格式化第一个,中间首字母和最后一个名称

时间:2015-05-30 08:33:52

标签: cobol

记录的格式为:

01 LAST-NAME    PIC X(18).

01 FIRST-NAME   PIC X(12).

01 MI-NAME      PIC X(01).

当它们进来时,姓氏和名字当然可以是任何大小。

我需要将名称字段放在一起(没有尾随空格 - 但每个名称之间有一个空格)到一个工作存储字段中,长度为42个空格:

01 WS-FULL-NAME PIC X(42)

示例:

LAST-NAME = Smithington 

FIRST-NAME = Edward

MI-NAME = H

期望的结果:

Edward H Smithington

如果Middle初始化为空白,我当然不包括它,所需的结果将是:

Edward Smithington

我有一个例程来确定每个名字字段的实际长度,它已经处理了尾随空格(*我不需要担心前导空格)(见下文):

      01 W-SUB   PIC 9(02) VALUE 0.

      PROCESS-LAST-NAME.

          PERFORM VARYING W-SUB FROM LENGTH OF LAST-NAME BY -1
            UNTIL W-SUB LESS THAN 1   
            OR LAST-NAME(W-SUB:1) NOT = ' '
          END-PERFORM 

       IF W-SUB > ZERO          
          MOVE LAST-NAME(1:W-SUB) TO  ?????

'移动最后一个名字(1:W-SUB)到?????'是我被困'的地方。

即。如何将三个名字字段“拼凑”在一起产生渴望的结果= Edward H Smithington(*包括F,MI + L之间的空格)。

1 个答案:

答案 0 :(得分:3)

您被要求使用STRING执行此操作。反对对名称使用STRING的论点是名称可以包含嵌入空格。 DE LA HAYE例如作为姓氏,' ST JOHN' (发音为sinjun)作为名字。也可能有拼写错误提供前导空白和嵌入式空白。你似乎知道你没有领先的空白,但真正的或错误的嵌入式空白使得STRING的简单使用更加棘手。

如果您可以保证没有领先或嵌入的空白(绝对保证),那么

IF MI-NAME EQUAL TO SPACE
    STRING                      FIRST-NAME 
                                 DELIMITED BY SPACE
                                ' '
                                 DELIMITED BY SIZE
                                LAST-NAME
                                 DELIMITED BY SPACE
       INTO                     FULL-NAME
ELSE
    STRING                      FIRST-NAME 
                                 DELIMITED BY SPACE
                                ' '
                                 DELIMITED BY SIZE
                                MI-NAME
                                 DELIMITED BY SIZE
                                ' '
                                 DELIMITED BY SIZE
                                LAST-NAME
                                 DELIMITED BY SPACE
       INTO                     FULL-NAME
END-IF

在IF之前,您需要将空格移动到全名,否则当前名称比前一个名称短时,您将得到以前名称的一部分。

如果您不能保证缺少前导和嵌入空格,则必须使用引用修改字段作为名字和姓氏(每个长度一个),并使用DELIMITED BY SIZE。那么重点是什么?

01  W-FULL-NAME.
    05  W-FIRST-NAME.
        10  FILLER OCCURS 0 TO 12 TIMES
            DEPENDING ON length-of-first-name.
            15  FILLER                        PIC X.
    05  SPACE-AFTER-FIRST-NAME                PIC X.
    05  W-MI-NAME.
        10  FILLER OCCURS 0 TO 2 TIMES
            DEPENDING ON length-for-mi.
            15  FILLER                        PIC X.
    05  W-LAST-NAME.
        10  FILLER OCCURS 0 TO 18 TIMES
            DEPENDING ON length-of-last-name.
            15  FILLER                        PIC X.

你有两个PERFORMs来获取名字和姓氏的长度(已经是)。如果WS-MI-NAME是空格,则移动ZERO为mi-length,否则将其设为两个。

然后:

MOVE SPACE                  TO SPACE-AFTER-FIRST-NAME
MOVE FIRST-NAME             TO W-FIRST-NAME
MOVE LAST-NAME              TO W-LAST-NAME
MOVE MI-NAME                TO W-MI-NAME

W-FULL-NAME是一个可变长度字段,以您想要的格式包含您想要的数据,然后您可以随意使用它。

通过改变"复杂性"通过数据定义进入DATA DIVISION,PROCEDURE DIVISION中的代码变得非常简单。

尝试一下,要查看格式化数据,请执行以下操作:

DISPLAY 
        ">"
        W-FULL-NAME
        "<"

&gt;和&lt;只是为了准确地向您显示数据是什么(我总是在显示数据时这样做)。您将看到字段的长度随着不同的测试数据而变化(假设使用不同的长度数据进行测试......)。

以所有输入作为空格进行测试,您在SYSOUT后台数据集上看到这一点:

><

零长度字段。

通过参考修改,您可以这样做:

do your PERFORM to count the first-name  trailing spaces
MOVE FIRST-NAME             TO WS-FULL-NAME
ADD 1                       WS-SUB
  GIVING                    next-available-output

IF MI-NAME NOT EQUAL TO SPACE
    MOVE MI-NAME            TO WS-FULL-NAME 
                                ( next-available-output : 1 )
    ADD 2                   TO next-available-output
END-IF

do your PERFORM for the last-name
MOVE LAST-NAME              TO WS-FULL-NAME 
                                ( next-available-output : W-SUB )

输出的第一个MOVE会将第一个名称复制到全名。两者都不需要被引用修改,效果将是除了名称的字符以外的其他目标字段将是空白的。

存在的字符数是已知的,因此可以通过添加一个来计算目标字段中数据的下一个可用位置。

第二个MOVE以是否存在任何中间初始数据为条件,如果是,则将MOVEd移动到上面计算的下一个可用输出位置。 MOVEd的字节数(一)在目标中受到限制。

第三个MOVE类似于第二个MOVE,除了无条件,MOVEd字节的限制是可变的。

以上变化是可能的。这是一种更简洁的方式,但在某种程度上取决于您的编译器。那你在用哪一个?

您可以简化尾随空白数量的计算:

  01  W-SUB                        COMP   PIC 9(4).

  PROCESS-LAST-NAME.
      MOVE ZERO                    TO W-SUB
      IF LAST-NAME NOT EQUAL TO SPACE
          MOVE FUNCTION LENGTH ( LAST-NAME )
                                   TO W-SUB
          PERFORM 
            UNTIL LAST-NAME ( W-SUB : 1 )
              NOT EQUAL TO SPACE
              SUBTRACT 1           FROM W-SUB
          END-PERFORM 
      END-IF

这样,您就不必拥有双重终止条件。我重新定义了该字段,并使用下标而不是引用修改。我还重命名W-SUB以表明它包含数据的长度。