C: strtok delivers segmentation fault

跟風遠走 提交于 2021-02-17 06:38:06

问题


I am trying to read a file line by line, and tokenize each line, which have strings separated by spaces and tabs. However, when I run my program, I get the a Segmentation Fault error when I try to print the token. I don't understand why this is happening, as I am using a buffer as the string to tokenize and checking if the token is null. Below is my code:

#include <stdio.h>
#include <stdlib.h>

#define MAX_LINE_LENGTH 70

int main(void)
{
    FILE * testFile;
    char buf[MAX_LINE_LENGTH];
    testFile = fopen("test_file.txt", "r");

    if (testFile == NULL)
    {
        printf("Cannot open test_file.txt.\n");
        exit(0);
    }

     while (fgets(buf, sizeof(buf), testFile) != NULL) {
        char *token = strtok(buf," \t"); 


        while (token != NULL) 
        {
            token = strtok(NULL, " \t"); 

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

    exit(1);
}

Below is the contents of test_file.txt:

String1 String2 String3
String4 String5 String6
String7 String8 String9

回答1:


Two helpful tips -- (1) enable compiler warnings, e.g. minimum -Wall -Wextra -pedantic for gcc/clang or /W3 for VS (any other compiler will have similar options), and do not accept code until it compiles without warning; (2) #include <string.h> where strtok is defined.

In addition to the lack of validation pointed out by @dreamer, you must be using an implicit definition for strtok. You should receive a compiler warning along those lines. Don't ignore any warning, instead go fix it, it will generally tell you the exact line the problem code is on.

Next, don't hardcode filenames. It is just as simple to pass the filename as the first argument to your program (or read from stdin by default). Your second option is to take the filename as input to your program.

Putting those together, you could do something simple like:

#include <stdio.h>
#include <string.h>

#define MAX_LINE_LENGTH 70
#define DELIM " \t\n"

int main (int argc, char **argv) {

    char buf[MAX_LINE_LENGTH];
    /* use filename provided as 1st argument (stdin by default) */
    FILE *fp = argc > 1 ? fopen (argv[1], "r") : stdin;

    if (!fp) {  /* validate file open for reading */
        perror ("file open failed");
        return 1;
    }

    while (fgets (buf, sizeof buf, fp))
        for (char *p = strtok(buf, DELIM); p; p = strtok(NULL, DELIM))
            puts (p);

    if (fp != stdin)   /* close file if not stdin */
        fclose (fp);

    return 0;
}

(note: you need to include '\n' as a delimiter character to prevent the additional '\n' from being part of the last token in each line)

Example Use/Output

$ ./bin/strtokfile test_file.txt
String1
String2
String3
String4
String5
String6
String7
String8
String9

Look things over and let me know if you have questions.




回答2:


Looks like you are printing without checking for NULL for token pointer.

If you need to print all tokens you also need to print inside while loop after strtok system call with addition to non-NULL check for token.



来源:https://stackoverflow.com/questions/59151844/c-strtok-delivers-segmentation-fault

标签
易学教程内所有资源均来自网络或用户发布的内容,如有违反法律规定的内容欢迎反馈
该文章没有解决你所遇到的问题?点击提问,说说你的问题,让更多的人一起探讨吧!