我正在研究一个程序,该程序在给定char数组的情况下执行计算,该数组表示格式 HH:MM:SS
的时间 . 它必须解析各个时间单位 . 这是我的代码的缩减版本,只关注时间:
unsigned long parseTime(const char *time)
{
int base = 10; //base 10
long hours = 60; //defaults to something out of range
char localTime[BUFSIZ] //declares a local array
strncpy(localTime, time, BUFSIZ); //copies parameter array to local
errno = 0; //sets errno to 0
char *par; //pointer
par = strchr(localTime, ':'); //parses to the nearest ':'
localTime[par - localTime] = '\0'; //sets the ':' to null character
hours = strtol(localTime, &par, base); //updates hours to parsed numbers in the char array
printf("errno is: %d\n", errno); //checks errno
errno = 0; //resets errno to 0
par++; //moves pointer past the null character
}
问题是如果输入无效(例如 aa:13:13
), strtol()
显然没有 errno
没有更新到 1
,所以我不能进行错误处理 . 我错了什么?
4 回答
sscanf()
的一个有用技巧是代码可以执行多次传递来检测错误输入:正如其他人所解释的那样,如果无法执行任何转换,
strtol
可能无法更新errno
. 如果转换后的值不适合long
整数,则C标准仅将errnor
设置为ERANGE
.您的代码还有其他问题:
使用
strncpy
复制字符串不正确:如果源字符串长于BUFSIZ
,localTime
将不会以空值终止 . 避免strncpy
,一个几乎从不适合这个目的的功能很难理解 .在这种情况下,您无需清除
:
至'\0'
,strtol
将停在第一个非数字字符处 .localTime[par - localTime] = '\0';
是一种复杂的写法*par = '\0';
一个更简单的版本是这样的:
我将返回类型更改为
long
,以便您可以轻松检查无效格式,甚至可以确定负返回值中的哪个错误 .要获得更简单的替代方案,请使用
sscanf
:此方法仍然接受不正确的字符串,例如
1: 1: 1
或12:00000002:1
. 手工解析字符串似乎是最简洁有效的解决方案 .如果不能执行转换,则不需要
strtol
来生成错误代码 . 相反,您应该使用第二个参数来存储转换后的最终位置,并将其与初始位置进行比较 .顺便说一下,您的代码中还有许多其他错误,这些错误不会影响您所看到的问题,但也应该修复,例如错误使用
strncpy
.在
hours = strtol(localTime, &par, base);
语句之后,您必须先保存errno的值 . 因为在此语句之后,您将调用printf()
语句,该语句也相应地设置errno
.所以在这个语句中"errno"给出
printf()
的错误指示而不是strtol()
...这样做在调用任何库函数之前保存"errno",因为大多数库函数都与"errno"交互 . 正确的用途是:现在检查一下 . 它肯定会给出正确的输出......还有一件事要将此
errno
转换为一些有意义的字符串来表示错误使用strerror()
函数为: