【问题标题】:Converting Number to Integer将数字转换为整数
【发布时间】:2017-09-12 14:26:46
【问题描述】:

我需要将一个可能超出有符号整数范围的数字从字符串转换为整数。如果值超出有符号整数限制,我总是得到数字 0。我了解 0 表示转换失败。

这是我尝试过的:

现在数据将始终低于 int 限制,因此将其存储到 int 中应该不成问题。即使将类型更改为 long 我仍然得到 0。

int getData(char* data){
    char *end;
    unsigned int x = strtol (data, &end, 7);
    return x;
}

我尝试将值放入无符号整数并返回到无符号整数。没关系,我什至没有从中得到正确的转换。

int getData(char* data){
    unsigned x = atoi(data);
    return x;
}

我也尝试过在另一个堆栈交换线程上找到的这个。这里也没有运气。

int getData(char* data){
    int x = strtoul(data, NULL, 10);
    return x;
}

我做错了什么?

【问题讨论】:

  • 你确定你希望结果是base 7strtoul(data, NULL, 7),我认为应该是strtoul(data, NULL, 10)
  • 不错,但如果我用 10 替换它也没关系。
  • 让我们知道您从这段代码中得到了什么以及您的期望
  • 如果要将字符串转换为整数,则必须将strtoul base 设置为 base 10。你想要这个strtol (data, &end, 7); 的base 7 你需要阅读手册页strtoul(3)
  • 我希望得到一个非 0 的数字。我选择什么基数都没有关系。我总是得到 0。例如,如果数据包含 3147483647,我想在名为 x 的无符号整数中查看该数字。

标签: c int type-conversion


【解决方案1】:

我知道 0 表示转换失败。

不完全是。

如果 strto*() 返回 0,则要么

  1. 转换成功,字符串类似于"0", " 0"

  2. 转换失败。字符串类似于"""--123""abc"

要区分,请测试endptr。更强大的getData() 错误消息如下:

int getData(const char* data){
    char *endptr;
    errno = 0; 
    long x = strtol (data, &end, 10);

    // This is the missing code needed for OP to locate the issue
    if (data == end) {
      printf("No conversion <%s>\n", data);

    } else if (errno) {
      printf("Overflow/implementation defined error, %d, <%s>\n", errno == ERANGE, data);
    }
    if (x < INT_MIN || x > INT_MAX) {
      printf("Overflow (long to int), %ld <%s>\n", x, data);
      x = x < 0 ? INT_MIN : INT_MAX; 
      errno = ERANGE;
    }
    return (int) x;
}

我怀疑 OP 的代码是 1) 没有使用预期的 字符串 调用 getData() 或 2) OP 的代码没有正确打印返回值。

【讨论】:

    【解决方案2】:

    虽然您的代码有点奇怪,但它应该可以工作。但是strtol 返回一个long,因此需要做更多的工作才能正确获得unsigned int

    #include <stdio.h>
    #include <stdlib.h>
    #include <string.h>
    #include <errno.h>
    #include <limits.h>
    
    // using "long" for a bit more clarity, adapt according to your needs
    long getData(char *data)
    {
      char *end;
      // reset errno before use.
      errno = 0;
      // variable "end" unused here
      long x = strtol(data, &end, 10);
      // from the manpage
      if ((errno == ERANGE && (x == LONG_MAX || x == LONG_MIN))
          || (errno != 0 && x == 0)) {
        // set errrno for caller (not the best idea here, 
        // this function should return its own error variable)
        errno = ERANGE;
        return LONG_MIN;
      }
      return x;
    }
    // example to get an unsigned int
    unsigned int getUData(char *data)
    {
      char *end;
      // reset errno before use.
      errno = 0;
      // use strtoul() instead
      unsigned long x = strtoul(data, &end, 10);
      // from the manpage
      if ((errno == ERANGE && (x == ULONG_MAX))
          || (errno != 0 && x == 0)) {
        // set errrno for caller (not the best idea here, 
        // this function should return its own error variable)
        errno = ERANGE;
        return UINT_MAX;
      }
      // check if it fits into an unsigned int
      if(x > UINT_MAX ){
        // should return a different error, of course
        errno = EDOM;
        return UINT_MAX;
      }
    
      return (unsigned int)x;
    }
    
    
    int main(int argc, char **argv)
    {
      long ret;
      unsigned int uret;
    
      if (argc != 2) {
        fprintf(stderr, "Usage: %s integer\n", argv[0]);
        exit(EXIT_FAILURE);
      }
    
      // reset errno
      errno = 0;
      // get the input transformed
      ret = getData(argv[1]);
      // check for errors
      if (ret == LONG_MIN && errno != 0) {
        fprintf(stderr, "An error occured while trying to transform %s to a long\n", argv[1]);
        exit(EXIT_FAILURE);
      } else {
        printf("getData(%s) returned %ld\n", argv[1], ret);
      }
    
      // reset errno
      errno = 0;
      // get the input transformed
      uret = getUData(argv[1]);
      // check for errors
      if (uret == UINT_MAX && errno != 0) {
        fprintf(stderr, "An error occured while trying to transform %s to an unsigned int\n", argv[1]);
        exit(EXIT_FAILURE);
      } else {
        printf("getUData(%s) returned %u\n", argv[1], uret);
      }
    
      exit(EXIT_SUCCESS);
    }
    

    我把所有支票放在一个if;您可能会发现将它们分开以从中获取更多信息以找到您的错误是一个更好的主意。

    【讨论】:

      猜你喜欢
      • 2011-12-23
      • 2012-06-27
      • 2013-09-27
      • 2016-09-01
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      相关资源
      最近更新 更多