[英]c reading a file using fgets, strtok causes segmentation fault
嘗試逐行讀取文件,文件中的一行如下所示:
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
,並且繼續運行並導致分段錯誤。 我嘗試在fgets()
之后的buff
末尾添加"\\0"
,但它沒有任何作用。
delim1: ":",
delim2: "(",
delim3: ",)"
我得到的輸出是
InputVector:0(1,3,4,2,40)
InputVector
0
1
3
4
2
40
segfault
您反復有如下代碼:
token = strtok(NULL, INV_DELIM2);
printf("%s\n", token);
如果strtok()
返回NULL,則將其傳遞給printf()
,由於format參數中的%s
,它希望獲得指向以0終止的有效字符串的指針。 NULL不是指向以0終止的有效字符串的指針,因此發生壞事,在您的情況下表現為崩潰。
解決方案:在嘗試使用strtok()
返回的指針之前,請確保其不為NULL。
對未來的建議:了解如何使用調試器單步執行代碼,並習慣於使用valgrind幫助跟蹤內存問題。 當您可以使用工具找出問題所在並確切了解問題出在哪里時,您不必對發生的事情做出錯誤的猜測。
不要跳過緩沖區大小 。 如果最長的行可以是25
字符,則不要使用26
字符作為緩沖區大小,而是:
#define MAXC 1024 /* constant for max characters in buf */
...
char buff[MAXC] = 1024;
(由您決定, 128
可以與其他任何值一起使用,以保證輸入長度的任何變化都不會超出數組的范圍。我寧願緩沖區的長度不能超過1個字符,而是1000個字符太短。)
然后通過檢查長度並驗證buff
中的最后一個字符為'\\n'
字符來驗證每個fgets
調用,例如
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
之前具有有效的字符串。
您不需要多個定界符
然后,如評論中所述,不需要單獨的定界符。 用#define DELIM ":(,)\\n"
或用const char *delim = ":(,)\\n"
聲明的單個delim
就足夠了。 然后,您可以使用以下命令簡單地遍歷所有令牌:
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
仔細檢查一下,如果您還有其他問題,請告訴我。
聲明:本站的技術帖子網頁,遵循CC BY-SA 4.0協議,如果您需要轉載,請注明本站網址或者原文地址。任何問題請咨詢:yoyou2525@163.com.