fpurge/fflush

A

alien

i use gcc in ubuntu.
My problem is that, when i use getchar() twice to read a single
character each time, it doesn't stop up and asks for a new character
at second time.

The two codes i use(fflush/fpurge) is:
#include <stdio.h>

int main()
{
char a,b;

printf("Which character is greater?\n");
printf("Type a character: ");
a=getchar();
fflush(stdin);
printf("Type another character: ");
b=getchar();

if(a>b) {
printf("'%c' is greater than '%c'\n",a,b);
}
else if(b>a) {
printf("'%c' is greater than '%c'\n",b,a);
}
else {
printf("Dont type the same character twice.\n");
}
return 0;
}

which says when i type 7 once:
Which character is greater?
Type a character: 7
Type another character: '7' is greater than '
'

And the other code with fpurge(stdin) says when i want to compile it:
/tmp/ccia6orp.o: In function `main':
greater1.c:(.text+0x3a): undefined reference to `fpurge'
collect2: ld returned 1 exit status

What am i doing wrong?
 
B

Beej Jorgensen

alien said:
a=getchar();
fflush(stdin);

I'm a little surprised this doesn't work, but fflush() isn't guaranteed
to do anything in particular with input streams, so I'm not entirely
shocked.

fpurge(stdin) is exactly what you want instead of fflush(stdin), but the
fpurge man page on my Linux machine says:

These functions are non-standard and not portable. The function
fpurge() was introduced in 4.4BSD and is not available under Linux.
The function __fpurge() was introduced in Solaris, and is present in
glibc 2.1.95 and later.

So maybe try __fpurge(stdin)?
printf("Type another character: ");
b=getchar();

It looks like second character you get is the RETURN you hit.

Perhaps a better option would be to use fgets() instead of getchar() to
read a line and then use the first character from it... but this might
be more than you have learned so far.

char line[128];

fgets(line, sizeof buf, stdin);
a = line[0];

-Beej
 
K

Keith Thompson

alien said:
i use gcc in ubuntu.
My problem is that, when i use getchar() twice to read a single
character each time, it doesn't stop up and asks for a new character
at second time.

The two codes i use(fflush/fpurge) is:
[snip]

fflush is not defined for input streams. fflush(stdin) *might*
do what you want on some particular system, but in general its
behavior is undefined.

fpurge is not a standard function.

On my system, the man page for fpurge says that it's not supported. A
similar function __fpurge is available. You should consult the
documentation for your system. The same man page says:

NOTES
Usually it is a mistake to want to discard input buffers.
 
K

kr0wie

Thanks for the answers.
All the codes you guys replied works!
Any way, i would like to know how the cryptic code (every command)
works that io_x posted, if you dont mind to explain:
#include <stdio.h>

int flush(FILE* pf, int cx)
{int c;
if(cx=='\n'|| cx==EOF)
return cx;
while((c=getc(pf))!=EOF && c!='\n');
return c;

}

int main()
{int a,b;

printf("Which character is greater?\n");
printf("Type a character: ");
fflush(stdout); // the one in <stdio.h>

a=getchar();
if(flush(stdin, a)==EOF) // the flush() function above
return 0;

printf("Type another character: "); fflush(stdout);
b=getchar();
if(b==EOF) return 0;
flush(stdin, b);

if(a>b) printf("\'%c\'[%d] is greater than \'%c\'[%d]\n",
(char)a, a, (char)b, b);
else if(b>a) printf("\'%c\'[%d] is greater than \'%c\'[%d]\n",
(char)b, b, (char)a, b);
else printf("Dont type the same character twice.\n");

return 0;
}
 
S

Seebs

i use gcc in ubuntu.
My problem is that, when i use getchar() twice to read a single
character each time, it doesn't stop up and asks for a new character
at second time.

Yes. That's because interactive terminals in Unix-land default to "line
mode", where the terminal driver handles input editing and delivers only
completed lines to your program.
fflush(stdin);

This is undefined behavior, and unlikely to work on most systems.
And the other code with fpurge(stdin) says when i want to compile it:
/tmp/ccia6orp.o: In function `main':
greater1.c:(.text+0x3a): undefined reference to `fpurge'
collect2: ld returned 1 exit status

What am i doing wrong?

fpurge() was added on BSD systems to solve your problem, but isn't a standard
language feature, and not everyone provides it.

There are two reasonable solutions available to you. One is to ask the user
for multiple characters at once, then parse a single line of input. Another
is to learn a bit about terminal drivers under Unix and write something that
moves the terminal into raw mode to perform these operations. (Be sure to
move back out of raw mode when you're done, though!)

-s
 
S

Seebs

this is UB don't know why (yes i know because standard would says so)

The answer is: The intended function of fflush is to finish-processing a
buffer. Not to discard it. fflush(stdout) doesn't discard characters; it
ensures that they are written. Trying to use it to discard characters
is conceptually backwards, and doesn't make sense. Some real systems dump
core if you try this, and no one saw any reason to make them change.
it seems to me that ' is a special char; better to use \'

Wrong.

' is not special inside a quoted string, only outside quoted strings or
inside a '' literal.

-s
 
L

Lew Pitcher

i will add
fflush(stdout);


this is UB don't know why (yes i know because standard would says so)

Think about it. What do you expect fflush(stdin) to do, given that
fflush(stdout) forces any data in the buffer /out/ to the device?

Would fflush(stdin) attempt to write the data currently in the buffer /back/
out to stdin? Would it attempt to force the buffered data into the program?
Would it discard the buffered data?

The semantics of fflush() say that it forces buffered data out to the
device. Since stdin is an input, and not an output, it is meaningless
to "force data out" to stdin. This is one of the reasons that the standard
does not define what happens when you fflush() an input stream.

--
Lew Pitcher

Master Codewright & JOAT-in-training | Registered Linux User #112576
http://pitcher.digitalfreehold.ca/ | GPG public key available by request
---------- Slackware - Because I know what I'm doing. ------
 
S

Seebs

Thanks for the answers.
All the codes you guys replied works!
Any way, i would like to know how the cryptic code (every command)
works that io_x posted, if you dont mind to explain:
#include <stdio.h>
int flush(FILE* pf, int cx)
{int c;
if(cx=='\n'|| cx==EOF)
return cx;
while((c=getc(pf))!=EOF && c!='\n');
return c;
}

This is a very odd design. It starts with the next character in a stream,
then loops through the stream until it gets either EOF or a newline character.
The intent is to discard the buffer. I don't see why it has a second
argument, though.
if(a>b) printf("\'%c\'[%d] is greater than \'%c\'[%d]\n",
(char)a, a, (char)b, b);

This is pure cargo cult. The backslashes on the ' are unnecessary and
confusing. The casts to (char) are useless; all that happens is the
values get promoted straight back to int anyway. The layout of trying
to arrange the arguments under their format controls is interesting, but
I wouldn't do it. The arrangement of the printf after the if is... Well,
again, I sure wouldn't do it. I would find this code hard to read.

-s
 
F

Flash Gordon

io_x said:
"alien" <[email protected]> ha scritto nel messaggio



it seems to me that ' is a special char; better to use \'

To the OP, as the above shows io_x knows very little C, and based on
past history generally posts code which almost everyone else agrees is
very badly formatted. Your original line above is fine.

int flush(FILE* pf, int cx)
{int c;
if(cx=='\n'|| cx==EOF)
return cx;
while((c=getc(pf))!=EOF && c!='\n');
return c;
}

<snip>

The above is absolutely horrendously formatted. It could also be written
a lot more simply...

int flush(FILE *pf, int cx)
{
while (cx!='\n' && cx!=EOF)
cx = getc(pf);
return cx;
}

The idea is to discard the remainder of the line, also stopping on an
input error or end of file.

If you want to actually have your code respond as soon as a key is
pressed then you will need to use a library or extention designed for
your system, and a group dedicated to your system would be the correct
place to start.
 
R

REH

Think about it. What do you expect fflush(stdin) to do, given that
fflush(stdout) forces any data in the buffer /out/ to the device?

Would fflush(stdin) attempt to write the data currently in the buffer /back/
out to stdin? Would it attempt to force the buffered data into the program?
Would it discard the buffered data?

The semantics of fflush() say that it forces buffered data out to the
device. Since stdin is an input, and not an output, it is meaningless
to "force data out" to stdin. This is one of the reasons that the standard
does not define what happens when you fflush() an input stream.

C doesn't support it, but its not a meaning thing to flush an input
stream. C++ streams support this concept via sync(). A lot of systems
support the ability to flush input streams.

I believe the C Standard doesn't support it because there are many
systems that don't support it, not because its meaningless.

REH
 
B

Beej Jorgensen

superpollo said:
Beej Jorgensen ha scritto:

doesnt it invoke ub?

Yeah. I was thinking more about it, and I'm almost positive I saw it
working on HPUX about 10 years ago... and I might have seen it work
under Ultrix, but I can't recall. So maybe I never did see it work
under Linux, after all.

-Beej
 
K

kr0wie

Wow, thank you all for taking time to helping me. Things have been
more clear for me now, thanks!
 
K

Keith Thompson

Seebs said:
The answer is: The intended function of fflush is to finish-processing a
buffer. Not to discard it. fflush(stdout) doesn't discard characters; it
ensures that they are written. Trying to use it to discard characters
is conceptually backwards, and doesn't make sense. Some real systems dump
core if you try this, and no one saw any reason to make them change.



Wrong.

' is not special inside a quoted string, only outside quoted strings or
inside a '' literal.

Correct, mostly. ' is special inside a quoted string in the sense
that you *can* (but aren't required to) escape it with \.

Thus "'" and "\'" are equivalent.

Similarly, '"' and '\"' are equivalent.

This is probably convenient in some cases.
 
S

Seebs

Correct, mostly. ' is special inside a quoted string in the sense
that you *can* (but aren't required to) escape it with \.

Good point.
This is probably convenient in some cases.

Yeah.

I was confused there -- I was actually sorta surprised that \' worked.
(Why was I confused? Because I spent a number of months studying shell
programming, specifically portable shell programming including shells
that don't live up to the standards, and the general rule seems to be
that you can't safely assume that you can backslash stuff that isn't
on the narrow list of things specifically defined to be backslashable.)

So in shell, "\'" is a backslash and a single quote -- the backslash
does nothing special. It has special meaning only for specific
following characters. (But don't try <echo "\'"> and expect it to work,
because some shells substitute POSIX echo for one that treats
backslashes specially!)

-s
 
K

kr0wie

I just got another quick question, it isn't anything about this.. But
anyway, i just started programming (which you would have figured out),
and how would the perfect start be for me? C isn't too difficult to
me, but maybe there were another language which would be better to
learn first? I mean.. Where would you start hacking/programming if you
could choose to start your life over?
 
B

Barry Schwarz

i use gcc in ubuntu.
My problem is that, when i use getchar() twice to read a single
character each time, it doesn't stop up and asks for a new character
at second time.

When you entered the first character, how many keys did you press? How
many characters were placed in the buffer supporting stdin? How many
of those characters were processed by the call to getchar? What do
you expect getchar to do when it finds data still in the buffer?
 
N

Nick Keighley

i don't know why i wrote above; should be

no it shouldn't because..

what meaning would you give it? Flushing an input stream doesn't
really
make sense. You could write a skip_to_next_line() if that's what you
want.
 
S

Seebs

kr0wie said:
if(a>b) printf("\'%c\'[%d] is greater than \'%c\'[%d]\n",
(char)a, a, (char)b, b);
this print the result
because "a" is of type int and "%c" want a char
i use the cast for to be sure

You're wrong.

c If no l length modifier is present, the int argument is converted to
an unsigned char, and the resulting character is written.

The c format takes an int argument. After your cast to (char), the value is
converted back to int anyway, because printf() is variadic.

-s
 

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,763
Messages
2,569,562
Members
45,038
Latest member
OrderProperKetocapsules

Latest Threads

Top