Saturday, March 29, 2008

scanf character classes -- oops

There was a serious bug in the code I posted for charToIntRange earlier (which I'll fix momentarily). I had thought that a character range "%[...]" in scanf acts like "%c" (with default width 1, no NUL added) but actually it acts like "%s". So, although &divider had the right type -- char* -- I was corrupting memory leading to an odd crash later. I guess the lesson for me is to read the documentation more thoroughly. (This is the first time I've used character classes in C. scanf suddenly seems much cooler than before now that I know of them.) This is also an error the compiler could catch though. If the argument corresponding to "%[...]" is a pointer to a char variable, this is always a sign of error. Maybe this case isn't common enough to warrant special attention though.

charClass2.c:
#include <stdio.h>
#include <string.h>

int main(int numArgs, char** args)
{
int i;
for (i = 0; i < numArgs; ++i) {
char x[3];
char y[1000];
if (sscanf(args[i], "%2[a]%999[a]", x, y) == 2) {
printf("%zu %zu\n", strlen(x), strlen(y));
}
else {
printf(":-(\n");
}
}
return 0;
}
$ gcc -Wall charClass2.c
$ ./a.out a aa aaa aaaa baaaa
:-(
:-(
:-(
2 1
2 2
:-(

("%zu" is not documented in the man page for printf on my system. I found it after getting warnings with earlier code about an incompatibility with size_t. It looks like it's a C99 extension. Discussion.)

//Actually... I didn't need a character class at all. Character literals match themselves. Of course! Ach. Lesson for me: Don't forget stuff like this.

//And it's not portable to assume char* index(const char *s, int c) is defined in string.h. I've switched to strchr, which I should've been using from the beginning.

No comments: