0

I have a file that contains lines as below:

25 1 0 0 0 0
27 1 0 0 0 0
20 0 0 0 0 0
32 1 0 0 0 0
23 1 0 0 0 0
16 0 0 0 0 0
28 1 0 0 0 0

First, I store each line with value=1 in the second column as element of a string array. I call the stored elements back via a for-loop, and parse the contents of the element into integers. How does one do that in c++?

#include <vector> 
#include <iostream>
#include <string>
using namespace std;
   .....
   .....
   .....
   .....
char line[100];
vector<string> vec_line;
string Vline;
int trimVal, compa, nil0, nil1, nil2, nil3;
  ......
  ......
  ......
//then store lines as strings in vec_line as required by the premise above
// after that, retrieve the contents of the elements of the vector
for (int iline=0; iline<vec_line.size(); iline++) {
   cout<<"iline  "<<iline<<"  vec_line[iline]";
   //then I want to parse contents of each string element and store them integer formats
   sscanf(vec_line[iline], "%d %d %d %d %d %d", &trimVal, &compa, &nil0, &nil1, &nil2, &nil3); //how would one do this simple parsing task in c and c++?
}

Thank you.

0

4 Answers 4

2

sscanf is a C function, since you are already using C++ streams to output (and presumably read from the file?) you are better off using a stringstream to convert between strings and data types.

For example:

#include <iostream>
#include <sstream>
#include <string>
using namespace std;

int main(int argc, char* argv[])
{
   stringstream sstr;
   string mystr = "123";
   int i;

   sstr << mystr;

   sstr >> i;

   cout << i << endl;

   return 0;
}

will output 123 to stdout. Of course you can also read from an ifstream using the >> operator directly into an int or double if you wish.

Hope this helps.

Sign up to request clarification or add additional context in comments.

Comments

1

This is incorrect:

sscanf(vec_line[iline], "%d %d ...

as the first argument to sscanf() is a const char* and not a std::string. Change to:

sscanf(vec_line[iline].c_str(), "%d %d ...

Recommend checking the return value of sscanf() to ensure all expected assignments were made:

if (6 == sscanf(vec_line[iline].c_str(), "%d %d ...

Comments

1

Unless I needed to store each row as a string, I'd do something more like this:

struct row { 
    static const int columns = 6;
    std::vector<int> column_data;

    // should we keep or ignore a row? Ignore if column 1 != 1.
    struct filter {
        bool operator()(row const &r) { return r.column_data[1] != 1; }
    };

    // read in a row.
    friend std::istream &operator>>(std::istream &is, row &r) {
        r.column_data.resize(row::columns);
        for (int i=0; i<row::columns; i++)
            is >> r.columns[i];
        return is;
    }

    // write a row out to a file.
    friend std::ostream &operator<<(std::ostream &os, row const &r) { 
        std::copy(r.column_data.begin(), r.column_data.end(),
                  std::ostream_iterator<int>(os, " "));
        return os;
};

Then reading and displaying the data would look something like this:

std::vector<row> data;

std::remove_copy_if(std::istream_iterator<row>(input_file),
                    std::istream_iterator<row>(),
                    std::back_inserter(data),
                    row::filter());

std::copy(data.begin(), data.end(), 
          std::ostream_iterator<row>(output_file, "\n"));

Or, if you just want to copy the correct rows from some input file to some output file, you can use the correct iterators to do that directly:

std::remove_copy_if(std::istream_iterator<row>(input_file),
                    std::istream_iterator<row>(),
                    std::ostream_iterator<row>(output_file),
                    row::filter());

Comments

0

There is always lex and yacc (or Flex and Bison)

Comments

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service and acknowledge you have read our privacy policy.

Start asking to get answers

Find the answer to your question by asking.

Ask question

Explore related questions

See similar questions with these tags.