问题
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