2012-11-09 178 views
0

所以我在这个网站上看到很多解决方案和关于从C++文本文件读入的教程,但还没有找到解决我的问题的方法。我是C++的新手,所以我觉得我无法将一些文档拼凑在一起来理解这一切。C++从文本文件中读取数字,忽略注释

我想要做的是读取文本文件数字,而忽略文件中用“#”表示的注释。因此,一个例子文件将是这样的:当没有任何意见

#here is my comment 
20 30 40 50 
#this is my last comment 
60 70 80 90 

我的代码可以阅读精细的数字,但我不明白解析流不够好,忽略注释。它现在是一种黑客解决方案。

/////////////////////// Read the file /////////////////////// 
std::string line; 
if (input_file.is_open()) 
{ 
    //While we can still read the file 
    while (std::getline(input_file, line)) 
    { 
     std::istringstream iss(line); 
     float num; // The number in the line 

     //while the iss is a number 
     while ((iss >> num)) 
     { 
      //look at the number 
     } 
    } 
} 

else 
{ 
    std::cout << "Unable to open file"; 
} 
/////////////////////// done reading file ///////////////// 

有没有一种方法,我可以将意见用此溶液处理或者我需要一种不同的方法?任何建议将是伟大的,谢谢。

+1

'line.assign(line.substr(0,line.find('#')));'(作为while循环中的第一条语句)将会是快速做出必要改变的一种方法。 – jogojapan

+0

这非常非常简单。你说你不明白上面的代码足以修改它。我想在你尝试别的之前,你需要花一些时间去理解。 – john

+0

你有没有试过它与文件中存在的评论?正如所写的,代码将忽略第一部分之后的行的任何部分,该部分不是包含注释的有效数字。 –

回答

2

如果文件包含#始终在第一列,然后只是测试,如果符合#这样开始:

while (std::getline(input_file, line)) 
{ 
    if (line[0] != "#") 
    { 
     std::istringstream iss(line); 
     float num; // The number in the line 

     //while the iss is a number 
     while ((iss >> num)) 
     { 
      //look at the number 
     } 
    } 
} 

这是明智的,虽然修剪开头和结尾的空格线,像这里示出例如:Remove spaces from std::string in C++

+1

如果它不是第一个字符,那么使用'std :: find'找到它是一个简单的命令,'std :: string :: erase'可以将其删除。 –

+0

请参阅我之前尝试过的if语句,并得到错误:'比较指针和整数('int'和'const char *')'。 –

+0

如果使用getline(input_file >> std :: ws,line)替换getline(input_file,line)',则注释行可以包含前导空格。 –

0

一个替代的“读艾琳并解析它作为一个字符串”,可以使用流本身作为入缓冲液:

while(input_file) 
{ 
    int n = 0; 

    char c; 
    input_file >> c; // will skip spaces ad read the first non-blank 

    if(c == '#') 
    { 
     while(c!='\n' && input_file) input_file.get(c); 
     continue; //may be not soooo beautiful, but does not introduce useless dynamic memory 
    } 

    //c is part of something else but comment, so give it back to parse it as number 
    input_file.unget(); //< this is what all the fuss is about! 
    if(input_file >> n) 
    { 
     // look at the nunber 
     continue; 
    } 

    // something else, but not an integer is there .... 
    // if you cannot recover the lopop will exit 
} 
+0

现在有一个如何编写不可读代码的好例子。更不用说最后的“if”不正确。 (如果你得到那么多,它总会是真的,_unless_有硬件错误。) –

+0

@JamesKanze:根据标准,当提取操作失败时,设置“failbit”(不是“badbit”,这是不同的)例如,因为您期望读取一个数字,但e是输入处的非数字数字)。这里的重点不是“关闭代码”,而是让它开放来分析更多的其他案例。我重新编写了代码,但这里的重点不在于使其优雅,而在于避免引入一些不必要的动态内存alloc/dealloc(通常用于string-s和sringstream-s)。 –

+0

在原始代码中,直到输入失败('input_file >> n'评估为false)之前,您才测试'failbit'。如果输入失败,则必须设置'failbit'或'badbit';当且仅当streambuf有一个异常时(这在大多数情况下从不),badbit被设置。所以当你测试'failbit'时,它几乎肯定会被设置。一旦出现故障,你可以测试'eof()'来决定是否因为没有更多内容需要读取,或者因为输入格式有错误(两者都会导致'failbit'被设置) 。 –

2

如果这仅仅是使用的一个,像你行定向投入, 简单的解决办法就是剥去从刚刚 读行注释:

line.erase(std::find(line.begin(), line.end(), '#'), line.end()); 

一个更通用的解决方案将是使用过滤流缓冲,东西 这样的:

class FilterCommentsStreambuf : public std::streambuf 
{ 
    std::istream& myOwner; 
    std::streambuf* mySource; 
    char myCommentChar; 
    char myBuffer; 

protected: 
    int underflow() 
    { 
     int const eof = std::traits_type::eof(); 
     int results = mySource->sbumpc(); 
     if (results == myCommentChar) { 
      while (results != eof && results != '\n') { 
       results = mySource->sbumpc(0; 
      } 
     } 
     if (results != eof) { 
      myBuffer = results; 
      setg(&myBuffer, &myBuffer, &myBuffer + 1); 
     } 
     return results; 
    } 

public: 
    FilterCommentsStreambuf(std::istream& source, 
          char comment = '#') 
     : myOwner(source) 
     , mySource(source.rdbuf()) 
     , myCommentChar(comment) 
    { 
     myOwner.rdbuf(this); 
    } 
    ~FilterCommentsStreambuf() 
    { 
     myOwner.rdbuf(mySource); 
    } 
}; 

在这种情况下,你甚至可以放弃getline

FilterCommentsStreambuf filter(input_file); 
double num; 
while (input_file >> num || !input_file.eof()) { 
    if (! input_file) { 
     // Formatting error, output error message, clear the 
     // error, and resynchronize the input---probably by 
     // ignore'ing until end of line. 
    } else { 
     // Do something with the number... 
    } 
} 

(在这种情况下,我发现跟踪 的行号FilterCommentsStreambuf也很有用。 )

相关问题