K&R 2 第 5.10 节中的说明

Clarification in Section 5.10 of K&R 2

如果输入是查找模式,模式识别程序必须打印包含该模式的所有行。如果输入是 find -x pattern,程序必须打印除包含 pattern 的行之外的所有行。

// .....
switch(c)
{
case 'x':
    except=1;
    break;
// ......
}

// ......
while(getline(line,MAXLINE)>0)
    {
    line_num++;
    if( (strstr(line,*argv)!=NULL) != except)
        {
        if(number)
            printf("%ld:",linenum);
        printf("%s",line);
        found++;
        }
    }
// ......

在上面来自 K&R 的代码中,except 可以是 1 或 0。if(strstr...) 块函数如何有效地处理 -x?

我不熟悉该代码,但是此语句将评估为布尔值(01),因为 strstr() 将 return 指向单词的指针正在搜索或 NULL 如果未找到:

strstr(line, *argv) != NULL

所以我猜 except 设置为 01 以影响 "was not found" 或 "was found" 条件。

如果-x没有通过那么except就是0:

if ((strstr(line, *argv) != NULL) != 0)

这意味着如果找到该词,请输入 if 子句。

如果-x通过则except1:

if ((strstr(line, *argv) != NULL) != 1)

这意味着如果找到该词,请不要输入 if 子句。

这是令人困惑的代码,所以我建议将其分解为:

const char *word = strstr(line,*argv);
int wasfound = word != NULL;
if (wasfound != except)
{

}

然后使用调试器单步执行。学习使用调试器也很重要。

逻辑很简单。如果模式是 "-x" 我们应该打印所有不包含模式的行。

对于此模式 except 等于 1

因此包含该模式的行满足条件

strstr(line,*argv)!=NULL

也就是说,如果一行包含该模式,则此条件将始终等于 1。

因此,如果 except 等于 1 并且条件 strstr(line,*argv)!=NULL 等于 1,我们应该跳过该模式。

否则,如果条件 strstr(line,*argv)!=NULL 不等于 1,即未找到模式,则 if 语句

if( (strstr(line,*argv)!=NULL) != except)

返回 true 并执行其复合语句。

另一方面,如果 except 等于 0 那么要实现 if 语句中的条件计算结果为真,我们需要条件 strstr(line,*argv)!=NULL 相等到 1.

其实你可以重写if语句

if( (strstr(line,*argv)!=NULL) != except)

以下方式

if( ( ( strstr(line,*argv) != NULL ) == 1 && except == 0 ) ||
    ( ( strstr(line,*argv) != NULL ) == 0 && except == 1 ) )

简而言之,if 语句在任何一个条件下都起作用

1 and 0

0 and 1

如果

1 and 1

0 and 0

那么if语句就不会执行了

这里的 1 和 0 是 if 语句中两个子表达式的求值结果。

!=运算符与异或运算的真值相同所以可以分解

if( (strstr(line,*argv)!=NULL) != except)
    {
    if(number)
        printf("%ld:",linenum);
    printf("%s",line);
    found++;
    }

进入(效率较低但可能更清晰)

char found_one_match;
if( strstr(line,*argv) != NULL )
{
    found_one_match = 1;
}
else
{
    found_one_match = 0;
}
found_one_match ^= except;
if (found_one_match)
{
    if(number)
        printf("%ld:",linenum);
    printf("%s",line);
}
found += found_one_match;

换句话说,except 反转在字符串中找到模式时发生的效果。