//////////////////////////////////////////////////////////////////////////////
//////////////////
1 文字の表示
#######################
#include <stdio.h>
main()
{
printf("ABC\n") ;
}
-----------------------
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) ;
}
--------------------------------
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"は変数の指定
実際に表示する変数の指定は、" "の外でカンマの後に行います。
#! 四則演算
+ 足し算
- 引き算
* かけ算
/ わり算
#! printfの第1引数(ひきすう)には、必ず文字列を置かなければなりません。
この文字列は特別な文字列なので、書式文字列と言います。
%dなどの変数は書式文字列の中に含めます。
%dなどの変数を変換支持子と言います。
printf("%d\n", 100 + 7) ;
↓
printf("変換支持子エスケープシーケンス" 100 + 7) ;
↓
printf("書式文字列", 100 + 7) ;
↓
関数("第1引数",第2引数) ;
===============================================================================
//////////////////////////////////////////////////////////////////////////////
////////////////////////
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]);
}
--------------------------------------
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) ;
}
------------------------------------------
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) ;
}
-------------------------------------------
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に書き変わってしまうのです。
すなわちプログラムをしたの様に変更してaを表示させる様にしてもやはり20
が表示されます。
##########################################
# include <stdio.h>
main()
{
int a ;
int *z ;
a = 10 ;
z = &a ;
*z = 20 ;
printf("%d\n,a) ;
}
------------------------------------------
20
##########################################
==============================================================================
///////////////////////////////////////////////////////////////////////////////
////////////////////////
5 配列とポインタ
##############################################
# include <stdio.h>
main()
{
int a[3] ;
int *z ;
a[0] = 10 ;
a[1] = 20 ;
a[2] = 30 ;
z = a ;
printf("%d,%d,%d\n",*z,*(z + 1),*(z + 2)) ;
printf("%d,%d,%d\n",*z,*z + 1,*z + 2) ;
}
---------------------------------------------
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]) ;
}
--------------------------------------
ABC
#######################################
#! 1文字ごとに操作する方法と、複数の文字をまとめて操作する方法があります。
まずは1文字ごとの操作です。
#! 入出力機能 stdio.hをincludeします。
#! main関数が始まります。
#! 文字を代入するための変数はchar型という型で宣言します。
ここではchar型の配列を宣言しています。
#! 配列を3つ用意し、それぞれの文字列を配列に代入しています。
#! 配列の各要素にA,B,Cの文字を1文字ずつ代入してます。
このときは代入する文字を' '(シングルコーテーション)で囲みます。
#! 文字列を1文字ずつ表示するときは%cを使います。
char 型の時は %c
==============================================================================
#########################################
#include <stdio.h>
main()
{
char a[4] ;
a[0] = 'A' ;
a[1] = 'B' ;
a[2] = 'C' ;
a[3] = '\0' ;
printf("%s\n",a) ;
}
------------------------------------------
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) ;
}
------------------------------------------
ABC
##########################################
#! 前の例の様に1文字ずつ代入するのは大変です。
そこで複数の文字をまとめて代入する方法があります。
static を付けて変数の型宣言をし(この場合はchar型の配列を宣言)
この宣言と同時に" " で代入したい文字列を代入します。
この方法を初期化と言います。
#! このやり方では配列の数を省略する事も出来ます。
省略しても自動的に代入した文字数にヌル文字1個分の記憶領域が確保されます。
=============================================================================
##########################################
#include <stdio.h>
main()
{
char *a ;
a = "ABC" ;
printf("%s\n",a) ;
}
------------------------------------------
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) ;
}
------------------------------------------
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) ;
}
----------------------------------------------
Error !
#############################################
実行するとエラーになります。
コピー先にポインタを指定する事は出来ません。
コピー元がポインタである事は問題ありません。
↓
#############################################
#include <stdio.h>
#include <string.h>
main()
{
static char a[] = "ABC" ;
char *b ;
b = a ;
printf("%s\n",b) ;
}
----------------------------------------------
ABC
#############################################
#! bがポインタの場合、単にb = aとします。
============================================================================
//////////////////////////////////////////////////////////////////////////////
///////////////////////////////////
7 プログラムにおける処理の流れの制御
分岐制御
************
if
************
#########################################
#include <stdio.h>
#include <string.h>
main()
{
int i ;
i = 1 ;
if(i == 0)
{
printf("0です\n") ;
}
if(i == 1)
{
printf("1です\n") ;
}
}
-----------------------------------------
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") ;
}
}
-------------------------------------------------
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") ;
}
else if(i == 1)
{
printf("i = 1\n") ;
}
}
----------------------------------------------------
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") ;
}
if(!strcmp(a,b))
{
printf("same\n") ;
}
}
------------------------------------------------
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 ;
}
}
----------------------------------------------
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 ;
}
printf("%d,%d,%d\n",a[0],a[1],a[2]) ;
}
--------------------------------------------------
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) ;
}
}
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]) ;
}
---------------------------------------------------------
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 ;
}
printf("%d\n",a) ;
}
-----------------------------------------------------
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 ;
}
printf("%d,%d\n",a,b);
}
--------------------------------------------------------
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++ ;
}
printf("%d\n",a) ;
}
----------------------------------------------------
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) ;
}
int tasu(int x, int y)
{
int z ;
z = x + y ;
return z ;
}
---------------------------------------------
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) ;
}
int tasu()
{
int c ;
c = a + b ;
return c ;
}
-----------------------------------------------
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) ;
}
void tasu(int x, int y, int *z)
{
*z = x + y ;
}
----------------------------------------------------
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]) ;
}
void cast(int *z)
{
*(z + 2) = (*z) * (*(z + 1)) ;
}
------------------------------------------------------
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]) ;
}
void tasu(int *x, int *y, int *z)
{
int i ;
for(i = 0 ; i < 3 ;i++)
{
*(z + i) = *(x + i) + *(y + i) ;
}
}
----------------------------------------------------------
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) ;
}
--------------------------------------------
>a?
5
5.000000
#############################################
プログラムを実行すると画面にa?と表示されます。
次に画面に数字(この例では5)を入力してreturnキーを押すと、入力した数字が実数
形式で出力されます。
printf("a?\n") ;
#! このprint文でa?を画面に表示しています。
この表示が無いと、作業者が何をすべきなのかが解らないので必ず書いておきます。
#! scanfというのが、キーボードからの入力を変数に代入するための命令です。
#! scanfで入力する為には変数の型を指定しなければなりません。
ここでは実数型を指定しています。%fですね。
#! 次のどの変数に代入するかを指定します。
代入する変数の指定は&aです。この指定はアドレスで行います。
#! 最後のprint文でaの値を実数型で表示します。
=============================================================================
*******************************************************************************
データファイルからのデータの読みとり
####################################################
***************************************
/home/data1
5,10
***************************************
#include<stdio.h>
#include <string.h>
main()
{
int a, b ;
char yomi[200] ;
FILE *fp ;
sprintf(yomi,"./home/data1") ;
if(NULL == (fp = fopen(yomi, "r")))
{
printf("\n %s can not be opened\n", yomi) ;
exit(1) ;
}
fscanf(fp, "%d, %d", &a, &b) ;
fclose(fp) ;
printf("%d, %d\n",a, b) ;
}
----------------------------------------------------
5,10
######################################################
データファイル
/home/data1
データがカンマなどに区切られてコンピュータ内に記録されているファイルの事です。
またデータファイルには、コンピュータ内での存在場所を示す為の名前が付いています
例では /home/data1
としています。
データファイルのデータが、カンマなどで整然と区切られた書式で記録されている場合
の読みとり方法です。プログラムを実行すると、データファイルに書き込まれていた5と
10というデータが各各aとbという変数に代入され、それがprint文で画面に表示されま
す。
#! まずincludeです。
c言語では自分の書いたプログラム以外のファイル(システム側であらかじめ用意して
いるファイル)も参照しないと処理が進まない場合があります。そのようなとき、inclu
deで参照すべきファイルを指定します。
#! ファイルの読み書きを行うためにはstdio.hというファイルをincludeする必要があ
ります。
#! 次に読み込むファイル名を記憶する為にchar型の配列を準備します。
#! また、読み込むファイルのアドレスを記憶する為にFILE型のポインタ変数を準備し
ます。
#! 次に配列yomiにデータファイルの名前の/home/data1を代入します。
このsprintfというのが、配列に文字列を代入する為の命令です。
#! ファイルを読み書きする為にはまずファイルを開かなければなりません。
このfopenでファイルを開きます。
#! if(NULL == (fp = fopen(yomi, "r")))
の yomi の部分で開くファイルの名前を指定します。
つまり、yomiに代入されている/home/data1というファイルを開く様に指定しています。
#! "r"の部分で開き方を指定します。
"r"とはread,すなわちファイルからデータが読み込み出来る様に開きます。
#! fpの部分で開いたファイルのポインタをfpに代入しています。
#! ファイルが開けなかった場合、NULLという値が返ってきます。
NULL ==
の部分ではそれを検出しています。
#! NULLになった場合、すなわちファイルが開けなかった場合、プログラムにとっては
予定外の事なのでプログラムを中断させなければいけません。
その場合、if文で中括弧内の処理を行います。
#! まずprint文で、どんな名前のファイルが開けないかを画面に表示します。
#! この後、exit文でプログラムを強制的に終了させます。
#! ファイルが開けた場合、fscanfという命令でファイルからデータを読み出します。
#! fpの部分で、どのファイルを読み込むかを指定します。
#! %d, %dの部分は読み込むデータの型の指定です。
ここでは整数型を指定しています。
#! &a, &bの部分でどの変数へデータを入力するかを指定します。
この指定はアドレスで行います。
#! fcloseでファイルを閉じます。
要済みのファイルは必ず閉じておきます。
#! 最後にprint文でa, bに代入したデータを画面に表示しています。
==============================================================================
*******************************************************************************
14 行単位でのfgetsのデータ読みとり
########################################################
*******************************************
/home/data2
1,2 3,4,5
*******************************************
#include <stdio.h>
#include <string.h>
main()
{
char a[257] ;
char yomi[200] ;
FILE *fp ;
sprintf(yomi,"./home/data2") ;
if(NULL == (fp = fopen(yomi, "r"))) ;
{
printf("\n %s can not be opened\n" ,yomi) ;
exit(1) ;
}
fgets(a, 255, fp) ;
fclose(fp) ;
printf("%s\n", a) ;
}
--------------------------------------------
1,2 3,4,5
#############################################
データを「,」や空白などの区切り単位で無く、行単位に読み込みたい場合があります
。例えば読みたいデータファイルの書式(データの区切り型)が一定していない場合な
どです。
その場合にはfgetsという命令を使い、行全体を文字列として読み込みます。
#! まず、データを読み込むための変数をchar型の配列で準備します。
char a[257] ;
#! このとき配列のよう素数は十分多くとります
十分多くとは(データファイルの1行に書かれている文字数の最大値+2です。)以上で
す。
#! データの読み込みにはfgetsと言う命令を使います。
fgets(a, 255, fp) ;
#! まず入力する配列の先頭アドレスを指定します。
a,
#! 次に1行に見込まれる文字数の最大値を指定します。
255,
#! 次に読み込むデータファイルを指定します。
fp
#! 最後にpirnt文で読み込んだデータを文字列として表示しています。
printf("%s\n", a) ;
============================================================================
********************************************************************************
15 複数行の場合のデータファイルの読みとり
#######################################################
/home/data5
1,10
2,20
3,30
4,40
5,50
************************************
#include <stdio.h>
main()
{
int i ;
int j ;
int a[50], b[50] ;
char yomi[200] ;
FILE *fp ;
sprintf(yomi, "/home/data3") ;
if(NULL == (fp = fopen(yomi, "r")))
{
printf("\n %s can not be opened\n", yomi) ;
exit(1) ;
}
i = 0 ;
while(fscanf(fp, "%d, %d", &a[i], &b[i]) !=EOF)
{
i++ ;
}
for(j = 0; j < i ; j++)
{
printf("%d, %d\n", a[j], b[j]) ;
}
fclose(fp) ;
}
----------------------------------------------------------
/home/data5
1,10
2,20
3,30
4,40
5,50
###########################################################
データファイルのデータが複数行に渡っている場合の読み込み方法です。
ここでは/home/data5というデータふぁりうに5行のデータが存在するとします。
プログラムを実行すると、5行文のデータが読み込まれ、画面に表示されます。
#! まず、データファイルの行数を計測するtめのint型の変巣を準備します。
#! 次にデータ読み込みのために、配列で変数を準備します。
データの行数が前もって解っていない時には、配列の大きさを充分大きく取って置きま
す。
#1 用意したint型の変数iの初期値を0に設定します。
#! 読み込みはwhile文の中のfscanfで行います。
#! ここでは配列a, bのi番目の要素a[i], b[i]に、データファイルのi行目を代入して
います。
#! そしてiを1つずつ増加させます。
#! データファイルが読み終わるとfcanfにEOFが代入されるので、このEOFによってデー
タファイルの終わりを検出します。
#! EOFが検出されると、データファイルを全て読み終えたと判断され読みとり作業を終
了し、whileループを脱出します。
#! このとき配列への入力データは、配列要素の0番目からi-1番目の合計i組になります
print文でこのi組のデータを表示しています。
==============================================================================
********************************************************************************
16 データファイルへの書き込み
#################################################
#include<stdio.h>
main()
{
int a ,b ;
char kaki[200] ;
FILE *fp2 ;
a = 5 ;
b = 10 ;
sprintf(kaki, "/home/data2") ;
if(NULL == (fp2 = fopen(kaki, "w")))
{
printf("\n %s can not be opened\n", kaki) ;
exit(1) ;
}
fprintf(fp2, "%d, %d\n", a,b) ;
fclose(fp2) ;
}
-----------------------------------------------------
データファイル
/home/data2 が生成される
5,10
######################################################
プログラムを実行しても、画面は何も変化しません。
しかし、コンピュータ内に/home/data2というファイルが作成され、そのファイルには5
と10が書き込まれます。
尚、このプログラムはコンピュータ内に既に/homeというディレクトリが存在すること
を前提にしています。
#1 ファイルへデータを書き込む手順は、データを読み込む際の手順と2カ所だけ異な
ります。そのうちの1つがこの
if(NULL == (fp2 = fopen(kaki, "w")))
部分です。ファイルを開く形式の指定をwにし、ファイ
ルを書き込みように開きます。
#! wを指定すると、その様なファイルが存在しなかった場合にはファイルを新しく作成
してから開きます。
#! ファイルが既に存在している場合には、その時ファイルに書き込まれているデータ
を全て消去してからファイルを開きます。従って、その後に書き込んだデータのみが記
録されます。
#! 既に存在しているファイルのデータを消したくない場合には、aを指定してファイル
を開きます。この場合には、新たに書き込むデータは今までのデータの後に追加して書
き込まれます。
#! データを読み込む手順との、もう一つの違いはこの部分です。
fprintfという命令でファイルにデータを書き込みます。
fprintf(fp2, "%d, %d\n", a,b) ;
#1 a, b で書き込む変数の指定を行います。
#! この指定は変数そのもので行います。
読み込みの時はアドレスで指定しますので混同しないで下さい。
ただし%sによる文字列の書き込みだけはアドレスで行います。ややこしいですね。
==============================================================================
///////////////////////////////////////////////////////////////////////////////
////////////////////////////
10 構造体と共用体
************
構造体とは複数の変数をひとまとまりにしたもの
構造体は一つの対象物の様々なデータ(この例ですと一人の子どもの名前、年齢、身長
)をひとまとめにして置くことが出来、データをどの変数に代入したかが覚えやすくな
ります。今はその利点が実感できないかもしれませんが、実際のプログラムで複雑なデ
ータを扱うようになるとその便利さが実感できると思います。
########################################################
#include <stdio.h>
main()
{
struct child { char name[10] ;int age, height ; } ;
struct child x, y ;
sprintf(x.name, "Taro") ; x.age = 6 ; x.height = 120 ;
sprintf(y.name, "Jiro") ; y.age = 4 ; y.height = 100 ;
printf("%s, %d, %d\n", x.name, x.age, x.height) ;
printf("%s, %d, %d\n", y.name, y.age, y.height) ;
}
---------------------------------------------------------
taro age 6 height 120
jiro age 4 height 100
#########################################################
#! 普通の変数では、最初から変数宣言を行います。
しかし構造体では、変数宣言に先立って型枠(テンプレート)の宣言を行います。
それがこの行でstructで構造体であることを宣言します。
struct child { char name[10] ;int age, height ; } ;
#! 次に型枠名(タグ)を書きます。型枠名は任意の名前を付けられます。
ここでは型枠名をchildにしています。
#! 次に型枠がchildの構造体の変数を宣言します。
struct child x, y ;
ここではxとyの2つの変数として宣言しています。
実際に変数として値を代入したりするのは、このxやyです。
#! xの構成要素name[10]の先頭アドレスをx.nameと表します。
#! ここではx.nameにtaroという文字列を代入しています。
sprintf(x.name, "Taro") ; x.age = 6 ; x.height = 120 ;
#! xの構成要素ageはx.age、構成要素heightはx.heightと表します。
x.ageには6をx.heightには120を代入しています。
#! x.name, x.age, x.heightなどは通常の変数と全く同じように扱えます。
ここではこれらをprint文で画面に表示します。
printf("%s, %d, %d\n", x.name, x.age, x.height) ;
printf("%s, %d, %d\n", y.name, y.age, y.height) ;
#! プログラムでは構造体変数yもxと全く同様に取り扱っています。
===========================================================================
*******************************************************************************
構造体の初期化
************
構造体では初期化と言って、構造体変数の宣言と同時に変数に値を代入する事も出来ま
す。
この例ではa, b, cの各変数が学校のクラスと担任の先生の名前を示すようにしてあり
ます。
1組はyamada先生2組はsato先生3組はkanda先生
###################################################
#include <stdio.h>
main()
{
struct school {int kumi ; char teach[10]; } ;
static struct school a = {1, "yamada" } ;
static struct school b = {2, "sato" } ;
static struct school c = {3, "kanda" } ;
printf("%d, %s\n", a.kumi, a. teach) ;
printf("%d, %s\n", b.kumi, b.teach) ;
printf("%d, %s\n", c.kumi, c.teach) ;
}
---------------------------------------------------
1,yamada
2,sato
3,kanda
###################################################
構造体では初期化と言って、構造体変数の宣言と同時に変数に値を代入する事も出来ま
す。
#! まず構造体の型枠を宣言します。
struct school {int kumi ; char teach[10]; } ;
構成要素はクラス名代入用のkumiと先生の名前代入用のteach[10]です。
#! 次に構造体変数の宣言と同時に、変数に値を代入します。
static struct school a = {1, "yamada" } ;
#! ここではa.kumiに1を、a.teachにyamadaを代入します。
このとき、変数宣言の先頭にstaticを付けなければなりません。
#! 構造体変数b, cも同様に変数宣言と値の代入を同時に行っています。
static struct school b = {2, "sato" } ;
static struct school c = {3, "kanda" } ;
#! a.kumi, a.teachに代入した値を画面に表示させています。
printf("%d, %s\n", a.kumi, a. teach) ;
#! 同様にこの部分でb b.kumi, b.teachに代入した値、c.kumi, c.teachに代入した値
を画面に表示させています。
printf("%d, %s\n", b.kumi, b.teach) ;
printf("%d, %s\n", c.kumi, c.teach) ;
=============================================================================
*******************************************************************************
構造体変数の配列の初期化
構造体変数の配列を使ってまとめて初期化する事も出来ます。
################################################
#include <stdio.h>
main()
{
struct school{int kumi ;char teach[10] ;} ;
static struct school z[3] = { 1, "Yamada",
2, "Sato",
3, "Kanda"} ;
int i ;
for(i = 0 ;i <3 ; i++)
{
printf("%d, %s\n", z[i].kumi, z[i].teach) ;
}
}
----------------------------------------------------
1, Yamada
2, Sato
3, Kanda
####################################################
#! 構造体変数として配列z[3]を宣言します。
static struct school z[3] = { 1, "Yamada",
2, "Sato",
3, "Kanda"} ;
#! 変数の宣言と同じ行で、z[-], z[1], z[2]の構成要素に順番に値を代入していきま
す。
{ 1, "Yamada",
2, "Sato",
3, "Kanda"} ;
#! z[0], z[1], z[2]の各構成要素の表示をforループを利用して行っています。
printf("%d, %s\n", z[i].kumi, z[i].teach) ;
==============================================================================
*******************************************************************************
構造体のポインタ変数
####################################################
#include <stdio.h>
main()
{
struct child {char name[10] ; int age, height ; } ;
struct child x ;
struct child *y ;
sprintf(x.name, "Taro") ; x.age = 6 ; x.height = 120 ;
y = &x ;
printf("%s, %d, %d\n", y->name, y->age, y->height) ;
}
----------------------------------------------------
Taro,6,120
######################################################
#! 最初に構造体の型枠の宣言をします
struct child {char name[10] ; int age, height ; } ;
#! 次に構造体の変数としてxを宣言しています。
これにより、構造体childを記憶する為の領域が確保されます。
struct child x ;
#! これはxの構成要素のx.name[10], x.age, x.heightの記憶領域が確保されることを
意味します。
そして&xは構造体xのアドレスを示します。
#! ここでx.name, x.age, x.heightに値を代入しています。
sprintf(x.name, "Taro") ; x.age = 6 ; x.height = 120 ;
#! 次に構造体のポインタ変数としてyを宣言します。
これにより構造体childのアドレスを記憶する為の領域が確保されます。
struct child *y ;
#! yに構造体xのアドレス&xを代入しています。
これによりyを介してxの各構成要素の値を参照する事が出来ます。
y = &x ;
#! この行ではyを介して構造体xの各校性要素をprint分で表示しています。
printf("%s, %d, %d\n", y->name, y->age, y->height) ;
#! その場合の表示法は、ポインタ変数->要素名です。
例えばx.nameを指し示すにはy->nameと書きます。
============================================================================]
*******************************************************************************
構造体のアドレス渡し
###############################################
#include <stdio.h>
struct child{char name[10] ; int age, height ; } ;
void past(struct child *y) ;
main()
{
struct child x ;
sprintf(x.name, "Taro") ; x.age = 6 ; x.height = 120 ;
past(&x) ;
}
void past(struct child *y)
{
printf("%s, %d, %d\n", y->name, y->age, y -> height) ;
}
------------------------------------------------
taro,6,120
################################################
#! まず構造体の型枠をグローバル(関数の外側)で宣言します。
struct child{char name[10] ; int age, height ; } ;
#! 次にmainで構造体変数xの宣言と値の代入を行います。
struct child x ;
sprintf(x.name, "Taro") ; x.age = 6 ; x.height = 120 ;
#! 次にxのアドレスを引数にして関数pastを呼び出します。
past(&x) ;
#! 関数pastでは、構造体childのポインタ変数yで引数を受け取ります。
void past(struct child *y)
#! これによりyに構造体変数xのアドレス&xが代入されます。
#! この結果、yを介してx.name, x,age, x.heightを参照出来る様になります。
printf("%s, %d, %d\n", y->name, y->age, y -> height) ;
==============================================================================
********************************************************************************
ポインタによる構造体変数の配列の参照
************
構造体のポインタ変数で、構造体変数の配列を参照する例題です。
プログラムでは、z[3]の各校性要素に入力した値がyに対するprint文で表示されます。
#################################################
#include <stdio.h>
main()
{
struct school{int kumi ;char teach[10] ;} ;
static struct school z[3] = { 1, "Yamada",
2, "Sato",
3, "Kanda"} ;
struct school *y ;
int i ;
y = z ;
for(i = 0 ; i < 3 ;i++)
{
printf("%d, %s\n", (y + i) -> kumi, (y + i) -> teach) ;
}
}
--------------------------------------------------
1, Yamada
2, Sato
3, Kanda
####################################################
#! まず最初に構造体の型枠をschoolという名前で宣言をします。
struct school{int kumi ;char teach[10] ;} ;
#! 構造体schoolの変数を配列z[3]で宣言すると共に、初期化により値を代入していま
す。
struct school{int kumi ;char teach[10] ;} ;
static struct school z[3] = { 1, "Yamada",
2, "Sato",
3, "Kanda"} ;
#! 構造体schoolのポインタ変数としてyを宣言しています。
struct school *y ;
#! 構造体のポインタ変数yに構造体変数の配列の先頭アドレスz = &z[0]を代入してい
ます。
y = z ;
#! するとy + 1はz[1]のアドレスに、y + 2はz[2]のアドレスに等しくなります。
#1 ところで、z[0]はkumiというint型の変数とteach[10]という文字型の配列により構
成されています。
#1 yを用いてz[0]の構成要素であるkumiとteach[10]の中身を参照出来ます。
y->kumi = z[0].kumi(中身そのもの)
y->teach=z[0].teach(アドレスz[0].teachを介しての参照)
#! 同様に(y + i)を用いてz[i]の構成要素を参照出来ます。
(y + i) ->kumi = z[i].kumi
(y + i) ->teach = z[i].tetach
=============================================================================
********************************************************************************
共用体
************
共用体は構造体とよく似ていますが、一つ異なる所があります。
それは、構造体が、各構成要素に別々の記憶領域を与えるのに対し、共用体は各構成要
素に同じ記憶領域を割り当てるのです。
構造体は各校性要素に別々の記憶領域を与えるのに対し
共用体は各校性要素に同じ記憶領域を割り当てるもの。
###################################################
#include <stdio.h>
main()
{
union abc { int a, b ; } ;
union abc x ;
x.a = 1 ;
x.b = 2 ;
printf("%d, %d\n", x.a, x.b) ;
}
----------------------------------------------------
2,2
###################################################
#! 共用体も構造体と同様、まず型枠の宣言をします。
違うのは、structの代わりにunionを使う事です。
型枠名はabc、構成要素はint型のaとbです。
union 共用体の型枠宣言
#1 次に共用体の変数を宣言します。
これによって共用体の記憶領域が確保されます。
union abc x ;
#! しかし、構造体と違って、この記憶領域は構成要素のx.aとx.bが共用するのです。
つまり、x.aのアドレスとx.bのアドレスは等しくなります。
#! この行でx.aに1を代入しています。実はこの段階でx.bも1になるのです。
x.a = 1 ;
#! 次にx.bに2を代入しています。
これによってx.bばかりでなくx.aも2に書き換えられてしまうのです。
x.b = 2 ;
#! 従ってprint文による表示ではx.aもx.bも2が表示されるのです。
printf("%d, %d\n", x.a, x.b) ;
==============================================================================
*******************************************************************************
構造体・共用体の入れ子
#####################################################
#include <stdio.h>
main()
{
union size { char type ;intwaist ; } ;
struct zubon { char color[5] ; unin size q ;} x, y ;
sprintf(s. color, "red") ;
x.q.type ='L' ;
sprintf(y.color, "blue" ) ;
y.q.waist = 76 ;
printf("%s, %c\n", x.color, x.q.type) ;
printf("%s, %d\n", y.color, y.q.waist) ;
}
-----------------------------------------------------
red,L
blue,76
########################################################
構造体、共用体の入れ子です。
構造胎動し、共用体同士、あるいは構造体と共用体を入れ子にして複雑な構造のデータ
を分かり易くまとめることが出来ます。
#! まず共用体sizeの型枠を宣言しています。
union size { char type ;intwaist ; } ;
#! sizeではL, M, Sの文字が入力されるchar型のtypeとウエストの長さが数字で入力さ
れるint型のwaistがあり、この内のどちらかが入力されます。
struct zubon { char color[5] ; unin size q ;} x, y ;
#! 次に構造体zubonの型枠宣言とzubonの変数x, yの宣言を同時に行っています。この
様に型枠の宣言と変数の宣言を同時に行うこともできます。
struct zubon { char color[5] ; unin size q ;} x, y ;
#! 構造体zubonの構成要素の一つはこのcolor[5]です。これにはズボンの色を代入しま
す。
char color[5]
#! この構造体zubonの構成要素中に、共用体sizeの変数qを宣言しています。
こうすることで、qはzubonの構成要素の一つになります。
unin size q ;
#! qはズボンのサイズを代入するのですが、typeとしてL, M, Sを代入する場合と、wais
tとしてウエストの長さを代入する場合があります。
この様に場合によって文字を入力したあり数字を入力したり出来る事が共用体の特徴で
す。
#! この行でx.colorにredを代入しています。
sprintf(s. color, "red") ;
#! この行でx.q.typeにLを代入してます。
x.q.type ='L' ;
#! このx.q.typeとは、構造体xの構成要素である共用体qの構成要素typeを意味します。
x.q.type ='L' ;
#! ここでy.colorにblueを代入しています。
sprintf(y.color, "blue" ) ;
#! ここでy.q.waistに76を代入しています。
y.q.waist = 76 ;
#! 最後にprint文でx.color, x.q.typeとy.color, y.q.waistに代入された値を表示し
ています。
printf("%s, %c\n", x.color, x.q.type) ;
printf("%s, %d\n", y.color, y.q.waist) ;
==============================================================================
==============================================================================
I-ichirow Suzuki _/_/_/_/_/_/_/_/_/_/_
URL :