ページ 11

ファイル出入力について

Posted: 2016年7月01日(金) 15:47
by 無記名
dat.txtというファイルに、
15 いちご
2 にんじん
5 ごりら
と打っておいて、番号をキーボードで打ったら文字が表示されるプログラムってどうやるんですか?



数字を入力して:5

結果:ごりら

Re: ファイル出入力について

Posted: 2016年7月01日(金) 16:34
by みけCAT
そのプログラムを動かすプラットフォームや、使用するプログラミング言語によるでしょう。
「どうやる」とは、具体的にどういうことですか?

Re: ファイル出入力について

Posted: 2016年7月01日(金) 16:54
by 無記名
初心者なので説明が曖昧ですいません。
C言語です。

ソースコード教えてください

Re: ファイル出入力について

Posted: 2016年7月01日(金) 17:05
by みけCAT
プラットフォームは何ですか?
例えば、LPC1114FN28/102とか、ATmega328Pとか…

Re: ファイル出入力について

Posted: 2016年7月01日(金) 17:20
by 無記名
プラットフォームってなんですか…ほんとに無知ですいません…

Re: ファイル出入力について

Posted: 2016年7月01日(金) 19:32
by amehirune
間を割って失礼します。

語句に関する者は特にそうですが、人に聞く前に、まず自分で調べてみましょう。
解答者によっては「ggrks」としか思われず、結果解答者の意欲を削いでしまう結果に陥ることがあります。
検索結果:プラットフォーム【Google】
さて、「作り方が分からない」とのことでしたが、ファイルの操作の前に、以下のことはできるでしょうか?



①キーボードから、以下のデータを入力(scanfなどでOK)
15 いちご
2 にんじん
5 ゴリラ

②数字を入力させ、それに応じたデータを表示(例:5→ゴリラ)

Re: ファイル出入力について

Posted: 2016年7月01日(金) 19:40
by 無記名
プラットフォームの意味は調べたんですが、自分が使ってるものがわからないです…


①は出来ますが②は出来ないです…

Re: ファイル出入力について

Posted: 2016年7月01日(金) 20:06
by amehirune
了解しました。では質問に答えてください。

1.OSは何ですか?
Windows10とかWindows7とかCentOSとかLinuxとかMacOSとか…どれでしょう?

2.使っている言語は何ですか?
C言語?Java言語?どれでしょう?

Re: ファイル出入力について

Posted: 2016年7月01日(金) 21:11
by 無記名
①OSはWindows7です。

②C言語です

説明不足ですいません

Re: ファイル出入力について

Posted: 2016年7月01日(金) 21:52
by amehirune
よく見たらC言語はすでに書かれていましたね…すみません…

で、肝心のプログラムの作り方ですが、
まずわかりやすく作るために、以下の方法を使います。
・if文
・for文
・配列
これらについては、もうお勉強の方はお済でしょうか?

Re: ファイル出入力について

Posted: 2016年7月01日(金) 22:03
by 無記名
勉強済みです

Re: ファイル出入力について

Posted: 2016年7月01日(金) 22:45
by Dixq (管理人)
上記のようにフォーマットが決まっているものなら
fscanf
が簡単かと思います。
fopenは分かりますか?
fopenしてファイルをオープンしたらそれに対してfscanfで%dと%sを読み込みましょう。
とりあえずループ文は無視し
int n;
char str[256];
のnとstrに

15 いちご

をスキャンして格納するプログラムを書いてみましょう。
できたらこうして特定の変数に入れるという処理をループ文で書けば良さそうです。

Re: ファイル出入力について

Posted: 2016年7月01日(金) 23:33
by 無記名
特定の変数を入れる処理をループ文にするのにはどういう意味があるのでしょうか?

Re: ファイル出入力について

Posted: 2016年7月02日(土) 07:39
by へにっくす
横から失礼。
無記名 さんが書きました:特定の変数を入れる処理をループ文にするのにはどういう意味があるのでしょうか?
それはdixqさんが出したお題のプログラムを書いて、そのコードを掲示してから聞くことだと思います。
なぜそうしなければならないか?
あなたが実際にC言語を使って書けるのかの確認と、そのあとの説明の仕方に影響があるからです。
(C言語勉強してるというが、それを使って書けないのなら勉強できているとは言えないのですよ)
物事には順序があるんです。
それをすっとばして知りたいことだけ知ろうとする。
いい印象もたれませんよ。

Re: ファイル出入力について

Posted: 2016年7月02日(土) 10:47
by usao
(質問者側の文章には含まれていない)「ループ」という単語が
途中から突然(?)出てきているので,そこは疑問に思ってもいいのではないですか?


>特定の変数を入れる処理をループ文にするのにはどういう意味があるのでしょうか?


1データを読み込む処理が無事にできたとして,じゃあ3データを読み込む処理はどうやればいいのか?
多分「同じことを3回やればいい」わけですが,その「3回やる」を実現する方法として

コード:

1データを読み込むための処理コード
1データを読み込むための処理コード
1データを読み込むための処理コード
と,3回書き連ねる方法と,

コード:

以下を3回やる(=3回ループ):
 {1データを読み込むための処理コード}
という形のコードを書く方法 の2種類くらいがぱっと思いつく(他にもまだいろいろとやり方はあるかもしれないけど).
どちらでも目的は達成できるのであれば,ループを使うことが必須というわけではないですから,
「何でループ?」みたいに疑問を持つことは悪くないと思います.

Re: ファイル出入力について

Posted: 2016年7月02日(土) 12:43
by 無記名

コード:

fscanf(fp,"%d %s",&n,str);
printf("数字を入力して:");
scanf("%d",&data);
printf("結果:%s\n",str);
Dixpさんを参考にこのように組んでみたんですが、数字と関係なく「いちご」とでてしまいます。
どこを直せばよいですか?

Re: ファイル出入力について

Posted: 2016年7月02日(土) 15:16
by double-clutch.
こんにちは、 無記名さん...

擬似言語を組んだので、これを元に C_code を書いてみてはどうでしょうか??

使用する擬似言語の仕様
► スポイラーを表示

大まかな手順...
► スポイラーを表示
処理の定義
► スポイラーを表示
自分が書いたC_code を元に上記の擬似言語を組んだのですが、
今日の夕方に元になったcode をこちらのサイトに上げさせていただきます。
その時、あなたの書いたものと比べてみましょう。

Re: ファイル出入力について

Posted: 2016年7月02日(土) 18:03
by double-clutch.
質問があれば、受け付けます。
► スポイラーを表示

Re: ファイル出入力について

Posted: 2016年7月02日(土) 20:15
by 無記名
ありがとうございます!
とりあえずやってみますね

Re: ファイル出入力について

Posted: 2016年7月02日(土) 20:41
by double-clutch.
無記名さん... 
上記の『大まかな手順...』部分の記述が
『処理の定義』部分と同じ内容になっていました。

2016/ 7月2日(土) / 20:35頃 に 修正しておきましたので、今一度確認してください。

補足...
『大まかな手順』では、全体の処理の順序を述べており、
『処理の定義』では、細かな部分を述べております。

Re: ファイル出入力について

Posted: 2016年7月03日(日) 00:57
by かずま
double-clutch. さんが書きました:質問があれば、受け付けます。
feof の使い方が間違っています。
fscanf(fp, "%d %s", &j, str); のあとに printf("d=%d, s=%s\n", j, str);
を入れて、検出なしとなるような番号を指定するとどうなりますか?

Re: ファイル出入力について

Posted: 2016年7月04日(月) 03:46
by double-clutch.
かずま さん...
ご指摘ありがとうございます。

feof() の使い方が間違っている

どのような問題が生じるのかを考察する...
それに際し、処理をより細かく行いたいので、
関数 fprintf() では、一度の呼び出しに対し、制御文に含めて良い『フォーマット指定子』はひとつまでとする
この条件で先に投稿したcodeの一部を改めたい。

原型...

コード:

while( !(feof(fp))) {
	fscanf(fp, "%d %s", &j, str);
	if (i == j)  {
		printf("見つかった文字列:: %s", str);
		break;
	}
}

改め...

コード:

while( !(feof(fp))) {
	fscanf(fp, "%d", &j);
	fscanf(fp, "%s", str);
	
	if (i == j)  {
		printf("見つかった文字列:: %s", str);
		break;
	}
}

[改め...] に続くcodeを擬似言語で表現してみる

コード:

[loop]-[ (fp が指しているファイルが終端に達している!!) の真偽反転 ]
// つまり、fp が指しているファイルが終端に達していない場合は、ループに入る
	-[ file から数字を読込み、変数 j に保持する ]
	-[ file から文字列を読込み、配列 str に保持する ]
	-[ file の読込み地点を次の行の、行頭に移動する ]

	[if]-[ i == j ]
		-[ 配列 str に保持されている文字列をコンソールに出力する ]
		-[ loop を抜ける ]
[/loop]

順を追って確認する...
► スポイラーを表示
問題の箇所...
► スポイラーを表示
如何にまずいか...を考える...
► スポイラーを表示

Re: ファイル出入力について

Posted: 2016年7月04日(月) 05:17
by かずま
かずま さんが書きました: fscanf(fp, "%d %s", &j, str); のあとに printf("d=%d, s=%s\n", j, str);
を入れて、検出なしとなるような番号を指定するとどうなりますか?
なぜ、この質問には答えず、頓珍漢な説明をするんですか?
double-clutch. さんが書きました: それに際し、処理をより細かく行いたいので、
関数 fprintf() では、一度の呼び出しに対し、制御文に含めて良い『フォーマット指
定子』はひとつまでとする
fprintf() は、fscanf() の間違いですよね。
double-clutch. さんが書きました:

コード:

[loop]-[ (fp が指しているファイルが終端に達している!!) の真偽反転 ]
// つまり、fp が指しているファイルが終端に達していない場合は、ループに入る
	-[ file から数字を読込み、変数 j に保持する ]
	-[ file から文字列を読込み、配列 str に保持する ]
	-[ file の読込み地点を次の行の、行頭に移動する ]
[/loop]
fscanf を 2つに分けて、j への読み込みと、str の読み込みの 2行はいいとして、
行頭に移動するは、元のコードに対応しません。
その疑似コードは、C のプログラムと対応しないので、これから先の議論は無意味です。
さらに、ファイルのフォーマットが異なる場合について考察していますが、
それはまた別の話です。たとえ、フォーマットが異なっていたとしても、"%s" で
str に「改行文字」が入ることはあり得ません。
double-clutch. さんが書きました:

コード:

『ファイルの終端』以降の『何か』を配列 str に読み込もうとしている...
..... 処理③に対応している、codeは fscanf(fp, "%s", str) ...
...『フォーマット指定子』は %s ... これは、対象のfile から『ヌル文字列』を読み込む...ということ...
...ここで、『ヌル文字列』の定義は最後の一文字が '\0' である、何かしらの『文字列』...
file には、'\0' はありません。
"%s" は、0個以上の空白(スペース、タブ、改行など)を読み飛ばした後、空白でない
文字を 1個以上読み取って、空白が出てくるか EOF になるまでを文字列として str
に入れます。そして、scanf が str に '\0' を追加します。
最後に読み取った空白は、入力に押し戻し、これは次の fscanf で読み込まれます。

さて、元に戻って、次のように printf を追加してみましょう。
かずま さんが書きました: fscanf(fp, "%d %s", &j, str); のあとに printf("d=%d, s=%s\n", j, str);
を入れて、検出なしとなるような番号を指定するとどうなりますか?
実行結果

コード:

調べたい番号を入力:: 3
j=15, str=いちご
j=2, str=にんじん
j=5, str=ごりら
j=5, str=ごりら
検出なし
printf は 4回実行されていることがわかります。
file には 3行しかないのに、です。
このため if (i == j) { も 4回実行されています。
3回目と 4回目は、j と str の値が同じなので、プログラムとしては何もおかしな
ことはおこりません。
しかし、3行すなわち 3組しかないデータを 4回チェックするのはロジックとして
間違いです。
3回目の fscanf を実行して、最後のデータを読み込んだ後、読み込み位置は
3行目の改行文字の直前になっています。まだ EOF に達していないので、feof()
は真にはなりません。
そして、4回目の fscanf を実行すると、"%d" が改行文字を読み飛ばし、読み込み
位置が EOF に達し、i への数値の読み込みに失敗します。
ここで feof が真になります。
feof のチェックは、fscanf の後に行わないと意味がないということです。
fscanf は書式に従って読み込みを続けるうちに EOF に達し、ひとつもデータを
読み込めなかった場合は、返却値として EOF を返します。だから、普通は、

コード:

    while (fscanf(fp, "%d%s", &j, str) != EOF) {
のように書きます。feof を使いません。
fscanf は、読み込めたデータ数を返しますから、

コード:

    while (fscanf(fp, "%d%s", &j, str) == 2) {
と書いたほうが、以後のデータ処理は正しく行われます。