Watch this simple program. What happens?

Write here if you have problems with your C++ source code

Moderator: Board moderators

Post Reply
User avatar
ImLazy
Experienced poster
Posts: 215
Joined: Sat Jul 10, 2004 4:31 pm
Location: Shanghai, China

Watch this simple program. What happens?

Post by ImLazy » Sun May 15, 2005 6:22 am

Code: Select all

#include <iostream.h>
void main(){
  char c;
  int v;
    cin>>c;
    cout<<c;

    cin>>v;
    cout<<v;

    cin>>c;
    cout<<c;
    cin>>c;
    cout<<c;
    cin>>c;
    cout<<c;
    cin>>c;
    cout<<c;
    cin>>c;
    cout<<c;
    cin>>c;
    cout<<c;
    cin>>c;
    cout<<c;
    cin>>c;
    cout<<c;
    cin>>c;
    cout<<c;
    cin>>c;
    cout<<c;
    cin>>c;
    cout<<c;
}
When I input:

Code: Select all

ab
Why the output is:

Code: Select all

a0aaaaaaaaaaa
I just input "ab", how can the "cin>>c" get so many 'a'?!
Why???
I stay home. Don't call me out.

Iwashere
New poster
Posts: 20
Joined: Mon Aug 11, 2003 1:50 pm
Location: Singapore

Post by Iwashere » Sun May 15, 2005 10:38 am

It's quite expected behaviour based on your input.
First it assigns 'a' to c and prints it out. Then it tries to assign 'b' to v, but fails as v is an integer. Then it outputs the value of an uninitialised v. After that, all the cins fail to work and the value of c is printed repeatedly.

User avatar
ImLazy
Experienced poster
Posts: 215
Joined: Sat Jul 10, 2004 4:31 pm
Location: Shanghai, China

Post by ImLazy » Mon May 16, 2005 12:49 pm

When I replace all the "cin" with "scanf()", the program works. Then can I say scanf() is better than cin>>, becuase even though a scanf("%d") fails to read a integer, other scanf() can still work?
I stay home. Don't call me out.

Ronald29
New poster
Posts: 15
Joined: Sat May 24, 2003 3:57 am

Post by Ronald29 » Tue May 17, 2005 5:48 am

ImLazy, cin can do just like scanf.
in your program, the other cin don't work because the enter key that you press after the 'ab' input. the other cin will read the enter key. that's because the enter key is still in the input buffer.
If you want to make the other cin works, first, you must clear the input buffer. you can use cin.clear(). the scanf() function can also fail (skipped), but you can't use cin.clear() on scanf(), you should use fflush(stdin).

hope this helps.

User avatar
Krzysztof Duleba
Guru
Posts: 584
Joined: Thu Jun 19, 2003 3:48 am
Location: Sanok, Poland
Contact:

Post by Krzysztof Duleba » Tue May 17, 2005 7:02 am

You've got it all confused.

clear() is a stream method that clears it's flags. If a stream encounters a problem (EOF or a non-digit character when an int is expected, for instace), it sets the fail flag. You can test that flag with fail() method or even by casting the stream to a bool, like in "if(cin){...}", which is equivalent to "if(! cin.fail()){}". There are also some other useful flags.

If scanf fails, no error flags are set (at least when everything goes well). scanf returns how many fields were successfully read.

fflusing input stream is pointless as it has no effect. fflush is a function that makes an _output_ buffer to deliver any pending output.

User avatar
Yile
New poster
Posts: 17
Joined: Sun Feb 27, 2005 10:36 am
Location: China

Post by Yile » Tue May 17, 2005 7:57 am

Oh, I see. I can use cin.fail() to see whether there is an input error, and use cin.clear to make the cin>> work again.
Thank you.

Ronald29
New poster
Posts: 15
Joined: Sat May 24, 2003 3:57 am

Post by Ronald29 » Wed May 18, 2005 5:54 am

hmmm, maybe my explanation is confusing or even wrong, but i have a simple example the usage of fflush(stdin). for example, this code. the code wants to receive 2 input. the second scanf() isn't work. to make it work, u can use fflush(stdin) after the first input.

#include <stdio.h>
void main()
{
char c;
printf("char1: ");scanf("%c", &c);
printf("char2: ");scanf("%c", &c);
}


#include <stdio.h>
void main()
{
char c;
printf("char1: ");scanf("%c", &c);
fflush(stdin);
printf("char2: ");scanf("%c", &c);
}

Thank You.

misof
A great helper
Posts: 430
Joined: Wed Jun 09, 2004 1:31 pm

Post by misof » Wed May 18, 2005 12:41 pm

You ARE wrong.

First, read this: http://faq.cprogramming.com/cgi-bin/sma ... 1043284351
The behaviour of flushing an input buffer is undefined... and thus it doesn't do the same on all systems.

Second, consider the following code:

Code: Select all

[misof@elvander]:~/Temp/delme$ cat a.c
#include <stdio.h>
int main(void)
{
  char c1,c2;
  printf("char1: ");scanf("%c", &c1);
  printf("char2: ");scanf("%c", &c2);
  printf("both chars: %c%c\n",c1,c2);
  return 0;
}
[misof@elvander]:~/Temp/delme$ gcc a.c
[misof@elvander]:~/Temp/delme$ echo -e "ab\n" | ./a.out
char1: char2: both chars: ab
[misof@elvander]:~/Temp/delme$ echo -e "a\nb\n" | ./a.out
char1: char2: both chars: a

[misof@elvander]:~/Temp/delme$ vim a.c
[misof@elvander]:~/Temp/delme$ cat a.c
#include <stdio.h>
int main(void)
{
  char c1,c2;
  printf("char1: ");scanf("%c", &c1);
  fflush(stdin);
  printf("char2: ");scanf("%c", &c2);
  printf("both chars: %c%c\n",c1,c2);
  return 0;
}
[misof@elvander]:~/Temp/delme$ gcc a.c
[misof@elvander]:~/Temp/delme$ ./a.out
char1: a
char2: both chars: a

[misof@elvander]:~/Temp/delme$ vim a.c
[misof@elvander]:~/Temp/delme$ cat a.c
#include <stdio.h>
int main(void)
{
  char c1,c2;
  printf("char1: ");scanf(" %c", &c1);
  printf("char2: ");scanf(" %c", &c2);
  printf("both chars: %c%c\n",c1,c2);
  return 0;
}
[misof@elvander]:~/Temp/delme$ gcc a.c
[misof@elvander]:~/Temp/delme$ echo -e "a\nb\n" | ./a.out
char1: char2: both chars: ab
The first example is your original program. If the input contains two consecutive chars, everything works as planned. However, most probably you are entering your input as a<Return>b<Return>. This is what the second run does. Now the first scanf reads the "a", the second one reads the linefeed (or carriage return on other systems). This is what you probably refer to as "doesn't work".

On Linux (i.e. also here on the UVa), your modified code does exactly the same.

The correct way of getting the intended result is to understand how scanf() handles whitespace... and how input buffers work. If you run the program interactively, everything you type is sent to the program only after you press <Return>. Thus you have to press <Return> before you see the second message. Now, scanf("%c",...) reads the next character from the input buffer, be it a space, an end of line, whatever.

Note that in the third example a space is added in the format string before the "%c". A space in the format string says to scanf: "skip all the whitespace on the current position". Thus, when reading the next char, my scanf first skips all spaces, tabs, linefeeds, etc. and reads the first non-blank character. This is probably what you had in mind.

Ronald29
New poster
Posts: 15
Joined: Sat May 24, 2003 3:57 am

Post by Ronald29 » Thu May 19, 2005 3:59 am

You're right misof.
Thanks for the info.
:D

Post Reply

Return to “C++”