1

我有一些具有以下模式的 .txt 文件:

#Some comments here

bull rocket 3
trailer laker -12

#More comments there

Warriors Pacers 9

基本上,有一些以 # 开头的注释,其他行包含两个字符串,后跟一个 int

我需要这两个字符串和一个 int 一个一个来处理,我必须忽略任何空白行或以 # 开头的行

我正在考虑使用 ifstream.get() 读取第一个字符并丢弃整行,如果它是 #

但是当涉及到数据时,我被卡住了。如何读取一个字符然后获取第一个字符串?即,我找到一个“b”,然后我需要“公牛”。我应该怎么办?

谢谢

4

5 回答 5

3

使用 " while (std::getline(is, line)) {" 一次读取文件流 ( std::istream is) 一行 ( std::string line)。

如果lineempty()或以#,开头continue。您可能希望在执行此检查之前修剪任何前导空格。

否则,解析该行(可能使用std::istringstream iss(line); iss >> first >> second >> value;)。StackOverflow 上的其他地方有很多很好的例子来说明如何做到这一点。

于 2013-02-26T06:03:43.167 回答
2

类似的东西:

#include <iostream>
#include <string>
#include <fstream>
int main(){
  std::ifstream input("input");
  while (input.good()) {
    char c = input.peek();
    if (c == '#' || c == '\n') {
      input.ignore(256, '\n');
      continue;
    }   
    std::string s1, s2; 
    int i;
    input >> s1 >> s2 >> i;
    if (input.good())
      std::cout << s1 << " - " << s2 << " - " << i << std::endl;
  }
  input.close();
  return 0;
}
于 2013-02-26T06:41:58.827 回答
2
 #include <iostream>
 #include <fstream>
 #include <sstream>
 #include <string>
 using namespace std;
 int main()
 {
        fstream f1("f1.data");
        string line,w1,w2;
        int num;

        while ( getline(f1,line) ) {
                if ( istringstream(line) >> w1 >> w2 >> num
                  && w1[0] != '#' )
                        cout << w1 <<' '<< w2 <<' '<< num << '\n';
        }
 }

这是轻量级文本扫描,而不是 javascript 解释器或类似的词法分析器;清晰胜过一切,因此请使用 C++ 中将其转化为脚本语言的部分,以充分发挥其优势。

于 2013-02-26T07:22:28.697 回答
1

示例代码:

    ifstream in("file.txt");
    if (!in.is_open())
        return false;

    string line;
    while (getline(in, line))
    {
        istringstream iss(line, istringstream::in);

        if (!line.length())
            continue;

        if (line[0] == '#') // Ignore the line starts with #
            continue;

       vector<string> words;

        string word;
        while (iss >> word)
        {
                words.push_back(word);
        }

        // now you have all words of current line
        // you can use them to parse your file
    }

这是一个示例代码,您应该在 # 之前跳过空格。例如左修剪很有用。

于 2013-02-26T06:05:35.507 回答
0

除了@MM. 的回答,您可以使用<regex>C++ 11 的新功能。但是请注意,目前并非所有标准库都完全实现了这一点,因此您可能还想在Boost.regex必要时回退。

#include <fstream>
#include <iostream>
#include <sstream>

// note: Most C++11 regex implementations are not up to scratch, offer
// Boost.regex as an alternative.
#ifdef USE_BOOST_REGEX
#include <boost/regex.hpp>
namespace std
{
  using ::boost::regex;
  using ::boost::regex_match;
  using ::boost::smatch;
}
#else
#include <regex>
#endif

#include <string>
#include <tuple>
#include <vector>

int main()
{
  // open input file
  std::ifstream in("file.txt");
  if (!in.is_open()) return 1;
  // ECMAScript syntax!
  std::regex empty_or_comment_re("\\s*(?:#.*)?");
  // note: only matches integers
  std::regex values_re("\\s*(\\S+)\\s+(\\S+)\\s+(-?\\d+)\\s*");
  // will contain the results
  std::vector<std::tuple<std::string, std::string, int> > results;
  size_t lineno = 0; // for error reporting
  std::string line;
  // read lines
  while (getline(in, line))
  {
    ++lineno;
    // match empty or comment lines
    if (regex_match(line, empty_or_comment_re)) continue;
    // match lines containing data
    std::smatch match;
    if (!regex_match(line, match, values_re))
    {
      std::cerr<< "ERROR: malformed line in file.txt, line " << lineno
        << ".\n";
      return 1;
    }
    // read integer from match
    int n;
    std::istringstream iss(match[3]);
    iss >> n;
    // append to results
    results.push_back(std::make_tuple(match[1], match[2], n));
  }
}
于 2013-02-26T07:07:15.817 回答