1 1
情報処理演習
第13回
2011年1月13日
工学部6・7・8・9・10組(奇数学籍番号)
担当: 長谷川英之
1. 配列データをmain以外の関数とやりとりする方法
2. データの型
構造体,共用体という新しいデータ型を学習します.
本日の講義の内容
2次元ベクトル
a(x, y)のノルム(長さ)d :
d
=
x
2+
y
2#include <stdio.h>
#include <math.h>
double dot(double x,double y)
{
return(sqrt(x*x+y*y));
}
main()
{
double x0,y0;
scanf(”%lf %lf”,&x0,&y0);
printf(”vector norm=%lf¥n”,dot(x0,y0));
}
プログラムh13.c
2次元ベクトルのノルムくらいなら変数を渡しても何とかなる
2次元ベクトルのノルム(長さ)を計算するプログラム
N 次元ベクトル a(x
0, x
1, ..., x
N-1)のノルムd :
2 1 2 1 2 0+
+
...
+
−=
x
x
x
Nd
#include <stdio.h>
#include <math.h>
#define N 5
double dot(double
vec[]
)
{
int i;
double d=0.0;
for(i=0;i<N;++i)
d=d+vec[i]*vec[i];
return(sqrt(d));
}
main()
{
int i;
double vec0[N];
for(i=0;i<N;++i)
scanf(”
%lf”,&vec0[i]);
printf(”vector norm=
%lf¥n”,dot(
vec0
));
}
プログラムh13-1.c
配列を渡したいときはこのように[]を付けて
定義(アドレス渡し,ということになる)
2 1 2 1 2 0 2...
−+
+
+
=
x
x
x
Nd
を計算
d
d
2=
として値を返す.
i=0からN-1までの5個の値を読み込んで対応
する配列要素vec0[i]に格納.
配列を渡すときは,配列の先頭
のアドレ(&vec0[0]=vec0)
を渡せば良い.
N 次元ベクトル(N >2)のノルムを計算するプログラム
#include <stdio.h>
#define N 3
void multar(float vec[], float a)
{
int i;
for(i=0;i<N;++i)
vec[i]=a*vec[i];
a=0.5;
}
main()
{
int i;
float a=2.5,vec0[N];
for(i=0;i<N;++i)
scanf(”
%f”,&vec0[i]);
printf(”*** input data ***¥n”);
printf(”a=
%f¥n”,a);
for(i=0;i<N;++i)
printf(”vec0[
%d]: %f¥n”,i,vec0[i]);
multar(vec0,a);
printf(”*** processed data ***¥n”);
printf(”a=%f¥n”,a);
for(i=0;i<N;++i)
printf(”vec0[
%d]: %f¥n”,i,vec0[i]);
プログラムh13-2.c
アドレス 0 1 2 3 4 5 6 7 8 メモリ内容 2. 1. 3. ① 配列vec0の各要素の値をキーボード入力 = vec0=&vec0[0] アドレス 0 1 2 3 4 5 6 7 8 メモリ内容 2. 1. 3. ② 関数multarをmainで呼び出しvec0のアドレスを渡す. = vec0=&vec0[0]=&vec[0] アドレス 0 1 2 3 4 5 6 7 8 メモリ内容 5. 2.5 7.5 ③ 配列vec (=vec0) の各要素をa (=2.5)倍する. = vec0=&vec0[0]=&vec[0]関数内で
配列
の内容を変えるとmainでも変更される
double
func(int a,
float *pr,
double x[])
関数の型: 値を
returnで返す
ときは
int
, float, double
な ど
.
返 さ な い
き は
v o i d
( 第 9 ~ 1 2 回 資 料 参 照 )
変数の内容を渡す
ときは
*
も[]も不要
.渡された変数
の内容は,関数中で変更さ
れない(第9回資料参照)
関数中で書き換えた内容を
main中でも有効にさせたい
ときは
*を付けポインタ変数
にする(第12回資料参照)
配列を渡したい
ときは,
[]を
付ける
.アドレス渡しになる
(第13回資料参照)
関数定義時
int a0;
float r;
double x0[10];
func(a0,&r,x0)
main関数中での呼び出し(コール)時
それぞれの変数・配列のmain中での定義
変数・配列のアドレスを渡して,渡した変数・配列が使用しているアドレスに
関数func中でデータを書き込ませる
→ main中でも同じ場所を参照するのでrとx0[i]は書き換えられた値となる
関数定義と呼び出し方のまとめ
⎪
⎪
⎪
⎪
⎪
⎪
⎩
⎪
⎪
⎪
⎪
⎪
⎪
⎨
⎧
⎪
⎩
⎪
⎨
⎧
⎪
⎩
⎪
⎨
⎧
型
共用体型
構造体型
配列
集合型
ポインタ
列挙型
点型,整数型,文字型
算術型・・・浮動小数
スカラ型
データ型
void
データの型(教科書第
9章)
文字型
char (メモリ上のサイズ:
1バイト
)
整数型
(符号つき(signed(省略可)),符号なし(unsigned)がある)
short (
2バイト
)
-32767~32767
(unsignedの場合:
0~65535
)
int, long (
4バイト
)
-21474836477~21474836477
(unsignedの場合:
0~42949672955
)
浮動小数点数型
float (単精度,
4バイト
)
±3.4×10
-38~±3.4×10
38double (倍精度,
8バイト
)
±1.7×10
-308~±1.7×10
308使い方
int
unsigned long
float
など
算術型
#include <stdio.h> main()
{
enum week {Sun,Mon,Tue,Wed,Thu,Fri,Sat}; enum week day;
int i; day=Sun; for(i=day;i<day+7;++i){ switch(i){ case 0: printf("Sunday¥n"); break; case 1: printf("Monday¥n"); break; case 2: printf("Tuesday¥n"); break; case 3: printf("Wednesday¥n"); break; case 4: printf("Thursday¥n"); break; case 5: printf("Friday¥n"); break; case 6: printf("Saturday¥n"); break; default: break; } } }
実行結果
[xxx]
% a.out
Sunday
Monday
Tuesday
Wednesday
Thursday
Friday
Saturday
値を明示しない場合は, 0 1 2 3 4 5 6列挙名がweekである列挙定数を定義
列挙型変数dayを定義
列挙型変数dayにSun(= 0を代入)
iをday(= 0)から
day+6(= 6)まで繰り返し
iの値が零のときの処理
iが0から6まで繰り返すので,
全てのケースに該当
列挙型を利用したプログラム例 enum.c
#include <stdio.h> main()
{
enum week {Sun=1,Mon,Tue,Wed,Thu,Fri,Sat}; enum week day;
int i; day=Sun; for(i=day;i<day+7;++i){ switch(i){ case 0: printf("Sunday¥n"); break; case 1: printf("Monday¥n"); break; case 2: printf("Tuesday¥n"); break; case 3: printf("Wednesday¥n"); break; case 4: printf("Thursday¥n"); break; case 5: printf("Friday¥n"); break; case 6: printf("Saturday¥n"); break; default: break; } } 値を指定した場合は(指定以降は順番に割当), 1 2 3 4 5 6 7
Sunが1
なので,
iをday(=
1
)から day+6(=
7
)
まで繰り返し
iは
1から7
まで繰り返すので,
i=0のケース(つまりSunday)
が表示されない
実行結果
[xxx]
% a.out
Monday
Tuesday
Wednesday
Thursday
Friday
Saturday
列挙型を利用したプログラム例 enum.c を変更
#include <stdio.h> main() { struct person{ int id; char name[40]; long phone; };
struct person student;
scanf(”%d %s %ld”,&student.id,student.name,&student.phone); printf(”%d %s %ld¥n”,student.id,student.name,student.phone); }
構造体名personを定義
3つの要素を持つ(任意の型を要素とできる)
構造体変数studentを定義
変数studentは3つの要素id, name, phoneを持つ
ピリオドをつけて
変数の要素を表す
int型なので&要 char型配列なので &不要 long型なので&要構造体型を利用したプログラム例 struct.c
#include <stdio.h> struct complex { double x; double y; };
struct complex conjg(struct complex z) { struct complex zz; zz.x=z.x; zz.y=-z.y; return(zz); } main() { struct complex z0,z1; z0.x=1.; z0.y=1.; z1=conjg(z0); printf(”complex conjugate of z0 = %lf %lf¥n”, z1.x,z1.y); }
関数の型(処理後に返す変数の型)や引数の型を,
定義した構造体の型とすることもできる.
構造体型を利用した複素数演算 cmpstr.c
#include <stdio.h> main() { union ic{ unsigned int a; unsigned short b[2]; }; union ic x; x.a=65535; printf(”%d %d¥n”,x.b[0],x.b[1]); }
共用体名icを定義.2つの要素を持つ.
実行結果
[xxx]
% a.out
65535 0
共用体の要素は,同じメモリの場所を使用する
この例の場合,
x.a=65535 の2進数表示: 11111111 11111111 00000000 00000000
※1バイト: 2進数8桁
変数a (int: 4バイト)
配列要素 b[0]
(short: 2バイト)
配列要素 b[1]
(short: 2バイト)
共用体変数xを定義
共用体型を利用したプログラム例 union.c
#include <stdio.h> main() { union ic{ unsigned int a; unsigned short b[2]; }; union ic x; x.a=65536; printf(”%d %d¥n”,x.b[0],x.b[1]); }