Newbie Q: Interactive program eats up CPU

P

Pan Yongzhi

Hi all,

I wrote a simple C program, exactly at the bottom of this post. It's an
interactively game, needing user's input. When invoked at the Linux
shell, it works OK. But if I click in my ROX-Filer, nothing popups
since no GUI, but it then cosume almost 100% of my CPU time. I have to
kill it. I'd like to know if I can make it quit silently when It's
clicked. Thank you very much. Below is the whole source.

Pan

------------------------------------- start of source
---------------------------------------
/*
* 4digits - This program make the interactive game Guess-the-Number
game
* available on PC and other architectures.
*
* Copyright (C) 2005 Pan Yongzhi
* Reach me: http://pan.cdut.cn or fossilet@@163..com
*
* This program is free software; you can redistribute it and/or
* modify it under the terms of the GNU General Public License
* as published by the Free Software Foundation; either version 2
* of the License, or (at your option) any later version.
*
* This program is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
* GNU General Public License for more details.
*
* You should have received a copy of the GNU General Public License
* along with this program; if not, write to the Free Software
* Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA
02111-1307, USA
* or see http://www.gnu.org/copyleft/gpl.html.
*
*/
# include <stdio.h>
# include <stdlib.h>
# include <math.h>
# include <time.h>
# include <ctype.h>
# define VERSION_STRING "4digits-0.1"
# define COPYRIGHT \
"4digits 0.1, Dec 2005\n\
Copyright (C) 2004, 2005 Pan Yongzhi\n\
4digits comes with NO WARRANTY to the extent permitted by law. This
program\n\
is free software; you can redistribute it and/or modify it under the
terms\n\
of the GNU General Public License as published by the Free Software\n\
Foundation - version 2. For more information about these matters, see
the\n\
file named COPYING.\n\n"

int main(void)
{
int n; /* the 4-digit number to be guessed*/
char mstr[4]; /* string for the 4-digit number */
int m; /* the 4-digit number inputted */
int i,j; /* counters for the 4 digits, <=4*/
int cnt; /* counter for the time of guess, <=8*/
int A; /* number of digits both value and place is right*/
int B; /* number of digits only vaule but place is right*/
int nd[4]= {0,0,0,0}; /* 4x1 array for the 4 digits of n*/
int md[4]={0,0,0,0}; /* 4x1 arrays for the 4 digits of m*/
time_t t; /* time_t type variable, to be seed for random n*/
printf(COPYRIGHT);
cnt = 0;

srand((int) time(&t));
n = 1000 + (int) ( 8999.0 * rand() / RAND_MAX );

/* generate a random 4-digit number*/
/* if the digits of n is not different from each other, regenerate
it*/
while(nd[0]==nd[1] || nd[1]==nd[2] || nd[2]==nd[3] || nd[0]==nd[2] ||
nd[0]==nd[3] || nd[1]==nd[3])
{
srand(n);
n = 1000 + (int) ( 8999.0 * rand() / RAND_MAX );
for(i=0;i<4;i++)
nd=(int) ( n / pow(10,3-i) )%10;
}

do
{
printf("Input a 4-digit number:");
fflush(NULL);
scanf("%s", mstr);
m = atoi(mstr);
if ((m < 1000) | (m > 9999))
{
printf("%d: input error!\n", m);
cnt--;
continue;
}
for(i=0;i<4;i++)
md=(int) ( m / pow(10,3-i) )%10;
/*comparision of nd & md*/
A=0, B=0;
for(i=0;i<4;i++)
for(j=0;j<4;j++)
if(md==nd[j])
(i==j) ? A++:B++;
printf("%dA%dB ",A,B);
printf("\t %d times left.\n", 7-cnt);
if(A==4)
printf("You win!\n"), exit(0);
}while(cnt++<=7);

printf("Hahah, you lose. It is %d.\n", n);
return 0;
}
------------------------------------- end of source
---------------------------------------
 
W

Walter Roberson

I wrote a simple C program, exactly at the bottom of this post. It's an
interactively game, needing user's input. When invoked at the Linux
shell, it works OK. But if I click in my ROX-Filer, nothing popups
since no GUI, but it then cosume almost 100% of my CPU time.
srand((int) time(&t));
n = 1000 + (int) ( 8999.0 * rand() / RAND_MAX );

/* generate a random 4-digit number*/
/* if the digits of n is not different from each other, regenerate
it*/
while(nd[0]==nd[1] || nd[1]==nd[2] || nd[2]==nd[3] || nd[0]==nd[2] ||
nd[0]==nd[3] || nd[1]==nd[3])
{
srand(n);

You should only rarely reseed your random number generator.

First you seed it with the time. Once that seed is set, the rand()
call in calculating n will follow a fixed formula to produce the
next random number based upon the current seed.

You then take that possibly-large result and multiply it by ~8999,
converting to double in the process, and divide that by RAND_MAX.
You would be safer off using 8999.0 * ((double)rand() / RAND_MAX)
as that prevents the possibility that 8999.0 * rand loses
precision.

There is only one possible value of n for any given original
seed (the seed based upon the time), and you re-seed the random
number generator with it, which can only produce one possible result
from the original time.
n = 1000 + (int) ( 8999.0 * rand() / RAND_MAX );

Again, once that time() was determined, there is only one
possible rand() that can can make it to the here the first
time through, and each iteration after that is fixed by the
srand()... so all the way back, your results will depend
solely upon that original time.

for(i=0;i<4;i++)
nd=(int) ( n / pow(10,3-i) )%10;
}


Those values are going to depend solely upon the calculated n,
by you are unnecessarily working with floating point in
this loop. You can do the same thing with:

for(i=0;i<4;i++) { nd[3-i] = n % 10; n /= 10; }
do
{
printf("Input a 4-digit number:");
fflush(NULL);

There is no certainty that that will appear on the screen.
You do fflush(), which is good, but the behaviour is
operating system defined when your output line does not end
with \n .

scanf("%s", mstr);

If scanf() fails, then mstr will be left with an indefinite
value, since you do not initialize mstr . That indefinite value
likely does not fall into the right range, so your program
probably ends up looping around printing errors about
bad input, then failing on the next scanf, failing again
the same way, and so on. You really need to check the result
of scanf().

Speaking of scanf(), you have:

char mstr[4]; /* string for the 4-digit number */

but if the user actually enters 4 digits, then the null that scanf()
is going to write afterwards is going to get written to some
indeterminate location in memory, scribbling over top of whatever
was there. If you want to allow for 4 digits of input, you need
at least char [5], with the 5th holding the null. And you need to
adjust your arguments to scanf() to prevent the possibility that the
user accidently entered too many characters... and you need to
adjust the logic about what you do after that because if the user
did happen to type in too many characters, the remainder are going
to be left in the input buffer for the next scanf(), but you
probably want to some out get them out of that input buffer until
the end of the input line...
 
I

ionshift

As a little tip, you don't really need to create a time_t variable to
seed the random number generator of the standard library function
srand(). You can can just call it as srand(time(NULL)), which actually
works the same way.
 
K

Keith Thompson

ionshift said:
As a little tip, you don't really need to create a time_t variable to
seed the random number generator of the standard library function
srand(). You can can just call it as srand(time(NULL)), which actually
works the same way.

As another little tip, please read <http://cfaj.freeshell.org/google/>.
Thank you.
 
T

Tydr Schnubbis

Pan said:
Hi all,

I wrote a simple C program, exactly at the bottom of this post. It's an
interactively game, needing user's input. When invoked at the Linux
shell, it works OK. But if I click in my ROX-Filer, nothing popups
since no GUI, but it then cosume almost 100% of my CPU time. I have to
kill it. I'd like to know if I can make it quit silently when It's
clicked. Thank you very much. Below is the whole source.

Pan
You should probably ask about this in a linux programming newsgroup,
since you can't really do what you want with standard C functions. Or
try your luck at the ROX web site.
------------------------------------- start of source
---------------------------------------
/*
* 4digits - This program make the interactive game Guess-the-Number
game
* available on PC and other architectures.
*
* Copyright (C) 2005 Pan Yongzhi
* Reach me: http://pan.cdut.cn or fossilet@@163..com
*
* This program is free software; you can redistribute it and/or
* modify it under the terms of the GNU General Public License
* as published by the Free Software Foundation; either version 2
* of the License, or (at your option) any later version.
*
* This program is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
* GNU General Public License for more details.
*
* You should have received a copy of the GNU General Public License
* along with this program; if not, write to the Free Software
* Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA
02111-1307, USA
* or see http://www.gnu.org/copyleft/gpl.html.
*
*/
# include <stdio.h>
# include <stdlib.h>
# include <math.h>
# include <time.h>
# include <ctype.h>
# define VERSION_STRING "4digits-0.1"
# define COPYRIGHT \
"4digits 0.1, Dec 2005\n\
Copyright (C) 2004, 2005 Pan Yongzhi\n\
4digits comes with NO WARRANTY to the extent permitted by law. This
program\n\
is free software; you can redistribute it and/or modify it under the
terms\n\
of the GNU General Public License as published by the Free Software\n\
Foundation - version 2. For more information about these matters, see
the\n\
file named COPYING.\n\n"
You could make the copyright string just a char array, and put the
version string into it like this:

#define VERSION_STRING "0.1, Dec 2005"
const char copyright[] = "4digits " VERSION_STRING "\n"
"Copyright (C) 2004, 2005 Pan Yongzhi\n"
"etcetera...\n\n"

Then you won't have to remember to update the version in two places.
int main(void)
{
int n; /* the 4-digit number to be guessed*/
char mstr[4]; /* string for the 4-digit number */
int m; /* the 4-digit number inputted */
int i,j; /* counters for the 4 digits, <=4*/
int cnt; /* counter for the time of guess, <=8*/
int A; /* number of digits both value and place is right*/
int B; /* number of digits only vaule but place is right*/
int nd[4]= {0,0,0,0}; /* 4x1 array for the 4 digits of n*/
int md[4]={0,0,0,0}; /* 4x1 arrays for the 4 digits of m*/
time_t t; /* time_t type variable, to be seed for random n*/
If you use more descriptive names, you don't need the comments, and your
code is easier to understand. Like this:

int answer;
char guess_str[] = "0000";
int guess;
int i, j;
int num_guesses;
int num_correct;
int num_wrong;

I also changed guess_str to 4 zero-initialized digits, that's a good
starting point. And it has space for a null terminator, which it needs
if you're going to fill it with a string of four digits.
printf(COPYRIGHT);
printf("%s", COPYRIGHT); might be better. That way you don't get
problems if COPYRIGHT contains something that looks like a format specifier.
cnt = 0;

srand((int) time(&t));
n = 1000 + (int) ( 8999.0 * rand() / RAND_MAX );
The simplest way is just n = 1000 + rand()%9000;
But I'm not sure if one way gives better results than the other.
/* generate a random 4-digit number*/
/* if the digits of n is not different from each other, regenerate
it*/
while(nd[0]==nd[1] || nd[1]==nd[2] || nd[2]==nd[3] || nd[0]==nd[2] ||
nd[0]==nd[3] || nd[1]==nd[3])
{
srand(n);
n = 1000 + (int) ( 8999.0 * rand() / RAND_MAX );
for(i=0;i<4;i++)
nd=(int) ( n / pow(10,3-i) )%10;

If you just need n as a string, do this:
sprintf(nd, "%d", n);
}

do
{
printf("Input a 4-digit number:");
fflush(NULL);
scanf("%s", mstr);
This will cause a buffer overflow if the user types something like
"12345678", because scanf reads the whole thing. You can limit how much
scanf reads by using a format string like "%4s" instead.

scanf can also read the number directly with "%d".

if (scanf("%d", n) != 1)
/* if scanf didn't return 1, it was unable to find a number */

To skip any remaining characters after the ones you want, you can use a
while loop and getchar:

while (getchar() != EOF);

You can also try fflush(stdin), but that's not portable.
m = atoi(mstr);
if ((m < 1000) | (m > 9999))
{
printf("%d: input error!\n", m);
cnt--;
continue;
}
for(i=0;i<4;i++)
md=(int) ( m / pow(10,3-i) )%10;
/*comparision of nd & md*/
A=0, B=0;
for(i=0;i<4;i++)
for(j=0;j<4;j++)
if(md==nd[j])
(i==j) ? A++:B++;
printf("%dA%dB ",A,B);
printf("\t %d times left.\n", 7-cnt);
if(A==4)
printf("You win!\n"), exit(0);

It's not very common to use the comma operator like this, just put
exit(0) on its on line instead. Best not to hide important stuff at the
end of the line. ;)
 
T

Tydr Schnubbis

Tydr said:
Pan Yongzhi wrote:
[snip]
/* generate a random 4-digit number*/
/* if the digits of n is not different from each other, regenerate
it*/
while(nd[0]==nd[1] || nd[1]==nd[2] || nd[2]==nd[3] || nd[0]==nd[2] ||
nd[0]==nd[3] || nd[1]==nd[3])
{
srand(n);
n = 1000 + (int) ( 8999.0 * rand() / RAND_MAX );
for(i=0;i<4;i++)
nd=(int) ( n / pow(10,3-i) )%10;

If you just need n as a string, do this:
sprintf(nd, "%d", n);

Seems I was a little too quick there, since nd is an array of ints, not
chars. But if you have char nd[5], you can do the same thing and it
should work. You can compare the chars directly, since you don't need
to know which numbers they are, just if they are the same or not. But
since you've already written the conversion...
}

do
{
printf("Input a 4-digit number:");
fflush(NULL);
scanf("%s", mstr);
This will cause a buffer overflow if the user types something like
"12345678", because scanf reads the whole thing. You can limit how much
scanf reads by using a format string like "%4s" instead.

scanf can also read the number directly with "%d".

if (scanf("%d", n) != 1)
/* if scanf didn't return 1, it was unable to find a number */

To skip any remaining characters after the ones you want, you can use a
while loop and getchar:

while (getchar() != EOF);

You can also try fflush(stdin), but that's not portable.
m = atoi(mstr);
if ((m < 1000) | (m > 9999))
{
printf("%d: input error!\n", m);
cnt--;
continue;
}
for(i=0;i<4;i++)
md=(int) ( m / pow(10,3-i) )%10;
/*comparision of nd & md*/
A=0, B=0;
for(i=0;i<4;i++)
for(j=0;j<4;j++)
if(md==nd[j])
(i==j) ? A++:B++;
printf("%dA%dB ",A,B);
printf("\t %d times left.\n", 7-cnt);
if(A==4)
printf("You win!\n"), exit(0);

It's not very common to use the comma operator like this, just put
exit(0) on its on line instead. Best not to hide important stuff at the
end of the line. ;)
}while(cnt++<=7);

printf("Hahah, you lose. It is %d.\n", n);
return 0;
}
------------------------------------- end of source
 
P

Pan Yongzhi

Walter said:
srand((int) time(&t));
n = 1000 + (int) ( 8999.0 * rand() / RAND_MAX );

/* generate a random 4-digit number*/
/* if the digits of n is not different from each other, regenerate
it*/
while(nd[0]==nd[1] || nd[1]==nd[2] || nd[2]==nd[3] || nd[0]==nd[2] ||
nd[0]==nd[3] || nd[1]==nd[3])
{
srand(n);

You should only rarely reseed your random number generator.

First you seed it with the time. Once that seed is set, the rand()
call in calculating n will follow a fixed formula to produce the
next random number based upon the current seed.

You then take that possibly-large result and multiply it by ~8999,
converting to double in the process, and divide that by RAND_MAX.
You would be safer off using 8999.0 * ((double)rand() / RAND_MAX)
as that prevents the possibility that 8999.0 * rand loses
precision.

Thank you. I get it! I read `man 3 rand` but missed a pair of brackets.
do
{
printf("Input a 4-digit number:");
fflush(NULL);

There is no certainty that that will appear on the screen.
You do fflush(), which is good, but the behaviour is
operating system defined when your output line does not end
with \n .

scanf("%s", mstr);

If scanf() fails, then mstr will be left with an indefinite
value, since you do not initialize mstr . That indefinite value
likely does not fall into the right range, so your program
probably ends up looping around printing errors about
bad input, then failing on the next scanf, failing again
the same way, and so on. You really need to check the result
of scanf().


Speaking of scanf(), you have:

char mstr[4]; /* string for the 4-digit number */

but if the user actually enters 4 digits, then the null that scanf()
is going to write afterwards is going to get written to some
indeterminate location in memory, scribbling over top of whatever
was there. If you want to allow for 4 digits of input, you need
at least char [5], with the 5th holding the null. And you need to
adjust your arguments to scanf() to prevent the possibility that the
user accidently entered too many characters... and you need to
adjust the logic about what you do after that because if the user
did happen to type in too many characters, the remainder are going
to be left in the input buffer for the next scanf(), but you
probably want to some out get them out of that input buffer until
the end of the input line...

So I better off use scanf("%4s", mstr)? This will not overwrite unknow
memory when the input is longer than 4 bytes? But why my original code
runs OK? But another problem occurs when the input is longer than 4:
next scanf does not pause for my input and skips with possibly wrong
data. The longer the input, the more scanf's skipped. It seems a mess
to correctly and safely deal with scanf input. I once tried gets, but
gcc told me it's dangerous. Can you be a little more elaborate on this?
It's really kind of you.
 
P

Pan Yongzhi

Walter said:
srand((int) time(&t));
n = 1000 + (int) ( 8999.0 * rand() / RAND_MAX );

/* generate a random 4-digit number*/
/* if the digits of n is not different from each other, regenerate
it*/
while(nd[0]==nd[1] || nd[1]==nd[2] || nd[2]==nd[3] || nd[0]==nd[2] ||
nd[0]==nd[3] || nd[1]==nd[3])
{
srand(n);

You should only rarely reseed your random number generator.

First you seed it with the time. Once that seed is set, the rand()
call in calculating n will follow a fixed formula to produce the
next random number based upon the current seed.

You then take that possibly-large result and multiply it by ~8999,
converting to double in the process, and divide that by RAND_MAX.
You would be safer off using 8999.0 * ((double)rand() / RAND_MAX)
as that prevents the possibility that 8999.0 * rand loses
precision.

Thank you. I get it! I read `man 3 rand` but missed a pair of brackets.
do
{
printf("Input a 4-digit number:");
fflush(NULL);

There is no certainty that that will appear on the screen.
You do fflush(), which is good, but the behaviour is
operating system defined when your output line does not end
with \n .

scanf("%s", mstr);

If scanf() fails, then mstr will be left with an indefinite
value, since you do not initialize mstr . That indefinite value
likely does not fall into the right range, so your program
probably ends up looping around printing errors about
bad input, then failing on the next scanf, failing again
the same way, and so on. You really need to check the result
of scanf().


Speaking of scanf(), you have:

char mstr[4]; /* string for the 4-digit number */

but if the user actually enters 4 digits, then the null that scanf()
is going to write afterwards is going to get written to some
indeterminate location in memory, scribbling over top of whatever
was there. If you want to allow for 4 digits of input, you need
at least char [5], with the 5th holding the null. And you need to
adjust your arguments to scanf() to prevent the possibility that the
user accidently entered too many characters... and you need to
adjust the logic about what you do after that because if the user
did happen to type in too many characters, the remainder are going
to be left in the input buffer for the next scanf(), but you
probably want to some out get them out of that input buffer until
the end of the input line...

So I better off use scanf("%4s", mstr)? This will not overwrite unknow
memory when the input is longer than 4 bytes? But why my original code
runs OK? But another problem occurs when the input is longer than 4:
next scanf does not pause for my input and skips with possibly wrong
data. The longer the input, the more scanf's skipped. It seems hard to
correctly and safely deal with scanf input. I once tried gets, but gcc
told me it's dangerous. Can you be a little more elaborate on this?
It's really kind of you.
 
P

Pan Yongzhi

Tydr said:
You should probably ask about this in a linux programming newsgroup,
since you can't really do what you want with standard C functions. Or
try your luck at the ROX web site.

I open a Konqueror in my shell, and click 4digits in Konqueror, thus I
can see what's outputed. On the shell it shows:

Input a 4-digit number:0: input error!
Input a 4-digit number:0: input error!
Input a 4-digit number:0: input error!
Input a 4-digit number:0: input error!
.......

And it never ends and my CPU is eaten up. Why is it get out of control?
I just want it to quit, like when I click on /bin/cat.
The simplest way is just n = 1000 + rand()%9000;
But I'm not sure if one way gives better results than the other.

Paragraphs from man 3 rand:
In Numerical Recipes in C: The Art of Scientific Computing
(William H.
Press, Brian P. Flannery, Saul A. Teukolsky, William T.
Vetterling; New
York: Cambridge University Press, 1992 (2nd ed., p. 277)), the
follow-
ing comments are made:
"If you want to generate a random integer between 1 and
10, you
should always do it by using high-order bits, as in

j = 1 + (int) (10.0 * (rand() / (RAND_MAX +
1.0)));

and never by anything resembling

j = 1 + (rand() % 10);

(which uses lower-order bits)."
This will cause a buffer overflow if the user types something like
"12345678", because scanf reads the whole thing. You can limit how much
scanf reads by using a format string like "%4s" instead.

scanf can also read the number directly with "%d".

if (scanf("%d", n) != 1)
/* if scanf didn't return 1, it was unable to find a number */

To skip any remaining characters after the ones you want, you can use a
while loop and getchar:

while (getchar() != EOF);

Seems scanf is for experts?
 
S

Simon Biber

Pan said:
Hi all,

I wrote a simple C program, exactly at the bottom of this post. It's an
interactively game, needing user's input. When invoked at the Linux
shell, it works OK. But if I click in my ROX-Filer, nothing popups
since no GUI, but it then cosume almost 100% of my CPU time. I have to
kill it. I'd like to know if I can make it quit silently when It's
clicked. Thank you very much. Below is the whole source.

You should check the result any input functions. If the first time you
try to read input, you are not successful at reading any input, call
exit(EXIT_FAILURE); or something like that.

For example:

....
printf("Input a 4-digit number:");
fflush(NULL);
if(scanf("%s", mstr) <= 0)
{
fprintf(stderr,
"This program requires interactive input from a terminal\n");
exit(EXIT_FAILURE);
}
....
 
O

Old Wolf

Pan said:
char mstr[4]; /* string for the 4-digit number */

So I better off use scanf("%4s", mstr)?

No. This reads a string of /at least/ 4 characters, so will always
overflow the buffer. You need:

int result = scanf("%.3s", mstr);

which reads /at most/ 3 characters, so uses up at most 4 bytes
of the buffer (don't forget about the terminating '\0').
But why my original code runs OK?

It doesn't run OK -- isn't that why you were posting in the first
place?
But another problem occurs when the input is longer than 4:
next scanf does not pause for my input and skips with possibly
wrong data.

Actually it gets all the data you didn't read the first time.
The longer the input, the more scanf's skipped. It seems hard to
correctly and safely deal with scanf input.

That's right.
I once tried gets, but gcc told me it's dangerous.

Use fgets .
 
C

Chris Torek

char mstr[4]; /* string for the 4-digit number */

No. This reads a string of /at least/ 4 characters, so will always
overflow the buffer. You need:

int result = scanf("%.3s", mstr);

which reads /at most/ 3 characters, so uses up at most 4 bytes
of the buffer (don't forget about the terminating '\0').

I think you are mixing up the printf and scanf engines here. In
the printf family, "%4s" gives you a minimum field width of four
but puts no limit on the actual length of the string and will use
more than four positions if needed:

printf("|%4s|\n", "");
printf("|%4s|\n", "123");
printf("|%4s|\n", "123456");

produces:

| |
| 123|
|123456|

for instance. Using "%.4s" in printf limits the "implied" length
of the string (which now no longer even needs to be a string) to 4.
Internally, inside the printf() engine, the effect works out to
the equivalent of the following pseudo-C code:

/* for %s, not for %ls */
str = va_arg(ap, char *);
if (a precision was given) {
p = memchr(str, '\0', prec); /* where prec is the precision */
len = p ? p - str : prec;
} else
len = strlen(str);

/* handle padding for %4s or %-4s */
pad_characters = 0;
if (a width was given && width > len) {
pad_characters = width - len;
if (not-doing-left-adjust) { /* %4s */
for (; pad_characters > 0; pad_characters--)
putc(' ', the_file);
}
}
while (len--)
putc(*str++, the_file);
/* now handle %-4s case, where pad comes after string */
for (; pad_characters > 0; pad_characters--)
putc(' ', the_file);

to print the string. (Note that this same code works for other
conversions like %d, once the number is converted to a string and
its length calculated, but %d needs to be able to zero-pad as well
as blank-pad, and numeric conversions must handle signs and so on.)

In the scanf family, however, "%4s" gives you a *maximum* field
width of four, and "%.4s" has no meaning -- precisions do not apply
in scanf. (And as you note, it requires an array of at least five
characters to hold a four-character field scanned via scanf().)

There is a false appearance of symmetry between printf() and scanf(),
but in reality, the two functions are quite different. I sometimes
think it would have been better if the names were not so similar.
 
O

Old Wolf

Chris said:
I think you are mixing up the printf and scanf engines here.

You're right.
There is a false appearance of symmetry between printf() and scanf(),
but in reality, the two functions are quite different. I sometimes
think it would have been better if the names were not so similar.

It might have been better if scanf had never existed..
 

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,744
Messages
2,569,479
Members
44,900
Latest member
Nell636132

Latest Threads

Top