473,789 Members | 2,728 Online
Bytes | Software Development & Data Engineering Community
+ Post

Home Posts Topics Members FAQ

ifstream::get() surprise

Hi!

Consider the following program

#include <fstream>
#include <iostream>
using namespace std;

int main() {
ifstream in("test.txt") ;
char buf[40];
in.get(buf,40);
cerr << "Read: *" << buf << "*, trouble: " << !in << endl;
}

and a file, test.txt, starting with an empty line, ie. a lone EOL
character on the first line.

I was quite surprised to find out, that under these circumstances
the aforementioned program produced
"Read **, trouble: 1".

Why does 'in' go to a fail state? I thought 'get' reads up to
the terminator, stores all characters into 'buf' and leaves the
terminator inside the stream. That would mean 'buf' containing
just a \0 char (no chars read), the EOL still in the stream, but
why a failed state? There are more lines in the file, so we're
not eof(), and my understanding of this situation is a
"successful read of zero characters" rather than "read error".

How then can I distinguish a successfull reading of an empty
line from an I/O error during reading a line? Of course I have
no a priori knowledge if these empty lines exist in my parsed
file or not.

TIA,
- J.
Jul 22 '05 #1
5 6035
Jacek Dziedzic wrote:
Consider the following program

#include <fstream>
#include <iostream>
using namespace std;

int main() {
ifstream in("test.txt") ;
char buf[40];
in.get(buf,40);
cerr << "Read: *" << buf << "*, trouble: " << !in << endl;
}

and a file, test.txt, starting with an empty line, ie. a lone EOL
character on the first line.

I was quite surprised to find out, that under these circumstances
the aforementioned program produced
"Read **, trouble: 1".

Why does 'in' go to a fail state?
Yes. It does that if it reads no characters.
I thought 'get' reads up to
the terminator, stores all characters into 'buf' and leaves the
terminator inside the stream. That would mean 'buf' containing
just a \0 char (no chars read), the EOL still in the stream, but
why a failed state?
There is no other way to tell you that no characters have been read.
There are more lines in the file, so we're
not eof(), and my understanding of this situation is a
"successful read of zero characters" rather than "read error".
Right.
How then can I distinguish a successfull reading of an empty
line from an I/O error during reading a line? Of course I have
no a priori knowledge if these empty lines exist in my parsed
file or not.


If your stream is in good standing before the operation and has its
'failbit' set after the operation, no characters have been stored. If
the file (stream) has somehow lost integrity, 'badbit' is set. That's
how you distinguish.

Victor
Jul 22 '05 #2
Victor Bazarov:
the EOL still in the stream, but
why a failed state?
There is no other way to tell you that no characters have been read.


Why not just store '\0' into the buffer and leave the stream ok?
If your stream is in good standing before the operation and has its
'failbit' set after the operation, no characters have been stored. If
the file (stream) has somehow lost integrity, 'badbit' is set. That's
how you distinguish.


Oh I see. So if someone eg. slips the floppy containg the file
out from the drive, then in.bad() will be true? Yes, that sounds
reasonable!

Thanks for the quick reply,
- J.
Jul 22 '05 #3

"Jacek Dziedzic" <ja************ *@janowo.net> wrote in message
news:cg******** **@korweta.task .gda.pl...
Hi!

Consider the following program

#include <fstream>
#include <iostream>
using namespace std;

int main() {
ifstream in("test.txt") ;
You need to check here whether the file was opened
successfully or not, and not proceed if it wasn't.

Also note that 'get()' is an unformatted input function.
Using it with a text-mode stream (the default) could have
unexpected results. If you want to read unformatted,
open with 'std::ios::bina ry'. But I think you're probably
just using the wrong function. See below.
char buf[40];
in.get(buf,40);
cerr << "Read: *" << buf << "*, trouble: " << !in << endl;
}

and a file, test.txt, starting with an empty line, ie. a lone EOL
character on the first line.

I was quite surprised to find out, that under these circumstances
the aforementioned program produced
"Read **, trouble: 1".
It's not surprising when you read the specification of 'std::istream:: get()'

Why does 'in' go to a fail state?
By design.
I thought 'get' reads up to
the terminator, stores all characters into 'buf' and leaves the
terminator inside the stream. That would mean 'buf' containing
just a \0 char (no chars read), the EOL still in the stream, but
why a failed state? There are more lines in the file, so we're
not eof(), and my understanding of this situation is a
"successful read of zero characters" rather than "read error".
No such thing as 'successful read of zero characters.' If characters
were requested and none were extracted, that's a 'failure'.
============== begin quote =============== ============
ISO/IEC 14882:1998(E)

27.6.1.3 Unformatted input functions

basic_istream<c harT,traits>& get(char_type* s, streamsize n,
char_type delim );

7 Effects: Extracts characters and stores them into successive locations
of an array whose first element is designated by s. (286) Characters
are extracted and stored until any of the following occurs:

-- n * 1 characters are stored;

-- end*of*file occurs on the input sequence (in which case the function
calls setstate(eofbit ));

-- c == delim for the next available input character c(in which case c
is not extracted).

8 If the function stores no characters, it calls setstate(failbi t) (which
may throw ios_base::failu re (27.4.4.3)). In any case, it then stores a
null character into the next successive location of the array.

9 Returns: *this.

basic_istream<c harT,traits>& get(char_type* s, streamsize n)

10 Effects: Calls get(s,n,widen(' \n'))

11 Returns: Value returned by the call.
============== end quote =============== ============

How then can I distinguish a successfull reading of an empty
line from an I/O error during reading a line? Of course I have
no a priori knowledge if these empty lines exist in my parsed
file or not.


I recommend you eschew the array and use std::strings and
std::getline to parse your file.

std::string s;
while(std::getl ine(in, s))
cout << s << '\n';

if(!in.eof())
cerr << "Error reading\n";

Now you don't have to worry if your array is big enough,
and you can get at individual characters the same way
as from an array, e.g.

char c = s[0];

HTH,
-Mike
Jul 22 '05 #4
On Thu, 26 Aug 2004 18:44:50 +0200, Jacek Dziedzic
<ja************ *@janowo.net> wrote:
Victor Bazarov:
the EOL still in the stream, but
why a failed state?
There is no other way to tell you that no characters have been read.


Why not just store '\0' into the buffer and leave the stream ok?


Well, you asked it to get characters, and it failed to get any, I
suppose. It's arguable whether this behaviour is the most useful and
least surprising or not, of course; I think I agree with you that
going into a fail state isn't the intuitive behaviour.

'\0' is stored into the buffer though.
If your stream is in good standing before the operation and has its
'failbit' set after the operation, no characters have been stored. If
the file (stream) has somehow lost integrity, 'badbit' is set. That's
how you distinguish.


Oh I see. So if someone eg. slips the floppy containg the file
out from the drive, then in.bad() will be true? Yes, that sounds
reasonable!


That's the intent of badbit I think. But floppy disks are
implementation defined - it's possible you just get eof on some
implementations .

Tom
Jul 22 '05 #5
Mike Wahler wrote:

int main() {
ifstream in("test.txt") ;
You need to check here whether the file was opened
successfully or not, and not proceed if it wasn't.


Obviously, but not in the famous "shortest possible program
displaying the behaviour", right?
Also note that 'get()' is an unformatted input function.
Using it with a text-mode stream (the default) could have
unexpected results.
What unexpected results, could you clarify?
If you want to read unformatted,
open with 'std::ios::bina ry'.
Nope, I want to read formatted. Binary mode is out because
I don't want to mind CR/LF differences. Plus I'm reading
trivial configuration text files.
But I think you're probably
just using the wrong function. See below.

So what's wrong with get()?

It's not surprising when you read the specification of 'std::istream:: get()'

Yes, but I don't have these.
No such thing as 'successful read of zero characters.' If characters
were requested and none were extracted, that's a 'failure'.
I see that now, but it's not obvious a'priori. Some read functions
don't complain about reading zero bytes or seek functions don't
complain about seeking zero bytes. I mean it's obvious for someone
who KNOWS already, but for me it was counter-intuitive.
============== begin quote =============== ============
ISO/IEC 14882:1998(E)

27.6.1.3 Unformatted input functions

basic_istream<c harT,traits>& get(char_type* s, streamsize n,
char_type delim );

7 Effects: Extracts characters and stores them into successive locations
of an array whose first element is designated by s. (286) Characters
are extracted and stored until any of the following occurs:

-- n * 1 characters are stored;

-- end*of*file occurs on the input sequence (in which case the function
calls setstate(eofbit ));

-- c == delim for the next available input character c(in which case c
is not extracted).

8 If the function stores no characters, it calls setstate(failbi t) (which
may throw ios_base::failu re (27.4.4.3)). In any case, it then storesa
null character into the next successive location of the array.

9 Returns: *this.

basic_istream<c harT,traits>& get(char_type* s, streamsize n)

10 Effects: Calls get(s,n,widen(' \n'))

11 Returns: Value returned by the call.
============== end quote =============== ============

Yes, that was helpful.
I recommend you eschew the array and use std::strings and
std::getline to parse your file.

std::string s;
while(std::getl ine(in, s))
cout << s << '\n';

if(!in.eof())
cerr << "Error reading\n";

Now you don't have to worry if your array is big enough,
and you can get at individual characters the same way
as from an array, e.g.

char c = s[0];
You overdid that one a bit, Mike :). I am in the middle of
coding a 'better_ifstrea m' class which inherits from ifstream
and supplies facilities like get_string(), get_word(),
parse_phrase(), etc.
std::strings are useless in my problem, since I need
byte-copiable POD types to be transferred across different
processors in a parallel system. But you couldn't have known that,
since the rule is to post the shortest code suffering from the
questioned behaviour, not the *neatest* shortest code, right? :)
HTH,
-Mike


yes, the quote did,
- J.
Jul 22 '05 #6

This thread has been closed and replies have been disabled. Please start a new discussion.

Similar topics

2
13780
by: Dave Johnston | last post by:
Hi, I'm currently trying to create a wrapper that uses C functions but behaves like ifstream (from fstream.h) - this is because the platform I'm using (WinCE) doesn't support streams and this is the easiest way to take a huge project across onto it. Basically, I've hit a problem. I have no idea how the ifstream class handles directories. In the code I have (which I didn't write), there are several places whereby an ifstream stream is...
7
19627
by: cylin | last post by:
Dear all, I can use c language function fscanf() to get a char. string. Ex: FILE *file=fopen("test.txt","r"); char data; while (!feof(file)) { fscanf(file,"%s",data); ... }
6
3661
by: Herv? LEBAIL | last post by:
Hi everybody, I'm writing a program which use the <string>, <vector> and <ifstream> classes. Given an array of string, i.e vector<string> file_names, example : file_names = "file1.txt" file_names = "file2.txt" etc ...
6
3396
by: Ram Laxman | last post by:
Iam new bie to C++ programming.. I want to write a program which will read the Comma separated values(CSV) file column wise. For example: In a.txt: "TicketNumber","Phone","CarNumber" 10,20,30
6
4286
by: csvka | last post by:
Hello, I wonder if I could pick your brains. I'm beginning to learn about C++. I have opened a file in my program and I want to read lines from it. I would like this to be done in a separate function called readline() because I would also like to do some processing on the line each time (ignoring comments and so on). I have:
1
2641
by: Alex Vinokur | last post by:
I have several questins concerning a program below. ------ foo.cpp : BEGIN ------ #include <cassert> #include <cstdlib> #include <iostream> #include <fstream> using namespace std; int main()
12
2303
by: Matthias Kirchhart | last post by:
-----BEGIN PGP SIGNED MESSAGE----- Hash: RIPEMD160 Hello guys, I am currently runnging Kubuntu 5.10 on an AMD Athlon XP +1600 machine. I am trying to implement a file class that allows bitwise access to a file. I have created a byte class which looks like this:
3
2442
by: farseer | last post by:
Hi, Hi, i am reading the content of a binary file, enoding as base64 and writing to an output file. After noticing that my output file seems to be truncated, i created the following simple test code in an attempt to isolate the issue. The actually binary is 25kb, however the length of the string appears to be only around 5kb. How can this be possible? ifstream myfile( argv ); string fc;
11
8148
by: adramolek | last post by:
So... I'm trying to get used to using C++ ifstream (or ofstream) instead of stdio (although I'm having second thoughts). Anyways, I want to be able to display a meaningful error message if ifstream fails to open a file, but nothing I read about ifstream says anything about a reliable place to get an error message. Using stdio I can simply do: FILE *f = fopen(filename, "rb"); if (!f) perror(filename);
0
9511
by: Hystou | last post by:
Most computers default to English, but sometimes we require a different language, especially when relocating. Forgot to request a specific language before your computer shipped? No problem! You can effortlessly switch the default language on Windows 10 without reinstalling. I'll walk you through it. First, let's disable language synchronization. With a Microsoft account, language settings sync across devices. To prevent any complications,...
0
10200
jinu1996
by: jinu1996 | last post by:
In today's digital age, having a compelling online presence is paramount for businesses aiming to thrive in a competitive landscape. At the heart of this digital strategy lies an intricately woven tapestry of website design and digital marketing. It's not merely about having a website; it's about crafting an immersive digital experience that captivates audiences and drives business growth. The Art of Business Website Design Your website is...
0
9021
agi2029
by: agi2029 | last post by:
Let's talk about the concept of autonomous AI software engineers and no-code agents. These AIs are designed to manage the entire lifecycle of a software development project—planning, coding, testing, and deployment—without human intervention. Imagine an AI that can take a project description, break it down, write the code, debug it, and then launch it, all on its own.... Now, this would greatly impact the work of software developers. The idea...
1
7529
isladogs
by: isladogs | last post by:
The next Access Europe User Group meeting will be on Wednesday 1 May 2024 starting at 18:00 UK time (6PM UTC+1) and finishing by 19:30 (7.30PM). In this session, we are pleased to welcome a new presenter, Adolph Dupré who will be discussing some powerful techniques for using class modules. He will explain when you may want to use classes instead of User Defined Types (UDT). For example, to manage the data in unbound forms. Adolph will...
0
6769
by: conductexam | last post by:
I have .net C# application in which I am extracting data from word file and save it in database particularly. To store word all data as it is I am converting the whole word file firstly in HTML and then checking html paragraph one by one. At the time of converting from word file to html my equations which are in the word document file was convert into image. Globals.ThisAddIn.Application.ActiveDocument.Select();...
0
5551
by: adsilva | last post by:
A Windows Forms form does not have the event Unload, like VB6. What one acts like?
1
4093
by: 6302768590 | last post by:
Hai team i want code for transfer the data from one system to another through IP address by using C# our system has to for every 5mins then we have to update the data what the data is updated we have to send another system
2
3703
muto222
by: muto222 | last post by:
How can i add a mobile payment intergratation into php mysql website.
3
2909
bsmnconsultancy
by: bsmnconsultancy | last post by:
In today's digital era, a well-designed website is crucial for businesses looking to succeed. Whether you're a small business owner or a large corporation in Toronto, having a strong online presence can significantly impact your brand's success. BSMN Consultancy, a leader in Website Development in Toronto offers valuable insights into creating effective websites that not only look great but also perform exceptionally well. In this comprehensive...

By using Bytes.com and it's services, you agree to our Privacy Policy and Terms of Use.

To disable or enable advertisements and analytics tracking please visit the manage ads & tracking page.