获取字符在整理序列中的位置

Get position of character in collating sequence

我正在寻找一种将 ASCII 文本转换为十六进制数据的方法,我的意思是您可以获得的十六进制方式

MOVE X'nn'  TO MYVAR.

然后我需要像使用数字一样使用它(我猜是 COMP-3)。

我试图将 PIC(X) 移动到 PIC S9(2)V COMP-3,但没有像我想的那样工作...

进一步解释,因为我的问题被标记为不清楚:

首先,不好意思,深夜才提这个问题,现在再看,是的,不清楚。

现在,真正的问题是我想使用 char(比方说 "A"),因为它是十六进制数字表示,将其用作内部 table.[=33 的索引=]

例如,在 C 中可能很容易,使:

int mynum;
char mytext;

mynum = atoi(mytext);

然后使用mychar访问一个数组。所以,在 COBOL 中我有:

01 MY-TABLE.
    05 MY-TABLE-ITEM  PIC X OCCURS 1000.

01 MY-TEXT  PIC X 100.
01 MY-TEXT-X PIC X OCCURS 100.

然后,我想迭代 MY-TEXT-X 并将其转换为十六进制代码以将其存储到数字变量(PIC 9(n))中以使用它来访问 MY-TABLE-ITEM,类似:

PERFORM VARYING I FROM 1 BY 1 UNTIL I > 100
    PERFORM TRANSFORM-DATA

    DISPLAY MY-TABLE-ITEM(MY-NUMBER)
END-PERFORM

正如我所说,我想我可以将 PIC X 移动到 PIC S9(2)V COMP-3,这样数字变量可以获得值,但它没有像我预期的那样工作...

编辑:

所以我发现我的编译器不支持内部函数,所以这对我没有帮助...

编辑 - 添加源代码

所以,这是我正在使用的源代码,还显示了来自编译器和执行的内容。

来源:

   IDENTIFICATION DIVISION.
   PROGRAM-ID.  likeatoi.
   DATA DIVISION.
   WORKING-STORAGE SECTION.
    01  the-char                            PIC X 
                                          VALUE "K".
    01  the-result                          PIC 999.
    01  the-other-result             PACKED-DECIMAL PIC 9(8) 
                                          VALUE ZERO.
    01  FILLER 
    REDEFINES the-other-result. 
       05  FILLER                          PIC X.
       05  char-to-convert                 PIC X.
    01 num pic 9(8).
   PROCEDURE DIVISION.
   MAINLINE.
  *    with instrinsic function
  *    MOVE FUNCTION ORD ( the-char ) 
  *                              TO the-result.
       DISPLAY 
           ">"
           the-char
           "<"
           ">"
           the-result
           "<".

  *    Old School
       MOVE  the-char               TO char-to-convert.
       DISPLAY 
           ">"
           the-char
           "<"
           ">"
           the-other-result
           "<".

       MOVE the-other-result       TO num.
       DISPLAY num.

       STOP RUN.

现在,这是我尝试过的所有细节:

  1. 首先,尝试使用内部函数顺序编译它:

    ***** 1) 0384: E User-defined word expected instead of reserved word. (scan su

  2. 有了这个编译,运行程序(忽略错误):

COBOL procedure error 211 at line 17 in ./ESCRITORIO/HEX/LIKEATOI.COB (/home/dohitb/Escritorio/HEX/likeatoi.COB) compiled 17/03/05 20:37:29.

  1. 注释FUNCTION部分,然后重新编译:

Errors: 0, Warnings: 1, Lines: 37 for program LIKEATOI.

(显示COMP变量的警告,没关系)

  1. 再次执行(没有"num",仍然有comp变量):

    >A<> <

    >A<>A<

  2. 添加"num"变量,将char更改为"K"并将COMP更改为PACKED-DECIMAL(十六进制:4B)

    >K<> <

    >K<>K<

    04900000

所以,正如我所说,这两个选项都不起作用。现在最准确的方法是使用重新定义为 PIC 9 的 PACKED-DECIMAL,但是 HEX 位置高于 "A" 它给出了“9”,所以它仍然无效。

我认为这可能是本地 COLLATION 的问题。

最终编辑

现在我对原始源代码做了一个变体:

   IDENTIFICATION DIVISION.
   PROGRAM-ID.  likeatoi.
   DATA DIVISION.
   WORKING-STORAGE SECTION.
    01  the-char                                    PIC X 
                                          VALUE "K".
    01  the-result                                  PIC 999.
    01  the-other-result             BINARY         PIC 9(4) 
                                          VALUE ZERO.
    01  FILLER-1
    REDEFINES the-other-result. 
       05  FILLER                          PIC X.
       05  char-to-convert                 PIC X.

    01  the-comp-result              COMP           PIC 9(4)
                                          VALUE ZERO.
    01  FILLER-2
    REDEFINES the-comp-result. 
       05  FILLER                          PIC X.
       05  char-to-convert                 PIC X.

    01  the-packed-result            PACKED-DECIMAL PIC 9(4)
                                          VALUE ZERO.
    01  FILLER-3
    REDEFINES the-packed-result. 
       05  FILLER                          PIC X.
       05  char-to-convert                 PIC X.

    01 num                                 PIC 9(8).
    01 alfa                                PIC X(20)
       VALUE 'ABCDEFGHIJabcdefghij'.
    01 FILLER REDEFINES alfa.
        05 char                            PIC X OCCURS 20.
    01 w-index                             PIC 99 VALUE ZEROES.

   PROCEDURE DIVISION.
   MAINLINE.

       PERFORM VARYING w-index FROM 1 BY 1 UNTIL w-index > 20
           MOVE char(w-index)       TO the-char

  *        Variations of "Old School" code
           MOVE the-char            TO char-to-convert OF FILLER-1
           MOVE the-char            TO char-to-convert OF FILLER-2
           MOVE the-char            TO char-to-convert OF FILLER-3

           DISPLAY 
           ">"
           the-char
           "<"
           " with BINARY >"
           the-other-result
           "<"

           MOVE the-other-result       TO num
           DISPLAY "Numeric value: " num

           DISPLAY 
           ">"
           the-char
           "<"
           " with COMP >"
           the-comp-result
           "<"

           MOVE the-comp-result       TO num
           DISPLAY "Numeric value: " num

           DISPLAY 
           ">"
           the-char
           "<"
           " with PACKED >"
           the-packed-result
           "<"

           MOVE the-packed-result       TO num
           DISPLAY "Numeric value: " num
       END-PERFORM.

       STOP RUN.

而且,令我惊讶的是,它给了我这个输出

>A< with BINARY >A<

Numeric value: 00000065

>A< with COMP >A<

Numeric value: 00000100

(等等...)所以现在看起来它正在工作...可能是因为我所做的第一次尝试使用的是 05-LEVEL 变量?

看来大功告成了!

谢谢大家,比尔,你会出现在我项目的问候部分:)

终于有一个细节了。

如果我做一个"MOVE"

MOVE 'A'     TO CHAR

然后做所有二进制的东西,结果是不同的...这里有一个例子。

使用 VALUE,对于 "D" 我得到 68,但是使用 MOVE 我得到 60...

您一直在为使用旧编译器而苦恼。它符合 COBOL 85 标准,但没有作为 1989 年标准扩展的内在函数。

此外,它有一个我以前从未遇到过的非标准行为,很难完全解释(无法访问该编译器)。

在 DISPLAY 中使用 > 和 < 的目的是让您始终准确知道每个输出字段的长度。您知道是否有空白或某些不可打印的字符。定义为 COMP 和 BINARY 的字段的显示仅显示一个字符,而不是通常保存在两个字节存储空间中的四个数字(类似于 INT,但限制为 9999)。

因此我建议使用 MOVE,当定义为 BINARY 时,您将获得预期的结果,而当定义为 COMP 时,您将获得...无法解释的结果。

对 COMP 结果的一种解释可能是 COMPUTATIONAL 字段完全由编译器实现者来定义。因此,一个系统上的 COMP 可能与另一个系统上的 COMP 是不同类型的字段(与 COMP-1、COMP-2、COMP-3 等相同)。这就是 1985 年标准引入新名称(例如 BINARY 和 PACKED-DECIMAL)的原因,以便它们可以跨 COBOL 编译器移植。

如果您坚持使用该编译器,那您很不幸。如果您有可能使用其他编译器,您可以在其他选择中找到开源 GnuCOBOL(我是 SourceForge.Net GnuCOBOL 项目讨论区的版主)。如果可以,请使用不同的编译器。

这是一个示例程序,它将在现代 COBOL 编译器上运行,同时使用内部函数 ORD 和它过去的完成方式(并且可能仍在完成)。请注意,如果您的 COMP 字段是 "little endian",请交换 REDEFINES 下的 FILLER 和字段的顺序。

   IDENTIFICATION DIVISION.
   PROGRAM-ID.  likeatoi.
   DATA DIVISION.
   WORKING-STORAGE SECTION.
   01  the-char                            PIC X 
                                              VALUE "A".
   01  the-result                          PIC 999.
   01  the-other-result             BINARY PIC 9(4) 
                                              VALUE ZERO.
   01  FILLER 
        REDEFINES the-other-result. 
       05  FILLER                          PIC X.
       05  char-to-convert                 PIC X.
   PROCEDURE DIVISION.
  *    with instrinsic function
       MOVE FUNCTION ORD ( the-char ) 
                                    TO the-result
       DISPLAY 
               ">"
               the-char
               "<"
               ">"
               the-result
               "<"

  *    Old School
       MOVE  the-char               TO char-to-convert
       DISPLAY 
               ">"
               the-char
               "<"
               ">"
               the-other-result
               "<"

       STOP RUN
       .

ORD 很简单,它实际上与 C 中的 atoi 相同(假设它为您提供了整理序列中的位置)。

其次,由于 COBOL 传统上不能有单字节二进制,因此使用 REDEFINES 是一种在双字节二进制的低位部分获取字符的方法,因此整个二进制字段表示该字符表示的 "numeric value"。

上面的输出是:

>A<>066<
>A<>0065<

请注意,ORD 给出整理序列中的 位置 (ORD 的二进制零会 return 一个),第二个只是给出直接表示(二进制零会给出零)。

如果您只对可打印的字符感兴趣,您可能想在之后 "re-base" 使用任一值。

请注意,我很困惑您的编译器支持内联 PERFORM 但不支持内部函数。如果 BINARY 的 USAGE 被拒绝,请改用 COMP。