代码之家  ›  专栏  ›  技术社区  ›  Jim Fell

如何使用'strtoul'解析零可能有效的字符串?

  •  5
  • Jim Fell  · 技术社区  · 7 年前

    根据以下文件: strtoul ,关于其返回值。。。

    如果我正在解析用户提供的字符串“0”,而对于我的应用程序,“0”可能是有效条目,该怎么办?在这种情况下,我似乎无法确定是否使用 斯特图尔

    4 回复  |  直到 7 年前
        1
  •  4
  •   chux    7 年前

    如何使用 strtoul 要分析零可能有效的字符串?

    strtoul() 可能来自预期的字符串输入,也可能来自 其他 并非预期的字符串。进一步的测试是有用的。

    以下 串 全部从返回0 strtoul()

    • "0" , "-0" , "+0"
    • 不好 "" , "abc"
    • 通常认为可以: " 0"
    • 是否正常取决于目标: "0xyz" , "0 " "0.0"

    strtoul()

    int base = 10;
    char *endptr;  //  Store the location where conversion stopped
    
    errno = 0;
    unsigned long y = strtoul(s, &endptr, base);
    
    if (s == endptr) puts("No conversion");      // "", "abc"
    else if (errno == ERANGE) puts("Overflow");
    else if (*endptr) puts("Extra text after the number"); // "0xyz", "0 ", "0.0"
    else puts("Mostly successful");
    

    尚未检测到的内容。

    • 负输入。 strtoul() 有效地围绕这样的 strtoul("-1", 0, 10) == ULONG_MAX) . 这个问题在粗略的文档审查中经常被忽略。

    • 允许前导空白。这可能是也可能不是所希望的。


    // find sign
    while (isspace((unsigned char) *s)) {
      s++;
    }
    char sign = *s;
    
    int base = 10;
    char *endptr;  //  Store the location where conversion stopped
    errno = 0;
    unsigned long y = strtoul(s, &endptr, base);
    
    if (s == endptr) puts("No conversiosn");
    else if (errno == ERANGE) puts("Overflow");
    else if (*endptr) puts("Extra text after the number"); 
    else if (sign == '-' && y != 0) puts("Negative value"); 
    else puts("Successful");
    
        2
  •  7
  •   Sourav Ghosh    7 年前

    man page :

    strtoul() 可以合法返回 0 或 ULONG_MAX ULLONG_MAX strtoull() )无论成功还是失败,都应设置调用程序 errno 到 然后通过检查 厄尔诺 在调用后具有非零值。

    另外,要处理另一种情况,即输入中没有读取数字。如果发生这种情况, strtol() 设置的值 *endptr 到 nptr

        3
  •  1
  •   Osiris    7 年前

    一种解决方案是传递 char 指针并检查它是否指向字符串的开头:

    char *str = "0";
    char *endptr;
    unsgined long x = strtoul(str, &endptr, 10);
    
    if(endptr == str)
    {
        //Nothing was read
    }
    
        4
  •  1
  •   Nominal Animal    7 年前

    考虑以下功能:

    #include <stdlib.h>
    #include <errno.h>
    /* SPDX-Identifier: CC0-1.0 */
    
    const char *parse_ulong(const char *src, unsigned long *to)
    {
        const char    *end;
        unsigned long  val;
    
        if (!src) {
            errno = EINVAL;
            return NULL;
        }
    
        end = src;
        errno = 0;
        val = strtoul(src, (char **)(&end), 0);
        if (errno)
            return NULL;
        if (end == src) {
            errno = EINVAL;
            return NULL;
        }
    
        if (to)
           *to = val;
    
        return end;
    }
    

    src ,返回指向中第一个未分析字符的指针 src ,并将未签名的long保存到 *to . 如果有错误,函数将返回NULL,并设置errno以指示错误。

    man 3 strtoul ,您将看到它正确地处理所有错误情况,并且仅在 src 生成有效的无符号长字符串。特别是注意事项部分。还要注意负数是如何处理的。

    同样的模式也适用于 strtol() , strtod() strtoull()