【问题标题】:Suppressing leading zeroes抑制前导零
【发布时间】:2015-12-10 18:35:20
【问题描述】:

我们使用数字编辑图片子句 Z(4).99 来抑制前导零。它用空格替换前导零。我的问题是,我们可以删除这些空格并只显示实际值而不显示前导空格吗?

我有 ws-amount,即 pic 9(09)v99。如果我将 100 移入其中,它将看起来像 00000010000。但在我的报告中,我需要将其显示为“LOAN AMOUNT $100.00”。

【问题讨论】:

  • 为什么要这样做?在一份报告中,它看起来就像一个废话。那你想这样做是为了什么?
  • 取决于报告。 “你必须支付 319.58 美元”并没有更好的空间。
  • @gazzz0x2z “你必须支付 319.58$bbbbb 否则我们将因极端偏见而终止”也好不到哪里去。那我为什么问。可能是“CSV”。除非接收者对此感到很奇怪,否则前导零应该无关紧要(它没有意义)。同样,如果是 CSV,则 跟随 数字。左对齐可能不够。所以在回答之前需要知道...
  • 是的,我同意。我们需要更多信息。只是想指出,需求可能是一件很重要的事情。当然,也许不是。有时,最好的代码就是没有代码。
  • 如果你有FUNCTION TRIM,那么它就是FUNCTION TRIM(field LEADING)

标签: cobol mainframe


【解决方案1】:

没有使用任何功能,因为这些功能取决于站点。

所以结果是一个怪物(我不会花更多时间来完善它):

   01  WS.
       05  W-AMOUNT                    PIC 9(09)v99.
       05  W-AMOUNT-ALPHA              REDEFINES W-AMOUNT
                                       PIC X(01) OCCURS 11.
       05  W-DISPLAY                   PIC X(25).
       05  W-DISPLAY-TAB               REDEFINES W-DISPLAY
                                       PIC X(01) OCCURS 25.
       05  W-SENTENCE                  PIC X(12)
                                       VALUE " TO PAY SOON".
       05  W-SENTENCE-TAB              REDEFINES W-SENTENCE
                                       PIC X(01) OCCURS 12.
       05  W-SENTENCE-LENGTH           PIC 9(04) COMP-5.
       05  W-POSITION-AMOUNT           PIC 9(04) COMP-5.
       05  W-POSITION-SENTENCE         PIC 9(04) COMP-5.
       05  W-POSITION-DISPLAY          PIC 9(04) COMP-5.
       05  W-LEADING-ZEROES            PIC X(01).
           88  STILL-LEADING-ZEROES    VALUE "Y".
           88  NO-MORE-LEADING-ZEROES  VALUE "N".

后跟:

   PROCEDURE DIVISION.
  *-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-
   CONTROL-PROCEDURE.
  **
  * The main procedure of the program
  **
       MOVE 15314.16 TO  W-AMOUNT
       PERFORM SUB-PROCEDURE
       DISPLAY  "LOAN AMOUNT $"
       W-DISPLAY
       MOVE 314.16 TO  W-AMOUNT
       PERFORM SUB-PROCEDURE
       DISPLAY  "LOAN AMOUNT $" W-DISPLAY
       GOBACK
       .
   SUB-PROCEDURE.
       MOVE ZERO   TO  W-POSITION-DISPLAY
                       W-POSITION-SENTENCE
       MOVE SPACES TO  W-DISPLAY
       SET STILL-LEADING-ZEROES TO TRUE
       PERFORM VARYING     W-POSITION-AMOUNT
               FROM        1 BY 1
               UNTIL       W-POSITION-AMOUNT > 9
           IF (W-AMOUNT-ALPHA (W-POSITION-AMOUNT)
              NOT EQUAL ZERO) THEN 
              SET NO-MORE-LEADING-ZEROES TO TRUE
           END-IF
           IF NO-MORE-LEADING-ZEROES THEN 
               ADD 1 TO W-POSITION-DISPLAY
               MOVE W-AMOUNT-ALPHA (W-POSITION-AMOUNT)
                 TO W-DISPLAY-TAB  (W-POSITION-DISPLAY)
           END-IF
       END-PERFORM
       ADD 1 TO    W-POSITION-DISPLAY
       MOVE "." TO W-DISPLAY-TAB (W-POSITION-DISPLAY)
       ADD 1 TO    W-POSITION-DISPLAY
       MOVE        W-AMOUNT-ALPHA (W-POSITION-AMOUNT)
         TO        W-DISPLAY-TAB  (W-POSITION-DISPLAY)
       ADD 1 TO    W-POSITION-DISPLAY
                   W-POSITION-AMOUNT
       MOVE        W-AMOUNT-ALPHA (W-POSITION-AMOUNT)
         TO        W-DISPLAY-TAB  (W-POSITION-DISPLAY)
       MOVE LENGTH OF W-SENTENCE TO W-SENTENCE-LENGTH
       PERFORM W-SENTENCE-LENGTH TIMES
           ADD  1  TO  W-POSITION-DISPLAY
                       W-POSITION-SENTENCE
           MOVE W-SENTENCE-TAB     (W-POSITION-SENTENCE)
             TO W-DISPLAY-TAB      (W-POSITION-DISPLAY)
       END-PERFORM
       .

最终结果:

LOAN AMOUNT $15314.16 TO PAY SOON     
LOAN AMOUNT $314.16 TO PAY SOON  

有很多优化它的方法(尤其是我处理点后面的数字的方式,这绝对是糟糕的,但我是在看其他东西的同时做的,所以我做了更简单的事情)。我不敢将它提交给代码审查。但它有效。

【讨论】:

    【解决方案2】:

    由于您似乎担心审阅者可能会说什么,所以这里的代码实际上可以满足您的要求:

       UNSTRING edited-field
                 DELIMITED BY ALL SPACE
                                    INTO ignore-this
                                         no-leading-space-field
    

    我完全不确定这会有多困难。它确实需要这些定义:

    01  edited-field                        PIC Z(10).99.
    01  no-leading-space-field              PIC x(13).
    01  ignore-this                         PIC X.
    

    如果您谈论的是性能优化,那么您需要处理 gazzz0x2z 在他们的答案中提供的代码。但是你的审阅者会再次对多行代码感到困惑。


    COBOL 动词 STRINGUNSTRING 自 1974 年 COBOL 标准以来一直存在,因此应该可以广泛使用。对于常规文本的操作,它们有很多用途。

       IDENTIFICATION DIVISION.
       PROGRAM-ID. supspace.
       DATA DIVISION.
       WORKING-STORAGE SECTION.
       01  unedited-field                      PIC 9(9)v99.
       01  edited-field                        PIC Z(10).99.
       01  no-leading-space-field              PIC x(13).
       01  output-text                         PIC x(80).
       01  text-intro                          PIC x(13) VALUE 
                                                 "LOAN AMOUNT $".
       01  text-outro                          PIC x(12) VALUE 
                                                 " TO PAY SOON".
       01  ignore-this                         PIC X.
       PROCEDURE DIVISION.
           MOVE 0.01                    TO unedited-field
           PERFORM                      the-work
           MOVE 123.01                  TO unedited-field
           PERFORM                      the-work
           MOVE ZERO                    TO unedited-field
           PERFORM                      the-work
           MOVE 123456789.01            TO unedited-field
           PERFORM                      the-work
           GOBACK
           .
       the-work.
           PERFORM                      left-justify-edit
           PERFORM                      assemble-output
           DISPLAY 
                  output-text
           .
       left-justify-edit.
           MOVE unedited-field          TO edited-field
           UNSTRING edited-field
                     DELIMITED BY ALL SPACE
                                        INTO ignore-this
                                             no-leading-space-field
           .
       assemble-output.
           MOVE SPACE                   TO output-text
           STRING 
                  text-intro
                   DELIMITED BY SIZE
                  no-leading-space-field
                   DELIMITED BY SPACE
                  text-outro
                   DELIMITED BY SIZE
                                        INTO output-text
           .
    

    输出是:

    LOAN AMOUNT $.01 TO PAY SOON
    LOAN AMOUNT $123.01 TO PAY SOON
    LOAN AMOUNT $.00 TO PAY SOON
    LOAN AMOUNT $123456789.01 TO PAY SOON
    

    请注意,edited-field 的定义比其他必要的长一个字节,Z(10) 而不是 Z(9)。这是为了确保 UNSTRING 的 DELIMITED 始终至少有一个前导空格。

    注意当结果值小于目标的大小时,STRING 不会对其目标字段进行空格填充,因此如果结果值的长度可变,请在此之前清除目标字段使用 STRING 动词。

    UNSTRING 使用指定的分隔符将单个字段拆分为多个字段。

    其工作原理的关键是字段 ignore-this 和 DELIMITED BY ALL SPACE,以及​​保证至少存在一个前导空格。

    ALL SPACE 是任意数量的空格,从 1 到它所应用的字段的大小。在 UNSTRING 中命名的任何分隔符都不包含在 INTO 字段中。前导分隔符的存在意味着第一个 INTO 字段将“包含”一段长度为零的数据,空格填充到第一个 INTO 字段的长度。第二个 INTO 字段将包含没有前导空格的数据,并将用空格填充到该字段的长度。

    STRING 取多个字段,可以由其中的数据分隔,并将它们放在一起形成一个数据,放在 INTO 字段中,必要时截断,但没有空格- 如果数据比 INTO 字段短,则填充。

    在此处使用的 STRING 中,只有 SPACE 是分隔符,而不是 ALL SPACE,因为单个空格足以分隔,并且代码将比使用 ALL SPACE 更快。

    【讨论】:

    • 谢谢,虽然需要优化,但上述建议确实很有帮助,否则审阅者会头疼审阅代码:P。非常感谢大家:)
    • @Maxcc0 你在说什么优化?如果您有必须工作的限制,您需要在问题中包括这些限制。有一个,数一数,一个,做你所要求的指令(UNSTRING)。看看你的用户名,我们可以在问题中添加 Mainframe 标签吗?
    • 我很难过你唯一的支持是我的。你的答案比我的要干净得多。
    • @Maxcc0 不应该是使程序更难阅读的代码行数。好的名字,好的程序结构和好的代码结构,大程序是可读的。没有这些,即使是小程序也是不可读的。源代码行数不是评估复杂性的方法。
    • @Bill :好的程序为相同的功能编写的代码行数要少得多......但不是通过尝试减少程序大小。他们通过简化数据和处理流程来做到这一点。过量的 LOC 通常来自于缺乏 DRY。我见过 30,000 行的怪物,使用 400 次相同的数据库调用,只是硬编码了不同的元素。最好多使用 20 行来进行可重用的数据库调用......(换句话说,你是对的,仅仅为了它而尝试减少 LOC 计数通常是一个坏主意)
    【解决方案3】:

    这是一个示例,“规范”,但它可能不是“供应商”,这取决于编译器的年龄,正如 gazzz0x2z 指出的那样。 (FUNCTION TRIM 出现在 1989 年的修正案中,所以 26 年后......) 编辑:原来,这是一个错误。正如比尔指出的那样,TRIM 仅出现在 2014 年的最新规范中。 我在不应该在的地方反对。留下评论,羞愧地低下头。

       identification division.
       program-id. left-just.
    
       data division.
       working-storage section.
       01 amount      pic 9(9)v99 value 100.00.
       01 dollars     pic $(8)9.99.
       01 show-loan   pic x(32).
    
       procedure division.
       move amount to dollars
       string
           "LOAN AMOUNT " delimited by size
           function trim(dollars leading) delimited by size
         into show-loan
       display function trim(show-loan trailing)
       goback.
       end program left-just.
    

    【讨论】:

    【解决方案4】:

    这里使用了我的部分代码。

    https://codereview.stackexchange.com/questions/69220/trim-functions-in-cobol

    ws-amount                           pic 9(09)V99.
    ws-formated-amount                  pic $$$$,$$$,$$9.99.
    ws-output-message                   pic X(27).
    
    MOVE ws-amount
      TO ws-formated-amount.
    MOVE ws-formated-amount
      TO STR-VALUE-IN.
    MOVE FUNCTION LENGTH (ws-formated-amount)
      TO STR-LENGTH-IN.
    PERFORM 5100-LTRIM.
    MOVE SPACES TO ws-output-message.
    STRING
       'LOAN AMOUNT '
       STR-VALUE-OUT (1:STR-LENGTH-OUT)
           DELIMITED SIZE
    INTO
       ws-output-message
    END-STRING.
    

    【讨论】:

    • 很好,@BillWoodger
    猜你喜欢
    • 1970-01-01
    • 1970-01-01
    • 2011-08-31
    • 2015-02-18
    • 2017-10-07
    • 2010-09-24
    • 2017-09-25
    • 1970-01-01
    • 1970-01-01
    相关资源
    最近更新 更多