C 检查表示数字的字符串的有效性

C 检查表示数字的字符串的有效性,c,C,我需要编写一个函数来检查字符串的一些属性: 字符串必须表示正整数(>0) 整数所需内存不得超过32位 字符串中没有字母 如果满足这些条件,它应该将字符串作为int返回,如果不满足这些条件中的任何一个,它应该返回-1 目前,该功能无法处理以下2个输入: 4y 13.4 如果我的isDigit()循环按预期工作,它将能够检查它们。为什么循环不起作用 int convert(const char length[]) { long input = atol(length); if (inpu

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

  • 字符串必须表示正整数(>0)
  • 整数所需内存不得超过32位
  • 字符串中没有字母
  • 如果满足这些条件,它应该将字符串作为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);
      }
    }
    
    int转换(常量字符长度[]){
    长输入=atol(长度);
    
    如果(输入>=2147483648 | |输入,则只检查第一个字符,然后立即返回

    input = atol(length);
    
    无法访问。请检查此循环:

    while (chkr < strlen(length)) {
        if (isdigit(length[chkr++]) == 0) {
            return -1;
        }
        else {
            return atoi(length);
        }
    }
    
    在那之后,这条线在这里

    input = atol(length);
    
    不需要。输入仍然具有该值。但不会造成任何伤害。

    int convert(const char length[]){
    
    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);
    }
    

    if(atol(length)>=2147483648 | | atol(length)如前面所述,而
    循环在第一次迭代后返回

    使用
    sscanf
    而不是
    atol
    atoi
    。这是最好的选择,因为您可以检测错误:

    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;
    }
    

    你的函数非常复杂而且错误

    改为使用此选项,并让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;
    }
    

    为此,我宁愿使用
    strtol
    。还请展示一些有效和无效字符串的示例,并告诉我们“3整数字符串”是什么。我建议
    length
    通常不是字符串的好名称-当然是在提供的代码上下文中。学会使用调试器。永远不要使用
    atol()
    (或
    atoi()
    atol()
    )。发件人:“…
    atoi()
    未检测到错误。”那么,你为什么不让编译器为你做这项工作,编写
    '0'
    而不是
    48
    '9'
    而不是
    57
    ?糟糕的重新设计是一个非常错误的想法,充其量是一个想法。我只想感谢大家的讨论。感觉我已经学到了一个绝对的教训,我的问题已经解决了已解决!1)isdigit未正确编码字符<0。2)不接受“+123”。问题要求的是正整数。我也不接受+123。感谢您对整理代码的回复。虽然函数现在更简单,但它现在无法将任何输入字符串转换为输出数字…我只想对所有讨论的人说声谢谢。感觉我已经学会了一个绝对的shedload,我的问题就这么解决了lved!isdigit需要一个在无符号字符范围或EOF中的值。对于字符,代码风险为UB。“isdigit((无符号字符)长度[…])是谨慎的。这将在“4000000000”上失败。
    printf(“%d\n”,convert(“5000000000”))
    返回
    705032704
    ,我希望OP想要
    -1
    。重点是,在扫描文本以保存在
    未签名的
    中时,溢出是未定义的行为。
    %u
    是合理的,但不可靠。
    /*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";
    
    #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;
    }
    
    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