计算文本文件

时间:2016-09-02 16:22:47

标签: c++ vector io istream

我的项目采用文件名并打开它。我需要读取.txt文件的每一行,直到第一个数字出现,跳过空格,字符,零或特殊字符。我的文本文件可能如下所示:

1435                 //1, nextline
0                   //skip, next line
                    //skip, nextline
(*Hi 245*) 2       //skip until second 2 after comment and count, next line
345 556           //3 and count, next line 
4                //4, nextline

我想要的输出将一直到九,但我浓缩了它:

Digit Count Frequency
1:      1     .25
2:      1     .25
3:      1     .25
4:      1     .25

我的代码如下:

    #include <iostream>
    #include <fstream>
    #include <string>
    using namespace std;

    int main() {

        int digit = 1;
        int array[8];
        string filename;
        //cout for getting user path
        //the compiler parses string literals differently so use a double backslash or a forward slash
        cout << "Enter the path of the data file, be sure to include extension." << endl;
        cout << "You can use either of the following:" << endl;
        cout << "A forwardslash or double backslash to separate each directory." << endl;
        getline(cin,filename);

        ifstream input_file(filename.c_str());

        if (input_file.is_open()) { //if file is open
            cout << "open" << endl; //just a coding check to make sure it works ignore

       string fileContents; //string to store contents
       string temp;
       while (!input_file.eof()) { //not end of file I know not best practice
       getline(input_file, temp);
       fileContents.append(temp); //appends file to string
    }
       cout << fileContents << endl; //prints string for test
        }
        else {
            cout << "Error opening file check path or file extension" << endl;
        }

在此文件格式中,(*表示注释的开头,因此应忽略从那里到匹配的*)的所有内容(即使它包含数字)。例如,如果输入(*Hi 245*) 6,则应计算6,而不是2

如何迭代文件,只查找第一个整数并对其进行计数,同时忽略注释?

1 个答案:

答案 0 :(得分:0)

解决问题的一种方法如下:

  1. 创建一个std::map<int, int>,其中键是数字,值是计数。这允许您计算数字的统计数据,例如计算和解析文件后的频率。类似的东西可以在this SO answer
  2. 中找到
  3. 使用std::string使用std::getline读取文件的每一行,如this SO answer所示。
  4. 对于每一行,使用如下函数删除注释:

    std::string& strip_comments(std::string & inp, 
                                std::string const& beg, 
                                std::string const& fin = "") {
      std::size_t bpos;
      while ((bpos = inp.find(beg)) != std::string::npos) {
        if (fin != "") {
          std::size_t fpos = inp.find(fin, bpos + beg.length());
          if (fpos != std::string::npos) {
            inp = inp.erase(bpos, fpos - bpos + fin.length());
          } else {
            // else don't erase because fin is not found, but break
            break;
          }
        } else {
          inp = inp.erase(bpos, inp.length() - bpos);
        }
      }
      return inp;
    }
    

    可以这样使用:

    std::string line;
    std::getline(input_file, line);
    line = strip_comments(line, "(*", "*)");
    
  5. 剥离评论后,使用字符串成员函数find_first_of查找第一个数字:

    std::size_t dpos = line.find_first_of("123456789");
    

    这里返回的是第一个数字的字符串中的索引位置。您应检查返回的位置是否为std::string::npos,因为这表示未找到任何数字。如果找到第一个数字,则可以使用const char c = line[dpos];提取相应的字符,并使用std::atoi转换为整数。

  6. 增加std::map中该数字的计数,如第一个链接的SO答案所示。然后循环回读下一行。

  7. 在读取文件中的所有行后,std::map将包含在每行删除注释时找到的所有第一个数字的计数。然后,您可以迭代此映射以检索所有计数,累计找到的所有数字的总计数,并计算每个数字的频率。请注意,未找到的数字不会出现在地图中。

  8. 我希望这有助于您入门。我把代码写给你。祝你好运!