echo charecter program...

H

hdsalbki

hi everyone,
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);
}
}
 
W

Walter Roberson

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: ");

You need to fflush(stdout); at this point.
scanf("%c",&a);

You need to check the return value of scanf at this point, in
order to find out if there has been an end-of-file or I/O error.
printf("\nYou typed: %c",a);
}
}

Your code does not have an 'int' before the 'main', so your
code is not valid C99 (C99 no longer supports the implicit int
type specifier.) But your code does not return a value to the
operating system; in C89 if you do not return a value to the
operating system when you exit the routine, the behaviour
is implementation defined, which can include crashing the computer.
This particular program is saved only because you never return
to the operating system except by terminating the program
through some external mechanism.


The reason you are getting an extra prompt is that when you
type the character of input, after typing the character you
are pressing return -- and that newline is still there in the
buffer. You only read the character itself with the first
scanf() call; the second time through the loop, there is already
input waiting, namely the newline character. A similar thing would
happen if you were to type several characters before pressing
return: your code would output the prompt for each one of them.
 
V

vippstar

hi everyone,
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>
A space here would not be bad,
#include <stdio.h>
Note that both are valid, but the former is considered bad style by
some.
main() Change that to int main(void)
{
char a;
while(1)
{
printf("\nPlease type a character: ");
You should fflush(stdout); after that printf().
scanf("%c",&a);
You should check the return value of scanf().
printf("\nYou typed: %c",a);
}

}


Here is the fix:

#include <stdio.h>

int main(void) {

char c;

while(1) {
printf("Please type a character: ");
fflush(stdout);
if(scanf("%c%*[^\n]%*c") < 1) break;
printf("You typed: %c\n", a);
}

return 0;
}
 
J

Joachim Schmitz

A space here would not be bad,
#include <stdio.h>
Note that both are valid, but the former is considered bad style by
some.
You should fflush(stdout); after that printf().
You should check the return value of scanf().


Here is the fix:
not quite
#include <stdio.h>

int main(void) {

char c;

while(1) {
printf("Please type a character: ");
fflush(stdout);
if(scanf("%c%*[^\n]%*c") < 1) break;
if(scanf("%c%*[^\n]%*c", &c) < 1) break;
printf("You typed: %c\n", a);
printf("You typed: %c\n", c);
}

return 0;
}

Bye, Jojo
 
H

hdsalbki

Walter said:
You need to fflush(stdout); at this point.


You need to check the return value of scanf at this point, in
order to find out if there has been an end-of-file or I/O error.


Your code does not have an 'int' before the 'main', so your
code is not valid C99 (C99 no longer supports the implicit int
type specifier.) But your code does not return a value to the
operating system; in C89 if you do not return a value to the
operating system when you exit the routine, the behaviour
is implementation defined, which can include crashing the computer.
This particular program is saved only because you never return
to the operating system except by terminating the program
through some external mechanism.


The reason you are getting an extra prompt is that when you
type the character of input, after typing the character you
are pressing return -- and that newline is still there in the
buffer. You only read the character itself with the first
scanf() call; the second time through the loop, there is already
input waiting, namely the newline character. A similar thing would
happen if you were to type several characters before pressing
return: your code would output the prompt for each one of them.

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. I don't know what fflush(stdout) (just in the second chapter)
but I will include it. wrt to scanf how can I get an end-of-file or I/
O error? 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) ). 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.
 
H

hdsalbki

hi everyone,
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>
A space here would not be bad,
#include <stdio.h>
Note that both are valid, but the former is considered bad style by
some.
main() Change that to int main(void)
{
char a;
while(1)
{
printf("\nPlease type a character: ");
You should fflush(stdout); after that printf().
scanf("%c",&a);
You should check the return value of scanf().
printf("\nYou typed: %c",a);
}

}


Here is the fix:

#include <stdio.h>

int main(void) {

char c;

while(1) {
printf("Please type a character: ");
fflush(stdout);
if(scanf("%c%*[^\n]%*c") < 1) break;
printf("You typed: %c\n", a);
}

return 0;
}

Thank you so much vippstar! I was really scratching my head with this
problem and my book said nothing about scanf() leaving the \n in
input. I will do the fixes you suggest but I just can't understand
your scanf() call after the "%c"...what do all those characters do?
can you please explain? thanks again.
 
V

vippstar

(e-mail address removed) wrote:
if(scanf("%c%*[^\n]%*c") < 1) break;
Thank you so much vippstar! I was really scratching my head with this
problem and my book said nothing about scanf() leaving the \n in
input. I will do the fixes you suggest but I just can't understand
your scanf() call after the "%c"...what do all those characters do?
can you please explain? thanks again.

See Mr Schmitz correction on my post to get the correct source code.
%* means match conversion but do not "write" to object.
So %*d would read an int but just discard it.

[^\n] means read everything until a newline or eof. push newline back.
%*c means read a byte and discard it.
%*[^\n]%*c reads and discards everything until a newline is met, which
it also discards.
 
H

hdsalbki

(e-mail address removed) wrote:
if(scanf("%c%*[^\n]%*c") < 1) break;
Thank you so much vippstar! I was really scratching my head with this
problem and my book said nothing about scanf() leaving the \n in
input. I will do the fixes you suggest but I just can't understand
your scanf() call after the "%c"...what do all those characters do?
can you please explain? thanks again.

See Mr Schmitz correction on my post to get the correct source code.
%* means match conversion but do not "write" to object.
So %*d would read an int but just discard it.
[^\n] means read everything until a newline or eof. push newline back.
%*c means read a byte and discard it.
%*[^\n]%*c reads and discards everything until a newline is met, which
it also discards.

Please correct me if I'm getting this wrong: in your call first
scanf() reads a character and loads it to a then it reads and throws
away everthing to the line end but leaves alone the \n and then reads
the \n and also throws it away. whew! I wish my book explained it like
this. thanks a lot! your code works perfectly. Can you also tell me
why I'm not able to read the function keys and arrow keys? Any way I
can do that?
 
H

hdsalbki

okay I followed everyone ideas and wrote another version of the
program. Now there is no extra prompt but the code misses every
alternate character I type. Can anyone help? Thanks a lot, never
imagined such a simple thing will be so difficult!

#include <stdio.h>

int main()
{
char a;
while(1)
{
printf("\nPlease enter a character: ");
fflush(stdout);
if(scanf("%c%*[^\n]%*c",&a) < 1)
{
break;
}
printf("You typed: %c\n",a);
fflush(stdout);
}
return(0);
}

o/p is:

dodo@sapphire:~/src/c/ws$ ./echo_char1

Please enter a character: a
You typed: a

Please enter a character: b
You typed:


Please enter a character: c
You typed: c

Please enter a character: d
You typed:


Please enter a character:
 
V

vippstar

okay I followed everyone ideas and wrote another version of the
program. Now there is no extra prompt but the code misses every
alternate character I type. Can anyone help? Thanks a lot, never
imagined such a simple thing will be so difficult!

#include <stdio.h>

int main()
I told you int main(void), not int main().
{
char a;
while(1)
{
printf("\nPlease enter a character: ");
fflush(stdout);
if(scanf("%c%*[^\n]%*c",&a) < 1)
{
break;
}
printf("You typed: %c\n",a);
fflush(stdout);
That fflush() is not necessary, as you write a newline to stdout. That
will flush the stream, since it's line buffered. (_IOLBF in setvbuf)
}
return(0);
return is not a function, it's a keyword. the parenthesis are not
needed, just like sizeof. (do not confuse it with sizeof (cast), it's
the cast that requires parenthesis, not sizeof)
}

o/p is:

dodo@sapphire:~/src/c/ws$ ./echo_char1

Please enter a character: a
You typed: a

Please enter a character: b
You typed:

Please enter a character: c
You typed: c

Please enter a character: d
You typed:

Please enter a character:
Yeah, it seems that it does not actually read the newline with %*c.
I can't tell you why this happends, perhaps someone else can explain.
Remove the %*c and add a getchar(), and it should work:

if(scanf("%c%^[\n]", &a) < 1) break;
(void)getchar();

Note that the cast to (void) is not necessary; I only added it to make
more clear that you don't need to check the return value of getchar.
 
H

hdsalbki

okay I followed everyone ideas and wrote another version of the
program. Now there is no extra prompt but the code misses every
alternate character I type. Can anyone help? Thanks a lot, never
imagined such a simple thing will be so difficult!

#include <stdio.h>

int main()
I told you int main(void), not int main().
{
char a;
while(1)
{
printf("\nPlease enter a character: ");
fflush(stdout);
if(scanf("%c%*[^\n]%*c",&a) < 1)
{
break;
}
printf("You typed: %c\n",a);
fflush(stdout);
That fflush() is not necessary, as you write a newline to stdout. That
will flush the stream, since it's line buffered. (_IOLBF in setvbuf)
}
return(0);
return is not a function, it's a keyword. the parenthesis are not
needed, just like sizeof. (do not confuse it with sizeof (cast), it's
the cast that requires parenthesis, not sizeof)
}

o/p is:

dodo@sapphire:~/src/c/ws$ ./echo_char1

Please enter a character: a
You typed: a

Please enter a character: b
You typed:

Please enter a character: c
You typed: c

Please enter a character: d
You typed:

Please enter a character:
Yeah, it seems that it does not actually read the newline with %*c.
I can't tell you why this happends, perhaps someone else can explain.
Remove the %*c and add a getchar(), and it should work:

if(scanf("%c%^[\n]", &a) < 1) break;
(void)getchar();

Note that the cast to (void) is not necessary; I only added it to make
more clear that you don't need to check the return value of getchar.

Thank you vippstar. I will use int main(void) from now on and use
fflush(stdout) only when there is no \n after output. Okay I confused
the return keyword with if() and while() which need brackets. And your
change works! looking at info for getchar() it says it is for reading
single character...maybe I should've done it with getchar()...thanks
again.
 
H

hdsalbki

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;
}
 
H

hdsalbki

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;
}

Sorry some errors were there. Corrected code follows:

#include <stdio.h>

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

vippstar

Sorry some errors were there. Corrected code follows:
<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.
 
J

Joachim Schmitz

hdsalbki said:
Sorry some errors were there. Corrected code follows:

#include <stdio.h>

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

Bye, Jojo
 
J

Joachim Schmitz

Joachim said:
hdsalbki said:
Sorry some errors were there. Corrected code follows:

#include <stdio.h>

int main(void)
{
char a;
while(1)
{
printf("\nPlease enter a character: ");
fflush(stdout);
scanf("%c",&a);
printf("You entered: %c\n",a);
while(1)
{
scanf("%c",&a);
if(a=='\r' || a=='\n')
{
break;
}
Why not
if(scanf("%c%*[^\r\n]%*c", &a) < 1) break;
Oops. Should be in the outer while, the inner while deleted entirely.

Bye, Jojo
 
B

Ben Bacarisse

hdsalbki said:
okay I followed everyone ideas and wrote another version of the
program. Now there is no extra prompt but the code misses every
alternate character I type. Can anyone help? Thanks a lot, never
imagined such a simple thing will be so difficult!

#include <stdio.h>

int main()
{
char a;
while(1)
{
printf("\nPlease enter a character: ");
fflush(stdout);
if(scanf("%c%*[^\n]%*c",&a) < 1)
{
break;
}
printf("You typed: %c\n",a);
fflush(stdout);
}
return(0);
}

You may have thought you picked an easy example, but this is very hard
using scanf. I simply would not try it. All the suggestions so far
are wrong in subtle ways.

The above fails because %*[\n] must match as least one character. The
match fails at that point (if there is nothing before the \n) and the
whole scanf return without doing the %*c (read without assigning a
char).

I'd use a getc call and a look to read and discard any remaining
characters up to the newline.
 
C

CBFalconer

hdsalbki said:
(e-mail address removed) wrote:
.... snip ...


Thank you vippstar. I will use int main(void) from now on and use
fflush(stdout) only when there is no \n after output. Okay I
confused the return keyword with if() and while() which need
brackets. And your change works! looking at info for getchar() it
says it is for reading single character...maybe I should've done
it with getchar()...thanks again.

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));
 
V

vippstar

You may have thought you picked an easy example, but this is very hard
using scanf. I simply would not try it. All the suggestions so far
are wrong in subtle ways.
My code along with the getchar() fix is fine.
The above fails because %*[\n] must match as least one character. The
Don't you mean %*[^\n]? Because that's what is used.
match fails at that point (if there is nothing before the \n) and the
whole scanf return without doing the %*c (read without assigning a
char).
Ah, so that's why that happends. Thanks.
<snip>
 
H

hdsalbki

Ben said:
hdsalbki said:
okay I followed everyone ideas and wrote another version of the
program. Now there is no extra prompt but the code misses every
alternate character I type. Can anyone help? Thanks a lot, never
imagined such a simple thing will be so difficult!

#include <stdio.h>

int main()
{
char a;
while(1)
{
printf("\nPlease enter a character: ");
fflush(stdout);
if(scanf("%c%*[^\n]%*c",&a) < 1)
{
break;
}
printf("You typed: %c\n",a);
fflush(stdout);
}
return(0);
}

You may have thought you picked an easy example, but this is very hard
using scanf. I simply would not try it. All the suggestions so far
are wrong in subtle ways.

The above fails because %*[\n] must match as least one character. The
match fails at that point (if there is nothing before the \n) and the
whole scanf return without doing the %*c (read without assigning a
char).

I'd use a getc call and a look to read and discard any remaining
characters up to the newline.

Thanks Ben. I see now that getc() is suited for this. I used scanf
because I have not yet arrived in my book where getchar()/getc() is
used.
 

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,774
Messages
2,569,596
Members
45,142
Latest member
arinsharma
Top