基礎演習3 C言語の基礎(3) 今日やること 先週の復習 先週の内容

今日やること

基礎演習3 C言語の基礎(3)



第09回(2010年06月23日)

先週の復習
算術演算
型変換とキャスト
構造化プログラミング
メモリとポインタ
先週の内容


先週の復習



C言語のファイル
リファレンスの読み方
変数
配列
printf の使い方(1)
3/59
配列 その2
多次元配列
 配列に値を代入・参照したい場合は、
配列名[番号]
のようにします。
#include<stdio.h>
main(){
int t[10];
t[2]=2;
t[5]=t[2];
}
t[0] t[1] t[2] t[3] t[4] t[5] t[6] t[7] t[8] t[9]
1
1
 配列を宣言するとき、次のように
配列名[番号][番号]
[番号]を複数つけることにより、多次元配列を利用できます。
#include<stdio.h>
main(){
int t[5][5];
t[2][3]=2;
t[4][1]=t[2][3];
}
t[0][0] t[0][1] t[0][2] t[0][3] t[0][4]
t[1][0] t[1][1] t[1][2] t[1][3] t[1][4]
t[2][0] t[2][1] t[2][2] t[2][3] t[2][4]
2
t[3][0] t[3][1] t[3][2] t[3][3] t[3][4]
t[4][0] t[4][1] t[4][2] t[4][3] t[4][4]
2
算術演算 その1
 C言語では、様々な演算子が使用できる。
算術演算子:
論理演算子:
x + y : x と y の和
A && B :AかつB
x - y : x と y の差
A || B :AもしくはB
x * y : x と y の積
x / y : x を y で割った商
x % y : x を y で割った余り
関係演算子:
x < y : x < y のとき真(1)、さもなければ偽(0)
x <= y : x <= y のとき真(1)、さもなければ偽(0)
x > y : x < y のとき真(1)、さもなければ偽(0)
x >= y : x > y のとき真(1)、さもなければ偽(0)
x == y : x = y のとき真(1)、さもなければ偽(0)
x != y : x != y のとき真(1)、さもなければ偽(0)
算術演算
7/59
演習:算術演算 (1)
算術演算 その2
 インクリメントとディクリメント
インクリメント → 増加
ディクリメント → 減少
A)
B)
C)
D)
x++ : xの値を評価後、インクリメント
++x : xの値をインクリメント後、評価
x-- : xの値を評価後、ディクリメント
--x : xの値をディクリメント後、評価
#include<stdio.h>
#include<stdio.h> それぞれの行が実行されたとき、
main(){
main(){
int
int x,y;
x,y;
例:
A)
B)
C)
D)
y=x++ : y=x; x=x+1; : 値を渡してから、xに1を加える
y=++x : x=x+1; y=x; : xに1を加えてから、値を渡す
y=x-- : y=x; x=x-1; : 値を渡してから、xから1を引く
y=--x : x=x-1; y=x; : xから1を引いてから、値を渡す
}}
変数の値がどうなるか、記入しましょう。
実行してみましょう
x
y
?
?
x=2+3;
x=2+3;
printf("001
printf("001 ->
-> %d¥n",x);
%d¥n",x);
y=x++;
y=x++;
printf("002
printf("002 ->
-> %d
%d %d
%d ¥n",x,y);
¥n",x,y);
y=++x;
y=++x;
printf("003
printf("003 ->
-> %d
%d %d
%d ¥n",x,y);
¥n",x,y);
演習:算術演算 (2)
#include<stdio.h>
#include<stdio.h>
main(){
main(){
int
int x,y;
x,y;
}}
実行してみましょう
型変換とキャスト
x=2+3;
x=2+3;
printf("001
printf("001 ->
-> %d¥n",x);
%d¥n",x);
y=x++;
y=x++;
printf("002
printf("002 ->
-> %d
%d %d
%d ¥n",x,y);
¥n",x,y);
y=++x;
y=++x;
printf("003
printf("003 ->
-> %d
%d %d
%d ¥n",x,y);
¥n",x,y);
12/59
型変換(1)
型変換(2)
次のようなプログラムの場合……。
#include<stdio.h>
#include<stdio.h>
int
int i;
i;
double
double d;
d;
main(){
main(){
i=2;
i=2;
d=i;
d=i;
printf("%f¥n",d);
printf("%f¥n",d);
}}

double型の変数に
整数型の変数iの値を
代入している!
C言語では、自動的に型変換が行われる。
 型の違う変数へ代入。
double の変数に int を代入等。

関数の引数として、異なる型の値を代入。
pow(x,y)のxとして整数値を渡す等。

大丈夫。
C言語では、自動的に型変換を行い、
代入してくれます。
今回も、double型の変数dには
2という値が代入されます。
できる限り、情報を失うことがないように変換する。
 int から double や、float から double は、情報を
失うことなく、きちんと変換する。
 double から int や double から float は、変換する
際に情報が欠落する。
13/59
14/59
強制的な型変換(キャスト)

計算結果の型
強制的に型変換を行うこともできる。
 (型名)を、変数や値につける。
#include<stdio.h>
#include<stdio.h>
int
int i;
i;
double
double d;
d;
main(){
main(){
i=2;
i=2;
d=(double)i;
d=(double)i;
printf("%f¥n",d);
printf("%f¥n",d);
}}
計算式中に複数の型が現れるときは、
優先順位に従って計算結果の型が決まる
int 型の変数 i の値を
double 型に変換したのち、
d に代入。
優先順位
int → (unsigned int →) long → (unsigned long →)
d=i としたときと同じ。
float → double → long double
気にしなくてもプログラムを書
くことができる場合も多い。
しかし、型変換を意識しない
といけない場合もある。
15/59
例:
 int型 + long型 = long型
 int型 + double型 = double型
演習:型変換(2)
演習:型変換(1)
実行し、何故そのような結果に
なるか、考えましょう
#include
#include <stdio.h>
<stdio.h>
main(){
main(){
printf("001->
printf("001-> %f¥n",5.0/4.0);
%f¥n",5.0/4.0);
printf("001->
printf("001-> %f¥n",5/4);
%f¥n",5/4);
printf("002->
printf("002-> %f¥n",5/4.0);
%f¥n",5/4.0);
printf("003->
printf("003-> %f¥n",(double)5/4);
%f¥n",(double)5/4);
printf("004->
printf("004-> %f¥n",(double)(5/4));
%f¥n",(double)(5/4));
}}
1 2
x
2
を計算しようと思い、次のプログラムを書いた。
#include<stdio.h>
#include<stdio.h>
#include<math.h>
#include<math.h>
main(){
main(){
double
double x=5,y;
x=5,y;
y=1/2*pow(x,2);
y=1/2*pow(x,2);
printf("%f¥n",y);
printf("%f¥n",y);
}}
実行して、結果を示しなさい。 もし、意図した値が出ていなかっ
たなら、出るように修正しなさい。
18/59
構造化プログラミング
 全体の処理を、複数のサブルーチンの組み合わ
せとして記述するプログラミング手法。
 構造化プログラミングでは、処理は上から順番に
実行されていく。
 プログラムの流れは、基本的に次の3つしかない。
1. 順次:順番に実行していく
2. 分岐:条件に従って、行う処理内容を変える。
3. 反復:ある条件が満たされている間、繰り返す。
構造化プログラミングと
構成要素
19/59
C言語における分岐、反復
構造化プログラミングのメリット
 全体の処理を、複数のサブルーチンの組み合わせと
して記述できるので、書く際にわかりやすい。
 順次・分岐・反復しかないため、人間がプログラムの
処理の流れを追うときに、わかりやすい。
構造化プログラミングの場合の例
構造化プログラミング以外の場合の例
略
10
略
10 for
for i=0
i=0 to
to 10
10 上から下に
main(){
20
main(){
流れるとは
20 print
print ii
基本的に、
int
i;
30
int i;
限らない
上から下に
30 next
next ii
for(i=0;i<10;i++)
40
for(i=0;i<10;i++)
流れる
40 end
end
printf("%d¥n",i);
50
printf("%d¥n",i);
50 goto
goto 10
10
if(i==10)
60
if(i==10)
60 if
if i=10
i=10 then
then 70
70 else
else 40
40
printf("%d¥n",i);
70
print
printf("%d¥n",i);
70 print ii
}}
 C言語におけて、分岐・反復を行うには、次のような
制御命令を使用する。
 反復:
 for
 while
 分岐:
 if
 switch
 順次・分岐・反復の枠に入らない goto もあるが、
普通は使用しない。
for
演習:for
for(式1;式2;式3){
文
}

式1
式2
No
以下のように実行される
1. 式1を行う。
2. 式2を評価した結果が
真であるなら3に進む。
偽ならfor文を終了する。
3. 文を実行する。
4. 式3を行い、2に戻る。
Yes
文
式3

break があると、そこから for
の外までジャンプする。
01:
01:
02:
02:
03:
03:
04:
04:
05:
05:
06:
06:
07:
07:
08:
08:
09:
09:
10:
10:
11:
11:
#include<stdio.h>
#include<stdio.h>
int
int main(){
main(){
int
int i,x;
i,x;
}}
どのように処理が流れていくかを
表に書きましょう。
それぞれの行が実行されたとき、
変数の値がどうなるか、
表に書きましょう。
x=0;
x=0;
for(i=0;i<4;i++){
for(i=0;i<4;i++){
x=x+i;
x=x+i;
}}
printf("%d
printf("%d %d
%d ¥n",i,x);
¥n",i,x);
while
演習:while

while( 式 ){
文
}
No
式1
Yes

文
01:
01:
02:
02:
03:
03:
04:
04:
05:
05:
06:
06:
07:
07:
08:
08:
09:
09:
10:
10:
11:
11:
12:
12:
13:
13:
以下の様に実行される。
1. 式を評価する。結果が、
真なら2に進む。
偽ならwhileを終了する。
2. 文を実行する。
3. 1に戻る。
文中にbreak があると、
while を終了する。
if~else
if(式1){
文1
}else{
文2
}
式1
No
01:
01:
02:
02:
03:
03:
04:
04:
05:
05:
06:
06:
07:
07:
08:
08:
09:
09:
10:
10:
11:
11:
12:
12:
13:
13:
次のように実行される。
1. 式1を評価する。結果が、
真である場合、2に進む。
偽である場合、3に進む。
2. 文1を実行し、4に進む。
3. 文2を実行し、4に進む。
4. if文を終了する。
Yes
文2

else 以降は省略しても良い。
switch文
switch(整数式){
case ラベル1:
文2
default:
文3
}
#include<stdio.h>
#include<stdio.h>
int
int main(){
main(){
int
int i,t;
i,t;
}}
どのように処理が流れていくかを
表に書きましょう。
それぞれの行が実行されたとき、
変数の値がどうなるか、
表に書きましょう。
for(i=0;i<4;i++){
for(i=0;i<4;i++){
if(i%2){
if(i%2){
printf("%d
printf("%d is
is odd
odd ¥n",i);
¥n",i);
}else{
}else{
printf("%d
printf("%d is
is even
even ¥n",i);
¥n",i);
}}
}}
switch文の例


文1
case ラベル2 :
}}
i=1;
i=1;
x=0;
x=0;
while(i<5){
while(i<5){
x*=i;
x*=i;
i++;
i++;
}}
printf("%d
printf("%d %d
%d ¥n",i,x);
¥n",i,x);
演習:if

文1
どのように処理が流れていくかを
#include<stdio.h>
#include<stdio.h> 表に書きましょう。
それぞれの行が実行されたとき、
int
int main(){
main(){
変数の値がどうなるか、
int
int i,x;
i,x;
表に書きましょう。




複数の分岐を行う際に使用。
整数式を評価し、対応するラ
ベルまでジャンプします。
対応するラベルが無い場合、
defaultにジャンプします。
ラベルの数は任意です。
defaultは省略可能です。
途中で抜けるときは、berak
を用います。
29/59
#include<stdio.h> •
•
(略)
•
int t;
対応するラベルまでジャンプ
対応するラベルがないとdefaultにジャンプ
break で switch文の外に
scanf("%d",&t);
switch(t){
t=1のとき t=2のとき t=3のとき t=4のとき
case 1: 文1
case 2: 文2; break;
case 3: 文3
}
}
default:文3
30/59
演習:switch
#include<stdio.h>
#include<stdio.h>
int
int t;
t;
メモリとポインタの概念
scanf("%d",&t);
scanf("%d",&t);
switch(t){
switch(t){
case
case 1:
1: printf("April
printf("April ¥n");
¥n");
case
case 2:
2: printf("May
printf("May ¥n");
¥n");
break;
break;
case
case 3:
3: printf("June
printf("June ¥n");
¥n");
default:
default: printf("July
printf("July ¥n");
¥n");
}}
ビットとバイト


メモリとアドレス
計算機内部では、データは2進数で保存している。
計算機は、メモリにデータを蓄えている。
 bit
1bit
0 もしくは 1 のどちらかを保存
 byte
1bitが8つ集まっている。
1byte


byte が、メモリの基本単位として使用される。
メモリの概念図
メモリは、1byteを保存で
きる場所が大量にある。
0000
0001
0002
それぞれの場所には、
0003
アドレスがふられている。
0004
0005
0006
アドレスがふられている
C言語の変数とメモリ

アドレスの参照とは
C言語で用いる変数等も、実際の値はメモリ上にある。
 メモリ上のどこに置くかとかは、OSやコンパイラが
適時やってくれる。
0000
0001
0002
0003
0004
これは此処
に入れるか
変数T
計算機
変数Tを
使用と・・・
人

C言語では、実際にどこにデータが保存されているの
か、プログラム中で参照できる。
0000
0001
0002
0003
0004
変数Tの
アドレスは?
計算機
変数T
0002です
人
アドレスの参照の方法
アドレスにある値の参照
変数の前に & をつけると、その値をどこに保存して
いるか(アドレス)を参照できる

例: #include
#include <stdio.h>
<stdio.h>
その場所に入っている値は何?
main(){
main(){
int
int i;
i;
}}
『どこに保存されているか』はわかる。
 次にやりたいことは?
アドレスの前に * をつけると、そのアドレスに保存
している値を参照できる
pirntf("%u¥n",&i);
pirntf("%u¥n",&i);

更に、C言語では、アドレスを保存する型も存在する。
&i とすることで、i が保存されているアドレスを参照できる。
ポインタとアドレス




ポインタ
ポインタの宣言(1)
ポインタ → アドレスを保存している変数です。
このポインタを型として宣言することができます。
整数型や文字型と合わせて宣言されます。
『変数 poi はアドレスである』と宣言するのではない!。
『変数 poi は整数型の変数を保存しているアドレス』
『変数 poi は文字型の変数を保存しているアドレス』
のように、どの型を保存しているアドレスなのかを区別。
ポインタの宣言の仕方
例: #include
#include <stdio.h>
<stdio.h>
*poi_01は整数型である。
main(){
main(){
int
int i;
i;
int
int *poi_01;
*poi_01;
int
int arr[10];
arr[10];
}}
poi_01の部分が
整数型のデータを保存する
アドレスを保存するポインタ
となる。
宣言するときに * をつけると、
* の次の文字は、ポインタになる。
ポインタの宣言(2)
#include
#include <stdio.h>
<stdio.h>
main(){
main(){
int
int i;
i;
int
int *poi_01;
*poi_01;
int
int arr[10];
arr[10];
}}
整数型の変数 i を宣言
整数型の変数 *poi_01 を宣言
poi_01はアドレス
サイズ10の整数型の配列
arrは配列の最初の要素のアドレス
アドレスを参照するには
int i;
サンプルプログラム
&i
値を参照するには
i
int *poi_01; poi_01(または &*poi_01)
*pot_01
int arr[10];
arr[0]
arr
#include
#include <stdio.h>
<stdio.h>
int
int main(){
main(){
unsigned
unsigned int
int i=101;
i=101;
unsigned
unsigned int
int *poi_01;
*poi_01;
unsigned
unsigned int
int arr[10]={103,2,3,4,5,6,7,8,9,10};
arr[10]={103,2,3,4,5,6,7,8,9,10};
*poi_01=104;
*poi_01=104;
printf("%u¥n",i);
printf("%u¥n",i);
printf("%u¥n",&i);
printf("%u¥n",&i);
printf("%u¥n",*poi_01);
printf("%u¥n",*poi_01);
printf("%u¥n",poi_01);
printf("%u¥n",poi_01);
printf("%u¥n",arr);
printf("%u¥n",arr);
printf("%u¥n",&arr[0]);
printf("%u¥n",&arr[0]);
}}
来週以降にやること
 関数と値渡し、アドレス渡し
 スコープ
 構造体
おわりに
43/59