Internet Start Page  TOP  
 Road of Developers
 
 


================================================================================

	Load of Developers C Launguage  ---- Vol. 2            I-ichirow Suzuki

================================================================================


前回の復習から・・・・・・

1 文字の表示
2 変数の内容表示
3 配列 こ
4 アドレスとポインタ
5 配列とポインタ
6 文字の操作
7 プログラムにおける処理の流れの制御
8 関数呼び出し
9 データの入出力


//////////////////////////////////////////////////////////////////////////////
//////////////////
1 文字の表示

#######################
#include <stdio.h>
main() {

	printf("ABC\n") ;

} // End main() ;
-----------------------
ABC
########################

#! ヘッダ
	入出力の機能を利用する際は、それに関する様々な情報が格納されているiostr
	eam.hの内容を#include指令で取り込まなければなりません。なおこの様なフ
	ァイルをヘッダ(header)と呼び、#include指令によって、ヘッダの内容を取
	り込むことをインクルードすると言います。
	今回は printfを使うので ヘッダは <stdio.h>にしてあります。

#!  "main()"はmain関数という
	C言語のプログラムにはこのmain関数という物が必要でこのmain関数の中に書
	かれた内容から処理が始まっています。

#! "{}" はmain関数の範囲を示す
	中括弧の中がmain関数の内容です

#! インデント
	Cのプログラムには行の概念がありません。
	ですから1つの文を複数行に分けて書く事も、また逆に複数の文を1行にまと
	めて書く事も出来ます。

		main(){printf("ABC\n");}

	しかしこれでは大変読みにくくなってしまいますので、通常は関数内部の文の
	先頭に空白を入れて読みやすくします。この段付けをインデントと言います。

#! "printf"は画面への表示命令
	printfで始まるこの行をprint文と言います

#! 表示内容は "ABC"
	表示させる内容は括弧とダブルコーテーションで囲まれた部分のうち、ABCの
	文字です

#! "\n"は改行の意味を表すエスケープシーケンスと言います。
	コンピュータによってはキーボードに\マークの無い場合があります。
	その場合はバックスラッシュを代用して下さい。

#! 行の終わりには ";"を入れる
	行の終わりには必ず " ; "セミコロンを付けます。これがないとエラーになり
	ます。

///////////////////////////////////////////////////////////////////////////////
///////////////////////////
2 変数の内容表示

################################
#include <stdio.h>
main() {
	int a ;

	a = 1 + 2 ;

	printf("%d\n",a) ;

} // End main() ;
--------------------------------
3
#################################

#! このプログラムはaという変数に1 + 2 の結果を代入し、その値を表示するプログラ
ムです

#! 入出力機能stdio.hをincludeします。

#! main関数が始まります。

#! "a"の事を変数という
	C言語ではaとかbとか言うアルファベットに色々な値を代入出来ます。
	この値を代入するaとかbとかを変数と言います。
	変数とは値を入れる箱の様な物です。

#! "int a"を変数の宣言と言う
	変数を使用する際には変数の型の宣言をしなければなりません。
	ここではaをint型の変数として宣言しています。

#! 変数"int"は整数の事を意味する
	int型とは、正数を入れる変数の型です

	intは	整数
	float 	実数
	char	文字列
	double	高い精度が必要な時の実数用

#! "%d"は変数を整数型で表示しなさいという意味

	int	%d 整数
	flort	%f 実数
	char	%s 文字列

#! "a"は変数の指定
	実際に表示する変数の指定は、" "の外でカンマの後に行います。

#! 四則演算
	+	足し算
	-	引き算
	*	かけ算
	/	わり算


//////////////////////////////////////////////////////////////////////////////
////////////////////////
3 配列

#######################################
#include <stdio.h>
main() {
	float a[3] ;

	a[0] = 10.5 ;
	a[1] = 20.2 ;
	a[2] = 30.3 ;

 	printf("%f\n%f\n%f\n",a[0],a[1],a[2]);

} // End main() ;
--------------------------------------
10.50000
20.20000
30.30000
#######################################

#! 入出力機能 stdio.hをincludeします。

#! main関数が始まります

#! "float"で 実数系の変数宣言
	floatと言うのは、実数型の変数の宣言です。
	小数点を含む数字はこの実数型の変数に代入しなければなりません。

#! "a[3]"は3種類の配列の宣言
	これによって a[0], a[1], a[2]と言う変数が3つ同時に用意されます。

	a[0] = 10.5 ;		/* 変数a[0] */
	a[1] = 20.2 ;		/* 変数a[1] */
	a[2] = 30.3 ;		/* 変数a[2] */

#! %fで3つの変数を実数で表示
	これは変数を実数型で表示しろと言う命令です。
	実数型の変数を表示させたい時にはこの%fを使います。


///////////////////////////////////////////////////////////////////////////////
///////////////////////////
4 アドレスとポインタ

########################################
#include <stdio.h>
main() {
	int a ;
	int *z ;

	a = 10 ;
	z = &a ;

	printf("%d\n",*z) ;
} // End main() ;
------------------------------------------
10
#########################################

#! このプログラムはaに代入した10をポインタを使用して表示する物です。

#! 入出力機能 stdio.hをincludeします。

#! main関数が始まります

#! int 型変数 a, *zを宣言します。

#! 値 10を aに代入します。

#! &aはaの値が記憶されている住所(address)
	まずこの&aに着目します。
	aと言う変数には10と言う正数の値が代入されています。
	&aにはこのaの値が記憶されている場所(記憶領域)の番号が代入されていま
	す。
	この記憶領域の番号をアドレスと言います。

		&a = アドレス

	コンピュータ内で変数のaの値(=10)が記憶されている場所の番号


#! 次にポインタです。 ポインタの型宣言には、変数の前に*(アスタリスク)を付け
ます。
	この*はかけ算の記号にも使われます。使われる状況によって同じ記号が別の
	意味を持ちますので、注意して下さい。

	このポインタは変数のアドレスを記憶するための変数です。
	ここではポインタzに変数aのアドレスである&aを代入しています。

		z = &a

	*zはアドレスz(=&a)の場所に記憶されている変数aの値、すなわち10を示しま
	す。
	従ってこのprint文で10が表示される事になります。

	*z = z = &a = a = 10

==============================================================================

###########################################
# include <stdio.h>
main() {
	int a ;
	int *z ;

	a = 10 ;
	z = &a ;
	*z = 20 ;

	printf("%d\n,*z) ;
} //End main() ;
-------------------------------------------
20
###########################################

#! 入出力機能 stdio.hをincludeします。

#! main関数が始まります。

#! int型変数 a, *zを宣言します。

#! 値10をaに代入します。

#! ポインタzにまず変数aのアドレス(&a)を代入しています。

###############こうしておくと*zに値を直接代入出来ます。############

	これはzにaのアドレス(すなわち&a)が既に入力されており、その&aの記憶領
	域(すなわちa)に入っているのはプログラマが任意に設定した値(すなわち10
	)なので、これを20に書き換えても一向に問題無いのです。

	そして
	*z = 20
	の様に書き換えるとaの値も自動的に20に書き変わってしまうのです。


///////////////////////////////////////////////////////////////////////////////
////////////////////////
5 配列とポインタ

##############################################
# include <stdio.h>
main() {
	int a[3] ;
	int *z ;

	a[0] = 10 ;
	a[1] = 20 ;
	a[2] = 30 ;

	z = a ;		// a = &a[0]

	printf("%d,%d,%d\n",*z,*(z + 1),*(z + 2)) ;
	printf("%d,%d,%d\n",*z,*z + 1,*z + 2) ;
} // End main() ;
---------------------------------------------
10,20,30
10,11,12
#############################################

#! このプログラムではprint分の1行目と2行目で表示が異なります。
なぜこうなるのでしょうか?

#! 入出力機能 stdio.hをincludeします。

#! main関数が始まります。

#! int型変数aの配列を3つ用意します

#! 用意した3つの配列に それぞれの値 10, 20, 30を代入します。
	配列でa[3]を宣言した場合、aは配列の先頭のa[0]のアドレスを示します。

#! aの値を ポインタzに代入します。

	z = a = &a[0]
	z + 1 = &a[1]
	z + 2 = &a[2]

	するとアドレスaの配列とポインタzの値は等しくなります。

#! 従って 	*z は a[0] の値である 10 を、
		*(z + 1) は a[1] の値である20を、
		*(z + 2) はa[2]の値である30を示す事になります。

#! 一方 *z + 1はa[0]に1を加えた値ですから11に
	*z + 2はa[0]に2を加えた値ですから12になります。

//////////////////////////////////////////////////////////////////////////////
//////////////////////////
6 文字の操作

######################################
#include <stdio.h>
main() {
	char a[3] ;

	a[0] = 'A' ;
	a[1] = 'B' ;
	a[2] = 'C' ;

	printf("%c%c%c\n",a[0],a[1],a[2]) ;
} // End main() ;
--------------------------------------
ABC
#######################################

#! 1文字ごとに操作する方法と、複数の文字をまとめて操作する方法があります。
まずは1文字ごとの操作です。

#! 入出力機能 stdio.hをincludeします。

#! main関数が始まります。

#! 文字を代入するための変数はchar型という型で宣言します。
ここではchar型の配列を宣言しています。

#! 配列を3つ用意し、それぞれの文字列を配列に代入しています。

#! 配列の各要素にA,B,Cの文字を1文字ずつ代入してます。
このときは代入する文字を' '(シングルコーテーション)で囲みます。

#! 文字列を1文字ずつ表示するときは%sを使います。

	char 型の時は %s

#########################################
#include <stdio.h>
main() {
	char a[4] ;

	a[0] = 'A' ;
	a[1] = 'B' ;
	a[2] = 'C' ;
	a[3] = '\0' ;

	printf("%s\n",a) ;
} // End main() ;
------------------------------------------
ABC
###########################################

#! まとまった文字を文字列と言います。
aに対する表示命令だけでABCの3文字が表示されました。

#! 入出力機能 stdio.hをincludeする。

#! main関数が始まる

#! char型変数 a の配列を4つ準備

#! 4つの配列に文字を代入

#! 最後の配列にまとめる文字の最後として\0(ヌル文字)を代入

#! この\0によって文字列の区切りをつけます。
	従って文字列を代入する配列のよう素数は8文字数+1)以上必要です。
	代入したい文字はA,B,Cの3文字ですから、ここでは要素数を4にしました。

#! 文字列として表示するためには%sを使用します。
	この%sは、示されたアドレスに記憶された文字からヌル文字の直前までの文字
	(この場合AからCまで)を表示しろと言う命令です。
	これによりAとCの中間にあるBも含め、ABCと表示されます。


#########################################
#include <stdio.h>
main() {
	static char a[] = "ABC";

	printf("%s\n",a) ;
} // End main() ;
------------------------------------------
ABC
##########################################

#! 前の例の様に1文字ずつ代入するのは大変です。
そこで複数の文字をまとめて代入する方法があります。
	static を付けて変数の型宣言をし(この場合はchar型の配列を宣言)
	この宣言と同時に"   " で代入したい文字列を代入します。
	この方法を初期化と言います。

#! このやり方では配列の数を省略する事も出来ます。
省略しても自動的に代入した文字数にヌル文字1個分の記憶領域が確保されます。

##########################################
#include <stdio.h>
main() {
	char *a ;

	a = "ABC" ;
	printf("%s\n",a) ;
} // End main() ;
------------------------------------------
ABC
###########################################

#! ポインタを使用して複数の文字を一度に代入するやり方です。
配列を使用した場合と同様にABCの文字が表示されます。

#! I/O stdio.h をinclude

#! main関数始まる

#! ポインタで変数を宣言

#! ポインタに"  "ダブルコーテーションで代入したい文字列を代入します。
	ここで注意したいのはaに代入するのであり、*aに代入するのでは無い事です。

###########################################
#include <stdio.h>
#include <string.h>
main() {
	static char a[] = "ABC" ;
	char b[4] ;

	strcpy(b,a) ;
	printf("%s\n",b) ;
} // End main() ;
------------------------------------------
ABC
###########################################

#! bを表示させたにもかかわらず、aに代入したABCが表示されています。

#! strcpyがaの内容をbへコピーしなさいと命令しているのです。

	a = &a[0] 	A	→	b = &b[0]	A
	&a[1]		B	→	&b[1]		B
	&a[2]		C	→	&b[2]		C
	&a[3]		\0	→	&b[3]		\0

#! そのためにはコピー先の変数であるbを文字型の配列として宣言しておく必要があり
ます。
	その時の配列の要素数はコピーする文字数+1個分かそれ以上の数にします。

============================================================================

#############################################
#include <stdio.h>
#include <string.h>
main() {
	static char a[] = "ABC" ;
	char *b ;

	strcpy(b,a) ;
	printf("%s\n",b) ;
} // End main() ;
----------------------------------------------
Error !
#############################################

実行するとエラーになります。
コピー先にポインタを指定する事は出来ません。
コピー元がポインタである事は問題ありません。

		↓

#############################################
#include <stdio.h>
#include <string.h>
main() {
	static char a[] = "ABC" ;
	char *b ;

	b = a ;
	printf("%s\n",b) ;
} // End main() ;
----------------------------------------------
ABC
#############################################

#! bがポインタの場合、単にb = aとします。


//////////////////////////////////////////////////////////////////////////////
///////////////////////////////////
7 プログラムにおける処理の流れの制御


分岐制御
************
if
************

#########################################
#include <stdio.h>
#include <string.h>
main() {
	int i ;
	i = 1 ;

	if(i == 0)	{
		printf("0です\n") ;
	} // End if(i == 0)

	if(i == 1)	{
		printf("1です\n") ;
	} // End if (i== 0)

} // End main() ;
-----------------------------------------
1です
##########################################

このプログラムでは2つあるprint分の表示命令のうち、「1です」の表示だけが実行
されます。

#! hederをinclude

#! main() から始まる

#! int 型変数 i を宣言

#! 整数値 1 を i に代入

#! もしi=0なら一つ目の{ }内を実行

#! もしi=1なら2つ目の{ }内を実行

#! if(i==0)の条件式の後に ; はつけない
	== は 等しいという意味です

#! 最初のif文は i=0でないので実行されない

#! 2つ目のif文は i=1なので実行される

#! 1です が表示される

==============================================================================

************
if else
************

##############################################

#include <stdio.h>
#include <string.h>

main() {
	int i ;
	i = 1 ;

	if(i == 0)	{
		printf("i = 0\n") ;
	}	else	{
		printf("i is no 0\n") ;
	} // End if(i == 0) else
} // End main() ;
-------------------------------------------------
i is not 0
#################################################

このプログラムはelseの下の中括弧内のprint文が実行され、i is not 0 が表示されま
す。

#! Hederをinclude

#! main() から始まる

#! int型変数 i を宣言

#! 整数値1を 変数iに代入

#! もし、i == 0 であれば 最初の中括弧内の内容を実行

#! else は if と対で使用されます。
	elseの後ろの中括弧内の内容はif文の内容が正しくない時に実行されます。
	従ってelseの中のprint文のみが実行され、i is no 1が表示されるのです。

###################################################
#include <stdio.h>
#include <string.h>
main() {
	int i ;
	i = 1 ;

	if(i == 0)	{
		printf("i = 0\n") ;
	} // End if(i == 0)
	else if(i == 1)	{
		printf("i = 1\n") ;
	} // End if (i == 1)
} // End main() ;
----------------------------------------------------
i = 1
####################################################

このプログラムはelse if の後ろの中括弧内のprint文のみが実行されます。

#! else if分の後ろの中括弧は、直前のif文の括弧内が正しくなく、かつelse ifの後
ろの括弧内が正しい時に初めて実行されます。

#! Header をinclude

#! main()から始まる

#! int型変数 i を宣言

#! 整数値1を変数i に代入

#! もしi == 0であれば最初の中括弧内を実行

#! そうではなくなおかつ i == 1である場合は 次の中括弧内を実行

==============================================================================

************
strcmp if
************

################################################
#include <stdio.h>
#include <string.h>
main() {
	static char a[] = "ABC" ;
	static char b[] = "ABC" ;

	if(strcmp(a,b))	{
		printf("different\n") ;
	} // End if (strcmp(a, b)

	if(!strcmp(a,b)) {
		printf("same\n") ;
	} // End if (!strcmp(a, b)
} // End main() ;
------------------------------------------------
same
################################################

このプログラムではsameのみが表示されます。

#! Headerをinclude

#! main()から始まる

#! static chatで 配列 を宣言 と同時に文字列を代入

#! strcmpでは括弧内の2つの変数で示されるアドレス内に代入されている文字列同士
が等しく無い時に真になります。

#! a, bに示されているアドレス内には共にABCという文字列が代入されているので両者
は等しく、従ってこのif文の条件式は真で無いためこのprint文は実行されません。

#! 次にこの条件式ではstrcmpの前に!マークがあります。この!マークは条件の否定な
ので、今度はアドレスa, bの中に代入されている文字列が等しい時に真になります。

#! a, bに示されているアドレス内には共にABCという文字列が代入されているので、if
文内の条件式は真になりこのprint文が実行されます。

==============================================================================

************
switch
************

#############################################
#include <stdio.h>
#include <string.h>
main() {
	int i ;
	i = 1 ;

	switch(i)	{
		case 0 ;
			printf("i=0\n") ;
			break ;
		case 1 ;
			printf("i=1\n") ;
			break ;
		case 2 ;
			printf("i=2\n") ;
			break ;
	} // End switch
} // End main() ;
----------------------------------------------
i=1
###############################################

このプログラムではcase1の直後に書かれたprint文のみが実行されます。

#! Headerをinclude

#! main()から始まる

#! int型変数 i を宣言

#! 整数値1を変数 i に代入

#! switch文では括弧内の変数、この場合ですとi の値によって直後の中括弧での実行
場所が決定されます。なおswitch文の行末には;(セミコロン)を付けません。

#! i の値と case文の値が同じであればその行以降の記述が実行されます。

#! breakによりswitch文の中括弧から脱出します。これにより、case2以下は全く実行
されません。(breakがないとcse2の下のprint文も実行されてしまいます)


============================================================================

繰り返し制御

************
for loop
************

#################################################

#include <stdio.h>
#include <string.h>

main() {
	int i ;
	int a[3] ;

	for(i = 0 ; i < 3 ; i++)	{
		a[i] = 10 * i ;
	} // End for

	printf("%d,%d,%d\n",a[0],a[1],a[2]) ;
} // End main() ;

--------------------------------------------------

0,10,20

##################################################

a[0], a[1], a[2]にそれぞれ0,10,20が代入され、それがprint文で画面に表示されまし
た。
このa[0], a[1], a[2]にそれぞれ1, 10, 20を代入する事がforループで行われたのです
。

#! Headerをinclude

#! main()から始まる

#! int型の変数iを準備

#! int型変数aを配列3つで準備

#! forループでは括弧内の条件で中括弧内の処理を繰り返します。

#! i = 0で変数iの初期値を設定します。ここでは0にしました。

#! i < 3は繰り返し条件です。i < 3の時に中括弧内の処理が行われます。

#! i = 0 < 3ですから、a[0] = 1 * 0 が実行されa[0]に0が代入されます。

#! 続いてi++が実行され i = 2になります。
	++の事をインクリメントと言います。一つ加えると言う意味です。
#! i = 2 < 3ですから処理が繰り返され、a[2] = 10 * 2が実行されます。

#! 続いて i++ が実行され i = 3になります。

#! i = 3より i < 3では無いので {  } を抜け出します。

#! print文が実行されます。

============================================================================

************
2重 for loop
************

######################################################
#include <stdio.h>
#include <string.h>
main() {
	int i, j ;
	int a[2][3] ;

	for(i = 0 ;i < 2 ;i++)	{
		for(j = 0 ;j < 3 ;J++)	{
			a[i][j] = i * 10 + (j + 1) ;
		} // End for(j = 0 ;j < 3 ; J++)
	} // End for (i = 0 ; i < 2 ; i ++)

	printf("%d, %d, %d\n",a[0][0],a[0][1],a[0][2]) ;
	printf("%d, %d, %d\n",a[1][0], a[1][1], a[1][2]) ;
} // End main() ;
---------------------------------------------------------
1, 2, 3
11, 12, 13
#########################################################

forループは何重にも入れ子にして使用出来ます。

#! Headerをinclude

#! main()関数から始まる

#! int型変数 i と j を準備

#! int型変数aを準備し、2つの配列と、3つの配列を準備

#! 外側のforループでi = 0が設定され、その状態で内側のforループでj = 0, j = 1, j
 = 2が順次実行されます。

#! その後外側のforループでi が1に設定し直され、その状態で再び内側のforループでj
 = 0, j = 1, j = 2が実行されます。

#! これによりa[0][0]には1が、a[0][1]には2が、a[0][2]には3が、そしてa[1][0]には1
1が、a[1][1]には12が、a[1][2]には13が代入され、その結果が表示されます。

===============================================================================

************
for loop break
************

##################################################
#include <stdio.h>
#include <string.h>
main() {
	int i ;
	int a ;

	a = 0 ;

	for(i = 0 ;i < 10 ; i++) {
		a = a + 1 ;

		if(a == 5)
		break ;
	} // End for (i = 0 ; i< 10; i++)

	printf("%d\n",a) ;
} // End main() ;
-----------------------------------------------------
5
#####################################################

#! Headerをinclude

#! main()から始まる

#! int型変数iを宣言

#! int型変数aを宣言

#! aの値をforループの前で0に初期化

#! forループの中でaは処理が繰り返される度に1ずつ増加します。
forループは本来なら10回繰り返されるはずですから、aの値は10になるように思えます

	a = a + 1という式はコンピュータ言語独特の物で、普通は見慣れないと思い
	ます。この式の意味は、「この式が実行される前のaの値(右辺のa)に1を足
	し、これを新しいaの値(左辺のa)とする」と言う事です。

#! ところが、a == 5になるとif文の下のbreak文が実行され、forループの外に脱出し
てしまいます。

#! 従ってaの値は5までしか増加せず、その値がprint文で表示されます。

=============================================================================

************
for loop continue
************

#######################################################
#include <stdio.h>
#include <string.h>
main() {
	int i ;
	int a, b ;

	a = b = 0 ;

	for(i = 0 ; i < 10 ; i++)	{
		a = a + 1 ;

		if(i > = 5)
			continue ;

		b = b + 1 ;
	} // End for(i = 0 ; i < 10 ; i++)

	printf("%d,%d\n",a,b);
} // End main() ;
--------------------------------------------------------
10,5
########################################################

#! Headerをinclude

#! main()から始まる

#! int型変数iを準備

#! int型変数a, bを準備

#! a = b = 0でaとbの値を0に初期化

#! i の値を0に初期化、iの値が10より小さいときは1インクリメントする
要するにforループを10回繰り返すと言う事です。

#! a の値(0)に1を加えた値を左辺の変数aに代入する

#! 次のif文でiが5以上の時にはそれ以後の処理を中断してforループの最初に戻る

#! ここでは先程のbreakの代わりにcontinueが使われています。
このcontinueはforループの外へ脱出する代わりにそれ以後の処理(ここではb = b + 1)
を中断してforループの最初に戻ります。

#! 従って、a = a + 1は10回、b = b + 1は5回実行されるので、a は10,bは5になるの
です。

==============================================================================

************
while loop
************

###################################################
#include <stdio.h>
#include <string.h>
main() {
	int i ;
	int a ;

	a = 0 ;
	i = 0 ;

	while(i < 10)	{
		a = a + 10 ;
		i++ ;
	} // End while
	printf("%d\n",a) ;
} // End main() ;
----------------------------------------------------
100
####################################################

#! forループと同様にまずint型の変数を準備します。

#! 次にwhileループの前で、準備した変数に初期値を代入します。

#! whileループでは、括弧内の条件が成立する間、中括弧内の処理を繰り返します。

#! 中括弧内で条件式で使っている変数を変化させます。
この場合、繰り返しの度にiが1ずつ大きくなり、iが10になるとループの外へ脱出しま
す。

#! 従ってa = a + 1はi = 0からi = 9まで計10回繰り返されます。
aの初期値はwhleループの前で0に設定していますから、a = 10になります。
この10がprint文で表示されます。


///////////////////////////////////////////////////////////////////////////////
/////////////////////////////
8 関数呼び出し

*******************************************************************************
引き数によるデータの引き渡し
************

#############################################
#include <stdio.h>
#include <string.h>

int tasu(int x,int y) ;

main() {
	int a, b, c ;
	a = 2 ;
	b = 3 ;

	c = tasu(a, b) ;

	printf("%d\n", c) ;
} // End main() ;

int tasu(int x, int y) {
	int z ;
	z = x + y ;

	return z ;
} // End tasu() ;
---------------------------------------------
5

#############################################

関数呼び出しの中の値渡しという方法のさらにその中の引数を使ってデータを引き渡す
方法を説明します。

プログラムは 2 + 3の結果である5がcの値として画面に表示されます。

#! C言語のプログラムは関数と呼ばれる単位から構成されています。
これまでの例では全てmainという関数だけでしたが、このプログラムはmainという関数
とtasuという関数から構成されています。

#! C言語ではmain関数は必ず作ります。

#! それ以外の関数は必要に応じて作り、適当な名前を付ける事が出来ます。

#! main以外の関数は、どんな物を作るかを最初に宣言しなければいけません。
これを関数のプロトタイプ宣言と言います。

#! このプロトタイプ宣言は記述の最後に;(セミコロン)を付ける事を除いてその関数の
本体部分の1行目と同一にします。
今回の例では最初に宣言されたtasu()は
int tasu(int x, int y) ;
本文中にでてくるtasu()は
int tasu(int x, int y)
ですよね。

#! では一番上からint型変数tasu関数を宣言します。

#! main()から処理を開始します。

#! int型変数a, b, cを宣言します。

#! 整数2をaに代入します。

#! 整数3をbに代入します。

#! そしてtasu(a, b) ;をcに代入しますが、処理の途中で関数の名前を見つけるとその
関数を呼び出し、その関数の処理に移ります。
もう一つのtasu()関数へ処理を移します。

#! その際呼び出し側から引数と呼ばれる変数によって情報が伝えられます。
今回の例ではaの値がxに、bの値がyに代入されます。
この作業を引数の引き渡しと言います。

#! 受け取った引数の型の宣言をします。その際、呼び出し側より受け継ぐ変数の型に
合わせて宣言します。この場合は共にint型です。
(int x, int y)の部分です。


#! 処理の結果を返値としてreturnで返します。
この例ですとzの値をcに代入しています。尚この返値の変数の型(この場合返値はxな
のでint型)を件数の名前の前に付けて置く規則になっています。この場合だとtasu(int
 x, int y)の前のintです。

#! その後mainに処理が戻りprint文によってcの値として5が表示されます。

=============================================================================

*******************************************************************************
グローバル変数によるデータの引き渡し

##############################################

#include <stdio.h>
#include <string.h>

int a, b ;
int tasu() ;

main() {
	int c ;
	a = 2 ;
	b = 3 ;
	c = tasu() ;

	printf("%d\n", c) ;
} // End main() ;

int tasu() {
	int c ;
	c = a + b ;

	return c ;
} // End main() ;
-----------------------------------------------
5
################################################

次のプログラムでは引数を使用しないでも今度は正しい答えが表示されます。

#!  全ての関数の外側でa, bと言う変数が宣言されています。
この様に宣言した変数をグローバル変数と呼びます。

#! グローバル変数は全ての関数で共通して使用出来ます。

#! 従って、関数mainでa, bに代入した結果がそのまま関数tasuでも有効に使え、正し
い計算が実行されたのです。

#! この様にグローバル変数は引数を使わずにデータをやり取り出来るので便利ですが
、反面では変数の値がどこで変わったかを解読するのが大変、目盛りの消費が大きいと
言った欠点があります。

#! グローバル変数は使いすぎないようにしましょう。

==============================================================================

*******************************************************************************

アドレス渡し

##################################################

#include <stdio.h>
#include <string.h>

void tasu(int x, int y, int *z) ;

main() {
	int a, b, c ;
	a = 2 ;
	b = 3 ;

	tasu(a, b, &c) ;

	printf("%d\n", c) ;
} // End main() ;

void tasu(int x, int y, int *z) {
	*z = x + y ;
} // End tasu () ;
----------------------------------------------------
5

####################################################

次は関数呼び出しのうち、アドレス渡しと呼ばれる物です。
関数mainのcの値として関数tsuで実行したx + y の結果である5が表示されます。

#! まず関数を呼び出す時の引数にアドレスを含ませます。
この場合ですと&cがそれに当たります。

#! 呼び出される関数のほうでは渡されるアドレスはポインタ変数で受け取ります。
ここでは int *zです

#! この場合ですとz に &cが代入されます。

#! 次にこの行でzをアドレスとする記憶領域にx + yの値を代入しています。

#! zをアドレスとする記憶領域とはz = &cなので実はcのことです。

#! すなわちc にx + yの値が代入されるのです。
x はa をyはbを受けていますからx + y は5です。
従ってc に5が代入されます。

#! 関数tasuの処理が終わると再び関数mainに戻り、print文が実行されてcの値として5
が表示されます。

#! この様にアドレス渡しではreturnで返値を返す事無く呼び出し側の関数に結果を
繁栄させます。

#! 尚、この例のようにreturnで返値を返さない関数は方をvoid型にします。
main()も返り血なしで使用しています。
本来であれば void main(void)と言うように記述しますが、省略もできます。

#! 返値のない関数の場合はvoidを付けます。
#! 返値のないmain関数の場合は省略する事が出来ます。
#! 関数の()無いに引数がない場合も(void)を付けますが、省略も出来ます。

===============================================================================

*******************************************************************************

配列のアドレス渡し

#####################################################
#include <stdio.h>
#include <string.h>

void cast(int *z) ;

main() {
	int a[3] ;

	a[0] = 2 ;
	a[1] = 3 ;

	cast(a) ;

	printf("%d\n", a[2]) ;
} // End main() ;

void cast(int *z) {
	*(z + 2) = (*z) * (*(z + 1)) ;
} // End cast() ;
------------------------------------------------------
6

######################################################

今度は配列が関係します。
プログラムを実行するとa[2]としてa[0]*[1]の結果である6が表示されます。

#! まず、配列で変数を準備します。

#! 関数を呼び出す時の引数として配列の先頭アドレス(a = &a[0])を引き渡します。
cast(a) ;ですね

#! int *zがaをポインタとしてzで受けます。

#! するとzにはa[0]のアドレスが代入されます。

#! 	*z = a[0]
	*(z + 1) = a[1]
	*(z + 2) = a[2]
	と、なります。

#! 従って、a[2]にはa[1]とa[2]の和が代入されることになります。

#! a[2]を表示させると、2 * 3の結果である6が画面に現れます。

#! アドレス渡しの利点は、この用に配列の先頭アドレスa(=&a[0])を1つ引き渡すだけ
で、配列の善要素(この場合だとa[0], a[1], a[2]を参照出来る事です。

===============================================================================

########################################################
#include <stdio.h>
#include <string.h>

void tasu(int *x, int *y, int *y) ;

main(){
	int a[3], b[3], c[3] ;

	a[0] = 1 ; a[1] = 2 ; a[2] = 3 ;
	b[0] = 10 ;b[1] = 20 ;b[2] = 30 ;

	tasu(a, b, c) ;

	printf("%d, %d, %d\n", c[0], c[1], c[2]) ;
} // End main() ;

void tasu(int *x, int *y, int *z) {
	int i ;

	for(i = 0 ; i < 3 ;i++)	{
		*(z + i) = *(x + i) + *(y + i) ;
	} // End for
} // End tasu() ;
----------------------------------------------------------
11, 22, 33

##########################################################

プログラムを実行するとc[1]としてa[1] + b[1]の結果である11がc[2]としてa[2] + b[2
]の結果である22がc[3]としてa[3] + b[3]の結果である33が表示されます。

#! まず配列で変数を準備します。

#! 次に関数を呼び出す時に引数として、配列の先頭アドレスを引き渡します。

#! ここではaはa[0]の、bはb[0]の、cはc[0]のアドレスを示します。

#! 受ける側では、a, b, cをそれぞれポインタのx, y, zで受けます。

#! するとzはc[0]のアドレスが代入されるのでz + 1 はc[1]の、z + 2 はc[2]のアドレ
スに等しくなります。

#! 同様にxはa[0]の、x + 1はa[1]の、x + 2 はa[2]のアドレスに等しくなり、yはb[0]
の、y + 1はb[1]の、y + 2はb[2]のアドレスに等しくなります。

#! 従って*(z + i)はc[i]を、*(x + i)はa[i]を、*(y + i)はb[i]を示すことになります

#! 従ってこの行はc[i]にa[i] + b[i]を代入している事になります。

#! この様にして関数tasuの処理が終了すると処理は関数mainに戻り、
c[0]としてa[0] + b[0]の結果の11が、
c[1]としてa[1]+b[1]の結果の22が、
c[2]として a[2] + b[2]の 結果の33が表示されます。


///////////////////////////////////////////////////////////////////////////////
/////////////////////////////////
9 データの入出力

#############################################
#include <stdio.h>
#include <string.h>
main() {
	float a ;

	printf("a?\n") ;
	scanf("%f", &a) ;
	printf("%f\n", a) ;
} // End main() ;
--------------------------------------------
>a?
 5
 5.000000

#############################################

プログラムを実行すると画面にa?と表示されます。
次に画面に数字(この例では5)を入力してreturnキーを押すと、入力した数字が実数
形式で出力されます。

printf("a?\n") ;
#! このprint文でa?を画面に表示しています。
この表示が無いと、作業者が何をすべきなのかが解らないので必ず書いておきます。

#! scanfというのが、キーボードからの入力を変数に代入するための命令です。

#! scanfで入力する為には変数の型を指定しなければなりません。
ここでは実数型を指定しています。%fですね。

#! 次のどの変数に代入するかを指定します。
代入する変数の指定は&aです。この指定はアドレスで行います。

#! 最後のprint文でaの値を実数型で表示します。


///////////////////////////////////////////////////////////////////////////////
To be continue.... To Vol.3


==============================================================================


インターネットスタートページ 鈴木維一郎 石橋三重子
        
         
               
                   

©2000 kg-group Inc.