2013-09-27 23 views
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; 
    } 
    
+0

您显示了很多注释行,其中很多回答了您所问的问题。你现在发布的内容不会运行,因为'main'被注释掉了,但是在那里,它正确地读取了行。将你的'cout'移到while循环的外部,并在循环结束时删除所有的东西到0。此外,检查行中单词的代码有一个错误:“一个单词[6个空格]和一个”'将导致8个单词。 –

回答

0

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

+0

或将每行/字转储到std :: set或std :: unordered_set,然后输出.size()。 – bstamour

+0

但是,当我删除这些重置计数器时,每次输入行时,计数器都会从停止的位置继续。例如我输入一行,它输出1.然后,当我输入另一行时,它应该说1输出2. – user2816003

+0

嗯,我想这取决于你。这听起来像是你想通过换行符累积它们。 – spartacus

0

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

0

我不想让批发的答案,但这里有一些想法让你开始。

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

在读取数据时,可以计算行数,字数和字符总数,所以我不会在那里详细讨论。

每个项目都是Googleable的,您可以选择以不同的方式实现不同的部分(例如,如果您不想使用字符串流,则可以遍历整个读取行)。这应该让您在右侧跟踪。

+0

我明白你在说什么。我尝试将字符串转储到集合中,并让程序返回集合的大小。然而,柜台只是随着每条线路不断增加而没有任何变化。 – user2816003

+0

例如,我输入一行,输出表示唯一行。然后,当我再次做到这一点时,计数应该只有一个,最多两个。 – user2816003

+0

这听起来像是你没有正确地计算事物。对于在一行中读取的每一次迭代,您应该a)更新“总计行数”计数器,以及b)将该行放入一个集合中。在循环结束时,您将有一个计数器,用于存储所读取的总行数,以及一个包含每条唯一行的集合。做相同的语言逻辑,你完成了很多。 – bstamour

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)中,它可能不是他真正想要的。我的猜测是,他的老师并没有真正要求这种关心的水平来尝试获得准确的字符数。

另请注意,如果您应该遇到比缓冲区更长的行,这仍然会给出不准确的行数 - 它会将每个缓冲区计数为全部数据作为单独的行,即使它没有找不到行分隔符。这也可以得到解决,但它增加了一个程序的复杂性,这个程序几乎可以肯定比预期的要复杂得多。