读取输入文件时“Ends_with”功能不起作用

时间:2014-03-19 09:02:26

标签: c++ boost ends-with

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

    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;
}
编译时没有问题,但是当我运行时,它没有显示任何内容。

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

我做错了什么? 谢谢!

2 个答案:

答案 0 :(得分:2)

我只能假设:

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

所以,

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

最好:使用正确的&#39;解析器来完成工作。

更新添加快速&amp;使用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";
}

答案 1 :(得分:2)

你根本不需要像升级这样的图书馆。在某些代码行中也可以使用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
        }
    }
}