scanf experiments

  • Thread starter Steve Zimmerman
  • Start date
S

Steve Zimmerman

This post is not intended as an argument to any other post,
just some simple scanf experiments that I wanted to share.

I found experiments 5 and 6 the most educational. Also, I
thought experiment 3 would give some kind of weird error,
due to the lack of a space between the two `percent d's
in the scanf statement, but it didn't.


Experiment 1: ###########################

int var1, var2;

printf("Enter two integers: ");
scanf("%d%d", &var1, &var2);
/* input from keyboard: 12 13 */

printf("%d %d\n", var1, var2);
/* output to screen: 12 13 */

Experiment 2: ###########################

int var1, var2;

printf("Enter two integers: ");
/* input from keyboard: 12 <enter> 13 */
scanf("%d %d", &var1, &var2);

printf("%d %d\n", var1, var2);
/* output to screen: 12 13 */

Experiment 3: ###########################

int var1, var2;

printf("Enter two integers: ");
/* input from keyboard: 12 <enter> 13 */
scanf("%d%d", &var1, &var2);

printf("%d %d", var1, var2);
/* output to screen: 12 13 */

Experiment 4: ############################

char letter;
char plus_or_minus;

printf("Enter your grade: ");
/* input from keyboard: A+ */
scanf("%c%c", &letter, &plus_or_minus);

printf("Your grade is %c%c\n", letter, plus_or_minus);
/* output to screen: Your grade is A+ */

Experiment 5: #############################

char *grade;

printf("Enter your grade: ");
/* input from keyboard: A+ */
scanf("%s", &grade);

printf("Your grade is %s\n", grade);
/* output to screen: Segmentation fault */

Experiment 6: #############################

char grade[2];

printf("Enter your grade: ");
/* input from keyboard: A+ */
scanf("%s", &grade);

printf("Your grade is %s\n", grade);
/* output to screen: Your grade is A+ */

End of experiments #########################


Regards,

--Steve
 
I

Irrwahn Grausewitz

Steve Zimmerman said:
I found experiments 5 and 6 the most educational. Also, I
thought experiment 3 would give some kind of weird error,
due to the lack of a space between the two `percent d's
in the scanf statement, but it didn't.

Experiment 3: ###########################

int var1, var2;

printf("Enter two integers: ");
/* input from keyboard: 12 <enter> 13 */
scanf("%d%d", &var1, &var2);

printf("%d %d", var1, var2);
/* output to screen: 12 13 */

Hm, '\n' (produced by hitting enter after '12') is treated as
a white-space, just like a blank, so what kind of "weird error"
did you expect?

Experiment 6: #############################

char grade[2];

printf("Enter your grade: ");
/* input from keyboard: A+ */
scanf("%s", &grade);

printf("Your grade is %s\n", grade);
/* output to screen: Your grade is A+ */

You're out of luck here: you produced a buffer overflow, but
nothing serious did happen to show the error!

Irrwahn,
member of the scanf()-hater club.
[No intend to start a flame war.]
 
D

Denis Perelyubskiy

Steve,

Steve Zimmerman, 9/1/2003 4:26 PM:
[...snip...]
Experiment 5: #############################

char *grade;

printf("Enter your grade: ");
/* input from keyboard: A+ */
scanf("%s", &grade);

printf("Your grade is %s\n", grade);
/* output to screen: Segmentation fault */

[...snip...]

When you experiment with code, turn on all of your compiler
warnings. The point is to try to make sure you're testing what you
think you're testing.

In this particular case, I am not certain what it is you were out to
find out.

In particular, if you said something like:

char grade[100]; /* notice, not char *grade */
...
scanf("%s", grade); /* notice, not &grade */

then you'd end up with a working piece of code. Of course, as people
in this newsgroup point out every 5 minutes, there is nothing to
stop your user from entering >= 100 characters (scanf will add a
NULL-terminator) and overflow your buffer, producing unpredictable
results.

if you said:

char *grade;
...
scanf("%s", grade); /* notice, not &grade */

you'd also end up with an unpredictable result, since you'd be
writing to who-knows-where, since grade points into oblivion.

However, both of the aforementioned cases would not have produced a
warning (i think).

What you're doing in experiment 5, however, produces the following
warning on my compiler:

tmp.c:10: warning: char format, pointer arg (arg 2)

Note, that I am a bit puzzled by the wording. Intuitively, what
you're doing should produce a warning, and not work as expected :),
since you are supplying an address of a pointer, instead of
supplying a pointer to where scanf should write its characters.
However, I am not certain why gcc says that this is a char format
and a pointer argument. Regardless of the wording, you'd probably
get a warning, and go back to see why it is you're getting it :)

denis
 
S

Steve Zimmerman

Denis said:
Steve,

Steve Zimmerman, 9/1/2003 4:26 PM:
[...snip...]
Experiment 5: #############################

char *grade;

printf("Enter your grade: ");
/* input from keyboard: A+ */
scanf("%s", &grade);

printf("Your grade is %s\n", grade);
/* output to screen: Segmentation fault */



Denis wrote:

scanf("%s", grade); /* notice, not &grade */



Thank you for your advice, Denis; it suggests a new experiment:

Experiment 8 ###############################################

char *grade;

printf("Enter grades of comp.lang.c regulars: ");
/* input from keyboard: A+ */
scanf("%s", grade); /* grade with no ampersand */

printf("Your grade is %s\n", grade);
/* output to screen: Your grade is A+ */

#############################################################

I'm experimenting with scanf to see what behaviors it produces
with various declarations, various inputs,
various format strings, and various arguments.

Your post is quite helpful.


Regards,

--Steve
 
I

Irrwahn Grausewitz

Steve Zimmerman said:
Thank you for your advice, Denis; it suggests a new experiment:

Experiment 8 ###############################################

char *grade;

printf("Enter grades of comp.lang.c regulars: ");
/* input from keyboard: A+ */
scanf("%s", grade); /* grade with no ampersand */

printf("Your grade is %s\n", grade);
/* output to screen: Your grade is A+ */
Again, you failed to allocate some memory for grade to point to!!!
And, again, you came out without demons flying out of your nose,
but still buggy (read: invoking UB) code.
 
J

John Bode

Steve Zimmerman said:
This post is not intended as an argument to any other post,
just some simple scanf experiments that I wanted to share.

I found experiments 5 and 6 the most educational. Also, I
thought experiment 3 would give some kind of weird error,
due to the lack of a space between the two `percent d's
in the scanf statement, but it didn't.
[snip]

Experiment 3: ###########################

int var1, var2;

printf("Enter two integers: ");
/* input from keyboard: 12 <enter> 13 */
scanf("%d%d", &var1, &var2);

printf("%d %d", var1, var2);
/* output to screen: 12 13 */

Remember that the %d conversion specifier skips over any leading
whitespace, so the above behavior isn't "weird" at all. You could
have hit Enter 100 times between the two inputs; scanf() will discard
all of them until it sees another string of decimal digits.
Experiment 4: ############################

char letter;
char plus_or_minus;

printf("Enter your grade: ");
/* input from keyboard: A+ */
scanf("%c%c", &letter, &plus_or_minus);

printf("Your grade is %c%c\n", letter, plus_or_minus);
/* output to screen: Your grade is A+ */

Gak. Perfectly legal, but from a style perspective...gak. The %c
specifier is one of the few that doesn't skip leading whitespace, so
if you fatfinger a space or enter or something, your plus_or_minus
variable will have garbage in it. Better to read it all as one string
and then parse out the modifying character separately (I'm a big
believer in reading whole lines and parsing the line as a separate
exercise).
Experiment 5: #############################

char *grade;

printf("Enter your grade: ");
/* input from keyboard: A+ */
scanf("%s", &grade);

Hint: For the %s conversion specifier, scanf() expects an argument of
type char *. What is the type of grade? More importantly, what is
the type of &grade?
printf("Your grade is %s\n", grade);
/* output to screen: Segmentation fault */

You understand *why* this happened, right?
Experiment 6: #############################

char grade[2];

printf("Enter your grade: ");
/* input from keyboard: A+ */
scanf("%s", &grade);

Same question wrt grade as above. Just because it didn't crash and
gave the output you expected doesn't mean it's right. There's a bug
in this line.
printf("Your grade is %s\n", grade);
/* output to screen: Your grade is A+ */

Actually, there are two bugs. How big does a char array have to be to
hold a string N characters long?
 
I

Irrwahn Grausewitz

(e-mail address removed) (John Bode) wrote in
... (I'm a big
believer in reading whole lines and parsing the line as a separate
exercise).
We should open a scoreboard. It's 3:1 'gainst "TheRealOS/2Guy" already!

:)

<SNIP>
 
J

John Bode

Steve Zimmerman said:
Denis said:
Steve,

Steve Zimmerman, 9/1/2003 4:26 PM:
[...snip...]
Experiment 5: #############################

char *grade;

printf("Enter your grade: ");
/* input from keyboard: A+ */
scanf("%s", &grade);

printf("Your grade is %s\n", grade);
/* output to screen: Segmentation fault */



Denis wrote:

scanf("%s", grade); /* notice, not &grade */



Thank you for your advice, Denis; it suggests a new experiment:

Experiment 8 ###############################################

char *grade;

printf("Enter grades of comp.lang.c regulars: ");
/* input from keyboard: A+ */
scanf("%s", grade); /* grade with no ampersand */

There's still a bug here. Remember that your input string will not be
stored in the variable grade, but in the chunk of memory that the
variable grade *points to*. Does grade point anywhere meaningful yet?

Since grade is declared with auto extent, it isn't explicitly
initialized to any particular value, and therefore contains some
random bit string that may or may not correspond to a writable memory
address. You need to assign the address of a writable chunk of memory
of the right size to grade *before* you make the call to scanf(),
either by using malloc() to allocate the memory dynamically, or by
assigning the address of a statically allocated buffer.
printf("Your grade is %s\n", grade);
/* output to screen: Your grade is A+ */

#############################################################

I'm experimenting with scanf to see what behaviors it produces
with various declarations, various inputs,
various format strings, and various arguments.

This is the *exact wrong way* to learn *anything* about any
programming language. You would be much better served by finding an
authoritative C reference (I use Harbison & Steele's "C: A Reference
Manual") and reading up on how scanf() is *supposed* to work. It will
tell you what all the conversion specifiers are, how they recognize
input, what argument types they expect, etc. It will also tell you
what will happen if you enter values that cannot be represented by the
target types.

Blind experimentation will tell you *nothing* about how C really
works. You may write a program that appears to work perfectly, but in
reality invokes undefined behavior that just happens to do the right
thing for that particular program on that particular machine with that
particular compiler with that particular combination of options, and
any change in the above could lead to crashes (if you're lucky) or
weird behavior (if you're not).
 
A

Allin Cottrell

Denis said:
In particular, if you said something like:

char grade[100]; /* notice, not char *grade */
...
scanf("%s", grade); /* notice, not &grade */

then you'd end up with a working piece of code. Of course, as people in
this newsgroup point out every 5 minutes, there is nothing to stop your
user from entering >= 100 characters (scanf will add a NULL-terminator)
and overflow your buffer...

Nothing in the code as written above, but it's trivial to fix it:

scanf("%99s", grade);

Allin Cottrell.
 

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,744
Messages
2,569,483
Members
44,903
Latest member
orderPeak8CBDGummies

Latest Threads

Top