c - strtol not changing errno -
i'm working on program performs calculations given char array represents time in format hh:mm:ss. has parse individual time units. here's cut down version of code, focusing on hours:
unsigned long parsetime(const char *time) { int base = 10; //base 10 long hours = 60; //defaults out of range char localtime[bufsiz] //declares local array strncpy(localtime, time, bufsiz); //copies parameter array local errno = 0; //sets errno 0 char *par; //pointer par = strchr(localtime, ':'); //parses nearest ':' localtime[par - localtime] = '\0'; //sets ':' null character hours = strtol(localtime, &par, base); //updates hours parsed numbers in char array printf("errno is: %d\n", errno); //checks errno errno = 0; //resets errno 0 par++; //moves pointer past null character } the problem if input invalid (e.g. aa:13:13), strtol() apparently doesn't detect error because it's not updating errno 1, can't error handling. getting wrong?
as others have explained, strtol may not update errno in case cannot perform conversion. c standard documents errnor set erange in case converted value not fit in long integer.
your code has other issues:
- copying string
strncpyincorrect: in case source string longerbufsiz,localtimenot null terminated. avoidstrncpy, poorly understood function never fits purpose. - in case, no not need clear
:'\0',strtolstop @ first non digit character.localtime[par - localtime] = '\0';complicated way write*par = '\0';
a simpler version this:
long parsetime(const char *time) { char *par; long hours; if (!isdigit((unsigned char)*time) { /* invalid format */ return -1; } errno = 0; hours = strtol(time, &par, 10); if (errno != 0) { /* overflow */ return -2; } /* may want check hour within decent range... */ if (*par != ':') { /* invalid format */ return -3; } par++; /* can parse further fields... */ return hours; } i changed return type long can check invalid format , determine error negative return value.
for simpler alternative, use sscanf:
long parsetime(const char *time) { unsigned int hours, minutes, seconds; char c; if (sscanf(time, "%u:%u:%u%c", &hours, &minutes, &seconds, &c) != 3) { /* invalid format */ return -1; } if (hours > 1000 || minutes > 59 || seconds > 59) { /* invalid values */ return -2; } return hours * 3600l + minutes * 60 + seconds; } this approach still accepts incorrect strings such 1: 1: 1 or 12:00000002:1. parsing string hand seem concise , efficient solution.
Comments
Post a Comment