0

我在使用这个程序时遇到了问题。该程序应该告诉用户在给定输入中存在的行数、单词数、字符数、唯一行数和唯一单词数。到目前为止,单词和字符都还可以。但是,如果用户想要输入多行,我该怎么做呢?这些函数一次只输出一行的结果,而不是将两行的结果相加。此外,我无法让独特的线条和独特的单词正常工作。我刚接触 C++,所以我没有太多经验。有人可以帮帮我吗?

问题:

  1. 程序一次读取一行,因此当用户多次输入时,程序会分别生成结果,而不是将其作为一个实体加在一起。
  2. 唯一行和唯一字不起作用。任何想法如何使用程序中使用的库来实现它。

    #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;
    }
    
4

4 回答 4

0

您在 getline while 循环结束时将计数变量重置为零。这就是为什么你只得到一条线的结果。用户可以在程序中输入多行,因为现在您只是在重置计数。

于 2013-09-27T17:31:29.300 回答
0

我认为你正朝着正确的方向前进。为了计算唯一的行和单词,您必须将每一行和单词存储在某种数据结构中,我建议使用 unordered_map。地图中的每个元素都有一个计数器,用于记录每行/单词的出现次数。

于 2013-09-27T17:34:04.343 回答
0

我不想批发给出答案,但这里有一些想法可以帮助您入门。

  1. 函数 getline() 可以读取整行输入。这样做直到没有更多的输入。
  2. 您可以使用像 std::set(或更好的 std::unordered_set)这样的容器来存储读入的行。不是最有效的,但它会跟踪您的所有行,并且只存储唯一的行。
  3. 然后可以将每一行分解为单词。考虑为此使用 std::stringstream 之类的东西。
  4. 将单词存储在不同的 std::unordered_set 中。
  5. 唯一行(字)的数量就是存储在容器中的行(字)的数量。使用 .size() 方法来获得它。

读取数据时可以计算行数、单词和字符的总数,所以我不会在这里详细介绍。

每个项目都是可搜索的,您可以选择以不同的方式实现不同的部分(例如,如果您不想使用字符串流,您可以随时迭代读取的行。)这应该让您走上正确的轨道。

于 2013-09-27T17:53:02.030 回答
0

获得相当准确的计数非常容易,但要获得所有这些的正确计数却非常困难。

最大的问题是字符数。如果您以文本模式打开文件(如通常那样),您计算的字符数可能与操作系统认为的不匹配。对于明显的示例,在 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),但这可能不是他真正想要的。我的猜测是,他的老师并没有真正要求这种程度的照顾来尝试获得准确的字符数。

另请注意,如果您遇到比缓冲区长的行,这仍然会给出不准确的行数——即使没有找到行,它也会将每个充满数据的缓冲区计算为单独的行——分隔符。这也可以修复,但它给几乎可以肯定已经比预期更复杂的程序增加了更多的复杂性。

于 2013-09-27T18:09:25.630 回答