ファイルの読み書きがやっとわかってきた

kerotan0820
記事: 91
登録日時: 14年前

ファイルの読み書きがやっとわかってきた

投稿記事 by kerotan0820 » 13年前

C言語に没頭すると疲れちゃうから、以前作ってた誕生日管理プログラムを完成させるためにはどうすればいいかな~と ぼーっと考えていたのだけど

最近突然やる気湧いたから、勉強しています。

とりあえずテキストファイルの読み書き方法を、ファイルを開く方法、閉じる方法みたいな当たり前なプログラムもちゃんと書いて実行することから始めた。

1文字入出力・・・fgetcで読み込んでfputcでファイルに書き込みみたいな。
1行入力・・・fgets で buff[hoge] に ファイルから読み込んで strstr()関数でそのファイル内に検索対象の文字列が含まれてるか調べる。とかやってみたり。

すぐ忘れるからたまに同じプログラムも打ち込み直してます。

ファイル操作や構造体にかんしては、本当に難しく感じていたけど、少しずつ見についてきて楽しくなって来ました。

データが記録できるようになると、今まで作ってきた、その場その場の計算プログラムだったりとかと違って、便利なものが作れるようになりますよね!

なんだかワクワクしてきたぞー!

ところで、サンプルプログラムをみてずっと思ってたのですが、

CODE:


#include
#include

#define BUF_SIZE 1024
#define SEARCH_STR "int"

main()
{
	FILE *rfp;
	FILE *wfp;
	char buff[BUF_SIZE];

	rfp=fopen("src.txt","r");
	if(rfp==NULL){
		fprintf(stderr,"ファイルのオープンに失敗しました。\n");
		exit(0);
	}
	wfp=fopen("dist.txt","w");
	if(wfp==NULL){
		fprintf(stderr,"ファイルのオープンに失敗しました。\n");
		exit(0);
	}
	while(1){
		if(fgets(buff,BUF_SIZE,rfp)==NULL){
			break;
		}
		fputs(buff,wfp);
	}
	fclose(rfp);
	fclose(wfp);
	return 0;
}
fgets関数でtxtファイルから配列に1行文読み込んで、それをfputs関数で別のtxtファイルへ書き込むプログラム。

CODE:

if(fgets(buff,BUF_SIZE,rfp)==NULL){
			break;
		}
このif文の条件…
fgets(buff,BUF_SIZE,rfp) == NULL

fgets(buff,BUF_SIZE,rfp) はストリーム(.txt)からBUF_SIZE 分の文字列を配列buff に読み込む。
で、もし返り値が NULL(終端ですよ~) だった場合、break!!!

と言うことはわかっていたものの、あくまでただの条件であって fgets 関数はその場でしか仕事してないと思ってました。

この条件文にしか fgets 無いし、ここで読み取ってるのですよね。

すごいなー if文すげ~!

do whlie みたい。 ちょっと違うか(笑)


このサンプルプログラムで最初 SEARCH_STR "int" って定義してるけど…
完全に一つ前のサンプルプログラムから消し忘れてるし。

(・∀・)ニヤニヤ
最後に編集したユーザー kerotan0820 on 2012年3月18日(日) 16:27 [ 編集 3 回目 ]

ISLe
記事: 2650
登録日時: 14年前

RE: ファイルの読み書きがやっとわかってきた

投稿記事 by ISLe » 13年前

kerotan0820 さんが書きました:すごいなー if文すげ~!

do whlie みたい。 ちょっと違うか(笑)
もっと簡潔にできますよ。
詰め込み過ぎは良くないですけど。

CODE:

#include
#include
 
#define BUF_SIZE 1024
 
int main(void)
{
    FILE *rfp;
    FILE *wfp;
    char buff[BUF_SIZE];
 
    if((rfp=fopen("src.txt","r"))==NULL){
        fprintf(stderr,"入力ファイルのオープンに失敗しました。\n");
        exit(EXIT_FAILURE);
    }
    if((wfp=fopen("dist.txt","w"))==NULL){
        fprintf(stderr,"出力ファイルのオープンに失敗しました。\n");
        exit(EXIT_FAILURE);
    }
    while(fgets(buff,BUF_SIZE,rfp)!=NULL){
        fputs(buff,wfp);
    }
    fclose(rfp);
    fclose(wfp);
    return EXIT_SUCCESS;
}
C++ならmain関数の戻り値のintは省略できませんし、Cなら仮引数リストのvoidを省略できません。
すぐにツッコミが入るので気を付けましょう。

(追記)
出力ファイルのオープンに失敗したとき、入力ファイルをきちんと閉じないと問題になる場合があるかもしれません。
最後に編集したユーザー ISLe on 2012年3月18日(日) 17:08 [ 編集 1 回目 ]

アバター
みけCAT
記事: 6734
登録日時: 14年前

Re: ファイルの読み書きがやっとわかってきた

投稿記事 by みけCAT » 13年前

ISLe さんが書きました:C++ならmain関数の戻り値のintは省略できませんし、Cなら仮引数リストのvoidを省略できません。
規格はともかく、どちらもエラーも警告も出ませんでした。
http://ideone.com/Pkzki
http://ideone.com/6TXah

ISLe
記事: 2650
登録日時: 14年前

Re: ファイルの読み書きがやっとわかってきた

投稿記事 by ISLe » 13年前

みけCAT さんが書きました:規格はともかく、どちらもエラーも警告も出ませんでした。
規格上C/C++ともに処理系定義の方法が認められているからです。
その場合、プログラムがmain関数から開始されるかどうかも処理系に依存することになります。
#-Wallオプションを付ければC++は警告が出ます。

結果として同じでもソースコードの持つ意味は異なります。
プログラムがmain関数から開始されたり標準ライブラリが使えたりすることを期待するのなら、main関数の型もそれなりに記述すべきです。
そうでなければ矛盾したソースコードとなり意図を読み取ることも困難になります。
最後に編集したユーザー ISLe on 2012年3月18日(日) 23:16 [ 編集 1 回目 ]

kerotan0820
記事: 91
登録日時: 14年前

RE: コメント返信

投稿記事 by kerotan0820 » 13年前

ISLeさん>>
確かに省略できますね。
とてもわかりやすくなりました(^^)
ありがとうございます♪

仮引数リストにvoidが欠かせない というのは 関数の引数がない場合は(void)と書かないといけないということでしょうか。

みけCATさん
難しい話ですが勉強になります^^。
ありがとうございます。

ISLe
記事: 2650
登録日時: 14年前

Re: ファイルの読み書きがやっとわかってきた

投稿記事 by ISLe » 13年前

kerotan0820 さんが書きました:仮引数リストにvoidが欠かせない というのは 関数の引数がない場合は(void)と書かないといけないということでしょうか。
C++では仮引数リストを省略するとvoidと同義です。
呼び出し側で実引数を指定するとコンパイルエラーになります。

Cでは仮引数リストを省略すると『実引数の検査をしない』という意味になります。
呼び出し側では実引数を指定してもコンパイルエラーになりません。
なので仮引数リストにvoidと書くか書かないかで別のものになります。