我在这个程序上遇到了问题。该程序应该告诉用户给定输入中的行数、单词、字符、唯一行数和唯一单词数。到目前为止,单词和字符还可以。但是,如果用户想要输入多行,我该怎么做?这些函数一次只会输出一行的结果,而不是将两行的结果相加。另外,我无法使"唯一行"和"唯一单词"正常工作。我刚进入C++所以我真的没有太多经验。有人可以帮我吗?
问题:
- 程序一次
- 读取一行,因此当用户多次输入时,程序会单独生成结果,而不是将其作为一个实体加在一起。 唯一
行和唯一单词不起作用。如何使用程序中使用的库实现它的任何想法。
#include <iostream> using std::cin; using std::cout; using std::endl; #include <string> using std::string; #include <set> using std::set; // write this function to help you out with the computation. unsigned long countLines() { return 1; } unsigned long countWords(const string& s) { int nw =1; for (size_t i = 0; i < s.size(); i++) { if (s[i] == ' ') //everytime the function encounters a whitespace, count increases by 1)// { nw++; } } return nw; } unsigned long countChars(const string& s) { int nc = 0; for (size_t i = 0; i < s.size(); i++) { if ( s[i] != ' ') //everytime the function encounters a character other than a whitespace, count increases// { nc++; } } return nc; } unsigned long countUnLines(const string& s, set<string>& wl) { wl.insert(s); return wl.size(); } unsigned long countUnWords(const string& s, set<string>& wl) { int m1 = 0; int m2 = 0; string substring; for(m2 = 0; m2 <= s.size(); m2++){ if (m2 != ' ' ) substring = s.substr(m1,m2); wl.insert(substring); m1 = m2 + 2;} } return wl.size(); int unw = 0; wl.insert(s); unw++; return unw; } int main() { //stores string string s; //stores stats unsigned long Lines = 0; unsigned long Words = 0; unsigned long Chars = 0; unsigned long ULines = 0; unsigned long UWords = 0; //delcare sets set<string> wl; while(getline(cin,s)) { Lines += countLines(); Words += countWords(s); Chars += countChars(s); ULines += countUnLines(s,wl); UWords += countUnWords(s); cout << Lines << endl; cout << Words<< endl; cout << Chars << endl; cout << ULines << endl; cout << UWords << endl; Words = 0; Chars = 0; ULines = 0; UWords = 0; } return 0; }
您在循环时将 get line 末尾的计数变量重置为零。 这就是为什么您只能获得一行的结果。 用户可以在您的程序中输入多行,因为现在您只是重置计数。
我认为你正朝着正确的方向前进。为了计算独特的行和单词,您必须将每一行和每个单词存储在某种数据结构中,我建议使用unordered_map。地图中的每个元素都有一个计数器,用于显示每行/单词的出现次数#。
我不想批发给出答案,但这里有一些想法可以帮助您入门。
- 函数 getline(( 可以读取整行输入。执行此操作,直到没有更多输入。
- 您可以使用像 std::set(或更好的 std::unordered_set(这样的容器来存储读入的行。不是最有效的,但它会跟踪您的所有行,并且只存储唯一的行。
- 然后,可以将每一行分解为单词。考虑使用类似 std::stringstream 的东西。
- 将单词存储在不同的 std::unordered_set 中。 唯一行数(字数
- (只是存储在容器中的行数(字数(。使用 .size(( 方法获取此值。
行数、单词数和字符数可以在您读取数据时计算,所以我不会在那里详细介绍。
每个项目都是可谷歌搜索的,你可以选择以不同的方式实现不同的部分(例如,如果你不想使用字符串流,你可以随时迭代行读取。这应该会让你走上正确的轨道。
获得相当准确的计数非常容易,但要获得所有这些的正确计数可能非常困难。
最大的问题是字符数。如果您以文本模式打开文件(像往常一样(,则您计算的字符数可能与操作系统认为的字符数不匹配。对于显而易见的示例,在 Windows 下,CR/LF 对将转换为单个换行符,因此您通常会将每行计为比实际短一个字符。
从技术上讲,也没有办法完全正确地处理这个问题——当文件以文本模式打开时,从外部表示到内部表示的转换理论上是任意的。至少在理论上,以二进制模式打开也没有多大帮助;在二进制模式下,在写入文件的数据结束后可以有任意数量的 NUL 字符。
然而,后者如今几乎是理论上的(它被允许主要是因为CP/M,大多数人早已忘记了(。
要读取行,但保留行尾分隔符不变,可以使用 std::cin.get()
而不是 std::getline()
,然后分别读取行本身的分隔符。
这给了我们这样的东西:
#include <iostream>
#include <set>
#include <string>
#include <iterator>
#include <sstream>
#include <fstream>
int main(int argc, char **argv) {
static char line[4096];
unsigned long chars = 0;
unsigned long words = 0;
unsigned long lines = 0;
std::set<std::string> unique_words;
std::ifstream in(argv[1], std::ios::binary);
while (in.get(line, sizeof(line), 'n')) {
++lines;
chars += strlen(line);
std::istringstream buffer(line);
std::string word;
while (buffer >> word) {
++words;
unique_words.insert(word);
}
while (in.peek() == 'n' || in.peek() == 'r') {
++chars;
in.ignore(1);
}
}
std::cout << "words: " << words << "n"
<< "lines: " << lines << "n"
<< "chars: " << chars << "n"
<< "unique words: " << unique_words.size() << "n";
}
请注意,尽管这确实回答了OP实际上至少要求大多数典型操作系统(Linux,*BSD,MacOS,Windows(的问题,但这可能不是他真正想要的。我的猜测是,他的老师并没有真正要求这种程度的关心来试图获得准确的字符数。
另请注意,如果您遇到比缓冲区长的行,这仍然会产生不准确的行计数 - 它会将每个充满数据的缓冲区计为单独的行,即使它没有找到行分隔符。这也可以修复,但它增加了一个几乎肯定已经比预期更复杂的程序的复杂性。