独習Cのファイル入出力について

このQ&Aのポイント
  • 独習Cで勉強しているが、ファイルの入出力についてわからない点が多い。
  • fopen関数を使い、ファイルを開くことができるが、なぜファイル型の宣言が必要なのか疑問である。
  • また、FILE型について理解ができていない。教科書の紹介もお願いしたい。
回答を見る
  • ベストアンサー

独習Cのファイル入出力の章について(長めです)

独習Cで勉強をしています。ファイルの入出力のところでわからなくなってしまいました。 ファイルを開くときはfopenを使うとあり、下記の説明があります。 FILE  *fopen(char *ファイル名, char *モード)  また、ファイル型は構造体という説明があります。 fopenはsdtio.hを使うとあります。 しかし実際の例題では FILE *fp; if ((fp = fopen("myfile","r"))==NULL) { printf("ファイルを開く際にエラーが発生しました\n"); 略 わからないところは次の点です。 fopenはポインタなのでしょうか。stdio,hを使えば良いとあるのに、なぜファイル型の宣言をしなければならないのでしょうか。また例題ではfopenはファイル型として宣言していませんがなぜこれでよいのでしょうか。 例題にある fpというのは特別な意味がある関数またはコマンドなのでしょうか。 FILE型とはどのような型なのでしょうか。int型やchar型はイメージできましたが、FILE型は想像できません。 以上わからないことだらけです。宜しくお願いします。 ほんとうに独習で勉強しています。独習Cより独習に適している教科書があったら、その紹介もお願いします。

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

  • ベストアンサー
  • smz-sys
  • ベストアンサー率100% (1/1)
回答No.4

 私自身100%の独学者なので、これらの疑問はよくわかります。若干無理やりなところ(正確ではない表現)はありますが、以下のように考えてみては如何でしょうか。 1) fopen は関数です。関数には、関数の名、引数、戻り値がセットになります。そこで、関数プロトタイプを、以下のように若干書き換えました。  FILE* fopen(char*, char*);  単に、fopen の頭の"*" を FILE の側に付け替えた違いしかありませんが、意味は同じです。 関数名の前にあるのは戻り値の型名ですので、fopen の戻り値は、FILE* ということになり、これは「 FILE 構造体型へのポインタを返す」ことを意味しています。 2) fopen は、管理するファイルの様々な情報を返す関数で、その入れ物が FILE 構造体(へのポインタ)でもあります。単にファイルを開く行為は、fp という変数は必要ありませんが、正しく動作しているかどうか確かめておかないと、その後の操作が怪しくなります。それを確かめるのが  if(fp == NULL){...} です。ファイルを開くことに失敗すると、fopen は NULL という値を返すのです。  なお、ここで、if(fopen(...) == NULL){...}ではどうしてダメなのかという問題がありますが 4)で後述します。 3) FILE 型の定義は、stdio.h で定義されていますが、入れ物たる変数の宣言は、ユーザーが用意する必要があります。それが fp です。  ここでもやはり、 FILE *fp; と FILE* fp; は同じことで、fp は FILE 構造体のポインタ変数になります。 4) ファイル操作の場合、ファイルが正しく開けたかどうか、ファイルが開いた状態(アクセス出来る状態)かどうか等の状態を操作前に確かめる必要があります。そこで役立つのが fp です。以後、このコードでは対象となるファイルへのアクセスは fp を使って行うのです。  fopen はファイルを開く動作を行いますが、その状態を保持することは出来ません。関数は、その一文を終えると、返す(戻り)値も消えてしまうからです。そのため、fp に保存しておくわけです。  なお、fp = fopen(...);  if(fp == NULL){...}  をまとめた一文が if((fp = fopen(...)) == NULL){}  になります。 5) 最後に、ファイルへの様々な情報を保持する FILE 構造体へのイメージですが、簡単に言えば接続中のファイルかどうかが分かる情報を持っていると考えると良いのではないでしょうか。  構造体なので、複数の情報(型や値)を持っていますが、現状でその中身を知ろうとするとハマります。とりあえず、開いたファイルの身代わりになる便利な変数として捉えましょう。 6) 補足:関数名の頭に * が付くケースとして、関数ポインタ  (*function)(type...) というものがありますので、後々注意しましょう。 7) ポインタに関しては紙面が足りませんが、本体かそのアドレスかの違い程度で今は良いのでは。 8) 良書は沢山あると思いますが、一長一短です。まずその独習Cを一通り読んでみてから(分からなければ飛ばす)、別書を手に取る方が結局速い習得方法かも知れません。その際、分からない、曖昧な点に印を付しておくことです。同書内で解決出来る場合もあれば、他書に頼らざる得ないケースも出て来ます。

その他の回答 (3)

回答No.3

 実際の回答は既に他の方が書かれているので、読んでいて思った事を述べさせてもらいます。  書かれた内容から察すると、「独習C」の該当箇所に至る部分までの内容を消化し切れていない気がします。もし消化できていれば、 > ファイルを開くときはfopenを使うとあり、下記の説明があります。 > FILE  *fopen(char *ファイル名, char *モード)  と書きつつ、 > fopenはポインタなのでしょうか。stdio,hを使えば良いとあるのに、なぜファイル型の宣言をしなければならないのでしょうか。また例題ではfopenはファイル型として宣言していませんがなぜこれでよいのでしょうか。 という質問、表現はしないので。  この様な時の対処は 2 つだと思います。 (1) ここまでの内容を読み直し、 * #include が何を意味するのか? * 関数とは何? * 型とは? あたりをしっかり復習・把握する (2) 取り敢えず、解らない箇所は付箋でも付けて、そのままスルーする 業務で使う場合、これは許されませんが、「独習」して、趣味としてなら問題ないでしょう  私は「独習C」を持っていませんので、どの様な順序で書かれているか解りません。  ただ C の場合、解らないなりに一通り学習すると、前解らなかった事が、「あ~、これはそういう事だったのか」とすんなり解る事が良くあります。  特にポインタは、ハードウェアに詳しくないのであれば、最初はサッパリ解らないと思います。  ##偉そうに書いていますが、私自身も人からポインタの説明を何度聞いても、良く解りませんでした(^^;。解るようになったのは、自分でそれを使ったプログラムを作ってからでした。 > ほんとうに独習で勉強しています。独習Cより独習に適している教科書があったら、その紹介もお願いします。  技術系に限らず、教科書代わりにする本は、本の質が良くても、自分自身の感覚 (リズムとでもいえば良いのか? 良い表現が見つからないm(__)m) とずれているサッパリ解りません。ですから、大きな書店が近くにあれば、実際に手にとって確認すると良いと思いますが、個人的は、 「明解C言語」など柴田望洋さんの本全般 は解りやすいと思います。

  • Tacosan
  • ベストアンサー率23% (3656/15482)
回答No.2

「FILE型」は「FILE型」だ, ってあっさり考えた方がいいと思うよ. どうせ中身は見ないわけだし. さらにいうと, 事実上「FILE *」の形でしか使わないんだから, 常にこの形で使うんだって思ってしまっていい. ついでですが, 規格上「FILE型が構造体である」とは限りません.

  • SAYKA
  • ベストアンサー率34% (944/2776)
回答No.1

fopen は 戻り値が アドレス値、つまりポインタだね。 FILE型というのはstdio.h内で宣言されている構造体で それと同じ物を用意するという話。 で、戻り値がアドレスという事なんだけど これって どういう形の箱なのかが分らないんだよね。 住所だけで 建ってる建物の種類が書いてないって話なので適切に取り出すにはfopenが返すのと同じ形の箱じゃないとならないわけ。 intとかは簡単な形だけどファイルを扱う時はもっと情報量が増えるから、そこで構造体の出番。 とりあえず まず構造体って何よ? ってとこから学んだ方が良いんじゃないかな。。。

関連するQ&A

  • ファイル

    AからZまでの文字が何回出力されるか数えるプログラムなのですが、うまく出力されません。 どこを変えればよろしいでしょうか。 #include<stdio.h> #include<stdlib.h> #include<ctype.h> int count[26]; int main(void) { char str[100] = "xyzYZZ\n"; FILE *fp; char *p; int i; char ch; if((fp = fopen("myfile","w")) == NULL){ printf("ファイルを開くことが出来ません"); exit(1); } p = str; while(*p){ if(fputc (*p,fp) == EOF){ printf("ファイル書き込みエラー"); exit(1); } p++; } fclose(fp); if((fp = fopen ("myfile","r")) == NULL){ printf("ファイルを開くことが出来ません"); exit(1); } while((ch == fgetc(fp)) != EOF){ ch = toupper(ch); if( ch >= 'A' && ch <='Z' ) count[ch - 'A']++ ; } for( i=0 ; i<26 ; i++) printf("%c は %d 回出現\n",i + 'A', count[i]); fclose(fp); return 0; }

  • 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言語)

    はじめまして、nathan3と申します。 昔、さらっとC言語を学んでいたので、仕事場でも活用できればと思い、勉強しなおしています。 以下のプログラムですが、コンパイルはするものの、実行がなされません。 sprintfをつかってファイルを作り、fprintfで読み込み、countで繰り返し別名のファイルを読み込み・作成し…といったプログラムを書いているつもりです。 調べながら書いた稚拙なプログラムですが、ここがちがう!というところをお教えいただけると大変助かります。 #include <stdio.h> int main(void){ FILE *fp,*fo; char *fname1; char *fname2; char s[100],t[100]; int ret,count; for(count = 0 ; count < 3 ; count++) { sprintf(fname1, "sankasha%d.txt", count); fp = fopen(fname1, "r"); if (fp == NULL){ printf("%s can't open a file\n", fname1); return -1; } sprintf(fname2, "matome%d.txt", count); fo = fopen(fname2,"w"); if (fo == NULL){ printf("%s can't open a file\n", fname2); return -1; } printf("--fscanf---"); while( (ret = fscanf(fp,"%[^,],%s", s, t)) != EOF ){ fprintf(fo,"%s ", t); } } fclose(fo); fclose(fp); return 0; } 何度見直しても間違いが見つからず困窮しております。 どうぞ、みなさまのお力をお貸しください! よろしくお願いいたします。

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

    for文の中でファイルの入出力をファイル名を変えながら行うことはできますか?作成したいプログラムは以下の通りになっています。 よろしくお願いします。 #include<stdio.h> main() { int i; FILE *fp; for(i=0;i<10;i++) {  fp=fopen("ココにiの値を入れたい.txt","w");  fprintf(fp,"%d\n",i);  fclose(fp); } return(0); }

  • ファイル入出力について教えて下さい。2

    ご覧いただきありがとうございます。 何度も低レベルな質問で申し訳ありません。 A.PRMというファイルに、 I have a pen. He has a pen. と2行の文章が入っています。 これを読み取り、printfで画面表示させたいのですが、 #include <stdio.h> int main(void) { FILE *fp; char a[50]; char b[50]; if( (fp=fopen("A.PRM", "r" )) != EOF ) { fgets( a, 49, fp ); fgets( b, 49, fp ); } fclose( fp ); printf( "a = %s\n", a ); printf( "b = %s\n", b ); return 0; } とすると、fgetsで余分な改行が入ってしまいます。 fgetsの代わりにfscanfを使用すると、今度はスペースの前までしか読み込んでくれず、「a = I」「b = He」と表示されてしまいます。 どうしたらよいでしょうか? 是非ご回答いただきたいです。よろしくお願いいたします。

  • C言語のファイル読み込みに関して。

    英文を入力したテキストファイルを読み込むプログラムをつくっているのですが、 ファイル読み込みが上手くできません。 #include<stdio.h> main() { char filename[33]; char sty[512]; FILE *fp; printf("FILENAME: "); fgets(filename, 33, stdin); //読み込むテキストファイルを指定 fp = fopen(filename,"r"); if(fp == NULL){ printf("Can't open the file!\n"); return -1; } fgets(sty, 512, fp); fclose(fp); printf("%s\n",sty); } このプログラムなのですが、どうしても"Can't open the file!"が表示されてしまいます。 どうすればいいのでしょうか?

  • ファイル入出力で

    現在ファイル入出力の項目をしているのですが、以下の内容で実行すると エラーが出てどうしても実行できません。主にどこを直せばいいのでしょうか? /* ファイルをコピーするプログラム */ #include <stdio.h> int main(void) { FILE *fin, *fout; char infile[40], outfile[40]; char str[256]; printf("コピー元ファイル = "); scanf("%39s", infile); printf("コピー先ファイル = "); scanf("%39s", outfile); if( (fin = fopen(infile, "r") ) == NULL) { printf("Input file open error.\n"); return 1; } if( (fout = fopen(outfile, "w") ) == NULL) { printf("Output file open error.\n"); fclose(fin); return 1; } while(fgets(str, sizeof(str), fin) != NULL) { fputs(str, fout); } fclose(fin); fclose(fout); return 0; } エラーは FILE 、fin, fout,NULLの未定義です。 よろしくお願いします。

  • C/C++ ファイル入出力操作 (長文です。)

    C/C++歴4ヶ月の初心者プログラマーです。現在、 C/C++でのファイル入出力で大変困っております。 その内容というのはファイルをオープンし指定した テキストファイルに書き込む時に制限をかけたいのです。 例えば、 ファイルに書き込む内容が50行を超えた場合 1番始めに書き込まれた1行目の内容を削除して、 2行目~50行目のデータを1行繰上げて、最新のデータを 50行目に書き込んでいく処理をしたいのですが僕一人では 全くわからず先に進めない状態です。どなたかわかる方 おられますか?よろしければご伝授してください。 途中までのソースを載せておきますので宜しくお願いいたします。 Cで書いていますがC++でも方法があればお願いいたします。 /****************************** サンプルソース ******************************/ #include <stdio.h> #include <stdlib.h> int main(void) { FILE *fp //ファイルポインタの宣言 char str[] = "テスト書き込み"; if((fp=("test.txt","w"))==NULL) //ファイルオープン { exit(1); //ファイルオープンエラー時 } //ここの処理がわかりません。50行まできたら1行目を削除し //2行目~50行目を1行繰上げ、最新データを50行目に書き込み fprintf(fp,"%s\n", str); fclose(); }

  • C言語 ファイル操作

    現在書籍にてC言語を用いたファイル操作を勉強しています。 何故か動作が停止してしまい次に進めません、よろしくお願いします。 #include <stdio.h> #pragma warning(disable:4996) int main(void) { FILE *fp; char fname[64]; printf("ファイル名:"); scanf_s("%s", fname); //ポインタfpが指すストリーム fp = fopen(fname, "r"); if (fp == NULL) printf("\aファイルをオープンできません\n"); else fclose(fp); return(0); } エラーメッセージ ハンドルされない例外が 0xFEFEFEFE (helloworld.exe) で発生しました: 0xC00001A5: 無効な例外ハンドラー ルーチンが検出されました。 (パラメーター: 0x00000003)。

  • ファイルの入出力

    初心者です。よろしくお願いします。 私は今、ErgoVista(EarthView)というソフトで画像を表示するために、datファイルを入力して、x00ファイルを出力するプログラムを作っています。datファイルをエディタで表示すると2行45万列の複素データが出てきます。 とりあえず何の処理もせず、ErgoVistaファイル入出力の例から、下のようなプログラムを作ったのですが、実行ができなく 「unknown software exception(0xc00000fd)がアプリケーションの0x00401997で発生しました」と出てきました。 初心者でして、なんで実行ができないのかまったくわかりません。誰か教えてください。 下のソースファイルで間違っているとこがありましたら、教えてもらえると幸いです。 #include<stdio.h> #include<math.h> #include<string.h> #include<stdlib.h> void Make_Header(char*,int,int); //ヘッダファイル書き出し関数,このまま使用 #define T 451584 main() { /*変数宣言*/ int i; long j; double data1[2][T]; FILE *fp_i, *fp_o; /*入力*/ printf("data in start\n"); fp_i = fopen("200113-HH-100a-IFFT.dat", "r"); for(j = 0; j < T; j++){ for(i = 0; i < 2; i++){ fread(&data1[i][j],sizeof(double),1,fp_i); } } //fread(代入する変数ポインタ,データ型サイズ,データ数,fp_i); fclose(fp_i); //開いたらちゃんと閉じる /*************************************** 処理部分 ***************************************/ /*出力*/ printf("write in start\n"); fp_o = fopen("200113-HH-100a-IFFT1.x00", "wb"); //ファイルオープン,wbはオープン形式でバイナリファイル書き出し fwrite(&data1[i][j],sizeof(double),1,fp_o); //出力部分,ループでまわしたり fclose(fp_o); //開いたらちゃんと閉じる Make_Header("200113-HH-100a-IFFT1.x00",2,T); //ErgoVistaのヘッダファイル情報を出力する関数,?pixel(横数)とline(縦数)を出入? return 0; } /* ヘッダ情報書きこみのサブルーチン このまま使用*/ void Make_Header(char FN[], int pixel, int line) { char hd[40]="", text[40]; FILE *fhd; strncat(hd, FN, strlen(FN)-3); strcat(hd, "hdr"); if((fhd = fopen(hd, "w")) == NULL){ printf("error : cannot open [%s] (header file)\n", FN); exit(1); } fprintf(fhd, "FILE_TYPE = IMAGE \n"); fprintf(fhd, "IMAGE_LINES = %d \n",line); fprintf(fhd, "LINE_SAMPLES = %d \nEND\n",pixel); fclose(fhd); }