【问题标题】:Word Count with Sorting C++使用 C++ 排序的字数统计
【发布时间】:2020-02-07 11:43:03
【问题描述】:

这是我的数据结构课程的一个问题。 我完全不知道如何处理它,请任何人提供一些提示吗?

  1. 如何停止程序并确保输出正确?
  2. 我是否必须处理映射?

the question paper I had from the professor

以下是我的编码示例:

#include <iostream>
#include <string>

using namespace std;

int main()
{
    string s [100];

    for (int i = 0; i < 100; i++) {
        cin >> s[i];
        s[i] = Sort(s[i], s[i+1]);
    }


    //check the number of time the words repeatcout the answer
    for (int i = 0; i < 100; i++) {
        cout << s[i] << count (s[i],s[i+1]) <<endl;
    }
    return 0;
}


string Sort(string current, string next ) {
    if (current > next) {
        string temp = current;
        current = next;
        next = temp;
    }
    else {
        return current;
    }
}

int count(string word, string Nextword) {
    int count;
    if (word == Nextword) {
        count++;
    }
    else {
        return count;
    }
}

【问题讨论】:

  • 哇...您可以使用vector&lt;string&gt; 代替字符串数组吗?这将使生活更轻松。问题,当您执行s[i] = Sort(s[i], s[i+1]); 时,s[i+1] 中是什么?类似的问题还有很多。
  • 您应该真正了解引用的工作原理,并在适当的时候开始使用它们。
  • s[i] = 排序(s[i], s[i+1]);在这里,您在该函数中调用 Sort 函数,您正在检查条件是真还是假。只有那个条件是假的,你才返回值。如果是真的,您没有返回并且值您正在交换 2 个值,它不会影响主要变量。并且返回值变为 NULL..
  • 你的代码不能编译wandbox.org/permlink/uET4wIH1eY4NlYD8你不能在声明之前调用一个函数。请提供minimal reproducible example
  • 我知道我的代码不能遵守...我不知道如何处理这个问题,因为我在学习这门课程之前只学习了非常基本的 C++。

标签: c++ sorting word-count


【解决方案1】:

与其尝试使用基本的字符串数组,不如使用某种方法来跟踪每个单词的出现次数。您可以使用简单的structstd::map。在任何一种情况下,您都可以关联一个单词和它被视为单个对象的次数。如果您随后在std::vector 中收集包含单词和计数的所有结构,而不是基本数组,则可以提供一个简单的比较函数来使用std::sort 按单词对向量进行排序,同时保留计数与每个字。

采取使用stuct 的方法,您可以创建一个包含std::string 和计数器的结构,例如:

 struct wordcount {      /* struct holding word and count */
    std::string word;
    size_t count;
};

对于wordcount的向量按word排序的比较函数,可以用一个简单的:

/* compare function to sort vector of struct by words */
bool cmp (const wordcount& a, const wordcount& b)
{
    return a.word < b.word;
}

使用结构体,您将需要遍历到目前为止所看到的单词,以确定您是否只需要在现有单词上增加 count 或将新的 wordcount 结构体添加到向量中count = 1; 为了使函数有用,如果单词已经存在,您可以让它返回向量中的索引(大致相当于数组中的索引),如果不存在则返回 -1

/* interate over each struct in vector words to find word */
int findword (const std::vector<wordcount>& words, 
                const std::string& word)
{
    for (auto w = words.begin(); w != words.end(); w++)
        if (w->word == word)            /* if word found */
            return w - words.begin();   /* return index */

    return -1;  /* return word not found */
}

根据返回值,您可以在索引处增加count,或者将新的wordcount 添加到您的向量中。使用上述方法的简短实现是:

int main (int argc, char **argv) {

    if (argc < 2) { /* validate filename given as argument */
        std::cerr << "error: insufficient input.\n"
                << "usage: " << argv[0] << "<filename>\n";
        return 1;
    }

    std::string word;                   /* string to hold word */
    std::vector<wordcount> words {};    /* vector of struct wordcount */
    std::fstream f (argv[1]);           /* file stream */

    while (f >> word) {                 /* read each word from file */
        int idx = findword (words, word);   /* alread exists, get index */
        if (idx != -1) {                /* if index found */
            words[idx].count++;         /* increment count */
        }
        else {  /* otherwise new word */
            wordcount tmp = {word, 1};  /* initialize struct */
            words.push_back(tmp);       /* add to vector */
        }
    }

    std::sort (words.begin(), words.end(), cmp);    /* sort by words */

    for (auto& w : words)   /* output results */
        std::cout << w.word << " " << w.count << '\n';
}

如果你把上面的所有部分放在一起,你会得到:

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

struct wordcount {      /* struct holding word and count */
    std::string word;
    size_t count;
};

/* compare function to sort vector of struct by words */
bool cmp (const wordcount& a, const wordcount& b)
{
    return a.word < b.word;
}

/* interate over each struct in vector words to find word */
int findword (const std::vector<wordcount>& words, 
                const std::string& word)
{
    for (auto w = words.begin(); w != words.end(); w++)
        if (w->word == word)            /* if word found */
            return w - words.begin();   /* return index */

    return -1;  /* return word not found */
}

int main (int argc, char **argv) {

    if (argc < 2) { /* validate filename given as argument */
        std::cerr << "error: insufficient input.\n"
                << "usage: " << argv[0] << "<filename>\n";
        return 1;
    }

    std::string word;                   /* string to hold word */
    std::vector<wordcount> words {};    /* vector of struct wordcount */
    std::fstream f (argv[1]);           /* file stream */

    while (f >> word) {                 /* read each word from file */
        int idx = findword (words, word);   /* alread exists, get index */
        if (idx != -1) {                /* if index found */
            words[idx].count++;         /* increment count */
        }
        else {  /* otherwise new word */
            wordcount tmp = {word, 1};  /* initialize struct */
            words.push_back(tmp);       /* add to vector */
        }
    }

    std::sort (words.begin(), words.end(), cmp);    /* sort by words */

    for (auto& w : words)   /* output results */
        std::cout << w.word << " " << w.count << '\n';
}

使用/输出示例

根据您的示例输入运行,您将收到。

$ ./bin/wordcount dat/webpage.txt
Computer 1
algorithm 1
analysis 1
and 1
computer 3
department 1
design 2
quantum 1
science 1
system 1

有很多很多方法可以解决这种类型的问题。它可以用普通的旧数组来完成,但是你会跟踪单词并在一些单独的数组(或数组)中计数,然后编写你自己的排序(或在一个包含单词的数组上使用 C qsort 和然后使用原始副本和计数数组将计数映射回排序输出)。无论您采用哪种方法,关键是您必须有一种方法来保留单词之间的预排序关联以及每个单词与单词的排序后结果的出现次数,然后将计数映射回来到正确的词。使用将单词和计数作为一个单元关联的对象可以解决关联问题。

仔细观察,将它们作为处理它的一种方式。如果您还有其他问题,请告诉我。

【讨论】:

    【解决方案2】:

    std::map 可以同时为你做排序和计数:

    #include <map>
    #include <iostream>
    using std::cin;
    using std::cout;
    using std::endl;
    using std::string;
    
    int main() {
      std::map<string,size_t> wordcount;
      for(string word;cin>>word;++wordcount[word]);
      for(auto it=wordcount.begin();it!=wordcount.end();++it)
        cout << it->first << " " << it->second << endl;
    }
    
    echo -ne "Computer system\ncomputer design\nalgorithm design and analysis\nquantum computer\ncomputer science department" | ./a.out
    Computer 1
    algorithm 1
    analysis 1
    and 1
    computer 3
    department 1
    design 2
    quantum 1
    science 1
    system 1
    

    【讨论】:

    • 这个答案给我留下了深刻的印象!!谢谢。
    • 你能解释一下这行“for(string word;cin>>word;++wordcount[word]);”请给我?我想不通。谢谢
    • "string word; while(!cin.eof()) {cin>>word;if (!cin.fail()) ++wordcount[word]; else break;}" 主要是相等的。 for 循环在其初始化语句中定义了一个“字符串单词”,将字符串读入来自 cin 的单词,该单词返回对 cin 的引用,其中调用 bool 运算符是因为 cin 在布尔上下文中使用,该上下文计算 !cin。 fail() 并在更新语句中增加与使用映射的单词相关联的数字。 for循环的主体是空的,没有“{}”,只有一个“;” . cplusplus.com/reference/ios/ios/operator_bool
    • std::map 是一个排序的关联容器,非常适合这项任务。 cplusplus.com/reference/map/map
    • @ChristiePPP 忘了告诉你:D
    【解决方案3】:

    复制粘贴此代码并检查多个字符串。 解决方案:

    #include <iostream>
    #include <string>
    #include <vector>
    #include <algorithm>
    
    using namespace std;
    
    vector<string> split(const string& i_str, const string& i_delim)
    {
        vector<string> result;
    
        size_t found = i_str.find(i_delim);
        size_t startIndex = 0;
    
        while (found != string::npos)
        {
            string temp(i_str.begin() + startIndex, i_str.begin() + found);
            result.push_back(temp);
            startIndex = found + i_delim.size();
            found = i_str.find(i_delim, startIndex);
        }
        if (startIndex != i_str.size())
            result.push_back(string(i_str.begin() + startIndex, i_str.end()));
        return result;
    }
    
    void countFunc(vector<string> cal) {
        vector<pair<string, int>> result;
        for (int i = 0; i < cal.size(); i++)
        {
            string temp = cal[i];
            if (temp.empty())
            {
                continue;
            }
            int ncount = 1;
            int j = i+1;
            while(j < cal.size())
            {
                if (temp == cal[j])
                {
                    ncount++;
                    cal[j] = "";
                }
                j++;
            }
            result.push_back(make_pair(temp, ncount));
        }
        std::cout << "String\tCount\n";
        for (int i = 0; i < result.size(); i++)
        {
            cout << result[i].first << "\t" << result[i].second << endl;
        }
    }
    
    int main()
    {
        vector<string> str;
        vector<string> res;
        printf("Enter the Number Line :");
        int size = 0;
        cin >> size;
        for (int i = 0; i < size+1; i++)
        {
            string s;
            getline(cin, s);
            if (s.empty())
            {
                continue;
            }
            else
            {
                str.push_back(s);
            }
        }
        for (int i = 0; i < size; i++)
        {
            vector<string> temp;
            temp = split(str[i], " ");
            res.insert(res.end(), temp.begin(), temp.end());
        }
        sort(res.begin(), res.end());
        countFunc(res);
    }
    

    【讨论】:

      【解决方案4】:

      如果使用 STL 不是一个选项,这意味着如果您不能使用矢量等,那么这个简单的解决方案可能会有所帮助。 同样在您的代码中,您已将字符串数组的大小声明为 100,我认为您这样做了,因为根据您的问题陈述,数组的 MAX 大小不能作为输入。

      您需要一种排序方法(我使用了冒泡排序),在对数组进行排序后,您只需遍历数组并计算单词,这很容易通过跟踪即将出现的单词并将它们与当前单词进行比较. 请记住,只要您输入一个空行,下面的代码就会停止输入。

      另外我建议你学习 C++ 中的 STL,它也将帮助你进行竞争性编码。

          #include <iostream>
          using namespace std;
      
          //Forward declaration of functions 
          void sortStringArray(int index,string* s);
          void printWordCount(int index,string array[]);
      
          int main()
          {
              string s [100]; //considering maximum words will be upto 100 words
              string input;  //variable to keep track of each line input
              int index=0;   //index to keep track of size of populated array since we don't need to sort whole array of size 100 if it is not filled
      
      
              while (getline(cin, input) && !input.empty()){  //while line is not empty continue to take inputs
                  string temp="";                     
                  char previous=' ';                  
                  for(int i=0;i<input.size();i++){            //loop to seperate the words by space or tab
                      if(input[i]==' ' && previous!=' '){
                          s[index++]=temp;
                          temp="";
                      }
                      else if(input[i]!=' '){
                          temp+=input[i];
                      }
                      previous=input[i];
                  }
                  if(temp.size()!=0){
                      s[index++] =temp;   
                  }
              }
      
              //Step 1: sort the generated array by calling function with reference, thus function directly modifies the array and don't need to return anything
              sortStringArray(index,s);
      
      
              //Step 2: print each word count in sorted order
              printWordCount(index,s);
      
      
              return 0;
          }
      
          /*
          Function takes the "index" which is the size upto which array is filled and we need only filled elements
          Function takes stirng array by reference and uses Bubble Sort to sort the array
          */
          void sortStringArray(int index,string* s){
              for(int i=0;i<index-1;i++){
                  for(int j=0;j<index-i-1;j++){
                      if(s[j]>s[j+1]){
                          string temp=s[j];
                          s[j]=s[j+1];
                          s[j+1]=temp;
                      }
                  }
              }
          }
      
      
          /*
          Function takes the "index" which is the size upto which array is filled and we need only filled elements
          Function takes stirng array by reference and prints count of each word
          */
          void printWordCount(int index,string array[]){
              int count=1; //to keep track of the similar word count
              for(int i=0;i<index-1;i++){
                  if(array[i]==array[i+1]){ //if current and upcoming words are same then increase the count
                      count++;
                  }
                  else{                       //if next word is not equal to current word then print the count of current word and set counter to 1
                      cout<<array[i]<<" "<<count<<endl;
                      count=1;
                  }
              }
              if(array[index-1]==array[index-2]){  //at end of array if the last and second last words were equal then print the count+1
                  cout<<array[index-1]<<" "<<count+1<<endl;
              }
              else{                               //otherwise the count equal to the last count which will be "1"
                  cout<<array[index-1]<<" "<<count;
              }
          }
      

      输出:

          Computer system
          computer design
          algorithm design and analysis
          quantum computer
          computer science department
      
          Computer 1
          algorithm 1
          analysis 1
          and 1
          computer 3
          department 1
          design 2
          quantum 1
          science 1
          system 1
          --------------------------------
          Process exited after 1.89 seconds with return value 0
      

      【讨论】:

      • 非常感谢,我会寻找 STL
      猜你喜欢
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 2014-10-15
      • 2015-07-19
      • 2015-08-31
      • 1970-01-01
      • 2021-12-26
      相关资源
      最近更新 更多