exception woes using fstream and .eof

G

Greg

I am trying to convert an older console application written in C to a
visual application using several Borland VCL components (open and save
dialogs). I am declaring input and output stream variables as follows:


ifstream InputFile;
ofstream OutputFile;

I am initializing them using the filename properties in the "open" and
"save" dialogs respectively, with the "._C_str" modifier attached to
the end. The files to be read are comma separated variable type with
5000 to 30000 data pairs. I was trying to use "InputFile.getline(line,
81)", but when I use it in the following while loop, I get runtime
exception errors that look like language exceptions:

while( ! InputFile.eof ( ))

{

InputFile.getline(line, 81);

and more stuff;

}

Two additional notes: 1) I can continue to run the program after the
exception dialog is closed, and the output file appears fine, and 2) If
I replace the while loop with a for loop, I don't get exceptions.
However, I'd rather use the while loop (much neater for my application)
Any help would be appreciated.

Thanks in advance.
 
D

Dietmar Kuehl

Greg said:
while( ! InputFile.eof ( ))

{

InputFile.getline(line, 81);

and more stuff;

}

If is always wrong not to check the success of an input function: the
library cannot know in advance what you want to read next. Thus, you
should test the read operation for success. In addition, I propose
that you don't use a fixed length string to deal with lines but rather
string object. Your loop should thus rather look something like this:

for (std::string line; std::getlin(InputFile, line); )
/* process your line */;
 
G

Greg

Please forgive my ignorance, but I'm still struggling with many aspects
of ANSI/ISO Standard C++ . I have several questions: (1) I have a
"using namespace std" statement below my preprocessor directives ( #
include <...>). Does that mean I don't have to use the "std::" prefix?
(2) What's the difference between "std::getline( )" and, in my
particular case: "InputFile.getline( )" ? (3) Should I use something
like: "if (InputFile.getline( )) { do some stuff with the string }" to
check the success of the input function? (4) Is using the ".eof ( )"
function not as straightforward as it appears? Isn't it a boolean
function that takes no input parameters? In my particular case, I'm
using "InputFile.eof( )" Thanks again for your assistance.
 
H

Heinz Ozwirk

Greg said:
Please forgive my ignorance, but I'm still struggling with many aspects
of ANSI/ISO Standard C++ . I have several questions: (1) I have a
"using namespace std" statement below my preprocessor directives ( #
include <...>). Does that mean I don't have to use the "std::" prefix?

You shuld better not use "using namespace std". You might get much more than
you want. Get used to the std:: prefix.
(2) What's the difference between "std::getline( )" and, in my
particular case: "InputFile.getline( )" ?

std::getline can read an std::string. ifstream's getline member cannot.
(3) Should I use something
like: "if (InputFile.getline( )) { do some stuff with the string }" to
check the success of the input function?

As Dietmar suggested, use something like for(...; std::getline(...); ...) or
while (std::getline(...))
(4) Is using the ".eof ( )"
function not as straightforward as it appears? Isn't it a boolean
function that takes no input parameters? In my particular case, I'm
using "InputFile.eof( )" Thanks again for your assistance.

eof is used after reading from a file, to determine whether reading has been
successfull or not. You cannot use eof to predict the result of the next
input operation. But I cannot remmber when I actually did use eof.
std::getline returns (something like) true on success and false on error
(including the end of the file). If you are interested in why reading
stopped, you can use eof, but do you really care?

HTH
Heinz
 
J

Jacek Dziedzic

Greg said:
Please forgive my ignorance, but I'm still struggling with many aspects
of ANSI/ISO Standard C++ .
> I have several questions: (1) I have a
"using namespace std" statement below my preprocessor directives ( #
include <...>). Does that mean I don't have to use the "std::" prefix?

Basically, yes. It brings all the symbols that are contained
in std:: to the global namespace. Make sure, however, that you
don't use 'using namespace std' in header files, only in
source files.

(2) What's the difference between "std::getline( )" and, in my
particular case: "InputFile.getline( )" ?

The first gets the line into a std::string, the latter into
a char[] array. Therefore the first one doesn't rely on the
line being 'short enough' to fit your fixed-size char[] array.
std::string can grow to accomodate data.
(4) Is using the ".eof ( )"
function not as straightforward as it appears?

It is not.
Isn't it a boolean
function that takes no input parameters? In my particular case, I'm
using "InputFile.eof( )"

Yes it is.

The trouble with .eof() is that you can't reliably tell
if a stream is at EOF *before* you try to read the last
datum. For instance someone can append data to the stream in
the meantime, or if the stream is tied to the keyboard it's
hard to tell EOF at all. For a longer explanation try

http://www.parashift.com/c++-faq-lite/input-output.html#faq-15.5

Perhaps you could catch the exception and see what it is?

#include<exception>
try {
// getline stuff
}
catch(exception &e) {
cerr "Shit has just happened: " << e.what() << endl;
}

HTH,
- J.
 
D

Dietmar Kuehl

Greg said:
(1) I have a
"using namespace std" statement below my preprocessor directives ( #
include <...>). Does that mean I don't have to use the "std::" prefix?

I'm no fan of using directives. I even only use using declarations
where I really have to. I prefer the explicit qualification, possibly
with a namespace alias for a short hand (of, course hardly for 'std'
as this is about a short as it gets). It makes it easier to tell where
a particular class or functions comes from.

However, yes, a using directive means that you don't have to use the
explicit scope qualification, i.e. you can omit the 'std::' if you
want to.
(2) What's the difference between "std::getline( )" and, in my
particular case: "InputFile.getline( )" ?

The function 'std::getline()' operates on 'std::string' objects (well,
it is actually a function template operating on 'std::basic_string'
instantiations but unless you are dealing with templates it is
probably sufficient to know that it operates on 'std:string') while
the member function 'std::istream::getline()' operates on character
arrays. 'std::string' has several advantages, one being that it can
cope with variable sized strings meaning that your lines effectively
become unlimited (there is a limit but it is generally rather large;
see 'std::string::max_size()' for the limit). I wouldn't advice people
new to C++ to use built-in arrays. The various classes like
'std::string', 'std::vector', etc. have many advantages.
(3) Should I use something
like: "if (InputFile.getline( )) { do some stuff with the string }" to
check the success of the input function?

No. You should use 'std::string's to operate on and check the result
of the corresponding stream: the stream functions return the stream they
operate on and there is a conversion to a Boolean state which indicates
whether the stream ran into an error. That is, you should use something
like

if (std::getline(InputFile, str)) { do some stuff with the string }

Hm, somehow I have the strange feeling I advised you to do so in the
previous article...
(4) Is using the ".eof ( )" function not as straightforward as it
appears?

Obviously... The only reasonable use for the member 'eof()' is to
determine whether input failed due to a format error or due to hitting
end of file. The former is generally an error which needs some form of
handling, e.g. informing the user that the input format was broken,
whereas the latter often just indicates that all input was read and
signals that you need to go on doing other stuff. It is only of minor
use when you want to tell whether the next input could be successful:
You know that it will fail for sure if the bit is set but it could
fail, too, if the bit is not set, e.g. because there is no more input.
Isn't it a boolean function that takes no input parameters?

Right. But the interpretation of the function's result is not as
simple as many people think it is. As a said before: the stream cannot
tell in advance what you want to read. Thus, you need to check your
results *after* you have tried to read something. This is actually a
statement applying to many more I/O libraries than just the C++
standard library.
In my particular case, I'm using "InputFile.eof( )"

I have seen that you were using it. ...and the way you use it is
entirely inappropriate - as I already stated [implicitly] in my
previous reply. A reasonable use of 'eof()' would look like this:

int i = 0;
if (!(std::cin >> i))
if (std::cin.eof())
std::cout << "OK, I'm done reading\n";
else
std::cout << "ERROR: expected to read an integer!\n";

Maybe it is worth to at least consider the advice you get from the
net, especially when you ask for it! What is the point of asking
otherwise?
 
G

Greg

Thanks very much for all of the advice.....It may take me a few hours,
days, or weeks to digest it all. As I said before, please forgive my
ignorance of the C++ language. I'll try to form some coherent comments
and questions, and reply again in a few hours. And again, thanks for
everyones' patience and generous information.
 
D

Default User

Greg said:
Please forgive my ignorance, but I'm still struggling with many
aspects of ANSI/ISO Standard C++

You are also struggling with how to post properly. Read my .sig below
for important information.



Brian
 

Ask a Question

Want to reply to this thread or ask your own question?

You'll need to choose a username for the site, which only take a couple of moments. After that, you can post your question and our members will help you out.

Ask a Question

Members online

No members online now.

Forum statistics

Threads
473,768
Messages
2,569,574
Members
45,051
Latest member
CarleyMcCr

Latest Threads

Top