Returning to beginning of file after getline
Since you have reached (and attempted to read past) the end of the file, the eof
and fail
flags will be set. You need to clear them using ifile.clear
– then try seeking:
ifile.clear();
ifile.seekg(0);
How do I return an ifstream back to the beginning of a line that was just read in C++?
There is no direct way to say "get back to the start of the last line". However, you can get back to a position you kept by using std::istream::tellg()
. That is, before reading a line you'd use tellg()
and then seekg()
to get back to the position.
However, calling the seek functions frequently is fairly expensive, i.e., I would look at removing the requirement to read lines again.
C++ getline function missing the first line of txt file
You create a single node so every iteration through the loop you overwrite the previously read values.
In the second iteration of the while loop your first call to getline
presumably fails and sets the value of name
to an empty string. As the stream is now in a failed state the rest of your reads are ignored and finally the loop breaks at the end of the loop.
This might be closer to what you wanted:
int recordCount = 0;
fs.open(fileName, ios::in | ios::binary);
while(fs) {
record * temp = new record;
std::getline(fs, temp->name);
std::getline(fs, temp->email);
std::getline(fs, temp->address);
fs >> temp->phoneNo;
if (!fs) {
// Reading failed, delete the temporary and exit the loop
delete temp;
break;
}
std::getline(fs, dummy);
recordCount++;
if(head == NULL){
head = temp;
previous = temp;
tail = temp;
} else {
previous->next = temp;
previous = temp;
tail = temp;
}
}
Your code could be made memory leak safer by using smart pointers to ensure temp
is never leaked even if exceptions are thrown.
How to go back to the beginning of a file after reaching .eof() in C++?
OK, it works. The trick is call
file.clear();
file.seekg(0, ios::beg);
just after the iteration. Sorry :(
What's actually happens when we try to extract line in file after which `eof` character is present with istream::getline() and std::getline()
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:
- You extract the last string. This sets eofbit, but not failbit
- You getline again
- getline constructs a sentry
- The sentry checks
is.good()
. This is false because eofbit is set - The sentry sets the failbit and sets its member ok_ to false
- The getline function checks if the sentry is true (operator bool). This is false
- The getline function returns before clearing your old string
Section 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.
Using getline() with file input in C++
getline
, as it name states, read a whole line, or at least till a delimiter that can be specified.
So the answer is "no", getline
does not match your need.
But you can do something like:
inFile >> first_name >> last_name >> age;
name = first_name + " " + last_name;
C++ - std::getline() returns nothing
You don't need to invoke file.open(filename);
because you already opened the file using the constructor std::ifstream file(filename);
.
Invoking file.open(filename);
after opening the file using the constructor causes the stream to enter an error state, because the file has not been closed yet.
See The difference between using fstream constructor and open function.
Related Topics
Std::Shared_Ptr Initialization: Make_Shared<Foo>() VS Shared_Ptr<T>(New Foo)
Why Does the Standard Differentiate Between Direct-List-Initialization and Copy-List-Initialization
The Implementation of Std::Forward
Generating M Distinct Random Numbers in the Range [0..N-1]
Assignment Operator Inheritance
In C++, How to Forward Declare a Class as Inheriting from Another Class
Is It Legal to Declare a Constexpr Initializer_List Object
What Is the Meaning of Numeric_Limits<Double>::Digits10
Explanation of Function Pointers
How to Export Templated Classes from a Dll Without Explicit Specification
Undefined Behaviour Somewhere in Boost::Spirit::Qi::Phrase_Parse
What's the Point of G++ -Wreorder
Cycles in Family Tree Software
Building Qt5 with Visual Studio 2012/Visual Studio 2013, and Integrating with the Ide