COBOL问题 - UNICODE

4

我们目前正在寻求将我们的传统COBOL代码从ANSII转换为UNICODE,但是我们遇到了一个问题,即仅将PIC X字段更改为PIC N并设置NSYMBOL(NATIONAL)将导致数据结构包含REDEFINES或RENAME语句的基本数据项使用PIC 9字段时出现问题。

01 WS-RECORD PIC N(26).
01 WS-RECORD-1 REDEFINES WS-RECORD.
02 WS-NUM PIC 9(6).
02 WS-DATA PIC N(20).

MOVE N"123456ABCDEFGHIJKLM" TO WS-RECORD.

在上述示例中,被移动的字符串将以UTF-16格式呈现,因此字段WS-NUM将会损坏,因为它包含了一个无效数字X"310032003300",而WS-DATA将包含X"3400350036004100..等内容。

问题是,在使用NATIONAL (UTF-16)数据类型时,如何处理数字,以便在重新定义后获得正确的数据。

我可以通过以下方式解决这个问题,但是其他WS-RECORD将会得到无效的数据。

MOVE 123456 TO WS-NUM.
MOVE N"ABCDEFGHIJKLM" TO WS_DATA.

以上内容是正确的,但如果我检查WS-RECORD,我会看到???ABCDEFGHIJKLM,其中???是十六进制的X"313233343536"。

我们的问题在于,我们有多个数据记录,取决于记录类型标识符,我们还在许多LINKAGE ITEM上使用重新定义。

有没有人有从传统ASCII转移到UNICODE的经验?

4个回答

3
02 WS-NUM PIC 9(6) USAGE NATIONAL.

应该可以工作(至少在IBM编译器上)。


感谢您的回答,我相信这对于IBM COBOL for zOS是正确的,但我们正在Windows平台上使用MicroFocus。 - bottomline

3
以下是MicroFocus提出的解决方案:
由于“pic 9(6)”的大小是“pic n(6)”的一半,因此WS-NCHAR-1和WS-NCHAR-FIELD的大小不同。
因此,快速但不整洁的解决方法是放置一个填充符,然后使用“FUNCTION DISPLAY-OF”重新校正字段。虽然这样可以解决问题,但客户需要了解“pic n”的大小与“pic 9”的大小不同,因此在使用重新定义和转换时需要小心。
以下是一个微调后的示例代码,应该能够说明我的意思...
01 ONE-PICN           PIC N.
01 ONE-PIC9           PIC 9.

01 WS-NCHAR-FIELD     PIC N(20).   
01 WS-NCHAR-1 REDEFINES WS-NCHAR-FIELD.
   02  WS-NUM            PIC 9(6).
   02  FILLER            PIC X(6).
   02  WS-REST           PIC N(14).

DISPLAY "PIC N SIZE     : " length of ONE-PICN    
DISPLAY "PIC 9 SIZE     : " length of ONE-PIC9

DISPLAY "WS-NCHAR-FIELD : " length of WS-NCHAR-FIELD   
DISPLAY "WS-NCHAR-1     : " length of WS-NCHAR-1

DISPLAY "WS-REST        : " length of WS-REST    
DISPLAY "WS-NUM         : " length of WS-NUM

MOVE N"123456ABCDEFGHIJKLM"  TO WS-NCHAR-FIELD.

MOVE FUNCTION DISPLAY-OF(WS-NCHAR-FIELD(1:6),1252) TO WS-NUM


DISPLAY "WS-NUM     : " WS-NUM    DISPLAY "WS-REST    : " WS-REST

上述方法不适用于S9(n)COMP或S9(n)V9(n)基本项。通过使用VISUAL COBOL,我发现我可以直接将数值移动到PIC N(n)元素中,然后使用FUNCTION NUMVAL()获取实际数字。对于带符号/COMP和小数字段,我还没有尝试过。感谢大家的帮助。

1

如果我理解你的意思正确,你想将X'3000'转换为X'30',将X'3100'转换为X'31',以此类推,直到X'3900'转换为X'39'。

我查阅了MicroFocus文档,但没有找到可以完成这个任务的内置函数。

你可以定义自己的过程来完成这个任务。

该过程的工作存储应如下所示:

01  WS-NUMERIC-CONVERSION.
    05  WS-LOOP-COUNT                     PIC S9(04) COMP.
    05  WS-NATIONAL-POSITION              PIC S9(04) COMP.
    05  WS-NUMBER-OF-CHARACTERS           PIC S9(04) COMP.
    05  WS-NATIONAL-INPUT.
        10  WS-NATIONAL-INPUT-BYTE        PIC X
                                          OCCURS 40 TIMES.
    05  WS-ASCII-OUTPUT.
        10  WS-ASCII-OUTPUT-BYTE          PIC X
                                          OCCURS 20 TIMES.

该过程将如下所示:

NATIONAL-TO-ASCII.
    PERFORM VARYING WS-LOOP-COUNT FROM 1 BY 1
        UNTIL WS-LOOP-COUNT > WS-NUMBER-OF-CHARACTERS

        COMPUTE WS-NATIONAL-POSITION = WS-LOOP-COUNT + WS-LOOP-COUNT - 1
        MOVE WS-NATIONAL-INPUT-BYTE(WS-NATIONAL-POSITION)
            TO WS-ASCII-OUTPUT-BYTE(WS-LOOP-COUNT)
    END-PERFORM.

调用该过程的方式如下:

05  WS-NATIONAL-NUMBER-X.
    10  WS-NATIONAL-NUMBER                 PIC N(06).
05  WS-ASCII-NUMBER-X.
    10  WS-ASCII-NUMBER                    PIC 9(06).


MOVE something TO WS-NATIONAL-NUMBER
MOVE WS-NATIONAL-NUMBER-X TO WS-NATIONAL-INPUT
MOVE +6 TO WS-NUMBER-OF-CHARACTERS
PERFORM NATIONAL-TO-ASCII
MOVE WS-ASCII-OUTPUT TO WS-ASCII-NUMBER-X
MOVE WS-ASCII-NUMBER TO something else

我定义的程序工作存储可以处理长度为20个字符的数字。如果不够用,可以将WS-NATIONAL-INPUTWS-ASCII-OUTPUT字段扩大。


实际上,我想使用REDEFINES,因为它适用于ASCII,但这是不可能的,因为我必须重新编写代码的许多部分,而且这个解决方案对于S9(n),S9(n)COMP或S9(n)V9(n)字段也不起作用。当使用标准ASCII时,它会按字节处理并正确表示值,对于PIC S9(n)... ELEMENTRY项,这些通常在01 GROUP级别使用,并且可以正常工作。 - bottomline
@bottomline:底线是你没有说有COMP和signed字段。你需要编写更多的转换程序。 - Gilbert Le Blanc

1
你可以使用DISPLAY-OF函数和引用修改,并添加一个填充符以确保大小平衡,添加78以减少魔法数字的使用!
总之,正如我所说有点乱,但是可行的。
例如:
  MOVE FUNCTION DISPLAY-OF(WS-RECORD-1(
                 1:LENGTH OF WS-RECORD(1:6)),1252)

随着更新后的程序为:

     78 NUM-SIZE  VALUE 6.

     01 WS-RECORD   PIC N(26).
     01 WS-RECORD-1 REDEFINES WS-RECORD.
       02 WS-NUM      PIC 9(NUM-SIZE).
       02 FILLER      PIC X(NUM-SIZE).
       02 WS-DATA     PIC N(20).


     MOVE N"123456ABCDEFGHIJKLM" TO WS-RECORD.

     DISPLAY "WS-NUM     : " WS-NUM
     DISPLAY "WS-DATA    : " WS-DATA

       MOVE FUNCTION DISPLAY-OF(WS-RECORD-1(
                 1:LENGTH OF WS-RECORD(1:NUM-SIZE)),1252)
              TO WS-NUM

     DISPLAY "WS-NUM     : " WS-NUM
     DISPLAY "WS-DATA    : " WS-DATA

(更新为更好的解决方案)


大致而言,这是正确的,但仍需要对现有代码进行大量的重构,而且它无法处理我们数据结构中存在/可以重新定义的PIC S9(n)类型变体。我从Micro Focus收到的解决方案与您提到的类似。 - bottomline
是的,它确实存在长度错误...但这个修复了它...将 MOVE FUNCTION DISPLAY-OF(WS-RECORD-1(1:LENGTH OF WS-RECORD(1:6)),1252) TO WS-NUM 移至 WS-NUM - Stephen Gennard

网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接