Sign in to follow this  

Help with ifstream::getline

This topic is 3739 days old which is more than the 365 day threshold we allow for new replies. Please post a new topic.

If you intended to correct an error in the post then please contact us.

Recommended Posts

Hi Everybody :) I have a question about ifstream::getline Lets say I have the following text file: ------------- 1234567 < this is the first line of the txt file hello world < this is the last line of the txt file ------------- my code is
  std::ifstream ft;
  ft.open(...);

  char buff[25];
  while(!ft.eof())
  {
   ft.getline(buff,3);
   cout<<buff<<endl;

  }

At the first iteration of the loop, when getline(buff,3) reads a line which contains more characters than the buffer I have specified, 3, than the next iteration getline(buff,3) does not read anything, i get an empty buffer even though there are more lines, and this loop continues forever. Do I need to clean the buffer or something like that? Thanks

Share this post


Link to post
Share on other sites
Quote:
from "The C plus plus Standard Library"
If they read lines with more than count-1 characters, they set failbit.


I believe it's std::ios_base::failbit. I would guess it keeps reading the same line over and over?

p.s. why can't I use the plus symbol?!?

Share this post


Link to post
Share on other sites
If the line is larger than the buffer, the stream will enter a "failed" state when you try to read it. You need to reset this failed state using ft.clear() on your stream. You can detect the failed state by calling ft.fail().

Share this post


Link to post
Share on other sites
Don't use while(!file.eof()), the end of file bit is set only after a failed read (so your loop will execute one extra time).

Instead use the read operation itself in the condition:

while( std::getline(file,input) ) {
}




Prefer the use of std::string for strings.

Also, since getline uses the last as the delimiter, but you probably meant to use '3'. If not please specify what you want to do.

Share this post


Link to post
Share on other sites
Quote:
Original post by rip-off
Also, since getline uses the last as the delimiter, but you probably meant to use '3'. If not please specify what you want to do.


istream::getline(char*, streamsize) uses the last as the number of characters to be read.

Share this post


Link to post
Share on other sites
If all you want to do is to read a file and put the contents somewhere, you can use rdbuf(), like:


std::ifstream in("file.txt"); // Initializes the stream
std::cout << in.rdbuf(); // Sends stream read buffer to cout
in.seekg(0); // Resets to beginning of buffer.
in.clear(); // Clears failbit and eofbit.


That should print the entire contents of "file.txt" verbatim. Drawback is that you
can't check the state of the stream. Always clear() and reset seekg(0) if you want to re-read the file.

Another alternative is to get the info character by character, like:


std::ifstream in("file.txt"); // Initializes the stream
char c;

while(in.get(c))
{
cout.put(c);
}


The above lets you check stream state. Also, unless you really have to, using a character buffer with std::getline(,) instead of a std::string is asking for problems, as mentioned by rip-off.

As ToohrVyk (and rip-off, indirectly) mentioned, use the fail state for your conditional. Something like:


std::ifstream in("file.txt");
std::string input;

while (!in.fail()) // similarly, rip-off suggested 'while( std::getline(in,input) ){}'
{
do something...
}


If you have a lot of character or string manipulation, my personal preference is to use file operations as little as possible, and read the contents into a string buffer, and then use string methods for everything else. So you could do something like:


#include <fstream>
#include <sstream>
#include <string>

std::string fileToString(const std::string& filename)
{
std::ostringstream out;
std::ifstream in(filename.c_str());
out << in.rdbuf();
return out.str();
}

std::string strbuf = fileToString("file.txt");


Then you can use the rather rich facilities of std::string to manipulate strbuf. I use the name 'strbuf' loosely here, as it is just a string. This is not to be confused with the standard library 'stringbuf' and 'wstringbuf' that are specializations of the 'basic_stringbuf<>' template class.

--random

[Edited by - random_thinker on September 18, 2007 3:37:15 AM]

Share this post


Link to post
Share on other sites
Quote:
Original post by random_thinker

#include <fstream>
#include <sstream>
#include <string>

std::string fileToString(const std::string& filename)
{
std::ostringstream out;
std::ifstream in(filename.c_str());
out << in.rdbuf();
return out.str();
}

std::string strbuf = fileToString("file.txt");


Then you can use the rather rich facilities of std::string to manipulate strbuf. I use the name 'strbuf' loosely here, as it is just a string. This is not to be confused with the standard library 'stringbuf' and 'wstringbuf' that are specializations of the 'basic_stringbuf<>' template class.

Better yet,

#include <fstream>
#include <iterator>
#include <string>
// ...
string fileimage = string(istreambuf_iterator<char>(ifstream(filename.c_str())),
istreambuf_iterator<char>());

Of course, this doesn't give you the opportunity to check for I/O errors, but it;s as simple as you can get for reading a file into an in-memory image.

Share this post


Link to post
Share on other sites
Quote:
Original post by Bregma
Better yet,

#include <fstream>
#include <iterator>
#include <string>
// ...
string fileimage = string(istreambuf_iterator<char>(ifstream(filename.c_str())),
istreambuf_iterator<char>());



What beautifully elegant C++ code...fantastic!

--random

Share this post


Link to post
Share on other sites
Quote:
Original post by ToohrVyk
Quote:
Original post by rip-off
Also, since getline uses the last as the delimiter, but you probably meant to use '3'. If not please specify what you want to do.


istream::getline(char*, streamsize) uses the last as the number of characters to be read.


Apologies, I must have been thinking of std::getline when I wrote that. [embarrass]

Share this post


Link to post
Share on other sites

This topic is 3739 days old which is more than the 365 day threshold we allow for new replies. Please post a new topic.

If you intended to correct an error in the post then please contact us.

Create an account or sign in to comment

You need to be a member in order to leave a comment

Create an account

Sign up for a new account in our community. It's easy!

Register a new account

Sign in

Already have an account? Sign in here.

Sign In Now

Sign in to follow this