尝试逐行读取文件, 文件中的一行如下所示:
InputVector:0(1,3,4,2,40)
代码:
FILE *file = fopen(filename, "r");
char buff[26];
char *token;
while(fgets(buff, 26, (FILE*)file) != NULL) {
buff[strlen(buff)] = '\0';
printf("%s\n", buff);
token = strtok(buff, INV_DELIM1);
printf("%s\n", token);
token = strtok(NULL, INV_DELIM2);
printf("%s\n", token);
while(token != NULL) {
token = strtok(NULL, INV_DELIM3);
printf("%s\n", token);
}
}
我的猜测是,在while循环中,strtok()
在最后一个数字之后没有返回NULL
,并且持续运行并导致分段错误。我尝试在"\0"
之后的buff
末尾添加fgets()
,但是它什么也没做。
delim1: ":",
delim2: "(",
delim3: ",)"
我得到的输出是
InputVector:0(1,3,4,2,40)
InputVector
0
1
3
4
2
40
segfault
答案 0 :(得分:4)
您反复输入以下代码:
token = strtok(NULL, INV_DELIM2);
printf("%s\n", token);
如果strtok()
返回NULL,则将其传递到printf()
,由于format参数中的%s
,它期望获得指向以0终止的有效字符串的指针。 NULL不是指向有效的以0结尾的字符串的指针,因此发生坏事,在您的情况下表现为崩溃。
解决方案:在尝试使用strtok()
返回的指针之前,请确保其不为NULL。
对未来的建议:了解如何使用调试器逐步遍历代码,并习惯于使用 valgrind 帮助跟踪内存问题。当您可以使用工具找出问题所在并确切了解问题出在哪里时,您不必对正在发生的事情做出错误的猜测。
答案 1 :(得分:2)
不要跳过缓冲区大小。如果最长行可以是25
个字符,则不要使用26
个字符作为缓冲区大小,而是:
#define MAXC 1024 /* constant for max characters in buf */
...
char buff[MAXC] = 1024;
(由您决定,128
的工作原理与其他任何值一样,可以保证输入长度的任何变化都不会超出数组范围。我宁愿缓冲区为1000-字符长于1个字符,太短。)
然后通过检查长度并验证fgets
中的最后一个字符为buff
字符来验证每个'\n'
调用,例如
while(fgets(buff, MAXC, file) != NULL) {
size_t len = strlen (buff);
if (len == MAXC - 1 && buff[len - 1] != '\n') {
fputs ("error: line too long.\n", stderr);
/* handle error - generally by reading and dicarding
* characters until '\n' or EOF encounterd and
* then either calling continue or break
*/
}
这将确保您在致电strtok
之前具有有效的字符串。
您不需要多个定界符
然后,如注释中所述,不需要单独的定界符。用delim
定义或用#define DELIM ":(,)\n"
声明的单个const char *delim = ":(,)\n"
就足够了。然后,您可以使用以下命令简单地遍历所有令牌:
for (token = strtok(buff, delim); token; token = strtok(NULL, delim))
printf ("%s\n", token);
简短示例
#include <stdio.h>
#include <string.h>
#define MAXC 1024
int main (int argc, char **argv) {
char buff[MAXC] = "";
char *token = NULL;
const char *delim = ":(,)\n";
FILE *file = argc > 1 ? fopen (argv[1], "r") : stdin;
if (!file) { /* validate file open for reading */
perror ("file open failed");
return 1;
}
while(fgets(buff, MAXC, file) != NULL) {
size_t len = strlen (buff);
if (len == MAXC - 1 && buff[len - 1] != '\n') {
fputs ("error: line too long.\n", stderr);
/* handle error - generally by reading and dicarding
* characters until '\n' or EOF encounterd and
* then either calling continue or break
*/
}
for (token = strtok(buff, delim); token; token = strtok(NULL, delim))
printf ("%s\n", token);
}
if (file != stdin) fclose (file); /* close file if not stdin */
return 0;
}
(如果需要其他结果,可以调整delim
)
使用/输出示例
$ echo "InputVector:0(1,3,4,2,40)" | ./bin/strtok_delims
InputVector
0
1
3
4
2
40
仔细检查一下,如果还有其他问题,请告诉我。