3
#include <iostream>
using namespace std;
int main( int argc, char *argv[])
{
    cout << "Hello\nWorld";
}

D:\test>hw |od -c
0000000   H   e   l   l   o  \r  \n   W   o   r   l   d
0000014

Why additional \r is injected in windows(doesn't happen on linux) ?

DriverBoy
  • 937
  • 1
  • 11
  • 23

3 Answers3

7

It is a feature of Windows going back to the first days of MS-DOS. In those systems, the convention is that a line delimiter is the character pair "\r\n". Of course, in Linux/Unix/Solaris/etc., the line delimiter is the single character "\n"

There are various utilities, such as Linux's dos2unix and unix2dos which do nothing but this transformation. Virtually every file transfer program has a means of dealing with it too. See kermit's mode command.

The convention affected the MSDOS/windows C runtime library function fopen() (among others): the second parameter can have a b or t to explicitly set the line delimiter conversion. A text conversion transforms \r\n to \n on input and \n to \r\n on output. A binary conversion does no such transformation.

FILE *f1 = fopen ("somefile.txt", "rt");  /* open in text conversion mode */
FILE *f2 = fopen ("anotherfile.bin", "rb");  /* open without text conversion */
wallyk
  • 56,922
  • 16
  • 83
  • 148
  • @wallyk,isn't cout supposed to output exactly what I told it ? – DriverBoy May 26 '11 at 06:00
  • I am quite sure there should be a compiler option for MS C++ compiler instructing it how to treat the "\n" - either as the LF character or as end-of-line sequence of CR+LF – davka May 26 '11 at 06:00
  • @DriverBoy: It *is* doing what you told it: you asked for a line delimiter, and that's what you got. – wallyk May 26 '11 at 06:01
  • @wallyk,I asked for a `\n` but it gives me `\r\n`. – DriverBoy May 26 '11 at 06:02
  • @DriverBoy: no you asked for a newline which, within `C`'s view of the world, is a line delimiter. When C within Windows talks to the filesystem, etc., it must convert to the convention of the operating system. (For example, in OpenVMS, the conversion is truly wicked since files are managed by a record management system: lines consume at least two bytes more space than Unix programmers expect.) According to the answer for http://stackoverflow.com/questions/5654067/how-to-make-cout-behave-as-in-binary-mode there is no way to change `cout` to binary mode. – wallyk May 26 '11 at 06:09
  • @davka ,I didn't use any compiler option when compiling the code above. – DriverBoy May 26 '11 at 06:12
  • @DirverBoy I know, the behavior you show should be a default on Windows. I assume/hope that should be a compiler switch for MSVC to tell it to behave in a C++ compliant way. – davka May 26 '11 at 06:18
  • 1
    @DriverBoy @Davka - This **is** the C++ compliant way! Printing `'\n'` in text mode is asking for a line break. Some systems just store the '\n', others store a '\r\n' or just a '\r'. Still others record the line length, and just store the other characters. In C and C++, printing '\n' works on all these systems. That is the standard! – Bo Persson May 26 '11 at 07:06
  • 1
    @davka: This is compliant behavior. You already have the option of turning off the transformation from within your program, so a compiler flag is quite unnecessary. – Dennis Zickefoose May 26 '11 at 07:21
  • @Bo, @Dennis - are you 100% sure? Stroustrup's CPL (C.3.2) defines `'\n'` as one of the **one-character** escapes and does not mention at all that this can be platform-dependent (and he usually does). @DriverBoy, anyway, I take back my "hope" for the compiler switch - the compiler should generate the code for the platform it is designed for. – davka May 26 '11 at 08:04
  • @davka - You are right that it is a one character escape, when used in a string in the program. However, when it is written to a file **opened in text mode**, it is translated to whatever the system considers a line break. If you open the file in binary mode, it is **not** translated. `std::cout` is obviously in text mode. – Bo Persson May 26 '11 at 09:43
  • @Bo, yes, realized this after my last comment - this is actually a library feature – davka May 26 '11 at 09:54
1

Because the output function is platform denpendent. in windows, all line break is \r\n, int constract, the linux/unix is \n

Chen Zhuo
  • 71
  • 5
  • it seems a bug of output functions in c/c++,this doesn't happen for other programing languages on windows. – DriverBoy May 26 '11 at 05:59
  • @DriverBoy, C/C++ is actually displaying the world in its right colours here. Many the other languages omits this problem from the programmers. – Tobias Wärre May 26 '11 at 06:02
  • A newline on Windows is \r\n. If your language doesn't do it for you then you must do it manually. Try filling a Win32 textarea without the \r and you'll see that it's all on one line with square boxes where the \n should be. It's not a bug at all. – Adam May 26 '11 at 06:09
  • @DriverBoy, it's not a bug but a platform depentdent implementation. c/c++ does little on your output and input while other language does plent, such as python or java. – Chen Zhuo May 26 '11 at 06:21
1

Windows, Unix and Mac all mark newlines differently.

Windows uses \r\n, Unix/Linux \n, Mac \r. Once you start dealing with text files on multiple platforms this becomes a real mess. This is why any serious text editor has an option to switch among them and why Linux has utilities like dos2unix. Try loading a Unix-style text file (with only \n) into Notepad. You'll notice it's all on one line.

Adam
  • 16,808
  • 7
  • 52
  • 98
  • @Adam,btw,I know `\n` means new line,which starts a new line,what about `\r`,what does it do exactly? – DriverBoy May 26 '11 at 06:01
  • This all harkens back to the day when you had dot-matrix printers that were just generic typewriters. \n means line feed (LF), i.e. move to the next line. \r means carriage return (CR), move the head to the beginning of the line. The lineage that Windows comes from had them move the head back first, then go to the next line. Unix assumed that a new line also meant a carriage return. – Adam May 26 '11 at 06:03
  • On Unix you can use \r to start over on the same line. You can make cheap progress counters this way. I.e. to have something count up in-place. – Adam May 26 '11 at 06:06
  • @Adam,by `Try loading a Unix-style text file (with only \n) into Notepad. You'll notice it's all on one line.`,so you mean a single `\n` without `\r` means nothing in windows,right? – DriverBoy May 26 '11 at 06:11
  • It's not nothing, to the Windows APIs a \n by itself is an unprintable character. Most Windows programs that read text will treat it as a newline, though. – Adam May 26 '11 at 06:14
  • 1
    Notepad is just a Win32 textarea and a menu. That's why it's susceptible to this. Any self-respecting text editor will handle it. I have little experience with Vista or newer notepads so they might have fixed this at last. – Adam May 26 '11 at 06:15