문제

I am trying to create a C++ code that using boost libraries reads an input file like the following,

    1             12       13        0        0      1      0      INLE
    .
    .
    .

In this case, I must do an action if the condition specified on the last column of the right is INLE. I have the following code,

#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;
}

while compiling there are no issues, but when I run, it doesnt shows anything.

By the other side, if I modify my boolean condition to false, it will print "Its true!" the number of lines that my input file has.

What am I doing wrong? Thanks!!

도움이 되었습니까?

해결책

I can only assume that:

  • your file contains whitespace at the end (use trim)
  • your file has windows line ends (CRLF) but you're reading it as UNIX text files, meaning that the lines will include a trailing `\r' (CR) (often shown as ^M in various text editors/pagers).

So, either

  • fix the line endings
  • trim whitespace from the lines before comparing
  • or both

Best: use a 'proper' parser to do the work.

Update adding a quick & dirty approach using Boost Spirit: see it 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";
}

As you can see, it validates the whole line, assuming (for now) that the columns are 7 integer values and a string (e.g. "INLE"). Now, the actual work is much simpler and can be implemented in a separate function:

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

The actual processing function doesn't have to meddle with trimming, line ends, even parsing the details columns :)

Full Code for reference

#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";
}

다른 팁

You don't need a library like boost at all. A solution with pur standard C++ is possible in some lines of code too:

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
        }
    }
}
라이센스 : CC-BY-SA ~와 함께 속성
제휴하지 않습니다 StackOverflow
scroll top