嗨,我正在编写一个程序,该程序计算每个单词在文件中出现的次数。 然后,它会打印一个计数在800到1000之间的单词列表,按计数顺序排序。 我坚持要保持计数器,以查看第一个单词是否与下一个单词匹配,直到出现新单词为止。 我主要尝试打开文件,逐个单词读取每个单词,然后在while循环中调用sort来对向量进行排序。 然后,在for循环中遍历所有单词,如果第一个单词等于第二个++。 我不认为这是您保持反击的方式。

这是代码:

#include <string>
#include <iostream>
#include <fstream>
#include <vector>
#include <algorithm>
#include <set>

using namespace std;

vector<string> lines;
vector<int> second;
set<string> words;
multiset<string> multiwords;

void readLines(const char *filename)
{
    string line;
    ifstream infile;
    infile.open(filename);
    if (!infile)
    {       
        cerr << filename << " cannot open" << endl; 
          return; 
    }       
    getline(infile, line);
    while (!infile.eof())
    {
        lines.push_back(line);
        getline(infile, line);
    }  
    infile.close();
}

int binary_search(vector<string> &v, int size, int value)
{
    int from = 0;
    int to = size - 1;
    while (from <= to)
    {  
        int mid = (from + to) / 2;
        int mid_count = multiwords.count(v[mid]);
        if (value == mid_count) 
            return mid;
        if (value < mid_count) to = mid - 1;
        else from = mid + 1;
    }
   return from;
}

int main() 
{
    vector<string> words;
    string x;
    ifstream inFile;
    int count = 0;

    inFile.open("bible.txt");
    if (!inFile) 
    {
        cout << "Unable to open file";
        exit(1);
    }
    while (inFile >> x){
        sort(words.begin(), words.end());
    }

    for(int i = 0;i < second.size();i++)
    {
        if(x == x+1)
        {
            count++;
        }
        else
            return;
    }
    inFile.close();
}

===============>>#1 票数:3

他。 我知道直截了当地显示解决方案并没有真正帮助您。 然而。

我浏览了一下您的代码,发现许多未使用和混乱的位。 这是我要做的:

#include <algorithm>
#include <fstream>
#include <functional>
#include <iostream>
#include <iterator>
#include <map>
#include <string>
#include <vector>

using namespace std;

// types
typedef std::pair<string, size_t> frequency_t;
typedef std::vector<frequency_t> words_t;

// predicates
static bool byDescendingFrequency(const frequency_t& a, const frequency_t& b)
{ return a.second > b.second; }

const struct isGTE // greater than or equal
{ 
    size_t inclusive_threshold;
    bool operator()(const frequency_t& record) const 
        { return record.second >= inclusive_threshold; }
} over1000 = { 1001 }, over800  = { 800 };

int main() 
{
    words_t words;
    {
        map<string, size_t> tally;

        ifstream inFile("bible.txt");
        string s;
        while (inFile >> s)
            tally[s]++;

        remove_copy_if(tally.begin(), tally.end(), 
                       back_inserter(words), over1000);
    }

    words_t::iterator begin = words.begin(),
                      end = partition(begin, words.end(), over800);
    std::sort(begin, end, &byDescendingFrequency);

    for (words_t::const_iterator it=begin; it!=end; it++)
        cout << it->second << "\t" << it->first << endl;
}

授权版本

993 because
981 men
967 day
954 over
953 God,
910 she
895 among
894 these
886 did
873 put
868 thine
864 hand
853 great
847 sons
846 brought
845 down
819 you,
811 so

Vulgata

995 tuum
993 filius
993 nec
966 suum
949 meum
930 sum
919 suis
907 contra
902 dicens
879 tui
872 quid
865 Domine
863 Hierusalem
859 suam
839 suo
835 ipse
825 omnis
811 erant
802 se

这两个文件的性能约为1.12s,但是在将map<>替换为boost::unordered_map<>之后,性能仅为0.355s。

===============>>#2 票数:2

可以使用单个map< string, int >出现的事件,逐个读取单词,并以m[ word ]递增计数器,从而实现更有效的方法。 在考虑完所有单词之后,遍历地图,对于给定范围内的单词,将它们添加到multimap<int, string> 最后转储多图的内容,该内容将按出现次数和字母顺序排序...

===============>>#3 票数:2 已采纳

一种解决方案可能是:定义letter_only语言环境,以便忽略来自流的标点符号,并仅从输入流中读取有效的“英语”字母。 这样,流将处理单词“ ways”,“ ways”。 和“方式!” 就像同一个词“ ways”一样,因为流将忽略标点符号,例如“”。 和“!”。

struct letter_only: std::ctype<char> 
{
    letter_only(): std::ctype<char>(get_table()) {}

    static std::ctype_base::mask const* get_table()
    {
        static std::vector<std::ctype_base::mask> 
            rc(std::ctype<char>::table_size,std::ctype_base::space);

        std::fill(&rc['A'], &rc['z'+1], std::ctype_base::alpha);
        return &rc[0];
    }
};

然后将其用作:

int main()
{
     std::map<std::string, int> wordCount;
     ifstream input;

     //enable reading only english letters only!
     input.imbue(std::locale(std::locale(), new letter_only())); 

     input.open("filename.txt");
     std::string word;
     std::string uppercase_word;
     while(input >> word)
     {
         std::transform(word.begin(), 
                        word.end(), 
                        std::back_inserter(uppercase_word),
                        (int(&)(int))std::toupper); //the cast is needed!
         ++wordCount[uppercase_word];
     }
     for (std::map<std::string, int>::iterator it = wordCount.begin(); 
                                               it != wordCount.end(); 
                                               ++it)
     {
           std::cout << "word = "<< it->first 
                     <<" : count = "<< it->second << std::endl;
     }
}

===============>>#4 票数:0

只是为了好玩,我使用Boost MultiIndex做了c ++ 0x风格的解决方案。

如果没有auto关键字 (类型推断),这种样式将非常笨拙。

通过始终按单词按频率维护索引无需删除,分区或对单词列表进行排序:它们将全部存在。

要编译并运行:

g++ --std=c++0x -O3 test.cpp -o test
curl ftp://ftp.funet.fi/pub/doc/bible/texts/english/av.tar.gz |
    tar xzO | sed 's/^[ 0-9:]\+//' > bible.txt
time ./test

#include <boost/foreach.hpp>
#include <boost/lambda/lambda.hpp>
#include <boost/multi_index_container.hpp>
#include <boost/multi_index/ordered_index.hpp>
#include <boost/multi_index/member.hpp>
#include <fstream>
#include <iostream>
#include <string>

using namespace std;

struct entry 
{
    string word;
    size_t freq;
    void increment() { freq++; }
};

struct byword {}; // TAG
struct byfreq {}; // TAG

int main() 
{
    using ::boost::lambda::_1;
    using namespace ::boost::multi_index;
    multi_index_container<entry, indexed_by< // sequenced<>,
            ordered_unique    <tag<byword>, member<entry,string,&entry::word> >, // alphabetically
            ordered_non_unique<tag<byfreq>, member<entry,size_t,&entry::freq> > // by frequency
                > > tally;

    ifstream inFile("bible.txt");
    string s;
    while (inFile>>s)
    {
        auto& lookup = tally.get<byword>();
        auto it = lookup.find(s);

        if (lookup.end() != it)
            lookup.modify(it, boost::bind(&entry::increment, _1));
        else
            lookup.insert({s, 1});
    }

    BOOST_FOREACH(auto e, tally.get<byfreq>().range(800 <= _1, _1 <= 1000))
        cout << e.freq << "\t" << e.word << endl;

}

注意如何

  • 定义自定义entry类型比使用std::pair稍微方便些
  • (出于明显的原因),这比我之前的代码要慢:在插入阶段,它会按频率维护索引。 这是不必要的,但是它可以更有效地提取[800,1000]范围:

    tally.get<byfreq>().range(800 <= _1, _1 <= 1000)

已经订购了多组频率。 因此,的实际速度/内存交易可能会偏向于此版本,特别是在文档较大且包含很少重复单词的情况下( ,,这是众所周知的圣经语料库文本不适合使用的属性。有人将其翻译为新溢漏(

  ask by Chris translate from so

未解决问题?本站智能推荐:

3回复

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

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

使用map计算文件中每个单词出现的次数。 (C ++)

我的主要问题是,当一个单词出现不止一次时,列出的单词也多于一次。 例如,如果文本以“ hello hello”开头,则cout会生成:“ hello:2”'\\ n'“ hello:2” 此外,我不想不必关闭,然后再次打开文件第二次才是正确的。 从最后一次while循环开始,它似乎仍
2回复

如何加快计算大文件中单词出现的次数?

我需要计算104gb文件中字符串"<page>"的出现次数,以获取给定Wikipedia转储中的文章数。 首先,我已经尝试过了。 但是,一段时间后grep崩溃。 因此,我编写了以下程序。 但是,它仅处理我机器上20mb / s的输入文件,这大约是我的硬盘工作量的5%。
2回复

在C ++中计算文件中单词出现的次数

这是我的代码,用于计算文件中特定字符串的出现次数。 该文件位于项目的根目录中。 问题是我对任何被计数的单词都得到0 。
2回复

计算向量中单词的出现次数

假设我有一个带有以下内容的std::vector<std::string> 现在我想计算向量中每个单词出现的次数。 我的第一个想法是使用以下算法,这是粗略的。 我想知道是否有更好的方法。
2回复

计算文件中每个字母的出现次数?

即使文件大小大到4GB或更多,如何以优化的方式查找字母AZ的出现(无视情况)? 在C ++ / C中可能有哪些不同的实现? 一个实现是: 伪代码
2回复

计算每个单词在输入中出现的次数

我正在从Accelerated C ++进行练习: 编写一个程序,计算每个单词在其输入中出现的次数。 这是我的代码: 如果编译并运行该程序,您将看到: 我输入如下: 然后显示: 我的预期结果是: 我不想使用地图,因为我还没有学过。
5回复

计算文件中字母的出现次数

我正在尝试计算每个字母出现在文件中的次数。 当我运行下面的代码时,它会计算两次“Z”。 有谁能解释为什么? 测试数据是: ABCDEFGHIJKLMNOPQRSTUVWXYZ ABCDEFGHIJKLMNOPQRSTUVWXYZ
4回复

C ++计算一个文件中单词的出现次数并写入另一个文件

这段代码有什么问题? 我正在尝试在input.txt input.txt-中搜索单词TID TID TID TID:fjkcgbkn 它在output.txt中仅显示0
1回复

计算字符串向量中单词的出现次数

我正在尝试创建一个字典,将文件读入字符串向量,并计算每个唯一单词出现的次数。 这是我到目前为止的内容: 问题1:如何使向量包含空格并识别单个单词? 问题2:关于如何进行第二部分(循环)的任何想法?