[英]fscanf on string causes segmentation fault
我有一個三行輸入文件。 第一行是一個整數,第二行是帶空格的整數,第三行是一個字符串。
我必須掃描它們而不是基於整數操作字符串。
我的問題是我可以掃描整數,但是掃描字符串會導致 fclose 出現分段錯誤。
我的代碼:
#include <stdio.h>
#include <stdlib.h>
#include <string.h>
int main()
{
FILE* in = fopen("be.txt", "r");
FILE* out = fopen("ki.txt", "w");
if(in==NULL){
printf("Error opening in!\n");
return -1;
}
if(out==NULL){
printf("Error opening out!\n");
return -1;
}
int brknglength, i;
fscanf(in, "%d", &brknglength);
printf("%d\n", brknglength);
int* seed[brknglength];
seed[brknglength] = malloc(sizeof(int[brknglength]));
for(i = 0; i < brknglength; i++){
if (fscanf(in, "%d", &seed[i]) != 1) {
printf("%d", i);
}
printf("%d.: %d \n", i, seed[i]);
}
char string;
fscanf(in, "%s", &string);
free(seed[brknglength]);
fclose(in);
fclose(out);
return 0;
}
導致分段錯誤的原因是什么?
int* seed[brknglength];
seed[brknglength] = malloc(sizeof(int[brknglength]));
看起來您在這里嘗試做的是使seed
成為指向int
數組的指針並為其分配空間。 但是,這是錯誤的語法。 因為[ ]
優先級高於*
, int* seed[brknglength];
定義一個指向int
的指針數組。 此外,對象的名稱是seed
,而不是seed[brknglength]
,因此您可以使用seed = …
而不是seed[brknglength] = …
為其分配值。
要創建指向數組的指針並為其分配空間,請使用:
int (*seed)[brknglength];
seed = malloc(sizeof *seed);
這些可以組合(這並不違反上面關於使用seed =
進行賦值的說明——初始化有一個特殊的語法):
int (*seed)[brknglength] = malloc(sizeof *seed);
但是,您可能不希望這樣。 如果size
是指向數組的指針,則必須在要引用數組的任何地方使用*seed
。 所以fscanf(in, "%d", &seed[i])
必須是fscanf(in, "%d", &(*seed)[i])
。
相反,使得seed
的指針數組,只是使它的指針int
,並盡可能多的分配空間int
只要你想:
int *seed = malloc(brknglength * sizeof *seed);
然后,您可以將seed[i]
用於數組的元素i
而不必使用(*seed)[i]
。
char string;
這將string
定義為單個char
。 但是fscanf(in, "%s", &string);
讀取與輸入一樣多的字符,直到一個空白字符。 因此,您需要向fscanf
傳遞一個指向許多char
第一個的指針。 您可以將string
聲明為數組:
char string[100];
或指向已分配空間的指針:
char *string = malloc(100 * sizeof *string);
然后你可以使用fscanf(in, "%s", string);
. 請注意,您不想傳遞&string
。 那是數組或指針的地址,具體取決於您定義string
。 您想傳遞第一個字符的地址,即&string[0]
,或等效的string
。 (如果string
是一個數組,它會在此表達式中自動轉換為指向其第一個元素的指針,因此它等效於&string[0]
。)
請注意, fscanf
將讀取與輸入包含的字符一樣多的字符,直到出現空白字符。 這可以超過您為string
提供的任何大小。 所以你需要確保輸入沒有太多字符或告訴fscanf
限制它讀取的數量,你可以這樣做:
fscanf(in, "%99s", string);
或者:
int n = 99;
fscanf(in, "%*s", n, string);
請注意,應該告訴fscanf
最多讀取比string
的空格少一個字符,因為它需要添加一個終止空字符。
要釋放這些對象,請使用:
free(seed);
free(string); // (If defined as a pointer, not an array.)
您的第一個問題出現在這里:
int* seed[brknglength];
這在堆棧上定義了一個int
指針數組。
seed[brknglength] = malloc(sizeof(int[brknglength]));
這將初始化數組后面的元素並覆蓋您的堆棧。 要修復它,請使用:
int seed[brknglength]; /* use without free(seed) */
或者:
int *seed = malloc(sizeof(int[brknglength]));
/* ... */
free(seed);
后者也適用於不支持可變長度數組的編譯器。
您的第二個問題是將字符串讀入單個char
變量中,該變量也會覆蓋堆棧。 嘗試類似:
char string[100];
fscanf(in, "%99s", &string);
請注意, "%s"
在空格處停止。 使用類似"%99[^\\t\\n]"
來定義你自己的分隔符,或者使用"%99c"
來定義一個固定長度的字符串。
GNU 編譯器為所有這些情況提供修飾符"m"
(=分配內存)作為方便的非標准擴展:
char *string;
fscanf(in, "%ms", &string);
/* ... */
free(string);
聲明:本站的技術帖子網頁,遵循CC BY-SA 4.0協議,如果您需要轉載,請注明本站網址或者原文地址。任何問題請咨詢:yoyou2525@163.com.