如何将右边的空格替换为COBOL左边的零?

时间:2014-02-10 20:17:48

标签: optimization cobol

我有一个长度为10的字母数字变量。它在开头包含一个数字,其余数字用空格填充。然后我需要将字符串向左移动并在开头放置'0'的空格数。这个例子说明了一切:

INPUT            OUTPUT
==============================
'123456    ' ->  '0000123456'
'12345678  ' ->  '0012345678'
'123456789 ' ->  '0123456789'
'1234567890' ->  '1234567890'

然后我做了类似的事情:

检查此COBOL小提琴,您可以尝试: http://ideone.com/mgbKZ3 (只需点击编辑

   IDENTIFICATION DIVISION.
   PROGRAM-ID. VARSWAP.
   ENVIRONMENT DIVISION.
   DATA DIVISION.
   WORKING-STORAGE SECTION. 

       01 VARIN   PIC X(10).
       01 VARSWAP PIC X(10) JUSTIFIED RIGHT.

   PROCEDURE DIVISION.

       MOVE '123456    ' TO VARIN

       UNSTRING VARIN DELIMITED BY ' ' INTO VARSWAP

       INSPECT VARSWAP REPLACING LEADING SPACE BY '0'

       MOVE VARSWAP TO VARIN

       DISPLAY VARIN

       STOP RUN.

返回:

0000123456

似乎工作正常,但我想知道你是否有更好,更简单或更清晰的方法。

5 个答案:

答案 0 :(得分:8)

您应该使用所有空白的输入来测试您的代码。

如果您 绝对 某些数据质量,无论是否检查空白,您都可以这样做:

   ID DIVISION.
   PROGRAM-ID. VARSWAP.
   DATA DIVISION.
   WORKING-STORAGE SECTION. 

       01 VARIN   PIC X(10).
          88  NO-VARIN-PRESENT VALUE SPACE.
       01 VARSWAP PIC 9(10).

   PROCEDURE DIVISION.

       MOVE '123456    ' TO VARIN
       IF NO-VARIN-PRESENT
           do what your spec says
       ELSE
           UNSTRING VARIN DELIMITED BY ' ' INTO VARSWAP
       END-IF

       DISPLAY VARSWAP

      GOBACK
      .

我不喜欢破坏输入,所以我改变了。

一种流行的方法是,FUNCTION REVERSE(你的领域),然后是INSPECT反向领域TALLYING ......用于领先空间。您可以在程序的早期使用FUNCTION LENGTH来确定字段的长度(并确保它们的长度相同)然后,首先将VARIN设置为ZERO,对源和目标使用引用修改 - 源将是( 1:计算的数据长度)目标将是(计算 - 右对齐开始:)(未指定长度使用字段的剩余部分)。

还有可变长度字段,逐字节MOVE(有时候是“传统主义者”首选,但最不清楚的是)。

具体方法取决于您的数据。如果您需要验证数据,首先需要代码,这将使您更清楚地选择。如果您的数据有保证,干净,那么......

我知道这只是一个例子,但我希望你能使用更好的数据名称。

答案 1 :(得分:2)

Bill Woodger提到:“还有......逐字节移动(有时候是”传统主义者“所喜欢的,但最不清楚的是)。”这是一个我希望相当清楚的解决方案。以下是两个版本。首先,针对以下建议更新解决方案。其次,提出原始解决方案,以参考理解所作的评论。比尔,谢谢你的好建议!我可能会学会在这些日子里写好COBOL:)

   IDENTIFICATION DIVISION.
   PROGRAM-ID. SHIFT-RIGHT.
  * SITUATION ON STACKOVERFLOW.COM:
  * I HAVE AN ALPHANUMERIC VARIABLE WITH A LENGTH OF 10. 
  * IT CONTAINS A NUMBER AT THE BEGINNING, THE REST OF THE DIGITS 
  * ARE FILLED WITH SPACES. THEN I NEED TO MOVE THE STRING TO THE 
  * LEFT AND PUT THE NUMBER OF SPACES WITH '0' AT THE BEGINING. 
  * THIS EXAMPLES SPEAKS FOR THEMSELVES:

  * INPUT            OUTPUT
  * ==============================
  * '123456    ' ->  '0000123456'
  * '12345678  ' ->  '0012345678'
  * '123456789 ' ->  '0123456789'
  * '1234567890' ->  '1234567890'
  *
  * ASSUME INPUT DATA VALIDATION DONE ELSEWHERE.


   ENVIRONMENT DIVISION.
   INPUT-OUTPUT SECTION.
   FILE-CONTROL.

   DATA DIVISION.
   FILE SECTION.

   WORKING-STORAGE SECTION.
   01  STRING-IN                   PIC X(10).
   01  STRING-OUT                  PIC X(10).
   01  STRING-LENGTH               PIC 99 USAGE COMP.
   01  CHAR-IN-NUM                 PIC 99 USAGE COMP.
   01  CHAR-OUT-NUM                PIC 99 USAGE COMP.

   PROCEDURE DIVISION.
   MAIN.
       PERFORM INITIALIZE-LENGTH
       MOVE '123456    ' TO STRING-IN
       PERFORM MAKE-AND-SHOW
       MOVE '12345678  ' TO STRING-IN
       PERFORM MAKE-AND-SHOW
       MOVE '123456789 ' TO STRING-IN
       PERFORM MAKE-AND-SHOW
       MOVE '1234567890' TO STRING-IN
       PERFORM MAKE-AND-SHOW
       MOVE SPACES TO STRING-IN
       PERFORM MAKE-AND-SHOW
       STOP RUN
       .

   INITIALIZE-LENGTH.
       MOVE LENGTH OF STRING-IN TO STRING-LENGTH
       IF LENGTH OF STRING-OUT NOT = STRING-LENGTH
           DISPLAY 'LENGTH OF STRING-IN, ' STRING-LENGTH ', '
                   'NOT EQUAL TO LENGTH OF STRING-OUT, '
                   LENGTH OF STRING-OUT
           STOP RUN
       END-IF
       .

   MAKE-AND-SHOW.
       PERFORM MAKE-STRING-OUT
       PERFORM SHOW-BEFORE-AFTER
       .

   MAKE-STRING-OUT.
       MOVE ZEROS         TO STRING-OUT
       MOVE STRING-LENGTH TO CHAR-OUT-NUM
                             CHAR-IN-NUM
       PERFORM STRING-LENGTH TIMES
           IF STRING-IN (CHAR-IN-NUM:1) NOT = SPACE
               MOVE STRING-IN (CHAR-IN-NUM:1) 
                 TO STRING-OUT (CHAR-OUT-NUM:1)
               SUBTRACT 1 FROM CHAR-OUT-NUM
           END-IF
           SUBTRACT 1 FROM CHAR-IN-NUM
       END-PERFORM
       .

   SHOW-BEFORE-AFTER.
       DISPLAY "STRING IN:  '" STRING-IN "'"
       DISPLAY "STRING OUT: '" STRING-OUT "'"
       DISPLAY " "
       .


  **********************************************
  * EARLIER VERSION, BEFORE IMPROVEMENTS 
  * SUGGESTED IN COMMENTS
  **********************************************

   IDENTIFICATION DIVISION.
   PROGRAM-ID. SHIFT-LEFT.
  * SITUATION ON STACKOVERFLOW.COM:
  * I HAVE AN ALPHANUMERIC VARIABLE WITH A LENGTH OF 10. 
  * IT CONTAINS A NUMBER AT THE BEGINNING, THE REST OF THE DIGITS 
  * ARE FILLED WITH SPACES. THEN I NEED TO MOVE THE STRING TO THE 
  * LEFT AND PUT THE NUMBER OF SPACES WITH '0' AT THE BEGINING. 
  * THIS EXAMPLES SPEAKS FOR THEMSELVES:

  * INPUT            OUTPUT
  * ==============================
  * '123456    ' ->  '0000123456'
  * '12345678  ' ->  '0012345678'
  * '123456789 ' ->  '0123456789'
  * '1234567890' ->  '1234567890'
  *
  * ASSUME INPUT DATA VALIDATION DONE ELSEWHERE.


   ENVIRONMENT DIVISION.
   INPUT-OUTPUT SECTION.
   FILE-CONTROL.

   DATA DIVISION.
   FILE SECTION.

   WORKING-STORAGE SECTION.
   01  STRING-IN                   PIC X(10).
   01  STRING-OUT                  PIC X(10).
   01  CHAR-IN-NUM                 PIC 99 USAGE COMP-3.
   01  CHAR-OUT-NUM                PIC 99 USAGE COMP-3.

   PROCEDURE DIVISION.
   MAIN.
       MOVE '123456    ' TO STRING-IN
       PERFORM MAKE-AND-SHOW
       MOVE '12345678  ' TO STRING-IN
       PERFORM MAKE-AND-SHOW
       MOVE '12345678  ' TO STRING-IN
       PERFORM MAKE-AND-SHOW
       MOVE '123456789 ' TO STRING-IN
       PERFORM MAKE-AND-SHOW
       MOVE '1234567890' TO STRING-IN
       PERFORM MAKE-AND-SHOW

       STOP RUN
       .

   MAKE-AND-SHOW.
       PERFORM MAKE-STRING-OUT
       PERFORM SHOW-BEFORE-AFTER
       .

   MAKE-STRING-OUT.
       MOVE SPACES TO STRING-OUT
       MOVE 10     TO CHAR-OUT-NUM
       PERFORM VARYING CHAR-IN-NUM FROM 10 BY -1
           UNTIL CHAR-IN-NUM < 1
           IF STRING-IN (CHAR-IN-NUM:1) NOT = SPACE
               MOVE STRING-IN (CHAR-IN-NUM:1) 
                 TO STRING-OUT (CHAR-OUT-NUM:1)
               SUBTRACT 1 FROM CHAR-OUT-NUM
           END-IF
       END-PERFORM
       PERFORM UNTIL CHAR-OUT-NUM < 1
           MOVE ZERO TO STRING-OUT (CHAR-OUT-NUM:1)
           SUBTRACT 1 FROM CHAR-OUT-NUM
       END-PERFORM
       .

   SHOW-BEFORE-AFTER.
       DISPLAY "STRING IN:  '" STRING-IN "'"
       DISPLAY "STRING OUT: '" STRING-OUT "'"
       DISPLAY " "
       .

答案 2 :(得分:1)

如果你有内在函数,请将一个功能修剪,LEADING或TRAILING作为适合目的,通过图9中的TRAILING,或者在下面的例子中同时进行。

identification division.
program-id. rjust.

data division.
working-storage section.
01 str    pic x(10) value '123       '.
01 some-n pic 9(10).

procedure division.

move function trim(str) to some-n
move some-n to str

display some-n, " : ", str end-display
goback.

0000000123 : 0000000123

正如Bill上面提到的验证,这假设所有空格都相当于0.这可能是也可能不是一个理智的东西。非数字也是一个问题。

答案 3 :(得分:1)

最简单的方法是在move语句中使用WITH CONVERSION子句,如果您不确定输入,请添加ON EXCEPTION子句。

IDENTIFICATION DIVISION.
PROGRAM-ID. ONCONVERSION.
ENVIRONMENT DIVISION.
DATA DIVISION.
WORKING-STORAGE SECTION. 

    01 VARIN  PIC X(10).
    01 VAROUT PIC 9(10).

PROCEDURE DIVISION.
    MOVE '123456    ' TO VARIN

    MOVE VARIN TO VAROUT WITH CONVERSION
    ON EXCEPTION
        MOVE ZERO TO VAROUT
    END-MOVE

    DISPLAY VARIN

    STOP RUN.

答案 4 :(得分:1)

我很惊讶没有人建议在这里使用NUMVAL ......

IDENTIFICATION DIVISION.
PROGRAM-ID. EXAMPLE.
DATA DIVISION.
WORKING-STORAGE SECTION.
01  VARIN     PIC X(10).
01  VAROUT    PIC 9(10).
PROCEDURE DIVISION.
    MOVE '123456    ' TO VARIN
    COMPUTE VAROUT = FUNCTION NUMVAL(VARIN)
    DISPLAY '>' VARIN '<'
    DISPLAY '>' VAROUT '<'
    GOBACK
    .

产生......

>123456    <
>0000123456<

这种方法的问题是如果NUMVAL参数没有转换为 数字程序引发异常并死亡。这也不是很好 从CPU使用的角度来看是有效的,因为它需要字符 二进制数字转换并再次返回显示格式(全部在封面下完成但需要循环)。

作为一般规则,我不会 建议使用NUMVAL(即使它看起来像'更好'的解决方案)。我会坚持使用解决方案 正如原始问题中所述。那 解决方案在计算上是高效的,并且是COOBL编程中常用的习惯用法。