2017-12-15 14 views
1

ボード(動的に割り当てられた2D配列)をファイルに保存しようとしています。ユーザーはボードを再び使用できます。ボードを保存するには、ユーザはs filenameを入力する必要があります。ユーザー入力を取得するには、私はsaveコマンドのために、他のif文があります。我々は唯一のオープン/リード/ Cでバイナリファイルに書き込む方法を学んできたので2次元配列をファイルに書き込んでC言語に戻す方法

else if (playerMove.command == 's') { 
    char* fileName = NULL; 
    scanf(" %s", fileName); 
    implementSave(boardState, fileName); 

を、私は同じことをやってみましたこれは私のimplementSave関数内で:

void implementSave(BoardState* boardState, char* fileName) { 
    FILE* file = fopen(fileName, "wb"); 
    fwrite(fileName, sizeof(char), sizeof(boardState->board.theBoard), file); 
    fclose(file); 
} 

注:自分のプログラムでいくつかの構造体を使用します。構造体boardにはchar** theBoard, int numRows, int numCols, char blankSpaceが含まれています。

ただし、saveコマンドを実行しようとするとエラーになります。誰かが私を正しい方向に向けることができますか?

+1

は、どのようなエラーの種類は?それがちょうど正しく保存されていない場合、それは 'sizeof'' char ** 'が4または8(またはそのようなもの)であるためです。保存またはロードする文字セルの数を計算する必要があります: 'boardState-> board.numRows * boardState-> board.numCols'。 –

+0

'char * fileName = NULL; scanf( "%s"、fileName); ' - あなたは' fileName'のための記憶域を割り当てていません....また、 '%s'ディレクティブ_は空白スペースをスキップします。書式文字列 –

+0

「BoardState」とは何かによって異なります。しかし、 'fwrite(fileName、sizeof(char)、sizeof(boardState-> board.theBoard)、file);'とにかく完全に間違っています。 'fwrite(boardState、sizeof(char)、sizeof(boardState-> board.theBoard)、file)を意味しましたか? –

答えて

0

ファイルへのダブルポインタの書き込みはできません。最初のポインタの各要素にインデックスを付け、データを行(または列)で書き出す必要がありますが、行を実証しました。これを行うには、forループを使用します。ボードがであると仮定すると、ファイルはバイナリファイルに保存されます。結果のファイルサイズはnumRow * numColバイトになります。

int i; 
for (i = 0; i < BoardState->board.numRow; ++i) { 
     fwrite(BoardState->board.theBoard[i], sizeof(char), BoardState->board.numCol, file) 
} 

読書(「ロード」)ファイルは上記のコードの逆で行われる - ファイルにボードを救う唯一の賢明でないことに注意してください - 私はあなたがの番号を保存、ファイルの先頭に示唆行と列を使用して、ファイルの読み込み(読み込み)中にメモリの割り当てを容易にします。

ですから、上記のコードint型の行/列の数は、これはエンディアンの問題を導入する可能性があります

fwrite(&BoardState->board.numRow, sizeof(int), 1, file); 
fwrite(&BoardState->board.numCol, sizeof(int), 1, file); 
int i; 
for (i = 0; i < BoardState->board.numRow; ++i) { 
     fwrite(BoardState->board.theBoard, sizeof(char), BoardState->board.numCol, file) 
} 

NOTEなっ保存仮定。あなたが興味があるならGoogleにすることができます。

+0

正しい引数の使い方のために 'fwrite()'への呼び出しを修正した場合、私はあなたの答えをアップボックします。 –

+0

@Dúthomhasはそれを捕まえていませんでした!ありがとうございました - モバイルで回答/編集が難しいです。 – Ankush

+1

ええ、私は私のPCの前に座っていなければ、それは私の努力の価値がないことを学んだ。 –

1

このコード

fwrite(fileName, sizeof(char), sizeof(boardState->board.theBoard), file); 

は意味:

書き込みデータをファイルfileに。データはfileNameを指すメモリ位置にあり、データはsizeof(boardState->board.theBoard)の項目から構成され、すべての項目はsizeof(char)バイトです。

これは正しいですか?私はそうは思わない;あなたがファイルにボードデータを書いて、ファイル名を書こうとしていないので、fileNameの位置にデータが見つかるのは間違いです。

sizeof()にも注意してください。 sizeof()は、一部のメモリの内容を動的に決定することはできません。静的メモリのサイズしか知りません。例えば。

char test[20]; 
size_t s = sizeof(test); 

sは20となる。しかし、今、この考えてみます。ポインタのサイズは通常サイズが4バイトまたは8つのバイトとしてs

char test[20]; 
char * ptr = test; 
size_t s = sizeof(ptr); 

は、4または8となります。 sizeof()は、ポインタが指しているメモリのサイズではなく、ここにポインタのサイズを与えます。ポインタが指し示すメモリブロックのサイズを得る方法はCにありません。このサイズは常に知られていなければなりません。

あなたのボードはchar ** theBoardだから、theBoardはメモリまたは文字へのポインタの配列へのポインタです。その場合

theBoard -> [0] -> ['a1', 'b1', 'c1', 'd1', ... ] 
      [1] -> ['a2', 'b2', 'c2', 'd2', ... ] 
      [2] -> ['a3', 'b3', 'c3', 'd3', ... ] 
      : 

作成コードは、([1]、...ロー[0]、と仮定して)そのように見える必要があるだろう:

theBoard = calloc(numberOfRows, sizeof(char *)); 
for (size_t i = 0; i < numberOfRows; i++) { 
    theBoard[i] = calloc(numberOfCols, sizeof(char)); 
} 

その場合は行ごとにデータを書き込む必要があります。

for (size_t row = 0; row < numberOfRows; row++) { 
    fwrite(boardState->board.theBoard[row], sizeof(char), numberOfCols, file); 
} 

もちろん、すべての行の列数が同じであるとします。

私はあなたにチップを与えることができる場合は、ボードchar **を作ってはいけません。ちょうどそれがchar *になります。お使いのボードが20x30(20行、30のcolsの)であれば、あなたはこのようなあなたのボードを定義することができ、参照してください:

char * theBoard = calloc(numberOfRows * numberOfCols, sizeof(char)) 

今、あなたはちょうどこのような単一のアレイ、持っている:

どう
theBoard -> ['a1', 'b1', 'c1', 'd1', ... , 
      'a2', 'b2', 'c2', 'd2', ... , 
      'a3', 'b3', 'c3', 'd3', ... , 
      : 
      ] 

を特定のフィールドにアクセスしますか?非常に単純:

int row = 5; 
int col = 8; 
char field = theBoard[(row * numberOfCols) + col]; 

そして、あなたは1回の呼び出しでボード全体を書き込むことができます。

fwrite(theBoard, sizeof(char), numberOfRows * numberOfCols, file); 

を参照してください、はるかに簡単。 char **アプローチを使用しているとき、あなたの代わりにこれをしなければならないのに対し、また、あなただけのfree(theBoard);を呼び出すことによって、基板全体を解放することができます

for (size_t i = 0; i < numberOfRows; i++) { 
    free(theBoard[i]); 
} 
free(theBoard); 
関連する問題