【问题标题】:counting newlines, spaces, and tabs计算换行符、空格和制表符
【发布时间】:2011-03-14 08:34:26
【问题描述】:

这个问题来自 K&R p。 20:编写一个程序来计算空格、制表符和换行符。

这是我的尝试:

#include <stdio.h>

int main()
{
  int character, whitespace = 0;

  printf("Enter some text, and press Ctrl-d when you're done.\n\n");

  while((character = getchar() != EOF) {
    if(character == (' ' || '\n' || '\t')) {
      ++whitespace;
    }
  }

  printf("\nYour text contains %d spaces, tabs, and lines.\n", whitespace);

  return 0;
}

程序不工作。无论用户文本包含多少空格、制表符和换行符,它总是给出答案 0。任何人都可以看到问题吗?还有一件奇怪的事情:我必须按两次 Ctrl-d 才能注册。我不知道为什么。 谢谢!

【问题讨论】:

  • 您的while 语句缺少右括号;这可能是一个复制和粘贴错误,因为您说程序编译并运行。确保程序中缺少的右括号在getchar() 之后而不是EOF 之后;否则你会得到不正确的结果。
  • 您可能必须按两次Ctrl-d,因为您在输入后没有按回车键。 shell 会缓冲你的输入,直到它看到换行符。

标签: c whitespace


【解决方案1】:

以上示例在技术上是正确的。它仅在调用EOF(文件结束)指示符后打印值。但是,我认为对这个练习(1.8)有更好的解释,所以让我指定一个替代方案。下面的代码将在每个新行之后打印新行、制表符和空白。

#include <stdio.h>
#define EOL '\n'

/* Excercise 1.8 - K&R's book - 2nd edition. */
main()
{
    int c, newlines, tabs, blanks;

    newlines = 0;
    tabs = 0;
    blanks = 0;

    while ((c = getchar()) != EOF)
    {
        if (c == '\n')
            ++newlines;
        else if (c == '\t')
            ++tabs;
        else if (c == ' ')
            ++blanks;

        if (c == EOL) {
        printf("Lines: %d\nTabs: %d\nBlanks: %d\n", newlines, tabs, blanks);
        }
    }
}

【讨论】:

    【解决方案2】:

    您的代码的问题是if(character == (' ' || '\n' || '\t')) 语句。语句(' ' || '\n' || '\t') 等价于32 || 13 || 9(每个字符替换为等价的ASCII 值),它等于1,因为在C/C++ 中任何非零的东西都被视为true,所以实际上你在做@ 987654326@。现在我认为您可以解决代码中的问题。

    还有书籍说要分别计算空白、制表符和换行符,而您正在尝试计算总数,所以请执行以下操作。

    if(character == ' ')
      ++blanks;
    
    if(character == '\t')
      ++tabs;
    
    if(character == '\n')
      ++newlines;
    

    如果你想要一个完整的解决方案,这是我很久以前写的。

    #include <stdio.h>
    
    int main(void)
    {
      int blanks, tabs, newlines;
      int c;
    
    
      blanks = 0;
      tabs = 0;
      newlines = 0;
    
      do {
          c = getchar();
          if(c == ' ') {
              ++blanks;
          }
          else if(c == '\t') {
             ++tabs;
          }
          else if(c == '\n') {
             ++newlines;
          }
      }
      while(c != EOF)
    
      printf("Blanks: %d\nTabs: %d\nLines: %d\n", blanks, tabs, newlines);
      return 0;
    }
    

    【讨论】:

      【解决方案3】:

      你的while语句中的括号是错误的,应该是

      while( (character = getchar()) != EOF) 
      

      您为字符分配了测试getchar() != EOF 的值,对于真正读取的任何字符,该值为 1。

      【讨论】:

        【解决方案4】:

        isspace 将根据您的系统作为宏或函数提供,这样您就不必再猜测环境中可能构成空白的内容了。严格来说,它可能是您系统上的所有以下字符。 GNU C 肯定是这样认为的。

        ' '
            space
        '\f'
            formfeed
        '\n'
            newline
        '\r'
            carriage return
        '\t'
            horizontal tab
        '\v'
            vertical tab
        

        这就是您可以进行测试的方法。

         #include <ctype.h>
        
          while((character = getchar() != EOF) {
            if (isspace(character)) whitespace++;
          }
        

        【讨论】:

        • 这解决了一个不同的问题(它计算了问题中的额外字符)。 -1 表示不阅读标准文档 - isspace 被定义为 完全 该组字符返回 true,以及可能在 C 语言环境之外的其他语言环境中的其他字符(但绝不会更少)。
        • 虽然我同意它解决了一个不同的问题(所问问题的超集),但我不认为这对健康有害,而是可能对 ab initio C 程序员有一些好处——也许鼓励在提出的问题之外进行一些思考。您如何得出结论认为我的回答表明我没有阅读标准文档更加好奇。事实上,能够在没有证据的情况下得出某事没有发生的结论是很有趣的。或许您可以详细说明您是如何得出如此新颖的结论的?我建议 -1 表示粗鲁的论点。
        【解决方案5】:
        if(character == (' ' || '\n' || '\t'))
        

        测试character是否等于(' ' || '\n' || '\t')的结果(this的结果为1,表示||的结果为真)。您需要针对三个可能值中的每一个单独测试它,例如,

        if(character == ' ' || character == '\n' || character == '\t')
        

        【讨论】:

        • 扩展 - 这是一个英语速记的例子,它根本不适用于大多数编程语言。 (a == b) || (a == c)(a == (b || c)) 不同 - 后者通常是一个错误。请注意,您打算为 (b || c) 使用的语义是构建一个列表 - 在 Python 中,您可以编写 IIRC if a in [b, c, d] :,但它仍然不仅仅是您想要的条件表达式的简写。
        【解决方案6】:

        您可能遇到的问题之一是您的状况。

        尝试类似:

        if (character == '\n' || character == ' ' || character == '\t') {
            ++ whitespace;
        }
        

        【讨论】:

          猜你喜欢
          • 1970-01-01
          • 1970-01-01
          • 1970-01-01
          • 2017-11-04
          • 1970-01-01
          • 2011-09-15
          • 2017-03-08
          • 2013-01-16
          • 1970-01-01
          相关资源
          最近更新 更多