如何使用 `strtoul` 解析零可能有效的字符串?
How to use `strtoul` to parse string where zero may be valid?
根据 strtoul
的文档,关于其 return 值...
This function returns the converted integral number as a long int value. If no valid conversion could be performed, a zero value is returned.
如果我正在解析用户提供的字符串“0”,对于我的应用程序,“0”可能是一个有效条目怎么办?在那种情况下,我似乎无法通过使用 strtoul
来确定是否执行了有效转换。还有其他方法可以解决这个问题吗?
进一步阅读man page:
Since strtoul()
can legitimately return 0
or ULONG_MAX
(ULLONG_MAX
for strtoull()
) on both success and failure, the calling program should set errno
to 0
before the call, and then determine if an error occurred by checking whether errno
has a nonzero value after the call.
此外,要处理另一种情况,即在输入中未读取任何数字。如果发生这种情况,strtol()
会将 *endptr
的值设置为 nptr
的值。因此,您还应该检查指针值比较是否相等。
一种解决方案是传递 char
指针的地址并检查它是否指向字符串的开头:
char *str = "0";
char *endptr;
unsgined long x = strtoul(str, &endptr, 10);
if(endptr == str)
{
//Nothing was read
}
How to use strtoul
to parse string where zero may be valid?
从 strtoul()
编辑的任何值 return 可能来自预期的字符串输入或来自 other 不是预期的字符串。进一步的测试是有用的。
以下串全部return0来自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)
。 这个问题在草率的文档审查中经常被遗漏。
前导白色 space 允许。这可能需要也可能不需要。
同时检测负值:
// 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");
考虑以下函数:
#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
中的unsigned long,return指向src
中第一个未解析字符的指针,并将unsigned long保存到*to
.如果出现错误,该函数将 return NULL 并设置 errno 以指示错误。
如果将该函数与 man 3 strtoul
进行比较,您会发现它可以正确处理所有错误情况,并且当 src
产生有效的 unsigned long 时只有 returns 非 NULL .尤其是看注释部分。还要注意负数是如何处理的。
同样的模式适用于 strtol()
、strtod()
、strtoull()
。
根据 strtoul
的文档,关于其 return 值...
This function returns the converted integral number as a long int value. If no valid conversion could be performed, a zero value is returned.
如果我正在解析用户提供的字符串“0”,对于我的应用程序,“0”可能是一个有效条目怎么办?在那种情况下,我似乎无法通过使用 strtoul
来确定是否执行了有效转换。还有其他方法可以解决这个问题吗?
进一步阅读man page:
Since
strtoul()
can legitimately return0
orULONG_MAX
(ULLONG_MAX
forstrtoull()
) on both success and failure, the calling program should seterrno
to0
before the call, and then determine if an error occurred by checking whethererrno
has a nonzero value after the call.
此外,要处理另一种情况,即在输入中未读取任何数字。如果发生这种情况,strtol()
会将 *endptr
的值设置为 nptr
的值。因此,您还应该检查指针值比较是否相等。
一种解决方案是传递 char
指针的地址并检查它是否指向字符串的开头:
char *str = "0";
char *endptr;
unsgined long x = strtoul(str, &endptr, 10);
if(endptr == str)
{
//Nothing was read
}
How to use
strtoul
to parse string where zero may be valid?
从 strtoul()
编辑的任何值 return 可能来自预期的字符串输入或来自 other 不是预期的字符串。进一步的测试是有用的。
以下串全部return0来自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)
。 这个问题在草率的文档审查中经常被遗漏。前导白色 space 允许。这可能需要也可能不需要。
同时检测负值:
// 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");
考虑以下函数:
#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
中的unsigned long,return指向src
中第一个未解析字符的指针,并将unsigned long保存到*to
.如果出现错误,该函数将 return NULL 并设置 errno 以指示错误。
如果将该函数与 man 3 strtoul
进行比较,您会发现它可以正确处理所有错误情况,并且当 src
产生有效的 unsigned long 时只有 returns 非 NULL .尤其是看注释部分。还要注意负数是如何处理的。
同样的模式适用于 strtol()
、strtod()
、strtoull()
。