whether is the standard input stream full buffered or line buffered after calling function setbuf()

K

kernelxu

hi,everybody.
I calling function setbuf() to change the characteristic of standsrd
input buffer.
some fragment of the progrem is:
(DEV-C++2.9.9.2)
#include <stdio.h>
#include <stdlib.h>
int main(void)
{
char buf[10] = {0};
int i;
int j;
char c;

setbuf(stdin, buf);
c = getchar();
for(j = 0; j < 10; j++)
{
printf("%d ",buf[j]);
j++;
}
printf("\n over \n");

return 0;
}

the following questions confused me for a long time.
1) how to judge whether the standard input stream is full buffered or
line buffered .what about it after calling the function setbuf(stdin,
buf)?

2) when I enter an letter 'a', the result is
97 10 10 0 0 0 0 0 0 0
where does the second '10' come from? does it due to the OS(I use
Windows 2000 professional)?

3)how does the system flush the buffers of I/O streams? are there any
differences between flushing input buffer and output buffer?

4)If I calling setbuf(stdin, (char *)0) to set the input buffer as no
buffer, does it work for all standard input functions or just for one
function near to it, for example:

/*DEV-C++*/
#include <stdio.h>

int main(void)
{
int i,j;
char c;

setbuf(stdin, (char *)0); /* 1 */

printf("\n do you want to cal:y/n \n");
while ((c = getchar()) == 'y')
{
printf("input number:\n");
scanf("%d%d", &i, &j);
printf("i*j = %ld", i*j);
setbuf(stdin, (char *)0); /* 2*/
printf("\n do you want to cal:y/n \n");
}

return 0;
}

should I select 1 or 2, though the first doesn't work? but why?

mang many questions, I am so confused on streams and buffers.
any help will be appreciated deeply.

kernelxu
 
W

Walter Roberson

I calling function setbuf() to change the characteristic of standsrd
input buffer.
#include <stdio.h>
#include <stdlib.h>
int main(void)
{
char buf[10] = {0};
int i;
int j;
char c;

setbuf(stdin, buf);
c = getchar();
for(j = 0; j < 10; j++)
{
printf("%d ",buf[j]);
j++;
}
printf("\n over \n");

return 0;
}
the following questions confused me for a long time.
1) how to judge whether the standard input stream is full buffered or
line buffered .what about it after calling the function setbuf(stdin,
buf)?

In order to determine the kind of buffering that a particular
stream has, one must use system-specific measures.

2) when I enter an letter 'a', the result is
97 10 10 0 0 0 0 0 0 0
where does the second '10' come from? does it due to the OS(I use
Windows 2000 professional)?

That 10 are the decimal representation of newline characters.

Note: I do not have my copy of the C89 standard here. The online
man page I am looking at suggests that in your program, the last
8 bytes of the supplied buffer, buf[2] thru buf[9], are used for
internal purposes rather than to store characters. If that is the
case, then the second 10 might be an artifact rather than an entered byte.

3)how does the system flush the buffers of I/O streams?

The FILE* data structure includes overhead information to indicate
the portion of the buffer that is used. The flush operation passes
that data to the operating system; the details of how it does that
are operating system dependant and subject to change without notice.
are there any
differences between flushing input buffer and output buffer?

Yes. In standard C, the operation of flushing an input buffer is not
defined.

4)If I calling setbuf(stdin, (char *)0) to set the input buffer as no
buffer, does it work for all standard input functions or just for one
function near to it,

All operations on that stream, until the stream is closed or
set*buf* called again.
#include <stdio.h>
int main(void)
{
int i,j;
char c;
setbuf(stdin, (char *)0); /* 1 */
printf("\n do you want to cal:y/n \n");
while ((c = getchar()) == 'y')
{
printf("input number:\n");
scanf("%d%d", &i, &j);
printf("i*j = %ld", i*j);
setbuf(stdin, (char *)0); /* 2*/
printf("\n do you want to cal:y/n \n");
}
return 0;
}
should I select 1 or 2, though the first doesn't work? but why?

You only need once.

If the first "doesn't work" then I can suggest a possible reason.
When you do the scanf(), the newline after the two numbers "conflicts"
with the %d format in order to terminate the reading of the number.
That newline is "left unread in the input stream". When you then do
the getchar(), that newline is going to be what is read, and it
isn't going to be 'y' so the while is going to terminate.

In the same vein: you generally need to enter a newline after the initial
'y' because although the input might not be "buffered" by the time it
gets to your program, it might be buffered at the shell -- setting
stdin to be unbuffered is *not* the same as undertaking system-
specific methods to turn on "raw" mode. This newline after the 'y'
is not happening to cause you problems because when you scanf() for i and j,
scanf is defined to skip -leading- whitespace -- and newline is
considered whitespace.

It is easy to fall into the habit of thinking that scanf()
starts at the beginning of the current line and "consumes" the
newline at the end, but it's just the opposite: it "consumes"
the -prior- newlines and leaves the -current- lineline in the buffer
(unless your format specifically asks for it.)
 
K

kernelxu

thank you very much, Walter.
Walter says:
In order to determine the kind of buffering that a particular
stream has, one must use system-specific measures.
so, if I assumed the standard input stream is line buffered, is it
still line buffered after calling "setbuf(stdin, buf)" ? on the other
word, the difference between setbuf() and
setvbuf() is that the latter can change the buffer mode but the former
can't.

Note: I do not have my copy of the C89 standard here. The online
man page I am looking at suggests that in your program, the last
8 bytes of the supplied buffer, buf[2] thru buf[9], are used for
internal purposes rather than to store characters. If that is the
case, then the second 10 might be an artifact rather than an entered byte.
I can't understand it completely, would you please give me some webpage
links such as
the man page you have found?

Yes. In standard C, the operation of flushing an input buffer is not
defined.
and,if I change the standard input buffer into my own buffer, is it
defined when I flush it?
for instance:

#include <stdio.h>
int main(void)
{
int i,j;
char c;
char my_buf[256];

setbuf(stdin, my_buf);

printf("\n do you want to cal:y/n \n");
while ((c = getchar()) == 'y')
{
printf("input number:\n");
scanf("%d%d", &i, &j);
printf("i*j = %ld", i*j);
fflush(stdin);
printf("\n do you want to cal:y/n \n");
}

return 0;
}

The program works or not due to specific system. it is fine on
Windows2000+DEV-C++, but somebody tell me it fails on his system( I
don't the details, but it does fail).

In the same vein: you generally need to enter a newline after the initial
'y' because although the input might not be "buffered" by the time it
gets to your program, it might be buffered at the shell -- setting
stdin to be unbuffered is *not* the same as undertaking system-
specific methods to turn on "raw" mode. This newline after the 'y'
is not happening to cause you problems because when you scanf() for i and j,
scanf is defined to skip -leading- whitespace -- and newline is
considered whitespace.
the problem becomes more and more complex, what should I do on earth
when confronted with input problem relevant with the buffer?
is it a good idea by calling setbuf() or setvbuf()?
or, are there any other efficient methods?

thank you very much ! looking forward to your reply.
 
W

Walter Roberson

Walter says:
so, if I assumed the standard input stream is line buffered,

That is not a safe assumption; input will only be line buffered if
it has been set to be line buffered. The default for input is fully
buffered.
is it
still line buffered after calling "setbuf(stdin, buf)" ?

According to the [SGI IRIX] manual page I am looking at, if buf
is NULL then the I/O will be unbuffered, and otherwise it will
be line-buffered if the stream is associated with a terminal.
on the other
word, the difference between setbuf() and
setvbuf() is that the latter can change the buffer mode but the former
can't.

No, setbuf() changes the mode, but A) has no way to force line
buffering (to a non-terminal); B) has no way to force full
buffering (to a terminal); and C) assumes that the buffer
is a particular minimum size whereas the size is a parameter
for setvbuf().

and,if I change the standard input buffer into my own buffer, is it
defined when I flush it?

No. The C standard only defines flushing output buffers.
fflush(stdin) will NOT work on most systems.

the problem becomes more and more complex, what should I do on earth
when confronted with input problem relevant with the buffer?

The default buffering works well in most situations, and
many of the rest of the situations can be dealt with by
flushing output at key locations.

Your problems are not with buffering: your problems are with
not understanding how to handle newlines.
 
N

Netocrat

On Sun, 14 Aug 2005 08:36:08 -0400, Eric Sosman wrote:

[...]
Unless your implementation's BUFSIZ is ten or less (I've never
encountered so small a value)

C89 requires it to be at least 256.
 
E

Eric Sosman

hi,everybody.
I calling function setbuf() to change the characteristic of standsrd
input buffer.
some fragment of the progrem is:
(DEV-C++2.9.9.2)
#include <stdio.h>
#include <stdlib.h>
int main(void)
{
char buf[10] = {0};
int i;
int j;
char c;

setbuf(stdin, buf);

This is wrong. The second argument to setbuf() must either
be NULL or must point to an area of at least BUFSIZ characters.
Unless your implementation's BUFSIZ is ten or less (I've never
encountered so small a value), your program goes completely off
the rails right here.
c = getchar();
for(j = 0; j < 10; j++)
{
printf("%d ",buf[j]);
j++;
}
printf("\n over \n");

return 0;

This is wrong, too. You've asked stdin to use a buffer
that will cease to exist as soon as main() returns, but when
main() returns stdin is still "alive" and hasn't been closed.
If any shutting-down operations try to make use of the now-
vanished buffer, there's no telling what could happen. (True,
this is usually more troublesome for output streams than for
input, but you're begging for trouble.)
 
D

Dave Thompson

That is not a safe assumption; input will only be line buffered if
it has been set to be line buffered. The default for input is fully
buffered.
According to the standard, the default for stdin (and out) is fully
buffered 'if and only if the stream can be determined not to refer to
an interactive device'. But it can be hard or even impossible for an
implementation to make this determination accurately, so it's best not
to assume either way.
is it
still line buffered after calling "setbuf(stdin, buf)" ?

According to the [SGI IRIX] manual page I am looking at, if buf
is NULL then the I/O will be unbuffered, and otherwise it will
be line-buffered if the stream is associated with a terminal.
NULL certainly must make it unbuffered at the C-library level, and a
valid buf (as already noted should be BUFSIZ not 10) fully buffered.
However, terminal input is line-oriented in most OS'es, including
AFAIK IRIX, so full has same effect as line. (As you correctly
explained in another thread by I believe the same OP!)
No, setbuf() changes the mode, but A) has no way to force line
buffering (to a non-terminal); B) has no way to force full
buffering (to a terminal); and C) assumes that the buffer
is a particular minimum size whereas the size is a parameter
for setvbuf().
A yes. B it does set full buffering _in C_ which should be effective
_to_ a terminal (on stdout, or stderr or other) but as above on most
systems not for input. C yes.

<snip rest>

- David.Thompson1 at worldnet.att.net
 
V

Villy Kruse

thank you very much, Walter.
Walter says:
so, if I assumed the standard input stream is line buffered, is it
still line buffered after calling "setbuf(stdin, buf)" ? on the other
word, the difference between setbuf() and
setvbuf() is that the latter can change the buffer mode but the former
can't.

What is the assumed difference between stdin being line buffered or fully
buffered? I would assume that in either case the stdio functions will
get whatever is available from the OS on every read. If the OS gives
you one line at a time, then that is what you get, but if it is like
unix and windows, just gives you a unstructured byte streadm there is
no way you can force the OS to give you data one line at a time.

Villy
 
M

Michael Wojcik

What is the assumed difference between stdin being line buffered or fully
buffered? I would assume that in either case the stdio functions will
get whatever is available from the OS on every read.

The implementation will likely "get whatever is available", but if
stdin is line buffered it should only return it to the caller if it
encounters a line terminator (or any condition it interprets as an
error or end-of-file). And if stdin is fully buffered, it should
only return data to the caller when the buffer is full (or it gets an
error or EOF).
If the OS gives
you one line at a time, then that is what you get, but if it is like
unix and windows, just gives you a unstructured byte streadm there is
no way you can force the OS to give you data one line at a time.

There's no need to force the OS to do anything. The implementation
does the buffering. When you call fgets(), the implementation is
free to wait until doomsday to return, if it wants to wait for a line
terminator or some other condition.
 

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

No members online now.

Forum statistics

Threads
473,994
Messages
2,570,223
Members
46,813
Latest member
lawrwtwinkle111

Latest Threads

Top