我正在学习C ++(正确),通过我自己的Andrew Koenig和Barbara Moo的书“Accelerated C ++”,并在每一章中进行所有练习。
练习3-3:编写一个程序来计算每个不同单词在其输入中出现的次数。对我来说,这个练习似乎非常困难,特别是考虑到:1。该章中的例子和其他练习相对简单,2。你只能使用向量,所以没有任何进步。 (或者也许只是我误判了困难)
我在网上搜索了一些提示,看到其他人在这个练习中遇到了麻烦,但是人们提供的解决方案对我来说似乎并不清楚。大多数人建议使用本书后面介绍的组织方法,这种方法会破坏练习的重点。最后,我将在不同论坛(包括此处)上找到的提示和一些方法拼凑在一起,以提出我自己的解决方案:
#include <algorithm>
#include <iomanip>
#include <ios>
#include <iostream>
#include <string>
#include <vector>
using std::cin;
using std::setprecision;
using std::cout;
using std::string;
using std::endl;
using std::streamsize;
using std::sort;
using std::vector;
int main()
{
// Ask for string input
cout << "Please write some text, followed by end-of-file: " << endl;
vector<string> word_input;
string word;
// input words into string vector word_input
typedef vector<string>::size_type vecsize;
while (cin >> word)
{
word_input.push_back(word);
}
// sort the vector in alphabetical order to be able to separate distinct words
sort(word_input.begin(),word_input.end());
// create two vectors: one where each (string) element is a unique word, and one
// that stores the index at which a new distinc word appears
vector<string> unique_words;
vector<int> break_index;
for (int i=0; i != word_input.size()-1; ++i)
{
if(word_input[i+1] != word_input[i])
{
unique_words.push_back(word_input[i]);
break_index.push_back(i);
}
}
// add the last word in the series to the unique word string vector
unique_words.push_back(word_input[word_input.size()-1]);
// create a vector that counts how many times each unique word occurs, preallocate
// with 1's with as many times a new word occurs in the series (plus 1 to count the first word)
vector<int> word_count(1,break_index[0]+1);
// if a new word occurs, count how many times the previous word occured by subtracting the number of words so far
for(int i=0; i != break_index.size()-1;++i)
{
word_count.push_back(break_index[i+1] - break_index[i]);
}
// add the number of times the last word in the series occurs: total size of text - 1 (index starts at 0) - index at which the last word starts
word_count.push_back(word_input.size()-1-break_index[break_index.size()-1]);
// number of (distinct) words and their frequency output
cout << "The number of words in this text is: " << word_input.size() << endl;
cout << "Number of distinct words is: " << unique_words.size() << endl;
// The frequency of each word in the text
for(int i=0; i != unique_words.size(); ++i)
cout << unique_words[i] << " occurs " << word_count[i] << " time(s)" << endl;
return 0;
}
使用矢量有更好的方法吗?通过组合任何循环可以使代码更高效吗?
答案 0 :(得分:1)
对我有用的解决方案(当我解决这个问题时)是使用三个向量:input_vector
,output_vector
和count_vector
。使用while
使用std::cin
阅读用户输入,直到输入转义字符:使用input_vector.push_back(input_word)
用文字填充input_vector
。使用std::sort
中的<algorithm>
对矢量进行排序,然后创建output_vector
(包含一个值,input_vector
中的第一个单词)和count_vector
(包含一个值, 1
)。
然后,对于input_vector
中的每个元素(从第二个开始,而不是第一个),检查当前元素是否与最后一个元素相同。如果是,请将1
添加到count_vector
中的当前元素。否则,使用input_vector
将output_vector
中的当前单词添加到push_back()
,并将count_vector
的大小增加一个元素(其值为1
)。
答案 1 :(得分:0)
如果你想象某人正在使用你的代码来处理莎士比亚的整个作品,你会因为存储每一个字而浪费大量的空间。如果您改为使用“单词”和“单词计数”的结构,您只需要存储单词“the”一次,即使它在您的程序输入的文本中出现了100000次。也就是说,如果您甚至需要知道该单词已经出现过多次 - 如果您只需要一个唯一单词列表,那么您只需要查看是否已经存储了该单词。 [以排序顺序存储它们可以使用binary_search
来查找它们,如果您确实通过代码运行莎士比亚的800K(非唯一)单词,这将有助于运行时间