- 本日の作業内容
- 前回の小テストについて
前回は初めての小テストだったのでしかたないところもありますが,コンパイルエラーがたくさん出てきました.提出しないように,強く言ったのですが,1年生から結構な数が出てきました.残念です.コンパイルエラーになる答案は即刻削除しますので,提出しても良いことは何もありませんので,以後は出さないでください.
コンパイルエラー: b1605 b1614 b1617 b1638 b1653 b1655 b1656 b1657
なお,以前にも説明したとおり,この授業の課題では scanf は扱いません.自動処理できないからというのが理由なんですが,今回,以下の学生さんから scanf を含むプログラムが出てきました.これも削除しないと,自動での一斉実行ができなくなりますので,削除しました.採点の対象外となりますので,以後は注意してください.
scanf を含む解答: b1630 b1665
以下に問題のあるプログラムの例をいくつか示しますので,参考にしてください.
int m = rand() % 20 + 50;
|
まずは,ありがちな間違いから,ですが,上の例は20が間違っています.50〜70までは数字が21個あります.
int num = rand () % 71 + 50;
|
上の間違いは意味不明です.わかりません?(@ o @)?
int dice = rand() % 21 + 58 ;
|
これもわかりません.
上の例はコンパイルエラーになった答案にいくつか見られたものです.これも???です.
授業中にも説明しましたが,上のように3つの項が絡むことは,ほとんど全てのプログラミング言語でできません.よく覚えておいてください.この場合は,左の 58 <= a のみが考慮されるので,期待した結果と違う結果が出てきます.
全く意味がわかりません.何をどうしたいのか?とりあえず,「式」の中にコンマは入れられませんので,それくらいは覚えておきましょう.
if(a>64){
printf("Corresponding character: %c\n", a);
printf("It's a letter.\n");
}
|
この例は間違っているわけでは無いのですが,ひとつ目の printf 文は,条件分岐にかかわらず必ず必要な出力なので,if の中に入れない方がベターです.
if(a >= 65 && a <= 90 || a <= 97 && a>= 122)
printf("letter.\n\n");
|
これも間違っているわけではありませんが,発生させる乱数の範囲が50〜70なのに,なんでそんな大きな数まで対象とするのかが??です.
if(num1<58)
printf("It's a numeral.\n");
else if(num1<65)
printf("It's a symbol.\n");
else if(num1<71)
printf("It's a letter.\n");
|
こちらも授業中にも説明しましたが,必ずどれかの出力を行うので,最後の if は不要です.else だけで良いですし,そうするのが良いプログラムです.
if(a <= 57)
printf("It's a numeral.");
if(a <= 64)
printf("It's a symbol.");
if(a <= 70)
printf("It's a letter.");
|
こちらも同様で,どれかの出力を必ず行うので,else を使ってください.
if(a<=57){
printf("It's a numeral\n\n");
if(a>=65)
printf("It's a letter\n\n");
else
printf("It's a symbol.\n\n");
}
|
最初の if に中括弧 { } がついているので,その if に合致しない条件の時の処理がなくなっています.また,英文の最後にはピリオドが必要です.
if(a < 58)
printf("It's a numeral");
|
これもピリオドが無い例なのですが,結構な数の人が間違っていたので,注意してください.英語の文章はピリオドで終わります.
printf("Corresponding character: %d%d%d%d\n", a);
if(a)
printf("It's a symbol.\n");
else if(a)
printf("It's a numeral.\n");
else(a);
printf("It's a letter.\n");
|
もう何がなんやら?です.
printf("Corresponding character: %c\n");
|
二重引用符 " " で囲まれた文字列中に %c があるのに,最後の変数を指定していない例です.前回までは採点対象外としましたが,今後は減点とします.注意してください.
printf("Corresponding character: ?\n");
|
上のような記述がかなり多くの解答に見られました.特に,再履修クラスの方に多かったのですが,問題に例示してある乱数63に相当する文字コードが ? なわけで,ここは乱数に対応する文字を表示させるところです.correspond は相当する,対応する,です.
printf("It's a manual.\n\n");
|
「数字」は英語で numeral と言いますが?
以下はインデント(字下げ)の問題です.今回もたくさんありました.相変わらずスペースで1文字ずつ字下げをしている人も見られました.そういう人のプログラムは行頭がバラバラの位置に来るので,非常に見苦しい物になりますので,早くTABを使うことに慣れてください.
if(m<58)
printf("It's a numeral.\n\n");
else if(64<m)
printf("It's a letter.\n\n");
else
printf("It's a symbol.\n\n");
|
プログラムの中身は良かったのに,インデントが残念な例.if 文の中がTAB2個になっちゃってます.
printf("Corresponding character:%2c\n",m);
if(m<=57)
printf("It's a numeral.\n\n");
else if(m<=64)
printf("It's a symbol.\n\n");
else
printf("It's a letter.\n\n");
printf("--------------------------\n");
|
こちらもプログラムの中身は良いのに,インデントで減点されました.if 文はインデントする必要が無いのに,下がっています.
最後にこのプログラムの肝を紹介します.やらないといけないことは下図のような文字コードの範囲を if 文を使って処理することでした.すなわち,50-57が数字,58-64が記号で,65-70が文字です.そうすると,数学的な表現に慣れている人はすぐに不等号2つで範囲を指定したくなります.間違い例として紹介したものですね.
ところが,if 文には else という便利な相方がいますので,解答例のように,最初に
とすると,もう57以下の数は else の方には来ないので,次に,
とするだけで記号の範囲になるわけです.最後は,もう,アルファベットしか残っていませんので,else だけで終わりです.このように数値の大小関係だけで選択できる場合には,両側を不等号で調べる必要が無いことを覚えておきましょう.
- 宿題について
残念ながら今回も以下の2名の採点対象外となる解答提出がありました.気をつけましょう.
コンパイルエラー: b1677
解答用紙不使用: b1629
なお,条件分岐という制御構造が出てきたためにインデント(字下げ)が2段になることがあります.しかし,1年生の方ではまだ慣れていないためか,インデントの不備が大量に見られました.以下に該当者を揚げておきますので,今後は正しくインデントを行うように気をつけてください.どこが悪いのかがわからない場合には,遠慮無く質問してください.毎回の宿題で2点減点は,将来的に大きく影響しますので,今のうちに直しましょう.
インデントの不備がある解答: b1601 b1604 b1605 b1606 b1609 b1612 b1627 b1628 b1635 b1636 b1637 b1638 b1641 b1648 b1650 b1653 b1658 b1659 b1661 b1670 b1672 b1679 b1680
以下は例によって問題のある答案の例です.参考にしてください.
if(num%10!=0)
printf("Reversed number: %d%d\n\n",num%10,num/10);
if(num%10==0){
int num1 = rand() % 9 + 1 ;
printf("Reversed number: %d%d\n\n",num1,num/10);
}
|
どちらかを必ず表示させるので,if 文の羅列ではなく,else を使います.
乱数については,説明もしてありますし,Webテキストには具体的な例も挙げてあるので,なぜ,間違うのか?
a = rand() % 90 + 10;
b = a % 10;
c = a - b;
d = b * 10;
e = c / 10;
f = d + e;
|
変数を無駄に置いた例です.わかりづらいものになりますし,本格的にプログラムを作成するとメモリを消費して重いものになる可能性があります.いらない変数は定義しないようにしましょう.
int n = rand() % 9 + 1;
int a = 10*n;
int b = rand() % 10;
int f = rand() % 9 + 1;
int c = a + b;
int tmp;
int d = 10*b;
int e = n + d;
int g = 10*f;
int h = g + n;
|
同じく,こちらも無駄な変数をたくさん用意した例です.
if(b != 0)
printf("Reversed number:%d%d\n",b,d);
|
「入れ替えた数」を作っていないですね.これでは入れ替えて表示しただけです.過年度生に多く見られました.ちょびっと減点です.
if(num%10 == 0){
printf("Random number: %d\n",num);
printf("Another number: %d%d\n",bb,num/10);
}
else{
printf("Random number: %d\n",num);
printf("Reversed number: %d%d\n\n",tt,p);
}
|
if 文の中の1つ目の printf は if の条件式の真偽にかかわらず実行するので,if 文の中に入れる意味は無いですね.
if(a%10==0)
printf("Another number:");
if(a%10==0)
printf("%d",b);
if(a%10!=0)
printf("Reversed number:");
if(a%10!=0)
printf("%d",c);
printf("%d\n",d);
|
else を使っていないところも問題ですが,if 文をそれぞれ2つに分ける意味がありません.
さて,以下のものはインデント(字下げ)の不適切な例です.注意してください.
if(a%10!=0)
printf("Reversed number:%d\n",a%10*10 + a/10);
else
printf("Another number:%d\n",b*10 + a/10);
|
if 文の中の式はブロックの中ですので,下がらなければなりません.教科書をよく見てください.
if(a%10==0){
b=(rand()% 9 + 1 )*10+a/10;
|
全体のインデントと if 文の中のインデントの幅が違います.
if(a%10==0){
printf("Another number: %d", b);
printf("%d\n\n", a/10);
|
2つめの printf がなぜ下がるのでしょうか?
int a = rand() % 90 + 10;
printf("My student number; s164012\n\n");
if(a%10==0)
|
if 自体は下がりません.
if(num % 10 != 0)
printf("Reversed number:%d\n",(num % 10) * 10 + (num / 10));
|
if 文の式がTAB2個分下がってしまっています.
printf("-------------------------------- \n");
return(0);
}
|
相変わらず見られた,最後の return がインデントされていないものです.
- 前回の復習
if 文の基本について学習しました.条
件式に関する重要な概念に真偽の判定がありますので,以下に説明しておきます.
教科書のp.24にあるように if 文の基本は図1のようになります.
図1 if 文の構成
ここで,式の値が「真」か「偽」かによって処理の流れが変わるのが if
文の基本動作ですが,式の値が真もしくは偽とはどういう意味なのか
について考えましょう.
教科書では関係演算子や等価演算子のような「比較演算子」の使用が最初から行
われていますので,括弧の中には比較する式が入るものと思いがちですが,そこ
には値さえあれば,何でも動作します.ですので,等価演算子 == の
代わりに間違って代入記号の = を使用してもエラーなく動作します.
(処理は間違ってしまいますが.)
以下のプログラムで,値の真と偽について考えてみましょう.
#include <stdio.h>
#include <stdlib.h>
#include <time.h>
main()
{
srand((unsigned) time(NULL));
int num = rand() % 3 - 1;
printf("%d\n", num);
if(num)
printf("True\n");
return(0);
}
|
- if ~ else文
もし〜ならば,という条件式にさらに「そうでないならば」という
else の処理を追加したプログラムを前回から学習しました.本日も,実習課題に沿って学習していきましょう.
else を使用するのは重要です.発生した状態に対して,必ず何かの処理を行なう必要がある場合には必ず最後に else を入れるようにしましょう.処理の洩れを防止するのに役立ちます.一方,必ず何かの処理をする訳では無いときには,else を入れないようにしましょう.
if(hoge)
hogehoge;
else
hogehogehoge;
|
上のようであれば,hogehoge か hogehogehoge のどちらかが必ず実行されます.一方,
if(hoge)
hogehoge;
else if(hege)
hogehogehoge;
|
であれば,hogehoge も hogehogehoge も実行されないこともあります.
注意
インデント(字下げ)について毎回注意していますが,if 文においても
インデントは論理構造を把握するのに重要です.ところが,教科書のインデント
の例はあまり良くないので,以下のどちらかのように揃えるようにしましょう.きっと,こ
の方が分かりやすいと思います.
if( hoge ){
hogehoge ;
hogehogehoge ;
}
if( hege )
hegehege ;
else
hegehegehege ;
if( huge )
hugehuge ;
else if( hugehugehuge)
hugehugehugehuge ;
else if( hage ){
hagehage ;
hagehagehage ;
}
else
hige ;
|
if( hoge ){
hogehoge ;
hogehogehoge ;
}
if( hege )
hegehege ;
else
hegehegehege ;
if( huge )
hugehuge ;
else if( hugehugehuge)
hugehugehugehuge ;
else if( hage ){
hagehage ;
hagehagehage ;
}
else
hige ;
|
- 論理演算子
複数の条件を if 文で処理したい時に,教科書p.30の表3.3にある論理演算子を使用します.小テストや実習の時に多くの人が間違えたような,以下のような処理がありました.
if( 1 < a < 5 )
if( a == b == c )
|
間違った記述.やっちゃだめ!
上のようなやり方はプログラミング言語には用意されていません.そこで,論理積の記号 && を使用して以下のように書くと正しいものになります.
論理演算子の結合の強さは四則演算や比較演算子よりも弱いので,式のように他の演算子を含む条件を記述する場合でも,特別にカッコを追加する必要はありません.
if( a + b > 10 && a * b < 100 )
|
- 実習
実習の演習問題はこちらです.
- 次回の予習範囲
教科書のp.35まで予習をしてきてください.
- 宿題
授業の終わりに宿題の案内をします.ただ
し,問題を見ることができるのは8日以降です.