计算一个词的出现次数

Counting occurrences of a word

我正在尝试从输入文件中查找给定单词的出现次数,并且我能够正确计算 letter/character 的出现次数,但是当我尝试查找单词时程序只是 returns 计数为 0。我做错了什么?

ifstream input("input.txt");
input.open("input.txt");
string video = "video", ands = "and";
string str1((istreambuf_iterator<char>(input)),
    istreambuf_iterator<char>());
int videocount = 0, sentcount = 0, wordcount = 0, wordcountand = 0, wordcountand2 = 0;
for (int i = 0; i < str1.length(); i++)
{
    if (str1 == video) {
        ++videocount;
    }

    if (str1[i] == '.') {
        sentcount++;
    }
    if (str1[i] == ' ') {
        wordcount++;
    }
    if (str1 == ands) {
        wordcountand++;
    }
}

编辑:我刚刚更改了读取文件的方式,然后一切又恢复正常了。

while (input >> filewords) {
      {wordcount++; }
      if (filewords == word1) {
          ++videocount;
      }
      if (filewords == word2) {
          wordcountand++;
      }
        for (int i = 0; i < filewords.length(); i++) {
            if (filewords[i] == '.') {
                sentcount++;
            }   
        }
    }

基本上问题已经在评论里回答过了。您不能将搜索字符串与存储在变量“str1”中的完整文本文件进行比较。结果当然永远是假的。

等于运算符 == 不查找 sub-strings。这已经给我们带来了答案,即我们想要使用的算法。我们将使用 std::string.substr。请参阅 here 了解该功能的说明。函数参数为:

  • 起始位置
  • 长度 sub-string

所以,我们需要找到一个词的start-position和一个词的end-position。有了它,我们可以计算出一个单词的长度是“end-position” - “start-position”.

但是如何识别一个词呢?一个单词通常由 alpha-numerical 个字符组成。如果我们遍历整个文本,并将之前检查的字符与当前评估的字符进行比较,我们可以声明以下内容:

  • 如果前一个字符不是 alpha-numeric 而当前是,那么我们找到了一个词的开头。然后我们会记住索引,那个词的开始位置。
  • 如果前一个字符是alpha-numeric而当前不是,那么我们找到了一个词的结尾。然后我们可以开始比较,因为我们知道开始结束位置。

然后,word = str1.substr(startPosition, endPosition-startPosition); 之类的东西会给我们一个词。我们可以将其与我们的搜索词进行比较,例如:

if (word == video) ++videocount;

但我们可以更进一步。用一个非常简单的标准方法,我们可以存储和统计所有的单词。为此,我们可以使用 std::mapstd::unordered_map。我们使用 std::maps 索引运算符。请参阅 here。并特别阅读句子:

Returns a reference to the value that is mapped to a key equivalent to key, performing an insertion if such key does not already exist.

因此,它将创建一个新条目,或者查找现有条目。在任何情况下,都会返回一个引用(对已经存在的或新创建的条目)。这将增加。这最终会变成这样:

wordCounter[text.substr(startIndexOfWord, index - startIndexOfWord)]++

所以,在这里,我们首先使用已经描述的算法构建一个 sub-string。这个 sub-string 然后被找到或添加到 std::map。在任何情况下,都会返回一个引用,我们将对其进行递增。

最后我们简单的输出所有的单词和计数器。

在下面的提议中,我使用 C++17 和 C++17 的特性,例如带有初始化程序或结构化绑定的 if-语句。所以你需要为你的编译器启用 C++17。

请看:

#include <iostream>
#include <fstream>
#include <string>
#include <iterator>
#include <cctype>
#include <vector>
#include <map>
#include <iomanip>

int main() {

    // Open the input file and check, if that works
    if (std::ifstream ifs("input.txt"); ifs) {

        // Read the complete text file into a string variable
        std::string text(std::istreambuf_iterator<char>(ifs), {});

        // Define the counters
        size_t sentenceCounter{};
        std::map<std::string, size_t> wordCounter{};
        size_t overallWordCounter{};

        // And temporary storage of characters from the complete text
        char currentCharacter{};    char lastCharacter{};

        // Here we stort the index of a word start
        size_t startIndexOfWord{};

        // Iterate over all characters from the source file
        for (size_t index{}; index < text.length(); ++index) {

            // Read the current character
            const char currentCharacter = text[index];

            // Each dot will be counted as an indicator for a sentence
            if ('.' == currentCharacter) ++sentenceCounter;

            // Now check, if we have found the start of a word. The we will just store the index
            if (std::isalnum(currentCharacter) and not std::isalnum(lastCharacter))
                startIndexOfWord = index;

            // Now, check, if we found the end of a word. Add to map and increment counter
            if (std::isalnum(lastCharacter) and not std::isalnum(currentCharacter)) 
                wordCounter[text.substr(startIndexOfWord, index - startIndexOfWord)]++;

            // The next lastCharacter is the currentCharacter of now
            lastCharacter = currentCharacter;
        }

        // Go through the complete map
        for (const auto& [word, count] : wordCounter) {
            // SHow words and counters
            std::cout << std::left << "Word: " << std::setw(30) << word << " Count: " << count << "\n";
            // Calculate overall sum of words
            overallWordCounter += count;
        }
        // Show final result
        std::cout << "\nWords overall: \t" << overallWordCounter << "\nSentences: \t" << sentenceCounter << '\n';
    }
    else {
        std::cerr << "\n***Error: Could not open input file.\n";
    }
    return 0;
}

当然还有很多其他可能的解决方案,尤其是 std::regex

如果您有任何问题,我很乐意回答