1

Here is a weird problem:

token = strtok(NULL, s);
printf(" %s\n", token);  // these two lines can read the token and print 

However!

token = strtok(NULL, s);
printf("%s\n", token); // these two lines give me a segmentation fault

Idk whats happened, because I just add a space before %s\n, and I can see the value of token.

my code:

int main() {    

    FILE *bi;

    struct _record buffer;

    const char s[2] = ",";
    char str[1000];
    const char *token;

    bi = fopen(DATABASENAME, "wb+");


    /*get strings from input, and devides it into seperate struct*/
    while(fgets(str, sizeof(str), stdin)!= NULL) {
            printf("%s\n", str); // can print string line by line
            token = strtok(str, s);
            strcpy(buffer.id, token);
            printf("%s\n", buffer.id); //can print the value in the struct
            while(token != NULL){
                token = strtok(NULL, s);
                printf("%s\n", token); // problem starts here
                /*strcpy(buffer.lname, token);  
                printf("%s\n", buffer.lname); // cant do anything with token */        
    }}

    fclose(bi);

    return 1;}

Here is the example of string I read from stdin and after parsed(I just tried to strtok the first two elements to see if it works):

<15322101,MOZNETT,JOSE,n/a,n/a,2/23/1943,MALE,824-75-8088,42 SMITH AVENUE,n/a,11706,n/a,n/a,BAYSHORE,NY,518-215-5848,n/a,n/a,n/a
<
< 15322101
< MOZNETT

jiaru zhu
  • 31
  • 4
  • 3
    Do you know how to use [GDB](https://www.gnu.org/software/gdb/)? – Alejandro Montilla Aug 31 '17 at 18:00
  • it would be helpful if you share an example of the string being parsed so we can reproduce it, please add it to the question. – Andrés Alcarraz Aug 31 '17 at 18:06
  • 1
    Make sure `token` isn't `NULL` – Kninnug Aug 31 '17 at 18:07
  • I can run my function well in my terminal, but my instructor requires me to submit it to Vocareum, and these function isn't work on that website. It seems no debug option on Vocareum. – jiaru zhu Aug 31 '17 at 18:08
  • 2
    @jiaru zhu You need to check whether token is equal to NULL. Also it is unclear how buffer.id is declared. – Vlad from Moscow Aug 31 '17 at 18:08
  • 1
    Never use `strtok`, use `strtok_r` instead. – o11c Aug 31 '17 at 18:23
  • problem seems to be when token is NULL, I can reproduce that on my machine. `printf("%s\n",NULL)` gives segmentation fault, while `printf(" %s\n",NULL)` prints (null). – Andrés Alcarraz Aug 31 '17 at 18:36
  • 2
    @AndrésAlcarraz: That's because some compilers, gcc for example, transform `printf("%s\n", s)` to the simpler and more direct `puts(s);` and `printf` catches null strings, but `puts` doesn't. – M Oehm Aug 31 '17 at 18:40

2 Answers2

2

In the first version your compiler transforms printf() into a puts() and puts does not allow null pointers, because internally invokes the strlen() to determine the lenght of the string.

In the case of the second version you add a space in front of format specifier. This makes it impossible for the compiler to call puts without appending this two string together. So it invokes the actual printf() function, which can handle NULL pointers. And your code works.

1

Your problem reduces to the following question What is the behavior of printing NULL with printf's %s specifier? .

In short NULL as an argument to a printf("%s") is undefined. So you need to check for NULL as suggested by @kninnug

You need to change you printf as follows:

token = strtok(NULL, s);
if (token != NULL) printf("%s\n", token); 

Or else

printf ("%s\n", token == NULL ? "" : token);
Andrés Alcarraz
  • 1,570
  • 1
  • 12
  • 21