Reputation: 648
roha.txt
I really love to spend time with you.
Let's go for coffee someday.
Enjoy whole day and cherish the memories.
Code-1
#include <iostream>
#include <fstream>
int main()
{
char str[100];
std::ifstream fin;
fin.open("roha.txt", std::ios::in);
for(int i=0; i<=3; i++)
{
std::cout<<bool(fin.getline(str,100) )<<" "<<str<<fin.fail()<<"\n";
}
}
Output
1 I really love to spend time with you.0
1 Let's go for coffee someday.0
1 Enjoy whole day and cherish the memories.0
0 1
Code-2
#include <iostream>
#include <fstream>
#include <string>
using std::string;
int main()
{
string str;
std::ifstream fin;
fin.open("roha.txt", std::ios::in);
for(int i=0; i<=3; i++)
{
std::cout<<bool(std::getline(fin,str) )<<" "<<str<<fin.fail()<<"\n";
}
}
Output
1 I really love to spend time with you.0
1 Let's go for coffee someday.0
1 Enjoy whole day and cherish the memories.0
0 Enjoy whole day and cherish the memories.1
I know C-style char array
, istream::getline
and string
, std::getline
are different. But I want to know what actually happens.
I am guessing that for string
, std::getline
, it extracts string for 1st, 2nd and when it tries to extract the 3rd time it sees eof
so it extracts just before eof
.
The next time we try to extract it, just encounters eof
so it didn't extract anything and set fail-bit
.
string str
didn't get modified, so when we try to print it, only the string last extracted gets printed.
I don't know if what I’m thinking is right...
Also I can’t make any such case regarding istream::getline()
, C-style char array
.
Upvotes: 2
Views: 1009
Reputation: 13310
To quote the standard, section 21.3.3.4 inserters and extractors [string.io]:
Clause 6:
[…] After constructing a
sentry
object, if thesentry
converts totrue
, callsstr.erase()
and then extracts characters fromis
and appends them tostr
[…] until any of the following occurs:
- end-of-file occurs on the input sequence (in which case, the
getline
function callsis.setstate(ios_base::eofbit))
.- […]
Section 29.7.4.1.3 Class basic_istream::sentry
:
explicit sentry(basic_istream<charT, traits>& is, bool noskipws = false);
Effects: Ifis.good()
isfalse
, callsis.setstate(failbit)
[…] If, after any preparation is completed,is.good()
istrue
,ok_ != false
otherwise,ok_ == false
. During preparation, the constructor may callsetstate(failbit)
[…]
explicit operator bool() const;
Returns:ok_
So, what is happening with the string version:
is.good()
. This is false because eofbit is setSection 29.7.4.3 Unformatted input functions
Clause 21 (this is about the C-string version):
In any case, if
n
is greater than zero, it then stores a null character (usingcharT()
) into the next successive location of the array
The rest of the wording is similar to the string version. In other words, the C-string version of getline always stores a '\0'
character, even if it failed. The std::string
version does not, presumably because it doesn't introduce the same memory safety issues that you have with the C version if you forget to check the failbit.
Upvotes: 3