检查代表数字的字符串的有效性

时间:2018-10-19 13:56:47

标签: c

我需要编写一个函数,该函数将检查字符串的一些属性:

  1. 字符串必须表示一个正整数(> 0)
  2. 整数不能超过32位内存
  3. 字符串中没有字母

如果满足这些条件,则应以int形式返回字符串,如果不满足任何条件,则应返回-1。

当前,该函数无法处理以下2个输入:

  • 4y
  • 13.4

如果我的isDigit()循环按预期工作,则可以检查它们。为什么循环不起作用?

int convert(const char length[]) {
  long input = atol(length);
  if (input >= 2147483648 || input <= 0) {
    return -1;
  }
  int chkr = 0;
  while (chkr < strlen(length)) {
    if (isdigit(length[chkr++]) == 0) {
      return -1;
   }
    else {
      return atoi(length);
    }
  }
  input = atol(length);
  if (length[0] == '0') {
    return -1;
  }
  if (strlen(length) < 3) {
    return -1;
  }
 else {
    return atoi(len gth);
  }
}

5 个答案:

答案 0 :(得分:1)

您的函数非常复杂且错误。

改为使用此代码,然后让C库完成肮脏的工作:

#include <stdio.h>
#include <stdlib.h>
#include <errno.h>
#include <ctype.h>

// The function you're interested in

int convert(const char string[]) {
  char *endptr;
  if (!isdigit((unsigned char)string[0]))
    return -1;

  errno = 0;    // need to set errno to 0 (see errno documentation)
  long value = strtol(string, &endptr, 10);
  if (errno != 0 || value <= 0 || value > 2147483647 || *endptr != 0)
  {
    return -1;
  }
  return value;
}

int main() {
  // Test different cases:

  struct {
    const char *input;
    int expected;
  } testcases[] =
  {
    // OK cases
    "123", 123,
    "1234", 1234,
    "2147483647", 2147483647,

    // fail cases
    "-1234", -1,      // number is negatif
    "12.3", -1,       // contains non digit '.'
    "123y", -1,       // contains non digit 'y'
    "2147483648", -1, // out of range
    " 123", -1,      // starts with a space

    // wrong test case on purpose
    "1234", 1245,
  };

  // Test all test cases

  for (int i = 0; i < sizeof(testcases) / sizeof(testcases[0]); i++)
  {
    int value = convert(testcases[i].input);
    if (value != testcases[i].expected)
    {
      printf("convert(\"%s\") failed, returned value = %d, expected value = %d\n", testcases[i].input, value, testcases[i].expected);
    }
    else
    {
      printf("convert(\"%s\") passed\n", testcases[i].input);
    }
  }
  return 0;
}

程序将打印每个测试用例。最后一个测试用例故意是错误的。

for循环遍历许多测试用例,对于每个失败的测试用例,它将打印涉及的值。

输出:

convert("123") passed
convert("1234") passed
convert("2147483647") passed
convert("-1234") passed
convert("12.3") passed
convert("123y") passed
convert("2147483648") passed
convert("1234") failed, returned value = 1234, expected value = 1245

答案 1 :(得分:0)

您仅检查第一个字符,然后立即返回。

input = atol(length);

无法访问。

答案 2 :(得分:0)

查看此循环:

while (chkr < strlen(length)) {
    if (isdigit(length[chkr++]) == 0) {
        return -1;
    }
    else {
        return atoi(length);
    }
}

您不会遍历整个字符串,反正要在第一个字符之后返回。您不想在此处以else的形式返回,否则将跳过程序的其余部分。拥有这个:

while (chkr < strlen(length)) {
    if (isdigit(length[chkr++]) == 0) {
        return -1;
    }
}

之后,此行在这里

input = atol(length);

不需要。输入仍然具有该值。但这不会造成任何伤害。

答案 3 :(得分:0)

int convert(const char length[]) {
    if (atol(length) >= 2147483648 || atol(length) <= 0)
        return -1;

    int chkr = 0;
    while (chkr < strlen (length)) {
        if (isdigit(length[chkr++]) == 0)
            return -1;
    }

    return atoi(length);
}

编辑:固定答案。不知道为什么我不使用isdigit()。
我想太努力了,以至于适得其反。

答案 4 :(得分:0)

如前所述,while循环在第一次迭代后返回。

使用sscanf代替atolatoi。这样比较可取,因为您可以检测到错误:

int convert(const char *length){
    int err, sz;
    unsigned rtn;
    /*%u reads an unsigned integer (mostly 32 bit) >= 0*/
    err = sscanf(length, "%u%n", &rtn, &sz);
    /*check reading error occured*/
    if(err == 0){
        return -1;
    }
    /*check if there is no whitespace/sign*/
    if(!isdigit(length[0])){
        return -1;
    }
    /*check if 0 < rtn <= INT_MAX*/
    if(rtn <= 0 || rtn > INT_MAX){
        return -1;
    }
    /*check everything got read*/
    /*=> no letters*/
    if(sz != strlen(length)){
        return -1;
    }
    return rtn;
}

让我们测试一下:

/*these fail*/
const char zero[] = "0";
const char spaceStart[] = " 84654";
const char spaceEnd[] = "84654 ";
const char negative[] = "-7869";
const char tooBig[] = "2147483648";
const char fitsInto32BitInt[] = "2147483647";
const char positive[] = "+7526";
const char withLetter[] = "4y";
const char withPoint[] = "13.4";
/*these work*/
const char one[] = "1";
const char fine[] = "746838";
const char fitsInto32BitInt[] = "2147483647";