Why use trailing newlines instead of leading with printf?
up vote
36
down vote
favorite
I heard that you should avoid leading newlines when using printf
. So that instead of printf("nHello World!")
you should use printf("Hello World!n")
In this particular example it does not make sense, since the output would be different, but consider this:
printf("Initializing");
init();
printf("nProcessing");
process_data();
printf("nExiting");
compared to:
printf("Initializingn");
init();
printf("Processingn");
process_data();
printf("Exiting");
I cannot see any benefit with trailing newlines, except that it looks better. Is there any other reason?
EDIT:
I'll address the close votes here and now. I don't think this belong to Stack overflow, because this question is mainly about design. I would also say that although it may be opinions to this matter, Kilian Foth's answer and cmaster's answer proves that there are indeed very objective benefits with one approach.
c
|
show 8 more comments
up vote
36
down vote
favorite
I heard that you should avoid leading newlines when using printf
. So that instead of printf("nHello World!")
you should use printf("Hello World!n")
In this particular example it does not make sense, since the output would be different, but consider this:
printf("Initializing");
init();
printf("nProcessing");
process_data();
printf("nExiting");
compared to:
printf("Initializingn");
init();
printf("Processingn");
process_data();
printf("Exiting");
I cannot see any benefit with trailing newlines, except that it looks better. Is there any other reason?
EDIT:
I'll address the close votes here and now. I don't think this belong to Stack overflow, because this question is mainly about design. I would also say that although it may be opinions to this matter, Kilian Foth's answer and cmaster's answer proves that there are indeed very objective benefits with one approach.
c
3
This question is on the border between "issues with code" (which is off-topic) and "conceptual software design" (which is on-topic). It may get closed, but don't take it too hard. I think adding concrete code examples was the right choice nevertheless.
– Kilian Foth
yesterday
23
The last line would merge with the command prompt on linux without a trailing newline.
– GrandmasterB
yesterday
2
If it "looks better" and it has no downside, that's a good enough reason to do it, IMO. Writing good code is no different to writing a good novel or a good technical paper - the devil is always in the detail.
– alephzero
yesterday
5
Doinit()
andprocess_data()
print anything themselves? What would you expect the result to look like if they did?
– Bergi
yesterday
2
n
is a line terminator, not a line separator. This is evidenced by the fact that text files, on UNIX, almost always end inn
.
– Jonathon Reinhart
8 hours ago
|
show 8 more comments
up vote
36
down vote
favorite
up vote
36
down vote
favorite
I heard that you should avoid leading newlines when using printf
. So that instead of printf("nHello World!")
you should use printf("Hello World!n")
In this particular example it does not make sense, since the output would be different, but consider this:
printf("Initializing");
init();
printf("nProcessing");
process_data();
printf("nExiting");
compared to:
printf("Initializingn");
init();
printf("Processingn");
process_data();
printf("Exiting");
I cannot see any benefit with trailing newlines, except that it looks better. Is there any other reason?
EDIT:
I'll address the close votes here and now. I don't think this belong to Stack overflow, because this question is mainly about design. I would also say that although it may be opinions to this matter, Kilian Foth's answer and cmaster's answer proves that there are indeed very objective benefits with one approach.
c
I heard that you should avoid leading newlines when using printf
. So that instead of printf("nHello World!")
you should use printf("Hello World!n")
In this particular example it does not make sense, since the output would be different, but consider this:
printf("Initializing");
init();
printf("nProcessing");
process_data();
printf("nExiting");
compared to:
printf("Initializingn");
init();
printf("Processingn");
process_data();
printf("Exiting");
I cannot see any benefit with trailing newlines, except that it looks better. Is there any other reason?
EDIT:
I'll address the close votes here and now. I don't think this belong to Stack overflow, because this question is mainly about design. I would also say that although it may be opinions to this matter, Kilian Foth's answer and cmaster's answer proves that there are indeed very objective benefits with one approach.
c
c
edited 12 hours ago
asked yesterday
Broman
317311
317311
3
This question is on the border between "issues with code" (which is off-topic) and "conceptual software design" (which is on-topic). It may get closed, but don't take it too hard. I think adding concrete code examples was the right choice nevertheless.
– Kilian Foth
yesterday
23
The last line would merge with the command prompt on linux without a trailing newline.
– GrandmasterB
yesterday
2
If it "looks better" and it has no downside, that's a good enough reason to do it, IMO. Writing good code is no different to writing a good novel or a good technical paper - the devil is always in the detail.
– alephzero
yesterday
5
Doinit()
andprocess_data()
print anything themselves? What would you expect the result to look like if they did?
– Bergi
yesterday
2
n
is a line terminator, not a line separator. This is evidenced by the fact that text files, on UNIX, almost always end inn
.
– Jonathon Reinhart
8 hours ago
|
show 8 more comments
3
This question is on the border between "issues with code" (which is off-topic) and "conceptual software design" (which is on-topic). It may get closed, but don't take it too hard. I think adding concrete code examples was the right choice nevertheless.
– Kilian Foth
yesterday
23
The last line would merge with the command prompt on linux without a trailing newline.
– GrandmasterB
yesterday
2
If it "looks better" and it has no downside, that's a good enough reason to do it, IMO. Writing good code is no different to writing a good novel or a good technical paper - the devil is always in the detail.
– alephzero
yesterday
5
Doinit()
andprocess_data()
print anything themselves? What would you expect the result to look like if they did?
– Bergi
yesterday
2
n
is a line terminator, not a line separator. This is evidenced by the fact that text files, on UNIX, almost always end inn
.
– Jonathon Reinhart
8 hours ago
3
3
This question is on the border between "issues with code" (which is off-topic) and "conceptual software design" (which is on-topic). It may get closed, but don't take it too hard. I think adding concrete code examples was the right choice nevertheless.
– Kilian Foth
yesterday
This question is on the border between "issues with code" (which is off-topic) and "conceptual software design" (which is on-topic). It may get closed, but don't take it too hard. I think adding concrete code examples was the right choice nevertheless.
– Kilian Foth
yesterday
23
23
The last line would merge with the command prompt on linux without a trailing newline.
– GrandmasterB
yesterday
The last line would merge with the command prompt on linux without a trailing newline.
– GrandmasterB
yesterday
2
2
If it "looks better" and it has no downside, that's a good enough reason to do it, IMO. Writing good code is no different to writing a good novel or a good technical paper - the devil is always in the detail.
– alephzero
yesterday
If it "looks better" and it has no downside, that's a good enough reason to do it, IMO. Writing good code is no different to writing a good novel or a good technical paper - the devil is always in the detail.
– alephzero
yesterday
5
5
Do
init()
and process_data()
print anything themselves? What would you expect the result to look like if they did?– Bergi
yesterday
Do
init()
and process_data()
print anything themselves? What would you expect the result to look like if they did?– Bergi
yesterday
2
2
n
is a line terminator, not a line separator. This is evidenced by the fact that text files, on UNIX, almost always end in n
.– Jonathon Reinhart
8 hours ago
n
is a line terminator, not a line separator. This is evidenced by the fact that text files, on UNIX, almost always end in n
.– Jonathon Reinhart
8 hours ago
|
show 8 more comments
6 Answers
6
active
oldest
votes
up vote
133
down vote
accepted
A fair amount of terminal I/O is line-buffered, so by ending a message with n you can be certain that it will be displayed in a timely manner. With a leading n the message may or may not be displayed at once. Often, this would mean that each step displays the progress message of the previous step, which causes no end of confusion and wasted time when you try to understand a program's behaviour.
14
This is particularly important when using printf for debugging a program that crashes. Putting the newline at the end of a printf means that stdout to the console gets flushed at each printf. (Note that when stdout is redirected to a file, the std libraries will usually do block buffering instead of line buffering, so that makes printf debugging a crash quite hard even with newline at the end.)
– Erik Eidt
yesterday
16
@ErikEidt Note that you should usefprintf(STDERR, …)
instead, which is generally not buffered at all for diagnostic output.
– Deduplicator
yesterday
2
@Deduplicator Writing diagnostic messages to the error stream has its downsides as well - many scripts assume a program has failed if something is written to the error stream.
– Voo
yesterday
30
@Voo: I would argue that any program that assumes writes to stderr indicate a failure is itself incorrect. The exit code of the process is what indicates whether or not it failed. If it was a failure, then the stderr output will explain why. If the process exited successfully (exit code zero) then stderr output should be considered informational output for a human user, with no particular machine-parseable semantic (it might contain human-readable warnings, for example), while stdout is the actual output of the program, possibly suitable for further processing.
– Daniel Pryden
yesterday
13
@Voo: What programs are you describing? I'm not aware of any widely-used software package that behaves like you describe. I do know that there are programs that do, but it's not like I just made up the convention I describe above: that's the way the vast majority of programs in a Unix or Unix-like environment work, and to my knowledge, the way the vast majority of programs always have. I certainly wouldn't advocate for any program to avoid writing to stderr simply because some scripts don't handle it well.
– Daniel Pryden
yesterday
|
show 4 more comments
up vote
37
down vote
On POSIX systems (basically any linux, BSD, whatever open-source based system you can find), a line is defined to be a string of characters that's terminated by a newline n
. This is the basic assumption all the standard command line tools build upon, including (but not limited to) wc
, grep
, sed
, awk
, and vim
. This is also the reason why some editor (like vim
) always add a n
at the end of a file, and why earlier standards of C required headers to end with a n
character.
Btw: Having n
terminated lines makes processing of text much easier: You know for sure that you've got a complete line when you've got that terminator. And you know for sure that you need to look at more characters if you didn't encounter that terminator yet.
Of course, this is on the input side of programs, but program output is very often used as program input again. So, your output should stick to the convention for the sake of allowing seamless input into other programs.
16
This is one of the oldest debates in software engineering: is it better to use newlines (or, in a programming language, another "end of statement" marker like a semicolon) as line terminators or line separators? Both approaches have their pros and cons. The Windows world has mostly settled on the idea that the newline sequence (which is typically CR LF there) is a line separator, and thus the last line in a file doesn't need to end with it. In the Unix world, though, a newline sequence (LF) is a line terminator, and many programs are built around this assumption.
– Daniel Pryden
yesterday
18
POSIX even defines a line as "A sequence of zero or more non-newline characters plus a terminating newline character."
– pipe
yesterday
3
Given that as @pipe says, it's in the POSIX specification, we can probably call it de jure as opposed to de facto as the answer suggests?
– Baldrickk
yesterday
3
@Baldrickk Right. I have updated my answer to be more affirmative, now.
– cmaster
yesterday
add a comment |
up vote
11
down vote
Using trailing newlines simplifies later modifications.
As a (very trivial) example based on the OP's code, suppose you need to produce some output before the "Initializing" message, and that output comes from a different logical part of the code, in a different source file.
When you run the first test and find "Initializing" is now appended to the end of a line of some other output, you have to search through the code to find where it got printed, and then hope changing "Initializing" to "nInitializing" doesn't screw up the format of something else, in different circumstances.
Now consider how to are going to handle the fact that your new output is actually optional, so your change to "nInitializing" sometimes produces an unwanted blank line at the start of the output ...
Do you set a global (shock horror??!!!) flag saying whether there was any preceding output and test it to print "Initializing" with an optional leading "n", or do you output the "n" along with your earlier output and leave future code readers wondering why this "Initializing" doesn't have a leading "n" like all the other output messages do?
If you consistently output trailing newlines, at the point where you know you have reached the end of the line that needs to be terminated, you sidestep all those issues. Note, that might require a separate puts("n") statement at the end of some logic that outputs a line piece by piece, but the point is you output the newline at the earliest place in the code where you know you need to do it, not somewhere else.
New contributor
If every independent output item is supposed to appear on its own line, trailing new lines can work fine. If multiple items should be consolidated when practical, however, things get more complicated. If it's practical to feed all output through a common routine, an operation to insert a clear-to-end-of-line if the last character was a CR, nothing if the last character was a newline, and a newline if the last character was anything else, may be helpful if programs need to do something other than output a sequence of independent lines.
– supercat
6 hours ago
add a comment |
up vote
8
down vote
In addition to what other have mentioned, I feel like there is a much simpler reason: it's the standard. Whenever anything prints to STDOUT, it almost always assumes that it is already on a new line, and thus doesn't need to start a new one. It also assumes the next line to be written will act the same way, so it helpfully ends by starting a new line.
If you output leading-newline lines interleaved with standard trailing-newline lines," it will end up looking like this:
Trailing-newline-line
Trailing-newline-line
Leading-newline-line
Leading-newline-line
Leading-newline-lineTrailing-newline-line
Trailing-newline-line
Leading-newline-lineTrailing-newline-line
Trailing-newline-line
Trailing-newline-line
...which is presumably not what you want.
If you use only leading newlines in your code and only run it in an IDE, it may turn out okay. As soon as you run it in a terminal or introduce other people's code that will write to STDOUT alongside your code, you'll see undesirable output like above.
add a comment |
up vote
5
down vote
Since the highly up-voted answers have already given excellent technical reasons why trailing newlines should be preferred, I will approach it from another angle.
In my opinions, the followings make a program more readable:
- a high signal-to-noise ratio (aka simple but not simpler)
- important ideas come first
From the above points, we can argue that trailing newlines are better. Newlines are formatting "noise" when compared to the message, the message should stand out and thus should come first (syntax-highlighting can help too).
4
Yes,"okn"
is much better than"nok"
...
– cmaster
yesterday
add a comment |
up vote
0
down vote
Leading newlines can often make it easier to write the code when there are conditionals, for example,
printf("Initializing");
if (jobName != null)
printf(": %s", jobName);
init();
printf("nProcessing");
(But as has been noted elsewhere you may need to flush the output buffer before doing any steps that takes much CPU time.)
Hence a good case can be made for both ways of doing it, however personly I don't like printf() and would use a custom class to build up the output.
add a comment |
StackExchange.ready(function () {
$("#show-editor-button input, #show-editor-button button").click(function () {
var showEditor = function() {
$("#show-editor-button").hide();
$("#post-form").removeClass("dno");
StackExchange.editor.finallyInit();
};
var useFancy = $(this).data('confirm-use-fancy');
if(useFancy == 'True') {
var popupTitle = $(this).data('confirm-fancy-title');
var popupBody = $(this).data('confirm-fancy-body');
var popupAccept = $(this).data('confirm-fancy-accept-button');
$(this).loadPopup({
url: '/post/self-answer-popup',
loaded: function(popup) {
var pTitle = $(popup).find('h2');
var pBody = $(popup).find('.popup-body');
var pSubmit = $(popup).find('.popup-submit');
pTitle.text(popupTitle);
pBody.html(popupBody);
pSubmit.val(popupAccept).click(showEditor);
}
})
} else{
var confirmText = $(this).data('confirm-text');
if (confirmText ? confirm(confirmText) : true) {
showEditor();
}
}
});
});
6 Answers
6
active
oldest
votes
6 Answers
6
active
oldest
votes
active
oldest
votes
active
oldest
votes
up vote
133
down vote
accepted
A fair amount of terminal I/O is line-buffered, so by ending a message with n you can be certain that it will be displayed in a timely manner. With a leading n the message may or may not be displayed at once. Often, this would mean that each step displays the progress message of the previous step, which causes no end of confusion and wasted time when you try to understand a program's behaviour.
14
This is particularly important when using printf for debugging a program that crashes. Putting the newline at the end of a printf means that stdout to the console gets flushed at each printf. (Note that when stdout is redirected to a file, the std libraries will usually do block buffering instead of line buffering, so that makes printf debugging a crash quite hard even with newline at the end.)
– Erik Eidt
yesterday
16
@ErikEidt Note that you should usefprintf(STDERR, …)
instead, which is generally not buffered at all for diagnostic output.
– Deduplicator
yesterday
2
@Deduplicator Writing diagnostic messages to the error stream has its downsides as well - many scripts assume a program has failed if something is written to the error stream.
– Voo
yesterday
30
@Voo: I would argue that any program that assumes writes to stderr indicate a failure is itself incorrect. The exit code of the process is what indicates whether or not it failed. If it was a failure, then the stderr output will explain why. If the process exited successfully (exit code zero) then stderr output should be considered informational output for a human user, with no particular machine-parseable semantic (it might contain human-readable warnings, for example), while stdout is the actual output of the program, possibly suitable for further processing.
– Daniel Pryden
yesterday
13
@Voo: What programs are you describing? I'm not aware of any widely-used software package that behaves like you describe. I do know that there are programs that do, but it's not like I just made up the convention I describe above: that's the way the vast majority of programs in a Unix or Unix-like environment work, and to my knowledge, the way the vast majority of programs always have. I certainly wouldn't advocate for any program to avoid writing to stderr simply because some scripts don't handle it well.
– Daniel Pryden
yesterday
|
show 4 more comments
up vote
133
down vote
accepted
A fair amount of terminal I/O is line-buffered, so by ending a message with n you can be certain that it will be displayed in a timely manner. With a leading n the message may or may not be displayed at once. Often, this would mean that each step displays the progress message of the previous step, which causes no end of confusion and wasted time when you try to understand a program's behaviour.
14
This is particularly important when using printf for debugging a program that crashes. Putting the newline at the end of a printf means that stdout to the console gets flushed at each printf. (Note that when stdout is redirected to a file, the std libraries will usually do block buffering instead of line buffering, so that makes printf debugging a crash quite hard even with newline at the end.)
– Erik Eidt
yesterday
16
@ErikEidt Note that you should usefprintf(STDERR, …)
instead, which is generally not buffered at all for diagnostic output.
– Deduplicator
yesterday
2
@Deduplicator Writing diagnostic messages to the error stream has its downsides as well - many scripts assume a program has failed if something is written to the error stream.
– Voo
yesterday
30
@Voo: I would argue that any program that assumes writes to stderr indicate a failure is itself incorrect. The exit code of the process is what indicates whether or not it failed. If it was a failure, then the stderr output will explain why. If the process exited successfully (exit code zero) then stderr output should be considered informational output for a human user, with no particular machine-parseable semantic (it might contain human-readable warnings, for example), while stdout is the actual output of the program, possibly suitable for further processing.
– Daniel Pryden
yesterday
13
@Voo: What programs are you describing? I'm not aware of any widely-used software package that behaves like you describe. I do know that there are programs that do, but it's not like I just made up the convention I describe above: that's the way the vast majority of programs in a Unix or Unix-like environment work, and to my knowledge, the way the vast majority of programs always have. I certainly wouldn't advocate for any program to avoid writing to stderr simply because some scripts don't handle it well.
– Daniel Pryden
yesterday
|
show 4 more comments
up vote
133
down vote
accepted
up vote
133
down vote
accepted
A fair amount of terminal I/O is line-buffered, so by ending a message with n you can be certain that it will be displayed in a timely manner. With a leading n the message may or may not be displayed at once. Often, this would mean that each step displays the progress message of the previous step, which causes no end of confusion and wasted time when you try to understand a program's behaviour.
A fair amount of terminal I/O is line-buffered, so by ending a message with n you can be certain that it will be displayed in a timely manner. With a leading n the message may or may not be displayed at once. Often, this would mean that each step displays the progress message of the previous step, which causes no end of confusion and wasted time when you try to understand a program's behaviour.
answered yesterday
Kilian Foth
86.7k33235262
86.7k33235262
14
This is particularly important when using printf for debugging a program that crashes. Putting the newline at the end of a printf means that stdout to the console gets flushed at each printf. (Note that when stdout is redirected to a file, the std libraries will usually do block buffering instead of line buffering, so that makes printf debugging a crash quite hard even with newline at the end.)
– Erik Eidt
yesterday
16
@ErikEidt Note that you should usefprintf(STDERR, …)
instead, which is generally not buffered at all for diagnostic output.
– Deduplicator
yesterday
2
@Deduplicator Writing diagnostic messages to the error stream has its downsides as well - many scripts assume a program has failed if something is written to the error stream.
– Voo
yesterday
30
@Voo: I would argue that any program that assumes writes to stderr indicate a failure is itself incorrect. The exit code of the process is what indicates whether or not it failed. If it was a failure, then the stderr output will explain why. If the process exited successfully (exit code zero) then stderr output should be considered informational output for a human user, with no particular machine-parseable semantic (it might contain human-readable warnings, for example), while stdout is the actual output of the program, possibly suitable for further processing.
– Daniel Pryden
yesterday
13
@Voo: What programs are you describing? I'm not aware of any widely-used software package that behaves like you describe. I do know that there are programs that do, but it's not like I just made up the convention I describe above: that's the way the vast majority of programs in a Unix or Unix-like environment work, and to my knowledge, the way the vast majority of programs always have. I certainly wouldn't advocate for any program to avoid writing to stderr simply because some scripts don't handle it well.
– Daniel Pryden
yesterday
|
show 4 more comments
14
This is particularly important when using printf for debugging a program that crashes. Putting the newline at the end of a printf means that stdout to the console gets flushed at each printf. (Note that when stdout is redirected to a file, the std libraries will usually do block buffering instead of line buffering, so that makes printf debugging a crash quite hard even with newline at the end.)
– Erik Eidt
yesterday
16
@ErikEidt Note that you should usefprintf(STDERR, …)
instead, which is generally not buffered at all for diagnostic output.
– Deduplicator
yesterday
2
@Deduplicator Writing diagnostic messages to the error stream has its downsides as well - many scripts assume a program has failed if something is written to the error stream.
– Voo
yesterday
30
@Voo: I would argue that any program that assumes writes to stderr indicate a failure is itself incorrect. The exit code of the process is what indicates whether or not it failed. If it was a failure, then the stderr output will explain why. If the process exited successfully (exit code zero) then stderr output should be considered informational output for a human user, with no particular machine-parseable semantic (it might contain human-readable warnings, for example), while stdout is the actual output of the program, possibly suitable for further processing.
– Daniel Pryden
yesterday
13
@Voo: What programs are you describing? I'm not aware of any widely-used software package that behaves like you describe. I do know that there are programs that do, but it's not like I just made up the convention I describe above: that's the way the vast majority of programs in a Unix or Unix-like environment work, and to my knowledge, the way the vast majority of programs always have. I certainly wouldn't advocate for any program to avoid writing to stderr simply because some scripts don't handle it well.
– Daniel Pryden
yesterday
14
14
This is particularly important when using printf for debugging a program that crashes. Putting the newline at the end of a printf means that stdout to the console gets flushed at each printf. (Note that when stdout is redirected to a file, the std libraries will usually do block buffering instead of line buffering, so that makes printf debugging a crash quite hard even with newline at the end.)
– Erik Eidt
yesterday
This is particularly important when using printf for debugging a program that crashes. Putting the newline at the end of a printf means that stdout to the console gets flushed at each printf. (Note that when stdout is redirected to a file, the std libraries will usually do block buffering instead of line buffering, so that makes printf debugging a crash quite hard even with newline at the end.)
– Erik Eidt
yesterday
16
16
@ErikEidt Note that you should use
fprintf(STDERR, …)
instead, which is generally not buffered at all for diagnostic output.– Deduplicator
yesterday
@ErikEidt Note that you should use
fprintf(STDERR, …)
instead, which is generally not buffered at all for diagnostic output.– Deduplicator
yesterday
2
2
@Deduplicator Writing diagnostic messages to the error stream has its downsides as well - many scripts assume a program has failed if something is written to the error stream.
– Voo
yesterday
@Deduplicator Writing diagnostic messages to the error stream has its downsides as well - many scripts assume a program has failed if something is written to the error stream.
– Voo
yesterday
30
30
@Voo: I would argue that any program that assumes writes to stderr indicate a failure is itself incorrect. The exit code of the process is what indicates whether or not it failed. If it was a failure, then the stderr output will explain why. If the process exited successfully (exit code zero) then stderr output should be considered informational output for a human user, with no particular machine-parseable semantic (it might contain human-readable warnings, for example), while stdout is the actual output of the program, possibly suitable for further processing.
– Daniel Pryden
yesterday
@Voo: I would argue that any program that assumes writes to stderr indicate a failure is itself incorrect. The exit code of the process is what indicates whether or not it failed. If it was a failure, then the stderr output will explain why. If the process exited successfully (exit code zero) then stderr output should be considered informational output for a human user, with no particular machine-parseable semantic (it might contain human-readable warnings, for example), while stdout is the actual output of the program, possibly suitable for further processing.
– Daniel Pryden
yesterday
13
13
@Voo: What programs are you describing? I'm not aware of any widely-used software package that behaves like you describe. I do know that there are programs that do, but it's not like I just made up the convention I describe above: that's the way the vast majority of programs in a Unix or Unix-like environment work, and to my knowledge, the way the vast majority of programs always have. I certainly wouldn't advocate for any program to avoid writing to stderr simply because some scripts don't handle it well.
– Daniel Pryden
yesterday
@Voo: What programs are you describing? I'm not aware of any widely-used software package that behaves like you describe. I do know that there are programs that do, but it's not like I just made up the convention I describe above: that's the way the vast majority of programs in a Unix or Unix-like environment work, and to my knowledge, the way the vast majority of programs always have. I certainly wouldn't advocate for any program to avoid writing to stderr simply because some scripts don't handle it well.
– Daniel Pryden
yesterday
|
show 4 more comments
up vote
37
down vote
On POSIX systems (basically any linux, BSD, whatever open-source based system you can find), a line is defined to be a string of characters that's terminated by a newline n
. This is the basic assumption all the standard command line tools build upon, including (but not limited to) wc
, grep
, sed
, awk
, and vim
. This is also the reason why some editor (like vim
) always add a n
at the end of a file, and why earlier standards of C required headers to end with a n
character.
Btw: Having n
terminated lines makes processing of text much easier: You know for sure that you've got a complete line when you've got that terminator. And you know for sure that you need to look at more characters if you didn't encounter that terminator yet.
Of course, this is on the input side of programs, but program output is very often used as program input again. So, your output should stick to the convention for the sake of allowing seamless input into other programs.
16
This is one of the oldest debates in software engineering: is it better to use newlines (or, in a programming language, another "end of statement" marker like a semicolon) as line terminators or line separators? Both approaches have their pros and cons. The Windows world has mostly settled on the idea that the newline sequence (which is typically CR LF there) is a line separator, and thus the last line in a file doesn't need to end with it. In the Unix world, though, a newline sequence (LF) is a line terminator, and many programs are built around this assumption.
– Daniel Pryden
yesterday
18
POSIX even defines a line as "A sequence of zero or more non-newline characters plus a terminating newline character."
– pipe
yesterday
3
Given that as @pipe says, it's in the POSIX specification, we can probably call it de jure as opposed to de facto as the answer suggests?
– Baldrickk
yesterday
3
@Baldrickk Right. I have updated my answer to be more affirmative, now.
– cmaster
yesterday
add a comment |
up vote
37
down vote
On POSIX systems (basically any linux, BSD, whatever open-source based system you can find), a line is defined to be a string of characters that's terminated by a newline n
. This is the basic assumption all the standard command line tools build upon, including (but not limited to) wc
, grep
, sed
, awk
, and vim
. This is also the reason why some editor (like vim
) always add a n
at the end of a file, and why earlier standards of C required headers to end with a n
character.
Btw: Having n
terminated lines makes processing of text much easier: You know for sure that you've got a complete line when you've got that terminator. And you know for sure that you need to look at more characters if you didn't encounter that terminator yet.
Of course, this is on the input side of programs, but program output is very often used as program input again. So, your output should stick to the convention for the sake of allowing seamless input into other programs.
16
This is one of the oldest debates in software engineering: is it better to use newlines (or, in a programming language, another "end of statement" marker like a semicolon) as line terminators or line separators? Both approaches have their pros and cons. The Windows world has mostly settled on the idea that the newline sequence (which is typically CR LF there) is a line separator, and thus the last line in a file doesn't need to end with it. In the Unix world, though, a newline sequence (LF) is a line terminator, and many programs are built around this assumption.
– Daniel Pryden
yesterday
18
POSIX even defines a line as "A sequence of zero or more non-newline characters plus a terminating newline character."
– pipe
yesterday
3
Given that as @pipe says, it's in the POSIX specification, we can probably call it de jure as opposed to de facto as the answer suggests?
– Baldrickk
yesterday
3
@Baldrickk Right. I have updated my answer to be more affirmative, now.
– cmaster
yesterday
add a comment |
up vote
37
down vote
up vote
37
down vote
On POSIX systems (basically any linux, BSD, whatever open-source based system you can find), a line is defined to be a string of characters that's terminated by a newline n
. This is the basic assumption all the standard command line tools build upon, including (but not limited to) wc
, grep
, sed
, awk
, and vim
. This is also the reason why some editor (like vim
) always add a n
at the end of a file, and why earlier standards of C required headers to end with a n
character.
Btw: Having n
terminated lines makes processing of text much easier: You know for sure that you've got a complete line when you've got that terminator. And you know for sure that you need to look at more characters if you didn't encounter that terminator yet.
Of course, this is on the input side of programs, but program output is very often used as program input again. So, your output should stick to the convention for the sake of allowing seamless input into other programs.
On POSIX systems (basically any linux, BSD, whatever open-source based system you can find), a line is defined to be a string of characters that's terminated by a newline n
. This is the basic assumption all the standard command line tools build upon, including (but not limited to) wc
, grep
, sed
, awk
, and vim
. This is also the reason why some editor (like vim
) always add a n
at the end of a file, and why earlier standards of C required headers to end with a n
character.
Btw: Having n
terminated lines makes processing of text much easier: You know for sure that you've got a complete line when you've got that terminator. And you know for sure that you need to look at more characters if you didn't encounter that terminator yet.
Of course, this is on the input side of programs, but program output is very often used as program input again. So, your output should stick to the convention for the sake of allowing seamless input into other programs.
edited yesterday
answered yesterday
cmaster
5,94311220
5,94311220
16
This is one of the oldest debates in software engineering: is it better to use newlines (or, in a programming language, another "end of statement" marker like a semicolon) as line terminators or line separators? Both approaches have their pros and cons. The Windows world has mostly settled on the idea that the newline sequence (which is typically CR LF there) is a line separator, and thus the last line in a file doesn't need to end with it. In the Unix world, though, a newline sequence (LF) is a line terminator, and many programs are built around this assumption.
– Daniel Pryden
yesterday
18
POSIX even defines a line as "A sequence of zero or more non-newline characters plus a terminating newline character."
– pipe
yesterday
3
Given that as @pipe says, it's in the POSIX specification, we can probably call it de jure as opposed to de facto as the answer suggests?
– Baldrickk
yesterday
3
@Baldrickk Right. I have updated my answer to be more affirmative, now.
– cmaster
yesterday
add a comment |
16
This is one of the oldest debates in software engineering: is it better to use newlines (or, in a programming language, another "end of statement" marker like a semicolon) as line terminators or line separators? Both approaches have their pros and cons. The Windows world has mostly settled on the idea that the newline sequence (which is typically CR LF there) is a line separator, and thus the last line in a file doesn't need to end with it. In the Unix world, though, a newline sequence (LF) is a line terminator, and many programs are built around this assumption.
– Daniel Pryden
yesterday
18
POSIX even defines a line as "A sequence of zero or more non-newline characters plus a terminating newline character."
– pipe
yesterday
3
Given that as @pipe says, it's in the POSIX specification, we can probably call it de jure as opposed to de facto as the answer suggests?
– Baldrickk
yesterday
3
@Baldrickk Right. I have updated my answer to be more affirmative, now.
– cmaster
yesterday
16
16
This is one of the oldest debates in software engineering: is it better to use newlines (or, in a programming language, another "end of statement" marker like a semicolon) as line terminators or line separators? Both approaches have their pros and cons. The Windows world has mostly settled on the idea that the newline sequence (which is typically CR LF there) is a line separator, and thus the last line in a file doesn't need to end with it. In the Unix world, though, a newline sequence (LF) is a line terminator, and many programs are built around this assumption.
– Daniel Pryden
yesterday
This is one of the oldest debates in software engineering: is it better to use newlines (or, in a programming language, another "end of statement" marker like a semicolon) as line terminators or line separators? Both approaches have their pros and cons. The Windows world has mostly settled on the idea that the newline sequence (which is typically CR LF there) is a line separator, and thus the last line in a file doesn't need to end with it. In the Unix world, though, a newline sequence (LF) is a line terminator, and many programs are built around this assumption.
– Daniel Pryden
yesterday
18
18
POSIX even defines a line as "A sequence of zero or more non-newline characters plus a terminating newline character."
– pipe
yesterday
POSIX even defines a line as "A sequence of zero or more non-newline characters plus a terminating newline character."
– pipe
yesterday
3
3
Given that as @pipe says, it's in the POSIX specification, we can probably call it de jure as opposed to de facto as the answer suggests?
– Baldrickk
yesterday
Given that as @pipe says, it's in the POSIX specification, we can probably call it de jure as opposed to de facto as the answer suggests?
– Baldrickk
yesterday
3
3
@Baldrickk Right. I have updated my answer to be more affirmative, now.
– cmaster
yesterday
@Baldrickk Right. I have updated my answer to be more affirmative, now.
– cmaster
yesterday
add a comment |
up vote
11
down vote
Using trailing newlines simplifies later modifications.
As a (very trivial) example based on the OP's code, suppose you need to produce some output before the "Initializing" message, and that output comes from a different logical part of the code, in a different source file.
When you run the first test and find "Initializing" is now appended to the end of a line of some other output, you have to search through the code to find where it got printed, and then hope changing "Initializing" to "nInitializing" doesn't screw up the format of something else, in different circumstances.
Now consider how to are going to handle the fact that your new output is actually optional, so your change to "nInitializing" sometimes produces an unwanted blank line at the start of the output ...
Do you set a global (shock horror??!!!) flag saying whether there was any preceding output and test it to print "Initializing" with an optional leading "n", or do you output the "n" along with your earlier output and leave future code readers wondering why this "Initializing" doesn't have a leading "n" like all the other output messages do?
If you consistently output trailing newlines, at the point where you know you have reached the end of the line that needs to be terminated, you sidestep all those issues. Note, that might require a separate puts("n") statement at the end of some logic that outputs a line piece by piece, but the point is you output the newline at the earliest place in the code where you know you need to do it, not somewhere else.
New contributor
If every independent output item is supposed to appear on its own line, trailing new lines can work fine. If multiple items should be consolidated when practical, however, things get more complicated. If it's practical to feed all output through a common routine, an operation to insert a clear-to-end-of-line if the last character was a CR, nothing if the last character was a newline, and a newline if the last character was anything else, may be helpful if programs need to do something other than output a sequence of independent lines.
– supercat
6 hours ago
add a comment |
up vote
11
down vote
Using trailing newlines simplifies later modifications.
As a (very trivial) example based on the OP's code, suppose you need to produce some output before the "Initializing" message, and that output comes from a different logical part of the code, in a different source file.
When you run the first test and find "Initializing" is now appended to the end of a line of some other output, you have to search through the code to find where it got printed, and then hope changing "Initializing" to "nInitializing" doesn't screw up the format of something else, in different circumstances.
Now consider how to are going to handle the fact that your new output is actually optional, so your change to "nInitializing" sometimes produces an unwanted blank line at the start of the output ...
Do you set a global (shock horror??!!!) flag saying whether there was any preceding output and test it to print "Initializing" with an optional leading "n", or do you output the "n" along with your earlier output and leave future code readers wondering why this "Initializing" doesn't have a leading "n" like all the other output messages do?
If you consistently output trailing newlines, at the point where you know you have reached the end of the line that needs to be terminated, you sidestep all those issues. Note, that might require a separate puts("n") statement at the end of some logic that outputs a line piece by piece, but the point is you output the newline at the earliest place in the code where you know you need to do it, not somewhere else.
New contributor
If every independent output item is supposed to appear on its own line, trailing new lines can work fine. If multiple items should be consolidated when practical, however, things get more complicated. If it's practical to feed all output through a common routine, an operation to insert a clear-to-end-of-line if the last character was a CR, nothing if the last character was a newline, and a newline if the last character was anything else, may be helpful if programs need to do something other than output a sequence of independent lines.
– supercat
6 hours ago
add a comment |
up vote
11
down vote
up vote
11
down vote
Using trailing newlines simplifies later modifications.
As a (very trivial) example based on the OP's code, suppose you need to produce some output before the "Initializing" message, and that output comes from a different logical part of the code, in a different source file.
When you run the first test and find "Initializing" is now appended to the end of a line of some other output, you have to search through the code to find where it got printed, and then hope changing "Initializing" to "nInitializing" doesn't screw up the format of something else, in different circumstances.
Now consider how to are going to handle the fact that your new output is actually optional, so your change to "nInitializing" sometimes produces an unwanted blank line at the start of the output ...
Do you set a global (shock horror??!!!) flag saying whether there was any preceding output and test it to print "Initializing" with an optional leading "n", or do you output the "n" along with your earlier output and leave future code readers wondering why this "Initializing" doesn't have a leading "n" like all the other output messages do?
If you consistently output trailing newlines, at the point where you know you have reached the end of the line that needs to be terminated, you sidestep all those issues. Note, that might require a separate puts("n") statement at the end of some logic that outputs a line piece by piece, but the point is you output the newline at the earliest place in the code where you know you need to do it, not somewhere else.
New contributor
Using trailing newlines simplifies later modifications.
As a (very trivial) example based on the OP's code, suppose you need to produce some output before the "Initializing" message, and that output comes from a different logical part of the code, in a different source file.
When you run the first test and find "Initializing" is now appended to the end of a line of some other output, you have to search through the code to find where it got printed, and then hope changing "Initializing" to "nInitializing" doesn't screw up the format of something else, in different circumstances.
Now consider how to are going to handle the fact that your new output is actually optional, so your change to "nInitializing" sometimes produces an unwanted blank line at the start of the output ...
Do you set a global (shock horror??!!!) flag saying whether there was any preceding output and test it to print "Initializing" with an optional leading "n", or do you output the "n" along with your earlier output and leave future code readers wondering why this "Initializing" doesn't have a leading "n" like all the other output messages do?
If you consistently output trailing newlines, at the point where you know you have reached the end of the line that needs to be terminated, you sidestep all those issues. Note, that might require a separate puts("n") statement at the end of some logic that outputs a line piece by piece, but the point is you output the newline at the earliest place in the code where you know you need to do it, not somewhere else.
New contributor
edited yesterday
New contributor
answered yesterday
alephzero
21925
21925
New contributor
New contributor
If every independent output item is supposed to appear on its own line, trailing new lines can work fine. If multiple items should be consolidated when practical, however, things get more complicated. If it's practical to feed all output through a common routine, an operation to insert a clear-to-end-of-line if the last character was a CR, nothing if the last character was a newline, and a newline if the last character was anything else, may be helpful if programs need to do something other than output a sequence of independent lines.
– supercat
6 hours ago
add a comment |
If every independent output item is supposed to appear on its own line, trailing new lines can work fine. If multiple items should be consolidated when practical, however, things get more complicated. If it's practical to feed all output through a common routine, an operation to insert a clear-to-end-of-line if the last character was a CR, nothing if the last character was a newline, and a newline if the last character was anything else, may be helpful if programs need to do something other than output a sequence of independent lines.
– supercat
6 hours ago
If every independent output item is supposed to appear on its own line, trailing new lines can work fine. If multiple items should be consolidated when practical, however, things get more complicated. If it's practical to feed all output through a common routine, an operation to insert a clear-to-end-of-line if the last character was a CR, nothing if the last character was a newline, and a newline if the last character was anything else, may be helpful if programs need to do something other than output a sequence of independent lines.
– supercat
6 hours ago
If every independent output item is supposed to appear on its own line, trailing new lines can work fine. If multiple items should be consolidated when practical, however, things get more complicated. If it's practical to feed all output through a common routine, an operation to insert a clear-to-end-of-line if the last character was a CR, nothing if the last character was a newline, and a newline if the last character was anything else, may be helpful if programs need to do something other than output a sequence of independent lines.
– supercat
6 hours ago
add a comment |
up vote
8
down vote
In addition to what other have mentioned, I feel like there is a much simpler reason: it's the standard. Whenever anything prints to STDOUT, it almost always assumes that it is already on a new line, and thus doesn't need to start a new one. It also assumes the next line to be written will act the same way, so it helpfully ends by starting a new line.
If you output leading-newline lines interleaved with standard trailing-newline lines," it will end up looking like this:
Trailing-newline-line
Trailing-newline-line
Leading-newline-line
Leading-newline-line
Leading-newline-lineTrailing-newline-line
Trailing-newline-line
Leading-newline-lineTrailing-newline-line
Trailing-newline-line
Trailing-newline-line
...which is presumably not what you want.
If you use only leading newlines in your code and only run it in an IDE, it may turn out okay. As soon as you run it in a terminal or introduce other people's code that will write to STDOUT alongside your code, you'll see undesirable output like above.
add a comment |
up vote
8
down vote
In addition to what other have mentioned, I feel like there is a much simpler reason: it's the standard. Whenever anything prints to STDOUT, it almost always assumes that it is already on a new line, and thus doesn't need to start a new one. It also assumes the next line to be written will act the same way, so it helpfully ends by starting a new line.
If you output leading-newline lines interleaved with standard trailing-newline lines," it will end up looking like this:
Trailing-newline-line
Trailing-newline-line
Leading-newline-line
Leading-newline-line
Leading-newline-lineTrailing-newline-line
Trailing-newline-line
Leading-newline-lineTrailing-newline-line
Trailing-newline-line
Trailing-newline-line
...which is presumably not what you want.
If you use only leading newlines in your code and only run it in an IDE, it may turn out okay. As soon as you run it in a terminal or introduce other people's code that will write to STDOUT alongside your code, you'll see undesirable output like above.
add a comment |
up vote
8
down vote
up vote
8
down vote
In addition to what other have mentioned, I feel like there is a much simpler reason: it's the standard. Whenever anything prints to STDOUT, it almost always assumes that it is already on a new line, and thus doesn't need to start a new one. It also assumes the next line to be written will act the same way, so it helpfully ends by starting a new line.
If you output leading-newline lines interleaved with standard trailing-newline lines," it will end up looking like this:
Trailing-newline-line
Trailing-newline-line
Leading-newline-line
Leading-newline-line
Leading-newline-lineTrailing-newline-line
Trailing-newline-line
Leading-newline-lineTrailing-newline-line
Trailing-newline-line
Trailing-newline-line
...which is presumably not what you want.
If you use only leading newlines in your code and only run it in an IDE, it may turn out okay. As soon as you run it in a terminal or introduce other people's code that will write to STDOUT alongside your code, you'll see undesirable output like above.
In addition to what other have mentioned, I feel like there is a much simpler reason: it's the standard. Whenever anything prints to STDOUT, it almost always assumes that it is already on a new line, and thus doesn't need to start a new one. It also assumes the next line to be written will act the same way, so it helpfully ends by starting a new line.
If you output leading-newline lines interleaved with standard trailing-newline lines," it will end up looking like this:
Trailing-newline-line
Trailing-newline-line
Leading-newline-line
Leading-newline-line
Leading-newline-lineTrailing-newline-line
Trailing-newline-line
Leading-newline-lineTrailing-newline-line
Trailing-newline-line
Trailing-newline-line
...which is presumably not what you want.
If you use only leading newlines in your code and only run it in an IDE, it may turn out okay. As soon as you run it in a terminal or introduce other people's code that will write to STDOUT alongside your code, you'll see undesirable output like above.
edited yesterday
answered yesterday
The Guy with The Hat
21819
21819
add a comment |
add a comment |
up vote
5
down vote
Since the highly up-voted answers have already given excellent technical reasons why trailing newlines should be preferred, I will approach it from another angle.
In my opinions, the followings make a program more readable:
- a high signal-to-noise ratio (aka simple but not simpler)
- important ideas come first
From the above points, we can argue that trailing newlines are better. Newlines are formatting "noise" when compared to the message, the message should stand out and thus should come first (syntax-highlighting can help too).
4
Yes,"okn"
is much better than"nok"
...
– cmaster
yesterday
add a comment |
up vote
5
down vote
Since the highly up-voted answers have already given excellent technical reasons why trailing newlines should be preferred, I will approach it from another angle.
In my opinions, the followings make a program more readable:
- a high signal-to-noise ratio (aka simple but not simpler)
- important ideas come first
From the above points, we can argue that trailing newlines are better. Newlines are formatting "noise" when compared to the message, the message should stand out and thus should come first (syntax-highlighting can help too).
4
Yes,"okn"
is much better than"nok"
...
– cmaster
yesterday
add a comment |
up vote
5
down vote
up vote
5
down vote
Since the highly up-voted answers have already given excellent technical reasons why trailing newlines should be preferred, I will approach it from another angle.
In my opinions, the followings make a program more readable:
- a high signal-to-noise ratio (aka simple but not simpler)
- important ideas come first
From the above points, we can argue that trailing newlines are better. Newlines are formatting "noise" when compared to the message, the message should stand out and thus should come first (syntax-highlighting can help too).
Since the highly up-voted answers have already given excellent technical reasons why trailing newlines should be preferred, I will approach it from another angle.
In my opinions, the followings make a program more readable:
- a high signal-to-noise ratio (aka simple but not simpler)
- important ideas come first
From the above points, we can argue that trailing newlines are better. Newlines are formatting "noise" when compared to the message, the message should stand out and thus should come first (syntax-highlighting can help too).
answered yesterday
Alex Vong
22912
22912
4
Yes,"okn"
is much better than"nok"
...
– cmaster
yesterday
add a comment |
4
Yes,"okn"
is much better than"nok"
...
– cmaster
yesterday
4
4
Yes,
"okn"
is much better than "nok"
...– cmaster
yesterday
Yes,
"okn"
is much better than "nok"
...– cmaster
yesterday
add a comment |
up vote
0
down vote
Leading newlines can often make it easier to write the code when there are conditionals, for example,
printf("Initializing");
if (jobName != null)
printf(": %s", jobName);
init();
printf("nProcessing");
(But as has been noted elsewhere you may need to flush the output buffer before doing any steps that takes much CPU time.)
Hence a good case can be made for both ways of doing it, however personly I don't like printf() and would use a custom class to build up the output.
add a comment |
up vote
0
down vote
Leading newlines can often make it easier to write the code when there are conditionals, for example,
printf("Initializing");
if (jobName != null)
printf(": %s", jobName);
init();
printf("nProcessing");
(But as has been noted elsewhere you may need to flush the output buffer before doing any steps that takes much CPU time.)
Hence a good case can be made for both ways of doing it, however personly I don't like printf() and would use a custom class to build up the output.
add a comment |
up vote
0
down vote
up vote
0
down vote
Leading newlines can often make it easier to write the code when there are conditionals, for example,
printf("Initializing");
if (jobName != null)
printf(": %s", jobName);
init();
printf("nProcessing");
(But as has been noted elsewhere you may need to flush the output buffer before doing any steps that takes much CPU time.)
Hence a good case can be made for both ways of doing it, however personly I don't like printf() and would use a custom class to build up the output.
Leading newlines can often make it easier to write the code when there are conditionals, for example,
printf("Initializing");
if (jobName != null)
printf(": %s", jobName);
init();
printf("nProcessing");
(But as has been noted elsewhere you may need to flush the output buffer before doing any steps that takes much CPU time.)
Hence a good case can be made for both ways of doing it, however personly I don't like printf() and would use a custom class to build up the output.
answered yesterday
Ian
4,1411225
4,1411225
add a comment |
add a comment |
Sign up or log in
StackExchange.ready(function () {
StackExchange.helpers.onClickDraftSave('#login-link');
});
Sign up using Google
Sign up using Facebook
Sign up using Email and Password
Post as a guest
Required, but never shown
StackExchange.ready(
function () {
StackExchange.openid.initPostLogin('.new-post-login', 'https%3a%2f%2fsoftwareengineering.stackexchange.com%2fquestions%2f381711%2fwhy-use-trailing-newlines-instead-of-leading-with-printf%23new-answer', 'question_page');
}
);
Post as a guest
Required, but never shown
Sign up or log in
StackExchange.ready(function () {
StackExchange.helpers.onClickDraftSave('#login-link');
});
Sign up using Google
Sign up using Facebook
Sign up using Email and Password
Post as a guest
Required, but never shown
Sign up or log in
StackExchange.ready(function () {
StackExchange.helpers.onClickDraftSave('#login-link');
});
Sign up using Google
Sign up using Facebook
Sign up using Email and Password
Post as a guest
Required, but never shown
Sign up or log in
StackExchange.ready(function () {
StackExchange.helpers.onClickDraftSave('#login-link');
});
Sign up using Google
Sign up using Facebook
Sign up using Email and Password
Sign up using Google
Sign up using Facebook
Sign up using Email and Password
Post as a guest
Required, but never shown
Required, but never shown
Required, but never shown
Required, but never shown
Required, but never shown
Required, but never shown
Required, but never shown
Required, but never shown
Required, but never shown
3
This question is on the border between "issues with code" (which is off-topic) and "conceptual software design" (which is on-topic). It may get closed, but don't take it too hard. I think adding concrete code examples was the right choice nevertheless.
– Kilian Foth
yesterday
23
The last line would merge with the command prompt on linux without a trailing newline.
– GrandmasterB
yesterday
2
If it "looks better" and it has no downside, that's a good enough reason to do it, IMO. Writing good code is no different to writing a good novel or a good technical paper - the devil is always in the detail.
– alephzero
yesterday
5
Do
init()
andprocess_data()
print anything themselves? What would you expect the result to look like if they did?– Bergi
yesterday
2
n
is a line terminator, not a line separator. This is evidenced by the fact that text files, on UNIX, almost always end inn
.– Jonathon Reinhart
8 hours ago