Hi,

I am trying to read the file (f1.txt) which contains :

3 0
-6 0
4 0
-8 0
...

I wish to read the first number from consecutive 2 lines and process them.

Following is my code:

std::vector<int> row;
std::vector<std::vector<int> > two_node;

int main()
{    
    string line1, line2;
    int writetofile();

    ifstream myfile ("f1.txt");
    if(myfile.is_open())
    {
        while(! myfile.eof() )
        {
            getline (myfile, line1);
            getline (myfile, line2);

            row.push_back(line[0]);
            row.push_back(line[1]);
            two_node.push_back(row);
            writetofile();
            row.clear();
        }
        myfile.close();
    }

    else cout << "Unable to open the file \n";
    return 0;
}

int writetofile()
{
        ofstream file1;
        file1.open("f2.imp",ios::app);
        file1 << row[0] << " " << row[1] << " " << 0 << "\n";

        file1.close();
    return 0;
}

My code is not working. I need the output in f2.imp as :

3 -6 0
4 -8 0
........

Thanks.

Edited 3 Years Ago by mike_2000_17: Fixed formatting

3 0
-6 0

What do the zeroes represent? Data? A line termination flag? Will they always be zero or always the same or could they be like this?

3 2
-6 1

Your output shows this:

3 -6 0

so you are throwing out one of the four numbers. Which one? The lower right one?

Anyway, you need to figure out exactly what your data format is and what you want to keep and what you want to throw away. If it is two lines of two integers, you may want to just use the >> operator rather than the getline function. If you use getline, you may need to somehow extract the two integers from the string and throw one of them out. >> doesn't present that problem, nor would there be any potential conversion problems between char and int. I'm not sure you need to use strings or chars at all for this program, but I don't know what it's supposed to do besides what you've posted. You may just want to keep it as all integers.

Hi,

In every line of the file there will be one integer and one zero always. i need to read the first integer and process that integer. I need to read the first integer of consecutive two lines and store them in a 2 Dimensional vector. Could you please provide me with a pseudo code of how to go about it.

Thanks

>What do the zeroes represent? Data? A line termination flag?
It doesn't matter. The requirement is only to process the first number on each line. Since none of the other numbers on the line aren't being processed, it's a safe assumption that they won't show up in the output.

>My code is not working.
You've got the right idea, it's just a matter of ironing out the details of your logic. :) First, this is how Edward would have done it:

#include <iostream>
#include <sstream>
#include <stdexcept>
#include <string>
#include <vector>

int main()
{
  using namespace std;

  try {
    // Simulate a data file
    istringstream is("3 0\n-6 0\n4 0\n-8 0");

    vector<int> data;
    string line;

    // Save the first number on each line
    while (getline(is, line)) {
      istringstream numbers(line);
      int number;

      // Try to extract the number
      if (!(numbers >> number))
        throw runtime_error("Expected a valid integer starting at '" + line + "'");

      data.push_back(number);
    }

    // Process the extracted data
    for (vector<int>::size_type i = 0; i < data.size(); i += 2) {
      cout << data.at(i);
      
      // Assume an odd size isn't a fatal error
      // and only displays one processed number
      if (i + 1 < data.size())
        cout << ' ' << data.at(i + 1);

      cout << " 0\n";
    }
  } catch (const exception& ex) {
    cerr << "Error processing data file: " + string(ex.what()) << '\n';
  }
}

If you don't mind some constructive criticism, there are a few issues with your code that need to be addressed.

// Potential error!
while(! myfile.eof() )

This isn't a good way to control an input loop, especially when it comes to files. The contents of the file can affect the number of lines you try to read, and that number can be wrong. The canonical example of this is when reading lines and a file ends with a '\n' character. Here's a test program:

#include <iostream>
#include <sstream>
#include <string>

int main()
{
  using namespace std;

  istringstream is1("line 1\nline 2\nline 3\n");
  istringstream is2("line 1\nline 2\nline 3");
  string line1;
  string line2;

  cout << "Reading is1\n";
  while (!is1.eof()) {
    getline(is1, line1);
    cout << line1 << '\n';
  }
  cout << "Done reading is1\n";

  cout << "Reading is2\n";
  while (!is2.eof()) {
    getline(is2, line2);
    cout << line2 << '\n';
  }
  cout << "Done reading is2\n";
}

Notice how the first loop has an extra line at the end. That's the off-by-one error where the loop runs once more than it should. The only difference between is1 and is2 is a '\n' at the end. In is1, the last character is '\n' and getline terminates by successfully finding a delimiter; is1.eofbit is not set. In is2, the last character isn't '\n' and getline terminates by reaching end-of-file; is2.eofbit is set.

The underlying problem is that the eof() member function doesn't return true unless there's been an extraction attempt that has failed in a way that causes eofbit for the stream object to be set.

It's more accurate if you use the extraction operation itself. They typically return something you can test for success or failure. For example, getline returns the stream object, and in a boolean condition, the stream object can be immediately tested for failure conditions:

#include <iostream>
#include <sstream>
#include <string>

int main()
{
  using namespace std;

  istringstream is1("line 1\nline 2\nline 3\n");
  istringstream is2("line 1\nline 2\nline 3");
  string line1;
  string line2;

  cout << "Reading is1\n";
  while (getline(is1, line1))
    cout << line1 << '\n';
  cout << "Done reading is1\n";

  cout << "Reading is2\n";
  while (getline(is2, line2))
    cout << line2 << '\n';
  cout << "Done reading is2\n";
}

Now the correct number of lines are read regardless of what the last character is.

// Potential error!
getline (myfile, line1);
getline (myfile, line2);

// Won't do what you expect!
row.push_back(line1[0]); // Dies if line1 is empty
row.push_back(line2[1]); // Dies if line2 is empty

Ed highly recommends checking every single extraction attempt for failure. What happens if there isn't a second line? What happens if there aren't any lines but the eofbit isn't set? Right now you're just ignoring that situation and assuming that both lines always exist.

Another problem here is that line1[0] and line2[0] are characters, not the integers that you want. By pushing them onto the vector you're causing an implicit conversion from the numeric value of the character to integers. For Unicode or ASCII, that means the first two lines will give you 51 and 45 for line1[0] and line2[0], respectively. That's because the numeric value of '3' is 51 and the numeric value of '-' is 45.

What you need to do is get the integer representation of the strings "3" and "-6". Notice that -6 consists of two characters, by the way. A good standard way is to break out the stringstreams as in Edward's examples above.

Comments
Talk about yourself in third person as much as you want! =)
Please refrain from talking about yourself in the third person. Thank you for observing the rules.
This article has been dead for over six months. Start a new discussion instead.