Velocity Reviews - Computer Hardware Reviews

Velocity Reviews > Newsgroups > Programming > C Programming > scanf experiments

Reply
Thread Tools

scanf experiments

 
 
Steve Zimmerman
Guest
Posts: n/a
 
      09-01-2003
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

 
Reply With Quote
 
 
 
 
Irrwahn Grausewitz
Guest
Posts: n/a
 
      09-02-2003
Steve Zimmerman <(E-Mail Removed)> wrote in
<(E-Mail Removed)>:
>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 */


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?

<SNIP>
>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.]
--
If it's not on fire, it's a software problem.
 
Reply With Quote
 
 
 
 
Denis Perelyubskiy
Guest
Posts: n/a
 
      09-02-2003
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


--
'From' email address is used as a sink. Not read. Ever.
Instead, send to [p-o-s-t-i-n-g|o-v-e-r-w-h-e-l-m|n-e-t]
(remove dashes, replace the first vertical bar with @,
and second with a dot). Sorry for any inconvenience.

 
Reply With Quote
 
Steve Zimmerman
Guest
Posts: n/a
 
      09-02-2003
Denis Perelyubskiy wrote:

> 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

 
Reply With Quote
 
Irrwahn Grausewitz
Guest
Posts: n/a
 
      09-02-2003
Steve Zimmerman <(E-Mail Removed)> wrote in
<(E-Mail Removed)>:
>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+ */

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.

--
Air is water with holes in it.
 
Reply With Quote
 
John Bode
Guest
Posts: n/a
 
      09-02-2003
Steve Zimmerman <(E-Mail Removed)> wrote in message news:<(E-Mail Removed)>...
> 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?

> End of experiments #########################
>
>
> Regards,
>
> --Steve

 
Reply With Quote
 
Irrwahn Grausewitz
Guest
Posts: n/a
 
      09-02-2003
http://www.velocityreviews.com/forums/(E-Mail Removed) (John Bode) wrote in
<(E-Mail Removed) >:
<SNIP>
> ... (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>
--
Air is water with holes in it.
 
Reply With Quote
 
John Bode
Guest
Posts: n/a
 
      09-02-2003
Steve Zimmerman <(E-Mail Removed)> wrote in message news:<(E-Mail Removed)>...
> Denis Perelyubskiy wrote:
>
> > 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).

> Your post is quite helpful.
>
>
> Regards,
>
> --Steve

 
Reply With Quote
 
Allin Cottrell
Guest
Posts: n/a
 
      09-03-2003
Denis Perelyubskiy wrote:

> 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.

 
Reply With Quote
 
 
 
Reply

Thread Tools

Posting Rules
You may not post new threads
You may not post replies
You may not post attachments
You may not edit your posts

BB code is On
Smilies are On
[IMG] code is On
HTML code is Off
Trackbacks are On
Pingbacks are On
Refbacks are Off


Similar Threads
Thread Thread Starter Forum Replies Last Post
difference between scanf("%i") and scanf("%d") ??? perhaps bug inVS2005? =?ISO-8859-1?Q?Martin_J=F8rgensen?= C Programming 18 05-02-2006 10:53 AM
scanf (yes/no) - doesn't work + deprecation errors scanf, fopen etc. =?ISO-8859-1?Q?Martin_J=F8rgensen?= C Programming 185 04-03-2006 02:49 PM
Experiments with speech to text Roedy Green Java 6 07-13-2004 07:42 PM
malloc experiments Steve Zimmerman C Programming 11 09-10-2003 06:40 PM
malloc experiments Steve Zimmerman C Programming 52 09-07-2003 03:17 AM



Advertisments