【问题标题】:Clarification in Section 5.10 of K&R 2K&R 2 第 5.10 节中的说明
【发布时间】:2016-01-29 07:54:31
【问题描述】:

如果输入是查找模式,则模式识别程序必须打印包含该模式的所有行。如果输入是 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 的上述代码中,除了可以是 1 或 0。if(strstr...) 块如何有效地处理 -x ?

【问题讨论】:

  • 我不明白这个问题。你能详细说明一下吗?
  • 您能否更新您的问题以显示except 的定义和初始化?

标签: c kernighan-and-ritchie


【解决方案1】:

逻辑很简单。如果模式是"-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 语句中两个子表达式的求值结果。

【讨论】:

    【解决方案2】:

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

    strstr(line, *argv) != NULL
    

    所以我猜except 设置为01 以实现“未找到”或“已找到”条件。

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

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

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

    如果-x 被传递,那么except 就是1

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

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

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

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

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

    【讨论】:

      【解决方案3】:

      != 运算符与异或运算具有相同的真值。所以你可以拆分

      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 反转了在字符串中找到模式时所发生的效果。

      【讨论】:

        猜你喜欢
        • 1970-01-01
        • 1970-01-01
        • 1970-01-01
        • 1970-01-01
        • 1970-01-01
        • 2021-04-16
        • 2015-11-11
        • 1970-01-01
        • 1970-01-01
        相关资源
        最近更新 更多