23

我想用这个代码检查一个字符串是否是一个数字。我必须检查字符串中的所有字符是否都是整数,但是 while 返回总是 isDigit = 1。我不知道为什么 if 不起作用。

char tmp[16];
scanf("%s", tmp);

int isDigit = 0;
int j=0;
while(j<strlen(tmp) && isDigit == 0){
  if(tmp[j] > 57 && tmp[j] < 48)
    isDigit = 0;
  else
    isDigit = 1;
  j++;
}
4

12 回答 12

43

忘记 ASCII 代码检查,使用isdigitor isnumber(参见 参考资料man isnumber)。第一个函数检查字符是否为 0-9,第二个函数还根据当前语言环境接受各种其他数字字符。

甚至可能有更好的函数来进行检查——重要的教训是这比看起来要复杂一些,因为“数字字符串”的精确定义取决于特定的语言环境和字符串编码。

于 2013-05-20T07:53:08.573 回答
11
  if(tmp[j] >= '0' && tmp[j] <= '9') // should do the trick
于 2013-05-20T07:50:49.610 回答
8

更明显和简单的线程安全示例:

#include <stdio.h>
#include <stdlib.h>
#include <string.h>

int main(int argc, char **argv)
{
    if (argc < 2){
        printf ("Dont' forget to pass arguments!\n");
        return(-1);
    }

    printf ("You have executed the program : %s\n", argv[0]);

    for(int i = 1; i < argc; i++){
        if(strcmp(argv[i],"--some_definite_parameter") == 0){
            printf("You have passed some definite parameter as an argument. And it is \"%s\".\n",argv[i]);
        }
        else if(strspn(argv[i], "0123456789") == strlen(argv[i])) {
            size_t big_digit = 0;
            sscanf(argv[i], "%zu%*c",&big_digit);
            printf("Your %d'nd argument contains only digits, and it is a number \"%zu\".\n",i,big_digit);
        }
        else if(strspn(argv[i], "0123456789abcdefghijklmnopqrstuvwxyz./") == strlen(argv[i]))
        {
            printf("%s - this string might contain digits, small letters and path symbols. It could be used for passing a file name or a path, for example.\n",argv[i]);
        }
        else if(strspn(argv[i], "ABCDEFGHIJKLMNOPQRSTUVWXYZ") == strlen(argv[i]))
        {
            printf("The string \"%s\" contains only capital letters.\n",argv[i]);
        }
    }
}
于 2017-06-09T08:25:40.093 回答
3

在这部分代码中:

if(tmp[j] > 57 && tmp[j] < 48)
  isDigit = 0;
else
  isDigit = 1;

您的if条件将始终为假,导致isDigit始终设置为1. 你可能想要:

if(tmp[j] > '9' || tmp[j] < '0')
  isDigit = 0;
else
  isDigit = 1;

但。这可以简化为:

isDigit = isdigit(tmp[j]);

但是,您的循环逻辑似乎有点误导:

int isDigit = 0;
int j=0;
while(j<strlen(tmp) && isDigit == 0){
  isDigit = isdigit(tmp[j]);
  j++;
}

由于tmp不是常数,因此不确定编译器是否会优化每次迭代的长度计算。

正如@andlrc 在评论中建议的那样,您可以只检查数字,因为终止的 NUL 无论如何都会使检查失败。

while (isdigit(tmp[j])) ++j;
于 2013-05-20T07:53:08.607 回答
3
if ( strlen(str) == strlen( itoa(atoi(str)) ) ) {
    //its an integer
}

由于 atoi 将字符串转换为跳过数字以外的字母的数字,如果只有数字,则其字符串长度必须与原始长度相同。如果检查的是整数,则此解决方案比 innumber() 更好。

于 2019-09-30T14:32:17.637 回答
2

我需要为我目前正在从事的项目做同样的事情。以下是我解决问题的方法:

/* Prompt user for input */
printf("Enter a number: ");

/* Read user input */
char input[255]; //Of course, you can choose a different input size
fgets(input, sizeof(input), stdin);

/* Strip trailing newline */
size_t ln = strlen(input) - 1;
if( input[ln] == '\n' ) input[ln] = '\0';

/* Ensure that input is a number */
for( size_t i = 0; i < ln; i++){
    if( !isdigit(input[i]) ){
        fprintf(stderr, "%c is not a number. Try again.\n", input[i]);
        getInput(); //Assuming this is the name of the function you are using
        return;
    }
}
于 2016-03-11T01:31:56.013 回答
2
#include <stdio.h>
#include <string.h>
char isNumber(char *text)
{
    int j;
    j = strlen(text);
    while(j--)
    {
        if(text[j] > 47 && text[j] < 58)
            continue;

        return 0;
    }
    return 1;
}
int main(){
    char tmp[16];
    scanf("%s", tmp);

    if(isNumber(tmp))
        return printf("is a number\n");

    return printf("is not a number\n");
}

您还可以检查它的字符串值,这也可以与非 Ascii 一起使用

char isNumber(char *text)
{
    int j;
    j = strlen(text);
    while(j--)
    {
        if(text[j] >= '0' && text[j] <= '9')
            continue;

        return 0;
    }
    return 1;
}
于 2019-10-28T05:05:26.223 回答
0

你的情况说if X is greater than 57 AND smaller than 48X不能同时大于 57 和小于 48。

if(tmp[j] > 57 && tmp[j] < 48)

它应该是if X is greater than 57 OR smaller than 48

if(tmp[j] > 57 || tmp[j] < 48)
于 2013-05-20T07:53:56.000 回答
0

重写整个函数如下:

bool IsValidNumber(char * string)
{
   for(int i = 0; i < strlen( string ); i ++)
   {
      //ASCII value of 0 = 48, 9 = 57. So if value is outside of numeric range then fail
      //Checking for negative sign "-" could be added: ASCII value 45.
      if (string[i] < 48 || string[i] > 57)
         return FALSE;
   }

   return TRUE;
}
于 2020-09-27T07:59:56.153 回答
0

问题是您的代码“isDigit”的结果只反映了最后一位数字测试。据我了解您的问题,只要您的字符串中有任何不是数字的字符,您就想返回 isDigit = 0 。按照你的逻辑,你应该这样编码:

char tmp[16];
scanf("%s", tmp);

int isDigit = 0;
int j=0;
isDigit = 1;  /* Initialised it here */
while(j<strlen(tmp) && isDigit == 0){
  if(tmp[j] > 57 || tmp[j] < 48) /* changed it to OR || */
    isDigit = 0;
  j++;
}

为了获得更易于理解的代码,我还将更改测试:

if(tmp[j] > 57 || tmp[j] < 48) 

到以下:

if(tmp[j] > '9' || tmp[j] < '0')
于 2020-11-06T20:10:39.527 回答
0

这些都不能适当地处理负数或浮点数。

怎么样:

bool
is_realnumber(char *instring) {
  if (*instring != '-' && *instring != '.' && !isdigit(*instring)) return false;
  if (strspn(instring+1, "0123456789.") < strlen(instring+1)) return false;
  int c = 0;
  while (*instring) if (*instring++ == '.') if (++c > 1) return false;
  return true;
}
于 2021-11-16T19:02:11.363 回答
0

I can extend Marcelo's answer supporting floating numbers also as following:

char isnumber(const char *str)
{
     int decpos = -1, pmpos = -1, engpos = strlen(str) - 1, epmpos = strlen(str) - 1;
  for (int i = 0; i < strlen(str); i++)
    /* check if it is integer */
    if (str[i] > 47 && str[i] < 58)
      continue;
    /* check if it is decimal seperator and used once*/
    else if (str[i] == 46 && decpos == -1)
    {
      decpos = i;
      continue;
    }
    /* check if it is +/-, at the begining*/
    else if ((str[i] == 43 || str[i] == 45) && i == 0)
    {
      pmpos = 1;
      continue;
    }
    /* check if it is engineering format e/E, used once, after decimal and before +/-*/
    else if ((str[i] == 69 || str[i] == 101) && engpos == strlen(str) - 1 && i > 0 && i > decpos && i < epmpos)
    {
      engpos = 1;
      continue;
    }
    /* check if it is engineering format +/-, used once, after decimal and after engineering e/E*/
    else if ((str[i] == 43 || str[i] == 45) && epmpos == strlen(str) - 1 && i > 0 && i > decpos && i > engpos)
    {
      epmpos = 1;
      continue;
    }
    else
      return 0;
  return 1;
}
于 2021-12-08T20:38:43.630 回答