![](http://oshiete.xgoo.jp/images/v2/pc/qa/question_title.png?5a7ff87)
現在BorlandのC言語で人の名前をセーブする処理を
作っています。そこで以下の様に書いたのですが、
コンパイラでは通るのに、実行してセーブをして
ロードをすると必ず強制終了させられてしまいます。
これは一体何がいけなかったのでしょうか?
また、どのように書いたらキチンと動作するのでしょう?
#include <stdio.h>
char *name[10];
void save(void){
FILE *file;
file = fopen("name.txt", "w+");
fprintf(file,"%s %s %s ", name[1], name[2], name[3]);
fclose(file);
}
void load(void){
FILE *file;
file = fopen("name.txt", "r+");
fscanf(file,"%s %s %s ", &name[1], &name[2], &name[3]);
fclose(file);
}
int main( void ){
name[1] = "いち";
name[2] = "に";
name[3] = "さん";
while ( 1 ){
int i;
printf("name[1]:%s name[2]:%s name[3]:%s \n", name[1], name[2], name[3]);
puts("1:セーブ 2:ロード");
scanf("%d",&i);
if ( i == 1 )
save();
else
load();
}
return 0;
}
No.1ベストアンサー
- 回答日時:
2つ間違いがあります。
fscanf(file,"%s %s %s ", &name[1], &name[2], &name[3]);
これは明らかな fscanfの使い方の間違いで、文字列へののポインタが格納されているはずの所に、文字列そのものを書き込んでしまいます。&を取ればとりあえず、環境によっていは動くこともあるでしょう。
しかし、これでも、文字列リテラルに直接書き込んでいるという間違いが依然としてあります。ご質問のプログラムのように最初と同じ文字列を書き込むのではなく"に"のところに"いち"を書く込むと領域を越えてしまいます。また、処理系によっては同じ大きさの文字列を書き込んでも、書き込み禁止の場所に場所に書き込んだ、というエラーが発生し、落ちます。ポインタではなく文字列の二次元配列で、char name[10][256]とか十分な大きさの文字列をとっておくか、ポインタを使うなら、読み込んだ時に malloc で文字列を入れる領域を確保してやるのがいいでしょう。
なるほど!そういうことだったのですか。
さすがにポインタを完全には理解できませんでしたが、
この話のお陰でかなり理解できました。
mallocを試しに使ってみて&をはずしたところ見事に
動作しました。ありがとうございました!
No.2
- 回答日時:
この問題の場合ポインタの配列を使うよりcharの2次元配列を使ったほうが適しているように思います。
-- 8< -- 8< -- 8< -- 8< -- 8< -- 8< -- 8< -- 8< -- 8< -- 8< --
#include <stdio.h>
#include <stdlib.h>
#include <errno.h>
#include <string.h>
char name[4][80];
void
save(void)
{
FILE *file;
if ((file = fopen("name.txt", "w+")) == NULL) {
perror("name.txt");
exit(errno);
}
fprintf(file, "%s %s %s ", name[1], name[2], name[3]);
fclose(file);
}
void
load(void)
{
FILE *file;
if ((file = fopen("name.txt", "r+")) == NULL) {
perror("name.txt");
exit(errno);
}
fscanf(file, "%s %s %s ", name[1], name[2], name[3]);
fclose(file);
}
int
main(void)
{
int i, j;
char buf[BUFSIZ];
strcpy(name[1], "いち");
strcpy(name[2], "に");
strcpy(name[3], "さん");
while (1) {
printf("name[1]:%s name[2]:%s name[3]:%s \n", name[1], name[2],
name[3]);
printf("1:セーブ 2:ロード 3:インプット >> ");
fgets(buf, BUFSIZ, stdin);
i = atoi(buf);
switch (i) {
case 1:
save();
break;
case 2:
load();
break;
case 3:
for (j = 1; j < 4; j++) {
printf("name[%d] => ", j);
fgets(buf, BUFSIZ, stdin);
buf[strlen(buf) - 1] = 0;
strcpy(name[j], buf);
}
break;
}
}
return 0;
}
具体的なソースをありがとうございます。
そういえば二次元配列で実現する方法もありますね・・。
ただ今回の場合どうしてもポインタでやる必要が
あったので・・・でもとても参考になりました。
ありがとうございます。
お探しのQ&Aが見つからない時は、教えて!gooで質問しましょう!
似たような質問が見つかりました
- C言語・C++・C# c言語の問題の説明、各所ごとに 5 2023/07/26 11:03
- PHP PHP MySql 画像を取得 1 2022/06/04 14:05
- PHP 画像が表示出来ません。 1 2023/02/02 16:30
- HTML・CSS CSSが効かずどのように指定すれば良いか分からないのでアドバイスお願い致します 2 2023/06/07 12:25
- PHP PHPで画像の渡しが上手く行きません。 1 2023/02/02 09:39
- JavaScript gasについて 1 2022/05/31 21:51
- C言語・C++・C# C++プログラミングコードにポリモーフィズムを取り入れ方を教えてください。 2 2023/06/09 11:17
- C言語・C++・C# #include <stdio.h>int main(void) { int buf[100] = 6 2022/11/01 22:45
- C言語・C++・C# C言語のエラーについて 2 2022/07/11 13:56
- C言語・C++・C# プログラミングの授業の課題です 1 2023/01/17 22:15
関連するカテゴリからQ&Aを探す
デイリーランキングこのカテゴリの人気デイリーQ&Aランキング
-
VBA で、スペースを含むファイ...
-
連想配列を複数条件で比較して...
-
サブフォルダ内の全てのテキス...
-
文法の質問です
-
ファイル名を変更してアップロ...
-
重複を防ぐ記述について教えて...
-
PHP FTPサーバへの画像アップロ...
-
phpで変数を使ってcopyできない
-
<input type="hidden" >で配列...
-
PHPでURLにジャンプするには?
-
フォーム送信後の更新ボタンで...
-
HTMLで前の画面に戻る時、入力...
-
ラジオボタンをsessionで使いたい
-
現在時刻を反映させた時刻のプ...
-
ini_setのpost_max_size
-
Submit(送信ボタン)を押した...
-
パラメーターを隠す
-
入力した部分を表示させたまま...
-
ゼロ除算
-
エラーを元の画面に表示させるには
マンスリーランキングこのカテゴリの人気マンスリーQ&Aランキング
-
VBA で、スペースを含むファイ...
-
Flaskでサーバー立ち上げに関して
-
POSTの項目に追加
-
ファイル名を変更してアップロ...
-
PHPで入力フォームでデータを確...
-
PHP MySql 画像を取得
-
foreachがうまく動かない
-
PHPからHTMLへの変数の受け...
-
phpで変数を使ってcopyできない
-
サブフォルダ内の全てのテキス...
-
UPDATEできない
-
php+mysqlでの重複チェックにつ...
-
phpでショッピングカート機能を...
-
fputcsv()で1レコード1行になる...
-
配列の値
-
openCVのトラックバーについて
-
if文のなかで
-
sqlite文字列を格納、出力
-
$a = ( $b == $c ) ? $d、 この...
-
$_REQUESTの意味を教えて下さい
おすすめ情報