Velocity Reviews - Computer Hardware Reviews

Velocity Reviews > Newsgroups > Programming > C++ > ifstream::getline() synatx

Reply
Thread Tools

ifstream::getline() synatx

 
 
Mark S.
Guest
Posts: n/a
 
      04-17-2009
Hi,
since my next exercise involves working with files, I tried to learn
some more about ifstream. So far in the book, reading from files was
generally handled like this:
ifstream in(file); // (1)
string s;
while(getline(in, s)) // (2)
...

So far, so good. But when looking around, I also found the following syntax:
ifstream in; // (3)
string s;
in.open(file); // (4)
in.getline(s, 30); // (5)
...
in.close(); // (6)

Both works, of course. The second way of handling files made more sense
to me, but I was still wondering about the syntax. Google brought up
this page:
http://www.cplusplus.com/reference/iostream/ifstream/

Now my questions:

a) On the web page, it says: "The file to be associated with the stream
can be specified either as a parameter in the constructor or by calling
member open."
Now, the way I understand it is this: (1) is opening the file via the
constructor (and creates the object "in"?) and (3) is creating the
object first, then opening the file explicitly (4) and eventually
closing it (6).
In the documentation, I don't read anything about a destructor, so I wonder:
- Why don't I need to close the file in the first example?

b) My second (more important) question has to do with getline. With (2),
the _complete_ (!) line is automatically read into the string "line"
while the second syntax seems to always require a second argument - the
length that is to be read. This is they way I also interpret the
documentation, however, the first example clearly works. So..

- I thought both example used the same functions, just with different
syntax?
- How come that the documentation does not mention how to read the
complete line? Is that part missing? Shouldn't in.getline(s) work the
same way getline(in, s) does?

The documentation says that getline() exists in fstream and in string,
could that be the problem? If so, how do I resolve it (I mean, isn't it
pretty common to have strings when you are working with files?)?

-> Basically, which way should I use to handle files? Or am I
overlooking something?

Thank you for your time!

Kind regards
Mark
 
Reply With Quote
 
 
 
 
Mark S.
Guest
Posts: n/a
 
      04-18-2009
Obnoxious User wrote:
> On Fri, 17 Apr 2009 19:14:42 +0200, Mark S. wrote:
>
>> Hi,
>> since my next exercise involves working with files, I tried to learn
>> some more about ifstream. So far in the book, reading from files was
>> generally handled like this:
>> ifstream in(file); // (1)
>> string s;
>> while(getline(in, s)) // (2)
>> ...
>>
>> So far, so good. But when looking around, I also found the following
>> syntax:
>> ifstream in; // (3)
>> string s;
>> in.open(file); // (4)
>> in.getline(s, 30); // (5)

>
> istream& istream::getline (char* s, streamsize n )
>
> You can't pass a std::string as an argument for 's'. It won't compile.
> You need to allocate a buffer.
>
> char buffer[20];
> in.getline(buffer,20);

I see.

>> ...
>> in.close(); // (6)
>>
>> Both works, of course.

>
> No they don't.

Ups, I compiled the second example without the actual getline. *blush*
All of this makes a lot more sense now!

> The destructor of fstream will close the file if you haven't
> done so yourself.

Yes, but what if I want to close it beforehand? Then I just in.close,
right? Also, I thought it is "good programming" to make sure these kind
of things are done right? So I guess my question should not only have
been whether or not it closes, but also if I should close in manually.

>> b) My second (more important) question has to do with getline. With (2),
>> the _complete_ (!) line is automatically read into the string "line"

>
> That's because std::getline() is an auxiliary function to make it easier
> to read a text line from any input stream without having to worry about
> buffer sizes.
>
>> while the second syntax seems to always require a second argument - the
>> length that is to be read. This is they way I also interpret the
>> documentation, however, the first example clearly works. So..

>
> istream& istream::getline (char* s, streamsize n )
>
> This member function needs to know how much it can store in the buffer
> pointed to by 's'. That's why you need to supply the size.
>
>> - I thought both example used the same functions, just with different
>> syntax?

>
> No, they use different functions.

Sorry again if this is a stupid question - but how do I make sure which
one is used? From my newbie perspective, both do the same (read a line
from a file). Moreover, how do I know which one is the better choice for
the task at hand?

 
Reply With Quote
 
 
 
 
James Kanze
Guest
Posts: n/a
 
      04-18-2009
On Apr 18, 8:24 am, "Mark S." <(E-Mail Removed)> wrote:
> Obnoxious User wrote:
> > On Fri, 17 Apr 2009 19:14:42 +0200, Mark S. wrote:


[...]
> > The destructor of fstream will close the file if you haven't
> > done so yourself.


> Yes, but what if I want to close it beforehand? Then I just
> in.close, right? Also, I thought it is "good programming" to
> make sure these kind of things are done right? So I guess my
> question should not only have been whether or not it closes,
> but also if I should close in manually.


It depends. In principal, close can fail, so should not be left
to the destructor. In practice, when inputting, you're checking
the status after each input anyway; if close fails, there's
something seriously wrong with the system, and you can't do much
about it, so there's really no strong motivation for not just
leaving it to the destructor. For output, close() can fail even
though all earlier output succeeded, and in such cases, your
data may not be correctly written. At the very least, you have
to inform the user of this in some way---if you're writing to a
file, you may even want to delete the file, rather than leaving
corrupt data lying around. So an explicit close in the normal
program flow is essential. On the other hand, if some other
serious error occured, so that you're abandonning processing
anyway (and will report an error and maybe delete the file
anyway), then it probably doesn't matter if the data in the file
isn't valid, so you can allow the close in the destructor to do
the job. (In this case, the destructor would typically be
called as a result of stack unwinding from an exception.)

[...]
> >> while the second syntax seems to always require a second argument - the
> >> length that is to be read. This is they way I also interpret the
> >> documentation, however, the first example clearly works. So..


> > istream& istream::getline (char* s, streamsize n )


> > This member function needs to know how much it can store in the buffer
> > pointed to by 's'. That's why you need to supply the size.


> >> - I thought both example used the same functions, just with different
> >> syntax?


> > No, they use different functions.


> Sorry again if this is a stupid question - but how do I make
> sure which one is used? From my newbie perspective, both do
> the same (read a line from a file). Moreover, how do I know
> which one is the better choice for the task at hand?


One's a member function, the other isn't, so the calling syntax
is different. And they take different types of arguments.

As to which is better, IMHO, there's never any valid reason to
input into a char[]. The member function is probably present
mainly for historical reasons---it was around before std::string
was invented.

--
James Kanze (GABI Software) email:(E-Mail Removed)
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

 
Reply With Quote
 
Mark S.
Guest
Posts: n/a
 
      04-18-2009
Arghhh, this whole exercise is more and more difficult for me. I'm at a
total loss here. This is the exercise (TICPP, 7.1):
Create a Text class that contains a string object to hold the text of a
file. Give it two constructors: a default constructor and a constructor
that takes a string argument that is the name of the file to open. When
the second constructor is used, open the file and read the contents into
the string member object. Add a member function contents( ) to return
the string so (for example) it can be printed. In main( ), open a file
using Text and print the contents.

For testing purposes, I tried to implement the procedure in main() first.

Before I wrote:
> ifstream in(file);


At that point I assumed I could easily define "file" like this:
string file = "E01.cpp";

But of course the argument needs to be a const char* (I still don't
really know what the difference between string and char* is - many
websites seem to use both terms simultaneously), so I need to convert it
first. Google brought up this (
http://www.codeguru.com/cpp/cpp/stri...cle.php/c13267 ):
char* name = new char[strlen("marius")+1];
strcpy(name, "marius");

but I can't get it to work. I guess the "+1" is for the terminating \0,
but strlen is problematic anyways, which is, I THINK, from cstring (?).
So I modified it:
string a = "E01.cpp";
char* b = new char[(a.length())+1];
But then I don't know how to copy the string!

The reference:
http://www.cplusplus.com/reference/string/string/copy/

says
size_t copy ( char* s, size_t n, size_t pos = 0) const;

Except the words "copy", "char* s" and "const", I have no idea what the
words mean and I don't understand the whole syntax of the line. Only
with the help of their description below, their example and Google I was
able to figure out some parts (but I still don't know why there is a
"const" at the end or why they use size_t instead of the unsigned int,
which it says it is). But seriously, how does one read this line??? How
do I go from not knowing anything about this function to writing a
working line of code? Is there a tutorial on how to read these things?

Anyways, in their example
size_t length;
char buffer[20];
string str ("Test string...");
length=str.copy(buffer,6,5);
buffer[length]='\0';
cout << "buffer contains: " << buffer << "\n";

the string is copied to the char array (which I guess is the same as
char* , right?) , but only 6 characters starting at position 5. Since
all parameters are required, *I don't see how just to copy a complete
string*, without defining the length first. I would have something like
this in mind:
string a = "can be very long or short, whatever";
char copyhere[] = a.length(); // or a.length + 1 ?
copyhere = a; || a.copy(copyhere); || copyhere = copy(a);
Or something like that. But nothing works and I am quite frustrated
right now so I would really appreciate any help you guys could give me.

Thank you in advance!

Kind regards
Mark
 
Reply With Quote
 
Phlip
Guest
Posts: n/a
 
      04-18-2009
Obnoxious User wrote:

> 'char *'-strings are old school C strings. Avoid them if you're learning.
> Use only std::string. It's a complete design failure that the fstream
> classes don't accept std::string.


You really think the Committee didn't think of that? They set a precedent
against silent type promotions that cause more trouble than they are worth
at scaling time. Just type the freaking .c_str() yourself.


 
Reply With Quote
 
James Kanze
Guest
Posts: n/a
 
      04-18-2009
On Apr 18, 6:14 pm, "Phlip" <(E-Mail Removed)> wrote:
> Obnoxious User wrote:
> > 'char *'-strings are old school C strings. Avoid them if
> > you're learning. Use only std::string. It's a complete
> > design failure that the fstream classes don't accept
> > std::string.


> You really think the Committee didn't think of that? They set
> a precedent against silent type promotions that cause more
> trouble than they are worth at scaling time. Just type the
> freaking .c_str() yourself.


He wasn't asking for an implicit conversion of std::string to
char const*. I think everyone pretty much understands why that
would be a bad thing. What surprised him is that
std::ifstream:pen doesn't take a string as its argument. And
the reason is purely historical, and related to deadlines when
producing the last standard---the next version of the standard
has such an overload.

--
James Kanze (GABI Software) email:(E-Mail Removed)
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
 
Reply With Quote
 
Phlip
Guest
Posts: n/a
 
      04-18-2009
James Kanze wrote:

> He wasn't asking for an implicit conversion of std::string to char const*.


I didn't say he did. I wouldn't have overloaded open() myself, but the
Committee is certainly free too!



 
Reply With Quote
 
Mark S.
Guest
Posts: n/a
 
      04-19-2009
Obnoxious User wrote:
> 'char *'-strings are old school C strings. Avoid them if you're learning.
> Use only std::string. It's a complete design failure that the fstream
> classes don't accept std::string.

Just to make sure: You mean that I should use c_str() whenever possible?
I am still confused when "some text" is treated as a string and when as
a char*. But I guess I'll figure it out eventually as time goes on.

> You don't need to. You can ask the std::string object to return
> a temporary c-string when necessary.
>
> string s = "E01.cpp";
> ifstream in(s.c_str());
> if(in.good()) {
> while(getline(in,s)) {
> cout << s << endl;
> }
> }

Thank you, that worked. On to exercise 2! :-p

I must say I do not quite understand the discussion that follows after
your post. Are you guys saying that C++ is still a work in progress?
 
Reply With Quote
 
Mark S.
Guest
Posts: n/a
 
      04-19-2009
James Kanze wrote:
> On Apr 18, 8:24 am, "Mark S." <(E-Mail Removed)> wrote:
>> Obnoxious User wrote:
>>> On Fri, 17 Apr 2009 19:14:42 +0200, Mark S. wrote:

>
> [...]
>>> The destructor of fstream will close the file if you haven't
>>> done so yourself.

>
>> Yes, but what if I want to close it beforehand? Then I just
>> in.close, right? Also, I thought it is "good programming" to
>> make sure these kind of things are done right? So I guess my
>> question should not only have been whether or not it closes,
>> but also if I should close in manually.

>
> It depends. In principal, close can fail, so should not be left
> to the destructor. In practice, when inputting, you're checking
> the status after each input anyway; if close fails, there's
> something seriously wrong with the system, and you can't do much
> about it, so there's really no strong motivation for not just
> leaving it to the destructor. For output, close() can fail even
> though all earlier output succeeded, and in such cases, your
> data may not be correctly written. At the very least, you have
> to inform the user of this in some way---if you're writing to a
> file, you may even want to delete the file, rather than leaving
> corrupt data lying around. So an explicit close in the normal
> program flow is essential.

Thanks, this is what I thought.

> On the other hand, if some other
> serious error occured, so that you're abandonning processing
> anyway (and will report an error and maybe delete the file
> anyway), then it probably doesn't matter if the data in the file
> isn't valid, so you can allow the close in the destructor to do
> the job. (In this case, the destructor would typically be
> called as a result of stack unwinding from an exception.)

Hmm, but I guess it would still be nice to tell the user what is going
on. Of course it all depends on the situation, but I think I will try to
explicitly close files for now.
 
Reply With Quote
 
Mark S.
Guest
Posts: n/a
 
      04-19-2009
Obnoxious User wrote:
> On Sun, 19 Apr 2009 08:10:51 +0200, Mark S. wrote:
>
>> Obnoxious User wrote:
>>> 'char *'-strings are old school C strings. Avoid them if you're
>>> learning. Use only std::string. It's a complete design failure that the
>>> fstream classes don't accept std::string.

>> Just to make sure: You mean that I should use c_str() whenever possible?
>> I am still confused when "some text" is treated as a string and when as
>> a char*. But I guess I'll figure it out eventually as time goes on.

>
> Any text string in double quotes is of type 'char const *'.
> "text"

So when I have
string str = "some text";
there is actually some kind of cast happening?

> C++ is standardized. But the next standard is in the pipeline.

I see. Thank you.
 
Reply With Quote
 
 
 
Reply

Thread Tools

Posting Rules
You may not post new threads
You may not post replies
You may not post attachments
You may not edit your posts

BB code is On
Smilies are On
[IMG] code is On
HTML code is Off
Trackbacks are On
Pingbacks are On
Refbacks are Off


Similar Threads
Thread Thread Starter Forum Replies Last Post
Exact synatx required...! shakeelsultan VHDL 1 02-20-2007 11:51 PM



Advertisments