Implement COBOL REDEFINES in C
我正在尝试用C语言实现COBOL中使用的REDEFINES逻辑。
下面是COBOL程序:
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 | IDENTIFICATION DIVISION. ENVIRONMENT DIVISION. DATA DIVISION. WORKING-STORAGE SECTION. 01 DATE-MMDDYY. 10 DATE-MM PIC 9(02). 10 DATE-DD PIC 9(02). 10 DATE-YY PIC 9(02). 01 SYSTEM-DATE-MMDDYY REDEFINES DATE-MMDDYY PIC X(6). PROCEDURE DIVISION. MOVE '011817' TO SYSTEM-DATE-MMDDYY. DISPLAY 'SYSTEM-DATE-MMDDYY: ' SYSTEM-DATE-MMDDYY. DISPLAY 'DATE-MM: ' DATE-MM. DISPLAY 'DATE-DD: ' DATE-DD. DISPLAY 'DATE-YY: ' DATE-YY. DISPLAY 'CHANGING DATE-YY = 18' MOVE '18' TO DATE-YY. DISPLAY 'New SYSTEM-DATE-MMDDYY: ' SYSTEM-DATE-MMDDYY. STOP RUN. |
下面是上面程序的执行:
1 2 3 4 5 6 | SYSTEM-DATE-MMDDYY: 011817 DATE-MM: 01 DATE-DD: 18 DATE-YY: 17 CHANGING DATE-YY = 18 New SYSTEM-DATE-MMDDYY: 011818 |
我知道C语言中的UNION可以用来实现类似的目的。但这对我不起作用。
下面是我编写的C程序:
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 | #include <stdio.h> #include <stdlib.h> #include <string.h> union redef { struct date_mmddyy{ char date_mm[2]; char date_dd[2]; char date_yy[2]; }date_mmddyy; char system_date_mmddyy[6]; }; typedef union redef redef; int main(){ redef redef; strcpy(redef.date_mmddyy.date_mm,"01"); strcpy(redef.date_mmddyy.date_dd,"18"); strcpy(redef.date_mmddyy.date_yy,"17"); printf("%s\ ",redef.date_mmddyy.date_mm); printf("%s\ ",redef.date_mmddyy.date_dd); printf("%s\ ",redef.date_mmddyy.date_yy); printf("%s\ ",redef.system_date_mmddyy); strcpy(redef.system_date_mmddyy,"021918"); printf("%s\ ",redef.date_mmddyy.date_mm); printf("%s\ ",redef.date_mmddyy.date_dd); printf("%s\ ",redef.date_mmddyy.date_yy); printf("%s\ ",redef.system_date_mmddyy); return 0; } |
运行如下:
1 2 3 4 5 6 7 8 | 011817 1817 17 011817 021918 1918 18 021918 |
可以请您分享一些想法吗?
更新1:
我现在已经用
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 | #include <stdio.h> #include <stdlib.h> #include <string.h> union redef { struct date_mmddyy{ char date_mm[3]; char date_dd[3]; char date_yy[3]; }date_mmddyy; char system_date_mmddyy[7]; }; typedef union redef redef; int main(){ redef redef; redef.date_mmddyy.date_mm[2] = '\\0'; redef.date_mmddyy.date_dd[2] = '\\0'; redef.date_mmddyy.date_yy[2] = '\\0'; redef.system_date_mmddyy[6] = '\\0'; strcpy(redef.date_mmddyy.date_mm,"01"); strcpy(redef.date_mmddyy.date_dd,"18"); strcpy(redef.date_mmddyy.date_yy,"17"); printf("%s\ ",redef.date_mmddyy.date_mm); printf("%s\ ",redef.date_mmddyy.date_dd); printf("%s\ ",redef.date_mmddyy.date_yy); printf("%s\ ",redef.system_date_mmddyy); strcpy(redef.system_date_mmddyy,"021918"); printf("%s\ ",redef.date_mmddyy.date_mm); printf("%s\ ",redef.date_mmddyy.date_dd); printf("%s\ ",redef.date_mmddyy.date_yy); printf("%s\ ",redef.system_date_mmddyy); return 0; } |
下面是执行:
1 2 3 4 5 6 7 8 | 01 18 17 01 021918 918 021918 |
输出与COBOL中的输出相去甚远。
如果要在C中使用COBOL中的
和:
注意结构填充(对于未声明为
这将导致类似
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 | #include <stdio.h> union redef { struct date_mmddyy{ char date_mm[2]; char date_dd[2]; char date_yy[2]; }date_mmddyy; char system_date_mmddyy[6]; }; typedef union redef redef; int main(){ redef redef; redef.date_mmddyy.date_mm[0] = '0'; redef.date_mmddyy.date_mm[1] = '1'; redef.date_mmddyy.date_dd[0] = '1'; redef.date_mmddyy.date_dd[1] = '8'; redef.date_mmddyy.date_yy[0] = '1'; redef.date_mmddyy.date_yy[1] = '7'; // or: memcpy((void *)redef.date_mmddyy, (void *)"011817", 6); printf("%c%c\ ",redef.date_mmddyy.date_mm[0], redef.date_mmddyy.date_mm[1]); [...] |
要使其实际可用,您可能需要使用两件事:
- 除了包含数据的结构外,还添加一个字段结构,该字段结构至少包含一个指向存储,大小和类型的指针(在示例中," x"和" numeric-display"就足够了)
- 添加辅助函数以设置/获取字段值
类似
的东西
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 | #include <stdio.h> enum cob_type { T_DISPLAY = 0, T_NUMERIC_DISPLAY }; struct cob_field{ char *data; int size; enum cob_type; }; /* one for the actual storage - could be a simple unnamed char array */ struct date_mmddyy{ char date_mm[2]; char date_dd[2]; char date_yy[2]; } date_mmddyy; /* fields with pointers to the storage and the size */ cob_field date_mmddyy = {&date_mmddyy, 6, T_DISPLAY}; cob_field date_mm = {&date_mmddyy.date_mm, 2, T_NUMERIC_DISPLAY}; cob_field date_dd = {&date_mmddyy.date_dd, 2, T_NUMERIC_DISPLAY}; cob_field date_yy = {&date_mmddyy.date_yy, 2, T_NUMERIC_DISPLAY}; cob_field system_date_mmddyy = {&date_mmddyy, 6, T_DISPLAY}; int main(){ set_field_data(system_date_mmddyy,"011817"); printf("SYSTEM-DATE-MMDDYY: %s\ ', get_field_data(system_date_mmddyy)); printf("DATE-MM: %s\ ', get_field_data(date_mm)); printf("DATE-DD: %s\ ', get_field_data(date_dd)); printf("DATE-YY: %s\ ', get_field_data(date_yy)); puts("CHANGING DATE-YY = 18"); set_field_data(date_yy,"18"); printf("SYSTEM-DATE-MMDDYY: %s\ ', get_field_data(system_date_mmddyy)); return 0; } |
鉴于COBOL具有许多不同的类型,您需要在辅助函数中编写很多逻辑-这里
顺便说一句:您可能要检查GnuCOBOL-它会将COBOL转换为C ...
您的工会正在工作。问题来自显示结构字段时字符串中缺少NULL终止符。
如果您不想修改结构,也许可以修改格式限定符。
1 2 3 4 5 6 7 8 |
问题在于输出本身。在C语言中,所有字符串(至少您要使用printf("%s",...)打印的字符串)最后都需要一个0字节。由于您的"字符串"应具有2或6个字节的固定长度,因此这将不起作用,因为2个字节的"字符串"中的每一个都需要第三个字节来完成字符串的
因此,实际上它是"可行的",但是结果是一个字符数组,这与C语言中的字符串有所不同,因此您不能使用常规的字符串操作。
这不是您想听到的,但我建议您不要使用字符串,而是使用整数并使用转换函数。例如
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 | #include <stdio.h> #include <string.h> #include <stdlib.h> struct Date { int day, month, year; }; void dateFromString(char* input, struct Date* output) { char tmp[3]; tmp[2] = '\\0'; memcpy(tmp, &input[0], 2); output->day = atoi(tmp); memcpy(tmp, &input[2], 2); output->month = atoi(tmp); memcpy(tmp, &input[4], 2); output->year = atoi(tmp); } void stringFromDate(struct Date* input, char* output) { sprintf(output,"%02i%02i%02i",input->day,input->month,input->year); } int main() { char text[] ="120456"; struct Date d; dateFromString(text, &d); printf("%i\ ",d.day); printf("%i\ ",d.month); printf("%i\ ",d.year); char buffer[7]; stringFromDate(&d,buffer); printf("%s\ ",buffer); } |