ファイル出力について 

フォーラム(掲示板)ルール
フォーラム(掲示板)ルールはこちら  ※コードを貼り付ける場合は [code][/code] で囲って下さい。詳しくはこちら
新人

ファイル出力について 

#1

投稿記事 by 新人 » 12年前

昨日の問題の延長なんですが、仕様が多くて困っています。
昨日教えて頂いたソースを参考に自分なりに考えて見たソースが下記です。
作成したファイルは"word.txt"としました。

ファイルの書き換えを行うプログラムを作成して下さい。
1:書き換えるファイル名の入力を促すメッセージを画面に出力し、キーボードからの入力を行う。
2:1文字以上入力された場合「1」で入力した名前でファイルの読み込みを行う。
 読み込むファイルが存在しない場合は新規に作成する。
3:ファイルの内容の入力を促すメッセージを画面に出力し、キーボードからの入力を行う。
4:「1」で指定したファイルの内容を「3」で入力した内容にする。
#include <stdio.h>
#include <string.h>

int main() 
{ 
	char str[128];
	FILE *fp;
	
	printf("ファイル名を入力してください。\n");
	
	fgets(str,sizeof(str),stdin);
	if(strcmp(str,"\n")){
		strtok(str,"\n");
		fp=fopen(str,"w");
		if(fp==NULL){
			fprintf(stderr,"ファイルが作成できません。\n");
			return 0;
		}
		printf("ファイルが作成されました。\n");	
			fclose(fp);
		}
		else{
		printf("ファイルが作成されませんでした。\n");
		}
	return 0;
}
仕様はまた後で記述します。

管理人

Re:続・課題

#2

投稿記事 by 管理人 » 12年前

#include <stdio.h>

int main() { 
	char str[128],str2[256];
	FILE *fp;
	printf("ファイル名を入力してください。\n");
	scanf("%s",str);//ファイル名入力	
	if((fp=fopen(str,"w"))==NULL){//ファイルポインタ格納し、無効なら終了
		printf("error\n");
		return 1;//以上終了を示す1
	}
	printf("ファイルに書き込む文章を入力してください。\n");
	scanf("%s",str2);//ファイルに書き込む内容
	fprintf(fp,"%s",str2);//str2の内容をfpが示す中に出力する
	printf("正常終了\n");
	fclose(fp);//閉じる。
	return 0;
}
こんな感じでどうでしょうか。

新人

Re:続・課題

#3

投稿記事 by 新人 » 12年前

早速のレスありがとうござます。
コメント付きで大変分かりやすいです。仕様書で

1回目文字入力後、リターンを押した場合(同一名称のファイルが作成されていない場合)
「ファイルが存在しないので新規に作成する旨のメッセージを表示されているか確認」
「ファイル内容の作成を促すメッセージが画面に出力されていることを確認」
「文字入力が出来ることを確認」(2回目文字入力)

1回目文字入力時、文字入力せずにリターンを押した場合
「ファイル名未入力のメッセージが画面に出力されることを確認」

上のブロックは同一名称のファイルがあるか比較して各々の処理をするのでしょうか?

下のブロックはエンターを認識させれば良いのでしょうか?

また、scanfとfgetsを一緒に使うことはあまりよろしくないのでしょうか?

質問ばかりで申し訳ありません。
ソフトウェア会社に入社したばかりで、今はC言語の本と毎日戦っています(笑)

管理人

Re:続・課題

#4

投稿記事 by 管理人 » 12年前

これ会社から出た宿題なんですか?

管理人

Re:続・課題

#5

投稿記事 by 管理人 » 12年前

恐らく大学生の宿題のように、
「その時答えがわかって提出すればいいや」って物じゃないと思うので、
勉強の仕方を勉強されたらよいかと思います。

専門職につくための、研修みたいな感じですかね?


何かわからないコードがあれば、たいていその箇所をgoogleで検索すればわかります。

例えば、fopen関数のwだとかrだとか書いてあるものの意味が判らない時は

fopen

と検索すれば

http://www.google.co.jp/search?hl=ja&q=fopen&lr=

このような一覧が表示されます。最初のmanは結構最初のうちは難しいので

2件目くらいにヒットするサイトを見てみましょう。

fopenの使い方を

http://www9.plala.or.jp/sgwr-t/c/sec17.html

この辺で調べてみて、こんな表を発見します。
モード 動作                   ファイルがあるとき          ファイルがないとき 
"r"    読み出し専用           正常                        エラー(NULL返却) 
"w"    書き込み専用           サイズを 0 にする(上書き) 新規作成 
"a"    追加書き込み専用       最後に追加する              新規作成 
"r+"   読み込みと書き込み     正常                        エラー(NULL返却) 
"w+"   書き込みと読み込み     サイズを 0 にする(上書き) 新規作成 
"a+"   読み込みと追加書き込み 最後に追加する              新規作成
これをみたら、fopenの返り値によってどのように条件分岐させたらよいかわかりますね。

このように、何かわからない箇所があれば、ぐぐって調べてみることです。

人に聞くにしても、ある程度自分で調べてから聞いたほうがずっとよくわかります。

手元に本をもっていることも大事ですが、今ではウェブでずいぶん勉強できます。

管理人

Re:続・課題

#6

投稿記事 by 管理人 » 12年前

書きそびれました。

scanfとfgetsについてですが、
scanfは悪名高い関数だといわれています。

ほとんどの環境で依存せず使えて、とてもわかりやすく便利な関数ですが、
最大入力文字数が指定できないという点に問題があり、
実際にソフトウェア開発などに携わるんでしたらまず、使う機会がないと思います。

例えば
fgets(str,sizeof(str),stdin);
と指定すればstrのサイズだけですみますが、
scanfは最大の文字数が不定のため、バッファがあふれてしまうことがります。
どんなに沢山10メガバイト位容量を確保したとしても、この関数で10MB+1バイトになってしまうかもしれません。
このような事からscanfはプロの書く関数ではないと思います。

また、scanf("%d %d", &x, &y); このように書いた時、
1
と入力してエンターを押したとしましょう。
改行コードは空白と同じ扱いなのでずっと待機状態になります。
いくらエンターを押しても待機したままということになります。

他にも色々理由はあるのでしょうが、scanfはプログラマーからは嫌われる存在らしいです。

私は完成度よりわかりやすさを重要視したいので、scanfはよく使います。
みんな見慣れてると思いますしね。
そこまで高度なプログラムが書けるようになるまでのお手伝いですから、
そのレベルまでいけば、自分で学べるでしょう。

Justy

Re:続・課題

#7

投稿記事 by Justy » 12年前

 明確にしなれければないのは、これは会社から新人向けに出された課題なのか、それとも(クライアントがついている等)正規の案件での問題なのか、ということです。
 それ次第で、エラーチェック1つとってもがらりと変わります。
 どちらにしても業務の一環なので社内で解決してほしいところですが。


>上のブロックは同一名称のファイルがあるか比較して各々の処理をするのでしょうか?
 そうです。
 fopenの戻り値でもいけますが、本来なら各OSの APIを使って確認するべきでしょう。

>下のブロックはエンターを認識させれば良いのでしょうか?
 fgetsを使っているならエンターは内部で勝手に認識しています。
 fgetsから返ってきた入力された文字列の長さを調べるといいでしょう。

>scanfとfgetsを一緒に使うことはあまりよろしくないのでしょうか?
 そんなことはないです。
 根本的に業務でその2つはほとんど使わないませんが、どちらにしても気をつけなければならないのはバッファをオーバーしてしまうことで、その際のエラー処理を忘れないようにすれば大丈夫です。

Justy

Re:続・課題

#8

投稿記事 by Justy » 12年前

>最大入力文字数が指定できないという点に問題があり、
 あ、一応できますよ。
[color=#d0d0ff" face="monospace]    char buff[8];
    scanf("%7s", buff);[/color]
 出来ても管理人さんの仰るとおり、業務では scanf自体使うことはまずないです。

管理人

Re:続・課題

#9

投稿記事 by 管理人 » 12年前

あ~なるほど~!

ホントにプログラムって本で得る知識だけじゃなく、
どう知識を組み合わせるかですね!

業務で使うにはキー入力は何の関数を使用するのが一般的なんですか?

新人

Re:続・課題

#10

投稿記事 by 新人 » 12年前

皆様回答ありがとうございます。まだまだクライアントの業務を
こなせるレベルではありませんので大丈夫です(汗)

それが社内の上司は教えてくれないことになってるんですよ。
まぁいろいろ試してやってみますね。

Justy

Re:続・課題

#11

投稿記事 by Justy » 12年前

 ちなみに buff[8]の 8を defineによる定数化した場合、以下のように工夫が必要になります。
[color=#d0e0f0" face="monospace]#define MAX_STRING_SIZE             7
#define STRING_BUFFER_SIZE      (MAX_STRING_SIZE+1)

#define STRING_VALUE_(n)    #n
#define STRING_VALUE(n)     STRING_VALUE_(n)

int main(){
    char buff[STRING_BUFFER_SIZE];
    scanf("%" STRING_VALUE(MAX_STRING_SIZE) "s", buff);
    return 0;
}[/color]
>業務で使うにはキー入力は何の関数を使用するのが一般的なんですか?
 状況にもよりますが、例えば GUIを使うなら各 OSの APIということになりますし、仮にコンソールで作るとしたら、処理の自動化の為に WSHとかバッチで処理できるようにしたいので、アプリへの引数として渡してしまいます。

 コンソールで対話型なんて、作る機会は業務では今まで一度もないですね・・・。
 もしあったとしたら、多分 C#か C++で作るのでやっぱり scanfとかは使わないかと。

新人

Re:続・課題

#12

投稿記事 by 新人 » 12年前

業務に関わることを教えていただきありがとうございます。
これからは「なぜ?」を大切にしていきたいと思います。

またお世話になると思います。Justyさん管理人さん
大変有用な回答、解説ありがとうございまいた。

管理人

Re:続・課題

#13

投稿記事 by 管理人 » 12年前

はい、解決されたようでよかったです。
頑張ってくださいね☆

閉鎖

“C言語何でも質問掲示板” へ戻る