liw.fi is right, by the way. I was a bit surprised by this, since strcspn has to do a much more general problem than the isdigit() approach, but it seems to be the case:
#include <stdio.h>
#include <stdlib.h>
#include <string.h>
#include <ctype.h>
#include <assert.h>
#define NTESTS 10000
#define TESTSIZE 10000
char stest1[TESTSIZE];
char stest2[TESTSIZE];
int test_isdigit(char *s) {
while (*s) {
if (isdigit(*s)) return 1;
s++;
}
return 0;
}
int test_range(char *s) {
while (*s) {
if ((*s >= '0') && (*s <= '9')) return 1;
s++;
}
return 0;
}
int test_strcspn(char *s) {
return s[strcspn(s, "0123456789")] != '\0';
}
int main(int argc, char **argv) {
long int i;
for (i=0; i<TESTSIZE; i++) {
stest1[i] = stest2[i] = 'A' + i % 26;
}
stest2[TESTSIZE-1] = '5';
int alg = atoi(argv[1]);
switch (alg) {
case 0:
printf("Testing strcspn\n");
for (i=0; i<NTESTS; i++) {
assert(test_strcspn(stest1) == 0);
assert(test_strcspn(stest2) != 0);
}
break;
case 1:
printf("Testing isdigit() loop\n");
for (i=0; i<NTESTS; i++) {
assert(test_isdigit(stest1) == 0);
assert(test_isdigit(stest2) != 0);
}
break;
case 2:
printf("Testing <= => loop\n");
for (i=0; i<NTESTS; i++) {
assert(test_range(stest1) == 0);
assert(test_range(stest2) != 0);
}
break;
default:
printf("eh?\n");
exit(1);
}
return 0;
}
It's awfully hard to beat the standard libraries at their own game ... (the usual caveats apply -- YMMV)
$ gcc -O6 -Wall -o strcspn strcspn.c
$ time ./strcspn 0
Testing strcspn
real 0m0.085s
user 0m0.090s
sys 0m0.000s
$ time ./strcspn 1
Testing isdigit() loop
real 0m0.753s
user 0m0.750s
sys 0m0.000s
$ time ./strcspn 2
Testing <= => loop
real 0m0.247s
user 0m0.250s
sys 0m0.000s
UPDATE: Just for fun, I added a bitmap lookup version based on Mike Dunlavey's answer:
char bitmap[256] = {
/* 0x00 */ 1, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
/* 0x10 */ 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
/* 0x20 */ 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
/* 0x30 */ 1, 1, 1, 1, 1, 1, 1, 1, 1, 1,
};
int test_bitmap(char *s) {
while (!bitmap[*(unsigned char *)s]) s++;
return (*s);
}
Which slightly outperforms the others (~.170s) but still can't touch strcspn!