電子書籍の厳選無料作品が豊富!

練習問題 5-20
列数を示す数値を入力し、'a'~'z'の文字を指定された列数に従って表示するプログラムを作成しなさい。
 以下のプログラムを解析中で、まだ素人で基本的な質問ですがご了承ください。

1) int col; /*
2) char i;/*文字列関数*/

3) scanf( "%d", &col );
/*英数文字の行に並ぶアルファベットの個数を1~26までの任意の数字を一件入力する。*/

4) for( i = 0 ; i < 26 ; i++ ){ /*アルファベットは26個はa b c・・・の順番でループする命令*/
5) if( i > 0 && ( i % col ) == 0 )/*アルファベットのループ範囲はa~です。アルファベット26文字÷3)で入力した数の余りが0・・・?
6) printf( "\n" ); /*結果がでたら改行する。*/

7) printf( "%c", 'a' + i ); /* 現在解析中*/
8) }
-----------------------------------------------------------------
 以上ですが、 
5)の==0で、このプログラムでの役割は何ですか?
 よろしくお願いいたします。

A 回答 (9件)

他の部分はさておき、質問に関して。



if(i>0 && (i%col)==0)
これだけを取り出すと見えにくいものがありますから、
for(i=0;i<26;i++){
if(i>0 && (i%col)==0)
の二つをセットで説明します。


/* ループを開始
for(i=0;i<26;i++){
/* ループ中にiが0以上で、かつ入力した数値と同じになったら*/
/*つまりループをcol回繰り返したら*/
if(i>0 && (i%col)==0)

ということです。つまりiは0から順次1づつ増加しているとき、
その間に、増加中のiと入力したcolの値の割り算の余りが0、
すなわち同じになったら、・・という意味ですが、言い換えると、
iは小さいほうから増加しますから、colが1から26までの数字なら
(i%col)==0という演算に当てはまるiが存在する、ということに
なります。それに当てはまる値にiが到達したとき・・・、という
のが上記二つの式の意味です。

このような手法は他の言語でもたまに見かけます。
たまたま見かけたものに以下のものがあります。
以下の一番下のところ。
http://office.microsoft.com/ja-jp/access-help/HA …
If I Mod 1000 = 0 Then
ModとはC言語の%と同じです。ただ、言語によって微妙な
違いはありますが。
http://en.wikipedia.org/wiki/Modulo_operation

少し蛇足がつきましたが以上です。
    • good
    • 0
この回答へのお礼

御回答ありがとうございました。
 御回答の内容から
増加中のiと入力したcolの値の割り算の余りが0、
すなわち同じになったら→
それに当てはまる値にiが到達したとき・・・
以上ですが、理解度は完ぺきでは御座いませんが、
なんとなくわかるような気がします。
勉強することにより理解を深めたいと思います。

お礼日時:2011/08/28 17:27

No.1 です。

ひとつ訂正。

> 5) if( i > 0 && ( i % col ) == 0 )/*アルファベットのループ範囲はa~です。アルファベット26文字÷入力した数の余りが0・・・?

であれば、「入力した数の余り」云々は、間違ってはないです。
    • good
    • 0

No.1 です。



> ご指摘していただいた通り、3ではなくて、「入力した数」に変更します。

大切なのは、単に「変更する」ことではなくて、

なぜ、3と書いたのか(その時に、自分はどう思っていたのか)

です。
それを無視して、いわれたから直すというのを繰り返すと、将来困ることになります。
ついでにいえば、
> 入力した数の余りが0・・・?
も日本語として間違いですね。

いずれにしろ、コメントを直すのは全くどうでも良いことで、このプログラムの流れを「実際に」「自分で」追いかけて何が起こっているかを確認することです。
これができない(しない)ようなら、プログラミングはあきらめたほうがいいです。
    • good
    • 0

一応 C なので 1点突っ込ませてもらう>#4.



「int で宣言した col, char で宣言した i を平気で演算している。」ということを問題視しておきながら i = (int)(c - 'a') +1; などと平気で書くのは片手落ちというものではなかろうか.
    • good
    • 0

No5に少し追加しておきます。



言い換えると、
iは小さいほうから増加しますから、colが1から26までの数字なら
(i%col)==0という演算に当てはまるiが存在する、ということに
なります。それに当てはまる値にiが到達したとき・・・、という
のが上記二つの式の意味です。

という説明をしていますから、

>アルファベット26文字÷3)で入力した数の余りが0・・・?

ではなく、たとえば3と入力したら、iが0から26に変化する
する間に入力した3に(i%3)==0の条件に合う値にiが到達したら・・・、
ということになります。したがって、そのiの値は3ですから、

/*つまりループをcol回繰り返したら*/

というコメントのようになります。
    • good
    • 0

まず、どんな参考書を見ているのかはわかりませんが、私から言わせていただければ


その参考書は「捨てたほうが良い」です。
C言語は型のチェックに疎く、ライブラリは実装系に依存する、式の優先順位は
それなりに決められているがわかりやすくすべき、という考えが私にはあります。

具体的にこのソースが初心者向けでない理由をあげます。

1. 0や負の数値が入力された時にどうなるか分からない。

2. scanf を使用している。
scanf は一見便利に見えるが、安全性に問題がおおくバグの温床になりやすい。
デバックもしにくい。実践で使われることもない。
このサンプルコードも数値を入力せずにエンターキーのみや文字列を入力したときの
動作がどうなるか全く不明。
scanf は初心者でも使用しないことを勧めます。

3. if の条件式がわかりづらい。
カッコがなく、演算子の優先順位から動くことはわかっても、極力わかりやすく
書くべき。比較なのか演算結果なのかわかり易くすること。
でないと、10分前に書いた式の意味がわからなくなります。
初心者に見せるのならばなおさら。
しかしなんで、0より大きい条件が入っているのでしょうか?

4. int で宣言した col, char で宣言した i を平気で演算している。
C言語は型宣言を行う言語なので、型は常に意識して式に書かないとバグが発生する。
無論、コンパイラがきちんと型変換を行いますが、C言語を書くならば、
意識するようなクセ付けをしなければならない。
初心者には特に重要です。

他にも、i はフツー int で、char は c で宣言するだろ(だから i の型変換を忘れて
いるんじゃないの?)、最後に改行入れないの?
何を学ばせるのを意図しているのか、回答のリストから全く読み取れない。
というのもあります。


for 分の中を以下のように書き換えると、少し意味がわかり易くなるはずです。

for (i=0; i<26; i++){
printf("%c", 'a'+i);
if ( (int)(i+1) % col ==0 ) printf("\n");
}

なお、for 文のループは a,b,c の順番ではなく、このままだと iが 0 から 25 までの変化する
26回のループです。

きちんと書くなら以下のよう。
01:#include <stdio.h>
02:#include <stdlib.h>
03:
04:int main(int argc, char *argv[])
05:{
06: int i, col;
07: char c;
08: char buf[1024];
09:
10: if (fgets(buf, 1024, stdin) == NULL){
11: fprintf(stderr, "数値の入力でエラーが発生しました\n");
12: return 1;
13: }
14:
15: col = atoi(buf);
16: if ((col <=0) || (col > 26)) {
17: fprintf(stderr, "数値の入力にミスがあります %s\n1から26までの整数値を入力してください\n",buf);
18: return 1;
19: }
20:
21: for (c='a'; c<='z'; c++) {
22: printf("%c",c);
23: i = (int)(c - 'a') +1;
24: /* i は a ならば 1, b ならば 2 が代入されます */
25: if ((i % col) ==0) printf("\n");
26: }
27: if (i % col !=0) printf("\n");
28: return 0;
29:}

scanf の処理が、10~19 行と膨大になりました。この部分は今の段階で必ずしも
理解をしなくてはいけない範疇ではないです。
しかし、このような処理を常に気を付けないといけないのが C という言語です。

私の独断では、scanf みたいなことを教えずに、こういったエラー処理を
まず初めに習うべきです。

21行目の for の書き方は異論があるかもしれません。
しかし課題の a~z の文字という文章を素直にfor文にしました。
これが、c が 'a' から 'z' までループする for文です。

また、問題文から読むと、普通は
1. 文字を出力 (22行目)
2. 改行が必要ならば改行を出力 (23~25行目)
という手順を思いつくはずなので、素直にそのような順序にしました。

23行目ではきちんと型を適切に変換しています。
25行目のif文の条件式は、24行目のコメントと col の意味がわかれば、素直に解釈できるでしょう。

27行目は、私の独断でつけたものです。単なる蛇足。
27行目がある場合とない場合で、数値の入力を 1~26 までずらせばわかるでしょう。
27行目の '\n' を '*\n' などと書き換えればわかるかもでしれません。
    • good
    • 0
この回答へのお礼

素晴らしい御指摘と御回答ありがとうございます。
かなりの上級の方と見受けられます。
 この御回答を全て読みました。
まだ私には模範解答を全て理解するには”まだまだ”です。
 最初は教本をやっていましたが、行き詰まり、http://akabas.net/lib/CExercise.aspx?id=105の1. 関数の基本練習問題 1-1からやってきました。
 HPの無料版の問題集なので、内容は雑な仕上げかと!皆様がご指摘が多かったので
 分かりました。しかし、これを吉に「C言語問題集の市販版」があれば購入しようかと思います。 

お礼日時:2011/08/28 17:27

改行を入れる条件かと思いました


それなら入力した列数ごとに改行を入れています
(最初のi=0以外の余りが0のとき)
    • good
    • 0

5)の==0で、このプログラムでの役割は何ですか?


右の式(数値)と 左の式(数値)が同じかをチェックする際の構文(比較演算子)です
(ってことを聞いてるんじゃなかったらすいません)

演算子などで計算の優先順位があるとはいえ見にくいソースですね
括弧で明確に書いたほうが分かりやすいでしょう
その場合以下のようになります
if(( i > 0) && (( i % col ) == 0) )
    • good
    • 0

この程度のプログラムなら、1ぎょうずつ、何をやっているか、地道に追いかけましょう。


その時に、i の値はどうなっていて、どういう計算が行われているか。

ソースを見ながら、手作業で追いかけるのです。

> 7) printf( "%c", 'a' + i ); /* 現在解析中*/

にしても、「何か一文字表示している」というのはわかりますよね?
だったら、とりあえず、「a と表示」と思って、やってみたらいいです。

あと、

> 5) if( i > 0 && ( i % col ) == 0 )/*アルファベットのループ範囲はa~です。アルファベット26文字÷3)で

の、「3」という数字はどこから出てきましたか?
「入力した数」とは違うのですか?

まず、最初は i = 0, 次は i = 1, .... と地道に追いかけましょう。

ついでにいえば、

> 6) printf( "\n" ); /*結果がでたら改行する。*/

のコメントは間違いです。
「結果が出たら」の結果とは何でしょう?
もっと具体的に、どういう場合に改行するのか、それを理解しましょう。

この回答への補足

ご回答ありがとうございます。
 質問内容誤りがありました。
ご指摘していただいた通り、3ではなくて、「入力した数」に変更します。

「5) if( i > 0 && ( i % col ) == 0 )/*アルファベットのループ範囲はa~です。アルファベット26文字÷3)で入力した数の余りが0・・・?」の内容を
5) if( i > 0 && ( i % col ) == 0 )/*アルファベットのループ範囲はa~です。アルファベット26文字÷入力した数の余りが0・・・?
 に修正します。

補足日時:2011/08/28 06:43
    • good
    • 0

お探しのQ&Aが見つからない時は、教えて!gooで質問しましょう!