【问题标题】:How to split a text file into words?如何将文本文件拆分为单词?
【发布时间】:2010-10-13 13:26:24
【问题描述】:

我正在做一个任务,我应该读取一个文件并计算行数,同时计算其中的单词。 我在 while 循环中尝试了 getline 和 strtok 的组合,但没有奏效。

file:example.txt(要读取的文件)。

嗨,你好,真是个惊喜。
欢迎来到这个地方。
愿您在这里过得愉快。
(3 行,一些单词)。

读取文件.cpp

#include <iostream>
#include <fstream>
#include<string>
using namespace std;
int main()
{
  ifstream in("example.txt");
  int count = 0;

  if(!in)
  {
    cout << "Cannot open input file.\n";
    return 1;
  }

  char str[255];
  string tok;
  char * t2;

  while(in)
  {
    in.getline(str, 255);
    in>>tok;
    char *dup = strdup(tok.c_str());
    do 
    {
        t2 = strtok(dup," ");
    }while(t2 != NULL);
    cout<<t2<<endl;
    free (dup);
    count++;
  }
  in.close();
  cout<<count;
  return 0;
}

【问题讨论】:

  • 你需要说的不仅仅是“没用”。告诉我们您遇到了什么错误,或者您的程序执行的操作与您预期的不同,然后提出一个具体问题。我们不会为您调试或重写您的作业。
  • 下面的一些示例怎么样:codeproject.com/KB/recipes/Tokenizer.aspx 它们非常高效且有些优雅。字符串工具包库使 C++ 中的复杂字符串处理变得简单易行。

标签: c++ string parsing token


【解决方案1】:

尝试将您的 cout&lt;&lt;t2&lt;&lt;end; 语句移动到您的 while 循环中。

这应该使您的代码基本上可以正常工作。

您可能希望查看this similar post 了解其他方法。

【讨论】:

    【解决方案2】:

    网上到处都有这样的例子。这是我在高中时写的一个数词程序。以它为起点。我想指出的其他事项是:

    std::stringstream :你 std::getline 整行,然后使用 std::stringstream 将其切成小块并标记它。您可以使用 std::getline 获取整行并将其输入到 std::string,然后您可以将其传递给 std::stringstream。

    再一次,这只是一个示例,不会完全按照您的意愿执行,您需要自己修改它以使其执行您想要执行的操作!

    #include <iostream>
    #include <map>
    #include <string>
    #include <cmath>
    #include <fstream>
    
    // Global variables
            std::map<std::string, int> wordcount;
            unsigned int numcount;
    
    void addEntry (std::string &entry) {
            wordcount[entry]++;
            numcount++;
            return;
    }
    
    
    void returnCount () {
            double percentage = numcount * 0.01;
            percentage = floor(percentage + 0.5f);
    
            std::map<std::string, int>::iterator Iter;
    
            for (Iter = wordcount.begin(); Iter != wordcount.end(); ++Iter) {
                    if ((*Iter).second > percentage) {
                            std::cout << (*Iter).first << " used " << (*Iter).second << " times" << std::endl;
                    }
            }
    
    }
    
    int main(int argc, char *argv[]) {
            if (argc != 2) {
                    std::cerr << "Please call the program like follows: \n\t" << argv[0] 
                            << " <file name>" << std::endl;
                    return 1;
            }
    
            std::string data;
    
            std::ifstream fileRead;
            fileRead.open(argv[1]);
            while (fileRead >> data) {
                    addEntry(data);
            }
            std::cout << "Total words in this file: " << numcount << std::endl;
            std::cout << "Words that are 1% of the file: " << std::endl;
            returnCount();
    }
    

    【讨论】:

    • 您好,感谢 Blorgbeard、Reed 和 X-Istence 的及时回复。我不仅需要解析线路,还需要跟踪线路编号。问题陈述是用它们出现的行号制作一个单词列表。
    • Ravi:我刚刚给你的代码会让你成功一半。我们不是来帮你做功课的!
    • 哦,不!这不是我的意图。我在第一部分遇到了麻烦。一旦解决了这个问题,我打算自己做剩下的事情。
    【解决方案3】:

    刚刚做对了!! 刚刚删除了所有不必要的代码。

    int main()
    {    
        ifstream in("example.txt");
        int LineCount = 0;
        char* str = new char[500];
    
        while(in)
        {
            LineCount++;
            in.getline(str, 255);
            char * tempPtr = strtok(str," ");
            while(tempPtr)
            {
                AddWord(tempPtr, LineCount);
                tempPtr = strtok(NULL," ,.");
            }
        }
        in.close();
        delete [] str;
        cout<<"Total No of lines:"<<LineCount<<endl;
        showData();
    
        return 0;
    }
    

    顺便说一句,最初的问题陈述是创建一个索引程序,该程序将接受用户文件并创建所有单词的行索引。

    【讨论】:

    • 请不要使用strtok。一旦你需要编写多线程代码,它就会回来咬你。标准 C++ 的一个很好的替代品是 std::istringstream。
    【解决方案4】:

    如果你可以使用 boost 库,我建议使用 boost::tokenizer

    boost Tokenizer 包提供了一个 灵活易用的破解方式 字符串或其他字符的 序列成一系列标记。 下面是一个简单的例子,它将 将短语分解成单词。

    // simple_example_1.cpp
    #include<iostream>
    #include<boost/tokenizer.hpp>
    #include<string>
    
    int main(){
       using namespace std;
       using namespace boost;
       string s = "This is,  a test";
       tokenizer<> tok(s);
       for(tokenizer<>::iterator beg=tok.begin();beg!=tok.end();++beg){
           cout << *beg << "\n";
       }
    }
    

    【讨论】:

      【解决方案5】:

      我没有尝试编译它,但这里有一个替代方法,它几乎与使用 Boost 一样简单,但没有额外的依赖。

      #include <iostream>
      #include <sstream>
      #include <string>
      
      int main() {
        std::string line;
        while (std::getline(std::cin, line)) {
          std::istringstream linestream(line);
          std::string word;
          while (linestream >> word) {
            std::cout << word << "\n";
          }
        }
        return 0;
       }
      

      【讨论】:

      • +1 我就是这样做的。现在只需插入计数器就完成了。
      【解决方案6】:
      ifstream is {"my_file_path"}; 
      vector<string> b {istream_iterator<string>{is},istream_iterator<string>{}};
      

      别忘了包括这个:

      <iterator>
      

      【讨论】:

        猜你喜欢
        • 1970-01-01
        • 1970-01-01
        • 2010-10-21
        • 2016-09-16
        • 1970-01-01
        • 2021-10-16
        • 2020-12-15
        • 1970-01-01
        • 2020-05-08
        相关资源
        最近更新 更多