Confused at newline requirement for printf

L

linq936

Hi,
I read in many places that the string to be outputted by printf()
must be ending with newline, for example, it should be

printf("Hello World.\n");

instead of

printf("Hello World.");

because the latter is "undefined" by standard.

But I tried the following code:

#include <stdio.h>

int main(){
printf("%d", 15);

printf("Type in some number:");
int i;
scanf("%d", &i);
printf("\nHey you typed in %d", i);

return 0;
}

You can see that I do not have '\n" in any of the printf, I see what
I expected:

$>./a.out
15Type in some number:9

Hey you typed in 9$>

I know this could be because the compiler implements the support
and also when program finishes the buffer gets flushed out.

My real question is like this, we see a lot of use cases that
printf() and scanf() are used together, as in my example, use printf()
to prompt user to type in something and then use scanf() to read it
in. It is best not to move the curer to a new line.

Then how that requirement that printf() should end with newline
comes to play?
 
E

Eric Sosman

linq936 said:
Hi,
I read in many places that the string to be outputted by printf()
must be ending with newline, for example, it should be

printf("Hello World.\n");

instead of

printf("Hello World.");

because the latter is "undefined" by standard.

Not exactly. A "line" of text usually ends with a
newline character, and if you don't supply one the
implementation might not treat whatever characters you
have already supplied as a "line." But there is no
requirement that all the characters of a "line" must
be output at the same time:

printf ("Hell");
x = sqrt(y);
printf ("o brave new World ");
x += atan(x, y);
printf ("that hath such creatures ");
x *= y;
printf ("in it!");
x = 42;
printf ("\n");

.... uses five printf() calls to generate one "line" of
output, and is perfectly all right. Each of the first
four printf() calls generates part of a "line," and the
fifth makes it complete. As long as the newline comes
along "eventually," all is well.
But I tried the following code:

#include <stdio.h>

int main(){
printf("%d", 15);

printf("Type in some number:");
int i;
scanf("%d", &i);
printf("\nHey you typed in %d", i);

return 0;
}

You can see that I do not have '\n" in any of the printf, I see what
I expected:

$>./a.out
15Type in some number:9

Hey you typed in 9$>

I know this could be because the compiler implements the support
and also when program finishes the buffer gets flushed out.

The implementation is trying to be helpful, probably by
flushing all pending output on all streams whenever you use
an input function on any stream. Not all implementations will
be so helpful (indeed, some may be intentionally *un*helpful,
because excessive output flushing defeats the purpose of
buffering and may hurt performance).

Also, it appears that this implementation can tolerate
"lines" that lack a newline terminator. Not all can do so.
Some implementations use entirely different methods to divide
a file into "lines," such as preceding each line with a number
giving its length. Such implementations cannot even begin to
output a line until the '\n' has appeared and the length can
be computed; if the '\n' never shows up it's anybody's guess
what will happen to the still-buffered data.

The blank line is probably (*probably*) caused by the
implementation echoing the newline (or newline-equivalent)
that ended your input, not by anything your program did on
its own.
My real question is like this, we see a lot of use cases that
printf() and scanf() are used together, as in my example, use printf()
to prompt user to type in something and then use scanf() to read it
in. It is best not to move the curer to a new line.

Then how that requirement that printf() should end with newline
comes to play?

Best practice: Make the prompt be a complete line, with
newline and all. If there's any chance that the output stream
might be "fully buffered," call fflush() before attempting input.
This will put the prompt and the response on separate lines,
but if the system is incapable of handling a partial line that's
the best you can manage anyhow.

Second-best practice: Prompt with a newline-less line, and
call fflush() before reading the response. This stands a fairly
good chance of forcing the prompt to appear, and a fairly good
chance of allowing the response to occupy the same line on the
terminal.

Third-best practice: Call setvbuf() very early to make the
prompting stream unbuffered. Then proceed as in the second-
best scenario, but now you can omit the fflush(). Note that this
will make *all* I/O on the stream unbuffered; if you're going to
begin with a few prompts and then write reams of output you may
not like the performance.

Fourth-best practice: Proceed as you did in the code you
showed, and hope for the best.

Worst practice: Use gets() to read the input.
 

Ask a Question

Want to reply to this thread or ask your own question?

You'll need to choose a username for the site, which only take a couple of moments. After that, you can post your question and our members will help you out.

Ask a Question

Members online

Forum statistics

Threads
473,755
Messages
2,569,535
Members
45,007
Latest member
obedient dusk

Latest Threads

Top