簡體   English   中英

字符串上的 fscanf 導致分段錯誤

[英]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.

 
粵ICP備18138465號  © 2020-2024 STACKOOM.COM