如何使用`strtoul`来解析零的字符串?

时间:2018-12-13 14:29:23

标签: c string-parsing strtoul

根据strtoul的文档,关于其返回值...

  

此函数将转换后的整数返回为long int值。如果无法执行有效的转换,则返回零值。

如果我要解析用户提供的字符串“ 0”,对于我的应用程序来说,“ 0”可能是有效条目,该怎么办?在那种情况下,似乎无法通过使用strtoul来确定是否执行了有效的转换。还有另一种方法可以解决这个问题吗?

4 个答案:

答案 0 :(得分:6)

进一步阅读man page

  

由于strtoul()可以成功返回0ULONG_MAX({{1}的ULLONG_MAX),因此调用程序应将{{1 }}到调用前的strtoull(),然后通过检查调用后errno是否具有非零值来确定是否发生了错误。

此外,要处理另一种情况,即在输入中未读取任何数字。如果发生这种情况,0会将errno的值设置为strtol()的值。因此,您还应该检查指针值是否相等。

答案 1 :(得分:3)

  

如何使用strtoul解析可能为零的字符串?

strtoul()返回的任何值都可能来自预期的字符串输入,或者来自 other 的非预期字符串。进一步的测试很有用。

以下所有字符串strtoul()

返回0
  • 确定"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 :(得分:1)

考虑以下功能:

#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中的无符号long,返回指向src中第一个未解析字符的指针,并将无符号long保存到*to。如果有错误,该函数将返回NULL,并设置errno来指示错误。

如果将函数与man 3 strtoul进行比较,您会看到它可以正确处理所有错误情况,并且仅在src产生有效的无符号长整数时返回非NULL。特别是请参阅“注释”部分。还请注意负数的处理方式。

此模式适用于strtol()strtod()strtoull()

答案 3 :(得分:0)

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

char *str = "0";
char *endptr;
unsgined long x = strtoul(str, &endptr, 10);

if(endptr == str)
{
    //Nothing was read
}