943,832 Members | Top Members by Rank

Ad:
  • C++ Discussion Thread
  • Unsolved
  • Views: 1640
  • C++ RSS
Aug 10th, 2008
0

Problem in reading the first number from a line in file

Expand Post »
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.
Last edited by guest7; Aug 10th, 2008 at 6:59 pm.
Similar Threads
Reputation Points: 10
Solved Threads: 0
Junior Poster
guest7 is offline Offline
109 posts
since Mar 2008
Aug 10th, 2008
0

Re: Problem in reading the first number from a line in file

Quote ...
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?

Quote ...
3 2
-6 1
Your output shows this:

Quote ...
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.
Featured Poster
Reputation Points: 2614
Solved Threads: 687
Posting Expert
VernonDozier is offline Offline
5,375 posts
since Jan 2008
Aug 10th, 2008
0

Re: Problem in reading the first number from a line in file

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
Reputation Points: 10
Solved Threads: 0
Junior Poster
guest7 is offline Offline
109 posts
since Mar 2008
Aug 10th, 2008
0

Re: Problem in reading the first number from a line in file

>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:
C++ Syntax (Toggle Plain Text)
  1. #include <iostream>
  2. #include <sstream>
  3. #include <stdexcept>
  4. #include <string>
  5. #include <vector>
  6.  
  7. int main()
  8. {
  9. using namespace std;
  10.  
  11. try {
  12. // Simulate a data file
  13. istringstream is("3 0\n-6 0\n4 0\n-8 0");
  14.  
  15. vector<int> data;
  16. string line;
  17.  
  18. // Save the first number on each line
  19. while (getline(is, line)) {
  20. istringstream numbers(line);
  21. int number;
  22.  
  23. // Try to extract the number
  24. if (!(numbers >> number))
  25. throw runtime_error("Expected a valid integer starting at '" + line + "'");
  26.  
  27. data.push_back(number);
  28. }
  29.  
  30. // Process the extracted data
  31. for (vector<int>::size_type i = 0; i < data.size(); i += 2) {
  32. cout << data.at(i);
  33.  
  34. // Assume an odd size isn't a fatal error
  35. // and only displays one processed number
  36. if (i + 1 < data.size())
  37. cout << ' ' << data.at(i + 1);
  38.  
  39. cout << " 0\n";
  40. }
  41. } catch (const exception& ex) {
  42. cerr << "Error processing data file: " + string(ex.what()) << '\n';
  43. }
  44. }
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:
C++ Syntax (Toggle Plain Text)
  1. #include <iostream>
  2. #include <sstream>
  3. #include <string>
  4.  
  5. int main()
  6. {
  7. using namespace std;
  8.  
  9. istringstream is1("line 1\nline 2\nline 3\n");
  10. istringstream is2("line 1\nline 2\nline 3");
  11. string line1;
  12. string line2;
  13.  
  14. cout << "Reading is1\n";
  15. while (!is1.eof()) {
  16. getline(is1, line1);
  17. cout << line1 << '\n';
  18. }
  19. cout << "Done reading is1\n";
  20.  
  21. cout << "Reading is2\n";
  22. while (!is2.eof()) {
  23. getline(is2, line2);
  24. cout << line2 << '\n';
  25. }
  26. cout << "Done reading is2\n";
  27. }
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:
C++ Syntax (Toggle Plain Text)
  1. #include <iostream>
  2. #include <sstream>
  3. #include <string>
  4.  
  5. int main()
  6. {
  7. using namespace std;
  8.  
  9. istringstream is1("line 1\nline 2\nline 3\n");
  10. istringstream is2("line 1\nline 2\nline 3");
  11. string line1;
  12. string line2;
  13.  
  14. cout << "Reading is1\n";
  15. while (getline(is1, line1))
  16. cout << line1 << '\n';
  17. cout << "Done reading is1\n";
  18.  
  19. cout << "Reading is2\n";
  20. while (getline(is2, line2))
  21. cout << line2 << '\n';
  22. cout << "Done reading is2\n";
  23. }
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.
Last edited by Radical Edward; Aug 10th, 2008 at 8:34 pm.
Reputation Points: 361
Solved Threads: 97
Posting Pro
Radical Edward is offline Offline
526 posts
since May 2008

This thread is more than three months old

No one has posted to this discussion for at least three months. Please let old threads die and do not reply to them unless you feel you have something new and valuable to contribute that absolutely must be added to make the discussion complete. Otherwise, please start a new thread in this forum instead.
Message:
Previous Thread in C++ Forum Timeline: Quick Question: Pointer to a 2D array
Next Thread in C++ Forum Timeline: Sending Text to a Printer





About Us | Contact Us | Advertise | Acceptable Use Policy
Forum Index | Build Custom RSS Feed


Follow us on Twitter


© 2011 DaniWeb® LLC