専門学校45日目(情報工学)6月14日(金)

1時限~3時限
C言語基礎 やさしいC 第5版

先週は中間テストでした。その答え合わせから始めます。平均点はペーパテストが約74点、プログラミングは約79点だったそうです。
■ペーパーテスト
問題の解説をいくつかピックアップします。
⑴ 9*4
⑵ 9/4
⑶ 9%4
⑷ 5/2.0
⑸ 15>>2
⑹ 5<<1
⑺ 0x31
⑻ 10^9
⑼ 13&11
⑽ '1'+'2'
などの出力がどうなるかを問う内容でしたが、後半は間違いが多かったようです。
15>>2は右に2ビットシフトする。2回2で割ればいいので15/2=7、7/2=3となり3が答え。
5<<1は左に1ビットシフトするので2をかけ5*2=10が答え。
0x31は16進数でこれを10進数に直す問題。重みをかけて3*16+1=49となる。
10^9は排他的論理和で2進数に直して計算する。答えは3。
13&11は論理積でこれも2進数に直して計算する。答えは9。
'1'+'2'は文字としての答えで12と答える人が多かった。しかし、文字コードで答えるので、問題用紙の下にASCIIコードで1は0x31、2は0x32になると書かれているので49+50=99が答え。

==や<などの比較を行う演算子は比較演算子もしくは関係演算子という。これは答えが2つありました。教科書では関係演算子となっています。
scanf_sやgetcharは標準入力という。

この辺は基礎なのでわからないところは放置せず相談してほしいとのことでした。


■プログラミングの試験の解答
問題3の標準偏差を求めるところで躓く人が多かった。間違えても部分点を加点できるのでわかる範囲で解いて提出してください。
5人分の得点は標準入力でscanf_sを使って入力させる。合計は単に足したものを出力し、平均は小数点が出てくるのでdouble型にキャスト変換して出力する。
標準偏差は
d1=(num1 - 平均)*(num1 * 平均)
というように、これを分散といいますが5人分求めて
double s = sqrt((d1+d2+d3+d4+d5)/5);
として求める。sqrtという平方根を計算する関数を使用するには#include <math.h>をインクルードする必要があります。


問題4は1から100までの整数のうち5もしくは7で割り切れる数の個数を計算し、表示するという問題。
これは単に100/5と100/7の商で数えられる。共通で割り切れるのは35なので100/35の商を求める。5と7での商を足すと共通で割れる数も含まれているので35で割った商を引いてやると5または7で割り切れる数の個数が求まる。


問題5は4つの整数を入力させ、条件に基づいて出力を変化させる内容でした。
if文で分岐させるのですが、
(a>0 && b%2==0)
(a<0 && c%2==1)
(d>0 && d>b)
などの条件があり、条件ごとに和や積をとって表示させます。どれにも当てはまらないときの処理も書く問題でした。問題文に忠実に画面表示されるようにコードを書いてほしいです。そうでないと減点対象になります。


今後も数学的な問題が出てくると思うのですが、実社会でロボット制御するときなど3次元での動きを実現するのに数学が必要ですので、しっかり学んでいただければと思います。


今日は6章何度も繰り返す、から学んでいきます。for文の処理はfor文(初期化の式;繰り返すか調べる式;変化のための式)の後に波括弧を用いてブロック化する必要があります。

int i;
for (i=1; i<=5; i++) {
printf("\n");
}
のように書きます。

for文を使って九九の表を出力させる。以下のように解きました。先生の解答も載せます。

#include <stdio.h>
int main(void) 
{
/**
int i, j;
for (i = 1; i <= 9; i++) {
    for (j = 1; j <= 9; j++) {
        printf("%d ", i*j);
    }
    printf("\n");
}
//*/

/**
int i;
for (i = 1; i <= 9; i++) {
    printf("%d %d %d %d %d %d %d %d %d\n", 
            i * 1, i * 2, i * 3, i * 4, i * 5, i * 6, i * 7, i * 8, i * 9);
}
//*/

/*表が出力されても整っていないので、桁を合わせるという書き方がある。
%2dと書くと一桁分の数とも2桁分にして表示される。*/
/**
int i;
for (i = 1; i <= 9; i++) {
    printf("%2d %2d %2d %2d %2d %2d %2d %2d %2d\n", 
            i * 1, i * 2, i * 3, i * 4, i * 5, i * 6, i * 7, i * 8, i * 9);
}

return 0;
}

for文を使って入力された数の分だけ*を表示させる。

#include <stdio.h>
int main(void) 
{
int num;
int i;
scanf_s("%d", &num);
for(i=1; i<=num; i++) {
    printf("*");
}
printf("\n");
return 0;
}

for文で1から入力した値までを足し上げるプログラムが例にある。
1から10までの数値で、1,3,5,7...というように足していくときはどうすればいいでしょうか。
for (i=1; i<=num; i+=2)
という条件になる。
10から1まで1つずつ減らしていく場合は、初期化を10とし、デクリメントで減らしていく。


■while文
for文と同じように繰り返し処理を行うものです。
for文での初期値などを外に出した形で書く。

int i = 1;
while(i<=5) {
printf("");
i++;
}
のように書いていく。for文のほうが1行でまとめて書ける。
先ほど書いた九九のfor文をwhile文に書き換えました。

#include <stdio.h>
int main(void) 
{
int i = 1;
while (i <= 9) {
    printf("%2d %2d %2d %2d %2d %2d %2d %2d %2d\n", 
            i * 1, i * 2, i * 3, i * 4, i * 5, i * 6, i * 7, i * 8, i * 9);
    i++;
}
return 0;
}

■do~while文
必ず1回は実行し、そのあと条件を見て繰り返すか終了するかを見る。while文は条件に当てはまらなかったら一度も実行されないことがあります。while文と同じように初期値はwhile文の前に出して書きます。

int i = 1;
do {
printf("");
i++;
}while(i <= 5);
のように書きます。

先ほどの九九をdo~while文に書き直しました。

#include <stdio.h>
int main(void) 
{
int i = 1;
do {
    printf("%2d %2d %2d %2d %2d %2d %2d %2d %2d\n",
        i * 1, i * 2, i * 3, i * 4, i * 5, i * 6, i * 7, i * 8, i * 9);
    i++;
} while (i <= 9);
return 0;
}

のようになります。条件の判定が最後に来ます。
注意していただきたいのが、while文にはセミコロンがいらなかったのですが、do~whileには最後のwhile()にセミコロンが必要になります。

■文のネスト
for文の中にfor文をループさせるといった使い方ができます。複数の文を入れ子構造にすることをネストするといいます。
先ほどのfor文をネストさせて九九の表を出力させるのを、今度は%2dで2桁表示にして書きました。

#include <stdio.h>
int main(void) 
{
int i, j;
for (i = 1; i <= 9; i++) {
    for (j = 1; j <= 9; j++) {
        printf("%2d ", i*j);
    }
    printf("\n");
}
return 0;
}

以上で今日の授業は終わりです。


4時限~6時限
webDBシステム開発 スッキリわかるSQL入門第3版ドリル256問付き

今日からテーブル設計を学びます。まずは共有フォルダの問題をやりました。問題の文章は載せませんが、解答だけ載せておきます。
期末試験はデータベースが7月26日、Javaは29日を予定しています。

create table ゲレンデマスタ (
    ID integer, 
    ゲレンデ名 varchar(12), 
    エリア varchar(3), 
    ボード可 varchar(3), 
    早朝スキー varchar(3), 
    ナイター varchar(3) 
)

insert into ゲレンデマスタ
values (1, '蔵王', '東北道', 'Yes', 'No', 'Yes')

insert into ゲレンデマスタ
values (2, '川場', '関越道', 'No', 'No', 'No')

insert into ゲレンデマスタ
values (3, '野沢温泉', '信越道', 'No', 'No', 'Yes')

insert into ゲレンデマスタ
values (4, '妙高', '信越道', 'Yes', 'No', 'Yes')

insert into ゲレンデマスタ
values (5, '志賀高原', '信越道', 'No', 'Yes', 'Yes')

insert into ゲレンデマスタ
values (6, '車山', '中央道', 'Yes', 'Yes', 'Yes')

insert into ゲレンデマスタ
values (7, 'アルツ磐梯', '東北道', 'Yes', 'Yes', 'Yes')

insert into ゲレンデマスタ
values (8, 'グランデコ', '東北道', 'Yes', 'Yes', 'No')

insert into ゲレンデマスタ
values (9, '苗場', '関越道', 'Yes', 'Yes', 'Yes')

insert into ゲレンデマスタ
values (10, 'エコーバレー', '中央道', 'Yes', 'No', 'Yes')

insert into ゲレンデマスタ
values (11, '乗鞍高原温泉', '中央道', 'No', 'No', 'No')

insert into ゲレンデマスタ
values (12, '八方尾根', '中央道', 'Yes', 'No', 'Yes')

insert into ゲレンデマスタ
values (13, '上越国際', '関越道', 'Yes', 'No', 'Yes')

insert into ゲレンデマスタ
values (14, '栂池高原', '中央道', 'Yes', 'No', 'Yes')

insert into ゲレンデマスタ
values (15, 'ハンターマウンテン', '東北道', 'Yes', 'Yes', 'Yes')

insert into ゲレンデマスタ
values (16, '小海リエックス', '中央道', 'Yes', 'No', 'No')

insert into ゲレンデマスタ
values (17, '猫魔', '東北道', 'Yes', 'Yes', 'Yes')

insert into ゲレンデマスタ
values (18, '田代・かぐら・みつまた', '関越道', 'Yes', 'No', 'No')

insert into ゲレンデマスタ
values (19, '神立高原', '関越道', 'Yes', 'Yes', 'No')

insert into ゲレンデマスタ
values (20, '尾瀬岩鞍', '関越道', 'No', 'Yes', 'Yes')

select *
from ゲレンデマスタ
where エリア = '東北道'

select *
from ゲレンデマスタ
where エリア <> '東北道'

select *
from ゲレンデマスタ
where エリア in ('中央道', '関越道')

select *
from ゲレンデマスタ
where エリア not in ('中央道', '関越道')

select *
from ゲレンデマスタ
where ID between 6 and 15

select *
from ゲレンデマスタ
where ID >= 16

select ID, ゲレンデ名
from ゲレンデマスタ
where 早朝スキー = 'Yes'
and ナイター = 'Yes'

select ID, ゲレンデ名
from ゲレンデマスタ
where 早朝スキー = 'Yes'
or ナイター = 'Yes'

select *
from ゲレンデマスタ
where ゲレンデ名 like '%温泉'

select *
from ゲレンデマスタ
where ゲレンデ名 like '%高原%'

select distinct エリア
from ゲレンデマスタ

select *
from ゲレンデマスタ
order by エリア

select *
from ゲレンデマスタ
order by エリア desc

select *
from ゲレンデマスタ
order by ボード可 desc, 早朝スキー desc, ナイター desc

select *
from ゲレンデマスタ
order by 3

select *
from ゲレンデマスタ
order by 4 desc, 5 desc, 6 desc

update ゲレンデマスタ
set 早朝スキー = 'No'
where ID = 8

delete from ゲレンデマスタ
where ID = 10

教科書p.241
p.241のテーブルは家計簿テーブルと費目テーブルに分かれている。問題を解いたとき、エリアで中央道や東北道などを指定してデータを追加していきました。しかし、別個のテーブルに分けるやり方を学びます。

テーブルをくっつけるときは
join テーブル名
on 家計簿.費目ID = 費目.ID
費目テーブルのIDは主キーだとわかる。
家計簿テーブルの費目IDの数字で費目テーブルの主キーIDを引っ張ってくる。このとき家計簿テーブルの費目IDを外部キーという。
E-R図の書き方も習いました。期末試験にも出すそうですが基本情報の試験でも問われます。
E-R図は四角で囲ったものの関係性を表します。四角の図形だけでは何の関係もない状態で、線を引くことで関連(リレーション)を表します。直線は1対1を、矢印は多対1を表します。たとえば費目テーブルの主キーは1で家計簿テーブルの外部キーは多の関係にあるとき、費目の四角から家計簿の四角に向かって矢印を引きます。

先ほどやった問題でdistinctを使った問いがあります。
select distinct エリア from ゲレンデマスタ
これは実行すると4件出てきたが、その4種類の道の名前を使います。
問題にあったテーブルのエリアには東北道や信越道などの漢字がたくさん出てきて煩わしいのでテーブルを独立させます。そしてエリアマスタテーブルを作る。
ゲレンデとエリアのE-R図を書いて、エリアマスタのテーブル設計をしました。

create table エリアマスタ ( 
    ID integer, 
    エリア varchar(3) 
    )

insert into エリアマスタ
values (1, '中央道')

insert into エリアマスタ
values (2, '信越道')

insert into エリアマスタ
values (3, '東北道')

insert into エリアマスタ
values (4, '関越道')

これでエリアマスタというテーブルを作ります。次にゲレンデマスタのテーブルをいじります。

alter table ゲレンデマスタ add エリアID integer

で新しくエリアIDという項目を追加します。追加したばかりだと何の値も入っていない状態です。そこにupdate文でデータを追加していきます。

update ゲレンデマスタ
set エリアID = 1
where エリア = '中央道'

update ゲレンデマスタ
set エリアID = 2
where エリア = '信越道'

update ゲレンデマスタ
set エリアID = 3
where エリア = '東北道'

update ゲレンデマスタ
set エリアID = 4
where エリア = '関越道'

これでIDに番号が割り当てられました。

alter table ゲレンデマスタ drop エリア

エリアマスタのテーブルにエリアの項目があるので、このalter~dropでゲレンデマスタのエリアは削除します。

select ゲレンデマスタ.ID, ゲレンデ名, エリア, ボード可, 早朝スキー, ナイター
from ゲレンデマスタ
join エリアマスタ
on ゲレンデマスタ.エリアID = エリアマスタ.ID

そしてjoinを使って2つのテーブル、ゲレンデマスタとエリアマスタをくっつけます。onによりゲレンデマスタのエリアIDとエリアマスタのIDを対応させます。select文でゲレンデマスタ.IDとあるのはIDがごっちゃになってしまうのでゲレンデマスタのIDと認識させる命令です。2つのテーブルをつなげたのでゲレンデマスタから削除したエリアをエリアマスタのエリアで参照できるようになり、項目の順を変えて
select ゲレンデマスタ.ID, ゲレンデ名, エリア, ボード可, 早朝スキー, ナイター
の順に表示させています。

この流れで何をやっているかが理解できないと来週以降躓いてしまうのでしっかり理解しておいてほしいそうです。

この記事が気に入ったらサポートをしてみませんか?