计算文本文件中每个单词的出现次数

时间:2013-06-01 00:49:30

标签: c++ count

给定一个包含多个字符串的大文本文件,读取文本文件并计算C ++中每个单词出现次数的最有效方法是什么?文本文件的大小未知,所以我不能只使用一个简单的数组。此外,还有另一个问题。此文本文件的每一行都以类别关键字开头,以下单词是该类别的功能。我需要能够计算该类别中每个单词的出现次数。

例如:

colors red blue green yellow orange purple
sky blue high clouds air empty vast big
ocean wet water aquatic blue
colors brown black blue white blue blue

通过这个例子,我需要在“颜色”类别中计算,有4次出现“蓝色”,即使总共发生了6次总共蓝色。

3 个答案:

答案 0 :(得分:4)

我会使用来读取和分隔单词(通过查找空格来分隔单词)并将它们保存到(标准C ++方法是使用std::map )。

这是C ++记录的代码:

#include <iostream>
#include <map> // A map will be used to count the words.
#include <fstream> // Will be used to read from a file.
#include <string> // The map's key value.
using namespace std;


//Will be used to print the map later.
template <class KTy, class Ty>
void PrintMap(map<KTy, Ty> map)
{
    typedef std::map<KTy, Ty>::iterator iterator;
    for (iterator p = map.begin(); p != map.end(); p++)
        cout << p->first << ": " << p->second << endl;
}

int main(void)
{
    static const char* fileName = "C:\\MyFile.txt";

    // Will store the word and count.
    map<string, unsigned int> wordsCount;


    {
        // Begin reading from file:
        ifstream fileStream(fileName);

        // Check if we've opened the file (as we should have).
        if (fileStream.is_open())
            while (fileStream.good())
            {
                // Store the next word in the file in a local variable.
                string word;
                fileStream >> word;

                //Look if it's already there.
                if (wordsCount.find(word) == wordsCount.end()) // Then we've encountered the word for a first time.
                    wordsCount[word] = 1; // Initialize it to 1.
                else // Then we've already seen it before..
                    wordsCount[word]++; // Just increment it.
            }
        else  // We couldn't open the file. Report the error in the error stream.
        {
            cerr << "Couldn't open the file." << endl;
            return EXIT_FAILURE;
        }

        // Print the words map.
        PrintMap(wordsCount);
    }

    return EXIT_SUCCESS;
}

输出:

    空气:1
    aquatic:1
    大:1
    黑色:1
    蓝色:6
    棕色:1
    云:1
    颜色:2
    空:1
    绿色:1
    高:1
    海洋:1
    橙色:1
    紫色:1
    红色:1
    天空:1
    浩大的:1     水:1
    潮湿:1
    白色:1
    黄色:1

答案 1 :(得分:2)

对单词进行标记并将其存储为键值对。

更新:我意识到我误解了这个问题。以下代码应按类别分开和计算:

#include <iostream>
#include <string>
#include <map>
#include <fstream>
using namespace std;
int main()
{
    ifstream file;
    file.open("path\\to\\text\\file");
    if(!file.is_open()) return 1;
    map<string, map<string, int> > categories;
    while(file.good())
    {
        string s;
        getline(file, s);
        int pos = s.find_first_of(' ');
        if(pos < 0) continue;
        string word = s.substr(0, pos);
        string category = word;
        s = s.erase(0, pos+1);
        while(s.size() > 0)
        {
            pos = s.find_first_of(' ');
            if(pos < 0)
                pos = s.size();
            string word = s.substr(0, pos);
            if(word != "")
                categories[category][word]++;
            s = s.erase(0, pos+1);
        }
    }
    for(map<string, map<string, int> >::iterator cit = categories.begin(); cit != categories.end(); ++cit)
    {
        cout << "Category - " << cit->first << endl;
        for(map<string, int>::iterator wit = cit->second.begin(); wit != cit->second.end(); ++wit)
            cout << "\tword: " << wit->first << ",\t" << wit->second << endl;
    }
    return 0;
}

更新2:Chris要求修改算法:

#include <iostream>
#include <string>
#include <map>
#include <fstream>
using namespace std;
int main()
{
    ifstream file;
    file.open("D:\\Documents\\txt.txt");
    if(!file.is_open()) return 1;
    map<string, int> categories;
    while(file.good())
    {
        string s;
        getline(file, s);
        int pos = s.find_first_of(' ');
        if(pos < 0) continue;
        while(s.size() > 0)
        {
            pos = s.find_first_of(' ');
            if(pos < 0)
                pos = s.size();
            string word = s.substr(0, pos);
            if(word != "")
                categories[word]++;
            s = s.erase(0, pos+1);
        }
    }
    for(map<string, int>::iterator wit = categories.begin(); wit != categories.end(); ++wit)
        cout << "word: " << wit->first << "\t" << wit->second << endl;
    return 0;
}

答案 2 :(得分:1)

这是一个达到您既定目标的解决方案。 See it live here

它使用std::map来维持(类别,字)对出现的次数。

std::istringstream用于先将数据分成行,然后分成单词。


<强>输出:

(colors, black) => 1
(colors, blue) => 4
(colors, brown) => 1
(colors, green) => 1
(colors, orange) => 1
(colors, purple) => 1
(colors, red) => 1
(colors, white) => 1
(colors, yellow) => 1
(ocean, aquatic) => 1
(ocean, blue) => 1
(ocean, water) => 1
(ocean, wet) => 1
(sky, air) => 1
(sky, big) => 1
(sky, blue) => 1
(sky, clouds) => 1
(sky, empty) => 1
(sky, high) => 1
(sky, vast) => 1

<强>方案:

#include <iostream>  // std::cout, std::endl
#include <map>       // std::map
#include <sstream>   // std::istringstream
#include <utility>   // std::pair

int main()
{
    // The data.
    std::string content =
        "colors red blue green yellow orange purple\n"
        "sky blue high clouds air empty vast big\n"
        "ocean wet water aquatic blue\n"
        "colors brown black blue white blue blue\n";

    // Load the data into an in-memory table.
    std::istringstream table(content);

    std::string row;
    std::string category;
    std::string word;
    const char delim = ' ';
    std::map<pair<std::string, std::string>, long> category_map;
    std::pair<std::string, std::string> cw_pair;
    long count;

    // Read each row from the in-memory table.
    while (!table.eof())
    {
        // Get a row of data.
        getline(table, row);

        // Allow the row to be read word-by-word.
        std::istringstream words(row);

        // Get the first word in the row; it is the category.
        getline(words, category, delim);

        // Get the remaining words in the row.
        while (std::getline(words, word, delim)) {
            cw_pair = std::make_pair(category, word);

            // Maintain a count of each time a (category, word) pair occurs.
            if (category_map.count(cw_pair) > 0) {
                category_map[cw_pair] += 1;
            } else {
                category_map[cw_pair] = 1;
            }
        }
    }

   // Print out each unique (category, word) pair and
   // the number of times that it occurs.
   std::map<pair<std::string, std::string>, long>::iterator it;

   for (it = category_map.begin(); it != category_map.end(); ++it) {
       cw_pair = it->first;
       category = cw_pair.first;
       word = cw_pair.second;
       count = it->second;

       std::cout << "(" << category << ", " << word << ") => "
           << count << std::endl;
   }
}
相关问题