void reverse_output(string s, fstream& file, streamoff initial_pos)
{
const char* a = s.c_str();
file.seekp(initial_pos, ios::beg);
for (int i = s.length() - 1; i >= 0; i--)
{
file.put(a[i]);
}
}
int main()
{
string file_name = "E:\\WorkSpace\\ConsoleApplication2\\Debug\\2.txt";
fstream file;
file.open(file_name.c_str());
string row;
streamoff pos = 0;
while (getline(file, row))
{
reverse_output(row, file, pos);
file.put('\n');
pos = file.tellp();
file.seekg(pos, ios::beg);
}
file.close();
return 0;
}
I want to write a program which reverse each row of a file.
Say a file which contains:
123456
qwe
will be converted to the same file contains:
654321
ewq
I have written the above codes but they won't work for the last row. I suspect
while (getline(file, row))
is the main reason. Who could help me and tell me the real reason?
Your use of while (std::getline(file, row))
is OK. Your issue is that the last line of your file doesn't contain a newline! When reading the last line, its end is determined by touching the end of the file. When the stream touches the end of the file, the flag std::ios_base::eofbit
gets set, i.e., file.eof()
yields true
.
The next operation you do is trying to seek the stream using file.seekp(...)
. The call to seekp()
creates a std::ostream::sentry
on the file which will convert to false
when file.good()
is false
. Having std::ios_base::eofbit
set causes file.good()
to be false
. When the sentry
object converts to false
the seek operation fails and std::ios_base::failbit
gets set.
The easiest fix to the problem is to reset std::ios_base::eofbit
at the start of the while
-loop:
while (getline(file, row))
{
file.clear();
// ...
}
Since the stream returned from std::getline()
converted to true
, only std::ios_base::eofbit
can be set anyway: if either std::ios_base::failbit
or std::ios_base::badbit
had been set, the stream would convert to false
.