合計 昨日 今日

アンク「Cの絵本」からの質問です

[このトピックは解決済みです]

フォーラムルール
フォーラムルールはこちら  ※コードを貼り付ける場合は [code][/code] で囲って下さい。詳しくはこちら
Name: papaまる
[URL]
ぴよぴよ(661 ポイント)
Date: 2017年9月03日(日) 09:16
No: 1
(OFFLINE)

 アンク「Cの絵本」からの質問です

初めまして。
Cの猛者さまばかりのなか恐縮するばかりですが、おヒマな方がいらっしゃったら、私の愚かなる質問にお付き合いください。
現在、アンク著「Cの絵本」でC言語を勉強中であります。
この中の58ページ、「英文中の単語の数をかぞえる」サンプルプログラムの意味を読解できなくて苦戦しているのです。
以下コードです。
<code>
#include <stdio.h>
main()
{
char c = '¥0';
char prevletter;
int wordnum;
int word_in;

while(1)
{
 wordnum = 0;
 word_in = 1;
 prevletter ='¥0';
 printf("文字列を入力してください:");
 while(1)
 {
  c = getchar();
  if(c == '¥n')
  {
    if(word_in)
      wordnum++;
    break;
  }
  prevletter = c;
  if(c ==' '||c =='.')
   {
    if(word_in)
    {
     wordnum++;
     word_in = 0;
    }
  }
  else
     word_in =1;
 }
 if(prevletter == '¥0')
    break;
 printf("ワード数:%d¥n",wordnum);
}
}
</code>

実行すると、
文字列を入力してください:I love cat.
ワード数:3
となります。

わからない部分であります。
1 冒頭のchar c = '¥0';は、宣言したら何かしら値を入力する必要があるのでヌル文字を入れているのでしょうか?
2 char prevletter;、int wordnum;、 int word_in;はwhile(1)の中で、値がそれぞれ入力されています。char c = '¥0';だけ、なぜ冒頭なのでしょうか?
3 処理の流れについて、いまいち分かっていません。以下は自分なりの解釈です。
  この処理は、スペースとピリオドで単語数を判断していると思います。
  例えば、I love cat.の末尾の方のtから入力すると、
  ・ getchar()にtが入力され、cに代入
  ・ c == '¥n'とはならない。そのため条件式はスルー
  ・ prevletterにcが代入
  ・ cの中身はスペースでもピリオドでもないtである。よってこの条件式はスルー
  ・ elseでword_in = 1となり、内側のwhile(1)頭にループ
  ・ 次にcat.の部分の最後のピリオドが、getchar()から入力され、cに代入
  ・ c == '¥n'とはならない。この条件式はスルー
  ・ prevletterにcが代入される
  ・ cの中身はピリオドで、条件式に入る
  ・ elseのところでword_in = 1としていたので、条件式中のifも真として実行
  ・ wordnum++で、それまでの2から1を加え、3となる。word_in = 0に変更。また内側のwhile(1)頭にループ
  ・ 次にリターンキーが入力され、cに代入される
  ・ c == '¥n'なので、条件式に入る
  ・ word_inは前回0になっているので、条件式中のifはスルー。breakが実行され、内側while(1)のループを抜ける
  ・ if(prevletter == '¥0')にたどり着くが、前回のprevletterは改行で¥0ではないので、これをスルー
  ・ printfが実行され、最終的なwordnumとして3が表示される。その後、外側のwhile(1)頭へとループ
  ・ 以降何も入力がなく、if(prevletter == '¥0')と判断され、外側whileのループから抜ける
  一番、最後の何も入力がない状態をどうやって判断しているのだろう、と疑問に思います。I love cat.改行と打ち込み、数秒間、キーボードの打ち込みがないならば、入力なしと判断して、外側のwhile(1)を抜けるのでしょうか??

 無知ゆえ、質問さえも散文になっている恐れがあります。
 1ページを1週間経っても抜け出せない状況でありますので、どうかアドバイスの方よろしくお願いいたします。
最後に編集したユーザー papaまる [ 2017年9月03日(日) 17:10 ], 累計 2 回

Name: みけCAT
[URL]
伝説なるハッカー(675,552 ポイント)
Date: 2017年9月03日(日) 09:45
No: 2
(OFFLINE)

 Re: アンク「Cの絵本」からの質問です

papaまる さんが書きました:1 冒頭のchar c = '¥0';は、宣言したら何かしら変数を入力する必要があるのでヌル文字を入れているのでしょうか?

普通の処理系では、宣言したら値を入れないといけないという決まりは無いはずです。 (「変数を入力する」というのは意味がよくわかりません)
このプログラムではcの値を使用する前にかならずc = getchar();を通るので、ここでの初期化の必要は無いでしょう。

papaまる さんが書きました:2 char prevletter;、int wordnum;、 int word_in;はwhile(1)の中で、変数がそれぞれ入力されています。char c = '¥0';だけ、なぜ冒頭なのでしょうか?

確かに不自然ですね。
cだけ内側のwhileループで値を代入されているのと何か関係があるかもしれない気がします。
気になるなら筆者に聞いたほうがいいかもしれません。

papaまる さんが書きました:この処理は、スペースとコロンで単語数を判断していると思います。
papaまる さんが書きました:  ・ cの中身はスペースでもコロンでもないtである。よってこの条件式はスルー
papaまる さんが書きました:  ・ 次にcat.の部分の最後のコロンが、getchar()から入力され、cに代入
papaまる さんが書きました:  ・ cの中身はコロンで、条件式に入る

コロンではなくピリオドですね。

papaまる さんが書きました:一番、最後の何も入力がない状態をどうやって判断しているのだろう、と疑問に思います。I love cat.改行と打ち込み、数秒間、キーボードの打ち込みがないならば、入力なしと判断して、外側のwhile(1)を抜けるのでしょうか??

空行(入力の最初または改行文字の直後に改行文字)を入力すると、内側のwhileの前に初期化したprevletter ='¥0' (複数文字の文字定数の値は環境依存。\0の誤り?) のまま内側のwhileの後に行くので、
if文の条件式が真になり、break;が実行されて外側のwhileループから抜けるはずです。
キーボードの打ち込みがない場合は、(標準入力がキーボードに繋がっている、かつシグナルなどで止められなければ)いつまでも入力を待っているはずです。
複雑な問題?マシンの性能を上げてOpenMPで殴ればいい!(死亡フラグ)

Name: papaまる
[URL]
ぴよぴよ(661 ポイント)
Date: 2017年9月03日(日) 17:31
No: 3
(OFFLINE)

 Re: アンク「Cの絵本」からの質問です

[解決!]

伝説なるハッカー様
ご返信大変ありがとうございました。
ご指摘を受けた
 ・ 変数と値の書き間違え
 ・ コロンとピリオドの書き間違え
を訂正いたしました。
実際にプログラムを実行させてみると、確かに冒頭の
char c = '/0';
をchar cとして、外側のwhile(1)内にc = '/0';と書いたところで実行結果は変わりませんし、
そもそもc = '/0';を書かなくても、きちんと実行できました。
それと、ピリオドに続き、改行/nを入力した場合は、確かに
 ・ word_in = 0となり、breakして内側whileのループを抜ける
 ・ その後、printfが実行され、外側のwhile(1)の頭にループ
 ・ prevletter = '/0';となり、外側while(1)の最後のifが実行(break)され、ループを脱する
という流れで無事処理が終わることを確認しました。
1週間悩むと、頭に刻まれますね。ありがとうございました。


Return to C言語何でも質問掲示板

オンラインデータ

このフォーラムを閲覧中のユーザー: なし & ゲスト[17人]