【问题标题】:Word counter returning incorrect number of words字数计数器返回错误的字数
【发布时间】:2021-12-22 16:49:20
【问题描述】:

我一直在尝试创建一个从文件中读取文本并将其存储在字符串中的程序。我将字符串提供给计算字符串中每个单词的函数。

但是它唯一准确的假设用户在行尾留下一些空格并且不创建空行......不是一个很好的单词计数器。

  • 创建空行会导致字数计数错误增加。

我不确定我的主要问题是使用布尔值执行此操作还是检查空格和“\n”字符。

bool countingLetters = false;
int wordCount = 0;
for (int i = 0; i < text.length(); i++)
{
    if (text[i] == ' ' && countingLetters == true)
    {
        countingLetters = false;
        wordCount++;
    }
    if (text[i] != ' ' && countingLetters == false)
    {
        countingLetters = true;
    }
    if (text[i] == '\n' && countingLetters == true)
    {
        countingLetters = false;
        wordCount++;
    }
}

【问题讨论】:

  • 可以在末尾加个空格,比如text += ' '
  • @justANewbie 啊哈我知道这是一件非常痛苦的事情,我想念谢谢。可悲的是,空白行被视为单词的另一个问题仍然存在。
  • 考虑当找到换行符(不是一个)时,将执行多少个(以及哪些)if 语句主体。
  • @1201ProgramAlarm 天哪,谢谢,我需要更好地阅读 if 语句或少用它们
  • @GarlicBread 好吧,你只需要在看到空行时减少wordCount。我知道的快速破解 ;)

标签: c++ arrays string char


【解决方案1】:

您的代码基本上是一个状态机。要完成您的解决方案,只需计算字符串结尾。

将此添加到代码的末尾:

if(countingLetters) { // word at the end of string, without any space charactor
   wordCount++;
}

或者如果你可以确定它是 C 风格的字符串,比如 std::string,你可以只索引 1 传递最后一个字符,并以同样的方式处理 '\0''\n'

要改进您的代码,请使用 isspace(这涵盖了更多的空格字符,包括 '\t' 等)。最好使用else if 模式。另外,==true 也不是很好的做法。只需使用布尔值作为条件。

或者,isalpha(c) 更适合您的需求。

bool countingLetters = false;
int wordCount = 0;
for (char c:text) {
    if (!isalpha(c) && countingLetters) { // this also works for newline
        countingLetters = false;
        ++wordCount;
    } else if (isalpha(c) && !countingLetters) {
        countingLetters = true;
    } // otherwise just skip
}
if(countingLetters) { // word at the end of string, without any space charactor
   ++wordCount;
}

为了这样一个简单的任务插入额外的字符是不可接受的。例如,text 可能是 const。

【讨论】:

    【解决方案2】:

    另一种方法是计算“单词”的开头

    让我们说一个单词的开头是一个非字母之后的一个字母。如果需要,我们可以调整它。

    int wordCount = 0;
    int prior = '\n';  // some non-letter
    for (int i = 0; i < text.length(); i++) {
      if (isalpha(text[i]) && !isalpha(prior)) {
        wordCount++;
      }
      prior = text[i];
    }
    

    【讨论】:

      【解决方案3】:

      C++ 还提供了一些非常高级的方法来做到这一点。

      一种是在字符串流上使用循环,它在空格上分割文本:

      #include <sstream>
      #include <string>
      
      std::size_t count_words( const std::string& s )
      {
        std::size_t count = 0;
        std::istringstream ss( s );
        std::string t;
        while (ss >> t) count += 1;
        return count;
      }
      

      另一个是使用流迭代器算法:

      #include <iterator>
      #include <sstream>
      #include <string>
      
      std::size_t count_words( const std::string& s )
      {
        std::istringstream ss( s );
        return std::distance( 
          std::istream_iterator <std::string> ( ss ), 
          std::istream_iterator <std::string> ()
        );
      }
      

      还有一个正在使用正则表达式:

      #include <iterator>
      #include <regex>
      #include <string>
      
      std::size_t count_words( const std::string& s )
      {
        std::regex re( "\\w+" );
        return std::distance(
          std::sregex_iterator( s.begin(), s.end(), re ),
          std::sregex_iterator()
        );
      }
      

      我敢肯定还有更多,但这三个是我脑海中浮现的。

      【讨论】:

        猜你喜欢
        • 1970-01-01
        • 1970-01-01
        • 2021-05-29
        • 1970-01-01
        • 1970-01-01
        • 2012-10-01
        • 2016-06-01
        • 1970-01-01
        • 2014-11-01
        相关资源
        最近更新 更多