在C中实现COBOL REDEFINES

时间:2017-01-18 16:38:06

标签: c struct cobol unions

我正在尝试用C语言实现COBOL中使用的REDEFINES逻辑。

以下是COBOL计划:

   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.

以下是上述程序的执行:

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程序:

#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\n",redef.date_mmddyy.date_mm);
        printf("%s\n",redef.date_mmddyy.date_dd);
        printf("%s\n",redef.date_mmddyy.date_yy);
        printf("%s\n",redef.system_date_mmddyy);

        strcpy(redef.system_date_mmddyy, "021918");
        printf("%s\n",redef.date_mmddyy.date_mm);
        printf("%s\n",redef.date_mmddyy.date_dd);
        printf("%s\n",redef.date_mmddyy.date_yy);
        printf("%s\n",redef.system_date_mmddyy);

        return 0;
}

它运行如下:

011817
1817
17
011817
021918
1918
18
021918

你能分享一些想法吗?

更新1:

我现在用\0终止了所有char数组。以下是更改后的代码:

#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\n",redef.date_mmddyy.date_mm);
        printf("%s\n",redef.date_mmddyy.date_dd);
        printf("%s\n",redef.date_mmddyy.date_yy);
        printf("%s\n",redef.system_date_mmddyy);

        strcpy(redef.system_date_mmddyy, "021918");
        printf("%s\n",redef.date_mmddyy.date_mm);
        printf("%s\n",redef.date_mmddyy.date_dd);
        printf("%s\n",redef.date_mmddyy.date_yy);
        printf("%s\n",redef.system_date_mmddyy);

        return 0;
}

以下是执行:

01
18
17
01
021918
918

021918

输出远离COBOL中的输出。

3 个答案:

答案 0 :(得分:4)

如果要在C中使用COBOL中的REDEFINE逻辑,则只有一个选项:不要将C字符串用于COBOL存储,因为COBOL数据仅使用字符数组进行数据结构。< /强> 和: 请注意structure padding (对于未声明为PIC X的任何项目)!

这会导致类似

的内容
#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\n",redef.date_mmddyy.date_mm[0],
                        redef.date_mmddyy.date_mm[1]);
        [...]

为了使其实际可用,您可能会使用两件事:

  • 除了包含数据的结构之外,添加一个字段结构,至少包含一个指向存储的指针,大小和类型(在样本'x'和'numeric-display'中就足够了
  • 添加辅助函数以设置/获取字段值

这样的东西
#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\n', get_field_data(system_date_mmddyy));
        printf("DATE-MM: %s\n', get_field_data(date_mm));
        printf("DATE-DD: %s\n', get_field_data(date_dd));
        printf("DATE-YY: %s\n', get_field_data(date_yy));

        puts("CHANGING DATE-YY = 18");
        set_field_data(date_yy, "18");
        printf("SYSTEM-DATE-MMDDYY: %s\n', get_field_data(system_date_mmddyy));

        return 0;
}

鉴于COBOL有许多不同的类型,你需要在辅助函数中编写大量逻辑 - 这里需要的void set_field (cob_field *f, char *data)char *get_field (cob_field *f)非常简单,这在使用所有类型COBOL时会发生变化当使用超过MOVE的文字(添加隐式类型转换)和DISPLAY时,会变得更加复杂。

BTW:你可能想检查一下GnuCOBOL - 它将COBOL翻译成C ......

答案 1 :(得分:2)

你的工会正在发挥作用。当您显示结构字段时,问题来自于字符串中缺少NULL终止符。

如果您不想修改结构,也许可以调整格式限定符。

printf("%2s\n",redef.date_mmddyy.date_mm);
printf("%2s\n",redef.date_mmddyy.date_dd);
printf("%2s\n",redef.date_mmddyy.date_yy);
printf("%6s\n",redef.system_date_mmddyy);

答案 2 :(得分:1)

问题在于输出本身。在C中所有字符串(至少那些你想用printf打印的字符串(&#34;%s&#34;,...))最后需要一个0字节。因为你的&#34;字符串&#34;意味着具有2或6个字节的固定长度,这将不起作用,因为每个2字节&#34;字符串&#34;需要第三个字节来完成字符串。

所以,实际上它&#34;工作&#34;,但结果是一个字符数组,这与C中的字符串不同,所以你不能使用通常的字符串操作。

这不是你想听到的,但我建议忘记字符串并使用整数并使用转换函数。例如

<script src="https://ajax.googleapis.com/ajax/libs/jquery/2.1.1/jquery.min.js"></script>
<div class="accordion">
  <div class="accordion-heading">heading</div>
  <div class="accordion-content">body</div>
  <div class="accordion-heading">heading</div>
  <div class="accordion-content">body</div>
  <div class="accordion-heading">heading</div>
  <div class="accordion-content">body</div>
</div>