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 strncpy incorrect: in case source string longer bufsiz, localtime not null terminated. avoid strncpy, poorly understood function never fits purpose.
  • in case, no not need clear : '\0', strtol stop @ 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

Popular posts from this blog

javascript - jQuery: Add class depending on URL in the best way -

caching - How to check if a url path exists in the service worker cache -

Redirect to a HTTPS version using .htaccess -