473,399 Members | 3,656 Online
Bytes | Software Development & Data Engineering Community
Post Job

Home Posts Topics Members FAQ

Join Bytes to post your question to a community of 473,399 software developers and data experts.

ifstream question

Hi

I'm using ifstream (which I hardly ever use) to read an ascii text
file (containing numbers delimited by newlines) in a loop using
something like:

ifstream infile("filename")
int value;

infile >value;
while(!infile.eof() {
infile >value;
:

}

The problem is if the file is missing a terminating newline the final
number is missed. How can I make sure its read anyway when the newline
is missing?

Thanks for any help

B2003
Jan 29 '08 #1
7 3185
Alf P. Steinbach wrote:
* Boltar:
>>
I'm using ifstream (which I hardly ever use) to read an ascii text
file (containing numbers delimited by newlines) in a loop using
something like:

ifstream infile("filename")
int value;

infile >value;
while(!infile.eof() {
infile >value;
:

}

The problem is if the file is missing a terminating newline the final
number is missed. How can I make sure its read anyway when the newline
is missing?

Don't test for eof, test for good stream state, i.e. that last read was
successful.
The answer is in the FAQ:
http://www.parashift.com/c++-faq-lit....html#faq-15.5
Like

ifstream infile( "filename" );

for( ;; )
{
int value;

infile >value;
if( !infile.good() )
{
break;
}
// Do something with value.
}
if( !infile.eof() ) { /* oops. */ }
When I see this I start to believe, that break in loops is evil, as James
said. The example in the FAQ is not as ugly as this code.

--
Thomas
Jan 29 '08 #2

"Alf P. Steinbach" <al***@start.nowrote in message
news:13*************@corp.supernews.com...
* Boltar:
I'm using ifstream (which I hardly ever use) to read an ascii text
file (containing numbers delimited by newlines) in a loop using
something like:

ifstream infile("filename")
int value;

infile >value;
while(!infile.eof() {
infile >value;
:

}

The problem is if the file is missing a terminating newline the final
number is missed. How can I make sure its read anyway when the newline
is missing?

Don't test for eof, test for good stream state, i.e. that last read was
successful.

Like

ifstream infile( "filename" );

for( ;; )
{
int value;

infile >value;
if( !infile.good() )
{
break;
}
// Do something with value.
}
if( !infile.eof() ) { /* oops. */ }

Disclaimer: I really hate iostreams, so possibly that last check isn't
completely 100% cover-all-cases or guaranteed to detect failure.
Pardon, please, but:
Oh. Good. _Grief_!!
Alf, I just spent manydays trying to do exactly this above (get a number
from a file), but with a piece of code another kind poster provided ('cause
I was stumped) and I modified.
To wit:

/*usual headers and using n.s.*/
ifstream ifstr("tvrfile.tvr");
string txt("");
char *tmp;
getline( ifstr, txt, ',');
const int pNum(strtod(txt.c_str(),&tmp));
cout << pNum << "\n"; //stick into pNum later

.........only to find in yours here --that I didn't even _need_ strod() !
(I thought his was elegant when I first saw it; I'm such a newbie....)

I compiled your code and ran it.
The numbers _are_ numbers, without strtod() !
I will study this thread intensely.
Is this sort of thing common?

_Thanks_! (many additional exclams)
What a great resource and learning aid you people are!
--
Peace
JB
jb@tetrahedraverse.com
Web: http://tetrahedraverse.com

Jan 30 '08 #3

"Alf P. Steinbach" <al***@start.nowrote in message
news:13*************@corp.supernews.com...
* Boltar:
I'm using ifstream (which I hardly ever use) to read an ascii text
file (containing numbers delimited by newlines) in a loop using
something like:

ifstream infile("filename")
int value;

infile >value;
while(!infile.eof() {
infile >value;
:

}

The problem is if the file is missing a terminating newline the final
number is missed. How can I make sure its read anyway when the newline
is missing?

Don't test for eof, test for good stream state, i.e. that last read was
successful.

Like

ifstream infile( "filename" );

for( ;; )
{
int value;

infile >value;
if( !infile.good() )
{
break;
}
// Do something with value.
}
if( !infile.eof() ) { /* oops. */ }

Disclaimer: I really hate iostreams, so possibly that last check isn't
completely 100% cover-all-cases or guaranteed to detect failure.
May I please ask further?
I ran this, modified as follows:
(usual up-top-stuff)

int main() {
ifstream infile("file.ext");
for(;;)
{
double value;
char toss; /*remove the commas (delimiter) & newlines*/
if(!infile.good()) {break;}
cout<<value<<" ";
}
infile>>value; cout<<value; /*kludge does get the final number....*/
if (!infile.eof()) {/*oops*/} /*my kludge for oops...(?)*/
return 0;
}

.......and it, too, misses the last number in the file without the post-loop
single extra use of infile>>value....
I tried many things, including the FAQ version, and putting an extra \n onto
the end of the file being read. No go; same problem.
All lines of file, example: 2.3,45.90,23,-0.2334,0.9\n
I get a beautiful sequence of every number in the file, exactly what I
wanted, and they are all _numbers_ (hallelujah), but the last one's not
there.

Your code modified to my need does everything I want it to except catch the
last number in the file _without_ the ugly kludge....

Is there more to this _neat_ clean way of getting my numbers from the file,
that catches the last one but also allows use of the char non-number
tosser?

Thanks!
--
Peace
JB
jb@tetrahedraverse.com
Web: http://tetrahedraverse.com


Jan 30 '08 #4
On Jan 30, 11:47*am, "Alf P. Steinbach" <al...@start.nowrote:
* John Brawley:


"Alf P. Steinbach" <al...@start.nowrote in message
news:13*************@corp.supernews.com...
* Boltar:
I'm using ifstream (which I hardly ever use) to read an ascii text
file (containing numbers delimited by newlines) in a loop using
something like:
>ifstream infile("filename")
int value;
>infile >value;
while(!infile.eof() {
* * * *infile >value;
* * * *:
>}
>The problem is if the file is missing a terminating newline the final
number is missed. How can I make sure its read anyway when the newline
is missing?
Don't test for eof, test for good stream state, i.e. that last read was
successful.
Like
* *ifstream infile( "filename" );
* *for( ;; )
* *{
* * * *int value;
* * * *infile >value;
* * * *if( !infile.good() )
* * * *{
* * * * * *break;
* * * *}
* * * *// Do something with value.
* *}
* *if( !infile.eof() ) { /* oops. */ }
Disclaimer: I really hate iostreams, so possibly that last check isn't
completely 100% cover-all-cases or guaranteed to detect failure.
May I please ask further?
I ran this, modified as follows:
(usual up-top-stuff)
int main() {
ifstream infile("file.ext");
for(;;)
* * {
double value;
char toss; */*remove the commas (delimiter) & newlines*/
if(!infile.good()) {break;}
cout<<value<<" ";
* * }
infile>>value; cout<<value; */*kludge does get the final number....*/
if (!infile.eof()) {/*oops*/} */*my kludge for oops...(?)*/
return 0;
}
......and it, too, misses the last number in the file without the post-loop
single extra use of * infile>>value....
I tried many things, including the FAQ version, and putting an extra \n onto
the end of the file being read. *No go; same problem.
All lines of file, example: 2.3,45.90,23,-0.2334,0.9\n
I get a beautiful sequence of every number in the file, exactly what I
wanted, and they are all _numbers_ (hallelujah), but the last one's not
there.

Try 'infile.fail()' or just '!infile' instead of '!infile.good()'.

As I wrote, I hate 'em streams and so couldn't guarantee correctness.
IMO the problem is that EOF is simultaneously a character in the
stream and some sort of abstraction representing the end of the
stream.

IIRC is.good() holds even if next op is is.get() == EOF;

is.good() is meant to be true if characters are available, but IMO if
the next char is EOF then by definition no characters are available.

Further if EOF is a character and you are at eof(), then you should
IMO be able to is.putback(), but IIRC you can't.

I opted to wrap up text streams, so they all have the same semantic,
for files, console and strings. Any stream has a name, for files the
name of the file, for strings a name you supply and for console the
name of the console ( and a terminator you supply) Also every stream
keeps a record of line and column position, so you can output error
messages including name, and current position in a user friendly
format. Final part is a checkpoint stack, so you can create
checkpoints with useful messages, and they pop off the stack at the
end of their scope. Another stream type is a stream stack, where you
can push and pop streams (say for #include files, or macros. Its not
perfect as ideally you should be able to pushback through eof, but
because of the semantics of std::stteams this isnt really feasible.

However I do despair of the std::streams ...

I expect I will hear other opinions from experts about the issue :-)

regards
Andy Little

Jan 30 '08 #5
In article <2db713c3-6d93-4f93-8fed-ee7a71ad52e5
@y5g2000hsf.googlegroups.com>, an**@servocomm.freeserve.co.uk says...

[ ... ]
is.good() is meant to be true if characters are available, but IMO if
the next char is EOF then by definition no characters are available.
You're misinterpreting is.good(). It's meant to indicate the current
error state of the stream buffer. IOW, if the end of file has been
encountered, it should signal so -- but if it hasn't been encountered
yet, it should NOT signal so.

IMO, this is generally a good thing -- Pascal's I/O system worked as you
describe and it made writing correct loops considerably more difficult.
Further if EOF is a character and you are at eof(), then you should
IMO be able to is.putback(), but IIRC you can't.
Trivially true -- any statement of the form "if x then y' is true, but
meaningless if x if false. In this case, you start with the idea that
EOF is a character -- but since it's not, the rest of the statement
means nothing.
I opted to wrap up text streams, so they all have the same semantic,
for files, console and strings. Any stream has a name, for files the
name of the file, for strings a name you supply and for console the
name of the console ( and a terminator you supply) Also every stream
keeps a record of line and column position, so you can output error
messages including name, and current position in a user friendly
format. Final part is a checkpoint stack, so you can create
checkpoints with useful messages, and they pop off the stack at the
end of their scope. Another stream type is a stream stack, where you
can push and pop streams (say for #include files, or macros. Its not
perfect as ideally you should be able to pushback through eof, but
because of the semantics of std::stteams this isnt really feasible.
If you're wrapping the stream anyway, it's pretty trivial to add your
own capability to put things back, even when not supported by the stream
itself (just put whatever back into your own buffer, and have your input
routines check that buffer before reading from the stream).

Years ago, I wrote a wrapper for lexing C source code that wrapped C's
FILE * I/O. It allowed you to unget a more or less arbitrary amount of
data -- and unless memory serves me particularly badly today, it should
have still allowed you to unget (and read) data after the stream itself
had encountered EOF.

--
Later,
Jerry.

The universe is a figment of its own imagination.
Jan 31 '08 #6
On Feb 1, 4:07 pm, Jerry Coffin <jcof...@taeus.comwrote:
In article <28432abe-730f-4a4c-8ef1-311adfef3131
@b2g2000hsg.googlegroups.com>, james.ka...@gmail.com says...
[ ... ]
I'd much rather write some sort of manipulator to
handle separators. Much more flexible, and much more accurate.
"Accurate" means it adheres more closely to some defined standard. In
this case, the only standard provided was his original description of
the file format, to which this adhered _perfectly_. As such, no higher
degree of accuracy is possible.
Accurate may not be the right word, but it didn't seem to me
that he wanted to have more than one comma handled as a single
separator. It looked more like he was dealing with a CSV
format.
Done correctly, for example, it wouldn't allow multiple
commas to be treated as a single separator.
This is a perfectly reasonable way of fulfilling that
requirement IF IT EXISTS. Claiming that it's more accurate is
simply a falsehood in this case. It's not really more flexible
either -- it simply fulfills a different set of requirements.
The general approach is more flexible, in that it allows for a
greater degree of variation in defining your separators (and
signaling an error if a separator isn't conform).
On one hand, if you want a series of separators to be
translated as a series of empty fields, it fulfills that
requirement quite nicely. OTOH, it makes it much more
difficult to meet a requirement that an arbitrary number
separators can be used to separate any two fields.
It's pretty trivial to add a loop on the comma.
Your solution would be extremely good if it was required --
but at least according to the OP, no such requirement exists.
That wasn't the way I interpreted what he said, but of course,
he didn't present an exact specification. In the end, it
probablyl depends on the wording in the specification: if the
specification says that commas are to be treated as white space,
then a new locale is a reasonable solution; if the specification
defines separators, then I think a manipulator which eats
separators is more appropriate. (I also think that a beginner
will reach the level of being able to write such manipulators
much sooner than being able to write a new locale. I know that
I have problems went I need to implement a new locale, and I'm
hardly a beginner.)

--
James Kanze (GABI Software) email:ja*********@gmail.com
Conseils en informatique orientée objet/
Beratung in objektorientierter Datenverarbeitung
9 place Sémard, 78210 St.-Cyr-l'École, France, +33 (0)1 30 23 00 34
Feb 1 '08 #7
On Feb 1, 2:05 pm, "Alf P. Steinbach" <al...@start.nowrote:
* James Kanze:
[...]
I just refuse to go around remembering arcane details of iostreams.
They're that ugly. :-)
The naming conventions and the error handling are bad, I'll
grant you that. And of course, IF you use the "standard" idiom,
you don't have to remember them.

[...]
The most important reason to use it is because it is the
standard idiom.
[...]
(even if in this case, it's a bit longer.) But that's not the
issue here. I don't write it like that, however, because as I
said above---any time you see something other than what is in
the FAQ...
Let's not elevate the FAQ to infallible authority.
Both you and I have contributed to the FAQ (at least I think
you have, I know I have).
If it were only the FAQ, and other experts in iostream were
saying other things... But all of the people I know who are
really competent in iostream use the same idiom.
So saying our own statements and viewpoints etc. are godlike
authoritative just because they have ended up in the FAQ, it
would be a very circular argument :-), and besides, in
addition to much great advice, the FAQ also contains some
dubious statements and examples.
I know. (As it happened, this idiom predates the time I learned
C++, so I can't claim any responsibility for it.)
Most experienced programmers, on seeing such code,
would start by asking if I understood iostream, or if he knew
better, by asking what was special here that caused me to break
with the standard idiom.
Some idioms are good.
Some are not.
More precisely: the fact that something is an established idiom
is a positive point for it. Other, negative points, can
outweigh that. In this case, although I'd have done something
different if the idiom didn't exist, the bad points of the idiom
are small enough that they don't outweigh the advantage of using
the idiom.

--
James Kanze (GABI Software) email:ja*********@gmail.com
Conseils en informatique orientée objet/
Beratung in objektorientierter Datenverarbeitung
9 place Sémard, 78210 St.-Cyr-l'École, France, +33 (0)1 30 23 00 34
Feb 1 '08 #8

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

Similar topics

7
by: Anton Ishmurzin | last post by:
Greetings All, I think everybodyknows the answer already. But i am quite a newbie in c++. I've got the following line in my code: ifstream ini_file_in("filename.dat", ios::in); But, the...
6
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"...
4
by: Gunnar | last post by:
Hello. The (stupid) code below does not compile with the message In method `istream::istream(const istream &)': /usr/lib/gcc-lib/i386-linux/2.95.4/../../../../include/g++-3/streambuf.h:128:...
15
by: Christopher Benson-Manica | last post by:
The dumb-o-meter's pegging out today... What, if anything, is wrong with the following code? std::ifstream f( "myfile.txt" ); if( !f ) { cerr << "Couldn't open file\n"; } while( getline(f,s)...
4
by: hall | last post by:
Hi. I ran across a bug in one of my problems and after spending some time tracking it down i found that the problem arose in a piece of code that essentially did this: ----------- ifstream...
2
by: Mathieu Malaterre | last post by:
Hi, I am tryig to convert part of a c++ IO library. Right now I am removing all 'FILE*' and replace them with ifstream. But I have a problem, after seeking through a stream I have to call the...
1
by: inkapyrite | last post by:
Hi all. I'm using ifstream to read from a named pipe but i've encountered an annoying problem. For some reason, the program blocks on reading an ifstream's internal buffer that's only half-filled....
2
by: Karl | last post by:
Hey everyone! I've got a quick question on whether std::ifstream is buffered or not. The reason is that I have a homework assignment that requires me to benchmark copying files using different...
4
by: manontheedge | last post by:
i'm working on a C++ program that uses operator overloads (which i'm just learning to use), and i have the ostream working fine, but i'm thinking i'm using it wrong somehow because the ofstream...
0
by: Charles Arthur | last post by:
How do i turn on java script on a villaon, callus and itel keypad mobile phone
1
by: nemocccc | last post by:
hello, everyone, I want to develop a software for my android phone for daily needs, any suggestions?
1
by: Sonnysonu | last post by:
This is the data of csv file 1 2 3 1 2 3 1 2 3 1 2 3 2 3 2 3 3 the lengths should be different i have to store the data by column-wise with in the specific length. suppose the i have to...
0
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...
0
Oralloy
by: Oralloy | last post by:
Hello folks, I am unable to find appropriate documentation on the type promotion of bit-fields when using the generalised comparison operator "<=>". The problem is that using the GNU compilers,...
0
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...
0
by: Hystou | last post by:
Overview: Windows 11 and 10 have less user interface control over operating system update behaviour than previous versions of Windows. In Windows 11 and 10, there is no way to turn off the Windows...
0
tracyyun
by: tracyyun | last post by:
Dear forum friends, With the development of smart home technology, a variety of wireless communication protocols have appeared on the market, such as Zigbee, Z-Wave, Wi-Fi, Bluetooth, etc. Each...
0
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...

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.