c ++从文本文件中读取数字,忽略注释

时间:2012-11-09 07:40:03

标签: c++ parsing inputstream

所以我在这个网站上看到了很多解决方案和有关从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 /////////////////

我是否可以将评论处理与此解决方案结合使用,还是需要采用不同的方法?任何建议都会很棒,谢谢。

3 个答案:

答案 0 :(得分:3)

如果您的文件始终在第一列中包含#,那么只需测试一下,如果该行以#开头,请执行以下操作:

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 :(得分:2)

如果这只是一个使用,对于像你这样的面向行的输入, 最简单的解决方案就是从你刚才的行中删除评论 读:

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

更通用的解决方案是使用过滤streambuf,某些东西 喜欢:

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。那样你就错了 邮件。)

答案 2 :(得分:0)

&#34;读取aline并将其解析为字符串&#34;的替代方法,可以使用流本身作为传入缓冲区:

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 
}