1

我正在尝试创建一个使用 boost 库读取输入文件的 C++ 代码,如下所示,

    1             12       13        0        0      1      0      INLE
    .
    .
    .

在这种情况下,如果右边最后一列指定的条件是 INLE,我必须执行一个操作。我有以下代码,

#include <iostream>
#include <fstream>
#include <string>
#include <boost/algorithm/string/predicate.hpp>


int main(int argc, const char * argv[])
{
    std::string line;
    const std::string B_condition = "INLE";
    std::ifstream myfile ("ramp.bnd");
    if (myfile.is_open())
    {
        while ( getline (myfile,line) )
        {
            if (boost::algorithm::ends_with(line,B_condition)==true)
            {
                std::cout << "Its True! \n"; // just for testing
                //add complete code
            }
        }
        myfile.close();
    }

    else std::cout << "Unable to open file";

    return 0;
}

编译时没有问题,但是当我运行时,它没有显示任何内容。

另一方面,如果我将布尔条件修改为假,它将打印“它是真的!” 我的输入文件的行数。

我究竟做错了什么?谢谢!!

4

2 回答 2

2

我只能假设:

  • 您的文件末尾包含空格(使用修剪)
  • 您的文件有 Windows 行结束符 (CRLF) ,但您将其作为 UNIX 文本文件读取,这意味着这些行将包含尾随 `\r' (CR)(在各种文本编辑器/寻呼机中通常显示为 ^M)。

所以,要么

  • 修复行尾
  • 在比较之前从行中修剪空白
  • 两者兼而有之

最好的:使用“适当的”解析器来完成这项工作。

更新使用 Boost Spirit 添加一个快速而肮脏的方法:看看它Live On Coliru

int main()
{
    std::ifstream myfile("ramp.bnd");
    myfile.unsetf(std::ios::skipws);

    boost::spirit::istream_iterator f(myfile), l;

    using namespace qi;
    bool ok = phrase_parse(f, l,
            (repeat(7) [ int_ ] >> as_string[lexeme[+(char_ - eol)]])
                [ phx::bind(process_line, _1, _2) ]
            % eol, // supports CRLF and LF
            blank);

    if (!ok)
        std::cerr << "Parse errors\n";
    if (f!=l)
        std::cerr << "Remaing input: '" << std::string(f,l) << "'\n";
}

如您所见,它验证整行,假设(现在)列是 7 个整数值和一个字符串(例如"INLE")。现在,实际工作要简单得多,可以在单独的函数中实现:

void process_line(std::vector<int> const& values, std::string const& kind)
{
    if (kind == "INLE")
    {
        std::cout << "Column 1: " << values[0] << "\n";
    }
}

实际的处理功能不必干预修剪、行结束,甚至解析详细信息列:)

完整代码供参考

#include <iostream>
#include <fstream>
#include <boost/spirit/include/qi.hpp>
#include <boost/spirit/include/phoenix.hpp>

namespace qi  = boost::spirit::qi;
namespace phx = boost::phoenix;

static const std::string B_condition = "INLE";

void process_line(std::vector<int> const& values, std::string const& kind)
{
    if (kind == "INLE")
    {
        std::cout << "Column 1: " << values[0] << "\n";
    }
}

int main()
{
    std::ifstream myfile("ramp.bnd");
    myfile.unsetf(std::ios::skipws);

    boost::spirit::istream_iterator f(myfile), l;

    using namespace qi;
    bool ok = phrase_parse(f, l,
            (repeat(7) [ int_ ] >> as_string[lexeme[+(char_ - eol)]])
                [ phx::bind(process_line, _1, _2) ]
            % eol, // supports CRLF and LF
            blank);

    if (!ok)
        std::cerr << "Parse errors\n";
    if (f!=l)
        std::cerr << "Remaing input: '" << std::string(f,l) << "'\n";
}
于 2014-03-19T10:22:11.090 回答
2

你根本不需要像 boost 这样的库。在某些代码行中也可以使用 pur 标准 C++ 的解决方案:

const std::string B_condition = "INLE";
std::ifstream myfile ("ramp.bnd");

for( char c; myfile >> c; )
{
    if( std::isdigit(c, myfile.getloc() ) ) // needs #include <locale>
    {
        int i;
        if( myfile.putback(c) >> i )
            std::cout << "read " << i << std::endl; // do something with 'i'
    }
    else
    {
        std::string token;
        if( myfile.putback(c) >> token )
        {
            if( token == B_condition )
                std::cout << B_condition << " found\n";
            else
                ; // no number, no B_condition -> what ever You want to do
        }
    }
}
于 2014-03-19T11:53:52.403 回答