echo charecter program...

H

hdsalbki

<snip wrong code>

Both are wrong. My code is correct, compare both codes and try to
understand why yours is not correct.
Do not continue this discussion if you're not a troll. Just reread the
discussion and use a reference for all the functions you will use.

Sorry if I offended you. I thought my version was correct because it
behaved just like your code. Anyway thanks for your help...i'm moving
on to the next exercise!
 
H

hdsalbki

CBFalconer said:
A handy routine to keep available is flushln, below. For your
application you could call "flushln(stdin);". You can also test it
for EOF.

int flushln(FILE *f) {
int ch;
while ((EOF != (ch = getc(f))) || (ch != '\n')) continue;
return ch;
} /* flushln */

for example:

do {
/* something that eats chars other than '\n' */
} while (EOF != flushln(stdin));

Thanks CBFalconer. But when I run the following program which uses
your code, I can't get past the first prompt. The app just seems to
there and all I can do is kill it with ctrl-c. Am I doing something
wrong? I copies and pasted your code so to avoid typo...

#include <stdio.h>

int flushln(FILE *f) {
int ch;
while ((EOF != (ch = getc(f))) || (ch != '\n')) continue;
return ch;
} /* flushln */

int main(void)
{
char a;
while(1)
{
printf("Please enter a character: ");
fflush(stdout);
scanf("%c",&a);
printf("You typed: %c\n",a);
flushln(stdin);
}
return 0;
}

o/p is:

dodo@sapphire:~/src/c/ws$ ./echo_char3
Please enter a character: x
You typed: x

Program hangs here. whatever I type the prompt is not printing again.
 
S

santosh

hdsalbki said:
CBFalconer wrote:

Please don't quote sigs (the text that follows the '-- ' bit) unless you
are specifically commenting on it.
Thanks CBFalconer. But when I run the following program which uses
your code, I can't get past the first prompt. The app just seems to
there and all I can do is kill it with ctrl-c. Am I doing something
wrong? I copies and pasted your code so to avoid typo...

#include <stdio.h>

int flushln(FILE *f) {
int ch;
while ((EOF != (ch = getc(f))) || (ch != '\n')) continue;

This needs to use the && logical operator to function as Chuck probably
intended it:

while ((EOF != (ch = getc(f))) && (ch != '\n')) continue;

<snip rest>
 
H

hdsalbki

santosh said:
This needs to use the && logical operator to function as Chuck probably
intended it:

while ((EOF != (ch = getc(f))) && (ch != '\n')) continue;

<snip rest>

Sorry, I'm new to Groups. And thanks, the code works now!
 
K

Keith Thompson

hdsalbki said:
Thanks to everyone I was able to do this. apart from what vippstar has
sugested I also came with the below code to read the rest of line in
stdin. Is this okay or am I doing something wrong. Thanks for any
comments.

#include <stdio.h>

int main()
{
char a;
while(1)
{
printf("\nPlease enter a character: ");
fflush(stdout);
scanf("%c",&a);
printf("You entered: %c\n",a);
fflush(stdout);
while(1)
{
scanf("%c",&a);
if(a=='\r' || a=='\n')
{
break;
}
}
}
return 0;
}

Why are you checking for '\r' as well as '\n'?

Even if your system happens to represent end-of-line with a CR-LF
pair, that will be translated to a single '\n' character on input (if
you're reading from a text stream, which you are here).

You're also not checking for end-of-file. (Hint: check for EOF, not
feof(stdin).)

I haven't read this whole thread yet, so I don't know whether anyone
else has suggested section 12 of the comp.lang.c FAQ, which covers
stdio. It's at <http://www.c-faq.com>.
 
K

Keith Thompson

hdsalbki said:
Sorry, I'm new to Groups. And thanks, the code works now!

It was Chuck's mistake, not yours; the code he posted actually had the
incorrect "||".

Not a huge deal either way; we all make mistakes. But it does
illustrate the fact that it's usually best to copy-and-paste source
code that's actually been successfully compiled and executed rather
than typing it on the fly.
 
K

Keith Thompson

hdsalbki said:
Thank you for our comment Walter. Actually in my book the \n is given
at the end of the prompt...I changed it to the front because otherwise
the extra prompt was getting printed on the same line as the character
echoed.

Putting a '\n' at the beginning of a prompt is something I've seen
mostly in Windows code, and I don't understand why.

If you want to print a line, put the '\n' at the end of the line. If
you want to print a prompt, with the input to be typed at the end of
the line, don't use '\n' at all. But printing a partial line like
that does complicate things a bit, specifically:
I don't know what fflush(stdout) (just in the second chapter)
but I will include it.

Yes, you should have the fflush(stdout), but don't be surprised if it
doesn't make any visible difference. Here's what's happening.

You're writing to standard output, which is a text stream. Any text
stream can be "unbuffered", "line buffered", or "fully buffered".
This determines when output written to the stream actually appears.
For an unbuffered stream, output appears immediately. For a line
buffered stream, it appears only when a line has been completed. For
a fully buffered stream, it appears when a buffer has been filled; the
size of the buffer can vary. (The latter is typical for writing to
disk files.)

If standard output is going to an interactive device, such as a
terminal or emulator, it's required to be either unbuffered or line
buffered. If it's line buffered, you need the call to fflush(stdout)
to force a partial line to appear. *However*, on most modern systems,
standard output for an interactive program is likely to be unbuffered,
which means that fflush(stdout) will have no effect. Adding the
fflush(stdout) is a precaution that may not be necessary for your
system, but it is necessary if you want your program to be maximally
portable. (Line buffering goes back to the days of hardcopy line
printers.)
wrt to scanf how can I get an end-of-file or I/
O error?

You can get end-of-file if you reach the end of the input file. If
you were reading from a disk file, that would simply be when you've
read everything from the file. For interactive keyboard input,
there's generally a system-specific way to trigger an end-of-file
condition; it's usually control-D for Unix-like systems, control-Z for
DOS/Windows-like systems. (Your program won't actually see the
control-D or control-Z character.)
And main() returns nothing...that's why I didn't return
anything... is that wrong? My book has this everywhere (in someplaces
it is main(void) ).

What book are you using?

If you write
main() { ... }
then the main function is *implicitly* declared to return type int. In other
words, this:
int main() { ...}
and this:
main() { ... }
are equivalent.

The best way to define main is:
int main(void) { ... }
or, if you want to accept command-line arguments:
int main(int argc, char **argv) { ... }
In either case, you *should* return an int value. Returning 0 is
usually the best. Add "return 0;" just before the closing brace.

Leaving off the "int", using "()" rather than "(void)", and leaving
out the return statement are all things that you can *probably* get
away with, but your compiler *might* complain about one or more of
them, depending on various things that I won't go into. (Declaring
main as "void main()" is another matter; don't do that, and avoid any
books that tell you you should.) Doing it right is a good habit, and
it can't hurt.
and I kill the program with ctrl-c because I
wanted to echo all that the user types. I get it now. So I think to
fix this I can have another scanf() call before my main one and just
read the '\n' to a dummy variable? Is this okay?

Once again thanks for your input.

As discussed elsewhere, scanf() isn't the best tool for
single-character input. Actually, it's not the best tool for much of
anything. It can be deceptively simple for simple usage, but once you
try to make your code more robust, it's just more trouble than it's
worth (IMHO).
 
K

Keith Thompson

hdsalbki said:
I have below a small program to echo back what character the user
types. It's working OK but prints a extra prompt between every
character. what can I do? I'm new in C and my book is very
difficult...
thanks for any help.

#include<stdio.h>

main()
{
char a;
while(1)
{
printf("\nPlease type a character: ");
scanf("%c",&a);
printf("\nYou typed: %c",a);
}
}

The program is actually doing just what you told it to do. In
response to the prompt, you typed, say, an 'x'. You didn't see
anything happen, so you pressed the return key (or enter, or however
it's labeled). You typed two characters, 'x' and return, and your
program reported each one.

The issue here is input buffering. (This is distinct from output
buffering, which I discussed in a separate followup.) Though your
scanf call asks for only one character, it doesn't complete until
you've entered a line of text. The new-line character is part of that
line.

More precisely, the scanf call *waits* for a full line of input, but
it only *consumes* a single character. Any other characters in the
line are left waiting in a buffer to be consumed by the next call to
scanf.

Try changing the second printf to:

printf("\nYou typed: '%c'",a);

so the output character is surrounded by single quotes. This will
show you more clearly that it's actually reading and printing each
character you type, including new-line.

Try typing just the return key, with nothing preceding it.

Try typing several characters, such as xyz<return>.

What you'd probably *like* to do is read a single character without
waiting for a complete line. C provides no guaranteed way to do that.
See question 19.1 of the comp.lang.c FAQ, <http://www.c-faq.com/>.

Or you can read a single character and then discard the remainder of
the input line. See the rest of this thread for various ways to do
that.

Text input in C is line-oriented. Usually the best way to handle it
is to use fgets() to read a full line at a time into a string, then
use other functions to process the string. You'll get to that later.
(Using fgets() introduces some issues for very long lines; that can
also wait for later.)
 
K

Keith Thompson

hdsalbki said:
I have below a small program to echo back what character the user
types. It's working OK but prints a extra prompt between every
character. what can I do? I'm new in C and my book is very
difficult...
thanks for any help.

#include<stdio.h>

main()
{
char a;
while(1)
{
printf("\nPlease type a character: ");
scanf("%c",&a);
printf("\nYou typed: %c",a);
}
}

The program is actually doing just what you told it to do. In
response to the prompt, you typed, say, an 'x'. You didn't see
anything happen, so you pressed the return key (or enter, or however
it's labeled). You typed two characters, 'x' and return, and your
program reported each one.

The issue here is input buffering. (This is distinct from output
buffering, which I discussed in a separate followup.) Though your
scanf call asks for only one character, it doesn't complete until
you've entered a line of text. The new-line character is part of that
line.

More precisely, the scanf call *waits* for a full line of input, but
it only *consumes* a single character. Any other characters in the
line are left waiting in a buffer to be consumed by the next call to
scanf.

Try changing the second printf to:

printf("\nYou typed: '%c'",a);

so the output character is surrounded by single quotes. This will
show you more clearly that it's actually reading and printing each
character you type, including new-line.

Try typing just the return key, with nothing preceding it.

Try typing several characters, such as xyz<return>.

What you'd probably *like* to do is read a single character without
waiting for a complete line. C provides no guaranteed way to do that.
See question 19.1 of the comp.lang.c FAQ, <http://www.c-faq.com/>.

Or you can read a single character and then discard the remainder of
the input line. See the rest of this thread for various ways to do
that.

Text input in C is line-oriented. Usually the best way to handle it
is to use fgets() to read a full line at a time into a string, then
use other functions to process the string. You'll get to that later.
(Using fgets() introduces some issues for very long lines; that can
also wait for later.)
 
K

Keith Thompson

Keith Thompson said:
hdsalbki said:
I have below a small program to echo back what character the user
types. It's working OK but prints a extra prompt between every
character. what can I do? I'm new in C and my book is very
difficult...
[snip]
The program is actually doing just what you told it to do.
[snip]

Apologies for the double post. I was insufficiently patient with my
news server.
 
K

Keith Thompson

Keith Thompson said:
hdsalbki said:
I have below a small program to echo back what character the user
types. It's working OK but prints a extra prompt between every
character. what can I do? I'm new in C and my book is very
difficult...
[snip]
The program is actually doing just what you told it to do.
[snip]

Apologies for the double post. I was insufficiently patient with my
news server.
 
B

Ben Bacarisse

On Jul 13, 4:56 pm, Ben Bacarisse <[email protected]> wrote:
The above fails because %*[\n] must match as least one character. The
Don't you mean %*[^\n]? Because that's what is used.

Yes, typo. Sorry. If I have the power to re-write standards I'd
allow a zero-length match for %[^...] since that is often what one
wants.
 
B

Ben Bacarisse

Joachim Schmitz said:
Why not
if(scanf("%c%*[^\r\n]%*c", &a) < 1) break;

I've got confused by corrections or corrections so maybe you mean
something else, but this code probably does not do what you expect.

As per my other post, the %*[^\r\n] must match at least one character.
If there is nothing but the \n, the whole scanf stops here having
failed (but it returns 1). The %*c does not get to read the newline.
 
C

CBFalconer

hdsalbki said:
CBFalconer wrote:
.... snip ...


Thanks CBFalconer. But when I run the following program which uses
your code, I can't get past the first prompt. The app just seems to
there and all I can do is kill it with ctrl-c. Am I doing something
wrong? I copies and pasted your code so to avoid typo...

#include <stdio.h>

int flushln(FILE *f) {
int ch;
while ((EOF != (ch = getc(f))) || (ch != '\n')) continue;
return ch;
} /* flushln */

That || should be a && ------------^ Sorry.
 
L

lawrence.jones

Keith Thompson said:
For an unbuffered stream, output appears immediately. For a line
buffered stream, it appears only when a line has been completed.

Not quite -- it is also supposed to appear when the buffer is full
(obviously), when input is requested on an unbuffered stream, and when
input is requested on a line buffered stream whose buffer is empty.
If standard output is going to an interactive device, such as a
terminal or emulator, it's required to be either unbuffered or line
buffered.

Provided the implementation can determine that it *is* an interactive
device. It's not always possible.
If it's line buffered, you need the call to fflush(stdout)
to force a partial line to appear. *However*, on most modern systems,
standard output for an interactive program is likely to be unbuffered,
which means that fflush(stdout) will have no effect.

Actually, most modern system line buffer interactive devices by default
for both input and output, so the above rules make the fflush()
redundant. However:
Adding the
fflush(stdout) is a precaution that may not be necessary for your
system, but it is necessary if you want your program to be maximally
portable.

That is 100% correct!
 
W

Walter Roberson

Not quite -- it is also supposed to appear when the buffer is full
(obviously), when input is requested on an unbuffered stream, and when
input is requested on a line buffered stream whose buffer is empty.

Hmmm, traditionally switching from output to input required
an explicit fseek() call; did that change in C99?
 
K

Keith Thompson

Not quite -- it is also supposed to appear when the buffer is full
(obviously), when input is requested on an unbuffered stream, and when
input is requested on a line buffered stream whose buffer is empty.

Hey, you don't expect me to cover *everything*, do you? :cool:}
Provided the implementation can determine that it *is* an interactive
device. It's not always possible.

But implementations are effectively required to assume that the device
is interactive if they can't prove it isn't. C99 7.19.3p7:

As initially opened, the standard error stream is not fully
buffered; the standard input and standard output streams are fully
buffered if and only if the stream can be determined not to refer
to an interactive device.
Actually, most modern system line buffer interactive devices by default
for both input and output, so the above rules make the fflush()
redundant. However:

Ah, I see. Line-buffering is sufficient because the input request
causes the partial line to appear. Whereas if I write:

printf("Hello, ");
/* something that takes a long time */
printf("world\n");

the line "Hello, world" will be printed all at once after a delay.
 
L

lawrence.jones

Walter Roberson said:
Hmmm, traditionally switching from output to input required
an explicit fseek() call; did that change in C99?

No, but the above is talking about input on *any* stream, not just the
same stream, so that's not really relevant.
 
L

lawrence.jones

Keith Thompson said:
But implementations are effectively required to assume that the device
is interactive if they can't prove it isn't. C99 7.19.3p7:

Actually, 7.19.5.3p7 is the better reference, since it applies to all
streams, not just stdout and stderr. (I misremembered the requirement
and thought it went the other way.)
Ah, I see. Line-buffering is sufficient because the input request
causes the partial line to appear. Whereas if I write:

printf("Hello, ");
/* something that takes a long time */
printf("world\n");

the line "Hello, world" will be printed all at once after a delay.

Correct on both counts.
 

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
474,265
Messages
2,571,069
Members
48,771
Latest member
ElysaD

Latest Threads

Top