scanf() wierdness

E

Eduardo Olivarez

The following code does not work correctly on my machine. Either one of the
scanf()'s alone work perfectly. However, when they are combined, the second
scanf() call just reads what the first one received as imput, without
taking any keyboard input and then the process terminates prematurely. I
looked through the glibc documentation trying to figure out what was
causing this to no avail, so I started messing around with the code.
Strangely enough, adding a call to getchar() in between the first scanf and
the second printf solves the problem. I have no idea why. Anyone kind
enough to enlighten me as to whats going on?

Non working code (minimized to isolate error):

#include <stdio.h>
#include <stdlib.h>
#include <ctype.h>

#define STRLEN 100

int main(void) {
int shift;
char *string;

string = (char *) malloc(sizeof(char) * STRLEN);

printf("Input a number: ");
scanf("%d", &shift);
printf("Input a string: ");
scanf("%[^\n]100", string);

printf("%d\n", shift);
printf("%s\n", string);
}

Working code:

#include <stdio.h>
#include <stdlib.h>
#include <ctype.h>

#define STRLEN 100

int main(void) {
int shift;
char *string;

string = (char *) malloc(sizeof(char) * STRLEN);

printf("Input a number: ");
scanf("%d", &shift);
getchar();
printf("Input a string: ");
scanf("%[^\n]100", string);

printf("%d\n", shift);
printf("%s\n", string);
}

Output of non working code:

remus@phobos remus $ ./test
Input a number: 12
Input a string: 12

remus@phobos remus $
 
M

Mad Wizard

If I understand correctly, scanf pushes back at least one
character in the input stream. When you get the number from stdin, you
terminate input with newline character, which is pushed back in the
stdin. When you call scanf second time, it starts to read stdin and the
very first character is newline, so it stops reading.
 
D

Darrell Grainger

The following code does not work correctly on my machine. Either one of the
scanf()'s alone work perfectly. However, when they are combined, the second
scanf() call just reads what the first one received as imput, without
taking any keyboard input and then the process terminates prematurely. I
looked through the glibc documentation trying to figure out what was
causing this to no avail, so I started messing around with the code.
Strangely enough, adding a call to getchar() in between the first scanf and
the second printf solves the problem. I have no idea why. Anyone kind
enough to enlighten me as to whats going on?

It is more accurate to say that "the followiung code does not do what I
expect on my machine." The problem is usually that it does the correct
thing but that we tend to misunderstand what the correct thing it.
Non working code (minimized to isolate error):

#include <stdio.h>
#include <stdlib.h>
#include <ctype.h>

#define STRLEN 100

int main(void) {
int shift;
char *string;

string = (char *) malloc(sizeof(char) * STRLEN);

You shouldn't need the cast. If you failed to #include <stdlib.h> the
compiler will assume that malloc returns an int and that you want to cast
the int to a pointer to char. This is undefined behaviour. Just don't cast
the result of malloc. It should be returning a pointer to void and not
need the cast.

Additionally, sizeof(char) is always 1. Seems redundant to use it here.
printf("Input a number: ");

Add a fflush(stdout); after the printf. Search the newsgroup for
'fflush(stdout)' and you'll probably find the explanation as to why.
scanf("%d", &shift);

If the user inputs "123\n" then scanf will read the "123", convert it to
123 and assign it to shift. The "\n" can remain on the stream.
printf("Input a string: ");
scanf("%[^\n]100", string);

This indicates to read 100 char until you reach a newline character. The
last scanf left the '\n' in the stream so this quits immediate and returns
0. You should check the return value of scanf and see if it was
successful. Your code below assumes it was. Don't assume when you can
check.
printf("%d\n", shift);
printf("%s\n", string);

return 0;

It is usually better to use fgets() to read in a line from the user then
use sscanf to scan the string. This will 'flush' the newline character
from the stdin stream.
Working code:

#include <stdio.h>
#include <stdlib.h>
#include <ctype.h>

#define STRLEN 100

int main(void) {
int shift;
char *string;

string = (char *) malloc(sizeof(char) * STRLEN);

printf("Input a number: ");
scanf("%d", &shift);
getchar();

This is a hack. Without understanding why you need this you should assume
the code still does not work. You can only assume it APPEARS to work. On
future runs it might fail.
printf("Input a string: ");
scanf("%[^\n]100", string);

printf("%d\n", shift);
printf("%s\n", string);
}

Output of non working code:

remus@phobos remus $ ./test
Input a number: 12
Input a string: 12

remus@phobos remus $
 
O

Old Wolf

string = (char *) malloc(sizeof(char) * STRLEN);
You shouldn't need the cast. If you failed to #include <stdlib.h> the
compiler will assume that malloc returns an int and that you want to cast
the int to a pointer to char. This is undefined behaviour. Just don't cast
the result of malloc. It should be returning a pointer to void and not
need the cast.

Additionally, sizeof(char) is always 1. Seems redundant to use it here.

Argh. I count 6 different active threads (posted to in the last
24 hours) where someone has "corrected" someone else's non-buggy
use of malloc(). Perhaps we need a new group, comp.lang.c.malloc ?
 
P

Peter Shaggy Haywood

Groovy hepcat Eduardo Olivarez was jivin' on Fri, 23 Jan 2004 08:17:31
GMT in comp.lang.c.
scanf() wierdness's a cool scene! Dig it!
The following code does not work correctly on my machine. Either one of the
scanf()'s alone work perfectly. However, when they are combined, the second
scanf() call just reads what the first one received as imput, without

READ THE FAQ!!! The FAQ exists for a reason: to answer questions
like this. Yet we still have to constantly tell people to read the
FAQ. This should be taken for granted, but no! You should also read
the newsgroup for some time. Your question is answered all the time.
You would know that if you had lurked here and read the FAQ, as you
should have done. It is very rude to post to a newsgroup without first
lurking for a while and reading its FAQ.
If I sound mean I'm sorry, but I'm tired of telling people to lurk
and read the FAQ. It should be the first thing you do when you enter a
newsgroup for the first time.
Lurk and ye shall see the FAQs.

--

Dig the even newer still, yet more improved, sig!

http://alphalink.com.au/~phaywood/
"Ain't I'm a dog?" - Ronny Self, Ain't I'm a Dog, written by G. Sherry & W. Walker.
I know it's not "technically correct" English; but since when was rock & roll "technically correct"?
 
Z

Zoran Cutura

Old Wolf said:
Argh. I count 6 different active threads (posted to in the last
24 hours) where someone has "corrected" someone else's non-buggy
use of malloc(). Perhaps we need a new group, comp.lang.c.malloc ?

Oh, actually I think CLC considers such usage of malloc to be buggy.
There are arguments against such usage and as some say there are for.
But I personally do not understand those who say that you should cast
mallocs return value.
Why would you say someone should cast malloc?
 

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,755
Messages
2,569,536
Members
45,009
Latest member
GidgetGamb

Latest Threads

Top