質問をすることでしか得られない、回答やアドバイスがある。

15分調べてもわからないことは、質問しよう!

新規登録して質問してみよう
ただいま回答率
85.48%
C

C言語は、1972年にAT&Tベル研究所の、デニス・リッチーが主体となって作成したプログラミング言語です。 B言語の後継言語として開発されたことからC言語と命名。そのため、表記法などはB言語やALGOLに近いとされています。 Cの拡張版であるC++言語とともに、現在世界中でもっとも普及されているプログラミング言語です。

Q&A

解決済

5回答

848閲覧

ファイルの入出力がうまくできません

sawayakaunagi

総合スコア17

C

C言語は、1972年にAT&Tベル研究所の、デニス・リッチーが主体となって作成したプログラミング言語です。 B言語の後継言語として開発されたことからC言語と命名。そのため、表記法などはB言語やALGOLに近いとされています。 Cの拡張版であるC++言語とともに、現在世界中でもっとも普及されているプログラミング言語です。

0グッド

1クリップ

投稿2021/12/05 14:59

編集2021/12/08 06:55

ファイルを読み込み、文字数と行数をカウントするプログラムを作成したのですが、実行すると、out.txtに行数は表示されるのですが、文字数が0となっていました。なぜこうなるのでしょうか?

c

1コード 2#include<stdio.h> 3int main() 4{ 5 FILE *fp; 6 int line = 0; 7 int word = 0; 8 char str[2048]; 9 int c; 10 11 fp = fopen("list.txt","r"); 12 13 if( fp == NULL) 14 { 15 printf("Cannot open file¥n"); 16 return 1; 17 } 18 while( fgets(str, 2048, fp) != NULL ) 19 { 20 line ++; 21 } 22 while(( c = fgetc(fp)) != EOF ) 23 { 24 word ++; 25 } 26 fclose(fp); 27 28 fp = fopen("out.txt", "w"); 29 30 if( fp == NULL) 31 { 32 printf("Cannot open file¥n"); 33 return 1; 34 } 35 fprintf( fp, "%d\n", line); 36 fprintf( fp, "%d", word); 37 fclose( fp ); 38 return 0; 39}

c

1list.txtの中身です。 2 3List of countries and dependencies by population density 4From Wikipedia, the free encyclopedia 5This is a list of countries and dependent territories ranked by area and by population. 6Area includes land and water. 7 8Number of countries in the list: 7 9Countries: Australia China India Japan Russia UK US 10 11List of population 12Countries Population 13China 1400055440 14India 1354969000 15US 330263247 16Russia 146877088 17Japan 126577691 18UK 66435600 19Australia 25525452 20 21List of area 22Countries Area 23Russia 17125242 24US 9833517 25China 9640821 26Australia 7692024 27India 3287240 28Japan 377944 29UK 242910 30

気になる質問をクリップする

クリップした質問は、後からいつでもMYページで確認できます。

またクリップした質問に回答があった際、通知やメールを受け取ることができます。

バッドをするには、ログインかつ

こちらの条件を満たす必要があります。

kazuma-s

2021/12/05 15:06

list.txt の内容はどうなっていますか? 何行で何文字なんですか?
BeatStar

2021/12/05 22:31 編集

前回だけでも散々言われてますよね? そもそもプログラミングってのは『書いて終わり』ではありません。 デバッグっていうのも含みます。 『DIYをやりたい』っていう人が、「椅子を作りたいから誰か設計図を書いてくれ」とか「椅子を作ったが、高さが合わない。誰が修繕してくれ」と言うようなものです。 DIYは修繕もその一部のはずです。 でも自分で修繕しようとすらしない。 『そんなにやりたくないならやらなければ?』と言いたくなりませんか? 別に作らなくとも既製品を店とかで買えばいいし。仮に欲しいものが既製品に無くとも『プロに金を払って頼んで作ってもらう』とかすればいいし。 さらに過去質問を見る限り改善する気が無いようにも思えます。 ひたすら「基礎からやるべき」といわれているのにそれをひたすら無視。 なんか、「プロなんだからこんな簡単なもんできるだろ。は?こんなんで金取るのかよ?ク○かよ!」というク○な態度みたいです。 (自分の持ち場は自分でやるのが当たり前では?) まずはデバッグからやりましょう。 (ご自分でやることを望んであえて発破をかけています)
BeatStar

2021/12/05 22:47

さらに、仕様が曖昧です。『表示』とはなんでしょうか? 少なくとも『標準出力』(コンソールへの出力)と『ファイルへの出力』の2種類があります。 さらに組み込み系のように独自の出力先もあったりします。 質問さんにとっては愚問でも回答者は天才ではないので提示された情報からしか読み取れません。 まずは最悪でも『仕様を明確に』しましょう。(できれば自分でデバッグまでしてほしい…)
BeatStar

2021/12/05 22:49

また、読み込むファイルの内容ぐらいは提示しましょう。コードの問題ではなく、ファイルが無いとか存在していてもファイルの中身が…とかもありえます。
majiponi

2021/12/06 00:24

Next CONAN'S Hint: 変数名
dodox86

2021/12/06 00:56

なぜこのコードで行数や文字数が得られると思えるのだろう。何となくコードを書くだけで、考えることは回答者に丸投げでしょうか。 まぁ、様々な質問・回答のスタイルがあると思いますが、残念ながら指摘に耳を傾けて改善するつもりは無いようなので、スルーが適当です。
dodox86

2021/12/09 02:20

@質問者さん 既にいくつも回答をいただいているのですから、応対しましょう。
guest

回答5

0

実行時に数字が表示されません。どこが問題でしょうか?

printf("Number of lines ="); fprintf( fp, "%d", line);

printf では、"Number of lines =" を表示していますが、行数は表示していません。
fprintf はファイルへの書き込みであり、表示ではありません。
行数は out.txt というファイルに書き込まれています。

ところが、fp というのは、入力ファイルの list.txt をオープンした時に
取得したものです。入力ファイルに書き込みができるはずがありません。
fprintf( fp2, "%d", line); なら、何の問題もなく out.txt に行数が書き込まれます。
でも、不思議なことに out.txt は出来ていて、行数が書き込まれていました。

調べてみたところ、次のようなことが分かりました。
fclose(fp); でポインタ fp が指していた FILE構造体は未使用になります。
fp2 = fopen("out.txt", "w"); でオープンした時、同じ FILE構造体が再利用されて
fp2 には fp と同じ値が返ってきていました。だから、書き込みがうまく行ったのです。

C

1printf("Number of lines = %d\n", line); 2fprintf(fp2, "Number of lines = %d\n", line);

このようにすれば、画面にも表示され、ファイルにも書き込まれます。
でも、プログラムは、1行読み込んで line を 1 にし、次の 1文字を読み込んで
word を 1 にするだけで、それ以上カウントアップはしていません。
変だということが分かりませんか?
コメントをお願いします。

投稿2021/12/06 05:29

kazuma-s

総合スコア8224

バッドをするには、ログインかつ

こちらの条件を満たす必要があります。

0

文字数と行数をカウントするプログラムを作成したのですが、実行すると、out.txtに行数は表示されるのですが、文字数が0となっていました。なぜこうなるのでしょうか?

とりあえず

  • 「行数だけ」を数えるプログラム
  • 「文字数だけ」を数えるプログラム

を個別に作ってみたらどうでしょうか.

おそらく,どちらも処理手順は ファイルを開く→(行数or文字数を)数える→ファイルを閉じる といったような流れになるでしょう.

そしたら,ものすごく単純に(脳死的に)この2つのプログラムを1つに統合することを考えれば,その統合結果は

まず ファイルを開く→行数を数える→ファイルを閉じる ということを行い,
次に ファイルを開く→文字数を数える→ファイルを閉じる ということを行う

といった形になるでしょう.
この形とあなたの現在のコードの形とでは何が違うでしょう?

なぜこうなるのでしょうか?

の理由は,そこらへんに潜んでいるのではないでしょうか.

投稿2021/12/08 14:58

fana

総合スコア11656

バッドをするには、ログインかつ

こちらの条件を満たす必要があります。

0

ベストアンサー

実行すると、out.txtに行数は表示されるのですが、文字数が0となっていました...

当たり前です。言うのが恥ずかしいほど当たり前です。

今回の場合、

[依頼] なあ、頼みがある。この台本にある文章の行数と文字数をカウントして教えてくれ。

的なものを先輩なり、同級生なりにお願いされたとします。質問者さんはどのようにしますか?
たとえば台本が羅生門とか。

私なら、ホワイトボードかなんかに「行数」と「文字数」をそれぞれ記録しておく。

羅生門の場合、ここをサンプルとして、PCで開いたと仮定すると、

まず一行目。「ある日の暮方の事である。一人の下人が、羅生門の下で雨やみを待っていた。」の行。これを読む。一行目なので 行数 = 1 とする。

この行は約35文字ですね。なので 文字数 = 35 と暫定的に取っておく。

行数 = 1 文字数 = 35

で、二行目も読み込む。「広い門の下には、この男のほかに誰もいない。ただ、所々丹塗にぬりの剥はげた、大きな円柱まるばしらに、蟋蟀きりぎりすが一匹とまっている。羅生門が、朱雀大路すざくおおじにある以上は、この男のほか」も同様に文字数をカウントする。
面倒なのでカウントしませんが、仮に64文字あるとして、現在記録されている文字数は 35。この35に64を加える。35 + 64 = 99文字。なので 文字数の記録を 35 から 99に書き換える。

行数は現在二行目なので1から2に書き換える。よって、

行数 = 2 文字数 = 99

のようになります。これを三行目、四行目…と繰り返し、EOF(ファイルの終端)になるまで繰り返す。

そうすれば最終的に行数と文字数がカウントできるはずです。

これを実装すればいいだけです。

で、N行目を読み込む…的なやつは一行レベルで読み込む関数かなんかで読み込む。そうするとchar型配列に文字列が格納されるはずです。
そうすれば文字数はそのchar型配列を対象にして計算すればいいはずです。(ただし日本語のように2バイト以上で構成されているような文字だと注意が必要。今回は問題なさそうですが)

記録のやつは変数とかでできそうですね。

次に『デバッグをしましょう』。

厳密なデバッグではないですが、基本的な考え方を書いておきます。

コードを読みましょう。コードを読むコツは『一行レベルで、何をしているかを考えながら読む』です。

C

1#include<stdio.h> 2int main() 3{ 4 // 変数等を宣言 5 FILE *fp; 6 int line = 0; 7 int word = 0; 8 char str[2048]; 9 int c; 10 11 // ファイルを読み込みモードで開く 12 fp = fopen("list.txt","r"); 13 // ファイルが開けなかったら 14 if( fp == NULL) 15 { 16 // 「開けなかった」系を表示 17 printf("Cannot open file¥n"); 18 // そのまま終了 19 return 1; 20 } 21 22 // 「これ以上読み込めない」か「エラーになるまで」ファイルを読み込み配列strに入れる(及びループ 23 while( fgets(str, 2048, fp) != NULL ) 24 { 25 // (読み込めたら)変数lineの値をインクリメント(+1する) 26 line ++; 27 } 28 // EOFになるまでファイルを読み込んで一文字分取り出す 29 while(( c = fgetc(fp)) != EOF ) 30 { 31 // (読み込めたら)変数wordをインクリメント(+1する) 32 word ++; 33 } 34 // ファイルを閉じる 35 fclose(fp); 36 37 // ファイルを書き込みモードで開く 38 fp = fopen("out.txt", "w"); 39 40 // ファイルが開けなかったら 41 if( fp == NULL) 42 { 43 // 「ファイルが開けなかった」系を表示 44 printf("Cannot open file¥n"); 45 // そのまま終了 46 return 1; 47 } 48 49 // ファイルに行数と文字数を書き込む 50 fprintf( fp, "%d\n", line); 51 fprintf( fp, "%d", word); 52 // ファイルを閉じる 53 fclose( fp ); 54 // 関数から抜ける(= 終了) 55 return 0; 56}

これを疑似コードとして抜き出してみる。

[疑似コード1] 0. 変数宣言 1. ファイルを読み込みモードで開く 2. ファイルが開けなかったら 2.1. 開けなかった」系を表示し、 2.2. そのまま終了 3. 「これ以上読み込めない」か「エラーになるまで」ファイルを読み込み配列strに入れる(及びループ) 3.1. (読み込めたら)変数lineの値をインクリメント(+1する) 4. EOFになるまでファイルを読み込んで一文字分取り出す 4.1. (読み込めたら)変数wordをインクリメント(+1する) 5. ファイルを閉じる 6. ファイルを書き込みモードで開く 7. ファイルが開けなかったら ...

のようになるはずです。これを現実世界でシミュレーションしてみてください。質問にあるlist.txtとかを使って実際に手作業でやってみてください。数学の手順なり料理のレシピとしてなり。

実際に値を入れて計算してみるとか

そうすると不自然なことに気づきます。(3)で『「これ以上読み込めない」か「エラーになるまで」ファイルを読み込み配列strに入れる(及びループ』とありますが、これは言い換えると『何かしらのバグで読めなかった』か『最後まで読みこんだのでこれ以上読み込めない』ってことです。
ということは、この時点で最終行まで読み込んでいるはずです。

よって、(4)につく頃には『最終行』の場所、つまりEOFになっているはずなので、(4)では常にEOFになる。

if( EOF != EOF )ということになり、EOF≠EOFなので満たしませんね。よって処理されずに(5)へ。

ということで、常に文字数が0になるのです。

考えてみれば当たり前ですね。

[追記0] ヒント: fgets - C言語関数辞典

投稿2021/12/08 08:16

編集2021/12/08 08:21
BeatStar

総合スコア4958

バッドをするには、ログインかつ

こちらの条件を満たす必要があります。

guest

0

ファイルから一行読みだす fgets(str, 2048, fp) を何度も(読めなくなるまで)繰り返し、
何回読んだか(繰り返し回数)を勘定すれば行数が得られます。

が、あなたのコードには
「fgets(str, 2048, fp) を何度も繰り返し」ている個所が見当たりません。

投稿2021/12/08 06:40

episteme

総合スコア16614

バッドをするには、ログインかつ

こちらの条件を満たす必要があります。

0

数字が表示されるコードではありません
どういうふうに表示させたいんでしょうか

投稿2021/12/05 15:02

y_waiwai

総合スコア87774

バッドをするには、ログインかつ

こちらの条件を満たす必要があります。

あなたの回答

tips

太字

斜体

打ち消し線

見出し

引用テキストの挿入

コードの挿入

リンクの挿入

リストの挿入

番号リストの挿入

表の挿入

水平線の挿入

プレビュー

15分調べてもわからないことは
teratailで質問しよう!

ただいまの回答率
85.48%

質問をまとめることで
思考を整理して素早く解決

テンプレート機能で
簡単に質問をまとめる

質問する

関連した質問