Changing std::endl to put out CR+LF instead of LF - c++

I'm writing a program on a Linux platform that is generating text files that will be viewed on, inevitably, a Windows platform.
Right now, passing std::endl into a ostream generates the CR character only for newlines. Naturally, these text files look wrong in MS Notepad.
Is there a way to change std::endl such that it uses CR+LF for newline instead of LF?
I know I could write my own custom manipulator, like win_endl, for generating my own newlines, but I use the std::endl symbol in a lot of places, and like many programmers, have a tendency to do the thing that requires the least work possible. Could I simply overload std::endl to produce CR+LF, or is this a dumb idea for maintainability?
NB: I checked out this question, but it's asking about going the other way, and the accepted answer seems rather incomplete.

std::endl is basicly:
std::cout << "\n" << std::flush;
So just use "\r\n" instead and omit the flush. It's faster that way, too!
From the ostream header file on endl:
This manipulator is often mistakenly used when a simple newline is desired, leading to poor buffering performance.

Opening a file in text mode should cause std::endl to be converted to the appropriate line ending for your platform. Your problem is that newline is appropriate for your platform, but the files you create aren't intended for your platform.
I'm not sure how you plan on overloading or changing endl, and changing its behavior would certainly be surprising for any developers new to your project. I'd recommend switching to win_endl (should be a simple search-and-replace) or maybe switching from a standard ostream to a Boost.Iostreams filtering stream to do the conversion for you.

Windows Notepad is pretty much the only Windows program you'll find that doesn't handle LF-only files properly. Almost everything else (including WordPad) handles LF-only files just fine.
This problem is a bug in Notepad.

You shouldn't use \r\n. Just use \n, but then open the stream in "text" mode, which than will do the conversion for you. You may not care about cross-platform, but this is the official way of doing it.
That way, the same code will spit-out \n on unix, \r\n on windows, and \r on mac.

Here was my solution to the problem. It's a bit of a mash-up of all the info provided in the answers:
I created a macro in a win_endl.h file for the newline I wanted:
#define win_endl "\r\n"
Then I did a search-and-replace:
sheepsimulator#sheep\_machine > sed -i 's/std::endl/win_endl' *
And ensured all my files included win_endl.h.

Related

C++ Control When cout Flushes

As the title suggests, I'm looking for a way to have cout 'flush' itself only when I explicitly tell it to. I know this can be achieved by 'buffering' the contents we want to write into a string or a stringstream, but I'm looking for the most efficient way of doing this.
Also it would be nice to also be able to eat up trailing newlines in this buffer. I've seen solutions that writes \b to cout; however I'm pretty sure this is unreliable due to flushing (correct me if I'm wrong).
Without using stringstream, your best bet it so prevent the two most common ways that lead to an automatic flush: when you are outputting something and when you explicitly call << std::endl. You can deactivate the first by setting the unitbuf flag of std::ios_base::fmtflags. This, though, won't likely stop the automatic flush when a new line is encountered. If your OS decides it needs to flush at every \n character, there's nothing you can do (on the standard C++ side).
Therefore I'd recommend manual buffering.

How can I add a ಠ symbol into my C++ output

I am writing a program for school, and want to include an Easter Egg with the look of disapproval (ಠ_ಠ), however, I do not know what classes in C++ support this character. I would assume this character be included in unicode, but I am not sure how to use that to output into a console application.
If anyone could help me out with this, I would appreciate it. Thanks
Well you need to enable Unicode for your application.
For MSVC you can use _setmode(_fileno(stdout), _O_U16TEXT); at the start of your main.
But for mingw this is a bit more difficult, see here.
To actually print it you can use the character code and use wcout but be wary!
From: http://www.cplusplus.com/reference/iostream/cout/
A program should not mix output operations on cout with output operations on wcout (or with other wide-oriented output operations on stdout): Once an output operation has been performed on either, the standard output stream acquires an orientation (either narrow or wide) that can only be safely changed by calling freopen on stdout.
You can use \u0CA0, that's the Unicode code for this eye thing. Here's a live example:
int main() {
cout << "hi \u0CA0_\u0CA0";
return 0;
}
https://ideone.com/QBFtsM
Although IDEOne supports unicode (as in, I can just paste ಠ) so I'm not sure if that will work for you. Let me know.

Filename with an extra ":" or a "-" c++

I want to create a filename with characters like ":","-".
i tried the following code to append the date and time to my filename.
Str.Format(_T("%d-%d-%d-%d:%d:%d.log"),systemTime.wDay ,systemTime.wMonth ,systemTime.wYear,systemTime.wHour,systemTime.wMinute,systemTime.wSecond);
std::wstring NewName=filename.c_str() + Str;
MoveFileEx(oldFilename.c_str(), NewName.c_str(), 2 )
MoveFileEx fails with windows ErrorCode 123(ERROR_INVALID_NAME).So i think the issue is with my new Filename which contain ":" and "-"
Thanks,
Indeed, you cannot use the : character in windows file names. Replace it with something else. If a program depends on the name then modify it to interpret the alternative delimiter.
"I want to create..." No you don't. Different systems impose different constraints on what is legal in a filename. Most modern systems do allows fairly long names (say more than a 100 characters), and don't impose a format on them (although Windows does still handle anything after the last ., if there is one, specially, so you want to be careful there). If you're not concerned about portability, you can simply follow the rules of the system you're on: under Unix, no '/' or '\0' (but I'd also avoid anything a Unix shell would consider a meta-character: anything in ()[]{}<>!$|?*" \ and the backtick, at least), and I'd avoid starting a filename with a '-'. Windows formally forbids anything in <>:"/\|?*; here to, I'd avoid anything other programs might consider special (including using two %, which could be interpreted as a shell variable), and I'd also be careful that if there was a ., the final .something was meaningful to the system. (If the filename already ends with something like .log, there's no problem with additional dots before that.)
In most cases, it's probably best to be conservative; you never know what system you'll be using in the future. In my own work (having been burned by creating a filename witha a colon under Linux, and not being able to even delete it later under Windows), I've pretty much adopted the rule of only allowing '-', '_' and the alphanumeric characters (and forbidding filenames which differ only in case—more than a few people I know will only use lower case for letters). That's far more restrictive than just Unix and Windows, but who knows what the future holds. (It's also too liberal for some of the systems I've worked on in the past. These are hopefully gone for good, however.)
Windows does not allow few special character for creating as a file name.
But, for creating file name using current date and time you can use this formatting.
CTime CurrentTime( CTime::GetCurrentTime() );
SampleFileName = CurrentTime.Format( _T( " %m_%d_%y %I_%M_%S" ) ) + fileExtension;
For more time formating, Please refer this

what determines what bytes are output from std::endl

I have a large code base that uses std::cout to generate its output, and it uses std::endl all over the place to generate its newlines. This program seems to generate only linefeeds for the endl, which isn't a huge problem in itself, but for whatever reason, wasn't what I had expected.
So as a reality check, I built a simple program to pump endl's into cout, compiled it with the same compiler and examined the output from that. That program emits both CR and LF for endl.
It doesn't look like the large program plays any games with cout to change the way endl works, at least not that I can recognize, so it seems strange that it should behave differently than the small program. It seems as though the large program must be doing something to change the defaults. What am I missing here?
Both programs were compiled using MinGW gcc 4.5.2 on 32bit windows.
To add to Tomalak Geret'kal's answer: the fact that endl expands to the platform-specific endline is a popular misconception.
Inside a C/C++ application the only "official" newline (at least, as far as streams and stream-related functions are concerned) is '\n'. The translation from '\n' to the platform-specific newline is done inside the streams1 when they are opened in text mode (i.e. without the ios::bin flag).
endl, instead, is used to force a stream flush after the '\n'; this can be useful for console output, but (1) often this is not the case (cout is automatically flushed when input is requested from cin via the tied-stream mechanism) and only wastes CPU time, and (2) you often find it used also on file streams, where it is almost never useful, and results in poor file writing performance.
As discussed in the comments, as far as the standard is concerned the translation could actually happen at any level below the stream (e.g. the stream may translate the presence/absence of ios::bin into a flag for the underlying OS file management functions, and it would be responsibility of the OS to do the translation); in reality, mainstream OSes do not have particular flags for this kind of translation, mainly because their file APIs are content-agnostic (you tell them what to write, they write it without modifications).
std::endl is defined by the C++ Standard to perform the following:
Stream a '\n' character;
Stream the std::flush I/O manipulator.
If you're seeing carriage returns at the other end of the stream, then that's occurring at the file interface (and not in the stream functionality itself); in particular, on Windows, you can expect "\n" to be translated transparently to "\r\n" during text-mode output to files.
So, check that your files are both being opened in text- or binary- mode respectively. There is nothing else in C++ that could affect this behaviour.
This FAQ entry pretty much covers what I just said, too.
When a file is opened in "TEXT" Mode (the default when you create file streams).
The '\n' character is converted into a platform specific "end of line sequence" when you write it to a file. Conversely the "end of line sequence" is converted into a '\n' when you read from the file.
Note if you open a file in "BINARY" Mode this conversion does not happen.
In relation to std::endl
stream << std::endl
Is equivalent to:
stream << '\n' << std::flush;
Thus if your stream is a std::fstream (that was opened normally) then '\n' character will be converted into "end of line sequence" which on some platforms is '\r\n'

Portable end of line

is there any way to automatically use correct EOL character depending on the OS used?
I was thinking of something like std::eol?
I know that it is very easy to use preprocessor directives but curious if that is already available.
What I am interested in is that I usually have some messages in my applications that I combine later into a single string and I want to have them separated with a EOL. I know that I could use std::stringstream << endl but it seems to be an overkill sometimes instead of a regular append.
std::endl is defined to do nothing besides write '\n' to the stream and flush it (§27.6.2.7). Flushing is defined to do nothing for a stringstream, so you're left with a pretty way of saying mystringstream << '\n'. The standard library implementation on your OS converts \n appropriately, so that's not your concern.
Thus endl is already the ultimate in performance and portability, and the only other thing you could want is << '\n' if you are trying to efficiently write to a file (not a stringstream). Well, << '\n' does also eliminate the pointless virtual call to stringbuf::flush. Unless profiling shows that empty function call to be taking time, don't think about it.
If you want to write a line separator to a stream:
std::cout << '\n';
or
std::cout << "\n";
or
std::cout << "whatever you were going to say anyway\n";
If the stream is text mode and the OS uses anything other than LF as a separator, it will be converted.
If you want to write a line separator and flush the stream:
std::cout << std::endl;
If you have binary-mode output for whatever reason, and you want to write a platform-specific line break, then I think you might have to do it indirectly (write '\n' to a text stream and then examine it in binary mode to see what you get). Possibly there's some way to directly get the line break sequence from the implementation, that I'm not aware of. It's not a great idea, anyway: if you're writing or reading a file in binary mode then it should be in a format which defines line breaks independently of the OS, or which doesn't have lines at all. That's what binary mode is for.
Just open a file in text mode
FILE *fp = fopen( "your_file.txt", "w+t" );
and then
fprintf( fp, "some string and integer %d\n", i );
fclose(fp);
and the OS will take care of the EOL accordingly to its standards.
Well, the STL has std::endl, which you can use as
std::cout << "Hi five!" << std::endl;
Note that besides adding an endline, std::endl also flushes the buffer, which may have undesirable performance consequences.
Files, even text files, are often transferred between machines, so "os-specific new line character" is an oxymoron.
It is though true that operating systems have a say on that matter, particularly one operating systems aka Windows, although many windows programs will read \n-spaced files correctly, even though the winapi multiline edit control would not. I suggest you consider twice what is the right for you: it's not necessarily what your OS recommends. If your files are ever to be stored on removable media, do not use OS standard. Use global standard, 0xA.