问题描述
WORKING-STORAGE. FIRST-STRING PIC X(15) VALUE SPACES. SECOND-STRING PIC X(15) VALUE SPACES. OUTPUT-STRING PIC X(31) VALUE SPACES.
如果 FIRST-NAME ='JON SNOW'和LAST-NAME = '什么都不知道。 ',我怎么能得到:
我想得到:
OUTPUT-STRING = 'JON SNOW, KNOWS NOTHING. '
当我尝试时:
String FIRST-STRING DELIMITED BY SPACES ' ' DELIMITED BY SIZE SECOND-STRING DELIMITED BY SIZE INTO OUTPUT-STRING
我得到'JON KNOWS什么都没有。 '
当我尝试时:
String FIRST-STRING DELIMITED BY SIZE SECOND-STRING DELIMITED BY SIZE INTO OUTPUT-STRING
我得到'JON SNOW,一无所知。 '
我发现了一个由 String FIRST-STRING BY''(两个空格)
但是不能保证我的第一串不包含两个空格,这会导致丢失一部分。
I have found a tweak which consist of String FIRST-STRING DELIMITED BY ' ' (two spaces)But there is no guarantee that my FIRST-STRING doesn't contains two spaces which will result in losing part of it.
推荐答案
首先,荣誉,因为很多人会使用以两个空格分隔,所以完全不用担心可能的后果。请注意,如果数据仅跟随一个尾随空格,您还将获得意外输出。还要注意,由于要插入空格以分隔数据,因此OUTPUT-STRING的字段定义短了一个字节。在两个字段都完全充满数据的情况下,您将丢失SECOND-STRING的最后一个字节。
Firstly, kudos, as many would go with the delimited-by-two-spaces and not be at all concerned at the possible consequences. Note that if the data is followed by one trailing space only, you also get "unexpected" output. Note also that your field definition for OUTPUT-STRING is one byte short, as you are inserting a space to separate the data. With both fields entirely filled with data, you will lose the final byte of SECOND-STRING.
COBOL是定长字段的语言(除非它们是可变的) 。这意味着没有标准定界符,因此任何字符或值都可以出现在字段中的任何位置。此外,默认填充字符(源比目标字段短)是空格,这是单词的完全正常的分隔符。
COBOL is a language of fixed-length fields (except when they are variable). Which means there are no "standard" delimiters, so any character or value can appear at any position in a field. Further, the default padding character, where source is shorter than the target field, is space, which is a perfectly normal separator for words.
,如果您需要知道字段中实际数据部分的长度(不包括尾随空格)。
In your, and the many similar, case you need to know the length of the actual data part of your field (excluding the trailing blanks).
一种非常常见的方法是@ user4341206在其答案中,。
A very common way to do this is as suggested by @user4341206 in their answer, https://stackoverflow.com/a/31938039/1927206.
根据1985年的COBOL标准,INSPECT可用于计算前导空间,但不能用于计算后移空间。 功能反转可以首先用于将尾随空格转换为前导空格,以便INSPECT可以对其进行计数。
Under the 1985 COBOL Standard, INSPECT can be be used to count leading spaces, but cannot be used to count trailing spaces. FUNCTION REVERSE can be used first to turn trailing spaces into leading spaces, so that INSPECT can count them.
一次您知道尾随空格的数量,可以使用 LENGTH OF 特殊寄存器或功能长度确定长度定长字段的值(在编译时都评估(或可以取决于编译器))。字段长度和尾随空白的数量之间的差异为您提供了数据的长度。
Once you know the number of trailing blanks, you can use the LENGTH OF special-register or FUNCTION LENGTH to determine the length of the fixed-length field (both are (or can be, depending on compiler) evaluated at compile time). The difference between the length of the field and the number of trailing blanks gives you the length of the data.
一旦您拥有了数据的长度,请记住可能为空(取决于数据的可能性),并且长度可能与字段相同
Once you have the length of the data, and bearing in mind that it may be blank (depends on possibilities for the data) and it may be the same length as the field
请注意,如果您有很多数据,与从字段末尾开始的简单循环相比,可能不希望反转字段并使用INSPECT(可能是运行时例程)来计数尾随空格。
Be aware that if you have a lot of data, you may not want to reverse your field and use INSPECT (probably a run-time routine) compared to a simple loop from the end of the field to count the trailing blanks.
注意,像AcuCOBOL这样的编译器(现在是Micro Focus的COBOL产品的一部分)具有语言扩展,该语言扩展提供了TRAILING作为INSPECT的选项。请注意,即使是2014年的COBOL标准也没有将跟踪作为INSPECT的选项。
Note, that compilers like AcuCOBOL (now part of Micro Focus's COBOL offerings) have a Language Extension which offers TRAILING as an option for INSPECT. Note, even the 2014 COBOL Standard does not have TRAILING as an option for INSPECT.
无论哪种方式,都需要完成数据的长度。
Either way, with the length of the data you are done. Sort of.
您可以在STRING语句中使用引用修改:
You can use reference-modification within the STRING statement:
String FIRST-STRING ( 1 : length-field-you-define ) DELIMITED BY SIZE ' ' DELIMITED BY SIZE SECOND-STRING DELIMITED BY SIZE INTO OUTPUT-STRING
注意,您可以删除BY SIZE,因为SIZE是默认设置,但确实可以使它更清晰
Note, you should be able to remove BY SIZE, as SIZE is the default, but it does make it clearer to the human reader.
您还可以在目标字段上使用带有引用修改的MOVE:
You could also use MOVE with reference-modification on the target field:
MOVE FIRST-STRING TO OUTPUT-STRING ( 1 : length-field-you-define ) MOVE SPACE TO OUTPUT-STRING ( length-field-you-define + 1 : 1 ) MOVE SECOND-STRING TO OUTPUT-STRING ( length-field-you-define + 2 : )
关于re长度字段中的引用修改(在另一个答案中提到)不应为零。
There is a specific issue with reference-modification (mentioned on the other answer) which is you length field should not be zero.
长度在此上下文中是第二个项目,在之后:,在引用修改表示法中。在这种情况下,这意味着您定义的长度字段不能为零,如果FIRST-STRING完全是空间,则可以将其计算出来。
Length in this context is the second item, after the :, in the reference-modification notation. In this case it means length-field-you-define must not be zero, which it could be calculated to if FIRST-STRING is entirely space.
潜在的问题是
MOVE FIRST-STRING TO OUTPUT-STRING ( 1 : length-field-you-define )
因此,根据您的数据(如果其中可能包含空格),您必须保护
Therefore, depending on your data (if it may contain blanks), you have to "protect" against that.
IF FIRST-STRING EQUAL TO SPACE PERFORM COPY-SECOND-STRING-ONLY ELSE PERFORM CONCATENATE-FIRST-AND-SECOND END-IF ... COPY-SECOND-STRING-ONLY. MOVE SECOND-STRING TO OUTPUT-STRING . CONCATENATE-FIRST-AND-SECOND. calculate length MOVE FIRST-STRING TO OUTPUT-STRING ( 1 : length-field-you-define ) MOVE SPACE TO OUTPUT-STRING ( length-field-you-define + 1 : 1 ) MOVE SECOND-STRING TO OUTPUT-STRING ( length-field-you-define + 2 : ) .
如果使用长度为零的引用修改,则结果不确定,尽管可能
If you use a reference-modification with a length of zero, the result is undefined, although it may "work" with your compiler.
带有STRING和可变长度字段的解决方案不会失败,因为引用修改之外的编译器对此感到满意零长度的项目。
The solutions with STRING and the variable-length fields won't "fail", because the compiler outside of reference-modification is happy with zero length items.
但是,出于两个原因,应采用相同的保护:您将插入一个前导空格(分隔符);您将使代码明确,因此人们不必问自己第一个字段为空白时会发生什么;
However, the same "protection" should be employed for two reasons: you'll insert a leading blank (the "separator"); you'll make your code explicit, so people won't have to ask themselves "what happens when the first field is blank"; you'll save on processing.
这样,您的程序也可以更好地描述您的数据。除了知道您的数据是准确进行程序设计的必要条件之外,您的程序对数据的描述越多,就越容易产生委托或遗漏错误,就越容易理解,并且越容易
In this way also your program "describes your data" better. Along with "know your data" as a necessity for accurate program design, the more your program describes the data, the more difficult it is to create errors of commission or omission, the more easy it is to understand, and the easier it is to change when, as happens, the structure of the data changes.
您还可以使用WITH POINTER选项查看STRING。首先,将FIRST-STRING移至OUTPUT-STRING(这也会将OUTPUT-STRING中未使用的字节清除为空格)。然后在您定义的长度字段中添加一个(用于中间空间),并在STRING中将其用于WITH POINTER。
You could also look at STRING using the WITH POINTER option. Firstly, MOVE FIRST-STRING to OUTPUT-STRING (which will also clear the unused bytes in OUTPUT-STRING to space). Then add one to the length-field-you-define (for the intervening space) and use that in the STRING for the WITH POINTER.
尽管这是完全有效的,如果使用的话,这是一个发表评论的机会,因为许多经常使用STRING的人不知道使用WITH POINTER,所以请帮助他们。
Although that is perfectly valid, if using, it is an occasion to comment, as many people who regularly use STRING have no idea of the use of WITH POINTER, so help them out.
另一种可能性
不幸的是,并非所有的COBOL编译器都使这变得容易。这是最标准形式的复杂ODO,它不是标准的,但是是该语言的IBM扩展。
Unfortunately, not all COBOL compilers make this easy. A "Complex ODO", which this would require in its purest form, is non-Standard, but is an IBM Extension to the language.
LINKAGE SECTION. 01 L-MAPPING-OF-OUTPUT-STRING. 05 L-MOOS-FIRST-STRING. 10 FILLER OCCURS 0 TO 15 TIMES DEPENDING ON length-field-you-define. 15 FILLER PIC X. 05 L-MOOS-SEPARATOR-SPACE PIC X. 05 L-MOOS-SECOND-STRING PIC X(15). ... SET ADDRESS OF L-MAPPING-OF-OUTPUT-STRING TO ADDRESS OF OUTPUT-STRING MOVE FIRST-STRING TO L-MOOS-FIRST-STRING MOVE SPACE TO L-MOOS-SEPARATOR-SPACE MOVE SECOND-STRING TO L-MOOS-SECOND-STRING
如果您有大量数据,最快的方法是仅引用修改建议。我对引用修改的看法是,它倾向于混淆,因为人们倾向于以混淆(且不必要)的方式使用它。
If you have lots of data, the fastest way is the reference-modidifcation-only suggestion. My opinion of reference-modification is that it tends to obfuscate, because people tend to use it in an obfuscatory (and unnecessary) way.
我的首选是最后一种,其中PROCEDURE DIVISION代码非常简单:您可以在第一个字段中找到数据的长度;您只需做三个简单的移动。
My preference is for the last, where the PROCEDURE DIVISION code is very simple: you find the length of the data in the first field; you just do three plain MOVEs.
也许您可以尝试每个,以更加了解未来情况的可能性。
Perhaps you can try each, to become more aware of the possibilities for future situations.
这篇关于Cobol字符串由尾部空格分隔的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持!