Question

I have this code:

#include <ctype.h> 

char *tokenHolder[2500];

for(i = 0; tokenHolder[i] != NULL; ++i){

         if(isdigit(tokenHolder[i])){ printf("worked"); }

Where tokenHolder holds the input of char tokens from user input which have been tokenized through getline and strtok. I get a seg fault when trying to use isdigit on tokenHolder — and I'm not sure why.

Was it helpful?

Solution

Since tokenHolder is an array of char *, when you index tokenHolder[i], you are passing a char * to isdigit(), and isdigit() does not accept pointers.

You are probably missing a second loop, or you need:

if (isdigit(tokenHolder[i][0]))
    printf("working\n");

Don't forget the newline.

Your test in the loop is odd too; you normally spell 'null pointer' as 0 or NULL and not as '\0'; that just misleads people.

Also, you need to pay attention to the compiler warnings you are getting! Don't post code that compiles with warnings, or (at the least) specify what the warnings are so people can see what the compiler is telling you. You should be aiming for zero warnings with the compiler set to fussy.

If you are trying to test that the values in the token array are all numbers, then you need a test_integer() function that tries to convert the string to a number and lets you know if the conversion does not use all the data in the string (or you might allow leading and trailing blanks). Your problem specification isn't clear on exactly what you are trying to do with the string tokens that you've found with strtok() etc.

As to why you are getting the core dump:

The code for the isdigit() macro is often roughly

#define isdigit(x) (_Ctype[(x)+1]&_DIGIT)

When you provide a pointer, it is treated as a very large (positive or possibly negative) offset to an array of (usually) 257 values, and because you're accessing memory out of bounds, you get a segmentation fault. The +1 allows EOF to be passed to isdigit() when EOF is -1, which is the usual value but is not mandatory. The macros/functions like isdigit() take either an character as an unsigned char — usually in the range 0..255, therefore — or EOF as the valid inputs.

OTHER TIPS

You're declaring an array of pointer to char, not a simple array of just char. You also need to initialise the array or assign it some value later. If you read the value of a member of the array that has not been initialised or assigned to, you are invoking undefined behaviour.

char tokenHolder[2500] = {0};

for(int i = 0; tokenHolder[i] != '\0'; ++i){

     if(isdigit(tokenHolder[i])){ printf("worked"); }

On a side note, you are probably overlooking compiler warnings telling you that your code might not be correct. isdigit expects an int, and a char * is not compatible with int, so your compiler should have generated a warning for that.

You need/want to cast your input to unsigned char before passing it to isdigit.

if(isdigit((unsigned char)tokenHolder[i])){ printf("worked"); }

In most typical encoding schemes, characters outside the USASCII range (e.g., any letters with umlauts, accents, graves, etc.) will show up as negative numbers in the typical case that char is a signed.

As to how this causes a segment fault: isdigit (along with islower, isupper, etc.) is often implemented using a table of bit-fields, and when you call the function the value you pass is used as an index into the table. A negative number ends up trying to index (well) outside the table.

Though I didn't initially notice it, you also have a problem because tokenHolder (probably) isn't the type you expected/planned to use. From the looks of the rest of the code, you really want to define it as:

char tokenHolder[2500];
Licensed under: CC-BY-SA with attribution
Not affiliated with StackOverflow
scroll top