I have a simple program with a function to check if a C string has only a whole number on it, if there is it returns true (1)
or false (0)
:
#include <ctype.h>
#include <stdio.h>
#include <stdbool.h>
bool isStrWholeNumber(const unsigned char *s) {
if (*s == '\0') return false;
while (isdigit(*s++));
if (*s == '\0') return true;
return false;
}
int main()
{
unsigned char str[] = "a";
bool b = isStrWholeNumber(str);
printf("%d\n", b);
return 0;
}
The pointer increment *s++
should pass the value before increment to the isdigit
function, but it seems it's passing the value after increment, so it's passing the character '\0' instead of 'a' because the function is returning true.
Changing the function to increment the pointer outside the function call, works, returning false for character 'a':
bool isStrWholeNumber(const unsigned char *s) {
if (*s == '\0') return false;
while (isdigit(*s)) s++;
if (*s == '\0') return true;
return false;
}
Why is the while (isdigit(*s++));
not working?
Conclusion
This is what happens when you are tired or don't sleep well, you end doing mistakes like this. The program was working correctly as you can see in answers.
After some rest, I got back to this function and got in a good result, fast and small as I wanted. I used the GCC profiler and gprof to test for performance and also checked the assembly for performance and code size. Tested with and without GCC optimization -O3.
Here is the result with comments, so you can understand it:
bool isStrWholeNumber(const unsigned char *s) {
if (*s) { // Check if string is not empty
--s; // Decrement pointer. It will be incremented in while bellow
while (isdigit(*++s)); // Iterate over string until a non digit character is found
return !*s; // Returns 1 if end of string was reached, else, return 0
}
return false; // Always returns false if string is empty
}
Probably this function could be optimized even further, but I don't know how.
This function is considered by many bad code because of poor legibility, don't go around using it everywhere.
Program is behaving as it should. In first code,
isdigit(*s++)
will return0
ands
will be incremented and the statementif (*s == '\0') return true;
will returntrue
.In second snippet,
*s++
will not be evaluated and the statementreturn false;
will returnfalse
.