joho1-2017の日記

joho1-2017の日記

情報処理実習1の解説ブログです.皆さんが課題を解く時の助けになれば幸いです.

データ型

第6回の6組の授業では,データ型について勉強しました.

我々人間と,コンピュータでは扱えるデータには違いがあり,これを理解せずプログラムすると,意図しないエラーが起こることもあります.
そして,これは経験上ですが,この手のエラーはコンパイルは通ってしまい,実行時に生じることが多々あり,デバッグが非常に厄介だったりします.今回の授業の内容は全て覚えるのはなかなか難しいですが,今後PCを使おうと思ってる人には是非知っていて欲しい内容です.

ビット(bit)とバイト(Byte)

コンピュータの記憶容量を数える際に使う単位で,ビット(bit)はその最小単位になります.そしてコンピュータは0と1の2値しか記憶しないので,1bitで表現できる数は,0か1になります.また,このbitを8つ集めたものをバイト(Byte)になります.

8bit = 1Byte
進数

我々が主に扱う0~9までの数字で数を表現するものを,「10進数」と呼びます.これに対し,コンピュータは0と1のみの「2進数」で記憶を行います.そして,あまり馴染みがないかもしれませんが,0~Fまでの「16進数」というものもあります.コンピュータの2進数を表記すると人間にはとても理解しにくいので,わかりやすい表現として16進数が扱われます.

変数

これまでの講義で扱ってきた変数も,割り当てられた要領だけメモリが確保されています.表は講義ページを参照してください.この事から,割り当てられた変数で表現できる以上の数を代入しても,正しい数は得られないため,エラーが起こります.しばしばエラーという形ではなく,正しくない数を返してくる事もあります.この場合は非常に厄介ですね...こんな事が起こらないようにするためにも,各変数に割り当てられたメモリのサイズ表は定期的に確認しておきましょう!

変数のスコープ,auto変数とstatic変数,グローバル変数は講義ページの通りです.長くプログラムを書く先輩としてアドバイスするならば,同一プログラム内に同名の変数があるのは,一部の例外(for文のカウンタ変数iなど)を除いて避けるべきです.例えそれがauto変数であっても,作った直後でない限り混乱しやすくなり,無駄にプログラムを読み返す時間を増やすことになるでしょう.

定数

変数と違って,値が変化しないものとして,定数がある.これらは講義ページにあるように,数値定数文字定数文字列定数と言うものがあります.ところで,この記事の最初の方で述べていますが,コンピュータは0か1しか記憶しません.なのに,文字を扱えるのはなぜでしょうか?
答えは,「文字を数で表現し,その数を記憶している」からです.そして,数と文字の対応を表にしているものがアスキーコード表なのです.この表は16進数で表現されていますが,これは1桁が4bit=

=16で表現されるため,16進数表記なのです.

型変換

(1)代入時の型変換
左辺と右辺の型が異なる場合,左辺の型に変換される.

int a;
double b = 3.14159265358;
a = b;         //これはint型に変換
実行結果:
3

(2)式中の変換
式中の型が異なる場合,制度の高い型に統一される.

精度高 double > float > long > int > char 精度低

(3)キャスト
型を一時的に強制変換できる方法もあります.

float x = 3.14159265358;
int y = (int)x;       //float型のxは一時的にint型に変換された!
独自の型作成

C言語では,ユーザ自身が独自に変数型を作成できる.これは後々プログラミングをとても楽かつ見やすくしてくれるものなので,是非覚えておいてもらいたい.書き方は講義ページを参照してください.

第6回の5組の授業では,配列について勉強しました.

学生の皆さんは,これまでのプログラミングで,何度も変数を宣言し,それらに値を代入するのは面倒だと思ったことはありませんか?
そして今後は,それではソースコードがとても長く,読み難くなる場合が出てきます.
こういった事を解決するものに,「配列」というものがあります.

1次元配列

配列とは変数のリストであり,1度で複数の変数を宣言できます(ただし,型が違う変数はそれぞれ宣言しなければならない).
1次元の配列は,

型 変数名[要素の個数];
 例: int days_of_month[12];

と宣言し,これにより,宣言した型の変数が要素の個数分生成されます(例だと,int型のday_of_monthという変数が12個生成された).
そして,これらの変数に値を代入したり,判定処理をするためにアクセスする時は,

month[0] = 31;

のように,変数名と何番目の要素にアクセスするのかを指定しなければいけません.注意すべき事として,

1.配列の宣言時に要素の個数がNならば,アクセスする時は0~(N-1)まで
//例  
int month[12];  //宣言が12個なら
month[0] = 1;
.
.
.
month[11]=12;  //アクセスは0~11まで
2.for文やwhile文などでまとめて値を代入する際,要素数以上の繰り返し処理をしてもコンパイルエラーは起きない
//例
int month[12];               //宣言は12個
for(int i=0; i<100; i++){  //要素数より多いループ回数!でもコンパイルは通ってしまう!
    month[i] = i+1;
}
3.まとめてのコピーは不可
int num1[12], num2[12];
num1 = num2;                 //これはできない!エラーになる.

1は宣言時とアクセス時で要素の扱う範囲が異なるように見えるので混乱しがちだが,アクセス時の[ ]内の数字は,最初の要素からのオフセットを表すので,1番目はオフセット0だし,今回の例の最期はオフセット11になるので,0~(N-1)となります.
2は実行して初めてミスに気付くとういう,かなり厄介なバグになるので,注意しましょう.
3は配列の特徴であり,C言語では対応していません.1つ1つに代入する事を意識しましょう.

配列とポインタの互換性は,ポインタを習っていない今解説しても混乱するだけなので,ここではしません.

多次元配列

実は1次元配列だけでなく,多次元配列も存在します.例えば2次元配列(3行5列)を作りたい場合,

int matrix[3][5];

と宣言する事で作成できます.
アクセスの場合,例えば1行目の3列目にアクセスしたい場合は,

matrix[0][2] = 12;

のように書きます.
三次元の時も,

int a[2][3][4];

のように,[ ]の数を増やす事で表せる.

 

以上で今回の講義のおさらいは終わりです.以下,各クラスの課題の考え方です. 

 

5組

1.キーボードから実数を10個入力し,全ての値を配列に格納し,そのなかの最大値,最小値を画面に表示せよ.

#include<stdio.h>

int main(void)
{
    const int N = 10;  /* 配列の要素数 */
    float data[N];     /* 実数10個分の配列 */
    
    .../* データ入力 */
    for(...)
        ...
    
    printf("最大値は %f \n", ... );
    printf("最小値は %f \n", ... );

    return 0;
}

この課題は練習問題2練習問題3を参考にすれば,簡単に解くことができると思います.
 ①実数型を用いること
 ②配列へのアクセス時は要素数番号は0~N-1であること
に注意しましょう.

2.キーボードから正の整数を10個入力し配列に格納し,そのなかから奇数の数をカウントして画面に表示せよ.
正でない整数が入力されたらエラーを表示して,正しい値が入力されるまで繰り返し再入力させよ.

実行例:
a[0]= 10
a[1]= -3
入力エラー! 正の整数を入力
a[1]= 0
入力エラー! 正の整数を入力
a[1]= 5
a[2]= 100
a[3]= 2
  .
  .
  .
a[9]= 10

奇数は 4 個ありました.

この課題のポイントは,
 ①入力された数が正の整数か判定
 ②奇数の判定
です.①はdo-while文で入力されるたびに判定すれば良いでしょう.もちろん他の方法でも構いません.②は2で割り切れるか判定すれば良いだけですね.

3.キーボードから 2 以上の整数を10個入力し,その中の素数の個数を数え表示するプログラムを作成せよ.

実行例:
a[0]= 10
a[1]= 1
入力エラー! 2以上の整数を入力
a[1]= 5
a[2]= 11
a[3]= 2
  .
  .
  .
a[9]= 10;

素数は 2, 5, 11 の 3 個ありました.

この課題のポイントは,
 ①入力された数が2以上の整数か判定
 ②素数の判定
①は2と同様にdo-while文で判定できますね.②に関してですが,素数とは,条件「1とその数自身以外の数では割り切れない数」を満たす数のことですね.と言うことは,入力された数nを1からnまで割っていき,余りが0になる数をカウントしていき,上述の条件を満たす時,素数であることを示す返り値を与えれば良いわけです.

<4.キーボードから10個の整数を配列に入力し,1.まず配列の全要素を画面に表示,2.次に大きい順に並べ替えて表示せよ.
ヒント(各自で調査せよ):ソーティング,アルゴリズム,単純ソート,挿入ソート,バブルソートヒープソートなど

a[0]= -2
a[1]= 1
a[2]= 11
a[3]= 2
  .
  .
  .
a[9]= 10;

並べ替え前:-2 1 11 2 ... 10
並べ替え後:11 10 ... 2 1 -2

この課題のポイントは,
 ①配列の並べ替え
です.様々なやり方があると思いますが,配列の要素番号の隣同士を比較して,要素番号が小さい方の中身の数が小さければ大きい方と入れ替える,という作業を要素数だけ繰り返せば,最終的にできた配列は大きい順に並び替わります.これには繰り返し処理のネストが必要になりますね.

5.整数型配列の各要素を全て絶対値に変換して,変換前後の配列の中身をそれぞれ表示せよ.

#include <stdio.h>

int main(void)
{
    const int N = 10;
    int a[N] = {3, -4, -9, 10, -5, 6, 2, 0, -9, 5};   /* 数値は例.値を書き換えても正しく動作すること. */

    ...

    return 0;
}
実行例: 変換前:3, -4, -9, 10, -5, 6, 2, 0, -9, 5
     変換後:3, 4, 9, 10, 5, 6, 2, 0, 9, 5

この課題のポイントは,
 ①整数を絶対値にする
です.C言語には絶対値を計算する関数というものがあります.詳しくは「C言語 絶対値」などでググるとでてきます.この時,いつものstdio.h以外にも他のヘッダーファイルをインクルードしないといけないことにも注意しましょう.
ただ,簡単な条件判定で解くことができるので,わざわざ使う必要はありません.

 

 

6組

1.QUIZ1,2,3 を参考にして,入力した文字が大文字であれば小文字に変換し, 小文字であれば大文字に変換するプログラム作成しなさい. また入力は半角文字のみとする. キー入力と表示以外は組み込み型の関数は使わずに実現して下さい.

実行例:
文字を入力して下さい: M
m
文字を入力して下さい: e
E
文字を入力して下さい: i
I
文字を入力して下さい: j
J
文字を入力して下さい: I
i

この課題のポイントは,
 ①大文字と小文字の認識
です.QUIZ1~3を参考にすればいいので,アスキーコード表を使うことは自明ですね.そしてアスキーコード表を見ると,同じアルファベットの大文字と小文字は下位4bitは同じですね.つまり,上位4bitに対して何かしらの条件処理をすれば,小文字->大文字,大文字->小文字の変換はできますね.

2.QUIZ4を参考にして,一桁の自然数(数値)を引数にとり,文字(数字)を返す関数 toascii() を作れ. 但し変換にprintfなどを用いてはならない.

char toascii(int number)
{
    // write your code down here.
}

int main(void)
{
    for(int i=0; i<10; i++){
        char c = toascii(i);
        printf("%c",c);
    }
    printf("¥n");
}

この課題のポイントは,
 ①数字から文字への変換
です.QUIZ4において,文字としての数字(0x30~0x39)を数値(0~9)に変換はできましたね.そして,その時に,関数atoi( )では,引数に対してどんな処理がされていますか?今回の問題はその逆をやればいいだけですね.

3.QUIZ5 を参考にして,2点の三次元座標A(x,y,z),B(p,q,r)を入力すると,内積を計算する関数 dot_product()と, 外積を計算する関数 cross_product() を作成せよ.

この課題のポイントは,
 ①独自の変数型作成
 ②内積外積計算

です.①はQUIZ5と全く同じで大丈夫なので,省略します.②は,QUIZ5の関数add( )の中身を内積外積の式に則って計算するよう書き換えれば解けますね.

以上で課題の考え方について終わりです.
もう授業では何も言いませんが,命名規則守ってください! 何人か未だに守れていない人がいます.

 

Remove all ads

関数

第5回の授業では,関数について勉強しました.
関数のイメージは,一言で言うと「関連する復数の処理を1つにまとめたプログラム」だと思ってください.

現在までの授業では,100行にも満たないとても短いプログラムしか書いていませんが,今後の課題では数百行や数千行というプログラムを書かなければいけないことが出てきます.このようなプログラムでは,どの部分でどのような処理が行われているのか,ということが把握しにくくなり,結果としてバグ(プログラムの間違い)だらけのプログラムになりやすくなってしまいます.

そこで,関数を利用して,関連した処理(例えば,累乗を計算する処理や総和を計算する処理など)を1つのまとまりとしてまとめることで,プログラムをコンパクトにし,どの部分でどの処理が行われているかを分かりやすくします.

関数を書いてプログラムをまとめる利点は,プログラムがコンパクトになり処理が把握しやすくなるだけでなく,

  • 同じような処理を複数回記述する手間を省ける
  • 各機能毎に関数をまとめておくことでプログラムの修正が容易になる(どの部分を直せば良いのか分かりやすい)

と言った点があげられます.

ですので,皆さんにはぜひmain文が非常に長いものにならないように,関数をうまく活用して行くことをお勧めします.

では,「具体的にはどのように関数を書くのか」と言う点について説明して行きたいと思います.関数の書き方についての詳細は授業ページを見ていただいて,ここでは基本的な書き方について簡単に説明したいと思います.

戻り値の型 関数名(引数){
    ...
    関数内での処理;
    ...
    return文;
}

この書き方が基本です.
例として,x+yの値を計算するプログラムを考えます(xyは整数とする).

#include <stdio.h>

int func(int x, int y){
	return x + y;
}

int main(void){

	int x_input = 1;
	int y_input = 2;

	int sum = wa(x_input, y_input);

	printf("sum = %d\n", sum);
	return 0;
}

この関数の処理の流れは,

  1. x_input,y_inputのそれぞれの変数に値 1,2を代入
  2. 変数sumに関数waで書いた処理(x + yのこと,具体的に何の値を足せば良いのかを関数に教えるために引数にx_input, y_inputをとる)を実行した時の戻り値を返す
  3. 最後にsumの値を画面に出力

という順番で行われます.

授業では,このときの関数とメイン文で同じ変数を使っていいのか?などの質問を多く受けましたが,とりあえずは,「{ }」の中で同じ変数が使われていなければ大丈夫である.と覚えておいてください.

以上で,今回の授業のおさらいは終わりです.
以下,課題の考え方についてです.

5組
1.キーボードから整数 n を入力し,1 から n までの和,∑n および二乗和 ∑n2 を計算し,画面に表示せよ.
この課題のポイントは,
 ①1からnまでの繰り返し計算
 ②繰り返しの終点が計算開始初期からわかっている
です.和の計算に関しては,授業内練習問題のQ2にてプログラム済みですので,もうできると思います.
また,繰り返し計算をどのループ(for, while)を使っても可能なので,各々試してみてください.強いて言うなら,②があるので,forループの方がやりやすいかも...?

2.フィボナッチの数列 ak = ak-1 + ak-2 ,a1 = 1, a2 = 1 の第n項までを画面に表示せよ.nはキーボードから入力する.

実行例:
n= 10
a1 = 1
a2 = 1
a3 = 2
a4 = 3
a5 = 5
a6 = 8
a7 = 13
a8 = 21
a9 = 34
a10 = 55

この課題のポイントは,
 ①各変数ak,ak-1,ak-2の計算順番です.例えば,3つの変数をそれぞれ用意しておきak = ak-1 + ak-2を計算し,その後ak-1とak-2の値を更新していくのと,更新を先に行ってから計算処理をするのでは,全く違う値が得られます.果たしてどの順番が正しいのか,混乱するとは思いますが,よく考えながらプログラムしましょう.

3.for文のネストを利用して,以下のように - と | が交互に出現する表を画面に表示しなさい

|-|-|-|-|-|-
-|-|-|-|-|-|
|-|-|-|-|-|-
-|-|-|-|-|-|
|-|-|-|-|-|-
-|-|-|-|-|-|

 この課題のポイントは,
 ①6×12の行列の形
 ②|と-が交互
です.①の形は,授業内練習課題のQ4でもやりましたね.②は,考え方はいくつかあると思います.for文のカウンタ変数の奇偶による条件分岐,四則演算による条件分岐etc...
ぜひ,TAも感心する処理方法を考えてプログラムしてみてください!

4. while 文を用い, 0 < x < 2π の範囲で,f( x ) = cos( x ) の最初の極小値と,その時のxの値を求め,画面に表示せよ. (もちろん答えは x = π のとき,-1 である)

#include <stdio.h>
#include <math.h>    /* cos 関数の使用に必要 */

int main(void)
{
    float x;
    float dx = ????;

    while( ??? ) {

        if(???)
            break;

        x += dx;
    }

    printf(...);       /* 結果の表示 */
    return 0;
}

この課題は,本ブログ「第4回 制御文2」内の課題の考え方6組2問目での考え方と一緒です.そちらと授業ページのヒントを参考にしましょう.

5.1から1000までの自然数において,(a)入力した列数で改行して表示し,(b)その際に任意の自然数の倍数を伏せ字にするプログラムを作成せよ.

実行例 :

改行する列数 = 7
伏字にするのは = 4 
    1|    2|    3|-----|    5|    6|    7| 
-----|    9|   10|   11|-----|   13|   14| 
   15|-----|   17|   18|   19|-----|   21| 
(中略) 
  967|-----|  969|  970|  971|-----|  973| 
  974|  975|-----|  977|  978|  979|-----| 
  981|  982|  983|-----|  985|  986|  987| 
-----|  989|  990|  991|-----|  993|  994| 
  995|-----|  997|  998|  999|-----| 

この課題のポイントは,
 ①表示が行列の形
 ②列数は入力した値で変化
 ③入力にて指定した自然数の倍数に対する処理
です.①は課題3と同じなのですが,列数の条件は入力された値によって変わります(②).ネストさせたループの列数を指定する条件判定部に気をつけてプロ グラムしてみましょう.③はこれまでもやってきた条件分岐の処理です.任意の数nの倍数ということは,言い換えるとnで割った余りが0というのは,授業中 に先生が何度も仰っていましたね.この課題は①,②ができたことを確認できたら,③を追加しましょう.1つの問題の中に複数の独立した問題がある場合 (今回でいうと,任意の列数の行列表示任意の数字の倍数の伏字化),片方だけでうまく実行できることを確認できた後に全部を1つにすることで,エラーが出た際にバグ部分を見つけやすくなります.

6組

1. 直角三角形の短辺2つの長さ(a,b)を入力すると,長辺の長さ(c)を返す関数を作りましょう. a,bの値はそれぞれキーボードから入力します.

この問題では,計算処理は関数で行い,main関数では,関数を呼び出す前処理や結果の表示だけ行います.
具体的に関数内で行う計算処理は三平方の定理を利用することです.
またこの問題では,math.hというヘッダファイルをインクルードすることで平方根の計算を非常に簡単に行うことが可能です.
プログラムの例としては,

#include <stdio.h>
#include <math.h>

float calculate_triangle(float a, float b){
	return sqrt(平方根の中身の計算);
}

となります.このプログラムの中身の計算は,上記で説明した三平方の定理を利用した計算式です.

2. QUIZの5番目の問題は,1から3までの3個の2乗和を求めました. このプログラムを改良して,1からNまでの2乗和を求めるプログラムにしてください. このとき,Nの値は,scanf()関数で与えられるようにしてください.

この問題は,QUIZ5で作成したjijo関数をそのまま流用し,wa関数を少しだけ修正することで簡単にプログラムを解くことが出来ます.
それぞれQUIZでは

//二乗を計算する関数
int jijo(int x){
	return x*x;
}

//3つの値の和を計算する関数
int wa(int a, int b, int c){
        return a + b + c;
}

となっていました.

QUIZと今回の問題の変更点は,「1から3までの3個の2乗和を求める」と「1からNまでの2乗和を求める」と言う点です.ここで,注目してもらいたい点は,「1からNまで」というフレーズです.この部分から制御文の授業で学んだ,「繰り返し」が使えるということに気づいてほしいですね.

このことに築くことが出来たならば,後は引数を繰り返し回数の上限であるNとするような関数を作成します.
解答例のヒントとしては

int wa2(int N){

	for(int i=0;i<N;i++){
		2乗和を計算する処理(QUIZで作成したjijo関数を利用しましょう);
	}
	return 1からNまでの2乗和;
}

3. 速度0で静止しているロケットに点火してロケットを打ち上げます.ロケットの質量を m,推力が  F で一定だとしたとき, 打ち上げから時間t秒後の速度 v(t)を求める関数を作って下さい.引数は m,F,tで,戻り値が v(t)です.

この問題は,

 V(t) = at + V_0

の数式を利用できるので,この数式をそのまま関数とします.

また引数がm, F, tということから加速度aを求めるために

 F = ma

を利用してください.

このことをふまえて関数を作成すると,解答の一例として以下のような関数が作成できると思います.

float velocity(float F, float m, int t){
	加速度aを求める計算処理;

	return 上記の加速度を利用した速度を計算する処理;
}

この解答例では,推力Fと質量mは少数でも計算可能なようにfloat型の変数で定義し,時間tは整数しか入力されないと考えint型としました.さらに,計算される速度も小数になり得ると考え,float型です.
ここのそれぞれの変数型は,きちんと速度の計算を行うことが出来れば,個人の自由に変更していただいて結構です.

 

授業ページの問題文”~する関数を作ってください”とありますが,もちろんmain関数も必要です.

すべてのプログラムにおいて,きちんとコンパイル(リンクまで)が通る形で提出してください.

 

 

繰り返しでくどいようですが,まだ,ファイルの命名規則が守られてない人がいます. ~.zip.zipになっていないかなど,きちんと確認をしてから提出するようにお願いします.

では,皆さん課題をがんばってください.

Remove all ads

制御文2

第4回 制御文2のおさらいと課題を解くにあたっての考え方について解説したいと思います.
第4回では,前回学んだif文,for文,while文の応用とその他の条件処理,ループ処理の方法を学びました.

if文

if文は,ある条件を満たす(あるいは満たさない)時にのみ何か処理をさせたい場合に使用するものです.

if(条件式){
            処理文
}

前回はここまで学びましたね.
では,ある条件の中にさらに条件がある,例えば「変数xが4と5の公倍数であり,変数y未満の場合」のような場合には,if文の処理文の中でさらにif文を入れ子にする(プログラミングにおいて,ネストにすると表現する)ことができます.上記の例をもとにすると,

if(x%4==0 || x%5==0){
             if(x < y){
                     処理文
}

のような書き方になります.
また,if文とelse文を組み合わせることで,さらに複雑な条件分岐もすっきりと書くことが可能になります.

if(条件式1){
           処理文1
}else if(条件式2){
           処理文2
}...
}else{
           処理文n
}

 

for文

for文はループ(繰り返し計算)処理を行う際によく用いられるものです.基本的な構文は,

for(初期設定部; 条件判定部; インクリメント部)  処理文

であるが,各部を"( )"の外で定義することも可能です.

int i = 0;  //初期設定部
for(  ;  ;  ){
           if(i > 10){  //条件判定部
                     処理式
           }
           i++;  //インクリメント部
}

ただし,このような書き方は書いていて混乱しやすいため,特別な場合を除き基本的な書き方に則って書くべきです.
for文もif文と同様,ネストにすることが可能です.

for(int i=0; i<10; i++){
    for(int j=0; j<10; j++){
         printf("%d × %d = %d\n", i, j, i*j);
    }
}

 

while文

while(条件式){ 処理文 }

while文は条件式が真である間,処理が繰り返されます.ということは,条件式が最初から偽である場合,処理は一度も実行されません.
しかし,まず最初に一度処理をさせてから条件判定をしたい場合というのも出てくると思います.その時には,do-while文を使います.

do{
                 処理文  //最初から条件式が偽でも一度は実行される
}while(条件式)

すなわち,
・まず条件判定をさせたい → while文
・まず処理判定をさせたい → do-while文
といった使い分けとなります.

 

break文, continue文, switch文

ループの途中で終了判定を待たずにそのループから抜け出せるbreak文,ある条件の時は処理をさせないcontinue文というのもある.
そして,if-else文を多く用いらなければならなく,条件の評価対象が整数の場合,switch文というものを使うと,すっきり見やすく書けます.また,どちらもネストさせることが可能です.

switch(変数){  //変数は整数(int, char)のみ
    case 定数1:  //変数が定数1なら,処理文1が実行される
         処理文1;
         break;
    case 定数2:
         処理文2;
         break;
    default;         //どの条件にも当てはまらない場合(if-else文のelseに相当)
         処理文3;
         break;
}

どうでしょうか?if-else文より見やすくなりましたか?正直,これは条件分岐が多い場合を実際にプログラムした時に初めて恩恵を感じる気がします.このswitch文も先述のfor文,while文同様ネストさせる事ができます.

以上,かなりざっくりとしてますが第4回のおさらいになります.

 

では,課題の考え方について解説したいと思います.


1.for文を2回使用して以下に示すような九九の計算結果を表示するプログラムを作りなさい. このとき,桁をきちんと合わせて表示すること.

【実行例】
1   2   3   4   5   6   7   8   9 
2   4   6   8  10  12  14  16  18 
3   6   9  12  15  18  21  24  27 
4   8  12  16  20  24  28  32  36 
5  10  15  20  25  30  35  40  45 
6  12  18  24  30  36  42  48  54 
7  14  21  28  35  42  49  56  63 
8  16  24  32  40  48  56  64  72 
9  18  27  36  45  54  63  72  81 

この課題のポイントは,
 ①for文を2回使うこと
 ②桁を合わせること
です.①については...このページにヒントが載っていますね!
②については,画面に出力するprintfの中の変換指定(%dや%fなど)で桁数の設定ができますよね.
こういう分からない時こそ,Google先生に聞きましょう!「C言語 桁数揃え」などと検索すると...?

 

2.while文を用い (0<=x<=2π) の範囲で,f(x)=sin(x) の極大値fmax(a)とその位置 a を探索し求めよ. なお探索時のxの刻み幅 dx=0.0001 とする.
この課題のポイントは,
 ①while文の条件式
 ②三角関数を使う
 ③極大値を調べる
です.①は,何と何を比較して真偽を判定するのでしょうか?この問題文の中で,範囲が指定されている変数がありますよね!
②は,実は皆さんは習っていない部分があります.現段階ではまだ"おまじない"と教わったかもしれませんが,プログラムのコードの最初に"#include "というのを書いていますよね?この1行をコメントアウト(/*と*/で挟む)して保存・コンパイルしてみてください.printfやscanfに関するエラーが出てくると思います.今まで使っていたprintfやscanfは「標準入出力関数」と呼ばれるもので,これらを使用するためには,stdio.hというヘッダファイルをインクルードしなければいけないのです.難しい説明になってしまいましたが,"#include を最初に書いておくことでprintfやscanfが使えるようになる!"とだけ理解しておけば今は大丈夫です.同じように,sinやcos(これらを数学関数と言う)を使えるようにするためには,math.hをインクルードしなければなりません.具体的には,"#include "の下の行に"#include "と書けば,三角関数を使えるようになります.
③は,始めに極大値を代入する変数fmaxを用意しておき,インクリメントする前の変数のf'(x)と後の変数のf(x)の値を大小比較して,もしインクリメント後のf(x)の方が大きければ,極大値fmaxにf(x)を代入していく,というのを繰り返せば,最終的なfmaxが極大値となります.

[解答例]

 

3.何月かを入力するとその月の英語名(January等)を表示するプログラムをswitch文を用いて作れ.

【実行例】
今は何月ですか?:5 
ああ,今は May なんですね! 

この課題のポイントは,
 ①何がswitch文の変数になるのか
です.出力させたい月の英語名は,何から判断されますか?それを考えれば,何を変数にしたらいいのか分かると思います.

以上が,第4回の課題を解くにあたっての考え方になります.
授業中にもお話しましたが,命名規則を守って提出をしましょう

 

Remove all ads

制御文1

第3回 制御文1のおさらいと課題を解くにあたっての考え方についての簡単に解説したいと思います.

まず今回の授業で扱った制御文ですが,今後いろいろなプログラムを書く上での基本となるため,しっかりと復習をしてください.
簡単なおさらいなので,詳しく勉強したいときは授業ページを見たり,Googleや本などできちんと調べてください.

さて,制御文とはプログラムを実行するときに「ある条件によって処理を変更」したり「同じ処理を何度も繰り返し(ループ)」たりするときに便利な書き方です.この制御文を利用することで,複雑な処理を実行することが可能となるメリットがあります.
このようにプログラムを書く上で重要となる制御文ですが,第3回の授業ではその基本となるif文とwhlie文,for文を勉強しました.

if文は英語の「もし~なら」という意味の通り,条件分岐を行うことができるようになります.
if文の詳しい構造は授業ページに書いてあるので,ここではif文のイメージを簡単に説明したいと思います.

	if(条件式){
		処理
	}

例えば,このようなif文があったときは,「条件式が正しければ(成り立てば),処理が実行される」という感じです.この条件式は関係演算子論理演算子を用いて表現します.関係演算子と論理演算子については,詳しくは授業ページにまとめられているのでそちらを参照してください.

while文,for文は繰り返しを行うことができる制御文です.
while文の構造は,

       while(条件式){
               処理
       }

この文のイメージは,「毎回の繰り返しにおいて,条件式が成り立つときは処理を行い,条件式が成り立たなくなったら繰り返しを終了する」という感じです.

for文の構造は,以下のようになっています.

	for(初期化式;条件式;値変化){
		処理
	}

この文のイメージは「初期化式で設定した変数が条件式を満たすことができなくなるまで,繰り返す(初期化式で設定した値は値変化で設定したように変化させる)」ということです.

授業では,特にfor文がどのような働きをするのかが分かっていない人が多かったように感じたので具体例をひとつ挙げて説明したいと思います.

)
	for(int i=0;i<10;i++){
		printf("%d¥n", i);
	}

このようなfor文があるとき,処理の流れは,

  1. 「i=0」によって,iに0を代入する
  2. 「i<10」よりiの値が10より小さいかを判定し,この条件を満たしていれば(iが10より小さければ),処理(printf)を実行する.
  3. 「printf」によって,iの値を出力する
  4. 「i++」によって,iに1を足す
  5. iが10以上になるまで,2〜4の処理を繰り返す

となります.

この流れがfor文の基本になり,繰り返しを行いたい処理(今回は「printf」)を適宜変更することで,様々なプログラムに応用できます.

以上が,第3回のおさらいです.情報処理自習1の授業は積み重ねが大切なので,繰り返しになりますが,復習をよろしくお願いします.

では,課題の考え方について解説したいと思います.
今回の課題は全部で3問ありましたが,すべてif文を使用します(正直に言うと,for文は使いません).

1.入力された2つの整数が等しいか否かを判定するプログラムを作成せよ.

【実行例】
整数1:3
整数2:4
2つの整数は違います.

この問題を解くポイントは,

  1. どのようにキーボードから値を入力するか?
  2. 等しいか否かの判定のやり方は?

という2点かと思います.
まず,①に関してですが,C言語には,キーボードから入力された値をプログラムで利用するための機能が予め用意されています(標準の関数が用意されているということ).(ちなみに,「printf」などは関数と呼びます).その関数は「scanf」という関数です.この関数の使い方は,main関数のなかで以下のように使います.

int input;

scanf("%d", &input);

この文は,「予め用意しておいた,変数(今回は「input」)にキーボードから入力された値を代入しています」.「scanf」の書き方は,少し「printf」に似ていますね.注意する点は,「&input」のように「&」マークをつけることです.この「&」をつける意味は,C言語でもっとも難しいと言われている「ポインタ」という部分に関係しているのですが,今はまだ「scanfの時はつけなきゃいけないもの」だと思っておいてください.

次に②については,「キーボードから値を入れた2つの変数をどのように比べるか」ですが,この部分にif文を利用します.このときのif文の構造は以下のようになると思います.

	if(条件式){
		printf("2つの整数は等しいです.¥n");
	}
	else{
		printf("2つの整数は違います.¥n");
	}

このときの条件式が「2つの変数が等しい」ということを表現できれば問題は解けると思います.

  • ヒント:授業ページの関係演算子の部分を参照

2.キーボードより入力した整数が3の倍数かどうか判定するプログラムを作りなさい.

【実行例】
・パターン1
3の倍数かどうか判定します。 
整数を入力してください:7
7は3の倍数ではありません。

・パターン2
3の倍数かどうか判定します。 
整数を入力してください:12
12は3の倍数です。

この問題を解くことにおけるポイントは,

  1. どのようにキーボードから値を入力するか?
  2. 3の倍数という判断はどのように行うのか?

の2点だと思います.
①に関しては,上記の問題1を参照してください.
②についてですが,「ある値(たいていは変数)が何の倍数(今回は3の倍数)かを判定する」ときには,「割り算をしたときのあまり」に注目することが非常に有効となります.C言語において,この「割り算をしたときのあまり」を計算してくれる演算子が「%」演算子です.つまり,例えば,ある値(x)が5の倍数かどうかを判定するには,「x%5」が「0」であれば良いのです.これを利用するととても簡単に「ある値が何の倍数なのか」を判定することができます.
この問題では,3の倍数かどうかを判定するので,キーボード入力さた変数が3で割った時にあまりが0となるように条件式を設定(「%」演算子を利用)してあげれば,if文の構文(else文も使う)によって解けるかと思います.

 

3.テストの点数(0~100)を入力し,成績(S,A,B,C,F)を表示するプログラムを作りなさい.点数が範囲外の場合はエラー判定をしなさい.

【実行例】
・パターン1
テストの点数を入力してください:89
89点の成績はAです.

・パターン2
テストの点数を入力してください:111
エラー:点数が範囲外です.

この問題を解くポイントは,

  1. キーボードからの入力
  2. 成績の判定
  3. エラー処理

の3つだと思います.

①は問題1を参照してください.
②についてですが,こちらはif文の条件式で成績S,A,B,C,Fとなる点数の範囲を設定してあげます.
例えば,S, Aの場合は

                if(90<=test_score){
			printf("%d点の成績はSです.¥n", test_score);
		}
		else if(80<=test_score && test_score<90){
			printf("%d点の成績はAです.¥n", test_score);
		}
                .....

となります.ここで「else if」ですが,多分岐構造のif文です.詳しくは授業ページの「else文」の項目を参照してください.
このif文での条件式は(80<=test_score && test_score<90)となっています.test_scoreが変数(キーボードから入力される点数)なので,数式的にこの条件式を表すと,


のようになります.これは成績Aについての例なので,それぞれ他の成績にも当てはめてあげてください.

最後に③ですが,このエラー処理を行う上でのヒントは授業ページの「コードブロック」の項目になります.
この処理もif文によって構成されるのですが,イメージとしては,「大きな枠組みで入力された値が範囲内かどうかを判断し,範囲外ならエラーを出力し,範囲内なら②の処理を行う」,という流れが良いかと思います.
例としては,

        if(入力された点数が0~100の間ある){
		if(点数が90点以上){
			成績Sと表示する
		}
		else if(点数が80点以上90点未満){
			成績Aと表示する
		}
                .....
	}
	else{
		エラーと表示する
	}

のようになると思います.

以上が第3回の宿題の考え方です.

また,授業中に気になったこととして,webブラウザで開いているタブが講義ページだけという人が多い印象を受けました. 授業中知らない単語がでてきたり,理解できない箇所がでてきたときにすぐに検索して調べる癖をつけましょう.

そして講義中はテキストファイルに残したり,Evernoteを使うなどして,メモをしっかりとるようにしてください.

 

タイピング練習についても,授業中に紹介したアプリや各種無料のタイピングゲームなどで,各自スキマ時間を使って行うようにしてください.

 

第3回のプログラムに関する質問は,こちらの記事のコメント欄にお願いします.

何度もしつこいようですが,ファイルの名前の付け方,zipファイルの名前の付け方は,授業中に伝えたルールに従ってつけてください.
ルールに従っていない場合は,採点することができなくなってしまいますので,よろしくお願いします.

Remove all ads

2017年度情報処理実習1 はじめに

2017年度の情報処理実習1についてのブログです.
このブログでは,授業についての簡単なおさらいと課題についての考え方や解説等を行っていきたいと思います.


また,授業についての質問対応等は基本的にこのブログで受け付けます.気軽にコメント欄にて質問してください.

オフィスアワーは,以下のようになっています.

  • 5組 : 金曜日 5-6限(17:10 - 20:40)
  • 6組 : 木曜日16:20~19:30
  • 再履5組:金曜日18:00~19:00
  • 再履6組:木曜日18:00~19:00

直接質問する場合はこの時間にD103に来てください.
基本的にこの時間以外の対応はできません

そのため,
まずは,インターネット等を利用して自分で調べる
次にこのブログのコメント欄で質問する.
それでも分からなければ,オフィスアワーを利用して質問に来る.
という形をとるようにしてください.

授業ページ
5組
http://www.isc.meiji.ac.jp/~be00085/

6組

http://www.isc.meiji.ac.jp/~re00104/

再履修

http://www.isc.meiji.ac.jp/~re00104/2017sairi/

 

昨年度ブログ

http://joho1-2016.hatenablog.com