【问题标题】:Count first digit on each line of a text file计算文本文件每一行的第一个数字
【发布时间】:2017-01-10 20:05:20
【问题描述】:

我的项目需要一个文件名并打开它。我需要读取 .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

我想要的输出一直是 9,但我把它浓缩了:

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

如何遍历文件只找到第一个整数并计算它,而忽略 cmets?

【问题讨论】:

  • 为什么输出中没有0?你的意思是第一个数字,还是第一个整数的所有数字?此外,您需要两个单独的循环(输入和输出)。至少打印你应该已经想到了。
  • 例子看不懂,文中出现了不止一次
  • 使用std::getline 创建一个使用std::isdigit 的手写循环。 vector&lt;int&gt; file_nums {infile_begin, eof}; 没有意义。 eof 是一种完全不同类型的迭代器,即使是 std::istreambuf_iterator&lt;char&gt;,你也不会解析任何东西。
  • 好的,我想我明白你想做什么了。问题是什么?
  • 您现在真的应该忘记该行的来源(文件,键盘,无关紧要),并编写一个给定字符串的函数,返回您的数字寻找。然后您测试该功能以查看是否确实完成了这项工作。一旦您对该功能进行了全面测试,然后您就可以在更大的程序中使用它。尝试一次性完成 3 或 4 个不同的任务并不是渐进式开发程序的方法。

标签: c++ vector io istream


【解决方案1】:

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

  1. 创建一个std::map&lt;int, int&gt;,其中键是数字,值是计数。这允许您计算您的数字的统计信息,例如在解析文件之后的计数和频率。在this SO answer 中可以找到类似的内容。
  2. 使用std::getline 将文件的每一行读取为std::string,如this SO answer 所示。
  3. 对于每一行,使用如下函数剥离 cmets:

    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, "(*", "*)");
    
  4. 剥离cmets后,使用字符串成员函数find_first_of求第一个数字:

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

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

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

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

我希望这可以帮助您入门。我把代码的编写留给你。祝你好运!

【讨论】:

    猜你喜欢
    • 1970-01-01
    • 1970-01-01
    • 2015-09-30
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 2020-11-28
    • 2015-03-01
    • 1970-01-01
    相关资源
    最近更新 更多