0

しばらくの間Cでデータベースを作成してきましたが、昨日、対処できないエラーが発生しました。.txt関数からの読み込みを書き込んでいたときに、プログラムが.txtからデータを読み取った後にいくつかの間違いがあった場合があります。(feそれは「1993-5-13」の代わりに「84683-3478-」でした)私はsthを変更しようとしました、そしてそれからがらくたが起こりました、そして私はその時以来そのようなエラーを受け取りました:

「セグメンテーション違反」->Linuxの場合「コールスタックメモリ」->Windowsの場合

私はあまり変更しなかったので(テキストの置き方)、問題がどこにあるのか本当にわかりませんが、がらくたが起こりました。関数を貼り付けています。手伝ってもらえますか?

void load(struct player *main)
{
    int bad;
    struct player *act, *prev;    // act- actual prev - previous
    FILE *plik;
    char a;
    char text[l];                 // l=15;
    if((plik = fopen("savings.txt", "r")) == NULL)
    {
        printf("No savings\n");
        return;
    }
    if(fgets(text, l, plik) == NULL)
    {
        printf("No saved things\n");
        return;
    }
    printf("These are your savings\n");
    do
    {
        printf("%s", text);
    }while(fgets(text, l, plik) != NULL);
    fclose(plik);
    printf("\nType the name of the file you want to load (with .txt) \n");
    do
    {
        gets(text);         // here program stops, no matter if the name is right or not
        char *text = (char*) malloc(30);
        while (getchar()!='\n')
            continue;
        strcat(text, ".txt");
        printf("%s", *text);
        if((plik = fopen(text, "r")) == NULL)
        {
            printf("There is no such file, type once again \n");
            bad=1;
        }
        else bad=0;
    }while(bad);
    act = main->next;
    while(act != NULL)              //cleaning the actual data base
    {
        prev = act;
        act = act->next;
        free(prev);
    }
    nr_of_players = 0;
    act = main;
    while(fscanf(plik, "%s", act->name)!=0)
    {
        fscanf(plik, "%s", biez->surname);
        fscanf(plik, "%d", &biez->date_y);
        fscanf(plik, "%d", &biez->date_m);
        fscanf(plik, "%d", &biez->date_d);
        fscanf(plik, "%s", biez->position);
        fscanf(plik, "%c", &a);
        fscanf(plik, "%d", &biez->nr_cart);
        fscanf(plik, "%d", &biez->salary);
        fscanf(plik, "%d", &biez->matches);
        act->id = ++nr_of_players;
        act->next = (struct player*) malloc(sizeof(struct player));
        prev = act;
        act = act->next;
    }
    free(act);
    prev->next = NULL;
    fclose(plik);
}
4

4 に答える 4

2

コードレビュー

宣言時にすべての変数を初期化する

void load(struct player *main)
{
    int bad = 0;
    struct player *act = NULL, *prev =  NULL;    
    FILE *plik = NULL;
    char a = '\0';

"l" を定数として使用しないでください。使用するフォントによっては、l と 1 を区別するのが難しくなります。

    char text[l] = {0};                 // l=15;


    if((plik = fopen("savings.txt", "r")) == NULL)
    {
        printf("No savings\n");
        return;
    }

ここで "l" を使用する代わりに sizeof(text) を使用することをお勧めします

    if(fgets(text, sizeof(text), plik) == NULL)

    printf("\nType the name of the file you want to load (with .txt) \n");
    do
    {
        // here if user puts his elbow on the keyb it crashes the 
        // program use fgets(buffer,sizeof(buffer),stdin) instead.
        gets(text); 

別のスコープで変数名を非表示にしないでください。新しい変数名を使用してください

        char *mytext = malloc(30); // in C don´t cast malloc 

以下では、「テキスト」で strcat を実行していますが、単に malloc:ed しただけなので、バッファーに何かが存在する可能性があります。strcat() を実行する前にバッファーをクリアするか、strcpy(_s) を使用する必要があります。

        strcat(text, ".txt");

C の文字列は一連の文字です。%s は、\0 で終わる文字列のアドレスを期待するように printf に指示し*textますが、それに文字値を指定すると、うまく終了しません。

        printf("%s", *text);

ときどきではなく、できるときに {} を使用することをお勧めします

        if((plik = fopen(text, "r")) == NULL)
        {
            printf("There is no such file, type once again \n");
            bad=1;
        }
        else bad=0;  
    }while(bad);

使用する前に、「メイン」が適切なものを指していることを確認してください。

    if ( main != NULL )
    {
      act = main->next;
      while(act != NULL)
      {
        prev = act;
        act = act->next;
        free(prev);
      }
    ...

ここでは、代わりに fgets() を使用してデータを読み込み、sscanf() を使用してデータを解析することをお勧めします。

    nr_of_players = 0;
    act = main;
    while(fscanf(plik, "%s", act->name)!=0)
    {
        fscanf(plik, "%s", biez->surname);
        fscanf(plik, "%d", &biez->date_y);
        fscanf(plik, "%d", &biez->date_m);
        fscanf(plik, "%d", &biez->date_d);
        fscanf(plik, "%s", biez->position);
        fscanf(plik, "%c", &a);
        fscanf(plik, "%d", &biez->nr_cart);
        fscanf(plik, "%d", &biez->salary);
        fscanf(plik, "%d", &biez->matches);
        act->id = ++nr_of_players;

これは珍しいことです。通常は、入れるものがもっとあるかもしれない場合に割り当てるのではなく、入れるものが見つかったときに割り当てます。

        act->next = malloc(sizeof(struct player));
        prev = act;
        act = act->next;
    }
于 2013-01-09T09:07:32.087 に答える
1

あなたがやっている:

char *text = (char*) malloc(30);
while (getchar()!='\n')
  continue;
strcat(text, ".txt");
printf("%s", *text);

最後の printf は次のようになります。

printf("%s", text);
于 2013-01-09T08:30:46.803 に答える
0
char text[l];                 // l=15;
 .... deleted a bunch of lines ....
do
{
gets(text);         // here program stops, no matter if the name is right or not
char *text = (char*) malloc(30);
while (getchar()!='\n')
  continue;
strcat(text, ".txt");

text[l]is used for gets()- and gets は、入力バッファの最後を上書きすることをまったく防止しないため、使用するのに悪い関数であることに注意してください。クラッシュするだけです(または、予期しないことをします)。

の代わりにgets()、 を使用しますfgets(stdin, ...)

コード als は意味がありません。

何かを読み取ったばかりtextのシャドウと呼ばれる新しい変数を割り当てるのはなぜですかtext

30 バイトの文字列が必要な場合は、最初に 15 ではなく 30 バイトの文字列を作成してください。

また、 「難読化された C 競合」に参加しない限り、lorと呼ばれる変数/定数を使用しないでください。Oそれらは数字の 1 と 0 に非常によく似ています。

于 2013-01-09T08:40:40.717 に答える
0

char *text = (char*) malloc(30);

なぜあなたはそれに名前を付けているのですか?別の名前を試してください。関数の開始時にtextすでに宣言されています。text

char text[l];

于 2013-01-09T08:40:43.583 に答える