AND和OR的问题(COBOL)

41

我似乎无法正确处理这一部分。我收到了一个输入文件,其中包含许多名称,其中一些我需要跳过,并提供每个名称的额外信息。我尝试使用AND和OR来跳过我不需要的名称,结果得到了以下代码:

IF DL-CLASS-STANDING = 'First Yr' OR 'Second Yr' AND
GRAD-STAT-IN = ' ' OR 'X'

只剩下一个人了,但是当我尝试添加另一组AND和OR时,程序开始表现得好像限制条件根本不存在。

是我的代码对编译器来说太复杂了吗?有没有更简单的方法跳过某些条件?

4个回答

143

尝试添加一些括号来逻辑地分组:

IF ((DL-CLASS-STANDING = '大一' OR DL-CLASS-STANDING = '大二') AND (GRAD-STAT-IN = ' ' OR GRAD-STAT-IN = 'X'))


31

当有很多从句时,您可能需要考虑完全展开缩写表达式,因为展开可能不是您想要的,这时变得更加明确通常会更好。


然而,会使用88级变量来使代码更易读 - 这些是特殊级别,允许在数据部分直接指定条件,而不是在代码中使用显式条件。

换句话说,将类似以下内容放入数据部分:

03  DL-CLASS-STANDING  PIC X(20).
    88 FIRST-YEAR          VALUE 'First Yr'.
    88 SECOND-YEAR         VALUE 'Second Yr'.
03  GRAD-STAT-IN       PIC X.
    88 GS-UNKNOWN          VALUE ' '.
    88 GS-NO               VALUE 'X'.

然后你可以在表达式中使用 88 级变量:

IF (FIRST-YEAR OR SECOND-YEAR) AND (GS-UNKNOWN OR GS-NO) ...

在我看来,这样更易读,而 COBOL 的整个目的就是要像可读性强的英语一样。


1
我不是COBOL程序员,但这个88语法看起来一点也不像可读的英语。 - Asaph
3
@Asaph,我添加了一段(可读的)代码,为了那些不会COBOL的人,也就是你们中的99.99999999999% :-) - paxdiablo
1
级别88是以COBOL风格执行枚举的方法。 - Paul Morgan
1
比字面检查更好的解决方案。 - Joe Zitzelberger
2
@Paul:COBOL的88级别与C枚举不完全相同。 88级别可以有多个值,例如'X''Y''Z'或90 THRU 100。 更准确的模型是返回布尔值的函数,如果任何值匹配,则返回true。 这是我在我的COBOL到C ++声明转换器中编写的方式(但也提供了枚举类型,如果可能的话)。 - dan04
显示剩余3条评论

9
首先需要注意的是,显示的代码是能工作的,而没有展示不起作用的修改后的代码。此外,如果只剩下一个人,为什么还需要更多选择呢?总之,实际问题不太清晰,只是说“我不知道如何在COBOL中使用OR。我不知道如何在COBOL中使用AND”。
除此之外,有两个实际问题:
1. 我让编译器难以理解吗? 2. 跳过某些东西是否有更简单的方法(是否有更清晰的写条件语句的方式)?
对于第一个问题,答案是否定的。这对于编译器来说并不困难。编译器确切地知道如何处理任何组合OR、AND(以及稍后我们将介绍的NOT)。问题是,人类编写者/读者是否能成功编写条件,以便编译器知道他们想要什么,而不仅仅是按照其规则给出结果(这些规则不考虑一行代码可能存在多种人类解释的情况)。
因此,第二个问题变成了:
如何编写复杂的条件语句,使得编译器能够理解作者的意图,并且对于任何有COBOL经验的代码阅读者也以相同的方式理解?
首先,让我们快速重新排列一下问题中的(可用)代码:
IF DL-CLASS-STANDING = 'First Yr' OR 'Second Yr'
AND GRAD-STAT-IN = ' ' OR 'X'

下面是其中一个答案中提到的建议代码:

IF (DL-CLASS-STANDING = 'First Yr' OR 'Second Yr')
AND (GRAD-STAT-IN = ' ' OR 'X')

第二个版本更清晰,但它与第一个版本相同。它没有使那段代码工作,而是让那段代码继续工作。
答案解决了条件复杂度增加的问题:括号(简单地简化复杂度是另一种可能性,但没有非工作示例很难提出建议)。
原始代码可以工作,但当需要更复杂时,就会出现问题。
建议的代码可以工作,但它并不能完全解决扩展条件复杂度的问题,因为在括号内部,它重复了扩展条件复杂度的问题。
这是怎么回事呢?
一个简单条件:
IF A EQUAL TO "B"

稍微复杂一点的条件:
IF A EQUAL TO "B" OR "C"

一个略微但不完全简化的解释是:
IF (A EQUAL TO "B" OR "C")

如果条件变得更加复杂,需要使用AND连接,这对人类来说可能很简单(编译器不会在意,它无法被欺骗):
IF (A EQUAL TO "B" OR "C")
AND (E EQUAL TO "F")

But what of this?

IF (A EQUAL TO "B" OR "C" AND E EQUAL TO "F")

将AND运算符放在括号内使得人类面临的原始问题被复制了。这是什么意思,它是如何工作的?
一个答案是:
IF (A EQUAL TO ("B" OR "C") AND E EQUAL TO "F")

也许对某些人来说更加清晰,但原始问题仍然存在于次要方面。所以:
IF A EQUAL TO "B"
OR A EQUAL TO "C"

简化一下,第一部分还有一个小问题(只需要加上AND),因此:
IF (A EQUAL TO "B")
OR (A EQUAL TO "C")

导致:

IF ((A EQUAL TO "B")
OR (A EQUAL TO "C"))

并且:

IF ((A EQUAL TO "B")
 OR (A EQUAL TO C))

现在,如果有人想要使用AND进行增强,那么这将变得容易而清晰。如果在条件的某个部分的同一级别上进行操作,则仅会附加到该部分。如果在最外层级别上执行,则会同时附加到所有条件。

IF (((A EQUAL TO "B")
  AND (E EQUAL TO "F"))
 OR (A EQUAL TO "C"))

或者

IF (((A EQUAL TO "B")
 OR (A EQUAL TO "C"))
AND (E EQUAL TO "F"))

如果有人想在括号内插入AND,该怎么办?因为括号内很简单,人们不太会这样做。如果括号内的内容已经复杂了,就会越来越复杂。似乎某些东西因为本身简单而不会变得复杂,而一些已经很复杂(不止一个元素,不能单独存在)的东西则容易被认为更加复杂而不需深思。
COBOL是一种老语言,许多用COBOL编写的旧程序仍在运行。许多COBOL程序必须进行修改或者只是阅读以理解某些内容,而这些程序往往需要多年的使用寿命。
在改变代码时,通过向条件添加内容,最好不要"干扰"条件的原始部分。如果复杂性留在括号内,那么代码需要干扰的可能性更大,这增加了理解所需的时间(它更加复杂)和更改的时间(需要更多的小心,需要更多的测试,因为代码被干扰了)。
许多旧程序将是不良实践的例子。对此除了小心处理外,没有太多可做的了。
没有任何借口去编写未来需要更多维护和关注的新代码,除非这是绝对必要的。
现在,上述示例可能被认为是冗长的。这是COBOL,对吧?需要大量打字?但是COBOL在数据定义方面给予了巨大的灵活性。作为其中一部分,COBOL具有Level 88,即条件名。
以下是上述内容的一部分数据定义:
01  A PIC X.
    88  PARCEL-IS-OUTSIZED VALUE "B" "C".
01  F PIC X.
    88  POSTAGE-IS-SUFFICIENT VALUE "F".

条件变为:
IF PARCEL-IS-OUTSIZED
AND POSTAGE-IS-SUFFICIENT

现在除了字面值,所有相关的字面值都有一个名称,这样程序员就可以指示它们实际的含义,以及承载该含义的实际值。如果应该向PARCEL-IS-OUTSIZED添加更多类别,则在88级上的VALUE子句将被扩展。

如果要组合另一个条件,则做到这一点要简单得多。

这是真的吗?是的。从这个角度来看。

COBOL基于编码时条件的结果运行。

If condition

通过使用括号,可以将简单条件组合成一个条件:

If condition = If (condition) = If ((condition1) operator (condition2))...

一直到编译器的极限。

人只需要处理他们想要达到目标的条件。对于一般逻辑流程,请查看If条件。对于验证,请查看最低细节。对于子集,请查看与子集相关的条件部分。

使用简单条件。通过括号使条件变得简单。在需要的情况下,通过组合简单条件来创建复杂条件。使用条件名称进行与文字值的比较。

到目前为止,OR和AND已经被处理过了。NOT通常被视为需谨慎对待的东西:

IF NOT A EQUAL TO B
IF A NOT EQUAL TO B

IF (NOT (A EQUAL TO B)), remembering that this is just IF condition

如果将NOT简化,它就不可怕了。

在整个过程中,我一直在编辑空格。因为括号存在,我喜欢让它们显眼。我喜欢结构化和缩进条件,以强调我赋予它们的含义。

所以:

IF ( ( ( condition1 )
    OR ( condition2 ) )
AND
     ( ( condition3 )
    OR ( condition4 ) ) )

(而且比那还要雕塑化)。通过结构化,我希望 a)自己减少错误 b)即使我犯错,别人也有更好的发现机会。

如果条件不简化,那么理解代码就更加困难。改变代码也更加困难。对于学习COBOL的人来说,保持简单是长期受益于所有人的。


2

通常情况下,我尽可能避免使用AND。嵌套的IF语句同样有效,更易阅读,并且通过巧用88级别,不需要深入嵌套。根据我的经验,这种写法更易于阅读:

05  DL-CLASS-STANDING            PIC X(20) VALUE SPACE.
    88  DL-CLASS-STANDING-VALID  VALUE 'First Yr' 'Second Yr'.
05  GRAD-STAT-IN                 PIC X     VALUE SPACE.
    88  GRAD-STAT-IN-VALID       VALUE SPACE 'N'.

那么代码就像这样简单:
IF DL-CLASS-STANDING-VALID
    IF GRAD-STAT-IN-VALID
        ACTION ...  .

这同样适用于其他编程语言,也适用于正则表达式。将复杂的部分分解成许多简单的部分。 - Peter Mortensen

网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接