現在ファイルへのc言語でファイル書き換えを行おうとしているのですが
その部分だけ表すとこんな感じです。
※多少省いていますので括弧の数等の間違えがあっても見逃してください。
if((fp = fopen("aaa.txt", "r+")) == NULL)
;
else{
while((ch = fgetc(fp)) != EOF){
if(ch == '\n'){
name[i] = '\0'
i = 0;
continue;
}
name[i] = ch;
i++
if(strcmp(name, name_a){
fprintf(fp, "%s", coment);
}
}
}
ファイルを読み込んでいって、ある名称が見つかったらその後ろの
コメントを更新するというプログラムなのですが。
fprintfまで着ていることは確認できたのですが、なぜか値が書き換わりません。
c言語ではファイル書き換えはあまり一般的ではないということは聞いていて、
以前はすべて読み込んで、一部分を変えてすべて書き込む方法をとって
いましたが、効率が悪い気がしたのでこのやり方を試しています。
1 やり方、関数の使い方が間違っているならば正しい方法を教えてください。
2 そもそも"r+"の使い方がおかしい場合は元のやり方でやります。ただし
"r+"の使い方が詳しく乗っているサイトが見つからなかったので、
わかりやすいサイト等ありましたら、教えてください。
3 ファイル読み書きで検索するとf_seekなる言葉をよく見かけるのですが、
あれを使わないとだめなんでしょうか?
1つでもいいので教えてください。
No.1ベストアンサー
- 回答日時:
# 検証していないので ...
while((ch = fgetc(fp)) != EOF){
if(ch == '\n'){
name[i] = '\0'
i = 0;
continue;
}
name[i] = ch;
i++
if(strcmp(name, name_a){
fprintf(fp, "%s", coment);
}
を
while((ch = fgetc(fp)) != EOF){
if(ch == '\n'){
name[i] = '\0'
i = 0;
continue;
}
name[i] = ch;
i++
if(strcmp(name, name_a){
fseek( fp, 0, SEEK_CUR );
fprintf(fp, "%s", coment);
fseek( fp, 0, SEEK_CUR );
}
といった具合にして fseekで挟んでみましょう
もしくは
ftelで現在位置を取得
ファイルの先頭へfseek
元位置にfseek
書き込み
ftelで現在位置を取得
ファイルの先頭へfseek
元位置にfseek
としたほうがいいのかも ...
VC++のヘルプでは
r+/w+での読み書きのモード変更時には fsetpo/fseek/rewindのいずれかを実行しなさい
と明記されていました
ご回答ありがとうございます。
このままの形ではできませんでしたが、
これを元に調べ、何とか作成できました。
やはりfseek等を使わないと無理みたいですね。
No.3
- 回答日時:
基本的な考え方が間違っています。
他の回答のようにfseekで挟んだとしても「ファイルに対し、挿入や削除は出来ない」ので、単にコメントをfprintfするだけだと、とても困った事になります。
例えば、以下のようなファイルで「123の後ろに、コメント『//456789abc』を書き足す」と、どうなるでしょうか?
あいう
123
ABC
012
###
xyz
結果は
あいう
123//456789abc.###
xyz
になります。(「.」の部分は文字化けが起こる)
あいう
123//456789abc
ABC
012
###
xyz
にはなりません。
また、元のコメントが「//456789abc」だった時に、コメントを「//abc」に短くしたら、どうなるでしょうか?
あいう
123//456789abc
ABC
012
###
xyz
は
あいう
123//abc789abc
ABC
012
###
xyz
になります。
あいう
123//abc
ABC
012
###
xyz
にはなりません。
質問者さんの方法でうまく動くのは「書き換え前のコメントと、書き換えた後のコメントの『バイト数』が、同じ場合だけ」です。
上記のように「コメントのバイト数が変わる」と失敗します。
こういう場合は
・元のファイルを読み込みモードで開く。
・別のファイルを新規作成モードで開く。
・元のファイルから1行読み込む。
・必要ならば、読み込んだ行をメモリ上で加工(コメントを足したり、コメントを短くしたり、コメントを長くしたり、コメントを削除したりする)する。加工が必要ないなら、そのままにする。
・加工が終わった行を、新規作成したファイルに書き込む。
・元のファイルがEOFになるまで「読んで、加工して、書き込んで」を繰り返す。
・繰り返しが終わったら、両方のファイルを閉じる。
・ファイルを閉じたら、元のファイルをunlinkなどで削除する。
・新規作成して閉じたファイルをrenameなどで「元のファイルのファイル名にリネーム」する。
と言う処理をしましょう。
ご回答ありがとうございます。
昔このやり方を使っていたのですが、
(学校の先生がこのやり方が一般的だといっていたため)
一部分だけを書き換える場合にファイル全てを読み込ま
ない方法を探していたため、r+での実装を考えていました。
一応、No1さんの内容を参考に、サイトなどを確認しfseekで作成できました。
バイト数は合わせてあります。
お探しのQ&Aが見つからない時は、教えて!gooで質問しましょう!
似たような質問が見つかりました
- Visual Basic(VBA) VBAのユーザーフォームのテキストボックスに入力制限をしたい 6 2022/11/15 08:28
- C言語・C++・C# このプログラミング誰か教えてくれませんか 1 2022/06/02 15:27
- PHP htmlspecialcharsが機能していないです。 バグですか? 1 2022/04/05 01:22
- Visual Basic(VBA) エクセルのマクロについて教えてください。 7 2023/07/04 09:18
- C言語・C++・C# c言語の問題の説明、各所ごとに 5 2023/07/26 11:03
- その他(IT・Webサービス) ホームページにカウント数を表示する 2 2022/10/28 10:37
- Visual Basic(VBA) 【VBA】写真の縦横比を変えずに貼り付ける 5 2023/06/13 11:42
- C言語・C++・C# このプログラミング誰か教えてくれませんか 2 2022/05/14 09:45
- Visual Basic(VBA) ファイル全てを .xlsm に変更したところ、プログラムが途中で落ちてしまっています 17 2022/12/07 12:03
- C言語・C++・C# プログラミングの授業の課題です 1 2023/01/17 22:15
関連するカテゴリからQ&Aを探す
デイリーランキングこのカテゴリの人気デイリーQ&Aランキング
-
C言語初心者の質問失礼します。
-
C言語関数違いについて。
-
テキストファイルの最終行を削...
-
富士通COBOLの画面定義について
-
ASP .NETでファイル選択ダイア...
-
ファイル名の先頭にアンダース...
-
動画処理のライブラリについて
-
バッチで118項目のCSVを処理し...
-
ダイアログボックスで複数フォ...
-
リエントランスな関数
-
大きいサイズのテキストファイ...
-
複数のファイルからのデータの...
-
最近使ったファイルからファイ...
-
ビットマップのコピーについて
-
エクセルVBAでフォルダ内の重複...
-
VBSでファイルを開く
-
インプットファイル・アウトプ...
-
ドラッグアンドドロップでファ...
-
グローバル変数のよくない使い...
-
スレッドの優先度を下げる方法。
マンスリーランキングこのカテゴリの人気マンスリーQ&Aランキング
-
C言語初心者の質問失礼します。
-
csvファイルを開かずに文字を検...
-
ファイル名の先頭にアンダース...
-
バッチで118項目のCSVを処理し...
-
テキストファイルの最終行を削...
-
CSVファイルへの保存の際、デー...
-
SGファイルって何ですか?
-
大きいサイズのテキストファイ...
-
ドラッグアンドドロップでファ...
-
分割コンパイルの#defineについて
-
グローバル変数のよくない使い...
-
iniファイルに追記がしたいです。
-
Excelマクロでの再読込み方法
-
C言語のfopenについて教えてく...
-
ハッシュの計算時間について
-
VBAにてEXCEL以外のファイル(テ...
-
Javascript で INI の読み書き
-
同じ名前のファイルを作った場...
-
ASP .NETでファイル選択ダイア...
-
VBに、Cのincludeのようなもの...
おすすめ情報