今日やること 基礎演習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
© Copyright 2024 Paperzz