Are you sure that there is a new line character inside your file? Your "example" doesn't seem to show one.
What happens if reading the stream fails for some reason before you encounter the new line character?
Did you try printing C inside the loop, or run the program in your debugger to try to "see" what is actually happening?
Also your function should be using an istream& not an ifstream&, then you can use any input stream not just an ifstream. You probably should be returning the stream if you're really trying to mimic std::getline().
read should take an istream not an ifstream since it's not using any of the extra ifstream methods (like open or close).
You should use the get method instead of operator>> since you obviously don't want to skip whitespace, otherwise you will never see a newline.
Assigning a null char to buffer is just weird. '\0' is not generally special to std::string. You're thinking of C-style strings. To ensure the string is empty, use its clear method.
Returning the stream is handy for checking for eof.
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16
#include <iostream>
#include <string>
std::istream& read(std::istream& in, std::string& line)
{
line.clear();
for (char c; in.get(c) && c != '\n'; ) line += c;
return in;
}
int main()
{
std::string s;
read(std::cin, s);
std::cout << s << '\n';
}
Actually the function could really be better, in one way:
It only reads a line if it ends with '\n' which is ok, but
you have to input a newline after the last line all the time...
This can get annoying. Any suggestions as to how I can
improve this? Other than that the function works great.
#include <iostream>
#include <fstream>
#include <string>
std::istream& read(std::istream& in, std::string& line)
{
line.clear();
for (char c; in.get(c) && c != '\n'; ) line += c;
return in;
}
int main()
{
std::ifstream in("file.txt");
std::string s;
// This should read and print the whole file
while (read(in, s))
std::cout << s << '\n';
}
1. Hello, world!
2. Another line printed. (1)
3. Another line printed. (2)
3 lines. No new line character after third line.
To make it print
Hello, world!
Another line printed. (1)
Another line printed. (2)
I would have to edit the file to look like this:
1. Hello, world!
2. Another line printed. (1)
3. Another line printed. (2)
4.
In other words, a newline character has to be after the last line.
Otherwise, it would print only the first 2 lines. I don't really know
why. The code looks like it should work perfectly.
You're right. The problem is that if it hits the eof after it's read some chars into line it still returns "in" in the eof state which causes our loop to stop. So if the line is not empty it should return "in" in the clear state, even if it's hit eof. Let it detect eof the next time read is called.
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19
#include <iostream>
#include <fstream>
#include <string>
std::istream& read(std::istream& in, std::string& line)
{
line.clear();
for (char c; in.get(c) && c != '\n'; ) line += c;
if (in.eof() && line.size()) in.clear();
return in;
}
int main()
{
std::ifstream in("file.txt");
std::string s;
while (read(in, s))
std::cout << s << '\n';
}
Note that "clear" for a string means to empty the string, but "clear" for a stream means to clear the state flags.
> Also, I was trying to make a custom version of the function, "std::getline(std::ifstream, std::string)"
This is slightly tricky because of the requirement:
Behaves as UnformattedInputFunction, except that input.gcount() is not affected. https://en.cppreference.com/w/cpp/string/basic_string/getline
(I guess the standard specifies that gcount() is not affected to make the operation more efficient)