问题
I have a char array, where should be only numbers (10 digits). If the user enters letters or special characters (even among those digits) the program should prompt the user again to enter the number.
I tried so many ways of doing it, but still couldn't find a way. That's what I could do so far:
int f = 1;
int i = 0;
int flag =1;
char num[11];
printf("Enter a number: ");
while (f == 1) {
scanf("%10s", num);
while (flag == 1 && isdigit(num[i])) {
i++;
if (i == 10) {
f = 0;
flag =0;
}
}
if (!isdigit(num[i])) {
printf("Enter numerical char: ");
}
}
After I enter incorrect value it displays an empty line. If I put any value to that empty line, only then it says "Enter numerical char: " and prompts to enter the num again.
P.S. I know there is a way of ensuring that only numerical values entered, considering the fact that characters, unlike numbers are included in single quotes. (have no idea how to do this tbh)
Thanks in advance!
回答1:
Working with input from stdin
in C can be a pain. I tried to explain what needs to be done in the comments while maintaining your variables in the manner in which you wanted them to be used. But I did need to add int ch
to capture the input from stdin
. The manner in which I captured input is FAR! from ideal but it illustrates the idea and does what you need it to do. But, to improve on your answer I'd suggest moving it into it's own function. Also, it ignores input of digits greater than 10 characters, so if for example you input 012345678901234567 it would just ignore the input beyond the 10th digit but still pass the test per your variables and flags. The comments should be self explanatory. I did not test this other than to make sure it compiled and once for digits and once for digits and text, but the idea is there, and you should be able to expand on it to match your requirements.
#include <ctype.h>
#include <stdio.h>
#include <stdlib.h> /* for fflush */
int main()
{
int f = 1; /* set f on */
int i = 0;
int flag = 0; /* set flag OFF */
char num[11];
int ch; /* adding ch to read characters from stdin */
printf("Enter a number: "); /* flush stdout if no newline */
fflush(stdout);
while(f == 1) {
/* you need to read stdin to the newline */
/* but not exceed the bounds of num */
ch = fgetc(stdin);
while(ch != '\n' && ch != EOF) {
if(i < 10) /* reusing your i variable that you set to 0, don't exceed 10 to save space for '\0' */
num[i] = ch;
i++;
ch = fgetc(stdin); /* get another character */
}
/* now add '\0' to terminate your string */
/* but not beyond num[10] */
if(i > 10) {
num[10] = '\0';
} else {
num[i] = '\0';
}
/* now that we are done reading stdin reset i to 0 to restore how you had it */
i = 0;
/* lets test num working with your variables */
while(num[i] != '\0' && flag == 0) {
/* test for digit at num[i] */
if(!isdigit(num[i]))
flag = 1; /* not a digit so set your flag variable on */
i++;
}
/* process your flag variable */
if(flag == 0) { /* flag is off so everything is ok */
f = 0; /* turn f off to exit loop */
} else { /* flag is on, so get another number */
printf("Enter numerical char: "); /* flush stdout if no newline */
fflush(stdout);
flag = 0; /* turn your flag variable back off */
i = 0; /* reset i to 0 to check the next input */
}
}
/* let's see what we got in num */
printf("%s\n", num);
return 0;
}
回答2:
There are a couple of ways to do this.
The simple way is to use fgets
to get a string.
Then, we can use strtol
to decode the number [and we check the ending char for validity].
To do it completely manually, we can use isdigit
in a loop, building up the number one digit at a time.
Here's some example code that is annotated and shows both ways:
#include <stdio.h>
#include <stdlib.h>
#include <string.h>
#include <errno.h>
#include <ctype.h>
// getstr -- get a string with prompt
// RETURNS: length or (<0 -> error)
int
getstr(char *buf,int buflen,const char *prompt)
{
char *cp;
int ret = 0;
// NOTE: usage of the error codes in errno.h is arbitrary
while (ret <= 0) {
// ensure buffer has enough space
if (buflen < 2) {
ret = -ENOMEM;
break;
}
// output prompt
printf("%s: ",prompt);
fflush(stdout);
// get a line
cp = fgets(buf,buflen,stdin);
// EOF
if (cp == NULL) {
ret = -ENODATA;
break;
}
// get buffer length
ret = strlen(buf);
// empty string
if (ret <= 0)
continue;
// point to last char
cp = &buf[ret - 1];
// ensure we got a newline -- if not, fgets had to chop the line (i.e.)
// the line is too long to fit in the buffer
if (*cp != '\n') {
ret = -ENOSPC;
break;
}
// strip the newline -- we are done
*cp = 0;
--ret;
}
return ret;
}
// getnum_strtol -- get number using strtol
long
getnum_strtol(const char *prompt)
{
int len;
int readflg = 1;
char *cp;
char buf[100];
long num = 0;
while (readflg) {
len = getstr(buf,sizeof(buf),prompt);
if (len < 0)
exit(1);
num = strtol(buf,&cp,10);
// ensure we got a least one digit
if (cp <= buf)
continue;
switch (*cp) {
case ' ':
case '\t':
case 0:
readflg = 0;
break;
default:
printf("getnum_strtol: not a valid number -- buffer '%s', invalid '%s'\n",
buf,cp);
break;
}
}
return num;
}
// getnum_manual -- get number _not_ using strtol
long
getnum_manual(const char *prompt)
{
int len;
int readflg = 1;
int sign = 0;
int valid;
int chr;
char *cp;
char buf[100];
long num = 0;
while (readflg) {
len = getstr(buf,sizeof(buf),prompt);
// fatal error
if (len < 0)
exit(1);
// point to buffer start
cp = buf;
// find first non-whitespace character
valid = 0;
while (1) {
chr = *cp;
// end of string
if (chr == 0)
break;
// found character
valid = ((chr != ' ') && (chr != '\t'));
if (valid)
break;
++cp;
}
if (! valid)
continue;
// reset the accumlated number and the sign
num = 0;
sign = 0;
valid = 0;
// loop through all characters in buffer
while (1) {
chr = *cp++;
// get the sign of the number (and skip an explicit sign)
if (sign == 0) {
switch (chr) {
case '+':
sign = 1;
chr = *cp++;
break;
case '-':
sign = -1;
chr = *cp++;
break;
default:
sign = 1;
break;
}
}
// stop decoding number on whitespace
switch (chr) {
case ' ':
case '\t':
chr = 0;
break;
}
// check for clean end of number
if (chr == 0) {
if (valid) {
readflg = 0;
break;
}
}
// not a valid digit
if (! isdigit((unsigned char) chr)) {
cp -= 1;
printf("getnum_manual: not a valid number -- buffer '%s', invalid '%s'\n",
buf,cp);
break;
}
// add digit to number
num *= 10;
chr -= '0';
num += chr;
// we got at least one valid digit
valid = 1;
}
}
// apply sign
num *= sign;
return num;
}
int
main(int argc,char **argv)
{
char *cp;
int opt_s = 0;
long num;
// skip over program name
--argc;
++argv;
// get options
for (; argc > 0; --argc, ++argv) {
cp = *argv;
if (*cp != '-')
break;
cp += 2;
switch (cp[-1]) {
case 's': // use strtol
opt_s = ! opt_s;
break;
}
}
while (1) {
if (opt_s)
num = getnum_strtol("Enter number [strtol]");
else
num = getnum_manual("Enter number [manual]");
printf("The number entered is: %ld\n",num);
if (num == 999)
break;
}
return 0;
}
来源:https://stackoverflow.com/questions/65011769/check-if-all-values-entered-into-char-array-are-numerical