how can we check to not enter the any string or char?

  • Thread starter emre esirik(hacettepe computer science and enginee
  • Start date
E

emre esirik(hacettepe computer science and enginee

int n_mines;
printf("How many mines do you want in the minefield?");
scanf("%d", &n_mines);

while(n_mines>100 || n_mines<0)
{
printf("Please only enter between 1 and 100");
scanf("%d", &n_mines);
}

so I dont want to user can enter the string or char value,how can I
check it?
 
J

John Gordon

In said:
int n_mines;
printf("How many mines do you want in the minefield?");
scanf("%d", &n_mines);
while(n_mines>100 || n_mines<0)
{
printf("Please only enter between 1 and 100");
scanf("%d", &n_mines);
}
so I dont want to user can enter the string or char value,how can I
check it?

Read the input as a string first. Examine the string to see if it contains
any incorrect characters. If it does not, convert the string to its
decimal value.

string input[80];
int n_mines;
int i;
int good_input = 1;

printf("How many mines do you want in the minefield?");
fgets(input, sizeof(input), stdin);

for(i = 0; i < strlen(input); i++)
{
if(isalpha(input))
{
// whoops! user entered a character
good_input = 0;
break;
}
}

if(good_input == 1)
{
n_mines = atoi(input);
}
else
{
printf("You must enter a number.\n");
}
 
S

santosh

emre said:
int n_mines;
printf("How many mines do you want in the minefield?");
scanf("%d", &n_mines);

scanf is a tricky function to use. If you do use it, you _must_ check
it's return value to ensure that it has succeeded.

If it fails it can, in certain situations, leave some input still in the
stdin's buffer, which will cause further calls to scanf to fail
repeatedly, until the stream is flushed.
while(n_mines>100 || n_mines<0)
{
printf("Please only enter between 1 and 100");
scanf("%d", &n_mines);
}

so I dont want to user can enter the string or char value,how can I
check it?

Frankly I advocate using fgets to input a line and strtoul or strtol to
convert to a numerical value. These functions provide more control and
better error reporting than either atoi or scanf/sscanf.

Also consider changing the above loop to a do/while one.
 
E

emre esirik(hacettepe computer science and enginee

I am just started to learn C programming, thank you for reply but I
dont understand, it looks too difficult,
do you think is there any easy way for this,or its difficult to solve
for me as a beginner c programmer
 
S

santosh

John said:
In <[email protected]> "emre
esirik(hacettepe computer science and engineering)"
int n_mines;
printf("How many mines do you want in the minefield?");
scanf("%d", &n_mines);
while(n_mines>100 || n_mines<0)
{
printf("Please only enter between 1 and 100");
scanf("%d", &n_mines);
}
so I dont want to user can enter the string or char value,how can I
check it?

Read the input as a string first. Examine the string to see if it
contains
any incorrect characters. If it does not, convert the string to its
decimal value.

string input[80];

What is this 'string' type? It's not defined in Standard C and if it is
C++'s std::string you might prefer to post in comp.lang.c++.
int n_mines;
int i;
int good_input = 1;

printf("How many mines do you want in the minefield?");
fgets(input, sizeof(input), stdin);

for(i = 0; i < strlen(input); i++)
{
if(isalpha(input))
{
// whoops! user entered a character
good_input = 0;
break;
}
}

if(good_input == 1)
{
n_mines = atoi(input);
}
else
{
printf("You must enter a number.\n");
}


What about input like 23.3 or 34&%$3 and other combinations?
I suggest using isdigit instead of isalpha. Also cast the is* function's
arguments to unsigned char.

Also check fgets for success, otherwise input's contents will be
indeterminate. strtol might also be a better alternative to atoi
providing status reporting.
 
K

Keith Thompson

John Gordon said:
In <[email protected]> "emre
esirik(hacettepe computer science and engineering)"




Read the input as a string first. Examine the string to see if it contains
any incorrect characters. If it does not, convert the string to its
decimal value.
[code snipped]

And if you choose to use scanf or (or fscanf or sscanf), remember that
it returns a value. Read your documentation to find out what the
returned value means, and *always* check it.
 
A

andreyvul

fgets() and strtol().

fgets(str, 4, stdin) to be specific

also, there are only up to 4 input bytes, so the loop should be
rewritten to this:
char[4] str;
int i = 0, n_mines = 0;
while (1) {
fgets(str, 4, stdin);
for (i = 0; i < 4; i++)
if ((str < 0x30 && str) || str > 0x39) /* check ascii
value if it's not */
/* a char-
encoded digit or a NULL*/
/* (end-of-
string terminator) */
goto enter_again;
n_mines = atoi(str);
if (n_mines < 1 || n_mines > 100)
goto enter_again:
enter_again:
printf("Please only enter between 1 and 100");
}

Note: in this situation, a goto was useful. However, gotos are like
#defines and should only be used sparingly.
Also, I hope you meant no tabs, spaces, or other control chars,
because the test checks for numbers only.
Also, you did not initialize n_mines before the loop. This may result
in undefined behavior if you are not careful to later initialize it,
especially in if- and switch-statements. C does not automatically zero
out variables before first use, so initialize your variables at the
top, when they are declared.
 
P

pete

emre said:
int n_mines;
printf("How many mines do you want in the minefield?");
scanf("%d", &n_mines);

while(n_mines>100 || n_mines<0)
{
printf("Please only enter between 1 and 100");
scanf("%d", &n_mines);
}

so I dont want to user can enter the string or char value,
how can I check it?

/* BEGIN n_mines.c */
/*
** Bulletproof numeric input with fscanf.
*/
#include <stdio.h>
#include <stdlib.h>

#define LENGTH 4
#define str(x) # x
#define xstr(x) str(x)

int main(void)
{
int rc;
char array[LENGTH + 1];
long number;
int n_mines;

for (;;) {
printf("How many mines do you want in the minefield?: ");
fflush(stdout);
rc = fscanf(stdin, "%" xstr(LENGTH) "[^\n]%*[^\n]", array);
if (!feof(stdin)) {
getc(stdin);
}
if (rc == 0 || rc == EOF) {
array[0] = '\0';
number = 0;
} else {
number = strtol(array, NULL, 10);
}
if (number > 100 || number < 1) {
printf("Please only enter between 1 and 100\n");
} else {
n_mines = number;
printf("\nn_mines is %d.\n", n_mines);
break;
}
}
return 0;
}

/* END n_mines.c */
 
P

pete

andreyvul said:
if ((str < 0x30 && str) || str > 0x39)


I see two numbers that are nine apart from each other,
so I'm guessing that this is what you mean:

if ((str < '0' && str) || str > '9')
 
C

Coos Haak

Op Thu, 01 Nov 2007 02:31:53 +0530 schreef santosh:

What about input like 23.3 or 34&%$3 and other combinations?
I suggest using isdigit instead of isalpha. Also cast the is* function's
arguments to unsigned char.
Why? I thought an int is expected. And char is promoted to int anyway,
signed or not.
 
V

vipvipvipvipvip.ru

Op Thu, 01 Nov 2007 02:31:53 +0530 schreef santosh:



Why? I thought an int is expected. And char is promoted to int anyway,
signed or not.

You should cast to (unsigned char) only the argument of to*()
functions.

pete:
Your `bulletproof' way can be replaced to 6 lines, fgets(), ret =
strtol(), if(error_check), this, else, that.
 
J

Jack Klein

Op Thu, 01 Nov 2007 02:31:53 +0530 schreef santosh:


Why? I thought an int is expected. And char is promoted to int anyway,
signed or not.

To avoid undefined behavior, that's why. The is* and to* functions
accept argument of type in ***in the range of 0 through UCHAR_MAX***,
or with the value EOF.

On implementations where plain char is signed, which is most of them
these days, a char can have a negative value, and will promote to an
int containing the same negative value. That just might happen to be
the value of EOF, which is required to be a negative int value, but
most likely will not be.

So on such an implementation, passing a signed character with a
negative value to an is* or to* function has at least a 125/126 chance
of producing undefined behavior.

--
Jack Klein
Home: http://JK-Technology.Com
FAQs for
comp.lang.c http://c-faq.com/
comp.lang.c++ http://www.parashift.com/c++-faq-lite/
alt.comp.lang.learn.c-c++
http://www.club.cc.cmu.edu/~ajo/docs/FAQ-acllc.html
 
J

Jack Klein

fgets() and strtol().

fgets(str, 4, stdin) to be specific

also, there are only up to 4 input bytes, so the loop should be
rewritten to this:
char[4] str;
int i = 0, n_mines = 0;
while (1) {
fgets(str, 4, stdin);
for (i = 0; i < 4; i++)
if ((str < 0x30 && str) || str > 0x39) /* check ascii
value if it's not */


But what if the platform does not use ASCII? C does not require it.
This is extremely foolish, when using '0' and '9' instead of 0x30 and
0x39 guarantees portability to any implementation of C now and
forever.
/* a char-
encoded digit or a NULL*/
/* (end-of-
string terminator) */
goto enter_again;

The line above is a valid goto statement.
n_mines = atoi(str);

At least you did manage to use the generally unsafe atoi() function
safely here, I'll give you that.
if (n_mines < 1 || n_mines > 100)
goto enter_again:

The line above is a syntax error, not a valid goto statement. And
it's completely unnecessary, since the label immediately follows the
botched goto.
enter_again:
printf("Please only enter between 1 and 100");
}

Note: in this situation, a goto was useful. However, gotos are like

There are very few situations where a goto is useful and justified.
This mess is not one of them. Why "mess"? There is no way out of the
loop, no matter what is entered.
#defines and should only be used sparingly.
Also, I hope you meant no tabs, spaces, or other control chars,
because the test checks for numbers only.
Also, you did not initialize n_mines before the loop. This may result
in undefined behavior if you are not careful to later initialize it,
especially in if- and switch-statements. C does not automatically zero
out variables before first use, so initialize your variables at the
top, when they are declared.

That last sentence of yours is only partially correct. C does not
automatically zero out automatic variables before use. It most
certainly initializes all objects with static storage duration to 0 if
they do not have an explicit initializer.

--
Jack Klein
Home: http://JK-Technology.Com
FAQs for
comp.lang.c http://c-faq.com/
comp.lang.c++ http://www.parashift.com/c++-faq-lite/
alt.comp.lang.learn.c-c++
http://www.club.cc.cmu.edu/~ajo/docs/FAQ-acllc.html
 
F

Flash Gordon

pete wrote, On 01/11/07 00:11:
andreyvul said:
if ((str < 0x30 && str) || str > 0x39)


I see two numbers that are nine apart from each other,
so I'm guessing that this is what you mean:

if ((str < '0' && str) || str > '9')


Still horrible, I would almost always use isdigit() rather than
comparing against '0' and '9'. I don't expect it to be more efficient
(although it could be) just more readable.
 
P

Philip Potter

Jack said:
fgets() and strtol().
fgets(str, 4, stdin) to be specific

also, there are only up to 4 input bytes, so the loop should be
rewritten to this:
char[4] str;
int i = 0, n_mines = 0;
while (1) {
fgets(str, 4, stdin);
for (i = 0; i < 4; i++)
if ((str < 0x30 && str) || str > 0x39) /* check ascii
value if it's not */


But what if the platform does not use ASCII? C does not require it.
This is extremely foolish, when using '0' and '9' instead of 0x30 and
0x39 guarantees portability to any implementation of C now and
forever.


It is unlikely but possible that the character set does not have the
digits 0-9 nicely in order. Better to use isdigit().
 

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
474,438
Messages
2,571,699
Members
48,796
Latest member
Greg L.
Top