what does std::endl represent exactly on each platform? - c++

Thinking about UNIX, Windows and Mac and an output stream (both binary and text),
What does std::endl represent, i.e. <CR><LF>, <LF> or <CR>? Or is it always the same no matter what platform/compiler?
The reason I'm asking is that I'm writing a TCP client that talks a protocol that expects each command to end in <CR><LF>. So I'm wondering whether to use std::endl or "\r\n" in my streams.
EDIT: Ok, so one flushes the buffer and another doesn't. I get that. But if I'm outputting text to a file, is '\n' equal to <LF> or does it convert to <CR><LF> on Windows and <LF> on Unix or not? I don't see a clear answer yet.

The code:
stream << std::endl;
// Is equivalent to:
stream << "\n" << std::flush;
So the question is what is "\n" mapped too.
On normal streams nothing happens. But for file streams (in text mode) then the "\n" gets mapped to the platfrom end of line sequence. Note: The read converts the platform end of line sequence back to a '\n' when it reads from a file in text mode.
So if you are using a normal stream nothing happens. If you are using a file stream, just make sure it is opened in binary mode so that no conversion is applied:
stream << "\r\n"; // <CR><LF>

The C++ standard says that it:
Calls os.put(os.widen(ā€™\nā€™) ), then
os.flush()
What the '\n' is converted to, if it is converted at all, is down to the stream type it is used on, plus any possible mode the stream may be opened in.

Use stream << "\r\n" (and open the stream in binary mode). stream << std::endl; is equivalent to stream << "\n" << flush;. The "\n" might be converted to a "\r\n" if the code runs on Windows, but you can't count on it -- at least one Windows compiler converts it to "\n\r". On a Mac, it's likely to be converted to "\r" and on Unix/Linux and most similar systems, it'll be left as just a "\n".

Quoted from the accepted answer on a related question:
The varying line-ending characters don't matter, assuming the file is open in text mode, which is what you get unless you ask for binary. The compiled program will write out the correct thing for the system compiled for.
The only difference is that std::endl flushes the output buffer, and '\n' doesn't. If you don't want the buffer flushed frequently, use '\n'. If you do (for example, if you want to get all the output, and the program is unstable), use std::endl
In your case, since you specifically want <CR><LF>, you should explicitly use \r\n, and then call std::flush() if you still want to flush the output buffer.

Looks like your question got munged. Each command ends in []? For an over-the-wire protocol, I'd suggest using a delimiter that doesn't vary by platform. std::endl could resolve to '\r\n' or '\n\r' depending on the platform.

Related

C++ newline fails diff test?

So I have a two programs that I am comparing output to. Whenever it does a newline, it says my output is different using a diff utility.
I have tried using:
std::cout << endl;
and
std::cout << '\n';
but it winmerge still says that our output is different. I am running both executables on the same machine.
Streaming std::endl is equivalent to streaming '\n' then std::flush so, no, you won't see any differences. More likely your tool is expecting to find a Windows-style line ending (that is, CRLF rather than just LF).
std::cout << "\r\n" << std::flush;
But, instead of guessing, you should simply open up that comparison data in a hex editor and see for yourself what characters are expected.
Read the file in binary mode and check the byte values for the newline.
One will probably be a char with ASCII code 10
and the other will be 10 and 13.

Code works only with endl - very strange

I encountered a strange problem earlier. I was working at insertion in B-trees and I wrote a simple display function. I ran it and it didn't show anything in the console even though I inserted some values.
I entered in the debug mode, I followed the flow of the program and the debugger showed me that the tree had values in it. Then I wanted to display only the first node's elements and I had the same problem: an empty console.
I asked my teacher what would be the mistake and he told me to put an endl after cout, like this:
cout << node->keys[i] << endl;
It worked!
He told me then that probably I addressed a NULL pointer in my program and Eclipse doesn't say anything about that but nothing about how endl could help.
Does anybody know what could be the problem and how that endl solves it? I'm very very confused.
I didn't understand what flushing the buffer has to do with my display function.
I'm a bit late to answer and how to flush has been explained by the other answers already so I wanna answer your comment on Johnsy's answer at least.
First the reason that output is buffered is that writing the data to some output stream and not in the memory is usually a really slow operation (this ofc depends if you wanna write to a file on a ssd or hdd or just to the display but they all are way slower than the ram).
So c++ writes it to an internal buffer first and only actually writes to the output when the buffer is full or you flush the stream. It does so to avoid the slow operation of writing on most output streams.
So now why do you need to flush the buffer before it gets displayed...
Like already said it only actually writes it out for you to see when the buffer is full or it gets explicitly flushed. Now when the program ends normally all streams get flushed automatically so what happens prolly is a crash of the Program (a crash won't flush the buffer) so your program quits w/o it ever displaying.
Since your program displays everything correctly when you add the endl I guess you're trying to output a node with a nullptrat the very end and crash just before returning from main. You could easily test that by adding std::cout << "end of the program" << std::endl; just before your returnin main and testing if it gets displayed.
std::endl flushes output stream....
cout is buffered, output will not be displayed immediately, they will be buffered, until the buffer overflows, then all buffered data will be displayed. If you want display the ouput sooner, flush it.
Inserts a endline character into the output sequence os and flushes it
as if by calling os.put(os.widen('\n')) followed by os.flush().[1]
You can use std::cout.flush(); too.
std::endl inserts a endline character into the output sequence (os, in your case cout) and flushes it as if by calling os.put(os.widen('\n')) followed by os.flush().
std::cout controls output to a stream buffer of implementation-defined type (derived from std::streambuf), associated with the standard C output stream stdout. This output is buffered (unlike std::cerr)
Before you put endl into your source code, your buffer was not being flushed and the output was not appearing on your screen.
std::endl not only appends a newline character to the output stream, but also causes it to be flushed. I'm not quite sure how large the buffer on std::cout is, but it is possible that you're not seeing anything because the buffer is not full and thus does not get flushed. You could try to call cout.flush(); after appending your data (without appending std::endl) and see if that solves the problem.
As M M has mentioned in his answer as have others above, the std::endl flushes output stream. What it means is to display or put the results/output to the standard output source immediately/real time.
Using '\n' instead of std::endl will also result in similar output but may not be displayed immediately if some operation is still going on.
The common down side of std::endl is considered to be degradation of performance, though it may not be of significance if the output is streamed to a display instead of a file - where the '\n' is the preferred method.
Hope this helps.

strange eof flags in stream

I have encountered a strange problem when parsing text file using c++ file stream. Here is the code:
while (true)
{
std::getline(inFile, line);
if (!inFile.good())
{
std::cout << "Fail, bad and eof flags:" << inFile.fail() << inFile.bad() << inFile.eof() << std::endl;
break;
}
parseLine(line);
}
When the read terminates, the output is:
Fail, bad and eof flags:001
But actually the reader does not reach the end of file. I open the file and find that the next character is actually 26 (ASCII code). Then the problem is: 1) why the eof flag is set when reading this character, and how to avoid this kind of false termination? and 2) how to recover from this state? Thanks!
PS: thanks the replies. What if I read the file in binary mode? Any better solution? I use the Windows platform but the file seems to be an unix file.
why the eof flag is set when reading this character
Because it's the EOF marker character.
From Wikipedia:
In Microsoft's DOS and Windows (and in CP/M and many DEC operating
systems), reading from the terminal will never produce an EOF.
Instead, programs recognize that the source is a terminal (or other
"character device") and interpret a given reserved character or
sequence as an end-of-file indicator; most commonly this is an ASCII
Control-Z, code 26.
how to avoid this kind of false termination
It's not a "false" termination.
how to recover from this state?
You don't need to.
If you were trying to read a "binary file" where arbitrary characters would be expected, you would open your file stream in binary mode.
The ASCII character 26 is the SUB control character, which in caret notation is ^Z. This might be recognizable to you as the Windows end of file character. So assuming ASCII and Windows, there you go.
Here you go:
Getline and 16h (26d) character
Looks like you have to write your own getline function. Seems there is no way around it :p That I know of, and it seems no one else knows. If anyone knows a better way, chime in.

Rewinding std::cout to go back to the beginning of a line

I'm writing a command-line tool for Mac OS X that processes a bunch of files. I would like to show the user the current file being processed, but do not want a bazillion files polluting the terminal window.
Instead I would like to use a single line to output the file path, then reuse that line for the next file. Is there a character (or some other code) to output to std::cout to accomplish this?
Also, if I wanted to re-target this tool for Windows, would the solution be the same for both platforms?
"\r" should work for both windows and Mac OS X.
Something like:
std::cout << "will not see this\rwill see this" << std::flush;
std::cout << std::endl; // all done
I don't have access to a mac, but from a pure console standpoint, this is going to be largely dependent on how it treats the carriage return and line-feed characters. If you can literally send one or the other to the console, you want to send just a carriage return.
I'm pretty sure Mac treats both carriage returns and line-feeds differently than *nix & windows.
If you're looking for in-place updates (e.g. overwrite the current line), I'd recommend looking at the curses lib. This should provide a platform independent means of doing what you're looking for. (because, even using standard C++, there is no platform independent means of what you're asking for).
As Nathan Ernst's answer says, if you want a robust, proper way to do this, use curses - specifically ncurses.
If you want a low-effort hackish way that tends to work, carry on...
Command-line terminals for Linux, UNIX, MacOS, Windows etc. tend to support a small set of basic ASCII control characters, including character 13 decimal - known as a Carriage Return and encoded in C++ as '\r' or equivalently in octal '\015' or hex '\x0D' - instructing the terminal to return to the start of the line.
What you generally want to do is...
int line_width = getenv("COLUMNS") ? atoi(getenv("COLUMNS")) : 80;
std::string spaces{line_width - 1, ' '};
for (const auto& filename : filenames) {
std::cout << '\r' << spaces << '\r' << filename << std::flush;
process_file(filename);
}
std::cout << std::endl; // move past last filename...
This uses a string of spaces to overwrite the old filename before writing the next one, so if you have a shorter filename you don't see trailing characters from the earlier longer filename(s).
The std::flush ensures the C++ program calls the OS write() function to send the text to the terminal before starting to process the file. Without that, the text needed for the update - \r, spaces, \r and a filename - will be appended to a buffer and only written to the OS - in e.g. 4k chunks - when the buffer is full, so the filename displayed would lag dozens of files behind the actual file being processing. Further, say the buffer is 4k - 4096 bytes - and at some point you have 4080 bytes buffered, then output text for the next filename: you'll end up with \r and 15 spaces fitting in the buffer, which when auto-flushed will end up wiping out the first 15 characters on the line on-screen and leaving the rest of the previous filename (if it was longer than 15 characters), then waiting until the buffer is full again before updating the screen (still haphazardly).
The final std::endl just moves the cursor on from the line where you've been printing filenames so you can write "all done", or just leave main() and have the shell prompt display on a nice clean line, instead of potentially overwriting part of your last filename (great shells like zsh check for this).

Problem with iostream, my output endl are littles squares

I have a problem with with my output when I write to I file I get squares when I put endl to change lines.
std::ofstream outfile (a_szFilename, std::ofstream::binary);
outfile<<"["<<TEST<<"]"<<std::endl;
I get something like this in my file plus the other outputs don't write on the next line but on the same one.
[TEST]square
apparently I can't write the square here, but is it something about the ofstream being binary or something?
You don't really want to open the file in binary mode in this case.
Try this instead:
std::ofstream outfile (a_szFilename);
outfile<<"["<<TEST<<"]"<<std::endl;
You're opening the file in binary mode. in this case the endl is written as \n while a newline on windows is supposed to be \r\n
To open you file in text mode just don't include the binary flag the translation will be done automatically
std::ofstream outfile(a_szFilename);
outfile<<"["<<TEST<<"]"<<std::endl;
It's probably because you're in binary mode and the line endings are wrong. std::endl will place '\n' on the stream before flushing. In text mode, this will be converted to the correct line ending for your platform. In binary mode, no such conversions take place.
If you're on Windows, your code will have a line feed (LF), but Windows also requires a carriage return (CF) first, which is '\r'. That is, it wants "\r\n", not just a newline.
Your fix is to open the file in text mode. Binary files are not suppose to be outputting newlines or formatted output, which is why you don't want to use the extraction and insertion operators.
If you really want to use binary, then treat your file like a binary file and don't expect it to display properly. Binary and formatted output do not go hand in hand. From your usage, it seems you should be opening in text mode.