2016-03-30 20 views
1

最近、C言語のRPGで作業していましたが、テキストファイルからいくつかのデータを保存/読み込む際にいくつかの困難がありました。C関数から返される文字列はガベージ

これは、これを行うの私の最新の試みですが、私はそれをやって多くの貴様の方法を試してみたが、それはほとんど常にで終わる
#include <stdio.h> 
#include <stdlib.h> 
#include <string.h> 

struct player{ 
    int id; 
    char* name; 
}; 

void save(struct player* player) 
{ 
    FILE* fp = 0; 
    char* buffer = 0; 

    fp = fopen("./gamesave.txt", "w"); 
    fclose(fp); 
    buffer = malloc(80); 
    memset(buffer, 0, 80); 

    snprintf(buffer, 80, "%d|%s|\n", player->id, player->name); 
    fp = fopen("./gamesave.txt", "a"); 
    fputs(buffer, fp); 
    free(buffer); 
    fclose(fp); 
} 

struct player* load() 
{ 
    FILE* fp = 0; 
    char* buffer = 0; 
    struct player* player = malloc(sizeof(struct player)); 
    char tokens[] = "|\n"; 

    buffer = malloc (80); 
    memset(buffer, 0, 80); 

    fp = fopen("./gamesave.txt", "r"); 

    if (fgets(buffer, 80, fp)) { 
     char temp[20]; 
     player->id = atoi(strtok(buffer, tokens)); 
     strcpy(temp, strtok(NULL, tokens)); 
     player->name = temp; 
     printf("during load : name is %s\n", player->name); 
    } 
    fclose(fp); 
    free(buffer); 
    return player; 
} 

void main() 
{ 


    struct player* player = malloc(sizeof(struct player)); 
    player->id = 5; 
    player->name = "Bobby"; 
    printf("before save : my name is %s and id is %d\n", player->name, player->id); 

    save(player); 
    struct player* playerN = load(); 
    printf("after load : name is %s and id is %d", playerN->name, playerN->id); 
} 

:ここ

は(それを短くするために簡略化)コードがあります同じ問題:私はの文字列の正しい値を得ることができないようですが、それはintegers.Iで動作しますが、負荷機能中に保存する前にプレイヤーの名前を印刷することはできますが、ロード後には、うまく動作します)。

私の推測では、何らかの種類のメモリ問題と関係していると思いますが、それは数時間から数時間後には解決できませんでした。

ありがとうございます。

+0

これはあなたの全体的な問題を解決するものではありませんが、プレーヤーのデータを保存するときに実行できるショートカットがあります。バッファを割り当て、 'snprintf'を使ってバッファに書き込んだ後、ファイルにバッファを書き込むのではなく、' fprintf'を直接使うだけでバッファを割り当てる必要はありません。 – dreamlax

+0

一時的なポインタを保存しないでください。また、 'player-> name'が何になるべきかを決めるべきです。それは文字列定数へのポインタになるでしょうか?動的に割り当てられたバッファへのポインタ?または何? –

答えて

2

player->nameの領域を割り当てる必要があります。

これには自動変数tempが使用されていますが、関数の復帰時に有効期間が終了します。自動変数はスタックにあります。

スタック上のアドレスを取得してオブジェクトとして保持しています。これは、スタックレベルを返すので、現在のスタックレベルへのポインタをリークします。自動変数へのポインタは使用しても問題ありませんが、その関数インスタンスがアクティブな間、つまりそのライフサイクルと関数が呼び出す関数の中でのみ使用してください。

+0

ちょっと、お返事いただきありがとうございます。それは 'char * temp = malloc(sizeof(char)* 20);を書くだけで私の問題を解決しました。代わりに。あなたがそれの背後に置いた理由(私は自動変数を聞いたことがない)がかなりわかりましたが、私は明日それを働かせます。 – Xely

+0

さて、Cオブジェクトの*記憶クラス*を見てください。永遠に存続する静的オブジェクトを生成する宣言や、関数呼び出しインスタンスがアクティブである間のみ存在する 'auto'と' register'ストレージクラス(今のところは同じものと考えてください)があります。スタックは重要な概念であり、Cのあらゆる重要な実装が自動(ローカル)オブジェクトをベースとするメカニズムです。 'auto'はローカル変数のデフォルトです。がんばろう。 – DigitalRoss

関連する問題