• ベストアンサー
※ ChatGPTを利用し、要約された質問です(原文:複数のC言語プログラムが,一つのファイルに書き込み)

C言語プログラムで複数のファイルに同時書き込みする際のエラーについて

このQ&Aのポイント
  • 複数のC言語プログラムが一つのファイルに書き込みを行う際、エラーが発生せずにプログラムが停止する現象について質問があります。
  • 動作環境はWindows 7のVC++2010コンパイラです。プログラムAは「test.txt」に「@」を無限に書き込み続け、プログラムBは「test.txt」に「_」を書き込む処理を実行します。
  • 質問内容は、(1)Aプログラムの実行結果に「NULL」が出力される理由、および(2)AプログラムがBプログラムの実行を待っているかどうかについてです。

質問者が選んだベストアンサー

  • ベストアンサー
回答No.2

同様の事を経験した事があります。 (以下、既に御存知の事が含まれていたらすみません) > Q.NULLが出力されているのはどうしてか. OS に依存する話かもしれませんが、少なくとも windows ではファイルハンドル毎に「現在の書き込み位置」が管理されています。そして、ファイルが現在どの様な状態になっていようとも「現在の書き込み位置」にデータを書き込もうとします。質問の例では、以下の様な動作になっているのではないでしょうか。 (1) プログラム A が起動し、test.txt を作成する (または、既存のファイルの長さを0にする)。   (初期の「書き込み位置」は、勿論ファイルの先頭。) (2) プログラム A が "位置 X" まで '@' を書き込む (X 文字の @ を出力する) (3) プログラム B が起動し、test.txt の長さを 0 にする。 (4) プログラム A は "位置 X" に新しく '@' を書き込もうとするが、   test.txt の長さが短くなっているので、「長さ X まで拡張」してから '@' を書き込む。 (5) 後は、プログラム B は先頭から順番に文字 '_' を書き込み、   プログラム A は "位置 X" 以降に文字 '@' を書き込む。   プログラム B は "位置 Y" まで書き込んだ所で停止し、   プログラム A は "位置 Z" まで書き込んだ所で停止する。 この過程の (4) の「長さ X まで拡張」の所で 0 (NUL) を fill しているのでしょう。 結果として、"_ _ … _ _ (位置 Y) NUL NUL … NUL NUL (位置 X) @ @ … @ @ (位置 Z)" という内容になるのだと思います。 (3) で長さ 0 にされるのが嫌ならば、fopen の時に "w" ではなくて "r+" で開けば良いです。 "r+" は既存ファイルを読み書き両用で開き、ファイルをクリアしない物です。 ファイルが既存でないかもしれないならば、"a" で開いてから rewind 関数を呼ぶなどすれば良いです。 > Q.AはBが書き込んでいる間,待っていたようだ うーん。質問に記述された結果だけ見れば、特にその様な事があったとは言えない気がします。また、(ファイル排他制御などしていないので) 「書き込みの間待っている」という仕様もないと思います。それから、エラーが出るかどうかについては…エラーが出るという事は無いと思いますが、ファイルの中身が滅茶苦茶になるのでこの様なプログラムに意味があるかは分かりません。。。 但し、それぞれのプログラムのバッファリングによって、文字が実際にファイルに書き込まれるタイミングが遅れる事には注意して下さい。 つまり、プログラム上で fputc を実行しても即座にディスクにデータが書き込まれる訳ではなくて、プログラム内部でデータが或る程度溜まるのを待ってから、まとめて書き出しを実行します。(1文字ごとにディスクと通信していたら時間がかかりますものね!) また、fclose を実行すると、溜めているデータを全部書き出してからファイルを閉じますが、プログラムを強制終了すると、溜めている未書き出しデータが出力されずに終了します。 余談: 参考までに: 「現在の書き込み位置」については ftell 関数 fseek 関数 rewind 関数 「バッファリング」に関しては: fflush 関数, setvbuf 関数

35fa8e3c
質問者

お礼

なるほど、(4)の時点で¥0で埋められている可能性があるのですね。 Y>XだとNULLが発生しないことになりますね。実験パターン不足ですみません。 納得しました。ありがとうございます。 又、rewindなどといった関数を初めて知りました。 あえて排他制御せずにこの失敗実験のようなことを意図的にやりたいときは、アナザープログラムで追加書き込みオープン+ファイルポインタ先頭化でいけるわけですね。必要になったら活かしていこうと思います。 バッファーのサイズも指定できるんですか。 いつもデバッグでプリント文挟んで、そのプリント文を通過しているにもかかわらず出力されず、結局exit関数でエラーの位置を特定するはめになる理由もこれかもしれないですね。出力バッファのサイズを1文字にすればこれを回避できそうです。効率が悪くなるのはありますけれども。 貴重なお話をありがとうございました。

35fa8e3c
質問者

補足

xitoaki様、akinomyoga様、ご回答ありがとうございました。 返信が遅れてすみません。 OSが勝手に排他制御をやってくれているわけではないと分かったので、排他制御をいれていこうと思います。 お二方とも、ありがとうございました。

全文を見る
すると、全ての回答が全文表示されます。

その他の回答 (1)

  • xitoaki
  • ベストアンサー率35% (36/101)
回答No.1

排他制御をしていなければこのようになるのが不思議ではありません。 OS依存の部分が大きいので、断定は出来ませんが、 「AはBが書き込んでいる間,待って」はいないと思います。 どちらもファイルの先頭にあたる同じアドレスから書き始めていますが、 Aが先に「@」を書き込んだ部分に、Bが後から「_」を上書いていっています。 先にBを止めたので、上書きが途中までしか行われず、 後半にAが書いた部分が残っているだけでしょう。 途中のNULLは、強制終了しているために変なデータが入っているのかもしれません。 テキストで開いているため、NULLに見えるだけで、 NULLではない何らかの制御文字が入っている可能性もあります。 毎回同じようになるのであれば、OSのファイル書き込み処理の手順的なものが 書かれているのでしょう。そうでなければ、たまたま何かゴミが入ったものと思います。 EOFを出力せずファイルをクローズもしていないので、 EOFの扱いがどうなっているか判りませんが (このあたりもOSに依存するものでしょう) Bが書いた領域の直後にEOFが書かれなかった為、結果的にAが書いたものが続いて見えています。

35fa8e3c
質問者

お礼

バイナリエディタで開いた上でNULLでした。 一連の現象はOS依存の未定義の挙動であって、本来は排他制御を行う必要があるということですね。 xitoakiさんの推理になるほどと思いました。 ご回答ありがとうございました。

全文を見る
すると、全ての回答が全文表示されます。

関連するQ&A

  • ファイルの入力、出力

    #include<stdio.h> int main(){ int a,b; FILE *fp0, *fp1;   fp0 = fopen("test1.dat", "r"); if( fp0 == NULL ){ printf("Cannot open test1.dat"); exit(1); } fp1 = fopen("file.txt", "w"); while((fscanf(fp0, "%d %d", &a,&b)) != EOF){ fprintf(fp1, "%d %d\n", a*a,b*b); } fclose(fp0); fclose(fp1); return(0); } test1.datファイルを読み込んで、変数a,bに値をいれ、 その二乗結果をfile.txtに書き込むプログラムなのですが test1.datファイルに書き込まれてる値をどのようにa,bに代入されているのかわかりません。 例えば test1.datが 1 2 3 4 5 であると、 file.txtには 1 4 9 16 25 16 と書き込まれています。 test1.datが 1 1 2 2 3 3 であると file.txtには 1 1 4 4 9 9 となっています。 どのように、変数に値が入るのでしょうか??

  • C言語でのファイルへの出力について

    1つのプログラムで、複数のファイルを出力したいと考えております。 ファイル名も test_1.txt test_2.txt   ・   ・   ・ test_100.txt というように、番号のみ違うものに。 そして手動ではなく、for文などを用いてファイル名を決めたいです。 つまり、 for(i=0;i<100;i++){   fp = fopen("test_i.txt","w") } みたいなことをしたいのです。 でも上記のようだとエラーが出ます。 どうしたらよろしいのでしょうか…。

  • C言語 複数指定したファイルの内容表示

    C言語の質問です。 「実行したファイル名を除いたコマンド ライン引数に、 複数個指定したすべてのファイルの内容を標準出力に表示する」 というプログラムを作成しようと思うのですが。。。 どうしても上手くいきません。 1つのファイルの内容を標準出力に表示するプログラムになってしまいます。 どなたかお力を貸してください。 ちなみに、私が作成したプログラムは、以下です。↓↓ #include <stdio.h> int main(int argc, char *argv[]) { FILE *fp; int c; if(argc != 2) { return 1; } if((fp=fopen(argv[1], "r"))==NULL) { return 1; } while((c=fgetc(fp)) !=EOF) { fputc(c, stdout); } fclose(fp); return 0; }

  • C言語 教えてください

    data.txtの中に入っているデータを読み込み、 全て出力するというプログラムを作ろうとしています。 しかし、上手く読み込み表示させることが出来ません。 自分で出来るだけ調べたのですが、 どこがおかしいのかわからないので教えてください。 ↓↓↓現在作っているプログラムです↓↓↓ #include <stdio.h> void main(void) { FILE *fp; char number, name; if ((fp = fopen("data.txt", "r")) == NULL) { printf("FILE OPEN ERROR\n"); } else { while (fscanf(fp, "%s%s", number, name) == 2) { printf("%s-%s\n", number, name); } } fclose(fp); printf("FILE CLOSE !!\n"); } ↑↑↑↑↑↑↑↑↑↑↑↑↑↑↑↑↑↑↑↑ ↓↓data.txt↓↓ 001 aaa 002 bbb 003 ccc 004 ddd 005 eee ↑↑↑↑↑↑↑↑ よろしくお願いします。

  • C言語 複数ファイル操作について

    Cプログラミング初心者です。 論文などの何行も文章があるようなテキストファイル(ここでは1.txtとします)と、他に予め単語をいくつか登録しているテキストファイル(2.txt)を開き、1.txtを最初の行から一行ごとに読み込み、2.txtの中にある単語が1つでもその一行の文章中に含まれていたらその一行の文章を出力し、また次の行においても2.txtの中にある単語のいずれかが含まれているかどうかを調べて含まれている場合は出力…含まれていない場合は出力せずに次の行へ…といったようにこれを1.txt内の最後の行まで繰り返し行うプログラムを作りたいのですが、自分が作ったプログラムでは含む・含まない関係なく1.txt内の文章全てが出力されてしまいます。おそらく最初のwhile文あたりがおかしいのだろうという予想はつくのですがどのように直せばよいのかわからず悩んでいます。どなたか教えていただければ嬉しいです(;_:) #include <stdio.h> #include <stdlib.h> #include <string.h> #define N 1056 void delkaigyo(char *s1,char *s2){ char *p = s1; p=strstr(s1,s2); if(p!=NULL){ strcpy(p,p+strlen(s2)); delkaigyo(p+1,s2); } } int main(void){ FILE *fp; char *filename = "2.txt"; char str1[N]; char str2[N]; char kaigyo[] = "\n"; int i; int a=0; char fname[64]; printf("file:"); scanf("%s", fname);   ←ここで1.txtを入力するとします fp = fopen(fname, "r"); while(fgets(str1, N, fp) != NULL){ delkaigyo(str1, kaigyo); memset(str1, 0, N); fread(str1, 1, N-1, fp); if((fp = fopen(filename, "r")) == NULL){ fprintf(stderr, "%serror.\n", filename); exit(EXIT_FAILURE); } while(fgets(str2, N, fp) != NULL){ delkaigyo(str2,kaigyo); if(strstr(str1,str2)!=NULL){ a = 1; printf("%s\n", str1); break; } } if(a==0){ return 0; } fclose(fp); } return EXIT_SUCCESS; }

  • C言語でファイルを出力

    ファイルの中に変数をいれて複数のファイルをつくろうとしたのですが、 できたファイルの後に?マークがついてきます。 file = fopen("filename.txt", "w"); for(j=0; j<30; j++){ fprintf(file ,"%d.dat\n",j ); } fclose(file); file2 = fopen("filename.txt", "r"); として、ファイル名を書いたファイルをつくってから、 for(k=0; k<30; k++){ fgets(fp,sizeof(fp),file2); file_out = fopen(fp,"w"); 省略 fprintf(file_out, %e %e \n",a ,b); fclose(file_out); } fclose(file2); をして、30個のファイルを出力すると、 0.dat? 1.dat? 2.dat? . . . 29.dat? というファイルができてしまいます。 ファイルの中はしっかりできています。 なにか解決法を知っている方がおりましたら、どうか教えて下さい。

  • 0x00をファイル出力

    #define TEST 0x00 FILE *fp; UCHAR wbuf[1]; wbuf[0] = TEST; if((fp=fopen("test.txt", "w"))==NULL){  printf("open error\n"); } fprintf(fp,"%s",wbuf[0]); fclose(fp); 以上がプログラムでこれを実行するとtest.txtには 文字化けして書き込まれます。 ファイルに0x00と表示させる為にはどうしたらいいですか?

  • C言語 iMacでのファイル入出力

    #include <stdio.h> int main() { FILE *fp; fp=fopen("test.txt","w"); if (fp==NULL){ perror("ファイル・オープンに失敗しました\n"); return -1; }else printf("ファイルを正常に開きました\n"); fprintf(fp,"これが初めてのファイル入出力です\n"); if (fclose(fp)!=0){ perror("ファイル・クローズに失敗しました\n"); return -1; }else printf("ファイルを正常に閉じました\n"); return 0; } これを実行してもどこにもtest.txtというファイルがありません。 同じプログラムをwinでも実行してみたところ正常にファイルが作られました。 mac初心者なもんで、どうすればいいのでしょうか?

  • c言語  2つのファイルを行ごとに読み込むプログラミング

    c言語  2つのファイルを行ごとに読み込むプログラミング 0.txt と 1.txt という2つのテキストフォルダがあり 0.txt の中身は a a b b 1.txt の中身は c c d d というものとします。 これら2つのフォルダを読み込むとき まず1つのフォルダの1行目(a a)を表示し 他方の1行目(c c) 2行目(d d)を表示させて 続いて1つのフォルダの2行目(b b)を表示し 他方の1行目(c c) 2行目(d d)を表示させたいのです。 つまり実行結果が a a c c a a d d b b  ←理想の実行結果です c c b b d d となるようにしたいのですが #include <stdio.h> #include <stdlib.h> #define STR_MAX 256 int main(void) { FILE *fp, *fp2; int i, j, k; char buf[STR_MAX]; char buf2[STR_MAX]; fp = fopen("0.txt", "r"); fp2 = fopen("1.txt", "r"); if (fp == NULL && fp2 == NULL){ printf("\n"); } while(fgets(buf, STR_MAX, fp) != NULL){ while(fgets(buf2, STR_MAX, fp2) != NULL){ printf("%s%s", buf,buf2); } printf("\n"); } fclose(fp); fclose(fp2); return 0; } このプログラミングの実行結果は a a c c a a d d となり、0.txtの2行目(b b)は表示されません。 おそらく while 文 を2重にすることで 不具合が起きているのだと思うのですが 色々と調べた結果、これ以外に プログラミングが思いつきません。 私の理想の実行結果にするためには どこを訂正させると良いのでしょうか? 恐れ入りますが ご回答 どうかよろしくお願いいたします。

  • C言語でファイルから読み込みができません。

    以下のプログラムを実行すると よくわからない値が返ってきます。 なぜでしょうか?教えてください。 #include <stdio.h> void main () { FILE *fp; double a, b; int count=0; fp = fopen("test.xls", "r"); while(1) { fscanf(fp, "%lf %lf\n", &a, &b); printf("%f, %f\n", a, b); count++; if(count==10)break; } fclose(fp); } test.xlsの中身は 1.0 2.0 3.0 4.0 5.0 6.0   :   :   :   : です。 よろしくお願いします。

このQ&Aのポイント
  • 久しぶりに印刷をしようとしたところ、マゼンタが全く出ないです。
  • ヘッドクリーニング、強力ヘッドクリーニングを10回ほど試しましたが、テストプリントでマゼンタが一切出ていません。
  • マゼンタが出るようにするにはどうしたらいいでしょうか?
回答を見る

専門家に質問してみよう