42
プログラミング言語 東海大学総合情報センター

n 第1章 章立ての部分は、書式(PC入門大見出し)を …第2章 数の表現 2-1 2進数 電子計算機の動作原理は0と1で表される2進数です。また、人間が日常生活で扱っている数

  • Upload
    others

  • View
    0

  • Download
    0

Embed Size (px)

Citation preview

Page 1: n 第1章 章立ての部分は、書式(PC入門大見出し)を …第2章 数の表現 2-1 2進数 電子計算機の動作原理は0と1で表される2進数です。また、人間が日常生活で扱っている数

プログラミング言語 C

東海大学総合情報センター

目 次

第1章 入門の復習 1

演習1 2 第2章 数の表現 3

2-1 2進数 3 演習2 5 2-2 8進数と16進数 5 2-3 文字コード 6 演習3 6

第3章 関数 7 3-1 関数とは 7 3-2 関数の形式 7 3-3 引数 8 演習4 8 3-4 戻り値 10 3-5 変数の通用範囲 11 演習5 11 3-6 動的変数と静的変数 12 3-7 スタック 13 3-8 再帰呼び出し 14 演習6 14

第4章 実習 15 4-1 操作手順 15

第5章 配列 18 5-1 二次元配列の初期化 18 演習7 19

第6章 ポインタ型変数 20 6-1 ポインタ型変数の宣言および参照 20 6-2 ポインタ型変数の初期化 21 演習8 23

第7章 構造体共用体 24 7-1 構造体 24 7-2 共用体 28

第8章 アルゴリズム 30 8-1 ソート 30

第9章 プリプロセッサ 31 9-1 ファイルの挿入 31 9-2 文字の置換 31 9-3 条件によるコンパイル 32

付録1 33 付録2 39 <注意> 本テキストでは(エスケープシーケンス)の表記をyenに統一します

第 1章 入門の復習 C入門で学習した内容について簡単に復習します

(1) プログラム構造

include ltstdiohgt main() 変数などの宣言文 式や if文などの実行文

(2) 変数配列の宣言

int 変数名 float 変数名 char 変数名 double 変数名

int 配列名[n] float 配列名[n] char 配列名[n] double 配列名[n]

(3)定数 整定数 実定数 文字定数

10進数 12 8進数 014 16進数 0xC

125 125e3 125times103を意味します 125e-3 125times10-3を意味します

文字定数 A 文字列定数 ABCDEFG

(4)演算子 算術演算子 関係演算子

インクリメントデクリメント演算子 インクリメント ++ デクリメント - -

加算 + 減算 - 除算 乗算 剰余 代入 = += -= = = =

> 左辺が右辺より大きいときに真 >= 左辺が右辺より大きいか等しいときに真 < 左辺が右辺より小さいときに真 <= 左辺が右辺より小さいか等しいときに真 == 左辺と右辺が等しいときに真 = 左辺と右辺が等しくないときに真

1

(5) 文複文

式 いくつかの文

(6) 条件分岐

if( 式 ) 文1 else 文2

if( 式 ) 文

文1 偽

文2

真 真

文 偽

文m

その他

文1

定数1

文2

定数2 文n 定数n

switch( 式 ) case 定数 1 文1 break case 定数2 文2 break case 定数n 文n break default 文m

(7) 繰り返し

while( 式 ) 文 for( 式1 式2 式3 ) 文 do文 while( 式 )

文 偽

式2

式1

式3

(8) その他

goto ラベル break continue

演習1 ある個人の国語算数理科社会のテストの点数をデータとして入力し合計点と平均点を

計算しなさいそのとき平均点が60点未満の場合はGanbareのメッセージを表示するようにしなさい 入出力例

入力) 60 56 68 54 出力) Total= 238 Average=595 Ganbare

2

第2章 数の表現 2-1 2進数

電子計算機の動作原理は0と1で表される2進数ですまた人間が日常生活で扱っている数

は10進数です10進数と2進数の関係について説明します (1) 2進数(固定小数点)

2進数とは0と1で表される数です 0 1 2進数4桁の数字を表した場合それぞれの位は2nになりますしたがって10進数に変換する

場合には以下のように計算しますまた括弧の添え字は括弧内が何進数で表されているのかを

示します (1 0 1 0)2 (2進数から10進数への変換) 20の位 1times23 + 0times22 + 1times21 + 0times20

21の位 =1 times 8 + 0 times 4 + 1 times 2 + 0 times 0 22の位 =8 + 0 + 2 + 0 23の位 =10 逆に10進数から2進数に変換するには次の手順で行います (10)10 2) 10 2) 5 0 hellip 20 2) 2 1 hellip 21 (10)10=(1010)2 2) 1 0 hellip 22

1 helliphelliphelliphelliphellip 23

仮想的な小数点が常に20の右側に存在することから固定小数点と呼ばれています (1010) 仮想小数点 電子計算機の世界では2進数1桁のことをビット(bit)と呼びますまた2進数8桁(8ビット)の集

りを1バイト(Byte)と呼びます 1バイト(8ビット) 27 26 25 24 23 22 21 20

したがって1バイトまたは2バイト4バイトで表すことのできる最大の数は以下のとおりです 1バイト 2バイト 4バイト 1バイト( 8ビット) 0から255(28-1) 2バイト(16ビット) 0から65535(216-1) 4バイト(32ビット) 0から4294967295(232-1)

3

次に負の場合を考えます負の数を表す場合には2の補数を使用します例えば(-10)10

を1バイトで表すにはまず(10)10の2進数を求めます (10)10 = (00001010)2次にその2の補数を得るために次の計算を行います (100000000)2 -( 00001010)2

( 11110110)2 (-10)101バイト2バイト4バイト長の符号付きデータの場合正負を表すために最上位ビットを符号ビッ

ト(S)として使用します 1バイト 2バイト 4バイト 1バイト( 8ビット) -128~127 2バイト(16ビット) -32768~32767 4バイト(32ビット) -2147483648~2147783647

S

S

S

(2) 2進数(浮動小数点) 2進数の浮動小数点形式は次のように表現されます (1 11 1)2 (2進数から10進数への変換) 2-2の位 1times21 + 1times20 + 1times2-1 + 1times2-2

2―1の位 = 2 + 1 + 05 + 025 20の位 = 375 21の位 計算機の内部では浮動小数点型データは以下の形式になっています

[パーソナルコンピュータの場合] 4バイト データ値=

4バイト 8バイト

演習2 次の10進数は2

a)(33)10 d)(00010100)

(-1)Stimes(05+(M2))times2E-128 有効桁数 10進数約 7桁 大きさ 10-38から1038

有効桁数 10進数約16桁 大きさ 10-38から1038

仮数部 M 指数部 E S

仮想小数点位置

進数に2進数は10進数に変換しなさい負の値は1バイトで表しなさい b)(125)10 c)(21)10

2 e)(11111111)2 f)(00001111)2

4

2-2 8進数と16進数 (1) 8進数

8進数とは0から7までの数字で表される数です (3 7 6 4)8 (8進数から10進数への変換) 80の位 3times83 + 7times82 + 6times81 + 4times80

81の位 = 3times512 + 7times64 + 6times8 + 4times1 82の位 = 1536 + 448 + 48 + 4 83の位 = 2036

(2) 16進数

16進数とは0から9およびAからFの文字で表される数ですABCDEFは10進数の

101112131415に対応します (1 2 A B)16 (16進数から10進数への変換) 160の位 1times163 + 2times162 + Atimes161 + Btimes160

161の位 = 1times4096 + 2times256 + Atimes16 + Btimes1 162の位 = 4096 + 512 + 160 + 11 163の位 = 4779

5

2-3 文字コード 文字 A などは8ビットのデータとして定義(コード化)されています文字コードの種類もいく

つかありUNIX や MS-DOS では ASCII コードを使用していますまた汎用機などではEBCDIC コードを使用しています

(1) ASCIIコード表(JIS8ビット)

上位4ビット

0 1 2 3 4 5 6 7 8 9 A B C D E F

0 SP 0 P p ― タ ミ 1 1 A Q a q ア チ ム 2 ldquo 2 B R b r 「 イ ツ メ 3 3 C S c s 」 ウ テ モ 4 $ 4 D T d t エ ト ヤ 5 5 E U e u オ ナ ユ 6 6 F V f v ヲ カ ニ ヨ 7 BE

L lsquo 7 G W g w ァ キ ヌ ラ

8 BS ( 8 H X h x ィ ク ネ リ 9 TAB ) 9 I Y i y ゥ ケ ノ ル A LF J Z j z ェ コ ハ レ B ESC + K [ k { ォ サ ヒ ロ C < L ¥ l | ャ シ フ ワ D CR - = M ] m } ュ ス ヘ ン E > N ^ n ~ ョ セ ホ ゛ F O _ o DE

L ッ ソ マ ゜

下位4ビット

したがって文字Aは ASCII コードで次のようになります A = (41)16

演習3

ASCII コード表を使って次の文字コードを16進数で表しなさい a) 9 b) M c) g

6

第3章 関数 3-1 関数とは

Cではプログラムの単位は関数で定義されますここでいう関数とは数学などで使われる

sincos 関数と同様の概念でありある値を与えると何らかの処理を行いその結果が関数値となるものですもちろんmain() も一つの関数ですその他にも自由に関数を作ることができます

例えば関数

f(x)=4x2+2x+5 を計算するときには次のようにプログラムを分けることができます データxを入力して関数f(x)を呼び出しその結果を印刷するプログラム 関数f(x)を計算するプログラム これをプログラムで表すと次のようになります

include ltstdiohgt main() float x y f() 変数と関数の型の宣言

while( scanf( f ampx ) = EOF ) y = f( x ) 関数の引用

printf( yenn x=f f(x)=f x y ) float f( float x ) 関数の定義

float y y = 40 x x + 20 x + 50 return y 計算を終了し結果を戻します

関数 f(x)は与えられたxの値によりyを計算して main()に結果を返します

3-2 関数の形式 関数を定義する場合には次の形式で定義します

型 関数名(仮引数の並び) float f ( float x )

変数の型宣言 関数内で使用する変数の宣言 プログラム プログラム }

関数の定義で型の指定がない場合にはint 型の関数となりますまた関数名は31文字以内の英数字の組み合わせです

3-3 引数

関数に渡すパラメータを引数といいますmain()関数などのように関数を引用する場合のパラメータを実引数と呼び呼ばれる関数で使用されているパラメータを仮引数と呼びます

include ltstdiohgt

7

main() float x y f() 変数と関数の型の宣言

while( scanf( f ampx ) = EOF ) y = f( x ) 関数の引用x は実引数と呼びます

printf( yenn x=f f(x)=f x y ) float f( float x ) 関数の定義x は仮引数と呼びます

float y y = 40 x x + 20 x + 50 return y 計算を終了し結果を戻します

[入力の終了について]

このプログラムを実行すると永遠とデータ入力を求められてしまいます終了条件が = EOF の場合はキーボードから CTRLキーを押しながら Z を入力することにより while文を抜け入力を終了することができます

複数の引数を受け渡しする場合には引用する側と関数を定義する側とで 引数の並び個数型

を合わせなければなりませんしかし変数名は同じでなくてもかまいません例えば配列 a と bを加算して配列 cに代入する場合には次のようになります

include ltstdiohgt main()

int a[10] = 18 24 56 28 96 51 82 34 65 72 UNIXの場合 static intにする int b[10] = 12 54 69 20 26 84 55 20 44 74 UNIXの場合 static intにする

int c[10] k void matadd() 関数の型宣言

matadd( a b c ) for( k = 0 k lt 10 k++ ) printf( yenn d + d = d a[k] b[k] c[k] ) void matadd( int x[] int y[] int z[] ) 関数の定義

int t for( t = 0 t lt 10 t++ ) z[t] = x[t] + y[t]

演習4 平均値を求める関数average()を作成し10名の数学の得点を読み込みその平均点を求め

るプログラムを作りなさい 「入力例」 「出力例」

45 63900000 78 97

8

この他にも関数にパラメータを渡す方法としてポインタを使用する方法があります文字列を

複写する関数の場合には次のとおりになります関数名は strcopy()最初の引数には複写先の配列名(配列の先頭番地)次の引数には複写元の配列名(配列の先頭番地)です

include ltstdiohgt main() char src[] = tokai dst[80] void strcopy() strcopy( dst src ) printf( syenn dst )

void strcopy( char str1 char str2 ) while( ( str1++ = str2++ ) = yen0 )

また配列の加算を行う関数の場合にもそれぞれの配列名をパラメータとし関数側でポイン

タ型変数として受け取ることができます

include ltstdiohgt main() int a[10] = 18 24 56 28 96 51 82 34 65 72 UNIXの場合 static intにする int b[10] = 12 54 69 20 26 84 55 20 44 74 UNIXの場合 static intにする

int c[10] int k void matadd() matadd( a b c 10 ) for( k = 0 k lt 10 k++ ) printf( d + d = d yenn a[k] b[k] c[k] )

void matadd( int x int y int z int n ) for( n gt 0 n-- ) z++ = x++ + y++

main()関数では配列名(アドレス定数)として引数に指定されていますが関数 matadd()ではポインタ型の変数として使用することができますしたがって変数 xyz は値を変更することができるようになります

配列 a 変数 x

9

配列 b 変数 y 配列 c 変数 x

3-4 戻り値 関数からの戻り値はreturn 文によって返されます整数型文字型の値を返す関数の場合

にはそれぞれ次のように定義します

int sub( int x ) char sub( int x ) int y char z

return y return z

またポインタを返す関数の場合には次のように定義します

int sub( int x ) char sub( int x ) int y char z

return y return z

return文で式の指定がない場合には何も値を返しません

[プログラム例]

文字列(文字型配列)の中に指定した文字があればその位置をポインタで返し無ければ NULLポインタを返す関数を考えてみます

char strfind( char str char ch ) while( str ) if( str == ch )return str str++ return NULL

いくつかのC言語のマニュアルでは関数の説明を以下のように記述しています sin 機能 正弦を求めます 形式 include ltmathhgt double sin( double x ) このとき関数 sin() の戻り値は double 型でありまた指定する引数も double 型でなけれ

ばなりませんそれと同時にこの関数を使用する場合にはinclude ltmathhgt を指定しなければなりません

10

3-5 変数の通用範囲 関数内で宣言された変数はその関数の中でのみ使用可能です他のプログラムからは使用

することはできません

include ltstdiohgt main() int i 変数 i は関数 main() と sub() とでは それぞれ独立に使用することができます main() で変数 i に設定した値は sub() では参照することはできません sub() 逆にsub() で変数 i に設定した値も main() では参照することはできません

int i

それぞれの関数の中でのみ使用可能な変数をローカル変数と呼び他の関数でも使用可能

な変数をグローバル変数と呼びますいくつかの関数で共通に使用するような場合にはグロー

バル変数を使用します グローバル変数を定義する場合には関数の外で宣言します

include ltstdiohgt int i グローバル変数の定義

main() i = 10

sub() extern int i printf( yenn i = d i )

このプログラムではmain() 関数でグローバル変数に値を設定し関数 sub() で変数の値を

参照しています extern 宣言は変数が他のプログラム内で宣言されていることを示しています宣言の形式

は以下のとおりです extern 型 変数並び

演習5 入力された任意の数の倍数を求めるプログラムを作成しなさい入力する数値は2つ倍数 を求めるための任意の数と倍数の上限値ですここでいう上限値とは任意の数の倍数をどの くらいの数まで求めるかということです

11

3-6 動的変数と静的変数 通常Cで使用される変数はその関数の中だけでのみ使用できる変数ですしたがって関数

が実行するときに関数の中で使用する変数の領域を確保し関数の実行が終るときにその領域

を解放するようにしてメモリを効率的に利用していますこのように関数が実行されるときに確

保される変数を動的変数(auto変数 )と呼びます プログラムの中ではその他に常に存在し使用できる変数を定義することができますそのよ

うな変数は静的変数(static変数 )と呼ばれます

func() int a b static int x y

また static 変数には内部的なリンケージの指定の意味もありますつまり関数の外で変数

を宣言すると自動的にグローバル変数となり他のプログラムからも使用することができるようにな

ります ファイル a ファイル b このような場合にはコンパイル単位が異なっていてもextern 宣言を行うことにより変数 abc

を使用することができますところが関数の外で static 宣言をして定義した変数についてはコンパイル単位が違うプログラムからは使用することができなくなります ファイル a ファイル b 同一コンパイル単位(ファイル)に存在する関数 sub()と subd()では変数 abcを使用することが

できますがコンパイル単位(ファイル)が異なる関数 func()では変数 abcを使用することはできません

int abc sub() abc = 10

func() extern int abc printf( ldquo abc =dyennrdquo abc )

static int abc sub() abc = 10 subd() abc++

func() extern int abc printf( ldquo abc =dyennrdquo abc )

12

3-7 スタック プログラム中にはプログラム領域データ領域の他にスタック領域があり一時的な作業領域と

して使用されています関数間での引数の受渡しの時にもこの領域を使用しますスタック領域に

データを格納することを「スタックに積む」ともいいます基本的にはスタック領域に格納されたデ

ータは最後に格納されたデータから順に取り出されることになります以下に格納が行われたとき

のスタックの状態を示します記号は次に格納すべき位置(スタックポインタの値)を示していま

逆にスタックからデータを取り出すときにはスタックポインタが指している位置の一つ下から取

り出すことになりますスタックからデータを取り出すときのスタックの状態は次のようになります

なり

10

20

10

30

20

10

40

30

20

10

10rarr

格納

20rarr

格納

30rarr

格納

40rarr

格納

40rarr 30rarr

関数を呼び出すときには次

逆にそれぞれの関数から

次のようになります

40

30

20

10

取出

main() z = f1( x y )

のようにパラメータがスタ

戻るときにはパラメータで

30

20

10

取出

f1( int a int b ) c = f2( d e

xの値 yの値

xの値 yの値

13

ックに格納されます

使用していたスタック領域は自動的になく

10

20

)

f2( int p int q ) r = p + q

xの値

eの値 dの値

yの値

xの値 yの値

dの値

eの値

3-8 再帰呼び出し 関数の引数の受渡しがスタックを利用して行われることから自分で自分自身の関数を呼び出

すことができます 以下のプログラムは入力した値の階乗を計算するプログラムです

3の階乗を求めることを考えてみます

return 文によって戻るときは次のようにして値を返します kai( 3 ) 3 kai( 3-1 ) 2 kai( 2-1 ) return 1

6 3 (2 1) 2 1 以上の計算から3=6が導き出されます 再帰呼び出しのことをリカーシブコールともいいます

include ltstdiohgt main() int n m kai() scanf( ldquodrdquoampn ) m = kai( n ) printf( ldquod = dyennrdquo n m )

int kai( int k ) if( k == 1 )return 1 else return k kai( k ndash 1 )

kai( 1 )

darr

return 1

kai( 2 )

darr

2 kai( 2-1 )

kai( 3 )

darr

3 kai( 3-1 )

main()

darr

kai( 3 )

3

2

1

2

3

1

2

3 3

32

32

1

2

1

3

3

演習6 1からnまでの総和を再帰呼び出しを使って計算する関数 sowa() を作りなさい n+(n-1)+ +2+1

14

第4章 実習 この章ではプログラムを実際に入力して実行するまでの手順を実習します

4-1 操作手順 (1)ログイン

[スタート]rarr[プログラム(P)]rarr[ネットワーク] Hostの欄に bosei を記述選択 rarr [Telnet(FreeWare)] を選択します して 「OK」 ボタンをクリックします

UP-UXV (Rel42MP) (bosei) (pts41) login 60us1234 larr 各自のログイン名を入力します Password larr パスワードを入力しても画面は何も変化しません 101 60us1234bosei larr セッションが開設されましたこれをプロンプトといいます この状態でコマンドを入力することができます

(2)プログラムの作成 以下のコマンドを入力しテキストエディタを起動します 60us1234boseicc ng rensyuc

すると下図のようにngエディタの画面になります

15

次のように入力します入力ミスの修正はBSキーで行ないます

include ltstdiohgt main() float abc scanf(f f ampaampb) c=ab printf(f f f yenn abc)

CTRL キーを押しながら XCTRL キーを押しながら C を押しますすると次のメッセージが画面下に表示されます

Save file uhomea60us1234rensyuc (y or n)

このメッセージに対して y と答えます

(3)データの作成 以下のコマンドを入力しテキストエディタを起動します 60us1234boseicc ng rensyud

ngエディタの画面になりますので次のように入力します 12 35

CTRLキーを押しながら XCTRLキーを押しながら C を押します save file uhomea60us1234rensyud (y or n)

このメッセージに対して y と答えます

(4)コンパイルと実行 コンピュータに処理を依頼します 60us1234boseicc ccg rensyu

ジョブを投入しましたジョブの状態を見るコマンドは myjobです

16

130 60us1234boseicc myjob ================================================= NQS (R0220) BATCH REQUEST HOST bosei ================================================= REQUEST ID NAME OWNER QUEUE PRI NICE STT PGRP R --------------- -------- -------- -------- ---- --- --- ------ - 99321bosei STDIN 60us1234 A 31 0 RUN 14161 - ---------------------------------------------------------------- ================================================== NQS (R0220) DEVICE REQUEST HOST bosei ジョブは実行中です

================================================== REQUEST ID NAME OWNER QUEUE PRI SIZE STT -------------------------------------------------------------

所有するファイルの一覧を見てみます

60us1234boseicc ls -l larr 持っているファイルの一覧を見るコマンドです

-rw-r--r-- 1 60us1234 other 4 4月26日 15時14分 rensyud -rw-r--r-- 1 60us1234 other 128 4月26日 15時10分 rensyuc -rwxr-xr-x 1 60us1234 other 361 4月26日 15時16分 rensyul

(5)計算結果の確認

計算結果を画面に表示して確認します 60us1234boseicc more rensyul

(6)印刷

計算結果の印刷を行ないます5号館2階のカフェテリア室にある bosei のプリンタに印刷 されます

60us1234boseicc lpr rensyul

(7)ログアウト セッションを終了します 60us1234boseicc logout

(8)実行の流れ

エラー

プログラムの作成 ログイン コンパイル実行

確 認 印 刷 ログアウト

17

第5章 配列 多数の変数をまとめて宣言する方法として配列があります配列の一つ一つは配列要素と呼

ばれ変数と同じ性格を持っています配列の宣言は型宣言と同時に次のように行います int a[5] 配列 a

a[0]

a[1]

a[2]

a[3]

a[4]

二次元配列(一次元配列を複数集めたもの)を宣言する場合には次のようになります int b[3][4] 配列 b

b[0][0] b[0][1] b[0][2] b[0][3]

b[1][0] b[1][1] b[1][2] b[1][3]

b[2][0] b[2][1] b[2][2] b[2][3]

配列要素に数値を代入する場合は次のようになります b[1][2]=10

5-1 二次元配列要素の初期化 変数の型宣言と同じように配列を宣言するときに初期値も同時に設定することができます

複数のデータがある場合には{}記号でくくって指定します int b[3][4] = 2 4 6 8 1 3 5 7 1 2 3 4

文字型配列の場合には以下のようになりますyen0 は文字列の終わりを表わします char univ[3][7] = T O K A I yen0 S I M I Z U yen0 Y O Y O G I yen0

また文字列定数として初期化することもできますこの場合コンパイル時に自動的に yen0 が付加されます

char univ[3][7] = TOKAI SIMIZU YOYOGI

18

[プログラム例] 二次元配列のタテヨコを加算するプログラム

include ltstdiohgt main() int mat[4][3]=123456789101112 int ijytotalttotal[3]total=0 for(j=0jlt3j++)ttotal[j]=0 for (i=0ilt4i++) ytotal=0 for(j=0jlt3j++) ytotal += mat[i][j] ttotal[j] += mat[i][j] total += mat[i][j] printf(3dmat[i][j]) printf( 3dyennytotal) printf(yenn) for(j=0jlt3j++)printf(3dttotal[j]) printf( 3dyenntotal)

[実行結果]

1 2 3 6 4 5 6 15 7 8 9 24 10 11 12 33 22 26 30 78

演習7

a)以下の配列はどのように初期化されるか答えなさい char errmsg[2][15] = Divide Error Overflow Error

b)九九の計算を2次元配列を使って求めなさい

19

第6章 ポインタ型変数 C言語では値を記憶するための変数だけではなく変数または定数の番地を記憶するため

のポインタ型変数を宣言することができますポインタとはデータ項目の一種で「記憶装置(メモ

リ)上の格納番地(アドレス)を指すデータ項目」です アドレス コンピュータの中ではデータ項目の格納番地のことをアドレス(住所)と呼びます 例えば記憶装置という名前のとてつもなく大きなマンションがあるとしますその中から Aさんを捜すときは部屋番号を参照しますマンションでは部屋番号で住居人を参照し ているのと同じようにコンピュータでは記憶装置上に確保された変数は格納番地 (アドレス)で管理されています

マンション 部屋番号 記憶装置 格納番地

Aさん Int a Bさん Cさん AAAさん BBBさん CCCさん

1号室

2号室

3号室

100号室

200号室

300号室

100番地

200番地

300番地

1000番地

2000番地

3000番地

Int b Int c float aaafloat bbbfloat ccc

ポインタ ポインタとは「指し示すもの」の意ですがC言語では記憶装置上のアドレスを指し示す もののことです上のマンションの例では部屋番号を格納するデータ項目ということに なりますAAAさんは100号室に住んでいます100という値をポインタのデータ項目に 記憶するとそのデータ項目は間接的にAAAさんを指すことになります

6-1 ポインタ型変数の宣言および参照 通常の変数と区別するために型宣言時に変数名の前に記号を付けて宣言します int a 整数型ポインタ変数 int b 整数型変数

変数 a は整数型の値を記憶するのではなく整数型の値を持つ変数などの番地を記憶する変数ですまた変数 b は通常の整数型の値を記憶するための変数です

20

include ltstdiohgt main() int a b c a はポインタ型の変数b c は整数型の変数 b = 12 変数 b に値 12 を代入します a = ampb 変数 a には変数 b の番地が代入されます c = a + 10 変数 a の指す変数(b)の内容と10の加算です つまり12 + 10 を変数 c に代入します

変数の型宣言において変数名に記号を付けることによりその変数はポインタ型の変数と

なりますポインタ型の変数は変数名のみを指定した場合には単にその変数の値(通常はメモリ

の番地)を表します変数名に記号を付けて使用した場合にはその変数が指し示している変

数の内容を表します c = a ポインタ型変数 a が指している値を変数 c に代入

ポインタ型の変数に番地を記憶させるためにはプログラム例のように変数名の前に記号を

指定します変数名 によって変数の番地(アドレス)を表します a = ampb 変数 b の番地をポインタ型変数 a に代入します

ポインタ型変数の型はポインタ型変数が指し示す先の変数の型を表しています int a 変数 a 整数型の値 float x 変数 x 実数型の値 char c 変数 c 文字型の値

6-2 ポインタ型変数の初期化 ポインタ型変数も型宣言のときに変数を初期化することができます特に文字型のポインタ変

数の場合によく使います char str = TOKAI University

ポインタ型変数 str は文字列定数 TOKAI University の最初の文字が格納されている番地を初期値として持つことになります

変数 str TOKAI University 文字列定数

[プログラム例]

(1)文字型配列 putchar() 関数を使って一次元の文字型配列を出力します include ltstdiohgt main() char str[6] = TOKAI int i for( i = 0 str[i] = yen0 i++ ) putchar( str[i] )

21

ポインタを使用した場合には以下のようになります include ltstdiohgt main() char str[6] = TOKAI char chp for( chp = str chp = yen0 chp++ ) putchar( chp )

chp str T [0] O K A I yen0 [5]

参照する変数 配列の表現 ポインタの表現 実際のアドレス 1番目の数 str[0] chp CHP 2番目の数 str[1] (chp+1) CHP+1 n番目の数 str[n-1] (chp+n-1) CHP+n-1 6番目の数 str[5] (chp+5) CHP+5

注意実際のアドレス CHPは実行時に決定されます

(2)二次元文字型配列 二次元の文字型配列に定数を設定しそれを出力するプログラムです文字型配列を使用す

ると次のとおりになります include ltstdiohgt main() char str[5][40] = TOKAI shounan campus NEC DEC int i for( i = 0 i lt 5 i++ ) printf( yenns str[i] )

40 バイト str TOKAI shounan campus NEC DEC

22

ポインタ型配列を使用すると次のとおりになります include ltstdiohgt main() char str[6] = TOKAI shounan campus NEC DEC NULL char chp for( chp = str chp = NULL chp++ ) printf( yenns chp ) str

chp 番地 TOKAI 番地 shounan 番地 campus 番地 NEC 番地 DEC

NULL

演習8 キーボードまたはデータファイルから読み込んだ文字列中にrsquoArsquo があったら rsquoarsquo に変換 するプログラムを配列とポインタを使って書きなさい

23

第7章 構造体共用体 7-1 構造体

プログラムの規模が大きくなるにつれて多数の intや floatcharなどのデータ型を扱うようになり複雑になってきますそこで多数のデータを1つにまとめて簡単に扱える機能が構造体です 構造体について住所録のデータを例にあげて考えてみます

住所録の個人データとして氏名住所電話番号年齢の項目を一つのデータとします これをC言語で変数の定義をすると次のようになります 氏名東海太郎 char name[30] 住所平塚市北金目1117 char address[30] 電話番号0463-58-1211 char tel[20] 年齢30 int age 個人の住所録データ C言語での表現 このような住所録の個人データを1つにまとめて新しいデータとして定義する機能を構造体と言

います struct 構造体タグ名 構造体メンバーの並び

「struct」は構造体を表すキーワードです 「構造体タグ名」は構造体の型枠を宣言しますここは自由に名前を定義することができ ます 「構造体メンバーの並び」は構造体の要素です複数指定できます

個人の住所録のデータを構造体で宣言すると次のようになります

struct jusho char name[30] char address[30] 構造体のメンバーの並び char tel[20] (複数可)

int age

上記の宣言では構造体の形式を宣言しているだけでメモリ中で実際の領域を確保している

わけではありません実際に領域を確保するためには次のように定義します

struct 構造体タグ名 構造体名

したがって構造体名を jdata とすると次のように指定します

struct jusho jdata

構造体 jdataは次のように構造体タグ jushoの形式で領域を確保します

24

Jdata name[30]

address[30] tel[20] age

(1)構造体の参照

プログラム中で構造体中のメンバーを参照する場合には次のように指定します 構造体名メンバー名

したがって「名前」を参照したいときには次のように指定します

jdataname

[プログラム例]

名前住所電話番号年齢を定義しそれを印字します include ltstdiohgt include ltstringhgt main() struct jusho char name[30] char address[30] char tel[20] int age struct jusho jdata strcpy( jdataname 東海 太郎) strcpy( jdataaddress 平塚市北金目1117)

strcpy( jdatatel 0463-58-1211) jdataage = 30 printf(yenn氏名 = syenn jdataname) printf(yenn住所 = syenn jdataaddress) printf(yenn電話番号= syenn jdatatel) printf(yenn年齢 = dyenn jdataage)

また構造体の形式の定義と領域の確保は次のように同時におこなうことができます

struct 構造体タグ名 構造体メンバーの並び 構造体名

struct jusho struct jusho char name[30] char name[30] char address[30] char address[30] char tel[30] = char tel[30] int age 同じ int age

jdata struct jusho jdata

型宣言と同時にメモリ上に領域を確保する方法 後からメモリ上に領域を確保する方法

25

(2) 構造体配列 住所録データの場合その中に入るデータは1件ではありませんやはり100件200件のデ

ータが必要になる場合がありますこのように個人単位のデータを多数扱う場合には構造体を配

列として宣言することができます 次の例は個人のデータを100個用意するために構造体を配列として宣言しています struct jusho jdata[100] jdata[0] name[30] address[30] tel[20] age

jdata[99 ] name[30] address[30] tel[20] age

(3)構造体配列の参照

プログラム中で構造体配列中のメンバーを参照する場合には次のように指定します 構造体名[要素番号]メンバー名

したがって10件目の人の「名前」を参照したいときには次のように指定します

jdata[10]name

[プログラム例]

名前住所電話番号年齢を定義しそれを印字します include ltstdiohgt include ltstringhgt main() struct jusho char name[30] char address[30] char tel[20] int age jdata[100] strcpy( jdata[10]name 東海 太郎) strcpy( jdata[10]address 平塚市北金目1117)

strcpy( jdata[10]tel 0463-58-1211) jdata[10]age = 30 printf(yenn氏名 = syenn jdata[10]name) printf(yenn住所 = syenn jdata[10]address) printf(yenn電話番号= syenn jdata[10]tel) printf(yenn年齢 = dyenn jdata[10]age)

26

(4) 構造体のポインタ 変数と同じように構造体へのポインタも定義することができます

変数へのポインタ例 構造体へのポインタ例 またポインタを使用して構造体メンバーを参照するには次のように -> 記号を使って指

定します ポインタ変数名 -> メンバー名

[プログラム例]

名前住所電話番号年齢を定義しそれを印字します include ltstdiohgt include ltstringhgt main() struct jusho char name[30] char address[30] char tel[20] int age jdatakp kp = ampjdata strcpy( kp-gtname 東海 太郎)

strcpy( kp-gtaddress 平塚市北金目1117)

strcpy( kp-gttel 0463-58-1211) kp-gtage = 30 printf(yenn氏名 = syenn kp-gtname) printf(yenn住所 = syenn kp-gtaddress) printf(yenn電話番号= syenn kp-gttel) printf(yenn年齢 = dyenn kp-gtage)

kp jdata

name[30] ポインタ型の変数 address[30]

tel[20]

構造体へのポインタを記憶 age

することができます

int a int b b = ampa

struct name jname struct name np np = ampname

27

7-2 共用体 共用体は構造体と同じようにして宣言しますが共用体は複数のデータ型を同一のアドレスに

割り当てる方法です union 共用体タグ名 共用体メンバーの並び

「union」は共用体を表すキーワードです 「共用体タグ名」は共用体の型枠の名前を宣言しますここは自由に名前を定義することがで

きます 「共用体メンバーの並び」は共用体の要素です複数指定できます

共用体の宣言の例を次に示します

union c_tag int a char b

共用体 cは次のように共用体タグ c_tagの形式で領域を確保します共用体はメモリ上に領域を確保するときは ab ともに同じ領域に割り付けられます これはab という2つのデータが同時に存在するわけではなく cを異なるデータ abで共有す

ることを表しています c a b

上記の宣言だけでは共用体の形式を宣言しているだけでメモリ中で実際の領域を確保して

いるわけではありません実際に領域を確保するためには次のように定義します union 構造体タグ名 構造体名

したがって共用体名を c とすると次のように指定します

union c_tag c

(1)共用体の参照

プログラム中で共用体中のメンバーを参照する場合には次のように指定します 共用体名メンバー名

したがって「a」または「b」を参照したいときには次のように指定します

ca (int 型) cb (char 型)

メンバー参照方法によって int型として使ったりchar型として利用することができます

28

[プログラム例]

includeltstdiohgt main() union data char a short b int c chk chkc = 0x12345678 printf( char a xyennchka) printf( short b xyennchkb) printf( int c xyennchkc)

chkb(int 型) chkb(short 型) chka(char 型) 12 12 12 34 34 56 78

29

第8章 アルゴリズム コンピュータに何か仕事をさせようとするときは仕事を具体的に実行するための処理や動作

の手順が必要ですこの「手順」がアルゴリズムです アルゴリズムを考えるときは解くべき問題をはっきりと定義することが必要です

8-1 ソート ソートとは与えられたデータを小さい順または大きい順に並べ換えることですソート方法は

いくつかありますが基本的な方法でソートするアルゴリズムを紹介します

includeltstdiohgt int data[10] main()

int data_in() sort() data_in() sort() int data_in() データ入力関数

int a printf(数値入力yenn)

for(a=0alt=9a++) printf( [d]a+1) scanf(dampdata[a]) int sort() ソート処理を行う関数

int cont1cont2tmp1tmp2mim for(cont1=0 cont1lt=9 cont1++) mim=data[cont1] tmp1=cont1 for(cont2=cont1+1 cont2lt=9 cont2++) if(data[cont2] lt mim) mim=data[cont2] tmp1=cont2 tmp2 = data[cont1] data[cont1] = data[tmp1] data[tmp1] = tmp2 printf(結果 yenn)

for (cont1 = 0 cont1 lt= 9 cont1++) printf(d yenn data[cont1])

30

第9章 プリプロセッサ C言語にはプログラムの中でコンパイルについての指示を行う「プリプロセッサ」という機能が

ありますまたプリプロセッサとはコンパイルする前に実行されるためその意味のとおり「前処理」 と呼ばれていますここでは代表的なものをいくつか説明します

9-1 ファイルの挿入 ソースプログラム中に指定されたファイルを挿入します

include ltstdiohgt helliphellip 標準ディレクトリを探します include progh helliphellip 現在のディレクトリを探しなければ標準ディレクトリを探します

includeltstdiohgt によって組み込まれた define EOF (-1) define EOF (-1) define define helliphelliphelliphellip 組み込み helliphelliphelliphellip

main() stdiohファイル

int helliphelliphelliphellip helliphelliphelliphellip

ソースファイル

9-2 文字の置換 プログラム中に使われている文字列を別の文字列に置き換えます

include ltstdiohgt define TRUE 1 define EOF (-1) main() define helliphellip helliphellip

while(TRUE) define TRUE 1 置き換え main() helliphellip helliphellip while(1)

break helliphelliphellip

31

9-3 条件によるコンパイル 識別子が定義されているか否かを判断しコンパイルする範囲を指定します

include ltstdiohgt define UNIX main() ifdef UNIX printf( UNIX yenn) else printf(MS-DOSyenn) endif

include ltstdiohgt define OS UNIX main() if OS == UNIX printf( UNIX yenn) else printf(MS-DOSyenn) endif

32

付 録 1 puts()gets()関数について

行単位に入出力を行う場合には puts() gets() 関数を用います

puts() 標準出力に文字列を出力します

include ltstdiohgt int puts( char s ) puts() は NULL で終る文字列 s を標準出力に出力し最後に改行文字 yenn も出力しま

gets() 標準入力から文字列を入力します

include ltstdiohgt char gets( char s ) 戻り値正常に入力した場合には引数 s の値が返されますエラーやEOFになった場合に

は NULL が返されます gets() は標準入力から復帰文字で終る文字列を入力しs に格納しますこのとき最後の復

帰文字は NULL文字に変更されます

入力行の出力 標準入力から gets() で入力したデータには改行コードは含まれませんまた標準出力へ

puts() で出力を行う場合には必ず改行コードが付加されますgets() を実行したときの戻り値としてファイルの終端を検出した場合には EOF ではなく NULL が返されますので注意して下さい

include ltstdiohgt main() char data[80] while( gets( data ) = NULL )puts( data )

putchar()getchar()関数について putchar() 標準出力に文字を出力します

include ltstdiohgt int putchar(int c ) 戻り値正常に出力できた場合には文字cをエラーの場合にはEOFを返します

33

getchar() 標準入力から文字を入力します

include ltstdiohgt int getchar(void) 戻り値正常に入力した場合には読み込んだ文字を int 型に変換して返しますまたファイ

ルエンドエラーの場合にはEOFを返します

標準入力標準出力

標準入力標準出力はプログラムが開始されるときにはオープンされていますそれぞれのフ

ァイルポインタは stdin stdout になっていますfopen() fclose() をせずとも使用することができます

scanf() 標準出力ストリームからテキストを読み込み解釈します include ltstdiohgt int scanf( const char format [ address ] ) 戻り値正しくスキャンし変換し格納した入力フィールドの数を返しますファイルエンドを読

み込んだ場合は戻り値は EOF となります値を格納したフィールドがなかった場合は戻り値は0となります

一連の入力フィールドをスキャンして1度に1文字ずつストリーム stdin から文字を読み込み

ます次に引き数 format によって指される書式文字列中の書式指定に従って各フィールドを書式化します最後にformat の後に続く各引き数が示しているアドレスに書式化した入力を格納していきます書式文字列中の書式指定の個数はその後に続くアドレスの数と同じでな

ければなりません 書式指定[入力幅][型指定文字] 入力幅 読むべき文字数の最大値 型指定文字 次のとおりです 型指定文字 期待される入力 引き数の型 d 10進整数 int へのポインタ( int arg ) x 16進整数 int へのポインタ( int arg ) f 浮動小数点数 float へのポインタ( float arg ) s 文字列 文字配列へのポインタ( char arg[] ) c 文字 文字へのポインタ( char arg )

printf() フォーマットを指定してテキスト標準出力ストリームに出力します include ltstdiohgt int printf( const char format [ argument ] ) 戻り値出力したバイト数を返しますエラーの場合は EOF を返します

34

format によって指される書式文字列中の書式指定をformat の後に続く各引き数に適用し

書式化されたデータを stdout に出力します書式指定は後に続く引き数と同じ数だけなければなりません

書式指定[印字幅][精度][型指定文字] 印字幅 印字する最小文字数 精度 印字する最大文字数 型指定文字 つぎのとおりです 型指定文字 入力引き数 出力の書式 d 整数 符号付き10進整数 x 整数 符号無し16進整数 f 浮動小数点 符号付きの dddddddd形式の値 c 文字 1個の文字 s 文字列ポインタ ヌル文字に出会うか精度に達するまで 文字をプリントする

fopen()fclose()関数について fopen() ファイルをオープンします

include ltstdiohgt FILE fopen( char filename char mode ) 戻り値正常にファイルのオープンができたらファイルポインタを返しますエラーがあった場

合には NULLを返します 文字列 filename で指定されたファイルをオープンしますオープン後の入出力のモードに

ついては文字列 mode で指定しますmode に指定できる文字は以下のとおりです r 入力モードでオープンします w 出力モードでオープンします a 存在するファイルに追加して出力するモードでオープンします r+ 既に作成してあるファイルを更新(入力出力)するモードでオープンします w+ 新しく作成するファイルを更新モードでオープンします a+ 既に作成してあるファイルの終りから更新用に作成します

以上の文字に b をつけ加えることによりバイナリモードで入出力することができるようになり

ます rb バイナリの入力モードでオープンします wb バイナリの出力モードでオープンします ab 存在するファイルに追加して出力するモード(バイナリ)でオープンします

fclose() 既にオープンしてあるファイルをクローズします include ltstdiohgt fclose( FILE fp ) 既にオープンしているファイルをクローズしますパラメータには fopen() 関数により返された

ファイルポインタを指定します

35

テキストモードとバイナリモード 行の最後はテキストモードの場合改行コードのみとなりバイナリモードの場合には復帰

コードと改行コードの組合わせになります行の最後としてテキストファイルには復帰コード改行

コードが書かれていますがテキストモードでオープンした場合には入力すると改行コードのみに

変換されて入力されますバイナリモードの場合には復帰コード改行コードがそれぞれ入力され

ます

fputs()fgets()関数について fputs() ファイルポインタで指定されるファイルに文字列を出力します

include ltstdiohgt

int fputs( char s FILE fp ) fputs() は NULL で終る文字列 s をファイルポインタに示されるファイルへ出力しますputs()

と違い最後に改行文字 yenn を出力することはありません

fgets() ファイルポインタで指定されるファイルから文字列を入力します include ltstdiohgt char fgets( char s int n FILE fp ) 戻り値正常に入力した場合には引数 s の値が返されますエラーやEOFになった場合に

は NULL が返されます fgets() はファイルポインタで指定されるファイルから ( n - 1 ) 文字または改行文字までの

文字列を入力しs に格納しますgets() と異なり最後に入力された改行文字は NULL 文字に変更されません

標準入力から入力しファイルへ出力する ファイルへ出力あるいは入力を行う場合には改行コードの変換(入力の場合の削除出力の

場合の付加)はされませんしたがって標準入力から入力しファイルへ出力する場合には改行

コードを付加しなければなりません include ltstdiohgt main() char data[80] FILE fp fp = fopen( data w ) while( gets( data ) = NULL ) strcat( data yenn ) 改行コードの付加

fputs( data fp ) fclose( fp )

36

fputc()fgetc()関数について fputc() ファイルポインタで指定されるファイルに1文字出力します

include ltstdiohgt int fputc( int c FILE fp ) 戻り値正常に出力できた場合には文字 c を返しエラーの場合には EOF を返します fputc() は文字 c をファイルポインタで示されるファイルへ出力します

fgetc() ファイルポインタで指定されるファイルから1文字入力します

include ltstdiohgt int fgetc( FILE fp ) 戻り値正常に入力した場合には入力した文字を返しますエラーやEOFになった場合には

EOF が返されます fgetc() はファイルポインタで指定されるファイルから文字を入力します

ファイルの内容の表示 include ltstdiohgt main() FILE fp int ch char fname[30] printf( Key in Fila name gt ) gets( fname ) fp = fopen( fname r ) while( ( ch = fgetc( fp ) ) = EOF )putchar( ch ) fclose( fp )

その他テキスト中で使用された関数について sin() 三角関数の正弦を計算します

include ltmathhgt double sin(double radian) sinはラジアンを単位とする引数 radianの三角関数を計算します

37

strcpy() 文字列を他の文字列へコピーします

include ltstringhgt char strcpy(char string1const char string2) strcpyは引数 string2の指す文字列を null文字まで含めて引数 string1の指す領域にコピ

ーする strcpyは string1を返します

strcat() ある文字列を他の文字列に加えます

include ltstringhgt char strcat( char dest const char src ) 戻り値連結された文字列へのポインタを返します strcat() はsrc のコピーを dest の最後につけ加えます得られる文字列の長さは

strlen(dest)+strlen(src) になります

fabs() 絶対値の計算をします include ltmathhgt double fabs(double z) fabsは倍精度浮動小数の絶対値を計算して返しますつまりzgt=0であれば z をzlt0であ

れば-zを返します exp() 指数関数を計算します

include ltmathhgt double exp(double z) exp は引数zの指数関数つまりezを返すここではeは自然対数の底を表します対数関

数logの逆関数です

38

付 録 2 コンパイルの方法には大きく分けて第4章の実習で学んだようにデータファイルを作成してお

き ccg でコンパイルさせる方法と実行中に対話型でデータを入力していく方法があります ここでは対話型で実行を進めていく方法を紹介します ただしこの方法は計算(cpu)時間が10秒以内のものに限ります10秒を超える計算(cpu)時

間を要する場合はccg でコンパイルをするようにしてください 第4章実習の(2)(p16)までは同様です

コンパイル

コンピュータに処理を依頼します 60us1234boseicc cc rensyuc

所有するファイルの一覧を見てみます

60us1234boseicc ls -l larr 持っているファイルの一覧を見るコマンドです

-rw-r--r-- 1 60us1234 other 128 4月26日 15時14分 rensyuc -rwxr-xr-x 1 60us1234 other 361 4月26日 15時16分 aout

aout という実行形式のファイルが作成されています

実行

60us1234boseicc aout12 35[リターン] データを入力

1 200000 3500000 4200000 実行結果の出力

60us1234boseicc

注意

aout ファイルは印刷することができません実行結果を印刷する場合にはファイルに落とし てから出力するようにしましょう

60us1234boseicc aout gt kekka12 35[リターン] データを入力

60us1234boseicc more kekka 計算結果の確認 60us1234boseicc lpr kekka 計算結果の印刷

39

Page 2: n 第1章 章立ての部分は、書式(PC入門大見出し)を …第2章 数の表現 2-1 2進数 電子計算機の動作原理は0と1で表される2進数です。また、人間が日常生活で扱っている数

目 次

第1章 入門の復習 1

演習1 2 第2章 数の表現 3

2-1 2進数 3 演習2 5 2-2 8進数と16進数 5 2-3 文字コード 6 演習3 6

第3章 関数 7 3-1 関数とは 7 3-2 関数の形式 7 3-3 引数 8 演習4 8 3-4 戻り値 10 3-5 変数の通用範囲 11 演習5 11 3-6 動的変数と静的変数 12 3-7 スタック 13 3-8 再帰呼び出し 14 演習6 14

第4章 実習 15 4-1 操作手順 15

第5章 配列 18 5-1 二次元配列の初期化 18 演習7 19

第6章 ポインタ型変数 20 6-1 ポインタ型変数の宣言および参照 20 6-2 ポインタ型変数の初期化 21 演習8 23

第7章 構造体共用体 24 7-1 構造体 24 7-2 共用体 28

第8章 アルゴリズム 30 8-1 ソート 30

第9章 プリプロセッサ 31 9-1 ファイルの挿入 31 9-2 文字の置換 31 9-3 条件によるコンパイル 32

付録1 33 付録2 39 <注意> 本テキストでは(エスケープシーケンス)の表記をyenに統一します

第 1章 入門の復習 C入門で学習した内容について簡単に復習します

(1) プログラム構造

include ltstdiohgt main() 変数などの宣言文 式や if文などの実行文

(2) 変数配列の宣言

int 変数名 float 変数名 char 変数名 double 変数名

int 配列名[n] float 配列名[n] char 配列名[n] double 配列名[n]

(3)定数 整定数 実定数 文字定数

10進数 12 8進数 014 16進数 0xC

125 125e3 125times103を意味します 125e-3 125times10-3を意味します

文字定数 A 文字列定数 ABCDEFG

(4)演算子 算術演算子 関係演算子

インクリメントデクリメント演算子 インクリメント ++ デクリメント - -

加算 + 減算 - 除算 乗算 剰余 代入 = += -= = = =

> 左辺が右辺より大きいときに真 >= 左辺が右辺より大きいか等しいときに真 < 左辺が右辺より小さいときに真 <= 左辺が右辺より小さいか等しいときに真 == 左辺と右辺が等しいときに真 = 左辺と右辺が等しくないときに真

1

(5) 文複文

式 いくつかの文

(6) 条件分岐

if( 式 ) 文1 else 文2

if( 式 ) 文

文1 偽

文2

真 真

文 偽

文m

その他

文1

定数1

文2

定数2 文n 定数n

switch( 式 ) case 定数 1 文1 break case 定数2 文2 break case 定数n 文n break default 文m

(7) 繰り返し

while( 式 ) 文 for( 式1 式2 式3 ) 文 do文 while( 式 )

文 偽

式2

式1

式3

(8) その他

goto ラベル break continue

演習1 ある個人の国語算数理科社会のテストの点数をデータとして入力し合計点と平均点を

計算しなさいそのとき平均点が60点未満の場合はGanbareのメッセージを表示するようにしなさい 入出力例

入力) 60 56 68 54 出力) Total= 238 Average=595 Ganbare

2

第2章 数の表現 2-1 2進数

電子計算機の動作原理は0と1で表される2進数ですまた人間が日常生活で扱っている数

は10進数です10進数と2進数の関係について説明します (1) 2進数(固定小数点)

2進数とは0と1で表される数です 0 1 2進数4桁の数字を表した場合それぞれの位は2nになりますしたがって10進数に変換する

場合には以下のように計算しますまた括弧の添え字は括弧内が何進数で表されているのかを

示します (1 0 1 0)2 (2進数から10進数への変換) 20の位 1times23 + 0times22 + 1times21 + 0times20

21の位 =1 times 8 + 0 times 4 + 1 times 2 + 0 times 0 22の位 =8 + 0 + 2 + 0 23の位 =10 逆に10進数から2進数に変換するには次の手順で行います (10)10 2) 10 2) 5 0 hellip 20 2) 2 1 hellip 21 (10)10=(1010)2 2) 1 0 hellip 22

1 helliphelliphelliphelliphellip 23

仮想的な小数点が常に20の右側に存在することから固定小数点と呼ばれています (1010) 仮想小数点 電子計算機の世界では2進数1桁のことをビット(bit)と呼びますまた2進数8桁(8ビット)の集

りを1バイト(Byte)と呼びます 1バイト(8ビット) 27 26 25 24 23 22 21 20

したがって1バイトまたは2バイト4バイトで表すことのできる最大の数は以下のとおりです 1バイト 2バイト 4バイト 1バイト( 8ビット) 0から255(28-1) 2バイト(16ビット) 0から65535(216-1) 4バイト(32ビット) 0から4294967295(232-1)

3

次に負の場合を考えます負の数を表す場合には2の補数を使用します例えば(-10)10

を1バイトで表すにはまず(10)10の2進数を求めます (10)10 = (00001010)2次にその2の補数を得るために次の計算を行います (100000000)2 -( 00001010)2

( 11110110)2 (-10)101バイト2バイト4バイト長の符号付きデータの場合正負を表すために最上位ビットを符号ビッ

ト(S)として使用します 1バイト 2バイト 4バイト 1バイト( 8ビット) -128~127 2バイト(16ビット) -32768~32767 4バイト(32ビット) -2147483648~2147783647

S

S

S

(2) 2進数(浮動小数点) 2進数の浮動小数点形式は次のように表現されます (1 11 1)2 (2進数から10進数への変換) 2-2の位 1times21 + 1times20 + 1times2-1 + 1times2-2

2―1の位 = 2 + 1 + 05 + 025 20の位 = 375 21の位 計算機の内部では浮動小数点型データは以下の形式になっています

[パーソナルコンピュータの場合] 4バイト データ値=

4バイト 8バイト

演習2 次の10進数は2

a)(33)10 d)(00010100)

(-1)Stimes(05+(M2))times2E-128 有効桁数 10進数約 7桁 大きさ 10-38から1038

有効桁数 10進数約16桁 大きさ 10-38から1038

仮数部 M 指数部 E S

仮想小数点位置

進数に2進数は10進数に変換しなさい負の値は1バイトで表しなさい b)(125)10 c)(21)10

2 e)(11111111)2 f)(00001111)2

4

2-2 8進数と16進数 (1) 8進数

8進数とは0から7までの数字で表される数です (3 7 6 4)8 (8進数から10進数への変換) 80の位 3times83 + 7times82 + 6times81 + 4times80

81の位 = 3times512 + 7times64 + 6times8 + 4times1 82の位 = 1536 + 448 + 48 + 4 83の位 = 2036

(2) 16進数

16進数とは0から9およびAからFの文字で表される数ですABCDEFは10進数の

101112131415に対応します (1 2 A B)16 (16進数から10進数への変換) 160の位 1times163 + 2times162 + Atimes161 + Btimes160

161の位 = 1times4096 + 2times256 + Atimes16 + Btimes1 162の位 = 4096 + 512 + 160 + 11 163の位 = 4779

5

2-3 文字コード 文字 A などは8ビットのデータとして定義(コード化)されています文字コードの種類もいく

つかありUNIX や MS-DOS では ASCII コードを使用していますまた汎用機などではEBCDIC コードを使用しています

(1) ASCIIコード表(JIS8ビット)

上位4ビット

0 1 2 3 4 5 6 7 8 9 A B C D E F

0 SP 0 P p ― タ ミ 1 1 A Q a q ア チ ム 2 ldquo 2 B R b r 「 イ ツ メ 3 3 C S c s 」 ウ テ モ 4 $ 4 D T d t エ ト ヤ 5 5 E U e u オ ナ ユ 6 6 F V f v ヲ カ ニ ヨ 7 BE

L lsquo 7 G W g w ァ キ ヌ ラ

8 BS ( 8 H X h x ィ ク ネ リ 9 TAB ) 9 I Y i y ゥ ケ ノ ル A LF J Z j z ェ コ ハ レ B ESC + K [ k { ォ サ ヒ ロ C < L ¥ l | ャ シ フ ワ D CR - = M ] m } ュ ス ヘ ン E > N ^ n ~ ョ セ ホ ゛ F O _ o DE

L ッ ソ マ ゜

下位4ビット

したがって文字Aは ASCII コードで次のようになります A = (41)16

演習3

ASCII コード表を使って次の文字コードを16進数で表しなさい a) 9 b) M c) g

6

第3章 関数 3-1 関数とは

Cではプログラムの単位は関数で定義されますここでいう関数とは数学などで使われる

sincos 関数と同様の概念でありある値を与えると何らかの処理を行いその結果が関数値となるものですもちろんmain() も一つの関数ですその他にも自由に関数を作ることができます

例えば関数

f(x)=4x2+2x+5 を計算するときには次のようにプログラムを分けることができます データxを入力して関数f(x)を呼び出しその結果を印刷するプログラム 関数f(x)を計算するプログラム これをプログラムで表すと次のようになります

include ltstdiohgt main() float x y f() 変数と関数の型の宣言

while( scanf( f ampx ) = EOF ) y = f( x ) 関数の引用

printf( yenn x=f f(x)=f x y ) float f( float x ) 関数の定義

float y y = 40 x x + 20 x + 50 return y 計算を終了し結果を戻します

関数 f(x)は与えられたxの値によりyを計算して main()に結果を返します

3-2 関数の形式 関数を定義する場合には次の形式で定義します

型 関数名(仮引数の並び) float f ( float x )

変数の型宣言 関数内で使用する変数の宣言 プログラム プログラム }

関数の定義で型の指定がない場合にはint 型の関数となりますまた関数名は31文字以内の英数字の組み合わせです

3-3 引数

関数に渡すパラメータを引数といいますmain()関数などのように関数を引用する場合のパラメータを実引数と呼び呼ばれる関数で使用されているパラメータを仮引数と呼びます

include ltstdiohgt

7

main() float x y f() 変数と関数の型の宣言

while( scanf( f ampx ) = EOF ) y = f( x ) 関数の引用x は実引数と呼びます

printf( yenn x=f f(x)=f x y ) float f( float x ) 関数の定義x は仮引数と呼びます

float y y = 40 x x + 20 x + 50 return y 計算を終了し結果を戻します

[入力の終了について]

このプログラムを実行すると永遠とデータ入力を求められてしまいます終了条件が = EOF の場合はキーボードから CTRLキーを押しながら Z を入力することにより while文を抜け入力を終了することができます

複数の引数を受け渡しする場合には引用する側と関数を定義する側とで 引数の並び個数型

を合わせなければなりませんしかし変数名は同じでなくてもかまいません例えば配列 a と bを加算して配列 cに代入する場合には次のようになります

include ltstdiohgt main()

int a[10] = 18 24 56 28 96 51 82 34 65 72 UNIXの場合 static intにする int b[10] = 12 54 69 20 26 84 55 20 44 74 UNIXの場合 static intにする

int c[10] k void matadd() 関数の型宣言

matadd( a b c ) for( k = 0 k lt 10 k++ ) printf( yenn d + d = d a[k] b[k] c[k] ) void matadd( int x[] int y[] int z[] ) 関数の定義

int t for( t = 0 t lt 10 t++ ) z[t] = x[t] + y[t]

演習4 平均値を求める関数average()を作成し10名の数学の得点を読み込みその平均点を求め

るプログラムを作りなさい 「入力例」 「出力例」

45 63900000 78 97

8

この他にも関数にパラメータを渡す方法としてポインタを使用する方法があります文字列を

複写する関数の場合には次のとおりになります関数名は strcopy()最初の引数には複写先の配列名(配列の先頭番地)次の引数には複写元の配列名(配列の先頭番地)です

include ltstdiohgt main() char src[] = tokai dst[80] void strcopy() strcopy( dst src ) printf( syenn dst )

void strcopy( char str1 char str2 ) while( ( str1++ = str2++ ) = yen0 )

また配列の加算を行う関数の場合にもそれぞれの配列名をパラメータとし関数側でポイン

タ型変数として受け取ることができます

include ltstdiohgt main() int a[10] = 18 24 56 28 96 51 82 34 65 72 UNIXの場合 static intにする int b[10] = 12 54 69 20 26 84 55 20 44 74 UNIXの場合 static intにする

int c[10] int k void matadd() matadd( a b c 10 ) for( k = 0 k lt 10 k++ ) printf( d + d = d yenn a[k] b[k] c[k] )

void matadd( int x int y int z int n ) for( n gt 0 n-- ) z++ = x++ + y++

main()関数では配列名(アドレス定数)として引数に指定されていますが関数 matadd()ではポインタ型の変数として使用することができますしたがって変数 xyz は値を変更することができるようになります

配列 a 変数 x

9

配列 b 変数 y 配列 c 変数 x

3-4 戻り値 関数からの戻り値はreturn 文によって返されます整数型文字型の値を返す関数の場合

にはそれぞれ次のように定義します

int sub( int x ) char sub( int x ) int y char z

return y return z

またポインタを返す関数の場合には次のように定義します

int sub( int x ) char sub( int x ) int y char z

return y return z

return文で式の指定がない場合には何も値を返しません

[プログラム例]

文字列(文字型配列)の中に指定した文字があればその位置をポインタで返し無ければ NULLポインタを返す関数を考えてみます

char strfind( char str char ch ) while( str ) if( str == ch )return str str++ return NULL

いくつかのC言語のマニュアルでは関数の説明を以下のように記述しています sin 機能 正弦を求めます 形式 include ltmathhgt double sin( double x ) このとき関数 sin() の戻り値は double 型でありまた指定する引数も double 型でなけれ

ばなりませんそれと同時にこの関数を使用する場合にはinclude ltmathhgt を指定しなければなりません

10

3-5 変数の通用範囲 関数内で宣言された変数はその関数の中でのみ使用可能です他のプログラムからは使用

することはできません

include ltstdiohgt main() int i 変数 i は関数 main() と sub() とでは それぞれ独立に使用することができます main() で変数 i に設定した値は sub() では参照することはできません sub() 逆にsub() で変数 i に設定した値も main() では参照することはできません

int i

それぞれの関数の中でのみ使用可能な変数をローカル変数と呼び他の関数でも使用可能

な変数をグローバル変数と呼びますいくつかの関数で共通に使用するような場合にはグロー

バル変数を使用します グローバル変数を定義する場合には関数の外で宣言します

include ltstdiohgt int i グローバル変数の定義

main() i = 10

sub() extern int i printf( yenn i = d i )

このプログラムではmain() 関数でグローバル変数に値を設定し関数 sub() で変数の値を

参照しています extern 宣言は変数が他のプログラム内で宣言されていることを示しています宣言の形式

は以下のとおりです extern 型 変数並び

演習5 入力された任意の数の倍数を求めるプログラムを作成しなさい入力する数値は2つ倍数 を求めるための任意の数と倍数の上限値ですここでいう上限値とは任意の数の倍数をどの くらいの数まで求めるかということです

11

3-6 動的変数と静的変数 通常Cで使用される変数はその関数の中だけでのみ使用できる変数ですしたがって関数

が実行するときに関数の中で使用する変数の領域を確保し関数の実行が終るときにその領域

を解放するようにしてメモリを効率的に利用していますこのように関数が実行されるときに確

保される変数を動的変数(auto変数 )と呼びます プログラムの中ではその他に常に存在し使用できる変数を定義することができますそのよ

うな変数は静的変数(static変数 )と呼ばれます

func() int a b static int x y

また static 変数には内部的なリンケージの指定の意味もありますつまり関数の外で変数

を宣言すると自動的にグローバル変数となり他のプログラムからも使用することができるようにな

ります ファイル a ファイル b このような場合にはコンパイル単位が異なっていてもextern 宣言を行うことにより変数 abc

を使用することができますところが関数の外で static 宣言をして定義した変数についてはコンパイル単位が違うプログラムからは使用することができなくなります ファイル a ファイル b 同一コンパイル単位(ファイル)に存在する関数 sub()と subd()では変数 abcを使用することが

できますがコンパイル単位(ファイル)が異なる関数 func()では変数 abcを使用することはできません

int abc sub() abc = 10

func() extern int abc printf( ldquo abc =dyennrdquo abc )

static int abc sub() abc = 10 subd() abc++

func() extern int abc printf( ldquo abc =dyennrdquo abc )

12

3-7 スタック プログラム中にはプログラム領域データ領域の他にスタック領域があり一時的な作業領域と

して使用されています関数間での引数の受渡しの時にもこの領域を使用しますスタック領域に

データを格納することを「スタックに積む」ともいいます基本的にはスタック領域に格納されたデ

ータは最後に格納されたデータから順に取り出されることになります以下に格納が行われたとき

のスタックの状態を示します記号は次に格納すべき位置(スタックポインタの値)を示していま

逆にスタックからデータを取り出すときにはスタックポインタが指している位置の一つ下から取

り出すことになりますスタックからデータを取り出すときのスタックの状態は次のようになります

なり

10

20

10

30

20

10

40

30

20

10

10rarr

格納

20rarr

格納

30rarr

格納

40rarr

格納

40rarr 30rarr

関数を呼び出すときには次

逆にそれぞれの関数から

次のようになります

40

30

20

10

取出

main() z = f1( x y )

のようにパラメータがスタ

戻るときにはパラメータで

30

20

10

取出

f1( int a int b ) c = f2( d e

xの値 yの値

xの値 yの値

13

ックに格納されます

使用していたスタック領域は自動的になく

10

20

)

f2( int p int q ) r = p + q

xの値

eの値 dの値

yの値

xの値 yの値

dの値

eの値

3-8 再帰呼び出し 関数の引数の受渡しがスタックを利用して行われることから自分で自分自身の関数を呼び出

すことができます 以下のプログラムは入力した値の階乗を計算するプログラムです

3の階乗を求めることを考えてみます

return 文によって戻るときは次のようにして値を返します kai( 3 ) 3 kai( 3-1 ) 2 kai( 2-1 ) return 1

6 3 (2 1) 2 1 以上の計算から3=6が導き出されます 再帰呼び出しのことをリカーシブコールともいいます

include ltstdiohgt main() int n m kai() scanf( ldquodrdquoampn ) m = kai( n ) printf( ldquod = dyennrdquo n m )

int kai( int k ) if( k == 1 )return 1 else return k kai( k ndash 1 )

kai( 1 )

darr

return 1

kai( 2 )

darr

2 kai( 2-1 )

kai( 3 )

darr

3 kai( 3-1 )

main()

darr

kai( 3 )

3

2

1

2

3

1

2

3 3

32

32

1

2

1

3

3

演習6 1からnまでの総和を再帰呼び出しを使って計算する関数 sowa() を作りなさい n+(n-1)+ +2+1

14

第4章 実習 この章ではプログラムを実際に入力して実行するまでの手順を実習します

4-1 操作手順 (1)ログイン

[スタート]rarr[プログラム(P)]rarr[ネットワーク] Hostの欄に bosei を記述選択 rarr [Telnet(FreeWare)] を選択します して 「OK」 ボタンをクリックします

UP-UXV (Rel42MP) (bosei) (pts41) login 60us1234 larr 各自のログイン名を入力します Password larr パスワードを入力しても画面は何も変化しません 101 60us1234bosei larr セッションが開設されましたこれをプロンプトといいます この状態でコマンドを入力することができます

(2)プログラムの作成 以下のコマンドを入力しテキストエディタを起動します 60us1234boseicc ng rensyuc

すると下図のようにngエディタの画面になります

15

次のように入力します入力ミスの修正はBSキーで行ないます

include ltstdiohgt main() float abc scanf(f f ampaampb) c=ab printf(f f f yenn abc)

CTRL キーを押しながら XCTRL キーを押しながら C を押しますすると次のメッセージが画面下に表示されます

Save file uhomea60us1234rensyuc (y or n)

このメッセージに対して y と答えます

(3)データの作成 以下のコマンドを入力しテキストエディタを起動します 60us1234boseicc ng rensyud

ngエディタの画面になりますので次のように入力します 12 35

CTRLキーを押しながら XCTRLキーを押しながら C を押します save file uhomea60us1234rensyud (y or n)

このメッセージに対して y と答えます

(4)コンパイルと実行 コンピュータに処理を依頼します 60us1234boseicc ccg rensyu

ジョブを投入しましたジョブの状態を見るコマンドは myjobです

16

130 60us1234boseicc myjob ================================================= NQS (R0220) BATCH REQUEST HOST bosei ================================================= REQUEST ID NAME OWNER QUEUE PRI NICE STT PGRP R --------------- -------- -------- -------- ---- --- --- ------ - 99321bosei STDIN 60us1234 A 31 0 RUN 14161 - ---------------------------------------------------------------- ================================================== NQS (R0220) DEVICE REQUEST HOST bosei ジョブは実行中です

================================================== REQUEST ID NAME OWNER QUEUE PRI SIZE STT -------------------------------------------------------------

所有するファイルの一覧を見てみます

60us1234boseicc ls -l larr 持っているファイルの一覧を見るコマンドです

-rw-r--r-- 1 60us1234 other 4 4月26日 15時14分 rensyud -rw-r--r-- 1 60us1234 other 128 4月26日 15時10分 rensyuc -rwxr-xr-x 1 60us1234 other 361 4月26日 15時16分 rensyul

(5)計算結果の確認

計算結果を画面に表示して確認します 60us1234boseicc more rensyul

(6)印刷

計算結果の印刷を行ないます5号館2階のカフェテリア室にある bosei のプリンタに印刷 されます

60us1234boseicc lpr rensyul

(7)ログアウト セッションを終了します 60us1234boseicc logout

(8)実行の流れ

エラー

プログラムの作成 ログイン コンパイル実行

確 認 印 刷 ログアウト

17

第5章 配列 多数の変数をまとめて宣言する方法として配列があります配列の一つ一つは配列要素と呼

ばれ変数と同じ性格を持っています配列の宣言は型宣言と同時に次のように行います int a[5] 配列 a

a[0]

a[1]

a[2]

a[3]

a[4]

二次元配列(一次元配列を複数集めたもの)を宣言する場合には次のようになります int b[3][4] 配列 b

b[0][0] b[0][1] b[0][2] b[0][3]

b[1][0] b[1][1] b[1][2] b[1][3]

b[2][0] b[2][1] b[2][2] b[2][3]

配列要素に数値を代入する場合は次のようになります b[1][2]=10

5-1 二次元配列要素の初期化 変数の型宣言と同じように配列を宣言するときに初期値も同時に設定することができます

複数のデータがある場合には{}記号でくくって指定します int b[3][4] = 2 4 6 8 1 3 5 7 1 2 3 4

文字型配列の場合には以下のようになりますyen0 は文字列の終わりを表わします char univ[3][7] = T O K A I yen0 S I M I Z U yen0 Y O Y O G I yen0

また文字列定数として初期化することもできますこの場合コンパイル時に自動的に yen0 が付加されます

char univ[3][7] = TOKAI SIMIZU YOYOGI

18

[プログラム例] 二次元配列のタテヨコを加算するプログラム

include ltstdiohgt main() int mat[4][3]=123456789101112 int ijytotalttotal[3]total=0 for(j=0jlt3j++)ttotal[j]=0 for (i=0ilt4i++) ytotal=0 for(j=0jlt3j++) ytotal += mat[i][j] ttotal[j] += mat[i][j] total += mat[i][j] printf(3dmat[i][j]) printf( 3dyennytotal) printf(yenn) for(j=0jlt3j++)printf(3dttotal[j]) printf( 3dyenntotal)

[実行結果]

1 2 3 6 4 5 6 15 7 8 9 24 10 11 12 33 22 26 30 78

演習7

a)以下の配列はどのように初期化されるか答えなさい char errmsg[2][15] = Divide Error Overflow Error

b)九九の計算を2次元配列を使って求めなさい

19

第6章 ポインタ型変数 C言語では値を記憶するための変数だけではなく変数または定数の番地を記憶するため

のポインタ型変数を宣言することができますポインタとはデータ項目の一種で「記憶装置(メモ

リ)上の格納番地(アドレス)を指すデータ項目」です アドレス コンピュータの中ではデータ項目の格納番地のことをアドレス(住所)と呼びます 例えば記憶装置という名前のとてつもなく大きなマンションがあるとしますその中から Aさんを捜すときは部屋番号を参照しますマンションでは部屋番号で住居人を参照し ているのと同じようにコンピュータでは記憶装置上に確保された変数は格納番地 (アドレス)で管理されています

マンション 部屋番号 記憶装置 格納番地

Aさん Int a Bさん Cさん AAAさん BBBさん CCCさん

1号室

2号室

3号室

100号室

200号室

300号室

100番地

200番地

300番地

1000番地

2000番地

3000番地

Int b Int c float aaafloat bbbfloat ccc

ポインタ ポインタとは「指し示すもの」の意ですがC言語では記憶装置上のアドレスを指し示す もののことです上のマンションの例では部屋番号を格納するデータ項目ということに なりますAAAさんは100号室に住んでいます100という値をポインタのデータ項目に 記憶するとそのデータ項目は間接的にAAAさんを指すことになります

6-1 ポインタ型変数の宣言および参照 通常の変数と区別するために型宣言時に変数名の前に記号を付けて宣言します int a 整数型ポインタ変数 int b 整数型変数

変数 a は整数型の値を記憶するのではなく整数型の値を持つ変数などの番地を記憶する変数ですまた変数 b は通常の整数型の値を記憶するための変数です

20

include ltstdiohgt main() int a b c a はポインタ型の変数b c は整数型の変数 b = 12 変数 b に値 12 を代入します a = ampb 変数 a には変数 b の番地が代入されます c = a + 10 変数 a の指す変数(b)の内容と10の加算です つまり12 + 10 を変数 c に代入します

変数の型宣言において変数名に記号を付けることによりその変数はポインタ型の変数と

なりますポインタ型の変数は変数名のみを指定した場合には単にその変数の値(通常はメモリ

の番地)を表します変数名に記号を付けて使用した場合にはその変数が指し示している変

数の内容を表します c = a ポインタ型変数 a が指している値を変数 c に代入

ポインタ型の変数に番地を記憶させるためにはプログラム例のように変数名の前に記号を

指定します変数名 によって変数の番地(アドレス)を表します a = ampb 変数 b の番地をポインタ型変数 a に代入します

ポインタ型変数の型はポインタ型変数が指し示す先の変数の型を表しています int a 変数 a 整数型の値 float x 変数 x 実数型の値 char c 変数 c 文字型の値

6-2 ポインタ型変数の初期化 ポインタ型変数も型宣言のときに変数を初期化することができます特に文字型のポインタ変

数の場合によく使います char str = TOKAI University

ポインタ型変数 str は文字列定数 TOKAI University の最初の文字が格納されている番地を初期値として持つことになります

変数 str TOKAI University 文字列定数

[プログラム例]

(1)文字型配列 putchar() 関数を使って一次元の文字型配列を出力します include ltstdiohgt main() char str[6] = TOKAI int i for( i = 0 str[i] = yen0 i++ ) putchar( str[i] )

21

ポインタを使用した場合には以下のようになります include ltstdiohgt main() char str[6] = TOKAI char chp for( chp = str chp = yen0 chp++ ) putchar( chp )

chp str T [0] O K A I yen0 [5]

参照する変数 配列の表現 ポインタの表現 実際のアドレス 1番目の数 str[0] chp CHP 2番目の数 str[1] (chp+1) CHP+1 n番目の数 str[n-1] (chp+n-1) CHP+n-1 6番目の数 str[5] (chp+5) CHP+5

注意実際のアドレス CHPは実行時に決定されます

(2)二次元文字型配列 二次元の文字型配列に定数を設定しそれを出力するプログラムです文字型配列を使用す

ると次のとおりになります include ltstdiohgt main() char str[5][40] = TOKAI shounan campus NEC DEC int i for( i = 0 i lt 5 i++ ) printf( yenns str[i] )

40 バイト str TOKAI shounan campus NEC DEC

22

ポインタ型配列を使用すると次のとおりになります include ltstdiohgt main() char str[6] = TOKAI shounan campus NEC DEC NULL char chp for( chp = str chp = NULL chp++ ) printf( yenns chp ) str

chp 番地 TOKAI 番地 shounan 番地 campus 番地 NEC 番地 DEC

NULL

演習8 キーボードまたはデータファイルから読み込んだ文字列中にrsquoArsquo があったら rsquoarsquo に変換 するプログラムを配列とポインタを使って書きなさい

23

第7章 構造体共用体 7-1 構造体

プログラムの規模が大きくなるにつれて多数の intや floatcharなどのデータ型を扱うようになり複雑になってきますそこで多数のデータを1つにまとめて簡単に扱える機能が構造体です 構造体について住所録のデータを例にあげて考えてみます

住所録の個人データとして氏名住所電話番号年齢の項目を一つのデータとします これをC言語で変数の定義をすると次のようになります 氏名東海太郎 char name[30] 住所平塚市北金目1117 char address[30] 電話番号0463-58-1211 char tel[20] 年齢30 int age 個人の住所録データ C言語での表現 このような住所録の個人データを1つにまとめて新しいデータとして定義する機能を構造体と言

います struct 構造体タグ名 構造体メンバーの並び

「struct」は構造体を表すキーワードです 「構造体タグ名」は構造体の型枠を宣言しますここは自由に名前を定義することができ ます 「構造体メンバーの並び」は構造体の要素です複数指定できます

個人の住所録のデータを構造体で宣言すると次のようになります

struct jusho char name[30] char address[30] 構造体のメンバーの並び char tel[20] (複数可)

int age

上記の宣言では構造体の形式を宣言しているだけでメモリ中で実際の領域を確保している

わけではありません実際に領域を確保するためには次のように定義します

struct 構造体タグ名 構造体名

したがって構造体名を jdata とすると次のように指定します

struct jusho jdata

構造体 jdataは次のように構造体タグ jushoの形式で領域を確保します

24

Jdata name[30]

address[30] tel[20] age

(1)構造体の参照

プログラム中で構造体中のメンバーを参照する場合には次のように指定します 構造体名メンバー名

したがって「名前」を参照したいときには次のように指定します

jdataname

[プログラム例]

名前住所電話番号年齢を定義しそれを印字します include ltstdiohgt include ltstringhgt main() struct jusho char name[30] char address[30] char tel[20] int age struct jusho jdata strcpy( jdataname 東海 太郎) strcpy( jdataaddress 平塚市北金目1117)

strcpy( jdatatel 0463-58-1211) jdataage = 30 printf(yenn氏名 = syenn jdataname) printf(yenn住所 = syenn jdataaddress) printf(yenn電話番号= syenn jdatatel) printf(yenn年齢 = dyenn jdataage)

また構造体の形式の定義と領域の確保は次のように同時におこなうことができます

struct 構造体タグ名 構造体メンバーの並び 構造体名

struct jusho struct jusho char name[30] char name[30] char address[30] char address[30] char tel[30] = char tel[30] int age 同じ int age

jdata struct jusho jdata

型宣言と同時にメモリ上に領域を確保する方法 後からメモリ上に領域を確保する方法

25

(2) 構造体配列 住所録データの場合その中に入るデータは1件ではありませんやはり100件200件のデ

ータが必要になる場合がありますこのように個人単位のデータを多数扱う場合には構造体を配

列として宣言することができます 次の例は個人のデータを100個用意するために構造体を配列として宣言しています struct jusho jdata[100] jdata[0] name[30] address[30] tel[20] age

jdata[99 ] name[30] address[30] tel[20] age

(3)構造体配列の参照

プログラム中で構造体配列中のメンバーを参照する場合には次のように指定します 構造体名[要素番号]メンバー名

したがって10件目の人の「名前」を参照したいときには次のように指定します

jdata[10]name

[プログラム例]

名前住所電話番号年齢を定義しそれを印字します include ltstdiohgt include ltstringhgt main() struct jusho char name[30] char address[30] char tel[20] int age jdata[100] strcpy( jdata[10]name 東海 太郎) strcpy( jdata[10]address 平塚市北金目1117)

strcpy( jdata[10]tel 0463-58-1211) jdata[10]age = 30 printf(yenn氏名 = syenn jdata[10]name) printf(yenn住所 = syenn jdata[10]address) printf(yenn電話番号= syenn jdata[10]tel) printf(yenn年齢 = dyenn jdata[10]age)

26

(4) 構造体のポインタ 変数と同じように構造体へのポインタも定義することができます

変数へのポインタ例 構造体へのポインタ例 またポインタを使用して構造体メンバーを参照するには次のように -> 記号を使って指

定します ポインタ変数名 -> メンバー名

[プログラム例]

名前住所電話番号年齢を定義しそれを印字します include ltstdiohgt include ltstringhgt main() struct jusho char name[30] char address[30] char tel[20] int age jdatakp kp = ampjdata strcpy( kp-gtname 東海 太郎)

strcpy( kp-gtaddress 平塚市北金目1117)

strcpy( kp-gttel 0463-58-1211) kp-gtage = 30 printf(yenn氏名 = syenn kp-gtname) printf(yenn住所 = syenn kp-gtaddress) printf(yenn電話番号= syenn kp-gttel) printf(yenn年齢 = dyenn kp-gtage)

kp jdata

name[30] ポインタ型の変数 address[30]

tel[20]

構造体へのポインタを記憶 age

することができます

int a int b b = ampa

struct name jname struct name np np = ampname

27

7-2 共用体 共用体は構造体と同じようにして宣言しますが共用体は複数のデータ型を同一のアドレスに

割り当てる方法です union 共用体タグ名 共用体メンバーの並び

「union」は共用体を表すキーワードです 「共用体タグ名」は共用体の型枠の名前を宣言しますここは自由に名前を定義することがで

きます 「共用体メンバーの並び」は共用体の要素です複数指定できます

共用体の宣言の例を次に示します

union c_tag int a char b

共用体 cは次のように共用体タグ c_tagの形式で領域を確保します共用体はメモリ上に領域を確保するときは ab ともに同じ領域に割り付けられます これはab という2つのデータが同時に存在するわけではなく cを異なるデータ abで共有す

ることを表しています c a b

上記の宣言だけでは共用体の形式を宣言しているだけでメモリ中で実際の領域を確保して

いるわけではありません実際に領域を確保するためには次のように定義します union 構造体タグ名 構造体名

したがって共用体名を c とすると次のように指定します

union c_tag c

(1)共用体の参照

プログラム中で共用体中のメンバーを参照する場合には次のように指定します 共用体名メンバー名

したがって「a」または「b」を参照したいときには次のように指定します

ca (int 型) cb (char 型)

メンバー参照方法によって int型として使ったりchar型として利用することができます

28

[プログラム例]

includeltstdiohgt main() union data char a short b int c chk chkc = 0x12345678 printf( char a xyennchka) printf( short b xyennchkb) printf( int c xyennchkc)

chkb(int 型) chkb(short 型) chka(char 型) 12 12 12 34 34 56 78

29

第8章 アルゴリズム コンピュータに何か仕事をさせようとするときは仕事を具体的に実行するための処理や動作

の手順が必要ですこの「手順」がアルゴリズムです アルゴリズムを考えるときは解くべき問題をはっきりと定義することが必要です

8-1 ソート ソートとは与えられたデータを小さい順または大きい順に並べ換えることですソート方法は

いくつかありますが基本的な方法でソートするアルゴリズムを紹介します

includeltstdiohgt int data[10] main()

int data_in() sort() data_in() sort() int data_in() データ入力関数

int a printf(数値入力yenn)

for(a=0alt=9a++) printf( [d]a+1) scanf(dampdata[a]) int sort() ソート処理を行う関数

int cont1cont2tmp1tmp2mim for(cont1=0 cont1lt=9 cont1++) mim=data[cont1] tmp1=cont1 for(cont2=cont1+1 cont2lt=9 cont2++) if(data[cont2] lt mim) mim=data[cont2] tmp1=cont2 tmp2 = data[cont1] data[cont1] = data[tmp1] data[tmp1] = tmp2 printf(結果 yenn)

for (cont1 = 0 cont1 lt= 9 cont1++) printf(d yenn data[cont1])

30

第9章 プリプロセッサ C言語にはプログラムの中でコンパイルについての指示を行う「プリプロセッサ」という機能が

ありますまたプリプロセッサとはコンパイルする前に実行されるためその意味のとおり「前処理」 と呼ばれていますここでは代表的なものをいくつか説明します

9-1 ファイルの挿入 ソースプログラム中に指定されたファイルを挿入します

include ltstdiohgt helliphellip 標準ディレクトリを探します include progh helliphellip 現在のディレクトリを探しなければ標準ディレクトリを探します

includeltstdiohgt によって組み込まれた define EOF (-1) define EOF (-1) define define helliphelliphelliphellip 組み込み helliphelliphelliphellip

main() stdiohファイル

int helliphelliphelliphellip helliphelliphelliphellip

ソースファイル

9-2 文字の置換 プログラム中に使われている文字列を別の文字列に置き換えます

include ltstdiohgt define TRUE 1 define EOF (-1) main() define helliphellip helliphellip

while(TRUE) define TRUE 1 置き換え main() helliphellip helliphellip while(1)

break helliphelliphellip

31

9-3 条件によるコンパイル 識別子が定義されているか否かを判断しコンパイルする範囲を指定します

include ltstdiohgt define UNIX main() ifdef UNIX printf( UNIX yenn) else printf(MS-DOSyenn) endif

include ltstdiohgt define OS UNIX main() if OS == UNIX printf( UNIX yenn) else printf(MS-DOSyenn) endif

32

付 録 1 puts()gets()関数について

行単位に入出力を行う場合には puts() gets() 関数を用います

puts() 標準出力に文字列を出力します

include ltstdiohgt int puts( char s ) puts() は NULL で終る文字列 s を標準出力に出力し最後に改行文字 yenn も出力しま

gets() 標準入力から文字列を入力します

include ltstdiohgt char gets( char s ) 戻り値正常に入力した場合には引数 s の値が返されますエラーやEOFになった場合に

は NULL が返されます gets() は標準入力から復帰文字で終る文字列を入力しs に格納しますこのとき最後の復

帰文字は NULL文字に変更されます

入力行の出力 標準入力から gets() で入力したデータには改行コードは含まれませんまた標準出力へ

puts() で出力を行う場合には必ず改行コードが付加されますgets() を実行したときの戻り値としてファイルの終端を検出した場合には EOF ではなく NULL が返されますので注意して下さい

include ltstdiohgt main() char data[80] while( gets( data ) = NULL )puts( data )

putchar()getchar()関数について putchar() 標準出力に文字を出力します

include ltstdiohgt int putchar(int c ) 戻り値正常に出力できた場合には文字cをエラーの場合にはEOFを返します

33

getchar() 標準入力から文字を入力します

include ltstdiohgt int getchar(void) 戻り値正常に入力した場合には読み込んだ文字を int 型に変換して返しますまたファイ

ルエンドエラーの場合にはEOFを返します

標準入力標準出力

標準入力標準出力はプログラムが開始されるときにはオープンされていますそれぞれのフ

ァイルポインタは stdin stdout になっていますfopen() fclose() をせずとも使用することができます

scanf() 標準出力ストリームからテキストを読み込み解釈します include ltstdiohgt int scanf( const char format [ address ] ) 戻り値正しくスキャンし変換し格納した入力フィールドの数を返しますファイルエンドを読

み込んだ場合は戻り値は EOF となります値を格納したフィールドがなかった場合は戻り値は0となります

一連の入力フィールドをスキャンして1度に1文字ずつストリーム stdin から文字を読み込み

ます次に引き数 format によって指される書式文字列中の書式指定に従って各フィールドを書式化します最後にformat の後に続く各引き数が示しているアドレスに書式化した入力を格納していきます書式文字列中の書式指定の個数はその後に続くアドレスの数と同じでな

ければなりません 書式指定[入力幅][型指定文字] 入力幅 読むべき文字数の最大値 型指定文字 次のとおりです 型指定文字 期待される入力 引き数の型 d 10進整数 int へのポインタ( int arg ) x 16進整数 int へのポインタ( int arg ) f 浮動小数点数 float へのポインタ( float arg ) s 文字列 文字配列へのポインタ( char arg[] ) c 文字 文字へのポインタ( char arg )

printf() フォーマットを指定してテキスト標準出力ストリームに出力します include ltstdiohgt int printf( const char format [ argument ] ) 戻り値出力したバイト数を返しますエラーの場合は EOF を返します

34

format によって指される書式文字列中の書式指定をformat の後に続く各引き数に適用し

書式化されたデータを stdout に出力します書式指定は後に続く引き数と同じ数だけなければなりません

書式指定[印字幅][精度][型指定文字] 印字幅 印字する最小文字数 精度 印字する最大文字数 型指定文字 つぎのとおりです 型指定文字 入力引き数 出力の書式 d 整数 符号付き10進整数 x 整数 符号無し16進整数 f 浮動小数点 符号付きの dddddddd形式の値 c 文字 1個の文字 s 文字列ポインタ ヌル文字に出会うか精度に達するまで 文字をプリントする

fopen()fclose()関数について fopen() ファイルをオープンします

include ltstdiohgt FILE fopen( char filename char mode ) 戻り値正常にファイルのオープンができたらファイルポインタを返しますエラーがあった場

合には NULLを返します 文字列 filename で指定されたファイルをオープンしますオープン後の入出力のモードに

ついては文字列 mode で指定しますmode に指定できる文字は以下のとおりです r 入力モードでオープンします w 出力モードでオープンします a 存在するファイルに追加して出力するモードでオープンします r+ 既に作成してあるファイルを更新(入力出力)するモードでオープンします w+ 新しく作成するファイルを更新モードでオープンします a+ 既に作成してあるファイルの終りから更新用に作成します

以上の文字に b をつけ加えることによりバイナリモードで入出力することができるようになり

ます rb バイナリの入力モードでオープンします wb バイナリの出力モードでオープンします ab 存在するファイルに追加して出力するモード(バイナリ)でオープンします

fclose() 既にオープンしてあるファイルをクローズします include ltstdiohgt fclose( FILE fp ) 既にオープンしているファイルをクローズしますパラメータには fopen() 関数により返された

ファイルポインタを指定します

35

テキストモードとバイナリモード 行の最後はテキストモードの場合改行コードのみとなりバイナリモードの場合には復帰

コードと改行コードの組合わせになります行の最後としてテキストファイルには復帰コード改行

コードが書かれていますがテキストモードでオープンした場合には入力すると改行コードのみに

変換されて入力されますバイナリモードの場合には復帰コード改行コードがそれぞれ入力され

ます

fputs()fgets()関数について fputs() ファイルポインタで指定されるファイルに文字列を出力します

include ltstdiohgt

int fputs( char s FILE fp ) fputs() は NULL で終る文字列 s をファイルポインタに示されるファイルへ出力しますputs()

と違い最後に改行文字 yenn を出力することはありません

fgets() ファイルポインタで指定されるファイルから文字列を入力します include ltstdiohgt char fgets( char s int n FILE fp ) 戻り値正常に入力した場合には引数 s の値が返されますエラーやEOFになった場合に

は NULL が返されます fgets() はファイルポインタで指定されるファイルから ( n - 1 ) 文字または改行文字までの

文字列を入力しs に格納しますgets() と異なり最後に入力された改行文字は NULL 文字に変更されません

標準入力から入力しファイルへ出力する ファイルへ出力あるいは入力を行う場合には改行コードの変換(入力の場合の削除出力の

場合の付加)はされませんしたがって標準入力から入力しファイルへ出力する場合には改行

コードを付加しなければなりません include ltstdiohgt main() char data[80] FILE fp fp = fopen( data w ) while( gets( data ) = NULL ) strcat( data yenn ) 改行コードの付加

fputs( data fp ) fclose( fp )

36

fputc()fgetc()関数について fputc() ファイルポインタで指定されるファイルに1文字出力します

include ltstdiohgt int fputc( int c FILE fp ) 戻り値正常に出力できた場合には文字 c を返しエラーの場合には EOF を返します fputc() は文字 c をファイルポインタで示されるファイルへ出力します

fgetc() ファイルポインタで指定されるファイルから1文字入力します

include ltstdiohgt int fgetc( FILE fp ) 戻り値正常に入力した場合には入力した文字を返しますエラーやEOFになった場合には

EOF が返されます fgetc() はファイルポインタで指定されるファイルから文字を入力します

ファイルの内容の表示 include ltstdiohgt main() FILE fp int ch char fname[30] printf( Key in Fila name gt ) gets( fname ) fp = fopen( fname r ) while( ( ch = fgetc( fp ) ) = EOF )putchar( ch ) fclose( fp )

その他テキスト中で使用された関数について sin() 三角関数の正弦を計算します

include ltmathhgt double sin(double radian) sinはラジアンを単位とする引数 radianの三角関数を計算します

37

strcpy() 文字列を他の文字列へコピーします

include ltstringhgt char strcpy(char string1const char string2) strcpyは引数 string2の指す文字列を null文字まで含めて引数 string1の指す領域にコピ

ーする strcpyは string1を返します

strcat() ある文字列を他の文字列に加えます

include ltstringhgt char strcat( char dest const char src ) 戻り値連結された文字列へのポインタを返します strcat() はsrc のコピーを dest の最後につけ加えます得られる文字列の長さは

strlen(dest)+strlen(src) になります

fabs() 絶対値の計算をします include ltmathhgt double fabs(double z) fabsは倍精度浮動小数の絶対値を計算して返しますつまりzgt=0であれば z をzlt0であ

れば-zを返します exp() 指数関数を計算します

include ltmathhgt double exp(double z) exp は引数zの指数関数つまりezを返すここではeは自然対数の底を表します対数関

数logの逆関数です

38

付 録 2 コンパイルの方法には大きく分けて第4章の実習で学んだようにデータファイルを作成してお

き ccg でコンパイルさせる方法と実行中に対話型でデータを入力していく方法があります ここでは対話型で実行を進めていく方法を紹介します ただしこの方法は計算(cpu)時間が10秒以内のものに限ります10秒を超える計算(cpu)時

間を要する場合はccg でコンパイルをするようにしてください 第4章実習の(2)(p16)までは同様です

コンパイル

コンピュータに処理を依頼します 60us1234boseicc cc rensyuc

所有するファイルの一覧を見てみます

60us1234boseicc ls -l larr 持っているファイルの一覧を見るコマンドです

-rw-r--r-- 1 60us1234 other 128 4月26日 15時14分 rensyuc -rwxr-xr-x 1 60us1234 other 361 4月26日 15時16分 aout

aout という実行形式のファイルが作成されています

実行

60us1234boseicc aout12 35[リターン] データを入力

1 200000 3500000 4200000 実行結果の出力

60us1234boseicc

注意

aout ファイルは印刷することができません実行結果を印刷する場合にはファイルに落とし てから出力するようにしましょう

60us1234boseicc aout gt kekka12 35[リターン] データを入力

60us1234boseicc more kekka 計算結果の確認 60us1234boseicc lpr kekka 計算結果の印刷

39

Page 3: n 第1章 章立ての部分は、書式(PC入門大見出し)を …第2章 数の表現 2-1 2進数 電子計算機の動作原理は0と1で表される2進数です。また、人間が日常生活で扱っている数

第 1章 入門の復習 C入門で学習した内容について簡単に復習します

(1) プログラム構造

include ltstdiohgt main() 変数などの宣言文 式や if文などの実行文

(2) 変数配列の宣言

int 変数名 float 変数名 char 変数名 double 変数名

int 配列名[n] float 配列名[n] char 配列名[n] double 配列名[n]

(3)定数 整定数 実定数 文字定数

10進数 12 8進数 014 16進数 0xC

125 125e3 125times103を意味します 125e-3 125times10-3を意味します

文字定数 A 文字列定数 ABCDEFG

(4)演算子 算術演算子 関係演算子

インクリメントデクリメント演算子 インクリメント ++ デクリメント - -

加算 + 減算 - 除算 乗算 剰余 代入 = += -= = = =

> 左辺が右辺より大きいときに真 >= 左辺が右辺より大きいか等しいときに真 < 左辺が右辺より小さいときに真 <= 左辺が右辺より小さいか等しいときに真 == 左辺と右辺が等しいときに真 = 左辺と右辺が等しくないときに真

1

(5) 文複文

式 いくつかの文

(6) 条件分岐

if( 式 ) 文1 else 文2

if( 式 ) 文

文1 偽

文2

真 真

文 偽

文m

その他

文1

定数1

文2

定数2 文n 定数n

switch( 式 ) case 定数 1 文1 break case 定数2 文2 break case 定数n 文n break default 文m

(7) 繰り返し

while( 式 ) 文 for( 式1 式2 式3 ) 文 do文 while( 式 )

文 偽

式2

式1

式3

(8) その他

goto ラベル break continue

演習1 ある個人の国語算数理科社会のテストの点数をデータとして入力し合計点と平均点を

計算しなさいそのとき平均点が60点未満の場合はGanbareのメッセージを表示するようにしなさい 入出力例

入力) 60 56 68 54 出力) Total= 238 Average=595 Ganbare

2

第2章 数の表現 2-1 2進数

電子計算機の動作原理は0と1で表される2進数ですまた人間が日常生活で扱っている数

は10進数です10進数と2進数の関係について説明します (1) 2進数(固定小数点)

2進数とは0と1で表される数です 0 1 2進数4桁の数字を表した場合それぞれの位は2nになりますしたがって10進数に変換する

場合には以下のように計算しますまた括弧の添え字は括弧内が何進数で表されているのかを

示します (1 0 1 0)2 (2進数から10進数への変換) 20の位 1times23 + 0times22 + 1times21 + 0times20

21の位 =1 times 8 + 0 times 4 + 1 times 2 + 0 times 0 22の位 =8 + 0 + 2 + 0 23の位 =10 逆に10進数から2進数に変換するには次の手順で行います (10)10 2) 10 2) 5 0 hellip 20 2) 2 1 hellip 21 (10)10=(1010)2 2) 1 0 hellip 22

1 helliphelliphelliphelliphellip 23

仮想的な小数点が常に20の右側に存在することから固定小数点と呼ばれています (1010) 仮想小数点 電子計算機の世界では2進数1桁のことをビット(bit)と呼びますまた2進数8桁(8ビット)の集

りを1バイト(Byte)と呼びます 1バイト(8ビット) 27 26 25 24 23 22 21 20

したがって1バイトまたは2バイト4バイトで表すことのできる最大の数は以下のとおりです 1バイト 2バイト 4バイト 1バイト( 8ビット) 0から255(28-1) 2バイト(16ビット) 0から65535(216-1) 4バイト(32ビット) 0から4294967295(232-1)

3

次に負の場合を考えます負の数を表す場合には2の補数を使用します例えば(-10)10

を1バイトで表すにはまず(10)10の2進数を求めます (10)10 = (00001010)2次にその2の補数を得るために次の計算を行います (100000000)2 -( 00001010)2

( 11110110)2 (-10)101バイト2バイト4バイト長の符号付きデータの場合正負を表すために最上位ビットを符号ビッ

ト(S)として使用します 1バイト 2バイト 4バイト 1バイト( 8ビット) -128~127 2バイト(16ビット) -32768~32767 4バイト(32ビット) -2147483648~2147783647

S

S

S

(2) 2進数(浮動小数点) 2進数の浮動小数点形式は次のように表現されます (1 11 1)2 (2進数から10進数への変換) 2-2の位 1times21 + 1times20 + 1times2-1 + 1times2-2

2―1の位 = 2 + 1 + 05 + 025 20の位 = 375 21の位 計算機の内部では浮動小数点型データは以下の形式になっています

[パーソナルコンピュータの場合] 4バイト データ値=

4バイト 8バイト

演習2 次の10進数は2

a)(33)10 d)(00010100)

(-1)Stimes(05+(M2))times2E-128 有効桁数 10進数約 7桁 大きさ 10-38から1038

有効桁数 10進数約16桁 大きさ 10-38から1038

仮数部 M 指数部 E S

仮想小数点位置

進数に2進数は10進数に変換しなさい負の値は1バイトで表しなさい b)(125)10 c)(21)10

2 e)(11111111)2 f)(00001111)2

4

2-2 8進数と16進数 (1) 8進数

8進数とは0から7までの数字で表される数です (3 7 6 4)8 (8進数から10進数への変換) 80の位 3times83 + 7times82 + 6times81 + 4times80

81の位 = 3times512 + 7times64 + 6times8 + 4times1 82の位 = 1536 + 448 + 48 + 4 83の位 = 2036

(2) 16進数

16進数とは0から9およびAからFの文字で表される数ですABCDEFは10進数の

101112131415に対応します (1 2 A B)16 (16進数から10進数への変換) 160の位 1times163 + 2times162 + Atimes161 + Btimes160

161の位 = 1times4096 + 2times256 + Atimes16 + Btimes1 162の位 = 4096 + 512 + 160 + 11 163の位 = 4779

5

2-3 文字コード 文字 A などは8ビットのデータとして定義(コード化)されています文字コードの種類もいく

つかありUNIX や MS-DOS では ASCII コードを使用していますまた汎用機などではEBCDIC コードを使用しています

(1) ASCIIコード表(JIS8ビット)

上位4ビット

0 1 2 3 4 5 6 7 8 9 A B C D E F

0 SP 0 P p ― タ ミ 1 1 A Q a q ア チ ム 2 ldquo 2 B R b r 「 イ ツ メ 3 3 C S c s 」 ウ テ モ 4 $ 4 D T d t エ ト ヤ 5 5 E U e u オ ナ ユ 6 6 F V f v ヲ カ ニ ヨ 7 BE

L lsquo 7 G W g w ァ キ ヌ ラ

8 BS ( 8 H X h x ィ ク ネ リ 9 TAB ) 9 I Y i y ゥ ケ ノ ル A LF J Z j z ェ コ ハ レ B ESC + K [ k { ォ サ ヒ ロ C < L ¥ l | ャ シ フ ワ D CR - = M ] m } ュ ス ヘ ン E > N ^ n ~ ョ セ ホ ゛ F O _ o DE

L ッ ソ マ ゜

下位4ビット

したがって文字Aは ASCII コードで次のようになります A = (41)16

演習3

ASCII コード表を使って次の文字コードを16進数で表しなさい a) 9 b) M c) g

6

第3章 関数 3-1 関数とは

Cではプログラムの単位は関数で定義されますここでいう関数とは数学などで使われる

sincos 関数と同様の概念でありある値を与えると何らかの処理を行いその結果が関数値となるものですもちろんmain() も一つの関数ですその他にも自由に関数を作ることができます

例えば関数

f(x)=4x2+2x+5 を計算するときには次のようにプログラムを分けることができます データxを入力して関数f(x)を呼び出しその結果を印刷するプログラム 関数f(x)を計算するプログラム これをプログラムで表すと次のようになります

include ltstdiohgt main() float x y f() 変数と関数の型の宣言

while( scanf( f ampx ) = EOF ) y = f( x ) 関数の引用

printf( yenn x=f f(x)=f x y ) float f( float x ) 関数の定義

float y y = 40 x x + 20 x + 50 return y 計算を終了し結果を戻します

関数 f(x)は与えられたxの値によりyを計算して main()に結果を返します

3-2 関数の形式 関数を定義する場合には次の形式で定義します

型 関数名(仮引数の並び) float f ( float x )

変数の型宣言 関数内で使用する変数の宣言 プログラム プログラム }

関数の定義で型の指定がない場合にはint 型の関数となりますまた関数名は31文字以内の英数字の組み合わせです

3-3 引数

関数に渡すパラメータを引数といいますmain()関数などのように関数を引用する場合のパラメータを実引数と呼び呼ばれる関数で使用されているパラメータを仮引数と呼びます

include ltstdiohgt

7

main() float x y f() 変数と関数の型の宣言

while( scanf( f ampx ) = EOF ) y = f( x ) 関数の引用x は実引数と呼びます

printf( yenn x=f f(x)=f x y ) float f( float x ) 関数の定義x は仮引数と呼びます

float y y = 40 x x + 20 x + 50 return y 計算を終了し結果を戻します

[入力の終了について]

このプログラムを実行すると永遠とデータ入力を求められてしまいます終了条件が = EOF の場合はキーボードから CTRLキーを押しながら Z を入力することにより while文を抜け入力を終了することができます

複数の引数を受け渡しする場合には引用する側と関数を定義する側とで 引数の並び個数型

を合わせなければなりませんしかし変数名は同じでなくてもかまいません例えば配列 a と bを加算して配列 cに代入する場合には次のようになります

include ltstdiohgt main()

int a[10] = 18 24 56 28 96 51 82 34 65 72 UNIXの場合 static intにする int b[10] = 12 54 69 20 26 84 55 20 44 74 UNIXの場合 static intにする

int c[10] k void matadd() 関数の型宣言

matadd( a b c ) for( k = 0 k lt 10 k++ ) printf( yenn d + d = d a[k] b[k] c[k] ) void matadd( int x[] int y[] int z[] ) 関数の定義

int t for( t = 0 t lt 10 t++ ) z[t] = x[t] + y[t]

演習4 平均値を求める関数average()を作成し10名の数学の得点を読み込みその平均点を求め

るプログラムを作りなさい 「入力例」 「出力例」

45 63900000 78 97

8

この他にも関数にパラメータを渡す方法としてポインタを使用する方法があります文字列を

複写する関数の場合には次のとおりになります関数名は strcopy()最初の引数には複写先の配列名(配列の先頭番地)次の引数には複写元の配列名(配列の先頭番地)です

include ltstdiohgt main() char src[] = tokai dst[80] void strcopy() strcopy( dst src ) printf( syenn dst )

void strcopy( char str1 char str2 ) while( ( str1++ = str2++ ) = yen0 )

また配列の加算を行う関数の場合にもそれぞれの配列名をパラメータとし関数側でポイン

タ型変数として受け取ることができます

include ltstdiohgt main() int a[10] = 18 24 56 28 96 51 82 34 65 72 UNIXの場合 static intにする int b[10] = 12 54 69 20 26 84 55 20 44 74 UNIXの場合 static intにする

int c[10] int k void matadd() matadd( a b c 10 ) for( k = 0 k lt 10 k++ ) printf( d + d = d yenn a[k] b[k] c[k] )

void matadd( int x int y int z int n ) for( n gt 0 n-- ) z++ = x++ + y++

main()関数では配列名(アドレス定数)として引数に指定されていますが関数 matadd()ではポインタ型の変数として使用することができますしたがって変数 xyz は値を変更することができるようになります

配列 a 変数 x

9

配列 b 変数 y 配列 c 変数 x

3-4 戻り値 関数からの戻り値はreturn 文によって返されます整数型文字型の値を返す関数の場合

にはそれぞれ次のように定義します

int sub( int x ) char sub( int x ) int y char z

return y return z

またポインタを返す関数の場合には次のように定義します

int sub( int x ) char sub( int x ) int y char z

return y return z

return文で式の指定がない場合には何も値を返しません

[プログラム例]

文字列(文字型配列)の中に指定した文字があればその位置をポインタで返し無ければ NULLポインタを返す関数を考えてみます

char strfind( char str char ch ) while( str ) if( str == ch )return str str++ return NULL

いくつかのC言語のマニュアルでは関数の説明を以下のように記述しています sin 機能 正弦を求めます 形式 include ltmathhgt double sin( double x ) このとき関数 sin() の戻り値は double 型でありまた指定する引数も double 型でなけれ

ばなりませんそれと同時にこの関数を使用する場合にはinclude ltmathhgt を指定しなければなりません

10

3-5 変数の通用範囲 関数内で宣言された変数はその関数の中でのみ使用可能です他のプログラムからは使用

することはできません

include ltstdiohgt main() int i 変数 i は関数 main() と sub() とでは それぞれ独立に使用することができます main() で変数 i に設定した値は sub() では参照することはできません sub() 逆にsub() で変数 i に設定した値も main() では参照することはできません

int i

それぞれの関数の中でのみ使用可能な変数をローカル変数と呼び他の関数でも使用可能

な変数をグローバル変数と呼びますいくつかの関数で共通に使用するような場合にはグロー

バル変数を使用します グローバル変数を定義する場合には関数の外で宣言します

include ltstdiohgt int i グローバル変数の定義

main() i = 10

sub() extern int i printf( yenn i = d i )

このプログラムではmain() 関数でグローバル変数に値を設定し関数 sub() で変数の値を

参照しています extern 宣言は変数が他のプログラム内で宣言されていることを示しています宣言の形式

は以下のとおりです extern 型 変数並び

演習5 入力された任意の数の倍数を求めるプログラムを作成しなさい入力する数値は2つ倍数 を求めるための任意の数と倍数の上限値ですここでいう上限値とは任意の数の倍数をどの くらいの数まで求めるかということです

11

3-6 動的変数と静的変数 通常Cで使用される変数はその関数の中だけでのみ使用できる変数ですしたがって関数

が実行するときに関数の中で使用する変数の領域を確保し関数の実行が終るときにその領域

を解放するようにしてメモリを効率的に利用していますこのように関数が実行されるときに確

保される変数を動的変数(auto変数 )と呼びます プログラムの中ではその他に常に存在し使用できる変数を定義することができますそのよ

うな変数は静的変数(static変数 )と呼ばれます

func() int a b static int x y

また static 変数には内部的なリンケージの指定の意味もありますつまり関数の外で変数

を宣言すると自動的にグローバル変数となり他のプログラムからも使用することができるようにな

ります ファイル a ファイル b このような場合にはコンパイル単位が異なっていてもextern 宣言を行うことにより変数 abc

を使用することができますところが関数の外で static 宣言をして定義した変数についてはコンパイル単位が違うプログラムからは使用することができなくなります ファイル a ファイル b 同一コンパイル単位(ファイル)に存在する関数 sub()と subd()では変数 abcを使用することが

できますがコンパイル単位(ファイル)が異なる関数 func()では変数 abcを使用することはできません

int abc sub() abc = 10

func() extern int abc printf( ldquo abc =dyennrdquo abc )

static int abc sub() abc = 10 subd() abc++

func() extern int abc printf( ldquo abc =dyennrdquo abc )

12

3-7 スタック プログラム中にはプログラム領域データ領域の他にスタック領域があり一時的な作業領域と

して使用されています関数間での引数の受渡しの時にもこの領域を使用しますスタック領域に

データを格納することを「スタックに積む」ともいいます基本的にはスタック領域に格納されたデ

ータは最後に格納されたデータから順に取り出されることになります以下に格納が行われたとき

のスタックの状態を示します記号は次に格納すべき位置(スタックポインタの値)を示していま

逆にスタックからデータを取り出すときにはスタックポインタが指している位置の一つ下から取

り出すことになりますスタックからデータを取り出すときのスタックの状態は次のようになります

なり

10

20

10

30

20

10

40

30

20

10

10rarr

格納

20rarr

格納

30rarr

格納

40rarr

格納

40rarr 30rarr

関数を呼び出すときには次

逆にそれぞれの関数から

次のようになります

40

30

20

10

取出

main() z = f1( x y )

のようにパラメータがスタ

戻るときにはパラメータで

30

20

10

取出

f1( int a int b ) c = f2( d e

xの値 yの値

xの値 yの値

13

ックに格納されます

使用していたスタック領域は自動的になく

10

20

)

f2( int p int q ) r = p + q

xの値

eの値 dの値

yの値

xの値 yの値

dの値

eの値

3-8 再帰呼び出し 関数の引数の受渡しがスタックを利用して行われることから自分で自分自身の関数を呼び出

すことができます 以下のプログラムは入力した値の階乗を計算するプログラムです

3の階乗を求めることを考えてみます

return 文によって戻るときは次のようにして値を返します kai( 3 ) 3 kai( 3-1 ) 2 kai( 2-1 ) return 1

6 3 (2 1) 2 1 以上の計算から3=6が導き出されます 再帰呼び出しのことをリカーシブコールともいいます

include ltstdiohgt main() int n m kai() scanf( ldquodrdquoampn ) m = kai( n ) printf( ldquod = dyennrdquo n m )

int kai( int k ) if( k == 1 )return 1 else return k kai( k ndash 1 )

kai( 1 )

darr

return 1

kai( 2 )

darr

2 kai( 2-1 )

kai( 3 )

darr

3 kai( 3-1 )

main()

darr

kai( 3 )

3

2

1

2

3

1

2

3 3

32

32

1

2

1

3

3

演習6 1からnまでの総和を再帰呼び出しを使って計算する関数 sowa() を作りなさい n+(n-1)+ +2+1

14

第4章 実習 この章ではプログラムを実際に入力して実行するまでの手順を実習します

4-1 操作手順 (1)ログイン

[スタート]rarr[プログラム(P)]rarr[ネットワーク] Hostの欄に bosei を記述選択 rarr [Telnet(FreeWare)] を選択します して 「OK」 ボタンをクリックします

UP-UXV (Rel42MP) (bosei) (pts41) login 60us1234 larr 各自のログイン名を入力します Password larr パスワードを入力しても画面は何も変化しません 101 60us1234bosei larr セッションが開設されましたこれをプロンプトといいます この状態でコマンドを入力することができます

(2)プログラムの作成 以下のコマンドを入力しテキストエディタを起動します 60us1234boseicc ng rensyuc

すると下図のようにngエディタの画面になります

15

次のように入力します入力ミスの修正はBSキーで行ないます

include ltstdiohgt main() float abc scanf(f f ampaampb) c=ab printf(f f f yenn abc)

CTRL キーを押しながら XCTRL キーを押しながら C を押しますすると次のメッセージが画面下に表示されます

Save file uhomea60us1234rensyuc (y or n)

このメッセージに対して y と答えます

(3)データの作成 以下のコマンドを入力しテキストエディタを起動します 60us1234boseicc ng rensyud

ngエディタの画面になりますので次のように入力します 12 35

CTRLキーを押しながら XCTRLキーを押しながら C を押します save file uhomea60us1234rensyud (y or n)

このメッセージに対して y と答えます

(4)コンパイルと実行 コンピュータに処理を依頼します 60us1234boseicc ccg rensyu

ジョブを投入しましたジョブの状態を見るコマンドは myjobです

16

130 60us1234boseicc myjob ================================================= NQS (R0220) BATCH REQUEST HOST bosei ================================================= REQUEST ID NAME OWNER QUEUE PRI NICE STT PGRP R --------------- -------- -------- -------- ---- --- --- ------ - 99321bosei STDIN 60us1234 A 31 0 RUN 14161 - ---------------------------------------------------------------- ================================================== NQS (R0220) DEVICE REQUEST HOST bosei ジョブは実行中です

================================================== REQUEST ID NAME OWNER QUEUE PRI SIZE STT -------------------------------------------------------------

所有するファイルの一覧を見てみます

60us1234boseicc ls -l larr 持っているファイルの一覧を見るコマンドです

-rw-r--r-- 1 60us1234 other 4 4月26日 15時14分 rensyud -rw-r--r-- 1 60us1234 other 128 4月26日 15時10分 rensyuc -rwxr-xr-x 1 60us1234 other 361 4月26日 15時16分 rensyul

(5)計算結果の確認

計算結果を画面に表示して確認します 60us1234boseicc more rensyul

(6)印刷

計算結果の印刷を行ないます5号館2階のカフェテリア室にある bosei のプリンタに印刷 されます

60us1234boseicc lpr rensyul

(7)ログアウト セッションを終了します 60us1234boseicc logout

(8)実行の流れ

エラー

プログラムの作成 ログイン コンパイル実行

確 認 印 刷 ログアウト

17

第5章 配列 多数の変数をまとめて宣言する方法として配列があります配列の一つ一つは配列要素と呼

ばれ変数と同じ性格を持っています配列の宣言は型宣言と同時に次のように行います int a[5] 配列 a

a[0]

a[1]

a[2]

a[3]

a[4]

二次元配列(一次元配列を複数集めたもの)を宣言する場合には次のようになります int b[3][4] 配列 b

b[0][0] b[0][1] b[0][2] b[0][3]

b[1][0] b[1][1] b[1][2] b[1][3]

b[2][0] b[2][1] b[2][2] b[2][3]

配列要素に数値を代入する場合は次のようになります b[1][2]=10

5-1 二次元配列要素の初期化 変数の型宣言と同じように配列を宣言するときに初期値も同時に設定することができます

複数のデータがある場合には{}記号でくくって指定します int b[3][4] = 2 4 6 8 1 3 5 7 1 2 3 4

文字型配列の場合には以下のようになりますyen0 は文字列の終わりを表わします char univ[3][7] = T O K A I yen0 S I M I Z U yen0 Y O Y O G I yen0

また文字列定数として初期化することもできますこの場合コンパイル時に自動的に yen0 が付加されます

char univ[3][7] = TOKAI SIMIZU YOYOGI

18

[プログラム例] 二次元配列のタテヨコを加算するプログラム

include ltstdiohgt main() int mat[4][3]=123456789101112 int ijytotalttotal[3]total=0 for(j=0jlt3j++)ttotal[j]=0 for (i=0ilt4i++) ytotal=0 for(j=0jlt3j++) ytotal += mat[i][j] ttotal[j] += mat[i][j] total += mat[i][j] printf(3dmat[i][j]) printf( 3dyennytotal) printf(yenn) for(j=0jlt3j++)printf(3dttotal[j]) printf( 3dyenntotal)

[実行結果]

1 2 3 6 4 5 6 15 7 8 9 24 10 11 12 33 22 26 30 78

演習7

a)以下の配列はどのように初期化されるか答えなさい char errmsg[2][15] = Divide Error Overflow Error

b)九九の計算を2次元配列を使って求めなさい

19

第6章 ポインタ型変数 C言語では値を記憶するための変数だけではなく変数または定数の番地を記憶するため

のポインタ型変数を宣言することができますポインタとはデータ項目の一種で「記憶装置(メモ

リ)上の格納番地(アドレス)を指すデータ項目」です アドレス コンピュータの中ではデータ項目の格納番地のことをアドレス(住所)と呼びます 例えば記憶装置という名前のとてつもなく大きなマンションがあるとしますその中から Aさんを捜すときは部屋番号を参照しますマンションでは部屋番号で住居人を参照し ているのと同じようにコンピュータでは記憶装置上に確保された変数は格納番地 (アドレス)で管理されています

マンション 部屋番号 記憶装置 格納番地

Aさん Int a Bさん Cさん AAAさん BBBさん CCCさん

1号室

2号室

3号室

100号室

200号室

300号室

100番地

200番地

300番地

1000番地

2000番地

3000番地

Int b Int c float aaafloat bbbfloat ccc

ポインタ ポインタとは「指し示すもの」の意ですがC言語では記憶装置上のアドレスを指し示す もののことです上のマンションの例では部屋番号を格納するデータ項目ということに なりますAAAさんは100号室に住んでいます100という値をポインタのデータ項目に 記憶するとそのデータ項目は間接的にAAAさんを指すことになります

6-1 ポインタ型変数の宣言および参照 通常の変数と区別するために型宣言時に変数名の前に記号を付けて宣言します int a 整数型ポインタ変数 int b 整数型変数

変数 a は整数型の値を記憶するのではなく整数型の値を持つ変数などの番地を記憶する変数ですまた変数 b は通常の整数型の値を記憶するための変数です

20

include ltstdiohgt main() int a b c a はポインタ型の変数b c は整数型の変数 b = 12 変数 b に値 12 を代入します a = ampb 変数 a には変数 b の番地が代入されます c = a + 10 変数 a の指す変数(b)の内容と10の加算です つまり12 + 10 を変数 c に代入します

変数の型宣言において変数名に記号を付けることによりその変数はポインタ型の変数と

なりますポインタ型の変数は変数名のみを指定した場合には単にその変数の値(通常はメモリ

の番地)を表します変数名に記号を付けて使用した場合にはその変数が指し示している変

数の内容を表します c = a ポインタ型変数 a が指している値を変数 c に代入

ポインタ型の変数に番地を記憶させるためにはプログラム例のように変数名の前に記号を

指定します変数名 によって変数の番地(アドレス)を表します a = ampb 変数 b の番地をポインタ型変数 a に代入します

ポインタ型変数の型はポインタ型変数が指し示す先の変数の型を表しています int a 変数 a 整数型の値 float x 変数 x 実数型の値 char c 変数 c 文字型の値

6-2 ポインタ型変数の初期化 ポインタ型変数も型宣言のときに変数を初期化することができます特に文字型のポインタ変

数の場合によく使います char str = TOKAI University

ポインタ型変数 str は文字列定数 TOKAI University の最初の文字が格納されている番地を初期値として持つことになります

変数 str TOKAI University 文字列定数

[プログラム例]

(1)文字型配列 putchar() 関数を使って一次元の文字型配列を出力します include ltstdiohgt main() char str[6] = TOKAI int i for( i = 0 str[i] = yen0 i++ ) putchar( str[i] )

21

ポインタを使用した場合には以下のようになります include ltstdiohgt main() char str[6] = TOKAI char chp for( chp = str chp = yen0 chp++ ) putchar( chp )

chp str T [0] O K A I yen0 [5]

参照する変数 配列の表現 ポインタの表現 実際のアドレス 1番目の数 str[0] chp CHP 2番目の数 str[1] (chp+1) CHP+1 n番目の数 str[n-1] (chp+n-1) CHP+n-1 6番目の数 str[5] (chp+5) CHP+5

注意実際のアドレス CHPは実行時に決定されます

(2)二次元文字型配列 二次元の文字型配列に定数を設定しそれを出力するプログラムです文字型配列を使用す

ると次のとおりになります include ltstdiohgt main() char str[5][40] = TOKAI shounan campus NEC DEC int i for( i = 0 i lt 5 i++ ) printf( yenns str[i] )

40 バイト str TOKAI shounan campus NEC DEC

22

ポインタ型配列を使用すると次のとおりになります include ltstdiohgt main() char str[6] = TOKAI shounan campus NEC DEC NULL char chp for( chp = str chp = NULL chp++ ) printf( yenns chp ) str

chp 番地 TOKAI 番地 shounan 番地 campus 番地 NEC 番地 DEC

NULL

演習8 キーボードまたはデータファイルから読み込んだ文字列中にrsquoArsquo があったら rsquoarsquo に変換 するプログラムを配列とポインタを使って書きなさい

23

第7章 構造体共用体 7-1 構造体

プログラムの規模が大きくなるにつれて多数の intや floatcharなどのデータ型を扱うようになり複雑になってきますそこで多数のデータを1つにまとめて簡単に扱える機能が構造体です 構造体について住所録のデータを例にあげて考えてみます

住所録の個人データとして氏名住所電話番号年齢の項目を一つのデータとします これをC言語で変数の定義をすると次のようになります 氏名東海太郎 char name[30] 住所平塚市北金目1117 char address[30] 電話番号0463-58-1211 char tel[20] 年齢30 int age 個人の住所録データ C言語での表現 このような住所録の個人データを1つにまとめて新しいデータとして定義する機能を構造体と言

います struct 構造体タグ名 構造体メンバーの並び

「struct」は構造体を表すキーワードです 「構造体タグ名」は構造体の型枠を宣言しますここは自由に名前を定義することができ ます 「構造体メンバーの並び」は構造体の要素です複数指定できます

個人の住所録のデータを構造体で宣言すると次のようになります

struct jusho char name[30] char address[30] 構造体のメンバーの並び char tel[20] (複数可)

int age

上記の宣言では構造体の形式を宣言しているだけでメモリ中で実際の領域を確保している

わけではありません実際に領域を確保するためには次のように定義します

struct 構造体タグ名 構造体名

したがって構造体名を jdata とすると次のように指定します

struct jusho jdata

構造体 jdataは次のように構造体タグ jushoの形式で領域を確保します

24

Jdata name[30]

address[30] tel[20] age

(1)構造体の参照

プログラム中で構造体中のメンバーを参照する場合には次のように指定します 構造体名メンバー名

したがって「名前」を参照したいときには次のように指定します

jdataname

[プログラム例]

名前住所電話番号年齢を定義しそれを印字します include ltstdiohgt include ltstringhgt main() struct jusho char name[30] char address[30] char tel[20] int age struct jusho jdata strcpy( jdataname 東海 太郎) strcpy( jdataaddress 平塚市北金目1117)

strcpy( jdatatel 0463-58-1211) jdataage = 30 printf(yenn氏名 = syenn jdataname) printf(yenn住所 = syenn jdataaddress) printf(yenn電話番号= syenn jdatatel) printf(yenn年齢 = dyenn jdataage)

また構造体の形式の定義と領域の確保は次のように同時におこなうことができます

struct 構造体タグ名 構造体メンバーの並び 構造体名

struct jusho struct jusho char name[30] char name[30] char address[30] char address[30] char tel[30] = char tel[30] int age 同じ int age

jdata struct jusho jdata

型宣言と同時にメモリ上に領域を確保する方法 後からメモリ上に領域を確保する方法

25

(2) 構造体配列 住所録データの場合その中に入るデータは1件ではありませんやはり100件200件のデ

ータが必要になる場合がありますこのように個人単位のデータを多数扱う場合には構造体を配

列として宣言することができます 次の例は個人のデータを100個用意するために構造体を配列として宣言しています struct jusho jdata[100] jdata[0] name[30] address[30] tel[20] age

jdata[99 ] name[30] address[30] tel[20] age

(3)構造体配列の参照

プログラム中で構造体配列中のメンバーを参照する場合には次のように指定します 構造体名[要素番号]メンバー名

したがって10件目の人の「名前」を参照したいときには次のように指定します

jdata[10]name

[プログラム例]

名前住所電話番号年齢を定義しそれを印字します include ltstdiohgt include ltstringhgt main() struct jusho char name[30] char address[30] char tel[20] int age jdata[100] strcpy( jdata[10]name 東海 太郎) strcpy( jdata[10]address 平塚市北金目1117)

strcpy( jdata[10]tel 0463-58-1211) jdata[10]age = 30 printf(yenn氏名 = syenn jdata[10]name) printf(yenn住所 = syenn jdata[10]address) printf(yenn電話番号= syenn jdata[10]tel) printf(yenn年齢 = dyenn jdata[10]age)

26

(4) 構造体のポインタ 変数と同じように構造体へのポインタも定義することができます

変数へのポインタ例 構造体へのポインタ例 またポインタを使用して構造体メンバーを参照するには次のように -> 記号を使って指

定します ポインタ変数名 -> メンバー名

[プログラム例]

名前住所電話番号年齢を定義しそれを印字します include ltstdiohgt include ltstringhgt main() struct jusho char name[30] char address[30] char tel[20] int age jdatakp kp = ampjdata strcpy( kp-gtname 東海 太郎)

strcpy( kp-gtaddress 平塚市北金目1117)

strcpy( kp-gttel 0463-58-1211) kp-gtage = 30 printf(yenn氏名 = syenn kp-gtname) printf(yenn住所 = syenn kp-gtaddress) printf(yenn電話番号= syenn kp-gttel) printf(yenn年齢 = dyenn kp-gtage)

kp jdata

name[30] ポインタ型の変数 address[30]

tel[20]

構造体へのポインタを記憶 age

することができます

int a int b b = ampa

struct name jname struct name np np = ampname

27

7-2 共用体 共用体は構造体と同じようにして宣言しますが共用体は複数のデータ型を同一のアドレスに

割り当てる方法です union 共用体タグ名 共用体メンバーの並び

「union」は共用体を表すキーワードです 「共用体タグ名」は共用体の型枠の名前を宣言しますここは自由に名前を定義することがで

きます 「共用体メンバーの並び」は共用体の要素です複数指定できます

共用体の宣言の例を次に示します

union c_tag int a char b

共用体 cは次のように共用体タグ c_tagの形式で領域を確保します共用体はメモリ上に領域を確保するときは ab ともに同じ領域に割り付けられます これはab という2つのデータが同時に存在するわけではなく cを異なるデータ abで共有す

ることを表しています c a b

上記の宣言だけでは共用体の形式を宣言しているだけでメモリ中で実際の領域を確保して

いるわけではありません実際に領域を確保するためには次のように定義します union 構造体タグ名 構造体名

したがって共用体名を c とすると次のように指定します

union c_tag c

(1)共用体の参照

プログラム中で共用体中のメンバーを参照する場合には次のように指定します 共用体名メンバー名

したがって「a」または「b」を参照したいときには次のように指定します

ca (int 型) cb (char 型)

メンバー参照方法によって int型として使ったりchar型として利用することができます

28

[プログラム例]

includeltstdiohgt main() union data char a short b int c chk chkc = 0x12345678 printf( char a xyennchka) printf( short b xyennchkb) printf( int c xyennchkc)

chkb(int 型) chkb(short 型) chka(char 型) 12 12 12 34 34 56 78

29

第8章 アルゴリズム コンピュータに何か仕事をさせようとするときは仕事を具体的に実行するための処理や動作

の手順が必要ですこの「手順」がアルゴリズムです アルゴリズムを考えるときは解くべき問題をはっきりと定義することが必要です

8-1 ソート ソートとは与えられたデータを小さい順または大きい順に並べ換えることですソート方法は

いくつかありますが基本的な方法でソートするアルゴリズムを紹介します

includeltstdiohgt int data[10] main()

int data_in() sort() data_in() sort() int data_in() データ入力関数

int a printf(数値入力yenn)

for(a=0alt=9a++) printf( [d]a+1) scanf(dampdata[a]) int sort() ソート処理を行う関数

int cont1cont2tmp1tmp2mim for(cont1=0 cont1lt=9 cont1++) mim=data[cont1] tmp1=cont1 for(cont2=cont1+1 cont2lt=9 cont2++) if(data[cont2] lt mim) mim=data[cont2] tmp1=cont2 tmp2 = data[cont1] data[cont1] = data[tmp1] data[tmp1] = tmp2 printf(結果 yenn)

for (cont1 = 0 cont1 lt= 9 cont1++) printf(d yenn data[cont1])

30

第9章 プリプロセッサ C言語にはプログラムの中でコンパイルについての指示を行う「プリプロセッサ」という機能が

ありますまたプリプロセッサとはコンパイルする前に実行されるためその意味のとおり「前処理」 と呼ばれていますここでは代表的なものをいくつか説明します

9-1 ファイルの挿入 ソースプログラム中に指定されたファイルを挿入します

include ltstdiohgt helliphellip 標準ディレクトリを探します include progh helliphellip 現在のディレクトリを探しなければ標準ディレクトリを探します

includeltstdiohgt によって組み込まれた define EOF (-1) define EOF (-1) define define helliphelliphelliphellip 組み込み helliphelliphelliphellip

main() stdiohファイル

int helliphelliphelliphellip helliphelliphelliphellip

ソースファイル

9-2 文字の置換 プログラム中に使われている文字列を別の文字列に置き換えます

include ltstdiohgt define TRUE 1 define EOF (-1) main() define helliphellip helliphellip

while(TRUE) define TRUE 1 置き換え main() helliphellip helliphellip while(1)

break helliphelliphellip

31

9-3 条件によるコンパイル 識別子が定義されているか否かを判断しコンパイルする範囲を指定します

include ltstdiohgt define UNIX main() ifdef UNIX printf( UNIX yenn) else printf(MS-DOSyenn) endif

include ltstdiohgt define OS UNIX main() if OS == UNIX printf( UNIX yenn) else printf(MS-DOSyenn) endif

32

付 録 1 puts()gets()関数について

行単位に入出力を行う場合には puts() gets() 関数を用います

puts() 標準出力に文字列を出力します

include ltstdiohgt int puts( char s ) puts() は NULL で終る文字列 s を標準出力に出力し最後に改行文字 yenn も出力しま

gets() 標準入力から文字列を入力します

include ltstdiohgt char gets( char s ) 戻り値正常に入力した場合には引数 s の値が返されますエラーやEOFになった場合に

は NULL が返されます gets() は標準入力から復帰文字で終る文字列を入力しs に格納しますこのとき最後の復

帰文字は NULL文字に変更されます

入力行の出力 標準入力から gets() で入力したデータには改行コードは含まれませんまた標準出力へ

puts() で出力を行う場合には必ず改行コードが付加されますgets() を実行したときの戻り値としてファイルの終端を検出した場合には EOF ではなく NULL が返されますので注意して下さい

include ltstdiohgt main() char data[80] while( gets( data ) = NULL )puts( data )

putchar()getchar()関数について putchar() 標準出力に文字を出力します

include ltstdiohgt int putchar(int c ) 戻り値正常に出力できた場合には文字cをエラーの場合にはEOFを返します

33

getchar() 標準入力から文字を入力します

include ltstdiohgt int getchar(void) 戻り値正常に入力した場合には読み込んだ文字を int 型に変換して返しますまたファイ

ルエンドエラーの場合にはEOFを返します

標準入力標準出力

標準入力標準出力はプログラムが開始されるときにはオープンされていますそれぞれのフ

ァイルポインタは stdin stdout になっていますfopen() fclose() をせずとも使用することができます

scanf() 標準出力ストリームからテキストを読み込み解釈します include ltstdiohgt int scanf( const char format [ address ] ) 戻り値正しくスキャンし変換し格納した入力フィールドの数を返しますファイルエンドを読

み込んだ場合は戻り値は EOF となります値を格納したフィールドがなかった場合は戻り値は0となります

一連の入力フィールドをスキャンして1度に1文字ずつストリーム stdin から文字を読み込み

ます次に引き数 format によって指される書式文字列中の書式指定に従って各フィールドを書式化します最後にformat の後に続く各引き数が示しているアドレスに書式化した入力を格納していきます書式文字列中の書式指定の個数はその後に続くアドレスの数と同じでな

ければなりません 書式指定[入力幅][型指定文字] 入力幅 読むべき文字数の最大値 型指定文字 次のとおりです 型指定文字 期待される入力 引き数の型 d 10進整数 int へのポインタ( int arg ) x 16進整数 int へのポインタ( int arg ) f 浮動小数点数 float へのポインタ( float arg ) s 文字列 文字配列へのポインタ( char arg[] ) c 文字 文字へのポインタ( char arg )

printf() フォーマットを指定してテキスト標準出力ストリームに出力します include ltstdiohgt int printf( const char format [ argument ] ) 戻り値出力したバイト数を返しますエラーの場合は EOF を返します

34

format によって指される書式文字列中の書式指定をformat の後に続く各引き数に適用し

書式化されたデータを stdout に出力します書式指定は後に続く引き数と同じ数だけなければなりません

書式指定[印字幅][精度][型指定文字] 印字幅 印字する最小文字数 精度 印字する最大文字数 型指定文字 つぎのとおりです 型指定文字 入力引き数 出力の書式 d 整数 符号付き10進整数 x 整数 符号無し16進整数 f 浮動小数点 符号付きの dddddddd形式の値 c 文字 1個の文字 s 文字列ポインタ ヌル文字に出会うか精度に達するまで 文字をプリントする

fopen()fclose()関数について fopen() ファイルをオープンします

include ltstdiohgt FILE fopen( char filename char mode ) 戻り値正常にファイルのオープンができたらファイルポインタを返しますエラーがあった場

合には NULLを返します 文字列 filename で指定されたファイルをオープンしますオープン後の入出力のモードに

ついては文字列 mode で指定しますmode に指定できる文字は以下のとおりです r 入力モードでオープンします w 出力モードでオープンします a 存在するファイルに追加して出力するモードでオープンします r+ 既に作成してあるファイルを更新(入力出力)するモードでオープンします w+ 新しく作成するファイルを更新モードでオープンします a+ 既に作成してあるファイルの終りから更新用に作成します

以上の文字に b をつけ加えることによりバイナリモードで入出力することができるようになり

ます rb バイナリの入力モードでオープンします wb バイナリの出力モードでオープンします ab 存在するファイルに追加して出力するモード(バイナリ)でオープンします

fclose() 既にオープンしてあるファイルをクローズします include ltstdiohgt fclose( FILE fp ) 既にオープンしているファイルをクローズしますパラメータには fopen() 関数により返された

ファイルポインタを指定します

35

テキストモードとバイナリモード 行の最後はテキストモードの場合改行コードのみとなりバイナリモードの場合には復帰

コードと改行コードの組合わせになります行の最後としてテキストファイルには復帰コード改行

コードが書かれていますがテキストモードでオープンした場合には入力すると改行コードのみに

変換されて入力されますバイナリモードの場合には復帰コード改行コードがそれぞれ入力され

ます

fputs()fgets()関数について fputs() ファイルポインタで指定されるファイルに文字列を出力します

include ltstdiohgt

int fputs( char s FILE fp ) fputs() は NULL で終る文字列 s をファイルポインタに示されるファイルへ出力しますputs()

と違い最後に改行文字 yenn を出力することはありません

fgets() ファイルポインタで指定されるファイルから文字列を入力します include ltstdiohgt char fgets( char s int n FILE fp ) 戻り値正常に入力した場合には引数 s の値が返されますエラーやEOFになった場合に

は NULL が返されます fgets() はファイルポインタで指定されるファイルから ( n - 1 ) 文字または改行文字までの

文字列を入力しs に格納しますgets() と異なり最後に入力された改行文字は NULL 文字に変更されません

標準入力から入力しファイルへ出力する ファイルへ出力あるいは入力を行う場合には改行コードの変換(入力の場合の削除出力の

場合の付加)はされませんしたがって標準入力から入力しファイルへ出力する場合には改行

コードを付加しなければなりません include ltstdiohgt main() char data[80] FILE fp fp = fopen( data w ) while( gets( data ) = NULL ) strcat( data yenn ) 改行コードの付加

fputs( data fp ) fclose( fp )

36

fputc()fgetc()関数について fputc() ファイルポインタで指定されるファイルに1文字出力します

include ltstdiohgt int fputc( int c FILE fp ) 戻り値正常に出力できた場合には文字 c を返しエラーの場合には EOF を返します fputc() は文字 c をファイルポインタで示されるファイルへ出力します

fgetc() ファイルポインタで指定されるファイルから1文字入力します

include ltstdiohgt int fgetc( FILE fp ) 戻り値正常に入力した場合には入力した文字を返しますエラーやEOFになった場合には

EOF が返されます fgetc() はファイルポインタで指定されるファイルから文字を入力します

ファイルの内容の表示 include ltstdiohgt main() FILE fp int ch char fname[30] printf( Key in Fila name gt ) gets( fname ) fp = fopen( fname r ) while( ( ch = fgetc( fp ) ) = EOF )putchar( ch ) fclose( fp )

その他テキスト中で使用された関数について sin() 三角関数の正弦を計算します

include ltmathhgt double sin(double radian) sinはラジアンを単位とする引数 radianの三角関数を計算します

37

strcpy() 文字列を他の文字列へコピーします

include ltstringhgt char strcpy(char string1const char string2) strcpyは引数 string2の指す文字列を null文字まで含めて引数 string1の指す領域にコピ

ーする strcpyは string1を返します

strcat() ある文字列を他の文字列に加えます

include ltstringhgt char strcat( char dest const char src ) 戻り値連結された文字列へのポインタを返します strcat() はsrc のコピーを dest の最後につけ加えます得られる文字列の長さは

strlen(dest)+strlen(src) になります

fabs() 絶対値の計算をします include ltmathhgt double fabs(double z) fabsは倍精度浮動小数の絶対値を計算して返しますつまりzgt=0であれば z をzlt0であ

れば-zを返します exp() 指数関数を計算します

include ltmathhgt double exp(double z) exp は引数zの指数関数つまりezを返すここではeは自然対数の底を表します対数関

数logの逆関数です

38

付 録 2 コンパイルの方法には大きく分けて第4章の実習で学んだようにデータファイルを作成してお

き ccg でコンパイルさせる方法と実行中に対話型でデータを入力していく方法があります ここでは対話型で実行を進めていく方法を紹介します ただしこの方法は計算(cpu)時間が10秒以内のものに限ります10秒を超える計算(cpu)時

間を要する場合はccg でコンパイルをするようにしてください 第4章実習の(2)(p16)までは同様です

コンパイル

コンピュータに処理を依頼します 60us1234boseicc cc rensyuc

所有するファイルの一覧を見てみます

60us1234boseicc ls -l larr 持っているファイルの一覧を見るコマンドです

-rw-r--r-- 1 60us1234 other 128 4月26日 15時14分 rensyuc -rwxr-xr-x 1 60us1234 other 361 4月26日 15時16分 aout

aout という実行形式のファイルが作成されています

実行

60us1234boseicc aout12 35[リターン] データを入力

1 200000 3500000 4200000 実行結果の出力

60us1234boseicc

注意

aout ファイルは印刷することができません実行結果を印刷する場合にはファイルに落とし てから出力するようにしましょう

60us1234boseicc aout gt kekka12 35[リターン] データを入力

60us1234boseicc more kekka 計算結果の確認 60us1234boseicc lpr kekka 計算結果の印刷

39

Page 4: n 第1章 章立ての部分は、書式(PC入門大見出し)を …第2章 数の表現 2-1 2進数 電子計算機の動作原理は0と1で表される2進数です。また、人間が日常生活で扱っている数

(5) 文複文

式 いくつかの文

(6) 条件分岐

if( 式 ) 文1 else 文2

if( 式 ) 文

文1 偽

文2

真 真

文 偽

文m

その他

文1

定数1

文2

定数2 文n 定数n

switch( 式 ) case 定数 1 文1 break case 定数2 文2 break case 定数n 文n break default 文m

(7) 繰り返し

while( 式 ) 文 for( 式1 式2 式3 ) 文 do文 while( 式 )

文 偽

式2

式1

式3

(8) その他

goto ラベル break continue

演習1 ある個人の国語算数理科社会のテストの点数をデータとして入力し合計点と平均点を

計算しなさいそのとき平均点が60点未満の場合はGanbareのメッセージを表示するようにしなさい 入出力例

入力) 60 56 68 54 出力) Total= 238 Average=595 Ganbare

2

第2章 数の表現 2-1 2進数

電子計算機の動作原理は0と1で表される2進数ですまた人間が日常生活で扱っている数

は10進数です10進数と2進数の関係について説明します (1) 2進数(固定小数点)

2進数とは0と1で表される数です 0 1 2進数4桁の数字を表した場合それぞれの位は2nになりますしたがって10進数に変換する

場合には以下のように計算しますまた括弧の添え字は括弧内が何進数で表されているのかを

示します (1 0 1 0)2 (2進数から10進数への変換) 20の位 1times23 + 0times22 + 1times21 + 0times20

21の位 =1 times 8 + 0 times 4 + 1 times 2 + 0 times 0 22の位 =8 + 0 + 2 + 0 23の位 =10 逆に10進数から2進数に変換するには次の手順で行います (10)10 2) 10 2) 5 0 hellip 20 2) 2 1 hellip 21 (10)10=(1010)2 2) 1 0 hellip 22

1 helliphelliphelliphelliphellip 23

仮想的な小数点が常に20の右側に存在することから固定小数点と呼ばれています (1010) 仮想小数点 電子計算機の世界では2進数1桁のことをビット(bit)と呼びますまた2進数8桁(8ビット)の集

りを1バイト(Byte)と呼びます 1バイト(8ビット) 27 26 25 24 23 22 21 20

したがって1バイトまたは2バイト4バイトで表すことのできる最大の数は以下のとおりです 1バイト 2バイト 4バイト 1バイト( 8ビット) 0から255(28-1) 2バイト(16ビット) 0から65535(216-1) 4バイト(32ビット) 0から4294967295(232-1)

3

次に負の場合を考えます負の数を表す場合には2の補数を使用します例えば(-10)10

を1バイトで表すにはまず(10)10の2進数を求めます (10)10 = (00001010)2次にその2の補数を得るために次の計算を行います (100000000)2 -( 00001010)2

( 11110110)2 (-10)101バイト2バイト4バイト長の符号付きデータの場合正負を表すために最上位ビットを符号ビッ

ト(S)として使用します 1バイト 2バイト 4バイト 1バイト( 8ビット) -128~127 2バイト(16ビット) -32768~32767 4バイト(32ビット) -2147483648~2147783647

S

S

S

(2) 2進数(浮動小数点) 2進数の浮動小数点形式は次のように表現されます (1 11 1)2 (2進数から10進数への変換) 2-2の位 1times21 + 1times20 + 1times2-1 + 1times2-2

2―1の位 = 2 + 1 + 05 + 025 20の位 = 375 21の位 計算機の内部では浮動小数点型データは以下の形式になっています

[パーソナルコンピュータの場合] 4バイト データ値=

4バイト 8バイト

演習2 次の10進数は2

a)(33)10 d)(00010100)

(-1)Stimes(05+(M2))times2E-128 有効桁数 10進数約 7桁 大きさ 10-38から1038

有効桁数 10進数約16桁 大きさ 10-38から1038

仮数部 M 指数部 E S

仮想小数点位置

進数に2進数は10進数に変換しなさい負の値は1バイトで表しなさい b)(125)10 c)(21)10

2 e)(11111111)2 f)(00001111)2

4

2-2 8進数と16進数 (1) 8進数

8進数とは0から7までの数字で表される数です (3 7 6 4)8 (8進数から10進数への変換) 80の位 3times83 + 7times82 + 6times81 + 4times80

81の位 = 3times512 + 7times64 + 6times8 + 4times1 82の位 = 1536 + 448 + 48 + 4 83の位 = 2036

(2) 16進数

16進数とは0から9およびAからFの文字で表される数ですABCDEFは10進数の

101112131415に対応します (1 2 A B)16 (16進数から10進数への変換) 160の位 1times163 + 2times162 + Atimes161 + Btimes160

161の位 = 1times4096 + 2times256 + Atimes16 + Btimes1 162の位 = 4096 + 512 + 160 + 11 163の位 = 4779

5

2-3 文字コード 文字 A などは8ビットのデータとして定義(コード化)されています文字コードの種類もいく

つかありUNIX や MS-DOS では ASCII コードを使用していますまた汎用機などではEBCDIC コードを使用しています

(1) ASCIIコード表(JIS8ビット)

上位4ビット

0 1 2 3 4 5 6 7 8 9 A B C D E F

0 SP 0 P p ― タ ミ 1 1 A Q a q ア チ ム 2 ldquo 2 B R b r 「 イ ツ メ 3 3 C S c s 」 ウ テ モ 4 $ 4 D T d t エ ト ヤ 5 5 E U e u オ ナ ユ 6 6 F V f v ヲ カ ニ ヨ 7 BE

L lsquo 7 G W g w ァ キ ヌ ラ

8 BS ( 8 H X h x ィ ク ネ リ 9 TAB ) 9 I Y i y ゥ ケ ノ ル A LF J Z j z ェ コ ハ レ B ESC + K [ k { ォ サ ヒ ロ C < L ¥ l | ャ シ フ ワ D CR - = M ] m } ュ ス ヘ ン E > N ^ n ~ ョ セ ホ ゛ F O _ o DE

L ッ ソ マ ゜

下位4ビット

したがって文字Aは ASCII コードで次のようになります A = (41)16

演習3

ASCII コード表を使って次の文字コードを16進数で表しなさい a) 9 b) M c) g

6

第3章 関数 3-1 関数とは

Cではプログラムの単位は関数で定義されますここでいう関数とは数学などで使われる

sincos 関数と同様の概念でありある値を与えると何らかの処理を行いその結果が関数値となるものですもちろんmain() も一つの関数ですその他にも自由に関数を作ることができます

例えば関数

f(x)=4x2+2x+5 を計算するときには次のようにプログラムを分けることができます データxを入力して関数f(x)を呼び出しその結果を印刷するプログラム 関数f(x)を計算するプログラム これをプログラムで表すと次のようになります

include ltstdiohgt main() float x y f() 変数と関数の型の宣言

while( scanf( f ampx ) = EOF ) y = f( x ) 関数の引用

printf( yenn x=f f(x)=f x y ) float f( float x ) 関数の定義

float y y = 40 x x + 20 x + 50 return y 計算を終了し結果を戻します

関数 f(x)は与えられたxの値によりyを計算して main()に結果を返します

3-2 関数の形式 関数を定義する場合には次の形式で定義します

型 関数名(仮引数の並び) float f ( float x )

変数の型宣言 関数内で使用する変数の宣言 プログラム プログラム }

関数の定義で型の指定がない場合にはint 型の関数となりますまた関数名は31文字以内の英数字の組み合わせです

3-3 引数

関数に渡すパラメータを引数といいますmain()関数などのように関数を引用する場合のパラメータを実引数と呼び呼ばれる関数で使用されているパラメータを仮引数と呼びます

include ltstdiohgt

7

main() float x y f() 変数と関数の型の宣言

while( scanf( f ampx ) = EOF ) y = f( x ) 関数の引用x は実引数と呼びます

printf( yenn x=f f(x)=f x y ) float f( float x ) 関数の定義x は仮引数と呼びます

float y y = 40 x x + 20 x + 50 return y 計算を終了し結果を戻します

[入力の終了について]

このプログラムを実行すると永遠とデータ入力を求められてしまいます終了条件が = EOF の場合はキーボードから CTRLキーを押しながら Z を入力することにより while文を抜け入力を終了することができます

複数の引数を受け渡しする場合には引用する側と関数を定義する側とで 引数の並び個数型

を合わせなければなりませんしかし変数名は同じでなくてもかまいません例えば配列 a と bを加算して配列 cに代入する場合には次のようになります

include ltstdiohgt main()

int a[10] = 18 24 56 28 96 51 82 34 65 72 UNIXの場合 static intにする int b[10] = 12 54 69 20 26 84 55 20 44 74 UNIXの場合 static intにする

int c[10] k void matadd() 関数の型宣言

matadd( a b c ) for( k = 0 k lt 10 k++ ) printf( yenn d + d = d a[k] b[k] c[k] ) void matadd( int x[] int y[] int z[] ) 関数の定義

int t for( t = 0 t lt 10 t++ ) z[t] = x[t] + y[t]

演習4 平均値を求める関数average()を作成し10名の数学の得点を読み込みその平均点を求め

るプログラムを作りなさい 「入力例」 「出力例」

45 63900000 78 97

8

この他にも関数にパラメータを渡す方法としてポインタを使用する方法があります文字列を

複写する関数の場合には次のとおりになります関数名は strcopy()最初の引数には複写先の配列名(配列の先頭番地)次の引数には複写元の配列名(配列の先頭番地)です

include ltstdiohgt main() char src[] = tokai dst[80] void strcopy() strcopy( dst src ) printf( syenn dst )

void strcopy( char str1 char str2 ) while( ( str1++ = str2++ ) = yen0 )

また配列の加算を行う関数の場合にもそれぞれの配列名をパラメータとし関数側でポイン

タ型変数として受け取ることができます

include ltstdiohgt main() int a[10] = 18 24 56 28 96 51 82 34 65 72 UNIXの場合 static intにする int b[10] = 12 54 69 20 26 84 55 20 44 74 UNIXの場合 static intにする

int c[10] int k void matadd() matadd( a b c 10 ) for( k = 0 k lt 10 k++ ) printf( d + d = d yenn a[k] b[k] c[k] )

void matadd( int x int y int z int n ) for( n gt 0 n-- ) z++ = x++ + y++

main()関数では配列名(アドレス定数)として引数に指定されていますが関数 matadd()ではポインタ型の変数として使用することができますしたがって変数 xyz は値を変更することができるようになります

配列 a 変数 x

9

配列 b 変数 y 配列 c 変数 x

3-4 戻り値 関数からの戻り値はreturn 文によって返されます整数型文字型の値を返す関数の場合

にはそれぞれ次のように定義します

int sub( int x ) char sub( int x ) int y char z

return y return z

またポインタを返す関数の場合には次のように定義します

int sub( int x ) char sub( int x ) int y char z

return y return z

return文で式の指定がない場合には何も値を返しません

[プログラム例]

文字列(文字型配列)の中に指定した文字があればその位置をポインタで返し無ければ NULLポインタを返す関数を考えてみます

char strfind( char str char ch ) while( str ) if( str == ch )return str str++ return NULL

いくつかのC言語のマニュアルでは関数の説明を以下のように記述しています sin 機能 正弦を求めます 形式 include ltmathhgt double sin( double x ) このとき関数 sin() の戻り値は double 型でありまた指定する引数も double 型でなけれ

ばなりませんそれと同時にこの関数を使用する場合にはinclude ltmathhgt を指定しなければなりません

10

3-5 変数の通用範囲 関数内で宣言された変数はその関数の中でのみ使用可能です他のプログラムからは使用

することはできません

include ltstdiohgt main() int i 変数 i は関数 main() と sub() とでは それぞれ独立に使用することができます main() で変数 i に設定した値は sub() では参照することはできません sub() 逆にsub() で変数 i に設定した値も main() では参照することはできません

int i

それぞれの関数の中でのみ使用可能な変数をローカル変数と呼び他の関数でも使用可能

な変数をグローバル変数と呼びますいくつかの関数で共通に使用するような場合にはグロー

バル変数を使用します グローバル変数を定義する場合には関数の外で宣言します

include ltstdiohgt int i グローバル変数の定義

main() i = 10

sub() extern int i printf( yenn i = d i )

このプログラムではmain() 関数でグローバル変数に値を設定し関数 sub() で変数の値を

参照しています extern 宣言は変数が他のプログラム内で宣言されていることを示しています宣言の形式

は以下のとおりです extern 型 変数並び

演習5 入力された任意の数の倍数を求めるプログラムを作成しなさい入力する数値は2つ倍数 を求めるための任意の数と倍数の上限値ですここでいう上限値とは任意の数の倍数をどの くらいの数まで求めるかということです

11

3-6 動的変数と静的変数 通常Cで使用される変数はその関数の中だけでのみ使用できる変数ですしたがって関数

が実行するときに関数の中で使用する変数の領域を確保し関数の実行が終るときにその領域

を解放するようにしてメモリを効率的に利用していますこのように関数が実行されるときに確

保される変数を動的変数(auto変数 )と呼びます プログラムの中ではその他に常に存在し使用できる変数を定義することができますそのよ

うな変数は静的変数(static変数 )と呼ばれます

func() int a b static int x y

また static 変数には内部的なリンケージの指定の意味もありますつまり関数の外で変数

を宣言すると自動的にグローバル変数となり他のプログラムからも使用することができるようにな

ります ファイル a ファイル b このような場合にはコンパイル単位が異なっていてもextern 宣言を行うことにより変数 abc

を使用することができますところが関数の外で static 宣言をして定義した変数についてはコンパイル単位が違うプログラムからは使用することができなくなります ファイル a ファイル b 同一コンパイル単位(ファイル)に存在する関数 sub()と subd()では変数 abcを使用することが

できますがコンパイル単位(ファイル)が異なる関数 func()では変数 abcを使用することはできません

int abc sub() abc = 10

func() extern int abc printf( ldquo abc =dyennrdquo abc )

static int abc sub() abc = 10 subd() abc++

func() extern int abc printf( ldquo abc =dyennrdquo abc )

12

3-7 スタック プログラム中にはプログラム領域データ領域の他にスタック領域があり一時的な作業領域と

して使用されています関数間での引数の受渡しの時にもこの領域を使用しますスタック領域に

データを格納することを「スタックに積む」ともいいます基本的にはスタック領域に格納されたデ

ータは最後に格納されたデータから順に取り出されることになります以下に格納が行われたとき

のスタックの状態を示します記号は次に格納すべき位置(スタックポインタの値)を示していま

逆にスタックからデータを取り出すときにはスタックポインタが指している位置の一つ下から取

り出すことになりますスタックからデータを取り出すときのスタックの状態は次のようになります

なり

10

20

10

30

20

10

40

30

20

10

10rarr

格納

20rarr

格納

30rarr

格納

40rarr

格納

40rarr 30rarr

関数を呼び出すときには次

逆にそれぞれの関数から

次のようになります

40

30

20

10

取出

main() z = f1( x y )

のようにパラメータがスタ

戻るときにはパラメータで

30

20

10

取出

f1( int a int b ) c = f2( d e

xの値 yの値

xの値 yの値

13

ックに格納されます

使用していたスタック領域は自動的になく

10

20

)

f2( int p int q ) r = p + q

xの値

eの値 dの値

yの値

xの値 yの値

dの値

eの値

3-8 再帰呼び出し 関数の引数の受渡しがスタックを利用して行われることから自分で自分自身の関数を呼び出

すことができます 以下のプログラムは入力した値の階乗を計算するプログラムです

3の階乗を求めることを考えてみます

return 文によって戻るときは次のようにして値を返します kai( 3 ) 3 kai( 3-1 ) 2 kai( 2-1 ) return 1

6 3 (2 1) 2 1 以上の計算から3=6が導き出されます 再帰呼び出しのことをリカーシブコールともいいます

include ltstdiohgt main() int n m kai() scanf( ldquodrdquoampn ) m = kai( n ) printf( ldquod = dyennrdquo n m )

int kai( int k ) if( k == 1 )return 1 else return k kai( k ndash 1 )

kai( 1 )

darr

return 1

kai( 2 )

darr

2 kai( 2-1 )

kai( 3 )

darr

3 kai( 3-1 )

main()

darr

kai( 3 )

3

2

1

2

3

1

2

3 3

32

32

1

2

1

3

3

演習6 1からnまでの総和を再帰呼び出しを使って計算する関数 sowa() を作りなさい n+(n-1)+ +2+1

14

第4章 実習 この章ではプログラムを実際に入力して実行するまでの手順を実習します

4-1 操作手順 (1)ログイン

[スタート]rarr[プログラム(P)]rarr[ネットワーク] Hostの欄に bosei を記述選択 rarr [Telnet(FreeWare)] を選択します して 「OK」 ボタンをクリックします

UP-UXV (Rel42MP) (bosei) (pts41) login 60us1234 larr 各自のログイン名を入力します Password larr パスワードを入力しても画面は何も変化しません 101 60us1234bosei larr セッションが開設されましたこれをプロンプトといいます この状態でコマンドを入力することができます

(2)プログラムの作成 以下のコマンドを入力しテキストエディタを起動します 60us1234boseicc ng rensyuc

すると下図のようにngエディタの画面になります

15

次のように入力します入力ミスの修正はBSキーで行ないます

include ltstdiohgt main() float abc scanf(f f ampaampb) c=ab printf(f f f yenn abc)

CTRL キーを押しながら XCTRL キーを押しながら C を押しますすると次のメッセージが画面下に表示されます

Save file uhomea60us1234rensyuc (y or n)

このメッセージに対して y と答えます

(3)データの作成 以下のコマンドを入力しテキストエディタを起動します 60us1234boseicc ng rensyud

ngエディタの画面になりますので次のように入力します 12 35

CTRLキーを押しながら XCTRLキーを押しながら C を押します save file uhomea60us1234rensyud (y or n)

このメッセージに対して y と答えます

(4)コンパイルと実行 コンピュータに処理を依頼します 60us1234boseicc ccg rensyu

ジョブを投入しましたジョブの状態を見るコマンドは myjobです

16

130 60us1234boseicc myjob ================================================= NQS (R0220) BATCH REQUEST HOST bosei ================================================= REQUEST ID NAME OWNER QUEUE PRI NICE STT PGRP R --------------- -------- -------- -------- ---- --- --- ------ - 99321bosei STDIN 60us1234 A 31 0 RUN 14161 - ---------------------------------------------------------------- ================================================== NQS (R0220) DEVICE REQUEST HOST bosei ジョブは実行中です

================================================== REQUEST ID NAME OWNER QUEUE PRI SIZE STT -------------------------------------------------------------

所有するファイルの一覧を見てみます

60us1234boseicc ls -l larr 持っているファイルの一覧を見るコマンドです

-rw-r--r-- 1 60us1234 other 4 4月26日 15時14分 rensyud -rw-r--r-- 1 60us1234 other 128 4月26日 15時10分 rensyuc -rwxr-xr-x 1 60us1234 other 361 4月26日 15時16分 rensyul

(5)計算結果の確認

計算結果を画面に表示して確認します 60us1234boseicc more rensyul

(6)印刷

計算結果の印刷を行ないます5号館2階のカフェテリア室にある bosei のプリンタに印刷 されます

60us1234boseicc lpr rensyul

(7)ログアウト セッションを終了します 60us1234boseicc logout

(8)実行の流れ

エラー

プログラムの作成 ログイン コンパイル実行

確 認 印 刷 ログアウト

17

第5章 配列 多数の変数をまとめて宣言する方法として配列があります配列の一つ一つは配列要素と呼

ばれ変数と同じ性格を持っています配列の宣言は型宣言と同時に次のように行います int a[5] 配列 a

a[0]

a[1]

a[2]

a[3]

a[4]

二次元配列(一次元配列を複数集めたもの)を宣言する場合には次のようになります int b[3][4] 配列 b

b[0][0] b[0][1] b[0][2] b[0][3]

b[1][0] b[1][1] b[1][2] b[1][3]

b[2][0] b[2][1] b[2][2] b[2][3]

配列要素に数値を代入する場合は次のようになります b[1][2]=10

5-1 二次元配列要素の初期化 変数の型宣言と同じように配列を宣言するときに初期値も同時に設定することができます

複数のデータがある場合には{}記号でくくって指定します int b[3][4] = 2 4 6 8 1 3 5 7 1 2 3 4

文字型配列の場合には以下のようになりますyen0 は文字列の終わりを表わします char univ[3][7] = T O K A I yen0 S I M I Z U yen0 Y O Y O G I yen0

また文字列定数として初期化することもできますこの場合コンパイル時に自動的に yen0 が付加されます

char univ[3][7] = TOKAI SIMIZU YOYOGI

18

[プログラム例] 二次元配列のタテヨコを加算するプログラム

include ltstdiohgt main() int mat[4][3]=123456789101112 int ijytotalttotal[3]total=0 for(j=0jlt3j++)ttotal[j]=0 for (i=0ilt4i++) ytotal=0 for(j=0jlt3j++) ytotal += mat[i][j] ttotal[j] += mat[i][j] total += mat[i][j] printf(3dmat[i][j]) printf( 3dyennytotal) printf(yenn) for(j=0jlt3j++)printf(3dttotal[j]) printf( 3dyenntotal)

[実行結果]

1 2 3 6 4 5 6 15 7 8 9 24 10 11 12 33 22 26 30 78

演習7

a)以下の配列はどのように初期化されるか答えなさい char errmsg[2][15] = Divide Error Overflow Error

b)九九の計算を2次元配列を使って求めなさい

19

第6章 ポインタ型変数 C言語では値を記憶するための変数だけではなく変数または定数の番地を記憶するため

のポインタ型変数を宣言することができますポインタとはデータ項目の一種で「記憶装置(メモ

リ)上の格納番地(アドレス)を指すデータ項目」です アドレス コンピュータの中ではデータ項目の格納番地のことをアドレス(住所)と呼びます 例えば記憶装置という名前のとてつもなく大きなマンションがあるとしますその中から Aさんを捜すときは部屋番号を参照しますマンションでは部屋番号で住居人を参照し ているのと同じようにコンピュータでは記憶装置上に確保された変数は格納番地 (アドレス)で管理されています

マンション 部屋番号 記憶装置 格納番地

Aさん Int a Bさん Cさん AAAさん BBBさん CCCさん

1号室

2号室

3号室

100号室

200号室

300号室

100番地

200番地

300番地

1000番地

2000番地

3000番地

Int b Int c float aaafloat bbbfloat ccc

ポインタ ポインタとは「指し示すもの」の意ですがC言語では記憶装置上のアドレスを指し示す もののことです上のマンションの例では部屋番号を格納するデータ項目ということに なりますAAAさんは100号室に住んでいます100という値をポインタのデータ項目に 記憶するとそのデータ項目は間接的にAAAさんを指すことになります

6-1 ポインタ型変数の宣言および参照 通常の変数と区別するために型宣言時に変数名の前に記号を付けて宣言します int a 整数型ポインタ変数 int b 整数型変数

変数 a は整数型の値を記憶するのではなく整数型の値を持つ変数などの番地を記憶する変数ですまた変数 b は通常の整数型の値を記憶するための変数です

20

include ltstdiohgt main() int a b c a はポインタ型の変数b c は整数型の変数 b = 12 変数 b に値 12 を代入します a = ampb 変数 a には変数 b の番地が代入されます c = a + 10 変数 a の指す変数(b)の内容と10の加算です つまり12 + 10 を変数 c に代入します

変数の型宣言において変数名に記号を付けることによりその変数はポインタ型の変数と

なりますポインタ型の変数は変数名のみを指定した場合には単にその変数の値(通常はメモリ

の番地)を表します変数名に記号を付けて使用した場合にはその変数が指し示している変

数の内容を表します c = a ポインタ型変数 a が指している値を変数 c に代入

ポインタ型の変数に番地を記憶させるためにはプログラム例のように変数名の前に記号を

指定します変数名 によって変数の番地(アドレス)を表します a = ampb 変数 b の番地をポインタ型変数 a に代入します

ポインタ型変数の型はポインタ型変数が指し示す先の変数の型を表しています int a 変数 a 整数型の値 float x 変数 x 実数型の値 char c 変数 c 文字型の値

6-2 ポインタ型変数の初期化 ポインタ型変数も型宣言のときに変数を初期化することができます特に文字型のポインタ変

数の場合によく使います char str = TOKAI University

ポインタ型変数 str は文字列定数 TOKAI University の最初の文字が格納されている番地を初期値として持つことになります

変数 str TOKAI University 文字列定数

[プログラム例]

(1)文字型配列 putchar() 関数を使って一次元の文字型配列を出力します include ltstdiohgt main() char str[6] = TOKAI int i for( i = 0 str[i] = yen0 i++ ) putchar( str[i] )

21

ポインタを使用した場合には以下のようになります include ltstdiohgt main() char str[6] = TOKAI char chp for( chp = str chp = yen0 chp++ ) putchar( chp )

chp str T [0] O K A I yen0 [5]

参照する変数 配列の表現 ポインタの表現 実際のアドレス 1番目の数 str[0] chp CHP 2番目の数 str[1] (chp+1) CHP+1 n番目の数 str[n-1] (chp+n-1) CHP+n-1 6番目の数 str[5] (chp+5) CHP+5

注意実際のアドレス CHPは実行時に決定されます

(2)二次元文字型配列 二次元の文字型配列に定数を設定しそれを出力するプログラムです文字型配列を使用す

ると次のとおりになります include ltstdiohgt main() char str[5][40] = TOKAI shounan campus NEC DEC int i for( i = 0 i lt 5 i++ ) printf( yenns str[i] )

40 バイト str TOKAI shounan campus NEC DEC

22

ポインタ型配列を使用すると次のとおりになります include ltstdiohgt main() char str[6] = TOKAI shounan campus NEC DEC NULL char chp for( chp = str chp = NULL chp++ ) printf( yenns chp ) str

chp 番地 TOKAI 番地 shounan 番地 campus 番地 NEC 番地 DEC

NULL

演習8 キーボードまたはデータファイルから読み込んだ文字列中にrsquoArsquo があったら rsquoarsquo に変換 するプログラムを配列とポインタを使って書きなさい

23

第7章 構造体共用体 7-1 構造体

プログラムの規模が大きくなるにつれて多数の intや floatcharなどのデータ型を扱うようになり複雑になってきますそこで多数のデータを1つにまとめて簡単に扱える機能が構造体です 構造体について住所録のデータを例にあげて考えてみます

住所録の個人データとして氏名住所電話番号年齢の項目を一つのデータとします これをC言語で変数の定義をすると次のようになります 氏名東海太郎 char name[30] 住所平塚市北金目1117 char address[30] 電話番号0463-58-1211 char tel[20] 年齢30 int age 個人の住所録データ C言語での表現 このような住所録の個人データを1つにまとめて新しいデータとして定義する機能を構造体と言

います struct 構造体タグ名 構造体メンバーの並び

「struct」は構造体を表すキーワードです 「構造体タグ名」は構造体の型枠を宣言しますここは自由に名前を定義することができ ます 「構造体メンバーの並び」は構造体の要素です複数指定できます

個人の住所録のデータを構造体で宣言すると次のようになります

struct jusho char name[30] char address[30] 構造体のメンバーの並び char tel[20] (複数可)

int age

上記の宣言では構造体の形式を宣言しているだけでメモリ中で実際の領域を確保している

わけではありません実際に領域を確保するためには次のように定義します

struct 構造体タグ名 構造体名

したがって構造体名を jdata とすると次のように指定します

struct jusho jdata

構造体 jdataは次のように構造体タグ jushoの形式で領域を確保します

24

Jdata name[30]

address[30] tel[20] age

(1)構造体の参照

プログラム中で構造体中のメンバーを参照する場合には次のように指定します 構造体名メンバー名

したがって「名前」を参照したいときには次のように指定します

jdataname

[プログラム例]

名前住所電話番号年齢を定義しそれを印字します include ltstdiohgt include ltstringhgt main() struct jusho char name[30] char address[30] char tel[20] int age struct jusho jdata strcpy( jdataname 東海 太郎) strcpy( jdataaddress 平塚市北金目1117)

strcpy( jdatatel 0463-58-1211) jdataage = 30 printf(yenn氏名 = syenn jdataname) printf(yenn住所 = syenn jdataaddress) printf(yenn電話番号= syenn jdatatel) printf(yenn年齢 = dyenn jdataage)

また構造体の形式の定義と領域の確保は次のように同時におこなうことができます

struct 構造体タグ名 構造体メンバーの並び 構造体名

struct jusho struct jusho char name[30] char name[30] char address[30] char address[30] char tel[30] = char tel[30] int age 同じ int age

jdata struct jusho jdata

型宣言と同時にメモリ上に領域を確保する方法 後からメモリ上に領域を確保する方法

25

(2) 構造体配列 住所録データの場合その中に入るデータは1件ではありませんやはり100件200件のデ

ータが必要になる場合がありますこのように個人単位のデータを多数扱う場合には構造体を配

列として宣言することができます 次の例は個人のデータを100個用意するために構造体を配列として宣言しています struct jusho jdata[100] jdata[0] name[30] address[30] tel[20] age

jdata[99 ] name[30] address[30] tel[20] age

(3)構造体配列の参照

プログラム中で構造体配列中のメンバーを参照する場合には次のように指定します 構造体名[要素番号]メンバー名

したがって10件目の人の「名前」を参照したいときには次のように指定します

jdata[10]name

[プログラム例]

名前住所電話番号年齢を定義しそれを印字します include ltstdiohgt include ltstringhgt main() struct jusho char name[30] char address[30] char tel[20] int age jdata[100] strcpy( jdata[10]name 東海 太郎) strcpy( jdata[10]address 平塚市北金目1117)

strcpy( jdata[10]tel 0463-58-1211) jdata[10]age = 30 printf(yenn氏名 = syenn jdata[10]name) printf(yenn住所 = syenn jdata[10]address) printf(yenn電話番号= syenn jdata[10]tel) printf(yenn年齢 = dyenn jdata[10]age)

26

(4) 構造体のポインタ 変数と同じように構造体へのポインタも定義することができます

変数へのポインタ例 構造体へのポインタ例 またポインタを使用して構造体メンバーを参照するには次のように -> 記号を使って指

定します ポインタ変数名 -> メンバー名

[プログラム例]

名前住所電話番号年齢を定義しそれを印字します include ltstdiohgt include ltstringhgt main() struct jusho char name[30] char address[30] char tel[20] int age jdatakp kp = ampjdata strcpy( kp-gtname 東海 太郎)

strcpy( kp-gtaddress 平塚市北金目1117)

strcpy( kp-gttel 0463-58-1211) kp-gtage = 30 printf(yenn氏名 = syenn kp-gtname) printf(yenn住所 = syenn kp-gtaddress) printf(yenn電話番号= syenn kp-gttel) printf(yenn年齢 = dyenn kp-gtage)

kp jdata

name[30] ポインタ型の変数 address[30]

tel[20]

構造体へのポインタを記憶 age

することができます

int a int b b = ampa

struct name jname struct name np np = ampname

27

7-2 共用体 共用体は構造体と同じようにして宣言しますが共用体は複数のデータ型を同一のアドレスに

割り当てる方法です union 共用体タグ名 共用体メンバーの並び

「union」は共用体を表すキーワードです 「共用体タグ名」は共用体の型枠の名前を宣言しますここは自由に名前を定義することがで

きます 「共用体メンバーの並び」は共用体の要素です複数指定できます

共用体の宣言の例を次に示します

union c_tag int a char b

共用体 cは次のように共用体タグ c_tagの形式で領域を確保します共用体はメモリ上に領域を確保するときは ab ともに同じ領域に割り付けられます これはab という2つのデータが同時に存在するわけではなく cを異なるデータ abで共有す

ることを表しています c a b

上記の宣言だけでは共用体の形式を宣言しているだけでメモリ中で実際の領域を確保して

いるわけではありません実際に領域を確保するためには次のように定義します union 構造体タグ名 構造体名

したがって共用体名を c とすると次のように指定します

union c_tag c

(1)共用体の参照

プログラム中で共用体中のメンバーを参照する場合には次のように指定します 共用体名メンバー名

したがって「a」または「b」を参照したいときには次のように指定します

ca (int 型) cb (char 型)

メンバー参照方法によって int型として使ったりchar型として利用することができます

28

[プログラム例]

includeltstdiohgt main() union data char a short b int c chk chkc = 0x12345678 printf( char a xyennchka) printf( short b xyennchkb) printf( int c xyennchkc)

chkb(int 型) chkb(short 型) chka(char 型) 12 12 12 34 34 56 78

29

第8章 アルゴリズム コンピュータに何か仕事をさせようとするときは仕事を具体的に実行するための処理や動作

の手順が必要ですこの「手順」がアルゴリズムです アルゴリズムを考えるときは解くべき問題をはっきりと定義することが必要です

8-1 ソート ソートとは与えられたデータを小さい順または大きい順に並べ換えることですソート方法は

いくつかありますが基本的な方法でソートするアルゴリズムを紹介します

includeltstdiohgt int data[10] main()

int data_in() sort() data_in() sort() int data_in() データ入力関数

int a printf(数値入力yenn)

for(a=0alt=9a++) printf( [d]a+1) scanf(dampdata[a]) int sort() ソート処理を行う関数

int cont1cont2tmp1tmp2mim for(cont1=0 cont1lt=9 cont1++) mim=data[cont1] tmp1=cont1 for(cont2=cont1+1 cont2lt=9 cont2++) if(data[cont2] lt mim) mim=data[cont2] tmp1=cont2 tmp2 = data[cont1] data[cont1] = data[tmp1] data[tmp1] = tmp2 printf(結果 yenn)

for (cont1 = 0 cont1 lt= 9 cont1++) printf(d yenn data[cont1])

30

第9章 プリプロセッサ C言語にはプログラムの中でコンパイルについての指示を行う「プリプロセッサ」という機能が

ありますまたプリプロセッサとはコンパイルする前に実行されるためその意味のとおり「前処理」 と呼ばれていますここでは代表的なものをいくつか説明します

9-1 ファイルの挿入 ソースプログラム中に指定されたファイルを挿入します

include ltstdiohgt helliphellip 標準ディレクトリを探します include progh helliphellip 現在のディレクトリを探しなければ標準ディレクトリを探します

includeltstdiohgt によって組み込まれた define EOF (-1) define EOF (-1) define define helliphelliphelliphellip 組み込み helliphelliphelliphellip

main() stdiohファイル

int helliphelliphelliphellip helliphelliphelliphellip

ソースファイル

9-2 文字の置換 プログラム中に使われている文字列を別の文字列に置き換えます

include ltstdiohgt define TRUE 1 define EOF (-1) main() define helliphellip helliphellip

while(TRUE) define TRUE 1 置き換え main() helliphellip helliphellip while(1)

break helliphelliphellip

31

9-3 条件によるコンパイル 識別子が定義されているか否かを判断しコンパイルする範囲を指定します

include ltstdiohgt define UNIX main() ifdef UNIX printf( UNIX yenn) else printf(MS-DOSyenn) endif

include ltstdiohgt define OS UNIX main() if OS == UNIX printf( UNIX yenn) else printf(MS-DOSyenn) endif

32

付 録 1 puts()gets()関数について

行単位に入出力を行う場合には puts() gets() 関数を用います

puts() 標準出力に文字列を出力します

include ltstdiohgt int puts( char s ) puts() は NULL で終る文字列 s を標準出力に出力し最後に改行文字 yenn も出力しま

gets() 標準入力から文字列を入力します

include ltstdiohgt char gets( char s ) 戻り値正常に入力した場合には引数 s の値が返されますエラーやEOFになった場合に

は NULL が返されます gets() は標準入力から復帰文字で終る文字列を入力しs に格納しますこのとき最後の復

帰文字は NULL文字に変更されます

入力行の出力 標準入力から gets() で入力したデータには改行コードは含まれませんまた標準出力へ

puts() で出力を行う場合には必ず改行コードが付加されますgets() を実行したときの戻り値としてファイルの終端を検出した場合には EOF ではなく NULL が返されますので注意して下さい

include ltstdiohgt main() char data[80] while( gets( data ) = NULL )puts( data )

putchar()getchar()関数について putchar() 標準出力に文字を出力します

include ltstdiohgt int putchar(int c ) 戻り値正常に出力できた場合には文字cをエラーの場合にはEOFを返します

33

getchar() 標準入力から文字を入力します

include ltstdiohgt int getchar(void) 戻り値正常に入力した場合には読み込んだ文字を int 型に変換して返しますまたファイ

ルエンドエラーの場合にはEOFを返します

標準入力標準出力

標準入力標準出力はプログラムが開始されるときにはオープンされていますそれぞれのフ

ァイルポインタは stdin stdout になっていますfopen() fclose() をせずとも使用することができます

scanf() 標準出力ストリームからテキストを読み込み解釈します include ltstdiohgt int scanf( const char format [ address ] ) 戻り値正しくスキャンし変換し格納した入力フィールドの数を返しますファイルエンドを読

み込んだ場合は戻り値は EOF となります値を格納したフィールドがなかった場合は戻り値は0となります

一連の入力フィールドをスキャンして1度に1文字ずつストリーム stdin から文字を読み込み

ます次に引き数 format によって指される書式文字列中の書式指定に従って各フィールドを書式化します最後にformat の後に続く各引き数が示しているアドレスに書式化した入力を格納していきます書式文字列中の書式指定の個数はその後に続くアドレスの数と同じでな

ければなりません 書式指定[入力幅][型指定文字] 入力幅 読むべき文字数の最大値 型指定文字 次のとおりです 型指定文字 期待される入力 引き数の型 d 10進整数 int へのポインタ( int arg ) x 16進整数 int へのポインタ( int arg ) f 浮動小数点数 float へのポインタ( float arg ) s 文字列 文字配列へのポインタ( char arg[] ) c 文字 文字へのポインタ( char arg )

printf() フォーマットを指定してテキスト標準出力ストリームに出力します include ltstdiohgt int printf( const char format [ argument ] ) 戻り値出力したバイト数を返しますエラーの場合は EOF を返します

34

format によって指される書式文字列中の書式指定をformat の後に続く各引き数に適用し

書式化されたデータを stdout に出力します書式指定は後に続く引き数と同じ数だけなければなりません

書式指定[印字幅][精度][型指定文字] 印字幅 印字する最小文字数 精度 印字する最大文字数 型指定文字 つぎのとおりです 型指定文字 入力引き数 出力の書式 d 整数 符号付き10進整数 x 整数 符号無し16進整数 f 浮動小数点 符号付きの dddddddd形式の値 c 文字 1個の文字 s 文字列ポインタ ヌル文字に出会うか精度に達するまで 文字をプリントする

fopen()fclose()関数について fopen() ファイルをオープンします

include ltstdiohgt FILE fopen( char filename char mode ) 戻り値正常にファイルのオープンができたらファイルポインタを返しますエラーがあった場

合には NULLを返します 文字列 filename で指定されたファイルをオープンしますオープン後の入出力のモードに

ついては文字列 mode で指定しますmode に指定できる文字は以下のとおりです r 入力モードでオープンします w 出力モードでオープンします a 存在するファイルに追加して出力するモードでオープンします r+ 既に作成してあるファイルを更新(入力出力)するモードでオープンします w+ 新しく作成するファイルを更新モードでオープンします a+ 既に作成してあるファイルの終りから更新用に作成します

以上の文字に b をつけ加えることによりバイナリモードで入出力することができるようになり

ます rb バイナリの入力モードでオープンします wb バイナリの出力モードでオープンします ab 存在するファイルに追加して出力するモード(バイナリ)でオープンします

fclose() 既にオープンしてあるファイルをクローズします include ltstdiohgt fclose( FILE fp ) 既にオープンしているファイルをクローズしますパラメータには fopen() 関数により返された

ファイルポインタを指定します

35

テキストモードとバイナリモード 行の最後はテキストモードの場合改行コードのみとなりバイナリモードの場合には復帰

コードと改行コードの組合わせになります行の最後としてテキストファイルには復帰コード改行

コードが書かれていますがテキストモードでオープンした場合には入力すると改行コードのみに

変換されて入力されますバイナリモードの場合には復帰コード改行コードがそれぞれ入力され

ます

fputs()fgets()関数について fputs() ファイルポインタで指定されるファイルに文字列を出力します

include ltstdiohgt

int fputs( char s FILE fp ) fputs() は NULL で終る文字列 s をファイルポインタに示されるファイルへ出力しますputs()

と違い最後に改行文字 yenn を出力することはありません

fgets() ファイルポインタで指定されるファイルから文字列を入力します include ltstdiohgt char fgets( char s int n FILE fp ) 戻り値正常に入力した場合には引数 s の値が返されますエラーやEOFになった場合に

は NULL が返されます fgets() はファイルポインタで指定されるファイルから ( n - 1 ) 文字または改行文字までの

文字列を入力しs に格納しますgets() と異なり最後に入力された改行文字は NULL 文字に変更されません

標準入力から入力しファイルへ出力する ファイルへ出力あるいは入力を行う場合には改行コードの変換(入力の場合の削除出力の

場合の付加)はされませんしたがって標準入力から入力しファイルへ出力する場合には改行

コードを付加しなければなりません include ltstdiohgt main() char data[80] FILE fp fp = fopen( data w ) while( gets( data ) = NULL ) strcat( data yenn ) 改行コードの付加

fputs( data fp ) fclose( fp )

36

fputc()fgetc()関数について fputc() ファイルポインタで指定されるファイルに1文字出力します

include ltstdiohgt int fputc( int c FILE fp ) 戻り値正常に出力できた場合には文字 c を返しエラーの場合には EOF を返します fputc() は文字 c をファイルポインタで示されるファイルへ出力します

fgetc() ファイルポインタで指定されるファイルから1文字入力します

include ltstdiohgt int fgetc( FILE fp ) 戻り値正常に入力した場合には入力した文字を返しますエラーやEOFになった場合には

EOF が返されます fgetc() はファイルポインタで指定されるファイルから文字を入力します

ファイルの内容の表示 include ltstdiohgt main() FILE fp int ch char fname[30] printf( Key in Fila name gt ) gets( fname ) fp = fopen( fname r ) while( ( ch = fgetc( fp ) ) = EOF )putchar( ch ) fclose( fp )

その他テキスト中で使用された関数について sin() 三角関数の正弦を計算します

include ltmathhgt double sin(double radian) sinはラジアンを単位とする引数 radianの三角関数を計算します

37

strcpy() 文字列を他の文字列へコピーします

include ltstringhgt char strcpy(char string1const char string2) strcpyは引数 string2の指す文字列を null文字まで含めて引数 string1の指す領域にコピ

ーする strcpyは string1を返します

strcat() ある文字列を他の文字列に加えます

include ltstringhgt char strcat( char dest const char src ) 戻り値連結された文字列へのポインタを返します strcat() はsrc のコピーを dest の最後につけ加えます得られる文字列の長さは

strlen(dest)+strlen(src) になります

fabs() 絶対値の計算をします include ltmathhgt double fabs(double z) fabsは倍精度浮動小数の絶対値を計算して返しますつまりzgt=0であれば z をzlt0であ

れば-zを返します exp() 指数関数を計算します

include ltmathhgt double exp(double z) exp は引数zの指数関数つまりezを返すここではeは自然対数の底を表します対数関

数logの逆関数です

38

付 録 2 コンパイルの方法には大きく分けて第4章の実習で学んだようにデータファイルを作成してお

き ccg でコンパイルさせる方法と実行中に対話型でデータを入力していく方法があります ここでは対話型で実行を進めていく方法を紹介します ただしこの方法は計算(cpu)時間が10秒以内のものに限ります10秒を超える計算(cpu)時

間を要する場合はccg でコンパイルをするようにしてください 第4章実習の(2)(p16)までは同様です

コンパイル

コンピュータに処理を依頼します 60us1234boseicc cc rensyuc

所有するファイルの一覧を見てみます

60us1234boseicc ls -l larr 持っているファイルの一覧を見るコマンドです

-rw-r--r-- 1 60us1234 other 128 4月26日 15時14分 rensyuc -rwxr-xr-x 1 60us1234 other 361 4月26日 15時16分 aout

aout という実行形式のファイルが作成されています

実行

60us1234boseicc aout12 35[リターン] データを入力

1 200000 3500000 4200000 実行結果の出力

60us1234boseicc

注意

aout ファイルは印刷することができません実行結果を印刷する場合にはファイルに落とし てから出力するようにしましょう

60us1234boseicc aout gt kekka12 35[リターン] データを入力

60us1234boseicc more kekka 計算結果の確認 60us1234boseicc lpr kekka 計算結果の印刷

39

Page 5: n 第1章 章立ての部分は、書式(PC入門大見出し)を …第2章 数の表現 2-1 2進数 電子計算機の動作原理は0と1で表される2進数です。また、人間が日常生活で扱っている数

第2章 数の表現 2-1 2進数

電子計算機の動作原理は0と1で表される2進数ですまた人間が日常生活で扱っている数

は10進数です10進数と2進数の関係について説明します (1) 2進数(固定小数点)

2進数とは0と1で表される数です 0 1 2進数4桁の数字を表した場合それぞれの位は2nになりますしたがって10進数に変換する

場合には以下のように計算しますまた括弧の添え字は括弧内が何進数で表されているのかを

示します (1 0 1 0)2 (2進数から10進数への変換) 20の位 1times23 + 0times22 + 1times21 + 0times20

21の位 =1 times 8 + 0 times 4 + 1 times 2 + 0 times 0 22の位 =8 + 0 + 2 + 0 23の位 =10 逆に10進数から2進数に変換するには次の手順で行います (10)10 2) 10 2) 5 0 hellip 20 2) 2 1 hellip 21 (10)10=(1010)2 2) 1 0 hellip 22

1 helliphelliphelliphelliphellip 23

仮想的な小数点が常に20の右側に存在することから固定小数点と呼ばれています (1010) 仮想小数点 電子計算機の世界では2進数1桁のことをビット(bit)と呼びますまた2進数8桁(8ビット)の集

りを1バイト(Byte)と呼びます 1バイト(8ビット) 27 26 25 24 23 22 21 20

したがって1バイトまたは2バイト4バイトで表すことのできる最大の数は以下のとおりです 1バイト 2バイト 4バイト 1バイト( 8ビット) 0から255(28-1) 2バイト(16ビット) 0から65535(216-1) 4バイト(32ビット) 0から4294967295(232-1)

3

次に負の場合を考えます負の数を表す場合には2の補数を使用します例えば(-10)10

を1バイトで表すにはまず(10)10の2進数を求めます (10)10 = (00001010)2次にその2の補数を得るために次の計算を行います (100000000)2 -( 00001010)2

( 11110110)2 (-10)101バイト2バイト4バイト長の符号付きデータの場合正負を表すために最上位ビットを符号ビッ

ト(S)として使用します 1バイト 2バイト 4バイト 1バイト( 8ビット) -128~127 2バイト(16ビット) -32768~32767 4バイト(32ビット) -2147483648~2147783647

S

S

S

(2) 2進数(浮動小数点) 2進数の浮動小数点形式は次のように表現されます (1 11 1)2 (2進数から10進数への変換) 2-2の位 1times21 + 1times20 + 1times2-1 + 1times2-2

2―1の位 = 2 + 1 + 05 + 025 20の位 = 375 21の位 計算機の内部では浮動小数点型データは以下の形式になっています

[パーソナルコンピュータの場合] 4バイト データ値=

4バイト 8バイト

演習2 次の10進数は2

a)(33)10 d)(00010100)

(-1)Stimes(05+(M2))times2E-128 有効桁数 10進数約 7桁 大きさ 10-38から1038

有効桁数 10進数約16桁 大きさ 10-38から1038

仮数部 M 指数部 E S

仮想小数点位置

進数に2進数は10進数に変換しなさい負の値は1バイトで表しなさい b)(125)10 c)(21)10

2 e)(11111111)2 f)(00001111)2

4

2-2 8進数と16進数 (1) 8進数

8進数とは0から7までの数字で表される数です (3 7 6 4)8 (8進数から10進数への変換) 80の位 3times83 + 7times82 + 6times81 + 4times80

81の位 = 3times512 + 7times64 + 6times8 + 4times1 82の位 = 1536 + 448 + 48 + 4 83の位 = 2036

(2) 16進数

16進数とは0から9およびAからFの文字で表される数ですABCDEFは10進数の

101112131415に対応します (1 2 A B)16 (16進数から10進数への変換) 160の位 1times163 + 2times162 + Atimes161 + Btimes160

161の位 = 1times4096 + 2times256 + Atimes16 + Btimes1 162の位 = 4096 + 512 + 160 + 11 163の位 = 4779

5

2-3 文字コード 文字 A などは8ビットのデータとして定義(コード化)されています文字コードの種類もいく

つかありUNIX や MS-DOS では ASCII コードを使用していますまた汎用機などではEBCDIC コードを使用しています

(1) ASCIIコード表(JIS8ビット)

上位4ビット

0 1 2 3 4 5 6 7 8 9 A B C D E F

0 SP 0 P p ― タ ミ 1 1 A Q a q ア チ ム 2 ldquo 2 B R b r 「 イ ツ メ 3 3 C S c s 」 ウ テ モ 4 $ 4 D T d t エ ト ヤ 5 5 E U e u オ ナ ユ 6 6 F V f v ヲ カ ニ ヨ 7 BE

L lsquo 7 G W g w ァ キ ヌ ラ

8 BS ( 8 H X h x ィ ク ネ リ 9 TAB ) 9 I Y i y ゥ ケ ノ ル A LF J Z j z ェ コ ハ レ B ESC + K [ k { ォ サ ヒ ロ C < L ¥ l | ャ シ フ ワ D CR - = M ] m } ュ ス ヘ ン E > N ^ n ~ ョ セ ホ ゛ F O _ o DE

L ッ ソ マ ゜

下位4ビット

したがって文字Aは ASCII コードで次のようになります A = (41)16

演習3

ASCII コード表を使って次の文字コードを16進数で表しなさい a) 9 b) M c) g

6

第3章 関数 3-1 関数とは

Cではプログラムの単位は関数で定義されますここでいう関数とは数学などで使われる

sincos 関数と同様の概念でありある値を与えると何らかの処理を行いその結果が関数値となるものですもちろんmain() も一つの関数ですその他にも自由に関数を作ることができます

例えば関数

f(x)=4x2+2x+5 を計算するときには次のようにプログラムを分けることができます データxを入力して関数f(x)を呼び出しその結果を印刷するプログラム 関数f(x)を計算するプログラム これをプログラムで表すと次のようになります

include ltstdiohgt main() float x y f() 変数と関数の型の宣言

while( scanf( f ampx ) = EOF ) y = f( x ) 関数の引用

printf( yenn x=f f(x)=f x y ) float f( float x ) 関数の定義

float y y = 40 x x + 20 x + 50 return y 計算を終了し結果を戻します

関数 f(x)は与えられたxの値によりyを計算して main()に結果を返します

3-2 関数の形式 関数を定義する場合には次の形式で定義します

型 関数名(仮引数の並び) float f ( float x )

変数の型宣言 関数内で使用する変数の宣言 プログラム プログラム }

関数の定義で型の指定がない場合にはint 型の関数となりますまた関数名は31文字以内の英数字の組み合わせです

3-3 引数

関数に渡すパラメータを引数といいますmain()関数などのように関数を引用する場合のパラメータを実引数と呼び呼ばれる関数で使用されているパラメータを仮引数と呼びます

include ltstdiohgt

7

main() float x y f() 変数と関数の型の宣言

while( scanf( f ampx ) = EOF ) y = f( x ) 関数の引用x は実引数と呼びます

printf( yenn x=f f(x)=f x y ) float f( float x ) 関数の定義x は仮引数と呼びます

float y y = 40 x x + 20 x + 50 return y 計算を終了し結果を戻します

[入力の終了について]

このプログラムを実行すると永遠とデータ入力を求められてしまいます終了条件が = EOF の場合はキーボードから CTRLキーを押しながら Z を入力することにより while文を抜け入力を終了することができます

複数の引数を受け渡しする場合には引用する側と関数を定義する側とで 引数の並び個数型

を合わせなければなりませんしかし変数名は同じでなくてもかまいません例えば配列 a と bを加算して配列 cに代入する場合には次のようになります

include ltstdiohgt main()

int a[10] = 18 24 56 28 96 51 82 34 65 72 UNIXの場合 static intにする int b[10] = 12 54 69 20 26 84 55 20 44 74 UNIXの場合 static intにする

int c[10] k void matadd() 関数の型宣言

matadd( a b c ) for( k = 0 k lt 10 k++ ) printf( yenn d + d = d a[k] b[k] c[k] ) void matadd( int x[] int y[] int z[] ) 関数の定義

int t for( t = 0 t lt 10 t++ ) z[t] = x[t] + y[t]

演習4 平均値を求める関数average()を作成し10名の数学の得点を読み込みその平均点を求め

るプログラムを作りなさい 「入力例」 「出力例」

45 63900000 78 97

8

この他にも関数にパラメータを渡す方法としてポインタを使用する方法があります文字列を

複写する関数の場合には次のとおりになります関数名は strcopy()最初の引数には複写先の配列名(配列の先頭番地)次の引数には複写元の配列名(配列の先頭番地)です

include ltstdiohgt main() char src[] = tokai dst[80] void strcopy() strcopy( dst src ) printf( syenn dst )

void strcopy( char str1 char str2 ) while( ( str1++ = str2++ ) = yen0 )

また配列の加算を行う関数の場合にもそれぞれの配列名をパラメータとし関数側でポイン

タ型変数として受け取ることができます

include ltstdiohgt main() int a[10] = 18 24 56 28 96 51 82 34 65 72 UNIXの場合 static intにする int b[10] = 12 54 69 20 26 84 55 20 44 74 UNIXの場合 static intにする

int c[10] int k void matadd() matadd( a b c 10 ) for( k = 0 k lt 10 k++ ) printf( d + d = d yenn a[k] b[k] c[k] )

void matadd( int x int y int z int n ) for( n gt 0 n-- ) z++ = x++ + y++

main()関数では配列名(アドレス定数)として引数に指定されていますが関数 matadd()ではポインタ型の変数として使用することができますしたがって変数 xyz は値を変更することができるようになります

配列 a 変数 x

9

配列 b 変数 y 配列 c 変数 x

3-4 戻り値 関数からの戻り値はreturn 文によって返されます整数型文字型の値を返す関数の場合

にはそれぞれ次のように定義します

int sub( int x ) char sub( int x ) int y char z

return y return z

またポインタを返す関数の場合には次のように定義します

int sub( int x ) char sub( int x ) int y char z

return y return z

return文で式の指定がない場合には何も値を返しません

[プログラム例]

文字列(文字型配列)の中に指定した文字があればその位置をポインタで返し無ければ NULLポインタを返す関数を考えてみます

char strfind( char str char ch ) while( str ) if( str == ch )return str str++ return NULL

いくつかのC言語のマニュアルでは関数の説明を以下のように記述しています sin 機能 正弦を求めます 形式 include ltmathhgt double sin( double x ) このとき関数 sin() の戻り値は double 型でありまた指定する引数も double 型でなけれ

ばなりませんそれと同時にこの関数を使用する場合にはinclude ltmathhgt を指定しなければなりません

10

3-5 変数の通用範囲 関数内で宣言された変数はその関数の中でのみ使用可能です他のプログラムからは使用

することはできません

include ltstdiohgt main() int i 変数 i は関数 main() と sub() とでは それぞれ独立に使用することができます main() で変数 i に設定した値は sub() では参照することはできません sub() 逆にsub() で変数 i に設定した値も main() では参照することはできません

int i

それぞれの関数の中でのみ使用可能な変数をローカル変数と呼び他の関数でも使用可能

な変数をグローバル変数と呼びますいくつかの関数で共通に使用するような場合にはグロー

バル変数を使用します グローバル変数を定義する場合には関数の外で宣言します

include ltstdiohgt int i グローバル変数の定義

main() i = 10

sub() extern int i printf( yenn i = d i )

このプログラムではmain() 関数でグローバル変数に値を設定し関数 sub() で変数の値を

参照しています extern 宣言は変数が他のプログラム内で宣言されていることを示しています宣言の形式

は以下のとおりです extern 型 変数並び

演習5 入力された任意の数の倍数を求めるプログラムを作成しなさい入力する数値は2つ倍数 を求めるための任意の数と倍数の上限値ですここでいう上限値とは任意の数の倍数をどの くらいの数まで求めるかということです

11

3-6 動的変数と静的変数 通常Cで使用される変数はその関数の中だけでのみ使用できる変数ですしたがって関数

が実行するときに関数の中で使用する変数の領域を確保し関数の実行が終るときにその領域

を解放するようにしてメモリを効率的に利用していますこのように関数が実行されるときに確

保される変数を動的変数(auto変数 )と呼びます プログラムの中ではその他に常に存在し使用できる変数を定義することができますそのよ

うな変数は静的変数(static変数 )と呼ばれます

func() int a b static int x y

また static 変数には内部的なリンケージの指定の意味もありますつまり関数の外で変数

を宣言すると自動的にグローバル変数となり他のプログラムからも使用することができるようにな

ります ファイル a ファイル b このような場合にはコンパイル単位が異なっていてもextern 宣言を行うことにより変数 abc

を使用することができますところが関数の外で static 宣言をして定義した変数についてはコンパイル単位が違うプログラムからは使用することができなくなります ファイル a ファイル b 同一コンパイル単位(ファイル)に存在する関数 sub()と subd()では変数 abcを使用することが

できますがコンパイル単位(ファイル)が異なる関数 func()では変数 abcを使用することはできません

int abc sub() abc = 10

func() extern int abc printf( ldquo abc =dyennrdquo abc )

static int abc sub() abc = 10 subd() abc++

func() extern int abc printf( ldquo abc =dyennrdquo abc )

12

3-7 スタック プログラム中にはプログラム領域データ領域の他にスタック領域があり一時的な作業領域と

して使用されています関数間での引数の受渡しの時にもこの領域を使用しますスタック領域に

データを格納することを「スタックに積む」ともいいます基本的にはスタック領域に格納されたデ

ータは最後に格納されたデータから順に取り出されることになります以下に格納が行われたとき

のスタックの状態を示します記号は次に格納すべき位置(スタックポインタの値)を示していま

逆にスタックからデータを取り出すときにはスタックポインタが指している位置の一つ下から取

り出すことになりますスタックからデータを取り出すときのスタックの状態は次のようになります

なり

10

20

10

30

20

10

40

30

20

10

10rarr

格納

20rarr

格納

30rarr

格納

40rarr

格納

40rarr 30rarr

関数を呼び出すときには次

逆にそれぞれの関数から

次のようになります

40

30

20

10

取出

main() z = f1( x y )

のようにパラメータがスタ

戻るときにはパラメータで

30

20

10

取出

f1( int a int b ) c = f2( d e

xの値 yの値

xの値 yの値

13

ックに格納されます

使用していたスタック領域は自動的になく

10

20

)

f2( int p int q ) r = p + q

xの値

eの値 dの値

yの値

xの値 yの値

dの値

eの値

3-8 再帰呼び出し 関数の引数の受渡しがスタックを利用して行われることから自分で自分自身の関数を呼び出

すことができます 以下のプログラムは入力した値の階乗を計算するプログラムです

3の階乗を求めることを考えてみます

return 文によって戻るときは次のようにして値を返します kai( 3 ) 3 kai( 3-1 ) 2 kai( 2-1 ) return 1

6 3 (2 1) 2 1 以上の計算から3=6が導き出されます 再帰呼び出しのことをリカーシブコールともいいます

include ltstdiohgt main() int n m kai() scanf( ldquodrdquoampn ) m = kai( n ) printf( ldquod = dyennrdquo n m )

int kai( int k ) if( k == 1 )return 1 else return k kai( k ndash 1 )

kai( 1 )

darr

return 1

kai( 2 )

darr

2 kai( 2-1 )

kai( 3 )

darr

3 kai( 3-1 )

main()

darr

kai( 3 )

3

2

1

2

3

1

2

3 3

32

32

1

2

1

3

3

演習6 1からnまでの総和を再帰呼び出しを使って計算する関数 sowa() を作りなさい n+(n-1)+ +2+1

14

第4章 実習 この章ではプログラムを実際に入力して実行するまでの手順を実習します

4-1 操作手順 (1)ログイン

[スタート]rarr[プログラム(P)]rarr[ネットワーク] Hostの欄に bosei を記述選択 rarr [Telnet(FreeWare)] を選択します して 「OK」 ボタンをクリックします

UP-UXV (Rel42MP) (bosei) (pts41) login 60us1234 larr 各自のログイン名を入力します Password larr パスワードを入力しても画面は何も変化しません 101 60us1234bosei larr セッションが開設されましたこれをプロンプトといいます この状態でコマンドを入力することができます

(2)プログラムの作成 以下のコマンドを入力しテキストエディタを起動します 60us1234boseicc ng rensyuc

すると下図のようにngエディタの画面になります

15

次のように入力します入力ミスの修正はBSキーで行ないます

include ltstdiohgt main() float abc scanf(f f ampaampb) c=ab printf(f f f yenn abc)

CTRL キーを押しながら XCTRL キーを押しながら C を押しますすると次のメッセージが画面下に表示されます

Save file uhomea60us1234rensyuc (y or n)

このメッセージに対して y と答えます

(3)データの作成 以下のコマンドを入力しテキストエディタを起動します 60us1234boseicc ng rensyud

ngエディタの画面になりますので次のように入力します 12 35

CTRLキーを押しながら XCTRLキーを押しながら C を押します save file uhomea60us1234rensyud (y or n)

このメッセージに対して y と答えます

(4)コンパイルと実行 コンピュータに処理を依頼します 60us1234boseicc ccg rensyu

ジョブを投入しましたジョブの状態を見るコマンドは myjobです

16

130 60us1234boseicc myjob ================================================= NQS (R0220) BATCH REQUEST HOST bosei ================================================= REQUEST ID NAME OWNER QUEUE PRI NICE STT PGRP R --------------- -------- -------- -------- ---- --- --- ------ - 99321bosei STDIN 60us1234 A 31 0 RUN 14161 - ---------------------------------------------------------------- ================================================== NQS (R0220) DEVICE REQUEST HOST bosei ジョブは実行中です

================================================== REQUEST ID NAME OWNER QUEUE PRI SIZE STT -------------------------------------------------------------

所有するファイルの一覧を見てみます

60us1234boseicc ls -l larr 持っているファイルの一覧を見るコマンドです

-rw-r--r-- 1 60us1234 other 4 4月26日 15時14分 rensyud -rw-r--r-- 1 60us1234 other 128 4月26日 15時10分 rensyuc -rwxr-xr-x 1 60us1234 other 361 4月26日 15時16分 rensyul

(5)計算結果の確認

計算結果を画面に表示して確認します 60us1234boseicc more rensyul

(6)印刷

計算結果の印刷を行ないます5号館2階のカフェテリア室にある bosei のプリンタに印刷 されます

60us1234boseicc lpr rensyul

(7)ログアウト セッションを終了します 60us1234boseicc logout

(8)実行の流れ

エラー

プログラムの作成 ログイン コンパイル実行

確 認 印 刷 ログアウト

17

第5章 配列 多数の変数をまとめて宣言する方法として配列があります配列の一つ一つは配列要素と呼

ばれ変数と同じ性格を持っています配列の宣言は型宣言と同時に次のように行います int a[5] 配列 a

a[0]

a[1]

a[2]

a[3]

a[4]

二次元配列(一次元配列を複数集めたもの)を宣言する場合には次のようになります int b[3][4] 配列 b

b[0][0] b[0][1] b[0][2] b[0][3]

b[1][0] b[1][1] b[1][2] b[1][3]

b[2][0] b[2][1] b[2][2] b[2][3]

配列要素に数値を代入する場合は次のようになります b[1][2]=10

5-1 二次元配列要素の初期化 変数の型宣言と同じように配列を宣言するときに初期値も同時に設定することができます

複数のデータがある場合には{}記号でくくって指定します int b[3][4] = 2 4 6 8 1 3 5 7 1 2 3 4

文字型配列の場合には以下のようになりますyen0 は文字列の終わりを表わします char univ[3][7] = T O K A I yen0 S I M I Z U yen0 Y O Y O G I yen0

また文字列定数として初期化することもできますこの場合コンパイル時に自動的に yen0 が付加されます

char univ[3][7] = TOKAI SIMIZU YOYOGI

18

[プログラム例] 二次元配列のタテヨコを加算するプログラム

include ltstdiohgt main() int mat[4][3]=123456789101112 int ijytotalttotal[3]total=0 for(j=0jlt3j++)ttotal[j]=0 for (i=0ilt4i++) ytotal=0 for(j=0jlt3j++) ytotal += mat[i][j] ttotal[j] += mat[i][j] total += mat[i][j] printf(3dmat[i][j]) printf( 3dyennytotal) printf(yenn) for(j=0jlt3j++)printf(3dttotal[j]) printf( 3dyenntotal)

[実行結果]

1 2 3 6 4 5 6 15 7 8 9 24 10 11 12 33 22 26 30 78

演習7

a)以下の配列はどのように初期化されるか答えなさい char errmsg[2][15] = Divide Error Overflow Error

b)九九の計算を2次元配列を使って求めなさい

19

第6章 ポインタ型変数 C言語では値を記憶するための変数だけではなく変数または定数の番地を記憶するため

のポインタ型変数を宣言することができますポインタとはデータ項目の一種で「記憶装置(メモ

リ)上の格納番地(アドレス)を指すデータ項目」です アドレス コンピュータの中ではデータ項目の格納番地のことをアドレス(住所)と呼びます 例えば記憶装置という名前のとてつもなく大きなマンションがあるとしますその中から Aさんを捜すときは部屋番号を参照しますマンションでは部屋番号で住居人を参照し ているのと同じようにコンピュータでは記憶装置上に確保された変数は格納番地 (アドレス)で管理されています

マンション 部屋番号 記憶装置 格納番地

Aさん Int a Bさん Cさん AAAさん BBBさん CCCさん

1号室

2号室

3号室

100号室

200号室

300号室

100番地

200番地

300番地

1000番地

2000番地

3000番地

Int b Int c float aaafloat bbbfloat ccc

ポインタ ポインタとは「指し示すもの」の意ですがC言語では記憶装置上のアドレスを指し示す もののことです上のマンションの例では部屋番号を格納するデータ項目ということに なりますAAAさんは100号室に住んでいます100という値をポインタのデータ項目に 記憶するとそのデータ項目は間接的にAAAさんを指すことになります

6-1 ポインタ型変数の宣言および参照 通常の変数と区別するために型宣言時に変数名の前に記号を付けて宣言します int a 整数型ポインタ変数 int b 整数型変数

変数 a は整数型の値を記憶するのではなく整数型の値を持つ変数などの番地を記憶する変数ですまた変数 b は通常の整数型の値を記憶するための変数です

20

include ltstdiohgt main() int a b c a はポインタ型の変数b c は整数型の変数 b = 12 変数 b に値 12 を代入します a = ampb 変数 a には変数 b の番地が代入されます c = a + 10 変数 a の指す変数(b)の内容と10の加算です つまり12 + 10 を変数 c に代入します

変数の型宣言において変数名に記号を付けることによりその変数はポインタ型の変数と

なりますポインタ型の変数は変数名のみを指定した場合には単にその変数の値(通常はメモリ

の番地)を表します変数名に記号を付けて使用した場合にはその変数が指し示している変

数の内容を表します c = a ポインタ型変数 a が指している値を変数 c に代入

ポインタ型の変数に番地を記憶させるためにはプログラム例のように変数名の前に記号を

指定します変数名 によって変数の番地(アドレス)を表します a = ampb 変数 b の番地をポインタ型変数 a に代入します

ポインタ型変数の型はポインタ型変数が指し示す先の変数の型を表しています int a 変数 a 整数型の値 float x 変数 x 実数型の値 char c 変数 c 文字型の値

6-2 ポインタ型変数の初期化 ポインタ型変数も型宣言のときに変数を初期化することができます特に文字型のポインタ変

数の場合によく使います char str = TOKAI University

ポインタ型変数 str は文字列定数 TOKAI University の最初の文字が格納されている番地を初期値として持つことになります

変数 str TOKAI University 文字列定数

[プログラム例]

(1)文字型配列 putchar() 関数を使って一次元の文字型配列を出力します include ltstdiohgt main() char str[6] = TOKAI int i for( i = 0 str[i] = yen0 i++ ) putchar( str[i] )

21

ポインタを使用した場合には以下のようになります include ltstdiohgt main() char str[6] = TOKAI char chp for( chp = str chp = yen0 chp++ ) putchar( chp )

chp str T [0] O K A I yen0 [5]

参照する変数 配列の表現 ポインタの表現 実際のアドレス 1番目の数 str[0] chp CHP 2番目の数 str[1] (chp+1) CHP+1 n番目の数 str[n-1] (chp+n-1) CHP+n-1 6番目の数 str[5] (chp+5) CHP+5

注意実際のアドレス CHPは実行時に決定されます

(2)二次元文字型配列 二次元の文字型配列に定数を設定しそれを出力するプログラムです文字型配列を使用す

ると次のとおりになります include ltstdiohgt main() char str[5][40] = TOKAI shounan campus NEC DEC int i for( i = 0 i lt 5 i++ ) printf( yenns str[i] )

40 バイト str TOKAI shounan campus NEC DEC

22

ポインタ型配列を使用すると次のとおりになります include ltstdiohgt main() char str[6] = TOKAI shounan campus NEC DEC NULL char chp for( chp = str chp = NULL chp++ ) printf( yenns chp ) str

chp 番地 TOKAI 番地 shounan 番地 campus 番地 NEC 番地 DEC

NULL

演習8 キーボードまたはデータファイルから読み込んだ文字列中にrsquoArsquo があったら rsquoarsquo に変換 するプログラムを配列とポインタを使って書きなさい

23

第7章 構造体共用体 7-1 構造体

プログラムの規模が大きくなるにつれて多数の intや floatcharなどのデータ型を扱うようになり複雑になってきますそこで多数のデータを1つにまとめて簡単に扱える機能が構造体です 構造体について住所録のデータを例にあげて考えてみます

住所録の個人データとして氏名住所電話番号年齢の項目を一つのデータとします これをC言語で変数の定義をすると次のようになります 氏名東海太郎 char name[30] 住所平塚市北金目1117 char address[30] 電話番号0463-58-1211 char tel[20] 年齢30 int age 個人の住所録データ C言語での表現 このような住所録の個人データを1つにまとめて新しいデータとして定義する機能を構造体と言

います struct 構造体タグ名 構造体メンバーの並び

「struct」は構造体を表すキーワードです 「構造体タグ名」は構造体の型枠を宣言しますここは自由に名前を定義することができ ます 「構造体メンバーの並び」は構造体の要素です複数指定できます

個人の住所録のデータを構造体で宣言すると次のようになります

struct jusho char name[30] char address[30] 構造体のメンバーの並び char tel[20] (複数可)

int age

上記の宣言では構造体の形式を宣言しているだけでメモリ中で実際の領域を確保している

わけではありません実際に領域を確保するためには次のように定義します

struct 構造体タグ名 構造体名

したがって構造体名を jdata とすると次のように指定します

struct jusho jdata

構造体 jdataは次のように構造体タグ jushoの形式で領域を確保します

24

Jdata name[30]

address[30] tel[20] age

(1)構造体の参照

プログラム中で構造体中のメンバーを参照する場合には次のように指定します 構造体名メンバー名

したがって「名前」を参照したいときには次のように指定します

jdataname

[プログラム例]

名前住所電話番号年齢を定義しそれを印字します include ltstdiohgt include ltstringhgt main() struct jusho char name[30] char address[30] char tel[20] int age struct jusho jdata strcpy( jdataname 東海 太郎) strcpy( jdataaddress 平塚市北金目1117)

strcpy( jdatatel 0463-58-1211) jdataage = 30 printf(yenn氏名 = syenn jdataname) printf(yenn住所 = syenn jdataaddress) printf(yenn電話番号= syenn jdatatel) printf(yenn年齢 = dyenn jdataage)

また構造体の形式の定義と領域の確保は次のように同時におこなうことができます

struct 構造体タグ名 構造体メンバーの並び 構造体名

struct jusho struct jusho char name[30] char name[30] char address[30] char address[30] char tel[30] = char tel[30] int age 同じ int age

jdata struct jusho jdata

型宣言と同時にメモリ上に領域を確保する方法 後からメモリ上に領域を確保する方法

25

(2) 構造体配列 住所録データの場合その中に入るデータは1件ではありませんやはり100件200件のデ

ータが必要になる場合がありますこのように個人単位のデータを多数扱う場合には構造体を配

列として宣言することができます 次の例は個人のデータを100個用意するために構造体を配列として宣言しています struct jusho jdata[100] jdata[0] name[30] address[30] tel[20] age

jdata[99 ] name[30] address[30] tel[20] age

(3)構造体配列の参照

プログラム中で構造体配列中のメンバーを参照する場合には次のように指定します 構造体名[要素番号]メンバー名

したがって10件目の人の「名前」を参照したいときには次のように指定します

jdata[10]name

[プログラム例]

名前住所電話番号年齢を定義しそれを印字します include ltstdiohgt include ltstringhgt main() struct jusho char name[30] char address[30] char tel[20] int age jdata[100] strcpy( jdata[10]name 東海 太郎) strcpy( jdata[10]address 平塚市北金目1117)

strcpy( jdata[10]tel 0463-58-1211) jdata[10]age = 30 printf(yenn氏名 = syenn jdata[10]name) printf(yenn住所 = syenn jdata[10]address) printf(yenn電話番号= syenn jdata[10]tel) printf(yenn年齢 = dyenn jdata[10]age)

26

(4) 構造体のポインタ 変数と同じように構造体へのポインタも定義することができます

変数へのポインタ例 構造体へのポインタ例 またポインタを使用して構造体メンバーを参照するには次のように -> 記号を使って指

定します ポインタ変数名 -> メンバー名

[プログラム例]

名前住所電話番号年齢を定義しそれを印字します include ltstdiohgt include ltstringhgt main() struct jusho char name[30] char address[30] char tel[20] int age jdatakp kp = ampjdata strcpy( kp-gtname 東海 太郎)

strcpy( kp-gtaddress 平塚市北金目1117)

strcpy( kp-gttel 0463-58-1211) kp-gtage = 30 printf(yenn氏名 = syenn kp-gtname) printf(yenn住所 = syenn kp-gtaddress) printf(yenn電話番号= syenn kp-gttel) printf(yenn年齢 = dyenn kp-gtage)

kp jdata

name[30] ポインタ型の変数 address[30]

tel[20]

構造体へのポインタを記憶 age

することができます

int a int b b = ampa

struct name jname struct name np np = ampname

27

7-2 共用体 共用体は構造体と同じようにして宣言しますが共用体は複数のデータ型を同一のアドレスに

割り当てる方法です union 共用体タグ名 共用体メンバーの並び

「union」は共用体を表すキーワードです 「共用体タグ名」は共用体の型枠の名前を宣言しますここは自由に名前を定義することがで

きます 「共用体メンバーの並び」は共用体の要素です複数指定できます

共用体の宣言の例を次に示します

union c_tag int a char b

共用体 cは次のように共用体タグ c_tagの形式で領域を確保します共用体はメモリ上に領域を確保するときは ab ともに同じ領域に割り付けられます これはab という2つのデータが同時に存在するわけではなく cを異なるデータ abで共有す

ることを表しています c a b

上記の宣言だけでは共用体の形式を宣言しているだけでメモリ中で実際の領域を確保して

いるわけではありません実際に領域を確保するためには次のように定義します union 構造体タグ名 構造体名

したがって共用体名を c とすると次のように指定します

union c_tag c

(1)共用体の参照

プログラム中で共用体中のメンバーを参照する場合には次のように指定します 共用体名メンバー名

したがって「a」または「b」を参照したいときには次のように指定します

ca (int 型) cb (char 型)

メンバー参照方法によって int型として使ったりchar型として利用することができます

28

[プログラム例]

includeltstdiohgt main() union data char a short b int c chk chkc = 0x12345678 printf( char a xyennchka) printf( short b xyennchkb) printf( int c xyennchkc)

chkb(int 型) chkb(short 型) chka(char 型) 12 12 12 34 34 56 78

29

第8章 アルゴリズム コンピュータに何か仕事をさせようとするときは仕事を具体的に実行するための処理や動作

の手順が必要ですこの「手順」がアルゴリズムです アルゴリズムを考えるときは解くべき問題をはっきりと定義することが必要です

8-1 ソート ソートとは与えられたデータを小さい順または大きい順に並べ換えることですソート方法は

いくつかありますが基本的な方法でソートするアルゴリズムを紹介します

includeltstdiohgt int data[10] main()

int data_in() sort() data_in() sort() int data_in() データ入力関数

int a printf(数値入力yenn)

for(a=0alt=9a++) printf( [d]a+1) scanf(dampdata[a]) int sort() ソート処理を行う関数

int cont1cont2tmp1tmp2mim for(cont1=0 cont1lt=9 cont1++) mim=data[cont1] tmp1=cont1 for(cont2=cont1+1 cont2lt=9 cont2++) if(data[cont2] lt mim) mim=data[cont2] tmp1=cont2 tmp2 = data[cont1] data[cont1] = data[tmp1] data[tmp1] = tmp2 printf(結果 yenn)

for (cont1 = 0 cont1 lt= 9 cont1++) printf(d yenn data[cont1])

30

第9章 プリプロセッサ C言語にはプログラムの中でコンパイルについての指示を行う「プリプロセッサ」という機能が

ありますまたプリプロセッサとはコンパイルする前に実行されるためその意味のとおり「前処理」 と呼ばれていますここでは代表的なものをいくつか説明します

9-1 ファイルの挿入 ソースプログラム中に指定されたファイルを挿入します

include ltstdiohgt helliphellip 標準ディレクトリを探します include progh helliphellip 現在のディレクトリを探しなければ標準ディレクトリを探します

includeltstdiohgt によって組み込まれた define EOF (-1) define EOF (-1) define define helliphelliphelliphellip 組み込み helliphelliphelliphellip

main() stdiohファイル

int helliphelliphelliphellip helliphelliphelliphellip

ソースファイル

9-2 文字の置換 プログラム中に使われている文字列を別の文字列に置き換えます

include ltstdiohgt define TRUE 1 define EOF (-1) main() define helliphellip helliphellip

while(TRUE) define TRUE 1 置き換え main() helliphellip helliphellip while(1)

break helliphelliphellip

31

9-3 条件によるコンパイル 識別子が定義されているか否かを判断しコンパイルする範囲を指定します

include ltstdiohgt define UNIX main() ifdef UNIX printf( UNIX yenn) else printf(MS-DOSyenn) endif

include ltstdiohgt define OS UNIX main() if OS == UNIX printf( UNIX yenn) else printf(MS-DOSyenn) endif

32

付 録 1 puts()gets()関数について

行単位に入出力を行う場合には puts() gets() 関数を用います

puts() 標準出力に文字列を出力します

include ltstdiohgt int puts( char s ) puts() は NULL で終る文字列 s を標準出力に出力し最後に改行文字 yenn も出力しま

gets() 標準入力から文字列を入力します

include ltstdiohgt char gets( char s ) 戻り値正常に入力した場合には引数 s の値が返されますエラーやEOFになった場合に

は NULL が返されます gets() は標準入力から復帰文字で終る文字列を入力しs に格納しますこのとき最後の復

帰文字は NULL文字に変更されます

入力行の出力 標準入力から gets() で入力したデータには改行コードは含まれませんまた標準出力へ

puts() で出力を行う場合には必ず改行コードが付加されますgets() を実行したときの戻り値としてファイルの終端を検出した場合には EOF ではなく NULL が返されますので注意して下さい

include ltstdiohgt main() char data[80] while( gets( data ) = NULL )puts( data )

putchar()getchar()関数について putchar() 標準出力に文字を出力します

include ltstdiohgt int putchar(int c ) 戻り値正常に出力できた場合には文字cをエラーの場合にはEOFを返します

33

getchar() 標準入力から文字を入力します

include ltstdiohgt int getchar(void) 戻り値正常に入力した場合には読み込んだ文字を int 型に変換して返しますまたファイ

ルエンドエラーの場合にはEOFを返します

標準入力標準出力

標準入力標準出力はプログラムが開始されるときにはオープンされていますそれぞれのフ

ァイルポインタは stdin stdout になっていますfopen() fclose() をせずとも使用することができます

scanf() 標準出力ストリームからテキストを読み込み解釈します include ltstdiohgt int scanf( const char format [ address ] ) 戻り値正しくスキャンし変換し格納した入力フィールドの数を返しますファイルエンドを読

み込んだ場合は戻り値は EOF となります値を格納したフィールドがなかった場合は戻り値は0となります

一連の入力フィールドをスキャンして1度に1文字ずつストリーム stdin から文字を読み込み

ます次に引き数 format によって指される書式文字列中の書式指定に従って各フィールドを書式化します最後にformat の後に続く各引き数が示しているアドレスに書式化した入力を格納していきます書式文字列中の書式指定の個数はその後に続くアドレスの数と同じでな

ければなりません 書式指定[入力幅][型指定文字] 入力幅 読むべき文字数の最大値 型指定文字 次のとおりです 型指定文字 期待される入力 引き数の型 d 10進整数 int へのポインタ( int arg ) x 16進整数 int へのポインタ( int arg ) f 浮動小数点数 float へのポインタ( float arg ) s 文字列 文字配列へのポインタ( char arg[] ) c 文字 文字へのポインタ( char arg )

printf() フォーマットを指定してテキスト標準出力ストリームに出力します include ltstdiohgt int printf( const char format [ argument ] ) 戻り値出力したバイト数を返しますエラーの場合は EOF を返します

34

format によって指される書式文字列中の書式指定をformat の後に続く各引き数に適用し

書式化されたデータを stdout に出力します書式指定は後に続く引き数と同じ数だけなければなりません

書式指定[印字幅][精度][型指定文字] 印字幅 印字する最小文字数 精度 印字する最大文字数 型指定文字 つぎのとおりです 型指定文字 入力引き数 出力の書式 d 整数 符号付き10進整数 x 整数 符号無し16進整数 f 浮動小数点 符号付きの dddddddd形式の値 c 文字 1個の文字 s 文字列ポインタ ヌル文字に出会うか精度に達するまで 文字をプリントする

fopen()fclose()関数について fopen() ファイルをオープンします

include ltstdiohgt FILE fopen( char filename char mode ) 戻り値正常にファイルのオープンができたらファイルポインタを返しますエラーがあった場

合には NULLを返します 文字列 filename で指定されたファイルをオープンしますオープン後の入出力のモードに

ついては文字列 mode で指定しますmode に指定できる文字は以下のとおりです r 入力モードでオープンします w 出力モードでオープンします a 存在するファイルに追加して出力するモードでオープンします r+ 既に作成してあるファイルを更新(入力出力)するモードでオープンします w+ 新しく作成するファイルを更新モードでオープンします a+ 既に作成してあるファイルの終りから更新用に作成します

以上の文字に b をつけ加えることによりバイナリモードで入出力することができるようになり

ます rb バイナリの入力モードでオープンします wb バイナリの出力モードでオープンします ab 存在するファイルに追加して出力するモード(バイナリ)でオープンします

fclose() 既にオープンしてあるファイルをクローズします include ltstdiohgt fclose( FILE fp ) 既にオープンしているファイルをクローズしますパラメータには fopen() 関数により返された

ファイルポインタを指定します

35

テキストモードとバイナリモード 行の最後はテキストモードの場合改行コードのみとなりバイナリモードの場合には復帰

コードと改行コードの組合わせになります行の最後としてテキストファイルには復帰コード改行

コードが書かれていますがテキストモードでオープンした場合には入力すると改行コードのみに

変換されて入力されますバイナリモードの場合には復帰コード改行コードがそれぞれ入力され

ます

fputs()fgets()関数について fputs() ファイルポインタで指定されるファイルに文字列を出力します

include ltstdiohgt

int fputs( char s FILE fp ) fputs() は NULL で終る文字列 s をファイルポインタに示されるファイルへ出力しますputs()

と違い最後に改行文字 yenn を出力することはありません

fgets() ファイルポインタで指定されるファイルから文字列を入力します include ltstdiohgt char fgets( char s int n FILE fp ) 戻り値正常に入力した場合には引数 s の値が返されますエラーやEOFになった場合に

は NULL が返されます fgets() はファイルポインタで指定されるファイルから ( n - 1 ) 文字または改行文字までの

文字列を入力しs に格納しますgets() と異なり最後に入力された改行文字は NULL 文字に変更されません

標準入力から入力しファイルへ出力する ファイルへ出力あるいは入力を行う場合には改行コードの変換(入力の場合の削除出力の

場合の付加)はされませんしたがって標準入力から入力しファイルへ出力する場合には改行

コードを付加しなければなりません include ltstdiohgt main() char data[80] FILE fp fp = fopen( data w ) while( gets( data ) = NULL ) strcat( data yenn ) 改行コードの付加

fputs( data fp ) fclose( fp )

36

fputc()fgetc()関数について fputc() ファイルポインタで指定されるファイルに1文字出力します

include ltstdiohgt int fputc( int c FILE fp ) 戻り値正常に出力できた場合には文字 c を返しエラーの場合には EOF を返します fputc() は文字 c をファイルポインタで示されるファイルへ出力します

fgetc() ファイルポインタで指定されるファイルから1文字入力します

include ltstdiohgt int fgetc( FILE fp ) 戻り値正常に入力した場合には入力した文字を返しますエラーやEOFになった場合には

EOF が返されます fgetc() はファイルポインタで指定されるファイルから文字を入力します

ファイルの内容の表示 include ltstdiohgt main() FILE fp int ch char fname[30] printf( Key in Fila name gt ) gets( fname ) fp = fopen( fname r ) while( ( ch = fgetc( fp ) ) = EOF )putchar( ch ) fclose( fp )

その他テキスト中で使用された関数について sin() 三角関数の正弦を計算します

include ltmathhgt double sin(double radian) sinはラジアンを単位とする引数 radianの三角関数を計算します

37

strcpy() 文字列を他の文字列へコピーします

include ltstringhgt char strcpy(char string1const char string2) strcpyは引数 string2の指す文字列を null文字まで含めて引数 string1の指す領域にコピ

ーする strcpyは string1を返します

strcat() ある文字列を他の文字列に加えます

include ltstringhgt char strcat( char dest const char src ) 戻り値連結された文字列へのポインタを返します strcat() はsrc のコピーを dest の最後につけ加えます得られる文字列の長さは

strlen(dest)+strlen(src) になります

fabs() 絶対値の計算をします include ltmathhgt double fabs(double z) fabsは倍精度浮動小数の絶対値を計算して返しますつまりzgt=0であれば z をzlt0であ

れば-zを返します exp() 指数関数を計算します

include ltmathhgt double exp(double z) exp は引数zの指数関数つまりezを返すここではeは自然対数の底を表します対数関

数logの逆関数です

38

付 録 2 コンパイルの方法には大きく分けて第4章の実習で学んだようにデータファイルを作成してお

き ccg でコンパイルさせる方法と実行中に対話型でデータを入力していく方法があります ここでは対話型で実行を進めていく方法を紹介します ただしこの方法は計算(cpu)時間が10秒以内のものに限ります10秒を超える計算(cpu)時

間を要する場合はccg でコンパイルをするようにしてください 第4章実習の(2)(p16)までは同様です

コンパイル

コンピュータに処理を依頼します 60us1234boseicc cc rensyuc

所有するファイルの一覧を見てみます

60us1234boseicc ls -l larr 持っているファイルの一覧を見るコマンドです

-rw-r--r-- 1 60us1234 other 128 4月26日 15時14分 rensyuc -rwxr-xr-x 1 60us1234 other 361 4月26日 15時16分 aout

aout という実行形式のファイルが作成されています

実行

60us1234boseicc aout12 35[リターン] データを入力

1 200000 3500000 4200000 実行結果の出力

60us1234boseicc

注意

aout ファイルは印刷することができません実行結果を印刷する場合にはファイルに落とし てから出力するようにしましょう

60us1234boseicc aout gt kekka12 35[リターン] データを入力

60us1234boseicc more kekka 計算結果の確認 60us1234boseicc lpr kekka 計算結果の印刷

39

Page 6: n 第1章 章立ての部分は、書式(PC入門大見出し)を …第2章 数の表現 2-1 2進数 電子計算機の動作原理は0と1で表される2進数です。また、人間が日常生活で扱っている数

次に負の場合を考えます負の数を表す場合には2の補数を使用します例えば(-10)10

を1バイトで表すにはまず(10)10の2進数を求めます (10)10 = (00001010)2次にその2の補数を得るために次の計算を行います (100000000)2 -( 00001010)2

( 11110110)2 (-10)101バイト2バイト4バイト長の符号付きデータの場合正負を表すために最上位ビットを符号ビッ

ト(S)として使用します 1バイト 2バイト 4バイト 1バイト( 8ビット) -128~127 2バイト(16ビット) -32768~32767 4バイト(32ビット) -2147483648~2147783647

S

S

S

(2) 2進数(浮動小数点) 2進数の浮動小数点形式は次のように表現されます (1 11 1)2 (2進数から10進数への変換) 2-2の位 1times21 + 1times20 + 1times2-1 + 1times2-2

2―1の位 = 2 + 1 + 05 + 025 20の位 = 375 21の位 計算機の内部では浮動小数点型データは以下の形式になっています

[パーソナルコンピュータの場合] 4バイト データ値=

4バイト 8バイト

演習2 次の10進数は2

a)(33)10 d)(00010100)

(-1)Stimes(05+(M2))times2E-128 有効桁数 10進数約 7桁 大きさ 10-38から1038

有効桁数 10進数約16桁 大きさ 10-38から1038

仮数部 M 指数部 E S

仮想小数点位置

進数に2進数は10進数に変換しなさい負の値は1バイトで表しなさい b)(125)10 c)(21)10

2 e)(11111111)2 f)(00001111)2

4

2-2 8進数と16進数 (1) 8進数

8進数とは0から7までの数字で表される数です (3 7 6 4)8 (8進数から10進数への変換) 80の位 3times83 + 7times82 + 6times81 + 4times80

81の位 = 3times512 + 7times64 + 6times8 + 4times1 82の位 = 1536 + 448 + 48 + 4 83の位 = 2036

(2) 16進数

16進数とは0から9およびAからFの文字で表される数ですABCDEFは10進数の

101112131415に対応します (1 2 A B)16 (16進数から10進数への変換) 160の位 1times163 + 2times162 + Atimes161 + Btimes160

161の位 = 1times4096 + 2times256 + Atimes16 + Btimes1 162の位 = 4096 + 512 + 160 + 11 163の位 = 4779

5

2-3 文字コード 文字 A などは8ビットのデータとして定義(コード化)されています文字コードの種類もいく

つかありUNIX や MS-DOS では ASCII コードを使用していますまた汎用機などではEBCDIC コードを使用しています

(1) ASCIIコード表(JIS8ビット)

上位4ビット

0 1 2 3 4 5 6 7 8 9 A B C D E F

0 SP 0 P p ― タ ミ 1 1 A Q a q ア チ ム 2 ldquo 2 B R b r 「 イ ツ メ 3 3 C S c s 」 ウ テ モ 4 $ 4 D T d t エ ト ヤ 5 5 E U e u オ ナ ユ 6 6 F V f v ヲ カ ニ ヨ 7 BE

L lsquo 7 G W g w ァ キ ヌ ラ

8 BS ( 8 H X h x ィ ク ネ リ 9 TAB ) 9 I Y i y ゥ ケ ノ ル A LF J Z j z ェ コ ハ レ B ESC + K [ k { ォ サ ヒ ロ C < L ¥ l | ャ シ フ ワ D CR - = M ] m } ュ ス ヘ ン E > N ^ n ~ ョ セ ホ ゛ F O _ o DE

L ッ ソ マ ゜

下位4ビット

したがって文字Aは ASCII コードで次のようになります A = (41)16

演習3

ASCII コード表を使って次の文字コードを16進数で表しなさい a) 9 b) M c) g

6

第3章 関数 3-1 関数とは

Cではプログラムの単位は関数で定義されますここでいう関数とは数学などで使われる

sincos 関数と同様の概念でありある値を与えると何らかの処理を行いその結果が関数値となるものですもちろんmain() も一つの関数ですその他にも自由に関数を作ることができます

例えば関数

f(x)=4x2+2x+5 を計算するときには次のようにプログラムを分けることができます データxを入力して関数f(x)を呼び出しその結果を印刷するプログラム 関数f(x)を計算するプログラム これをプログラムで表すと次のようになります

include ltstdiohgt main() float x y f() 変数と関数の型の宣言

while( scanf( f ampx ) = EOF ) y = f( x ) 関数の引用

printf( yenn x=f f(x)=f x y ) float f( float x ) 関数の定義

float y y = 40 x x + 20 x + 50 return y 計算を終了し結果を戻します

関数 f(x)は与えられたxの値によりyを計算して main()に結果を返します

3-2 関数の形式 関数を定義する場合には次の形式で定義します

型 関数名(仮引数の並び) float f ( float x )

変数の型宣言 関数内で使用する変数の宣言 プログラム プログラム }

関数の定義で型の指定がない場合にはint 型の関数となりますまた関数名は31文字以内の英数字の組み合わせです

3-3 引数

関数に渡すパラメータを引数といいますmain()関数などのように関数を引用する場合のパラメータを実引数と呼び呼ばれる関数で使用されているパラメータを仮引数と呼びます

include ltstdiohgt

7

main() float x y f() 変数と関数の型の宣言

while( scanf( f ampx ) = EOF ) y = f( x ) 関数の引用x は実引数と呼びます

printf( yenn x=f f(x)=f x y ) float f( float x ) 関数の定義x は仮引数と呼びます

float y y = 40 x x + 20 x + 50 return y 計算を終了し結果を戻します

[入力の終了について]

このプログラムを実行すると永遠とデータ入力を求められてしまいます終了条件が = EOF の場合はキーボードから CTRLキーを押しながら Z を入力することにより while文を抜け入力を終了することができます

複数の引数を受け渡しする場合には引用する側と関数を定義する側とで 引数の並び個数型

を合わせなければなりませんしかし変数名は同じでなくてもかまいません例えば配列 a と bを加算して配列 cに代入する場合には次のようになります

include ltstdiohgt main()

int a[10] = 18 24 56 28 96 51 82 34 65 72 UNIXの場合 static intにする int b[10] = 12 54 69 20 26 84 55 20 44 74 UNIXの場合 static intにする

int c[10] k void matadd() 関数の型宣言

matadd( a b c ) for( k = 0 k lt 10 k++ ) printf( yenn d + d = d a[k] b[k] c[k] ) void matadd( int x[] int y[] int z[] ) 関数の定義

int t for( t = 0 t lt 10 t++ ) z[t] = x[t] + y[t]

演習4 平均値を求める関数average()を作成し10名の数学の得点を読み込みその平均点を求め

るプログラムを作りなさい 「入力例」 「出力例」

45 63900000 78 97

8

この他にも関数にパラメータを渡す方法としてポインタを使用する方法があります文字列を

複写する関数の場合には次のとおりになります関数名は strcopy()最初の引数には複写先の配列名(配列の先頭番地)次の引数には複写元の配列名(配列の先頭番地)です

include ltstdiohgt main() char src[] = tokai dst[80] void strcopy() strcopy( dst src ) printf( syenn dst )

void strcopy( char str1 char str2 ) while( ( str1++ = str2++ ) = yen0 )

また配列の加算を行う関数の場合にもそれぞれの配列名をパラメータとし関数側でポイン

タ型変数として受け取ることができます

include ltstdiohgt main() int a[10] = 18 24 56 28 96 51 82 34 65 72 UNIXの場合 static intにする int b[10] = 12 54 69 20 26 84 55 20 44 74 UNIXの場合 static intにする

int c[10] int k void matadd() matadd( a b c 10 ) for( k = 0 k lt 10 k++ ) printf( d + d = d yenn a[k] b[k] c[k] )

void matadd( int x int y int z int n ) for( n gt 0 n-- ) z++ = x++ + y++

main()関数では配列名(アドレス定数)として引数に指定されていますが関数 matadd()ではポインタ型の変数として使用することができますしたがって変数 xyz は値を変更することができるようになります

配列 a 変数 x

9

配列 b 変数 y 配列 c 変数 x

3-4 戻り値 関数からの戻り値はreturn 文によって返されます整数型文字型の値を返す関数の場合

にはそれぞれ次のように定義します

int sub( int x ) char sub( int x ) int y char z

return y return z

またポインタを返す関数の場合には次のように定義します

int sub( int x ) char sub( int x ) int y char z

return y return z

return文で式の指定がない場合には何も値を返しません

[プログラム例]

文字列(文字型配列)の中に指定した文字があればその位置をポインタで返し無ければ NULLポインタを返す関数を考えてみます

char strfind( char str char ch ) while( str ) if( str == ch )return str str++ return NULL

いくつかのC言語のマニュアルでは関数の説明を以下のように記述しています sin 機能 正弦を求めます 形式 include ltmathhgt double sin( double x ) このとき関数 sin() の戻り値は double 型でありまた指定する引数も double 型でなけれ

ばなりませんそれと同時にこの関数を使用する場合にはinclude ltmathhgt を指定しなければなりません

10

3-5 変数の通用範囲 関数内で宣言された変数はその関数の中でのみ使用可能です他のプログラムからは使用

することはできません

include ltstdiohgt main() int i 変数 i は関数 main() と sub() とでは それぞれ独立に使用することができます main() で変数 i に設定した値は sub() では参照することはできません sub() 逆にsub() で変数 i に設定した値も main() では参照することはできません

int i

それぞれの関数の中でのみ使用可能な変数をローカル変数と呼び他の関数でも使用可能

な変数をグローバル変数と呼びますいくつかの関数で共通に使用するような場合にはグロー

バル変数を使用します グローバル変数を定義する場合には関数の外で宣言します

include ltstdiohgt int i グローバル変数の定義

main() i = 10

sub() extern int i printf( yenn i = d i )

このプログラムではmain() 関数でグローバル変数に値を設定し関数 sub() で変数の値を

参照しています extern 宣言は変数が他のプログラム内で宣言されていることを示しています宣言の形式

は以下のとおりです extern 型 変数並び

演習5 入力された任意の数の倍数を求めるプログラムを作成しなさい入力する数値は2つ倍数 を求めるための任意の数と倍数の上限値ですここでいう上限値とは任意の数の倍数をどの くらいの数まで求めるかということです

11

3-6 動的変数と静的変数 通常Cで使用される変数はその関数の中だけでのみ使用できる変数ですしたがって関数

が実行するときに関数の中で使用する変数の領域を確保し関数の実行が終るときにその領域

を解放するようにしてメモリを効率的に利用していますこのように関数が実行されるときに確

保される変数を動的変数(auto変数 )と呼びます プログラムの中ではその他に常に存在し使用できる変数を定義することができますそのよ

うな変数は静的変数(static変数 )と呼ばれます

func() int a b static int x y

また static 変数には内部的なリンケージの指定の意味もありますつまり関数の外で変数

を宣言すると自動的にグローバル変数となり他のプログラムからも使用することができるようにな

ります ファイル a ファイル b このような場合にはコンパイル単位が異なっていてもextern 宣言を行うことにより変数 abc

を使用することができますところが関数の外で static 宣言をして定義した変数についてはコンパイル単位が違うプログラムからは使用することができなくなります ファイル a ファイル b 同一コンパイル単位(ファイル)に存在する関数 sub()と subd()では変数 abcを使用することが

できますがコンパイル単位(ファイル)が異なる関数 func()では変数 abcを使用することはできません

int abc sub() abc = 10

func() extern int abc printf( ldquo abc =dyennrdquo abc )

static int abc sub() abc = 10 subd() abc++

func() extern int abc printf( ldquo abc =dyennrdquo abc )

12

3-7 スタック プログラム中にはプログラム領域データ領域の他にスタック領域があり一時的な作業領域と

して使用されています関数間での引数の受渡しの時にもこの領域を使用しますスタック領域に

データを格納することを「スタックに積む」ともいいます基本的にはスタック領域に格納されたデ

ータは最後に格納されたデータから順に取り出されることになります以下に格納が行われたとき

のスタックの状態を示します記号は次に格納すべき位置(スタックポインタの値)を示していま

逆にスタックからデータを取り出すときにはスタックポインタが指している位置の一つ下から取

り出すことになりますスタックからデータを取り出すときのスタックの状態は次のようになります

なり

10

20

10

30

20

10

40

30

20

10

10rarr

格納

20rarr

格納

30rarr

格納

40rarr

格納

40rarr 30rarr

関数を呼び出すときには次

逆にそれぞれの関数から

次のようになります

40

30

20

10

取出

main() z = f1( x y )

のようにパラメータがスタ

戻るときにはパラメータで

30

20

10

取出

f1( int a int b ) c = f2( d e

xの値 yの値

xの値 yの値

13

ックに格納されます

使用していたスタック領域は自動的になく

10

20

)

f2( int p int q ) r = p + q

xの値

eの値 dの値

yの値

xの値 yの値

dの値

eの値

3-8 再帰呼び出し 関数の引数の受渡しがスタックを利用して行われることから自分で自分自身の関数を呼び出

すことができます 以下のプログラムは入力した値の階乗を計算するプログラムです

3の階乗を求めることを考えてみます

return 文によって戻るときは次のようにして値を返します kai( 3 ) 3 kai( 3-1 ) 2 kai( 2-1 ) return 1

6 3 (2 1) 2 1 以上の計算から3=6が導き出されます 再帰呼び出しのことをリカーシブコールともいいます

include ltstdiohgt main() int n m kai() scanf( ldquodrdquoampn ) m = kai( n ) printf( ldquod = dyennrdquo n m )

int kai( int k ) if( k == 1 )return 1 else return k kai( k ndash 1 )

kai( 1 )

darr

return 1

kai( 2 )

darr

2 kai( 2-1 )

kai( 3 )

darr

3 kai( 3-1 )

main()

darr

kai( 3 )

3

2

1

2

3

1

2

3 3

32

32

1

2

1

3

3

演習6 1からnまでの総和を再帰呼び出しを使って計算する関数 sowa() を作りなさい n+(n-1)+ +2+1

14

第4章 実習 この章ではプログラムを実際に入力して実行するまでの手順を実習します

4-1 操作手順 (1)ログイン

[スタート]rarr[プログラム(P)]rarr[ネットワーク] Hostの欄に bosei を記述選択 rarr [Telnet(FreeWare)] を選択します して 「OK」 ボタンをクリックします

UP-UXV (Rel42MP) (bosei) (pts41) login 60us1234 larr 各自のログイン名を入力します Password larr パスワードを入力しても画面は何も変化しません 101 60us1234bosei larr セッションが開設されましたこれをプロンプトといいます この状態でコマンドを入力することができます

(2)プログラムの作成 以下のコマンドを入力しテキストエディタを起動します 60us1234boseicc ng rensyuc

すると下図のようにngエディタの画面になります

15

次のように入力します入力ミスの修正はBSキーで行ないます

include ltstdiohgt main() float abc scanf(f f ampaampb) c=ab printf(f f f yenn abc)

CTRL キーを押しながら XCTRL キーを押しながら C を押しますすると次のメッセージが画面下に表示されます

Save file uhomea60us1234rensyuc (y or n)

このメッセージに対して y と答えます

(3)データの作成 以下のコマンドを入力しテキストエディタを起動します 60us1234boseicc ng rensyud

ngエディタの画面になりますので次のように入力します 12 35

CTRLキーを押しながら XCTRLキーを押しながら C を押します save file uhomea60us1234rensyud (y or n)

このメッセージに対して y と答えます

(4)コンパイルと実行 コンピュータに処理を依頼します 60us1234boseicc ccg rensyu

ジョブを投入しましたジョブの状態を見るコマンドは myjobです

16

130 60us1234boseicc myjob ================================================= NQS (R0220) BATCH REQUEST HOST bosei ================================================= REQUEST ID NAME OWNER QUEUE PRI NICE STT PGRP R --------------- -------- -------- -------- ---- --- --- ------ - 99321bosei STDIN 60us1234 A 31 0 RUN 14161 - ---------------------------------------------------------------- ================================================== NQS (R0220) DEVICE REQUEST HOST bosei ジョブは実行中です

================================================== REQUEST ID NAME OWNER QUEUE PRI SIZE STT -------------------------------------------------------------

所有するファイルの一覧を見てみます

60us1234boseicc ls -l larr 持っているファイルの一覧を見るコマンドです

-rw-r--r-- 1 60us1234 other 4 4月26日 15時14分 rensyud -rw-r--r-- 1 60us1234 other 128 4月26日 15時10分 rensyuc -rwxr-xr-x 1 60us1234 other 361 4月26日 15時16分 rensyul

(5)計算結果の確認

計算結果を画面に表示して確認します 60us1234boseicc more rensyul

(6)印刷

計算結果の印刷を行ないます5号館2階のカフェテリア室にある bosei のプリンタに印刷 されます

60us1234boseicc lpr rensyul

(7)ログアウト セッションを終了します 60us1234boseicc logout

(8)実行の流れ

エラー

プログラムの作成 ログイン コンパイル実行

確 認 印 刷 ログアウト

17

第5章 配列 多数の変数をまとめて宣言する方法として配列があります配列の一つ一つは配列要素と呼

ばれ変数と同じ性格を持っています配列の宣言は型宣言と同時に次のように行います int a[5] 配列 a

a[0]

a[1]

a[2]

a[3]

a[4]

二次元配列(一次元配列を複数集めたもの)を宣言する場合には次のようになります int b[3][4] 配列 b

b[0][0] b[0][1] b[0][2] b[0][3]

b[1][0] b[1][1] b[1][2] b[1][3]

b[2][0] b[2][1] b[2][2] b[2][3]

配列要素に数値を代入する場合は次のようになります b[1][2]=10

5-1 二次元配列要素の初期化 変数の型宣言と同じように配列を宣言するときに初期値も同時に設定することができます

複数のデータがある場合には{}記号でくくって指定します int b[3][4] = 2 4 6 8 1 3 5 7 1 2 3 4

文字型配列の場合には以下のようになりますyen0 は文字列の終わりを表わします char univ[3][7] = T O K A I yen0 S I M I Z U yen0 Y O Y O G I yen0

また文字列定数として初期化することもできますこの場合コンパイル時に自動的に yen0 が付加されます

char univ[3][7] = TOKAI SIMIZU YOYOGI

18

[プログラム例] 二次元配列のタテヨコを加算するプログラム

include ltstdiohgt main() int mat[4][3]=123456789101112 int ijytotalttotal[3]total=0 for(j=0jlt3j++)ttotal[j]=0 for (i=0ilt4i++) ytotal=0 for(j=0jlt3j++) ytotal += mat[i][j] ttotal[j] += mat[i][j] total += mat[i][j] printf(3dmat[i][j]) printf( 3dyennytotal) printf(yenn) for(j=0jlt3j++)printf(3dttotal[j]) printf( 3dyenntotal)

[実行結果]

1 2 3 6 4 5 6 15 7 8 9 24 10 11 12 33 22 26 30 78

演習7

a)以下の配列はどのように初期化されるか答えなさい char errmsg[2][15] = Divide Error Overflow Error

b)九九の計算を2次元配列を使って求めなさい

19

第6章 ポインタ型変数 C言語では値を記憶するための変数だけではなく変数または定数の番地を記憶するため

のポインタ型変数を宣言することができますポインタとはデータ項目の一種で「記憶装置(メモ

リ)上の格納番地(アドレス)を指すデータ項目」です アドレス コンピュータの中ではデータ項目の格納番地のことをアドレス(住所)と呼びます 例えば記憶装置という名前のとてつもなく大きなマンションがあるとしますその中から Aさんを捜すときは部屋番号を参照しますマンションでは部屋番号で住居人を参照し ているのと同じようにコンピュータでは記憶装置上に確保された変数は格納番地 (アドレス)で管理されています

マンション 部屋番号 記憶装置 格納番地

Aさん Int a Bさん Cさん AAAさん BBBさん CCCさん

1号室

2号室

3号室

100号室

200号室

300号室

100番地

200番地

300番地

1000番地

2000番地

3000番地

Int b Int c float aaafloat bbbfloat ccc

ポインタ ポインタとは「指し示すもの」の意ですがC言語では記憶装置上のアドレスを指し示す もののことです上のマンションの例では部屋番号を格納するデータ項目ということに なりますAAAさんは100号室に住んでいます100という値をポインタのデータ項目に 記憶するとそのデータ項目は間接的にAAAさんを指すことになります

6-1 ポインタ型変数の宣言および参照 通常の変数と区別するために型宣言時に変数名の前に記号を付けて宣言します int a 整数型ポインタ変数 int b 整数型変数

変数 a は整数型の値を記憶するのではなく整数型の値を持つ変数などの番地を記憶する変数ですまた変数 b は通常の整数型の値を記憶するための変数です

20

include ltstdiohgt main() int a b c a はポインタ型の変数b c は整数型の変数 b = 12 変数 b に値 12 を代入します a = ampb 変数 a には変数 b の番地が代入されます c = a + 10 変数 a の指す変数(b)の内容と10の加算です つまり12 + 10 を変数 c に代入します

変数の型宣言において変数名に記号を付けることによりその変数はポインタ型の変数と

なりますポインタ型の変数は変数名のみを指定した場合には単にその変数の値(通常はメモリ

の番地)を表します変数名に記号を付けて使用した場合にはその変数が指し示している変

数の内容を表します c = a ポインタ型変数 a が指している値を変数 c に代入

ポインタ型の変数に番地を記憶させるためにはプログラム例のように変数名の前に記号を

指定します変数名 によって変数の番地(アドレス)を表します a = ampb 変数 b の番地をポインタ型変数 a に代入します

ポインタ型変数の型はポインタ型変数が指し示す先の変数の型を表しています int a 変数 a 整数型の値 float x 変数 x 実数型の値 char c 変数 c 文字型の値

6-2 ポインタ型変数の初期化 ポインタ型変数も型宣言のときに変数を初期化することができます特に文字型のポインタ変

数の場合によく使います char str = TOKAI University

ポインタ型変数 str は文字列定数 TOKAI University の最初の文字が格納されている番地を初期値として持つことになります

変数 str TOKAI University 文字列定数

[プログラム例]

(1)文字型配列 putchar() 関数を使って一次元の文字型配列を出力します include ltstdiohgt main() char str[6] = TOKAI int i for( i = 0 str[i] = yen0 i++ ) putchar( str[i] )

21

ポインタを使用した場合には以下のようになります include ltstdiohgt main() char str[6] = TOKAI char chp for( chp = str chp = yen0 chp++ ) putchar( chp )

chp str T [0] O K A I yen0 [5]

参照する変数 配列の表現 ポインタの表現 実際のアドレス 1番目の数 str[0] chp CHP 2番目の数 str[1] (chp+1) CHP+1 n番目の数 str[n-1] (chp+n-1) CHP+n-1 6番目の数 str[5] (chp+5) CHP+5

注意実際のアドレス CHPは実行時に決定されます

(2)二次元文字型配列 二次元の文字型配列に定数を設定しそれを出力するプログラムです文字型配列を使用す

ると次のとおりになります include ltstdiohgt main() char str[5][40] = TOKAI shounan campus NEC DEC int i for( i = 0 i lt 5 i++ ) printf( yenns str[i] )

40 バイト str TOKAI shounan campus NEC DEC

22

ポインタ型配列を使用すると次のとおりになります include ltstdiohgt main() char str[6] = TOKAI shounan campus NEC DEC NULL char chp for( chp = str chp = NULL chp++ ) printf( yenns chp ) str

chp 番地 TOKAI 番地 shounan 番地 campus 番地 NEC 番地 DEC

NULL

演習8 キーボードまたはデータファイルから読み込んだ文字列中にrsquoArsquo があったら rsquoarsquo に変換 するプログラムを配列とポインタを使って書きなさい

23

第7章 構造体共用体 7-1 構造体

プログラムの規模が大きくなるにつれて多数の intや floatcharなどのデータ型を扱うようになり複雑になってきますそこで多数のデータを1つにまとめて簡単に扱える機能が構造体です 構造体について住所録のデータを例にあげて考えてみます

住所録の個人データとして氏名住所電話番号年齢の項目を一つのデータとします これをC言語で変数の定義をすると次のようになります 氏名東海太郎 char name[30] 住所平塚市北金目1117 char address[30] 電話番号0463-58-1211 char tel[20] 年齢30 int age 個人の住所録データ C言語での表現 このような住所録の個人データを1つにまとめて新しいデータとして定義する機能を構造体と言

います struct 構造体タグ名 構造体メンバーの並び

「struct」は構造体を表すキーワードです 「構造体タグ名」は構造体の型枠を宣言しますここは自由に名前を定義することができ ます 「構造体メンバーの並び」は構造体の要素です複数指定できます

個人の住所録のデータを構造体で宣言すると次のようになります

struct jusho char name[30] char address[30] 構造体のメンバーの並び char tel[20] (複数可)

int age

上記の宣言では構造体の形式を宣言しているだけでメモリ中で実際の領域を確保している

わけではありません実際に領域を確保するためには次のように定義します

struct 構造体タグ名 構造体名

したがって構造体名を jdata とすると次のように指定します

struct jusho jdata

構造体 jdataは次のように構造体タグ jushoの形式で領域を確保します

24

Jdata name[30]

address[30] tel[20] age

(1)構造体の参照

プログラム中で構造体中のメンバーを参照する場合には次のように指定します 構造体名メンバー名

したがって「名前」を参照したいときには次のように指定します

jdataname

[プログラム例]

名前住所電話番号年齢を定義しそれを印字します include ltstdiohgt include ltstringhgt main() struct jusho char name[30] char address[30] char tel[20] int age struct jusho jdata strcpy( jdataname 東海 太郎) strcpy( jdataaddress 平塚市北金目1117)

strcpy( jdatatel 0463-58-1211) jdataage = 30 printf(yenn氏名 = syenn jdataname) printf(yenn住所 = syenn jdataaddress) printf(yenn電話番号= syenn jdatatel) printf(yenn年齢 = dyenn jdataage)

また構造体の形式の定義と領域の確保は次のように同時におこなうことができます

struct 構造体タグ名 構造体メンバーの並び 構造体名

struct jusho struct jusho char name[30] char name[30] char address[30] char address[30] char tel[30] = char tel[30] int age 同じ int age

jdata struct jusho jdata

型宣言と同時にメモリ上に領域を確保する方法 後からメモリ上に領域を確保する方法

25

(2) 構造体配列 住所録データの場合その中に入るデータは1件ではありませんやはり100件200件のデ

ータが必要になる場合がありますこのように個人単位のデータを多数扱う場合には構造体を配

列として宣言することができます 次の例は個人のデータを100個用意するために構造体を配列として宣言しています struct jusho jdata[100] jdata[0] name[30] address[30] tel[20] age

jdata[99 ] name[30] address[30] tel[20] age

(3)構造体配列の参照

プログラム中で構造体配列中のメンバーを参照する場合には次のように指定します 構造体名[要素番号]メンバー名

したがって10件目の人の「名前」を参照したいときには次のように指定します

jdata[10]name

[プログラム例]

名前住所電話番号年齢を定義しそれを印字します include ltstdiohgt include ltstringhgt main() struct jusho char name[30] char address[30] char tel[20] int age jdata[100] strcpy( jdata[10]name 東海 太郎) strcpy( jdata[10]address 平塚市北金目1117)

strcpy( jdata[10]tel 0463-58-1211) jdata[10]age = 30 printf(yenn氏名 = syenn jdata[10]name) printf(yenn住所 = syenn jdata[10]address) printf(yenn電話番号= syenn jdata[10]tel) printf(yenn年齢 = dyenn jdata[10]age)

26

(4) 構造体のポインタ 変数と同じように構造体へのポインタも定義することができます

変数へのポインタ例 構造体へのポインタ例 またポインタを使用して構造体メンバーを参照するには次のように -> 記号を使って指

定します ポインタ変数名 -> メンバー名

[プログラム例]

名前住所電話番号年齢を定義しそれを印字します include ltstdiohgt include ltstringhgt main() struct jusho char name[30] char address[30] char tel[20] int age jdatakp kp = ampjdata strcpy( kp-gtname 東海 太郎)

strcpy( kp-gtaddress 平塚市北金目1117)

strcpy( kp-gttel 0463-58-1211) kp-gtage = 30 printf(yenn氏名 = syenn kp-gtname) printf(yenn住所 = syenn kp-gtaddress) printf(yenn電話番号= syenn kp-gttel) printf(yenn年齢 = dyenn kp-gtage)

kp jdata

name[30] ポインタ型の変数 address[30]

tel[20]

構造体へのポインタを記憶 age

することができます

int a int b b = ampa

struct name jname struct name np np = ampname

27

7-2 共用体 共用体は構造体と同じようにして宣言しますが共用体は複数のデータ型を同一のアドレスに

割り当てる方法です union 共用体タグ名 共用体メンバーの並び

「union」は共用体を表すキーワードです 「共用体タグ名」は共用体の型枠の名前を宣言しますここは自由に名前を定義することがで

きます 「共用体メンバーの並び」は共用体の要素です複数指定できます

共用体の宣言の例を次に示します

union c_tag int a char b

共用体 cは次のように共用体タグ c_tagの形式で領域を確保します共用体はメモリ上に領域を確保するときは ab ともに同じ領域に割り付けられます これはab という2つのデータが同時に存在するわけではなく cを異なるデータ abで共有す

ることを表しています c a b

上記の宣言だけでは共用体の形式を宣言しているだけでメモリ中で実際の領域を確保して

いるわけではありません実際に領域を確保するためには次のように定義します union 構造体タグ名 構造体名

したがって共用体名を c とすると次のように指定します

union c_tag c

(1)共用体の参照

プログラム中で共用体中のメンバーを参照する場合には次のように指定します 共用体名メンバー名

したがって「a」または「b」を参照したいときには次のように指定します

ca (int 型) cb (char 型)

メンバー参照方法によって int型として使ったりchar型として利用することができます

28

[プログラム例]

includeltstdiohgt main() union data char a short b int c chk chkc = 0x12345678 printf( char a xyennchka) printf( short b xyennchkb) printf( int c xyennchkc)

chkb(int 型) chkb(short 型) chka(char 型) 12 12 12 34 34 56 78

29

第8章 アルゴリズム コンピュータに何か仕事をさせようとするときは仕事を具体的に実行するための処理や動作

の手順が必要ですこの「手順」がアルゴリズムです アルゴリズムを考えるときは解くべき問題をはっきりと定義することが必要です

8-1 ソート ソートとは与えられたデータを小さい順または大きい順に並べ換えることですソート方法は

いくつかありますが基本的な方法でソートするアルゴリズムを紹介します

includeltstdiohgt int data[10] main()

int data_in() sort() data_in() sort() int data_in() データ入力関数

int a printf(数値入力yenn)

for(a=0alt=9a++) printf( [d]a+1) scanf(dampdata[a]) int sort() ソート処理を行う関数

int cont1cont2tmp1tmp2mim for(cont1=0 cont1lt=9 cont1++) mim=data[cont1] tmp1=cont1 for(cont2=cont1+1 cont2lt=9 cont2++) if(data[cont2] lt mim) mim=data[cont2] tmp1=cont2 tmp2 = data[cont1] data[cont1] = data[tmp1] data[tmp1] = tmp2 printf(結果 yenn)

for (cont1 = 0 cont1 lt= 9 cont1++) printf(d yenn data[cont1])

30

第9章 プリプロセッサ C言語にはプログラムの中でコンパイルについての指示を行う「プリプロセッサ」という機能が

ありますまたプリプロセッサとはコンパイルする前に実行されるためその意味のとおり「前処理」 と呼ばれていますここでは代表的なものをいくつか説明します

9-1 ファイルの挿入 ソースプログラム中に指定されたファイルを挿入します

include ltstdiohgt helliphellip 標準ディレクトリを探します include progh helliphellip 現在のディレクトリを探しなければ標準ディレクトリを探します

includeltstdiohgt によって組み込まれた define EOF (-1) define EOF (-1) define define helliphelliphelliphellip 組み込み helliphelliphelliphellip

main() stdiohファイル

int helliphelliphelliphellip helliphelliphelliphellip

ソースファイル

9-2 文字の置換 プログラム中に使われている文字列を別の文字列に置き換えます

include ltstdiohgt define TRUE 1 define EOF (-1) main() define helliphellip helliphellip

while(TRUE) define TRUE 1 置き換え main() helliphellip helliphellip while(1)

break helliphelliphellip

31

9-3 条件によるコンパイル 識別子が定義されているか否かを判断しコンパイルする範囲を指定します

include ltstdiohgt define UNIX main() ifdef UNIX printf( UNIX yenn) else printf(MS-DOSyenn) endif

include ltstdiohgt define OS UNIX main() if OS == UNIX printf( UNIX yenn) else printf(MS-DOSyenn) endif

32

付 録 1 puts()gets()関数について

行単位に入出力を行う場合には puts() gets() 関数を用います

puts() 標準出力に文字列を出力します

include ltstdiohgt int puts( char s ) puts() は NULL で終る文字列 s を標準出力に出力し最後に改行文字 yenn も出力しま

gets() 標準入力から文字列を入力します

include ltstdiohgt char gets( char s ) 戻り値正常に入力した場合には引数 s の値が返されますエラーやEOFになった場合に

は NULL が返されます gets() は標準入力から復帰文字で終る文字列を入力しs に格納しますこのとき最後の復

帰文字は NULL文字に変更されます

入力行の出力 標準入力から gets() で入力したデータには改行コードは含まれませんまた標準出力へ

puts() で出力を行う場合には必ず改行コードが付加されますgets() を実行したときの戻り値としてファイルの終端を検出した場合には EOF ではなく NULL が返されますので注意して下さい

include ltstdiohgt main() char data[80] while( gets( data ) = NULL )puts( data )

putchar()getchar()関数について putchar() 標準出力に文字を出力します

include ltstdiohgt int putchar(int c ) 戻り値正常に出力できた場合には文字cをエラーの場合にはEOFを返します

33

getchar() 標準入力から文字を入力します

include ltstdiohgt int getchar(void) 戻り値正常に入力した場合には読み込んだ文字を int 型に変換して返しますまたファイ

ルエンドエラーの場合にはEOFを返します

標準入力標準出力

標準入力標準出力はプログラムが開始されるときにはオープンされていますそれぞれのフ

ァイルポインタは stdin stdout になっていますfopen() fclose() をせずとも使用することができます

scanf() 標準出力ストリームからテキストを読み込み解釈します include ltstdiohgt int scanf( const char format [ address ] ) 戻り値正しくスキャンし変換し格納した入力フィールドの数を返しますファイルエンドを読

み込んだ場合は戻り値は EOF となります値を格納したフィールドがなかった場合は戻り値は0となります

一連の入力フィールドをスキャンして1度に1文字ずつストリーム stdin から文字を読み込み

ます次に引き数 format によって指される書式文字列中の書式指定に従って各フィールドを書式化します最後にformat の後に続く各引き数が示しているアドレスに書式化した入力を格納していきます書式文字列中の書式指定の個数はその後に続くアドレスの数と同じでな

ければなりません 書式指定[入力幅][型指定文字] 入力幅 読むべき文字数の最大値 型指定文字 次のとおりです 型指定文字 期待される入力 引き数の型 d 10進整数 int へのポインタ( int arg ) x 16進整数 int へのポインタ( int arg ) f 浮動小数点数 float へのポインタ( float arg ) s 文字列 文字配列へのポインタ( char arg[] ) c 文字 文字へのポインタ( char arg )

printf() フォーマットを指定してテキスト標準出力ストリームに出力します include ltstdiohgt int printf( const char format [ argument ] ) 戻り値出力したバイト数を返しますエラーの場合は EOF を返します

34

format によって指される書式文字列中の書式指定をformat の後に続く各引き数に適用し

書式化されたデータを stdout に出力します書式指定は後に続く引き数と同じ数だけなければなりません

書式指定[印字幅][精度][型指定文字] 印字幅 印字する最小文字数 精度 印字する最大文字数 型指定文字 つぎのとおりです 型指定文字 入力引き数 出力の書式 d 整数 符号付き10進整数 x 整数 符号無し16進整数 f 浮動小数点 符号付きの dddddddd形式の値 c 文字 1個の文字 s 文字列ポインタ ヌル文字に出会うか精度に達するまで 文字をプリントする

fopen()fclose()関数について fopen() ファイルをオープンします

include ltstdiohgt FILE fopen( char filename char mode ) 戻り値正常にファイルのオープンができたらファイルポインタを返しますエラーがあった場

合には NULLを返します 文字列 filename で指定されたファイルをオープンしますオープン後の入出力のモードに

ついては文字列 mode で指定しますmode に指定できる文字は以下のとおりです r 入力モードでオープンします w 出力モードでオープンします a 存在するファイルに追加して出力するモードでオープンします r+ 既に作成してあるファイルを更新(入力出力)するモードでオープンします w+ 新しく作成するファイルを更新モードでオープンします a+ 既に作成してあるファイルの終りから更新用に作成します

以上の文字に b をつけ加えることによりバイナリモードで入出力することができるようになり

ます rb バイナリの入力モードでオープンします wb バイナリの出力モードでオープンします ab 存在するファイルに追加して出力するモード(バイナリ)でオープンします

fclose() 既にオープンしてあるファイルをクローズします include ltstdiohgt fclose( FILE fp ) 既にオープンしているファイルをクローズしますパラメータには fopen() 関数により返された

ファイルポインタを指定します

35

テキストモードとバイナリモード 行の最後はテキストモードの場合改行コードのみとなりバイナリモードの場合には復帰

コードと改行コードの組合わせになります行の最後としてテキストファイルには復帰コード改行

コードが書かれていますがテキストモードでオープンした場合には入力すると改行コードのみに

変換されて入力されますバイナリモードの場合には復帰コード改行コードがそれぞれ入力され

ます

fputs()fgets()関数について fputs() ファイルポインタで指定されるファイルに文字列を出力します

include ltstdiohgt

int fputs( char s FILE fp ) fputs() は NULL で終る文字列 s をファイルポインタに示されるファイルへ出力しますputs()

と違い最後に改行文字 yenn を出力することはありません

fgets() ファイルポインタで指定されるファイルから文字列を入力します include ltstdiohgt char fgets( char s int n FILE fp ) 戻り値正常に入力した場合には引数 s の値が返されますエラーやEOFになった場合に

は NULL が返されます fgets() はファイルポインタで指定されるファイルから ( n - 1 ) 文字または改行文字までの

文字列を入力しs に格納しますgets() と異なり最後に入力された改行文字は NULL 文字に変更されません

標準入力から入力しファイルへ出力する ファイルへ出力あるいは入力を行う場合には改行コードの変換(入力の場合の削除出力の

場合の付加)はされませんしたがって標準入力から入力しファイルへ出力する場合には改行

コードを付加しなければなりません include ltstdiohgt main() char data[80] FILE fp fp = fopen( data w ) while( gets( data ) = NULL ) strcat( data yenn ) 改行コードの付加

fputs( data fp ) fclose( fp )

36

fputc()fgetc()関数について fputc() ファイルポインタで指定されるファイルに1文字出力します

include ltstdiohgt int fputc( int c FILE fp ) 戻り値正常に出力できた場合には文字 c を返しエラーの場合には EOF を返します fputc() は文字 c をファイルポインタで示されるファイルへ出力します

fgetc() ファイルポインタで指定されるファイルから1文字入力します

include ltstdiohgt int fgetc( FILE fp ) 戻り値正常に入力した場合には入力した文字を返しますエラーやEOFになった場合には

EOF が返されます fgetc() はファイルポインタで指定されるファイルから文字を入力します

ファイルの内容の表示 include ltstdiohgt main() FILE fp int ch char fname[30] printf( Key in Fila name gt ) gets( fname ) fp = fopen( fname r ) while( ( ch = fgetc( fp ) ) = EOF )putchar( ch ) fclose( fp )

その他テキスト中で使用された関数について sin() 三角関数の正弦を計算します

include ltmathhgt double sin(double radian) sinはラジアンを単位とする引数 radianの三角関数を計算します

37

strcpy() 文字列を他の文字列へコピーします

include ltstringhgt char strcpy(char string1const char string2) strcpyは引数 string2の指す文字列を null文字まで含めて引数 string1の指す領域にコピ

ーする strcpyは string1を返します

strcat() ある文字列を他の文字列に加えます

include ltstringhgt char strcat( char dest const char src ) 戻り値連結された文字列へのポインタを返します strcat() はsrc のコピーを dest の最後につけ加えます得られる文字列の長さは

strlen(dest)+strlen(src) になります

fabs() 絶対値の計算をします include ltmathhgt double fabs(double z) fabsは倍精度浮動小数の絶対値を計算して返しますつまりzgt=0であれば z をzlt0であ

れば-zを返します exp() 指数関数を計算します

include ltmathhgt double exp(double z) exp は引数zの指数関数つまりezを返すここではeは自然対数の底を表します対数関

数logの逆関数です

38

付 録 2 コンパイルの方法には大きく分けて第4章の実習で学んだようにデータファイルを作成してお

き ccg でコンパイルさせる方法と実行中に対話型でデータを入力していく方法があります ここでは対話型で実行を進めていく方法を紹介します ただしこの方法は計算(cpu)時間が10秒以内のものに限ります10秒を超える計算(cpu)時

間を要する場合はccg でコンパイルをするようにしてください 第4章実習の(2)(p16)までは同様です

コンパイル

コンピュータに処理を依頼します 60us1234boseicc cc rensyuc

所有するファイルの一覧を見てみます

60us1234boseicc ls -l larr 持っているファイルの一覧を見るコマンドです

-rw-r--r-- 1 60us1234 other 128 4月26日 15時14分 rensyuc -rwxr-xr-x 1 60us1234 other 361 4月26日 15時16分 aout

aout という実行形式のファイルが作成されています

実行

60us1234boseicc aout12 35[リターン] データを入力

1 200000 3500000 4200000 実行結果の出力

60us1234boseicc

注意

aout ファイルは印刷することができません実行結果を印刷する場合にはファイルに落とし てから出力するようにしましょう

60us1234boseicc aout gt kekka12 35[リターン] データを入力

60us1234boseicc more kekka 計算結果の確認 60us1234boseicc lpr kekka 計算結果の印刷

39

Page 7: n 第1章 章立ての部分は、書式(PC入門大見出し)を …第2章 数の表現 2-1 2進数 電子計算機の動作原理は0と1で表される2進数です。また、人間が日常生活で扱っている数

2-2 8進数と16進数 (1) 8進数

8進数とは0から7までの数字で表される数です (3 7 6 4)8 (8進数から10進数への変換) 80の位 3times83 + 7times82 + 6times81 + 4times80

81の位 = 3times512 + 7times64 + 6times8 + 4times1 82の位 = 1536 + 448 + 48 + 4 83の位 = 2036

(2) 16進数

16進数とは0から9およびAからFの文字で表される数ですABCDEFは10進数の

101112131415に対応します (1 2 A B)16 (16進数から10進数への変換) 160の位 1times163 + 2times162 + Atimes161 + Btimes160

161の位 = 1times4096 + 2times256 + Atimes16 + Btimes1 162の位 = 4096 + 512 + 160 + 11 163の位 = 4779

5

2-3 文字コード 文字 A などは8ビットのデータとして定義(コード化)されています文字コードの種類もいく

つかありUNIX や MS-DOS では ASCII コードを使用していますまた汎用機などではEBCDIC コードを使用しています

(1) ASCIIコード表(JIS8ビット)

上位4ビット

0 1 2 3 4 5 6 7 8 9 A B C D E F

0 SP 0 P p ― タ ミ 1 1 A Q a q ア チ ム 2 ldquo 2 B R b r 「 イ ツ メ 3 3 C S c s 」 ウ テ モ 4 $ 4 D T d t エ ト ヤ 5 5 E U e u オ ナ ユ 6 6 F V f v ヲ カ ニ ヨ 7 BE

L lsquo 7 G W g w ァ キ ヌ ラ

8 BS ( 8 H X h x ィ ク ネ リ 9 TAB ) 9 I Y i y ゥ ケ ノ ル A LF J Z j z ェ コ ハ レ B ESC + K [ k { ォ サ ヒ ロ C < L ¥ l | ャ シ フ ワ D CR - = M ] m } ュ ス ヘ ン E > N ^ n ~ ョ セ ホ ゛ F O _ o DE

L ッ ソ マ ゜

下位4ビット

したがって文字Aは ASCII コードで次のようになります A = (41)16

演習3

ASCII コード表を使って次の文字コードを16進数で表しなさい a) 9 b) M c) g

6

第3章 関数 3-1 関数とは

Cではプログラムの単位は関数で定義されますここでいう関数とは数学などで使われる

sincos 関数と同様の概念でありある値を与えると何らかの処理を行いその結果が関数値となるものですもちろんmain() も一つの関数ですその他にも自由に関数を作ることができます

例えば関数

f(x)=4x2+2x+5 を計算するときには次のようにプログラムを分けることができます データxを入力して関数f(x)を呼び出しその結果を印刷するプログラム 関数f(x)を計算するプログラム これをプログラムで表すと次のようになります

include ltstdiohgt main() float x y f() 変数と関数の型の宣言

while( scanf( f ampx ) = EOF ) y = f( x ) 関数の引用

printf( yenn x=f f(x)=f x y ) float f( float x ) 関数の定義

float y y = 40 x x + 20 x + 50 return y 計算を終了し結果を戻します

関数 f(x)は与えられたxの値によりyを計算して main()に結果を返します

3-2 関数の形式 関数を定義する場合には次の形式で定義します

型 関数名(仮引数の並び) float f ( float x )

変数の型宣言 関数内で使用する変数の宣言 プログラム プログラム }

関数の定義で型の指定がない場合にはint 型の関数となりますまた関数名は31文字以内の英数字の組み合わせです

3-3 引数

関数に渡すパラメータを引数といいますmain()関数などのように関数を引用する場合のパラメータを実引数と呼び呼ばれる関数で使用されているパラメータを仮引数と呼びます

include ltstdiohgt

7

main() float x y f() 変数と関数の型の宣言

while( scanf( f ampx ) = EOF ) y = f( x ) 関数の引用x は実引数と呼びます

printf( yenn x=f f(x)=f x y ) float f( float x ) 関数の定義x は仮引数と呼びます

float y y = 40 x x + 20 x + 50 return y 計算を終了し結果を戻します

[入力の終了について]

このプログラムを実行すると永遠とデータ入力を求められてしまいます終了条件が = EOF の場合はキーボードから CTRLキーを押しながら Z を入力することにより while文を抜け入力を終了することができます

複数の引数を受け渡しする場合には引用する側と関数を定義する側とで 引数の並び個数型

を合わせなければなりませんしかし変数名は同じでなくてもかまいません例えば配列 a と bを加算して配列 cに代入する場合には次のようになります

include ltstdiohgt main()

int a[10] = 18 24 56 28 96 51 82 34 65 72 UNIXの場合 static intにする int b[10] = 12 54 69 20 26 84 55 20 44 74 UNIXの場合 static intにする

int c[10] k void matadd() 関数の型宣言

matadd( a b c ) for( k = 0 k lt 10 k++ ) printf( yenn d + d = d a[k] b[k] c[k] ) void matadd( int x[] int y[] int z[] ) 関数の定義

int t for( t = 0 t lt 10 t++ ) z[t] = x[t] + y[t]

演習4 平均値を求める関数average()を作成し10名の数学の得点を読み込みその平均点を求め

るプログラムを作りなさい 「入力例」 「出力例」

45 63900000 78 97

8

この他にも関数にパラメータを渡す方法としてポインタを使用する方法があります文字列を

複写する関数の場合には次のとおりになります関数名は strcopy()最初の引数には複写先の配列名(配列の先頭番地)次の引数には複写元の配列名(配列の先頭番地)です

include ltstdiohgt main() char src[] = tokai dst[80] void strcopy() strcopy( dst src ) printf( syenn dst )

void strcopy( char str1 char str2 ) while( ( str1++ = str2++ ) = yen0 )

また配列の加算を行う関数の場合にもそれぞれの配列名をパラメータとし関数側でポイン

タ型変数として受け取ることができます

include ltstdiohgt main() int a[10] = 18 24 56 28 96 51 82 34 65 72 UNIXの場合 static intにする int b[10] = 12 54 69 20 26 84 55 20 44 74 UNIXの場合 static intにする

int c[10] int k void matadd() matadd( a b c 10 ) for( k = 0 k lt 10 k++ ) printf( d + d = d yenn a[k] b[k] c[k] )

void matadd( int x int y int z int n ) for( n gt 0 n-- ) z++ = x++ + y++

main()関数では配列名(アドレス定数)として引数に指定されていますが関数 matadd()ではポインタ型の変数として使用することができますしたがって変数 xyz は値を変更することができるようになります

配列 a 変数 x

9

配列 b 変数 y 配列 c 変数 x

3-4 戻り値 関数からの戻り値はreturn 文によって返されます整数型文字型の値を返す関数の場合

にはそれぞれ次のように定義します

int sub( int x ) char sub( int x ) int y char z

return y return z

またポインタを返す関数の場合には次のように定義します

int sub( int x ) char sub( int x ) int y char z

return y return z

return文で式の指定がない場合には何も値を返しません

[プログラム例]

文字列(文字型配列)の中に指定した文字があればその位置をポインタで返し無ければ NULLポインタを返す関数を考えてみます

char strfind( char str char ch ) while( str ) if( str == ch )return str str++ return NULL

いくつかのC言語のマニュアルでは関数の説明を以下のように記述しています sin 機能 正弦を求めます 形式 include ltmathhgt double sin( double x ) このとき関数 sin() の戻り値は double 型でありまた指定する引数も double 型でなけれ

ばなりませんそれと同時にこの関数を使用する場合にはinclude ltmathhgt を指定しなければなりません

10

3-5 変数の通用範囲 関数内で宣言された変数はその関数の中でのみ使用可能です他のプログラムからは使用

することはできません

include ltstdiohgt main() int i 変数 i は関数 main() と sub() とでは それぞれ独立に使用することができます main() で変数 i に設定した値は sub() では参照することはできません sub() 逆にsub() で変数 i に設定した値も main() では参照することはできません

int i

それぞれの関数の中でのみ使用可能な変数をローカル変数と呼び他の関数でも使用可能

な変数をグローバル変数と呼びますいくつかの関数で共通に使用するような場合にはグロー

バル変数を使用します グローバル変数を定義する場合には関数の外で宣言します

include ltstdiohgt int i グローバル変数の定義

main() i = 10

sub() extern int i printf( yenn i = d i )

このプログラムではmain() 関数でグローバル変数に値を設定し関数 sub() で変数の値を

参照しています extern 宣言は変数が他のプログラム内で宣言されていることを示しています宣言の形式

は以下のとおりです extern 型 変数並び

演習5 入力された任意の数の倍数を求めるプログラムを作成しなさい入力する数値は2つ倍数 を求めるための任意の数と倍数の上限値ですここでいう上限値とは任意の数の倍数をどの くらいの数まで求めるかということです

11

3-6 動的変数と静的変数 通常Cで使用される変数はその関数の中だけでのみ使用できる変数ですしたがって関数

が実行するときに関数の中で使用する変数の領域を確保し関数の実行が終るときにその領域

を解放するようにしてメモリを効率的に利用していますこのように関数が実行されるときに確

保される変数を動的変数(auto変数 )と呼びます プログラムの中ではその他に常に存在し使用できる変数を定義することができますそのよ

うな変数は静的変数(static変数 )と呼ばれます

func() int a b static int x y

また static 変数には内部的なリンケージの指定の意味もありますつまり関数の外で変数

を宣言すると自動的にグローバル変数となり他のプログラムからも使用することができるようにな

ります ファイル a ファイル b このような場合にはコンパイル単位が異なっていてもextern 宣言を行うことにより変数 abc

を使用することができますところが関数の外で static 宣言をして定義した変数についてはコンパイル単位が違うプログラムからは使用することができなくなります ファイル a ファイル b 同一コンパイル単位(ファイル)に存在する関数 sub()と subd()では変数 abcを使用することが

できますがコンパイル単位(ファイル)が異なる関数 func()では変数 abcを使用することはできません

int abc sub() abc = 10

func() extern int abc printf( ldquo abc =dyennrdquo abc )

static int abc sub() abc = 10 subd() abc++

func() extern int abc printf( ldquo abc =dyennrdquo abc )

12

3-7 スタック プログラム中にはプログラム領域データ領域の他にスタック領域があり一時的な作業領域と

して使用されています関数間での引数の受渡しの時にもこの領域を使用しますスタック領域に

データを格納することを「スタックに積む」ともいいます基本的にはスタック領域に格納されたデ

ータは最後に格納されたデータから順に取り出されることになります以下に格納が行われたとき

のスタックの状態を示します記号は次に格納すべき位置(スタックポインタの値)を示していま

逆にスタックからデータを取り出すときにはスタックポインタが指している位置の一つ下から取

り出すことになりますスタックからデータを取り出すときのスタックの状態は次のようになります

なり

10

20

10

30

20

10

40

30

20

10

10rarr

格納

20rarr

格納

30rarr

格納

40rarr

格納

40rarr 30rarr

関数を呼び出すときには次

逆にそれぞれの関数から

次のようになります

40

30

20

10

取出

main() z = f1( x y )

のようにパラメータがスタ

戻るときにはパラメータで

30

20

10

取出

f1( int a int b ) c = f2( d e

xの値 yの値

xの値 yの値

13

ックに格納されます

使用していたスタック領域は自動的になく

10

20

)

f2( int p int q ) r = p + q

xの値

eの値 dの値

yの値

xの値 yの値

dの値

eの値

3-8 再帰呼び出し 関数の引数の受渡しがスタックを利用して行われることから自分で自分自身の関数を呼び出

すことができます 以下のプログラムは入力した値の階乗を計算するプログラムです

3の階乗を求めることを考えてみます

return 文によって戻るときは次のようにして値を返します kai( 3 ) 3 kai( 3-1 ) 2 kai( 2-1 ) return 1

6 3 (2 1) 2 1 以上の計算から3=6が導き出されます 再帰呼び出しのことをリカーシブコールともいいます

include ltstdiohgt main() int n m kai() scanf( ldquodrdquoampn ) m = kai( n ) printf( ldquod = dyennrdquo n m )

int kai( int k ) if( k == 1 )return 1 else return k kai( k ndash 1 )

kai( 1 )

darr

return 1

kai( 2 )

darr

2 kai( 2-1 )

kai( 3 )

darr

3 kai( 3-1 )

main()

darr

kai( 3 )

3

2

1

2

3

1

2

3 3

32

32

1

2

1

3

3

演習6 1からnまでの総和を再帰呼び出しを使って計算する関数 sowa() を作りなさい n+(n-1)+ +2+1

14

第4章 実習 この章ではプログラムを実際に入力して実行するまでの手順を実習します

4-1 操作手順 (1)ログイン

[スタート]rarr[プログラム(P)]rarr[ネットワーク] Hostの欄に bosei を記述選択 rarr [Telnet(FreeWare)] を選択します して 「OK」 ボタンをクリックします

UP-UXV (Rel42MP) (bosei) (pts41) login 60us1234 larr 各自のログイン名を入力します Password larr パスワードを入力しても画面は何も変化しません 101 60us1234bosei larr セッションが開設されましたこれをプロンプトといいます この状態でコマンドを入力することができます

(2)プログラムの作成 以下のコマンドを入力しテキストエディタを起動します 60us1234boseicc ng rensyuc

すると下図のようにngエディタの画面になります

15

次のように入力します入力ミスの修正はBSキーで行ないます

include ltstdiohgt main() float abc scanf(f f ampaampb) c=ab printf(f f f yenn abc)

CTRL キーを押しながら XCTRL キーを押しながら C を押しますすると次のメッセージが画面下に表示されます

Save file uhomea60us1234rensyuc (y or n)

このメッセージに対して y と答えます

(3)データの作成 以下のコマンドを入力しテキストエディタを起動します 60us1234boseicc ng rensyud

ngエディタの画面になりますので次のように入力します 12 35

CTRLキーを押しながら XCTRLキーを押しながら C を押します save file uhomea60us1234rensyud (y or n)

このメッセージに対して y と答えます

(4)コンパイルと実行 コンピュータに処理を依頼します 60us1234boseicc ccg rensyu

ジョブを投入しましたジョブの状態を見るコマンドは myjobです

16

130 60us1234boseicc myjob ================================================= NQS (R0220) BATCH REQUEST HOST bosei ================================================= REQUEST ID NAME OWNER QUEUE PRI NICE STT PGRP R --------------- -------- -------- -------- ---- --- --- ------ - 99321bosei STDIN 60us1234 A 31 0 RUN 14161 - ---------------------------------------------------------------- ================================================== NQS (R0220) DEVICE REQUEST HOST bosei ジョブは実行中です

================================================== REQUEST ID NAME OWNER QUEUE PRI SIZE STT -------------------------------------------------------------

所有するファイルの一覧を見てみます

60us1234boseicc ls -l larr 持っているファイルの一覧を見るコマンドです

-rw-r--r-- 1 60us1234 other 4 4月26日 15時14分 rensyud -rw-r--r-- 1 60us1234 other 128 4月26日 15時10分 rensyuc -rwxr-xr-x 1 60us1234 other 361 4月26日 15時16分 rensyul

(5)計算結果の確認

計算結果を画面に表示して確認します 60us1234boseicc more rensyul

(6)印刷

計算結果の印刷を行ないます5号館2階のカフェテリア室にある bosei のプリンタに印刷 されます

60us1234boseicc lpr rensyul

(7)ログアウト セッションを終了します 60us1234boseicc logout

(8)実行の流れ

エラー

プログラムの作成 ログイン コンパイル実行

確 認 印 刷 ログアウト

17

第5章 配列 多数の変数をまとめて宣言する方法として配列があります配列の一つ一つは配列要素と呼

ばれ変数と同じ性格を持っています配列の宣言は型宣言と同時に次のように行います int a[5] 配列 a

a[0]

a[1]

a[2]

a[3]

a[4]

二次元配列(一次元配列を複数集めたもの)を宣言する場合には次のようになります int b[3][4] 配列 b

b[0][0] b[0][1] b[0][2] b[0][3]

b[1][0] b[1][1] b[1][2] b[1][3]

b[2][0] b[2][1] b[2][2] b[2][3]

配列要素に数値を代入する場合は次のようになります b[1][2]=10

5-1 二次元配列要素の初期化 変数の型宣言と同じように配列を宣言するときに初期値も同時に設定することができます

複数のデータがある場合には{}記号でくくって指定します int b[3][4] = 2 4 6 8 1 3 5 7 1 2 3 4

文字型配列の場合には以下のようになりますyen0 は文字列の終わりを表わします char univ[3][7] = T O K A I yen0 S I M I Z U yen0 Y O Y O G I yen0

また文字列定数として初期化することもできますこの場合コンパイル時に自動的に yen0 が付加されます

char univ[3][7] = TOKAI SIMIZU YOYOGI

18

[プログラム例] 二次元配列のタテヨコを加算するプログラム

include ltstdiohgt main() int mat[4][3]=123456789101112 int ijytotalttotal[3]total=0 for(j=0jlt3j++)ttotal[j]=0 for (i=0ilt4i++) ytotal=0 for(j=0jlt3j++) ytotal += mat[i][j] ttotal[j] += mat[i][j] total += mat[i][j] printf(3dmat[i][j]) printf( 3dyennytotal) printf(yenn) for(j=0jlt3j++)printf(3dttotal[j]) printf( 3dyenntotal)

[実行結果]

1 2 3 6 4 5 6 15 7 8 9 24 10 11 12 33 22 26 30 78

演習7

a)以下の配列はどのように初期化されるか答えなさい char errmsg[2][15] = Divide Error Overflow Error

b)九九の計算を2次元配列を使って求めなさい

19

第6章 ポインタ型変数 C言語では値を記憶するための変数だけではなく変数または定数の番地を記憶するため

のポインタ型変数を宣言することができますポインタとはデータ項目の一種で「記憶装置(メモ

リ)上の格納番地(アドレス)を指すデータ項目」です アドレス コンピュータの中ではデータ項目の格納番地のことをアドレス(住所)と呼びます 例えば記憶装置という名前のとてつもなく大きなマンションがあるとしますその中から Aさんを捜すときは部屋番号を参照しますマンションでは部屋番号で住居人を参照し ているのと同じようにコンピュータでは記憶装置上に確保された変数は格納番地 (アドレス)で管理されています

マンション 部屋番号 記憶装置 格納番地

Aさん Int a Bさん Cさん AAAさん BBBさん CCCさん

1号室

2号室

3号室

100号室

200号室

300号室

100番地

200番地

300番地

1000番地

2000番地

3000番地

Int b Int c float aaafloat bbbfloat ccc

ポインタ ポインタとは「指し示すもの」の意ですがC言語では記憶装置上のアドレスを指し示す もののことです上のマンションの例では部屋番号を格納するデータ項目ということに なりますAAAさんは100号室に住んでいます100という値をポインタのデータ項目に 記憶するとそのデータ項目は間接的にAAAさんを指すことになります

6-1 ポインタ型変数の宣言および参照 通常の変数と区別するために型宣言時に変数名の前に記号を付けて宣言します int a 整数型ポインタ変数 int b 整数型変数

変数 a は整数型の値を記憶するのではなく整数型の値を持つ変数などの番地を記憶する変数ですまた変数 b は通常の整数型の値を記憶するための変数です

20

include ltstdiohgt main() int a b c a はポインタ型の変数b c は整数型の変数 b = 12 変数 b に値 12 を代入します a = ampb 変数 a には変数 b の番地が代入されます c = a + 10 変数 a の指す変数(b)の内容と10の加算です つまり12 + 10 を変数 c に代入します

変数の型宣言において変数名に記号を付けることによりその変数はポインタ型の変数と

なりますポインタ型の変数は変数名のみを指定した場合には単にその変数の値(通常はメモリ

の番地)を表します変数名に記号を付けて使用した場合にはその変数が指し示している変

数の内容を表します c = a ポインタ型変数 a が指している値を変数 c に代入

ポインタ型の変数に番地を記憶させるためにはプログラム例のように変数名の前に記号を

指定します変数名 によって変数の番地(アドレス)を表します a = ampb 変数 b の番地をポインタ型変数 a に代入します

ポインタ型変数の型はポインタ型変数が指し示す先の変数の型を表しています int a 変数 a 整数型の値 float x 変数 x 実数型の値 char c 変数 c 文字型の値

6-2 ポインタ型変数の初期化 ポインタ型変数も型宣言のときに変数を初期化することができます特に文字型のポインタ変

数の場合によく使います char str = TOKAI University

ポインタ型変数 str は文字列定数 TOKAI University の最初の文字が格納されている番地を初期値として持つことになります

変数 str TOKAI University 文字列定数

[プログラム例]

(1)文字型配列 putchar() 関数を使って一次元の文字型配列を出力します include ltstdiohgt main() char str[6] = TOKAI int i for( i = 0 str[i] = yen0 i++ ) putchar( str[i] )

21

ポインタを使用した場合には以下のようになります include ltstdiohgt main() char str[6] = TOKAI char chp for( chp = str chp = yen0 chp++ ) putchar( chp )

chp str T [0] O K A I yen0 [5]

参照する変数 配列の表現 ポインタの表現 実際のアドレス 1番目の数 str[0] chp CHP 2番目の数 str[1] (chp+1) CHP+1 n番目の数 str[n-1] (chp+n-1) CHP+n-1 6番目の数 str[5] (chp+5) CHP+5

注意実際のアドレス CHPは実行時に決定されます

(2)二次元文字型配列 二次元の文字型配列に定数を設定しそれを出力するプログラムです文字型配列を使用す

ると次のとおりになります include ltstdiohgt main() char str[5][40] = TOKAI shounan campus NEC DEC int i for( i = 0 i lt 5 i++ ) printf( yenns str[i] )

40 バイト str TOKAI shounan campus NEC DEC

22

ポインタ型配列を使用すると次のとおりになります include ltstdiohgt main() char str[6] = TOKAI shounan campus NEC DEC NULL char chp for( chp = str chp = NULL chp++ ) printf( yenns chp ) str

chp 番地 TOKAI 番地 shounan 番地 campus 番地 NEC 番地 DEC

NULL

演習8 キーボードまたはデータファイルから読み込んだ文字列中にrsquoArsquo があったら rsquoarsquo に変換 するプログラムを配列とポインタを使って書きなさい

23

第7章 構造体共用体 7-1 構造体

プログラムの規模が大きくなるにつれて多数の intや floatcharなどのデータ型を扱うようになり複雑になってきますそこで多数のデータを1つにまとめて簡単に扱える機能が構造体です 構造体について住所録のデータを例にあげて考えてみます

住所録の個人データとして氏名住所電話番号年齢の項目を一つのデータとします これをC言語で変数の定義をすると次のようになります 氏名東海太郎 char name[30] 住所平塚市北金目1117 char address[30] 電話番号0463-58-1211 char tel[20] 年齢30 int age 個人の住所録データ C言語での表現 このような住所録の個人データを1つにまとめて新しいデータとして定義する機能を構造体と言

います struct 構造体タグ名 構造体メンバーの並び

「struct」は構造体を表すキーワードです 「構造体タグ名」は構造体の型枠を宣言しますここは自由に名前を定義することができ ます 「構造体メンバーの並び」は構造体の要素です複数指定できます

個人の住所録のデータを構造体で宣言すると次のようになります

struct jusho char name[30] char address[30] 構造体のメンバーの並び char tel[20] (複数可)

int age

上記の宣言では構造体の形式を宣言しているだけでメモリ中で実際の領域を確保している

わけではありません実際に領域を確保するためには次のように定義します

struct 構造体タグ名 構造体名

したがって構造体名を jdata とすると次のように指定します

struct jusho jdata

構造体 jdataは次のように構造体タグ jushoの形式で領域を確保します

24

Jdata name[30]

address[30] tel[20] age

(1)構造体の参照

プログラム中で構造体中のメンバーを参照する場合には次のように指定します 構造体名メンバー名

したがって「名前」を参照したいときには次のように指定します

jdataname

[プログラム例]

名前住所電話番号年齢を定義しそれを印字します include ltstdiohgt include ltstringhgt main() struct jusho char name[30] char address[30] char tel[20] int age struct jusho jdata strcpy( jdataname 東海 太郎) strcpy( jdataaddress 平塚市北金目1117)

strcpy( jdatatel 0463-58-1211) jdataage = 30 printf(yenn氏名 = syenn jdataname) printf(yenn住所 = syenn jdataaddress) printf(yenn電話番号= syenn jdatatel) printf(yenn年齢 = dyenn jdataage)

また構造体の形式の定義と領域の確保は次のように同時におこなうことができます

struct 構造体タグ名 構造体メンバーの並び 構造体名

struct jusho struct jusho char name[30] char name[30] char address[30] char address[30] char tel[30] = char tel[30] int age 同じ int age

jdata struct jusho jdata

型宣言と同時にメモリ上に領域を確保する方法 後からメモリ上に領域を確保する方法

25

(2) 構造体配列 住所録データの場合その中に入るデータは1件ではありませんやはり100件200件のデ

ータが必要になる場合がありますこのように個人単位のデータを多数扱う場合には構造体を配

列として宣言することができます 次の例は個人のデータを100個用意するために構造体を配列として宣言しています struct jusho jdata[100] jdata[0] name[30] address[30] tel[20] age

jdata[99 ] name[30] address[30] tel[20] age

(3)構造体配列の参照

プログラム中で構造体配列中のメンバーを参照する場合には次のように指定します 構造体名[要素番号]メンバー名

したがって10件目の人の「名前」を参照したいときには次のように指定します

jdata[10]name

[プログラム例]

名前住所電話番号年齢を定義しそれを印字します include ltstdiohgt include ltstringhgt main() struct jusho char name[30] char address[30] char tel[20] int age jdata[100] strcpy( jdata[10]name 東海 太郎) strcpy( jdata[10]address 平塚市北金目1117)

strcpy( jdata[10]tel 0463-58-1211) jdata[10]age = 30 printf(yenn氏名 = syenn jdata[10]name) printf(yenn住所 = syenn jdata[10]address) printf(yenn電話番号= syenn jdata[10]tel) printf(yenn年齢 = dyenn jdata[10]age)

26

(4) 構造体のポインタ 変数と同じように構造体へのポインタも定義することができます

変数へのポインタ例 構造体へのポインタ例 またポインタを使用して構造体メンバーを参照するには次のように -> 記号を使って指

定します ポインタ変数名 -> メンバー名

[プログラム例]

名前住所電話番号年齢を定義しそれを印字します include ltstdiohgt include ltstringhgt main() struct jusho char name[30] char address[30] char tel[20] int age jdatakp kp = ampjdata strcpy( kp-gtname 東海 太郎)

strcpy( kp-gtaddress 平塚市北金目1117)

strcpy( kp-gttel 0463-58-1211) kp-gtage = 30 printf(yenn氏名 = syenn kp-gtname) printf(yenn住所 = syenn kp-gtaddress) printf(yenn電話番号= syenn kp-gttel) printf(yenn年齢 = dyenn kp-gtage)

kp jdata

name[30] ポインタ型の変数 address[30]

tel[20]

構造体へのポインタを記憶 age

することができます

int a int b b = ampa

struct name jname struct name np np = ampname

27

7-2 共用体 共用体は構造体と同じようにして宣言しますが共用体は複数のデータ型を同一のアドレスに

割り当てる方法です union 共用体タグ名 共用体メンバーの並び

「union」は共用体を表すキーワードです 「共用体タグ名」は共用体の型枠の名前を宣言しますここは自由に名前を定義することがで

きます 「共用体メンバーの並び」は共用体の要素です複数指定できます

共用体の宣言の例を次に示します

union c_tag int a char b

共用体 cは次のように共用体タグ c_tagの形式で領域を確保します共用体はメモリ上に領域を確保するときは ab ともに同じ領域に割り付けられます これはab という2つのデータが同時に存在するわけではなく cを異なるデータ abで共有す

ることを表しています c a b

上記の宣言だけでは共用体の形式を宣言しているだけでメモリ中で実際の領域を確保して

いるわけではありません実際に領域を確保するためには次のように定義します union 構造体タグ名 構造体名

したがって共用体名を c とすると次のように指定します

union c_tag c

(1)共用体の参照

プログラム中で共用体中のメンバーを参照する場合には次のように指定します 共用体名メンバー名

したがって「a」または「b」を参照したいときには次のように指定します

ca (int 型) cb (char 型)

メンバー参照方法によって int型として使ったりchar型として利用することができます

28

[プログラム例]

includeltstdiohgt main() union data char a short b int c chk chkc = 0x12345678 printf( char a xyennchka) printf( short b xyennchkb) printf( int c xyennchkc)

chkb(int 型) chkb(short 型) chka(char 型) 12 12 12 34 34 56 78

29

第8章 アルゴリズム コンピュータに何か仕事をさせようとするときは仕事を具体的に実行するための処理や動作

の手順が必要ですこの「手順」がアルゴリズムです アルゴリズムを考えるときは解くべき問題をはっきりと定義することが必要です

8-1 ソート ソートとは与えられたデータを小さい順または大きい順に並べ換えることですソート方法は

いくつかありますが基本的な方法でソートするアルゴリズムを紹介します

includeltstdiohgt int data[10] main()

int data_in() sort() data_in() sort() int data_in() データ入力関数

int a printf(数値入力yenn)

for(a=0alt=9a++) printf( [d]a+1) scanf(dampdata[a]) int sort() ソート処理を行う関数

int cont1cont2tmp1tmp2mim for(cont1=0 cont1lt=9 cont1++) mim=data[cont1] tmp1=cont1 for(cont2=cont1+1 cont2lt=9 cont2++) if(data[cont2] lt mim) mim=data[cont2] tmp1=cont2 tmp2 = data[cont1] data[cont1] = data[tmp1] data[tmp1] = tmp2 printf(結果 yenn)

for (cont1 = 0 cont1 lt= 9 cont1++) printf(d yenn data[cont1])

30

第9章 プリプロセッサ C言語にはプログラムの中でコンパイルについての指示を行う「プリプロセッサ」という機能が

ありますまたプリプロセッサとはコンパイルする前に実行されるためその意味のとおり「前処理」 と呼ばれていますここでは代表的なものをいくつか説明します

9-1 ファイルの挿入 ソースプログラム中に指定されたファイルを挿入します

include ltstdiohgt helliphellip 標準ディレクトリを探します include progh helliphellip 現在のディレクトリを探しなければ標準ディレクトリを探します

includeltstdiohgt によって組み込まれた define EOF (-1) define EOF (-1) define define helliphelliphelliphellip 組み込み helliphelliphelliphellip

main() stdiohファイル

int helliphelliphelliphellip helliphelliphelliphellip

ソースファイル

9-2 文字の置換 プログラム中に使われている文字列を別の文字列に置き換えます

include ltstdiohgt define TRUE 1 define EOF (-1) main() define helliphellip helliphellip

while(TRUE) define TRUE 1 置き換え main() helliphellip helliphellip while(1)

break helliphelliphellip

31

9-3 条件によるコンパイル 識別子が定義されているか否かを判断しコンパイルする範囲を指定します

include ltstdiohgt define UNIX main() ifdef UNIX printf( UNIX yenn) else printf(MS-DOSyenn) endif

include ltstdiohgt define OS UNIX main() if OS == UNIX printf( UNIX yenn) else printf(MS-DOSyenn) endif

32

付 録 1 puts()gets()関数について

行単位に入出力を行う場合には puts() gets() 関数を用います

puts() 標準出力に文字列を出力します

include ltstdiohgt int puts( char s ) puts() は NULL で終る文字列 s を標準出力に出力し最後に改行文字 yenn も出力しま

gets() 標準入力から文字列を入力します

include ltstdiohgt char gets( char s ) 戻り値正常に入力した場合には引数 s の値が返されますエラーやEOFになった場合に

は NULL が返されます gets() は標準入力から復帰文字で終る文字列を入力しs に格納しますこのとき最後の復

帰文字は NULL文字に変更されます

入力行の出力 標準入力から gets() で入力したデータには改行コードは含まれませんまた標準出力へ

puts() で出力を行う場合には必ず改行コードが付加されますgets() を実行したときの戻り値としてファイルの終端を検出した場合には EOF ではなく NULL が返されますので注意して下さい

include ltstdiohgt main() char data[80] while( gets( data ) = NULL )puts( data )

putchar()getchar()関数について putchar() 標準出力に文字を出力します

include ltstdiohgt int putchar(int c ) 戻り値正常に出力できた場合には文字cをエラーの場合にはEOFを返します

33

getchar() 標準入力から文字を入力します

include ltstdiohgt int getchar(void) 戻り値正常に入力した場合には読み込んだ文字を int 型に変換して返しますまたファイ

ルエンドエラーの場合にはEOFを返します

標準入力標準出力

標準入力標準出力はプログラムが開始されるときにはオープンされていますそれぞれのフ

ァイルポインタは stdin stdout になっていますfopen() fclose() をせずとも使用することができます

scanf() 標準出力ストリームからテキストを読み込み解釈します include ltstdiohgt int scanf( const char format [ address ] ) 戻り値正しくスキャンし変換し格納した入力フィールドの数を返しますファイルエンドを読

み込んだ場合は戻り値は EOF となります値を格納したフィールドがなかった場合は戻り値は0となります

一連の入力フィールドをスキャンして1度に1文字ずつストリーム stdin から文字を読み込み

ます次に引き数 format によって指される書式文字列中の書式指定に従って各フィールドを書式化します最後にformat の後に続く各引き数が示しているアドレスに書式化した入力を格納していきます書式文字列中の書式指定の個数はその後に続くアドレスの数と同じでな

ければなりません 書式指定[入力幅][型指定文字] 入力幅 読むべき文字数の最大値 型指定文字 次のとおりです 型指定文字 期待される入力 引き数の型 d 10進整数 int へのポインタ( int arg ) x 16進整数 int へのポインタ( int arg ) f 浮動小数点数 float へのポインタ( float arg ) s 文字列 文字配列へのポインタ( char arg[] ) c 文字 文字へのポインタ( char arg )

printf() フォーマットを指定してテキスト標準出力ストリームに出力します include ltstdiohgt int printf( const char format [ argument ] ) 戻り値出力したバイト数を返しますエラーの場合は EOF を返します

34

format によって指される書式文字列中の書式指定をformat の後に続く各引き数に適用し

書式化されたデータを stdout に出力します書式指定は後に続く引き数と同じ数だけなければなりません

書式指定[印字幅][精度][型指定文字] 印字幅 印字する最小文字数 精度 印字する最大文字数 型指定文字 つぎのとおりです 型指定文字 入力引き数 出力の書式 d 整数 符号付き10進整数 x 整数 符号無し16進整数 f 浮動小数点 符号付きの dddddddd形式の値 c 文字 1個の文字 s 文字列ポインタ ヌル文字に出会うか精度に達するまで 文字をプリントする

fopen()fclose()関数について fopen() ファイルをオープンします

include ltstdiohgt FILE fopen( char filename char mode ) 戻り値正常にファイルのオープンができたらファイルポインタを返しますエラーがあった場

合には NULLを返します 文字列 filename で指定されたファイルをオープンしますオープン後の入出力のモードに

ついては文字列 mode で指定しますmode に指定できる文字は以下のとおりです r 入力モードでオープンします w 出力モードでオープンします a 存在するファイルに追加して出力するモードでオープンします r+ 既に作成してあるファイルを更新(入力出力)するモードでオープンします w+ 新しく作成するファイルを更新モードでオープンします a+ 既に作成してあるファイルの終りから更新用に作成します

以上の文字に b をつけ加えることによりバイナリモードで入出力することができるようになり

ます rb バイナリの入力モードでオープンします wb バイナリの出力モードでオープンします ab 存在するファイルに追加して出力するモード(バイナリ)でオープンします

fclose() 既にオープンしてあるファイルをクローズします include ltstdiohgt fclose( FILE fp ) 既にオープンしているファイルをクローズしますパラメータには fopen() 関数により返された

ファイルポインタを指定します

35

テキストモードとバイナリモード 行の最後はテキストモードの場合改行コードのみとなりバイナリモードの場合には復帰

コードと改行コードの組合わせになります行の最後としてテキストファイルには復帰コード改行

コードが書かれていますがテキストモードでオープンした場合には入力すると改行コードのみに

変換されて入力されますバイナリモードの場合には復帰コード改行コードがそれぞれ入力され

ます

fputs()fgets()関数について fputs() ファイルポインタで指定されるファイルに文字列を出力します

include ltstdiohgt

int fputs( char s FILE fp ) fputs() は NULL で終る文字列 s をファイルポインタに示されるファイルへ出力しますputs()

と違い最後に改行文字 yenn を出力することはありません

fgets() ファイルポインタで指定されるファイルから文字列を入力します include ltstdiohgt char fgets( char s int n FILE fp ) 戻り値正常に入力した場合には引数 s の値が返されますエラーやEOFになった場合に

は NULL が返されます fgets() はファイルポインタで指定されるファイルから ( n - 1 ) 文字または改行文字までの

文字列を入力しs に格納しますgets() と異なり最後に入力された改行文字は NULL 文字に変更されません

標準入力から入力しファイルへ出力する ファイルへ出力あるいは入力を行う場合には改行コードの変換(入力の場合の削除出力の

場合の付加)はされませんしたがって標準入力から入力しファイルへ出力する場合には改行

コードを付加しなければなりません include ltstdiohgt main() char data[80] FILE fp fp = fopen( data w ) while( gets( data ) = NULL ) strcat( data yenn ) 改行コードの付加

fputs( data fp ) fclose( fp )

36

fputc()fgetc()関数について fputc() ファイルポインタで指定されるファイルに1文字出力します

include ltstdiohgt int fputc( int c FILE fp ) 戻り値正常に出力できた場合には文字 c を返しエラーの場合には EOF を返します fputc() は文字 c をファイルポインタで示されるファイルへ出力します

fgetc() ファイルポインタで指定されるファイルから1文字入力します

include ltstdiohgt int fgetc( FILE fp ) 戻り値正常に入力した場合には入力した文字を返しますエラーやEOFになった場合には

EOF が返されます fgetc() はファイルポインタで指定されるファイルから文字を入力します

ファイルの内容の表示 include ltstdiohgt main() FILE fp int ch char fname[30] printf( Key in Fila name gt ) gets( fname ) fp = fopen( fname r ) while( ( ch = fgetc( fp ) ) = EOF )putchar( ch ) fclose( fp )

その他テキスト中で使用された関数について sin() 三角関数の正弦を計算します

include ltmathhgt double sin(double radian) sinはラジアンを単位とする引数 radianの三角関数を計算します

37

strcpy() 文字列を他の文字列へコピーします

include ltstringhgt char strcpy(char string1const char string2) strcpyは引数 string2の指す文字列を null文字まで含めて引数 string1の指す領域にコピ

ーする strcpyは string1を返します

strcat() ある文字列を他の文字列に加えます

include ltstringhgt char strcat( char dest const char src ) 戻り値連結された文字列へのポインタを返します strcat() はsrc のコピーを dest の最後につけ加えます得られる文字列の長さは

strlen(dest)+strlen(src) になります

fabs() 絶対値の計算をします include ltmathhgt double fabs(double z) fabsは倍精度浮動小数の絶対値を計算して返しますつまりzgt=0であれば z をzlt0であ

れば-zを返します exp() 指数関数を計算します

include ltmathhgt double exp(double z) exp は引数zの指数関数つまりezを返すここではeは自然対数の底を表します対数関

数logの逆関数です

38

付 録 2 コンパイルの方法には大きく分けて第4章の実習で学んだようにデータファイルを作成してお

き ccg でコンパイルさせる方法と実行中に対話型でデータを入力していく方法があります ここでは対話型で実行を進めていく方法を紹介します ただしこの方法は計算(cpu)時間が10秒以内のものに限ります10秒を超える計算(cpu)時

間を要する場合はccg でコンパイルをするようにしてください 第4章実習の(2)(p16)までは同様です

コンパイル

コンピュータに処理を依頼します 60us1234boseicc cc rensyuc

所有するファイルの一覧を見てみます

60us1234boseicc ls -l larr 持っているファイルの一覧を見るコマンドです

-rw-r--r-- 1 60us1234 other 128 4月26日 15時14分 rensyuc -rwxr-xr-x 1 60us1234 other 361 4月26日 15時16分 aout

aout という実行形式のファイルが作成されています

実行

60us1234boseicc aout12 35[リターン] データを入力

1 200000 3500000 4200000 実行結果の出力

60us1234boseicc

注意

aout ファイルは印刷することができません実行結果を印刷する場合にはファイルに落とし てから出力するようにしましょう

60us1234boseicc aout gt kekka12 35[リターン] データを入力

60us1234boseicc more kekka 計算結果の確認 60us1234boseicc lpr kekka 計算結果の印刷

39

Page 8: n 第1章 章立ての部分は、書式(PC入門大見出し)を …第2章 数の表現 2-1 2進数 電子計算機の動作原理は0と1で表される2進数です。また、人間が日常生活で扱っている数

2-3 文字コード 文字 A などは8ビットのデータとして定義(コード化)されています文字コードの種類もいく

つかありUNIX や MS-DOS では ASCII コードを使用していますまた汎用機などではEBCDIC コードを使用しています

(1) ASCIIコード表(JIS8ビット)

上位4ビット

0 1 2 3 4 5 6 7 8 9 A B C D E F

0 SP 0 P p ― タ ミ 1 1 A Q a q ア チ ム 2 ldquo 2 B R b r 「 イ ツ メ 3 3 C S c s 」 ウ テ モ 4 $ 4 D T d t エ ト ヤ 5 5 E U e u オ ナ ユ 6 6 F V f v ヲ カ ニ ヨ 7 BE

L lsquo 7 G W g w ァ キ ヌ ラ

8 BS ( 8 H X h x ィ ク ネ リ 9 TAB ) 9 I Y i y ゥ ケ ノ ル A LF J Z j z ェ コ ハ レ B ESC + K [ k { ォ サ ヒ ロ C < L ¥ l | ャ シ フ ワ D CR - = M ] m } ュ ス ヘ ン E > N ^ n ~ ョ セ ホ ゛ F O _ o DE

L ッ ソ マ ゜

下位4ビット

したがって文字Aは ASCII コードで次のようになります A = (41)16

演習3

ASCII コード表を使って次の文字コードを16進数で表しなさい a) 9 b) M c) g

6

第3章 関数 3-1 関数とは

Cではプログラムの単位は関数で定義されますここでいう関数とは数学などで使われる

sincos 関数と同様の概念でありある値を与えると何らかの処理を行いその結果が関数値となるものですもちろんmain() も一つの関数ですその他にも自由に関数を作ることができます

例えば関数

f(x)=4x2+2x+5 を計算するときには次のようにプログラムを分けることができます データxを入力して関数f(x)を呼び出しその結果を印刷するプログラム 関数f(x)を計算するプログラム これをプログラムで表すと次のようになります

include ltstdiohgt main() float x y f() 変数と関数の型の宣言

while( scanf( f ampx ) = EOF ) y = f( x ) 関数の引用

printf( yenn x=f f(x)=f x y ) float f( float x ) 関数の定義

float y y = 40 x x + 20 x + 50 return y 計算を終了し結果を戻します

関数 f(x)は与えられたxの値によりyを計算して main()に結果を返します

3-2 関数の形式 関数を定義する場合には次の形式で定義します

型 関数名(仮引数の並び) float f ( float x )

変数の型宣言 関数内で使用する変数の宣言 プログラム プログラム }

関数の定義で型の指定がない場合にはint 型の関数となりますまた関数名は31文字以内の英数字の組み合わせです

3-3 引数

関数に渡すパラメータを引数といいますmain()関数などのように関数を引用する場合のパラメータを実引数と呼び呼ばれる関数で使用されているパラメータを仮引数と呼びます

include ltstdiohgt

7

main() float x y f() 変数と関数の型の宣言

while( scanf( f ampx ) = EOF ) y = f( x ) 関数の引用x は実引数と呼びます

printf( yenn x=f f(x)=f x y ) float f( float x ) 関数の定義x は仮引数と呼びます

float y y = 40 x x + 20 x + 50 return y 計算を終了し結果を戻します

[入力の終了について]

このプログラムを実行すると永遠とデータ入力を求められてしまいます終了条件が = EOF の場合はキーボードから CTRLキーを押しながら Z を入力することにより while文を抜け入力を終了することができます

複数の引数を受け渡しする場合には引用する側と関数を定義する側とで 引数の並び個数型

を合わせなければなりませんしかし変数名は同じでなくてもかまいません例えば配列 a と bを加算して配列 cに代入する場合には次のようになります

include ltstdiohgt main()

int a[10] = 18 24 56 28 96 51 82 34 65 72 UNIXの場合 static intにする int b[10] = 12 54 69 20 26 84 55 20 44 74 UNIXの場合 static intにする

int c[10] k void matadd() 関数の型宣言

matadd( a b c ) for( k = 0 k lt 10 k++ ) printf( yenn d + d = d a[k] b[k] c[k] ) void matadd( int x[] int y[] int z[] ) 関数の定義

int t for( t = 0 t lt 10 t++ ) z[t] = x[t] + y[t]

演習4 平均値を求める関数average()を作成し10名の数学の得点を読み込みその平均点を求め

るプログラムを作りなさい 「入力例」 「出力例」

45 63900000 78 97

8

この他にも関数にパラメータを渡す方法としてポインタを使用する方法があります文字列を

複写する関数の場合には次のとおりになります関数名は strcopy()最初の引数には複写先の配列名(配列の先頭番地)次の引数には複写元の配列名(配列の先頭番地)です

include ltstdiohgt main() char src[] = tokai dst[80] void strcopy() strcopy( dst src ) printf( syenn dst )

void strcopy( char str1 char str2 ) while( ( str1++ = str2++ ) = yen0 )

また配列の加算を行う関数の場合にもそれぞれの配列名をパラメータとし関数側でポイン

タ型変数として受け取ることができます

include ltstdiohgt main() int a[10] = 18 24 56 28 96 51 82 34 65 72 UNIXの場合 static intにする int b[10] = 12 54 69 20 26 84 55 20 44 74 UNIXの場合 static intにする

int c[10] int k void matadd() matadd( a b c 10 ) for( k = 0 k lt 10 k++ ) printf( d + d = d yenn a[k] b[k] c[k] )

void matadd( int x int y int z int n ) for( n gt 0 n-- ) z++ = x++ + y++

main()関数では配列名(アドレス定数)として引数に指定されていますが関数 matadd()ではポインタ型の変数として使用することができますしたがって変数 xyz は値を変更することができるようになります

配列 a 変数 x

9

配列 b 変数 y 配列 c 変数 x

3-4 戻り値 関数からの戻り値はreturn 文によって返されます整数型文字型の値を返す関数の場合

にはそれぞれ次のように定義します

int sub( int x ) char sub( int x ) int y char z

return y return z

またポインタを返す関数の場合には次のように定義します

int sub( int x ) char sub( int x ) int y char z

return y return z

return文で式の指定がない場合には何も値を返しません

[プログラム例]

文字列(文字型配列)の中に指定した文字があればその位置をポインタで返し無ければ NULLポインタを返す関数を考えてみます

char strfind( char str char ch ) while( str ) if( str == ch )return str str++ return NULL

いくつかのC言語のマニュアルでは関数の説明を以下のように記述しています sin 機能 正弦を求めます 形式 include ltmathhgt double sin( double x ) このとき関数 sin() の戻り値は double 型でありまた指定する引数も double 型でなけれ

ばなりませんそれと同時にこの関数を使用する場合にはinclude ltmathhgt を指定しなければなりません

10

3-5 変数の通用範囲 関数内で宣言された変数はその関数の中でのみ使用可能です他のプログラムからは使用

することはできません

include ltstdiohgt main() int i 変数 i は関数 main() と sub() とでは それぞれ独立に使用することができます main() で変数 i に設定した値は sub() では参照することはできません sub() 逆にsub() で変数 i に設定した値も main() では参照することはできません

int i

それぞれの関数の中でのみ使用可能な変数をローカル変数と呼び他の関数でも使用可能

な変数をグローバル変数と呼びますいくつかの関数で共通に使用するような場合にはグロー

バル変数を使用します グローバル変数を定義する場合には関数の外で宣言します

include ltstdiohgt int i グローバル変数の定義

main() i = 10

sub() extern int i printf( yenn i = d i )

このプログラムではmain() 関数でグローバル変数に値を設定し関数 sub() で変数の値を

参照しています extern 宣言は変数が他のプログラム内で宣言されていることを示しています宣言の形式

は以下のとおりです extern 型 変数並び

演習5 入力された任意の数の倍数を求めるプログラムを作成しなさい入力する数値は2つ倍数 を求めるための任意の数と倍数の上限値ですここでいう上限値とは任意の数の倍数をどの くらいの数まで求めるかということです

11

3-6 動的変数と静的変数 通常Cで使用される変数はその関数の中だけでのみ使用できる変数ですしたがって関数

が実行するときに関数の中で使用する変数の領域を確保し関数の実行が終るときにその領域

を解放するようにしてメモリを効率的に利用していますこのように関数が実行されるときに確

保される変数を動的変数(auto変数 )と呼びます プログラムの中ではその他に常に存在し使用できる変数を定義することができますそのよ

うな変数は静的変数(static変数 )と呼ばれます

func() int a b static int x y

また static 変数には内部的なリンケージの指定の意味もありますつまり関数の外で変数

を宣言すると自動的にグローバル変数となり他のプログラムからも使用することができるようにな

ります ファイル a ファイル b このような場合にはコンパイル単位が異なっていてもextern 宣言を行うことにより変数 abc

を使用することができますところが関数の外で static 宣言をして定義した変数についてはコンパイル単位が違うプログラムからは使用することができなくなります ファイル a ファイル b 同一コンパイル単位(ファイル)に存在する関数 sub()と subd()では変数 abcを使用することが

できますがコンパイル単位(ファイル)が異なる関数 func()では変数 abcを使用することはできません

int abc sub() abc = 10

func() extern int abc printf( ldquo abc =dyennrdquo abc )

static int abc sub() abc = 10 subd() abc++

func() extern int abc printf( ldquo abc =dyennrdquo abc )

12

3-7 スタック プログラム中にはプログラム領域データ領域の他にスタック領域があり一時的な作業領域と

して使用されています関数間での引数の受渡しの時にもこの領域を使用しますスタック領域に

データを格納することを「スタックに積む」ともいいます基本的にはスタック領域に格納されたデ

ータは最後に格納されたデータから順に取り出されることになります以下に格納が行われたとき

のスタックの状態を示します記号は次に格納すべき位置(スタックポインタの値)を示していま

逆にスタックからデータを取り出すときにはスタックポインタが指している位置の一つ下から取

り出すことになりますスタックからデータを取り出すときのスタックの状態は次のようになります

なり

10

20

10

30

20

10

40

30

20

10

10rarr

格納

20rarr

格納

30rarr

格納

40rarr

格納

40rarr 30rarr

関数を呼び出すときには次

逆にそれぞれの関数から

次のようになります

40

30

20

10

取出

main() z = f1( x y )

のようにパラメータがスタ

戻るときにはパラメータで

30

20

10

取出

f1( int a int b ) c = f2( d e

xの値 yの値

xの値 yの値

13

ックに格納されます

使用していたスタック領域は自動的になく

10

20

)

f2( int p int q ) r = p + q

xの値

eの値 dの値

yの値

xの値 yの値

dの値

eの値

3-8 再帰呼び出し 関数の引数の受渡しがスタックを利用して行われることから自分で自分自身の関数を呼び出

すことができます 以下のプログラムは入力した値の階乗を計算するプログラムです

3の階乗を求めることを考えてみます

return 文によって戻るときは次のようにして値を返します kai( 3 ) 3 kai( 3-1 ) 2 kai( 2-1 ) return 1

6 3 (2 1) 2 1 以上の計算から3=6が導き出されます 再帰呼び出しのことをリカーシブコールともいいます

include ltstdiohgt main() int n m kai() scanf( ldquodrdquoampn ) m = kai( n ) printf( ldquod = dyennrdquo n m )

int kai( int k ) if( k == 1 )return 1 else return k kai( k ndash 1 )

kai( 1 )

darr

return 1

kai( 2 )

darr

2 kai( 2-1 )

kai( 3 )

darr

3 kai( 3-1 )

main()

darr

kai( 3 )

3

2

1

2

3

1

2

3 3

32

32

1

2

1

3

3

演習6 1からnまでの総和を再帰呼び出しを使って計算する関数 sowa() を作りなさい n+(n-1)+ +2+1

14

第4章 実習 この章ではプログラムを実際に入力して実行するまでの手順を実習します

4-1 操作手順 (1)ログイン

[スタート]rarr[プログラム(P)]rarr[ネットワーク] Hostの欄に bosei を記述選択 rarr [Telnet(FreeWare)] を選択します して 「OK」 ボタンをクリックします

UP-UXV (Rel42MP) (bosei) (pts41) login 60us1234 larr 各自のログイン名を入力します Password larr パスワードを入力しても画面は何も変化しません 101 60us1234bosei larr セッションが開設されましたこれをプロンプトといいます この状態でコマンドを入力することができます

(2)プログラムの作成 以下のコマンドを入力しテキストエディタを起動します 60us1234boseicc ng rensyuc

すると下図のようにngエディタの画面になります

15

次のように入力します入力ミスの修正はBSキーで行ないます

include ltstdiohgt main() float abc scanf(f f ampaampb) c=ab printf(f f f yenn abc)

CTRL キーを押しながら XCTRL キーを押しながら C を押しますすると次のメッセージが画面下に表示されます

Save file uhomea60us1234rensyuc (y or n)

このメッセージに対して y と答えます

(3)データの作成 以下のコマンドを入力しテキストエディタを起動します 60us1234boseicc ng rensyud

ngエディタの画面になりますので次のように入力します 12 35

CTRLキーを押しながら XCTRLキーを押しながら C を押します save file uhomea60us1234rensyud (y or n)

このメッセージに対して y と答えます

(4)コンパイルと実行 コンピュータに処理を依頼します 60us1234boseicc ccg rensyu

ジョブを投入しましたジョブの状態を見るコマンドは myjobです

16

130 60us1234boseicc myjob ================================================= NQS (R0220) BATCH REQUEST HOST bosei ================================================= REQUEST ID NAME OWNER QUEUE PRI NICE STT PGRP R --------------- -------- -------- -------- ---- --- --- ------ - 99321bosei STDIN 60us1234 A 31 0 RUN 14161 - ---------------------------------------------------------------- ================================================== NQS (R0220) DEVICE REQUEST HOST bosei ジョブは実行中です

================================================== REQUEST ID NAME OWNER QUEUE PRI SIZE STT -------------------------------------------------------------

所有するファイルの一覧を見てみます

60us1234boseicc ls -l larr 持っているファイルの一覧を見るコマンドです

-rw-r--r-- 1 60us1234 other 4 4月26日 15時14分 rensyud -rw-r--r-- 1 60us1234 other 128 4月26日 15時10分 rensyuc -rwxr-xr-x 1 60us1234 other 361 4月26日 15時16分 rensyul

(5)計算結果の確認

計算結果を画面に表示して確認します 60us1234boseicc more rensyul

(6)印刷

計算結果の印刷を行ないます5号館2階のカフェテリア室にある bosei のプリンタに印刷 されます

60us1234boseicc lpr rensyul

(7)ログアウト セッションを終了します 60us1234boseicc logout

(8)実行の流れ

エラー

プログラムの作成 ログイン コンパイル実行

確 認 印 刷 ログアウト

17

第5章 配列 多数の変数をまとめて宣言する方法として配列があります配列の一つ一つは配列要素と呼

ばれ変数と同じ性格を持っています配列の宣言は型宣言と同時に次のように行います int a[5] 配列 a

a[0]

a[1]

a[2]

a[3]

a[4]

二次元配列(一次元配列を複数集めたもの)を宣言する場合には次のようになります int b[3][4] 配列 b

b[0][0] b[0][1] b[0][2] b[0][3]

b[1][0] b[1][1] b[1][2] b[1][3]

b[2][0] b[2][1] b[2][2] b[2][3]

配列要素に数値を代入する場合は次のようになります b[1][2]=10

5-1 二次元配列要素の初期化 変数の型宣言と同じように配列を宣言するときに初期値も同時に設定することができます

複数のデータがある場合には{}記号でくくって指定します int b[3][4] = 2 4 6 8 1 3 5 7 1 2 3 4

文字型配列の場合には以下のようになりますyen0 は文字列の終わりを表わします char univ[3][7] = T O K A I yen0 S I M I Z U yen0 Y O Y O G I yen0

また文字列定数として初期化することもできますこの場合コンパイル時に自動的に yen0 が付加されます

char univ[3][7] = TOKAI SIMIZU YOYOGI

18

[プログラム例] 二次元配列のタテヨコを加算するプログラム

include ltstdiohgt main() int mat[4][3]=123456789101112 int ijytotalttotal[3]total=0 for(j=0jlt3j++)ttotal[j]=0 for (i=0ilt4i++) ytotal=0 for(j=0jlt3j++) ytotal += mat[i][j] ttotal[j] += mat[i][j] total += mat[i][j] printf(3dmat[i][j]) printf( 3dyennytotal) printf(yenn) for(j=0jlt3j++)printf(3dttotal[j]) printf( 3dyenntotal)

[実行結果]

1 2 3 6 4 5 6 15 7 8 9 24 10 11 12 33 22 26 30 78

演習7

a)以下の配列はどのように初期化されるか答えなさい char errmsg[2][15] = Divide Error Overflow Error

b)九九の計算を2次元配列を使って求めなさい

19

第6章 ポインタ型変数 C言語では値を記憶するための変数だけではなく変数または定数の番地を記憶するため

のポインタ型変数を宣言することができますポインタとはデータ項目の一種で「記憶装置(メモ

リ)上の格納番地(アドレス)を指すデータ項目」です アドレス コンピュータの中ではデータ項目の格納番地のことをアドレス(住所)と呼びます 例えば記憶装置という名前のとてつもなく大きなマンションがあるとしますその中から Aさんを捜すときは部屋番号を参照しますマンションでは部屋番号で住居人を参照し ているのと同じようにコンピュータでは記憶装置上に確保された変数は格納番地 (アドレス)で管理されています

マンション 部屋番号 記憶装置 格納番地

Aさん Int a Bさん Cさん AAAさん BBBさん CCCさん

1号室

2号室

3号室

100号室

200号室

300号室

100番地

200番地

300番地

1000番地

2000番地

3000番地

Int b Int c float aaafloat bbbfloat ccc

ポインタ ポインタとは「指し示すもの」の意ですがC言語では記憶装置上のアドレスを指し示す もののことです上のマンションの例では部屋番号を格納するデータ項目ということに なりますAAAさんは100号室に住んでいます100という値をポインタのデータ項目に 記憶するとそのデータ項目は間接的にAAAさんを指すことになります

6-1 ポインタ型変数の宣言および参照 通常の変数と区別するために型宣言時に変数名の前に記号を付けて宣言します int a 整数型ポインタ変数 int b 整数型変数

変数 a は整数型の値を記憶するのではなく整数型の値を持つ変数などの番地を記憶する変数ですまた変数 b は通常の整数型の値を記憶するための変数です

20

include ltstdiohgt main() int a b c a はポインタ型の変数b c は整数型の変数 b = 12 変数 b に値 12 を代入します a = ampb 変数 a には変数 b の番地が代入されます c = a + 10 変数 a の指す変数(b)の内容と10の加算です つまり12 + 10 を変数 c に代入します

変数の型宣言において変数名に記号を付けることによりその変数はポインタ型の変数と

なりますポインタ型の変数は変数名のみを指定した場合には単にその変数の値(通常はメモリ

の番地)を表します変数名に記号を付けて使用した場合にはその変数が指し示している変

数の内容を表します c = a ポインタ型変数 a が指している値を変数 c に代入

ポインタ型の変数に番地を記憶させるためにはプログラム例のように変数名の前に記号を

指定します変数名 によって変数の番地(アドレス)を表します a = ampb 変数 b の番地をポインタ型変数 a に代入します

ポインタ型変数の型はポインタ型変数が指し示す先の変数の型を表しています int a 変数 a 整数型の値 float x 変数 x 実数型の値 char c 変数 c 文字型の値

6-2 ポインタ型変数の初期化 ポインタ型変数も型宣言のときに変数を初期化することができます特に文字型のポインタ変

数の場合によく使います char str = TOKAI University

ポインタ型変数 str は文字列定数 TOKAI University の最初の文字が格納されている番地を初期値として持つことになります

変数 str TOKAI University 文字列定数

[プログラム例]

(1)文字型配列 putchar() 関数を使って一次元の文字型配列を出力します include ltstdiohgt main() char str[6] = TOKAI int i for( i = 0 str[i] = yen0 i++ ) putchar( str[i] )

21

ポインタを使用した場合には以下のようになります include ltstdiohgt main() char str[6] = TOKAI char chp for( chp = str chp = yen0 chp++ ) putchar( chp )

chp str T [0] O K A I yen0 [5]

参照する変数 配列の表現 ポインタの表現 実際のアドレス 1番目の数 str[0] chp CHP 2番目の数 str[1] (chp+1) CHP+1 n番目の数 str[n-1] (chp+n-1) CHP+n-1 6番目の数 str[5] (chp+5) CHP+5

注意実際のアドレス CHPは実行時に決定されます

(2)二次元文字型配列 二次元の文字型配列に定数を設定しそれを出力するプログラムです文字型配列を使用す

ると次のとおりになります include ltstdiohgt main() char str[5][40] = TOKAI shounan campus NEC DEC int i for( i = 0 i lt 5 i++ ) printf( yenns str[i] )

40 バイト str TOKAI shounan campus NEC DEC

22

ポインタ型配列を使用すると次のとおりになります include ltstdiohgt main() char str[6] = TOKAI shounan campus NEC DEC NULL char chp for( chp = str chp = NULL chp++ ) printf( yenns chp ) str

chp 番地 TOKAI 番地 shounan 番地 campus 番地 NEC 番地 DEC

NULL

演習8 キーボードまたはデータファイルから読み込んだ文字列中にrsquoArsquo があったら rsquoarsquo に変換 するプログラムを配列とポインタを使って書きなさい

23

第7章 構造体共用体 7-1 構造体

プログラムの規模が大きくなるにつれて多数の intや floatcharなどのデータ型を扱うようになり複雑になってきますそこで多数のデータを1つにまとめて簡単に扱える機能が構造体です 構造体について住所録のデータを例にあげて考えてみます

住所録の個人データとして氏名住所電話番号年齢の項目を一つのデータとします これをC言語で変数の定義をすると次のようになります 氏名東海太郎 char name[30] 住所平塚市北金目1117 char address[30] 電話番号0463-58-1211 char tel[20] 年齢30 int age 個人の住所録データ C言語での表現 このような住所録の個人データを1つにまとめて新しいデータとして定義する機能を構造体と言

います struct 構造体タグ名 構造体メンバーの並び

「struct」は構造体を表すキーワードです 「構造体タグ名」は構造体の型枠を宣言しますここは自由に名前を定義することができ ます 「構造体メンバーの並び」は構造体の要素です複数指定できます

個人の住所録のデータを構造体で宣言すると次のようになります

struct jusho char name[30] char address[30] 構造体のメンバーの並び char tel[20] (複数可)

int age

上記の宣言では構造体の形式を宣言しているだけでメモリ中で実際の領域を確保している

わけではありません実際に領域を確保するためには次のように定義します

struct 構造体タグ名 構造体名

したがって構造体名を jdata とすると次のように指定します

struct jusho jdata

構造体 jdataは次のように構造体タグ jushoの形式で領域を確保します

24

Jdata name[30]

address[30] tel[20] age

(1)構造体の参照

プログラム中で構造体中のメンバーを参照する場合には次のように指定します 構造体名メンバー名

したがって「名前」を参照したいときには次のように指定します

jdataname

[プログラム例]

名前住所電話番号年齢を定義しそれを印字します include ltstdiohgt include ltstringhgt main() struct jusho char name[30] char address[30] char tel[20] int age struct jusho jdata strcpy( jdataname 東海 太郎) strcpy( jdataaddress 平塚市北金目1117)

strcpy( jdatatel 0463-58-1211) jdataage = 30 printf(yenn氏名 = syenn jdataname) printf(yenn住所 = syenn jdataaddress) printf(yenn電話番号= syenn jdatatel) printf(yenn年齢 = dyenn jdataage)

また構造体の形式の定義と領域の確保は次のように同時におこなうことができます

struct 構造体タグ名 構造体メンバーの並び 構造体名

struct jusho struct jusho char name[30] char name[30] char address[30] char address[30] char tel[30] = char tel[30] int age 同じ int age

jdata struct jusho jdata

型宣言と同時にメモリ上に領域を確保する方法 後からメモリ上に領域を確保する方法

25

(2) 構造体配列 住所録データの場合その中に入るデータは1件ではありませんやはり100件200件のデ

ータが必要になる場合がありますこのように個人単位のデータを多数扱う場合には構造体を配

列として宣言することができます 次の例は個人のデータを100個用意するために構造体を配列として宣言しています struct jusho jdata[100] jdata[0] name[30] address[30] tel[20] age

jdata[99 ] name[30] address[30] tel[20] age

(3)構造体配列の参照

プログラム中で構造体配列中のメンバーを参照する場合には次のように指定します 構造体名[要素番号]メンバー名

したがって10件目の人の「名前」を参照したいときには次のように指定します

jdata[10]name

[プログラム例]

名前住所電話番号年齢を定義しそれを印字します include ltstdiohgt include ltstringhgt main() struct jusho char name[30] char address[30] char tel[20] int age jdata[100] strcpy( jdata[10]name 東海 太郎) strcpy( jdata[10]address 平塚市北金目1117)

strcpy( jdata[10]tel 0463-58-1211) jdata[10]age = 30 printf(yenn氏名 = syenn jdata[10]name) printf(yenn住所 = syenn jdata[10]address) printf(yenn電話番号= syenn jdata[10]tel) printf(yenn年齢 = dyenn jdata[10]age)

26

(4) 構造体のポインタ 変数と同じように構造体へのポインタも定義することができます

変数へのポインタ例 構造体へのポインタ例 またポインタを使用して構造体メンバーを参照するには次のように -> 記号を使って指

定します ポインタ変数名 -> メンバー名

[プログラム例]

名前住所電話番号年齢を定義しそれを印字します include ltstdiohgt include ltstringhgt main() struct jusho char name[30] char address[30] char tel[20] int age jdatakp kp = ampjdata strcpy( kp-gtname 東海 太郎)

strcpy( kp-gtaddress 平塚市北金目1117)

strcpy( kp-gttel 0463-58-1211) kp-gtage = 30 printf(yenn氏名 = syenn kp-gtname) printf(yenn住所 = syenn kp-gtaddress) printf(yenn電話番号= syenn kp-gttel) printf(yenn年齢 = dyenn kp-gtage)

kp jdata

name[30] ポインタ型の変数 address[30]

tel[20]

構造体へのポインタを記憶 age

することができます

int a int b b = ampa

struct name jname struct name np np = ampname

27

7-2 共用体 共用体は構造体と同じようにして宣言しますが共用体は複数のデータ型を同一のアドレスに

割り当てる方法です union 共用体タグ名 共用体メンバーの並び

「union」は共用体を表すキーワードです 「共用体タグ名」は共用体の型枠の名前を宣言しますここは自由に名前を定義することがで

きます 「共用体メンバーの並び」は共用体の要素です複数指定できます

共用体の宣言の例を次に示します

union c_tag int a char b

共用体 cは次のように共用体タグ c_tagの形式で領域を確保します共用体はメモリ上に領域を確保するときは ab ともに同じ領域に割り付けられます これはab という2つのデータが同時に存在するわけではなく cを異なるデータ abで共有す

ることを表しています c a b

上記の宣言だけでは共用体の形式を宣言しているだけでメモリ中で実際の領域を確保して

いるわけではありません実際に領域を確保するためには次のように定義します union 構造体タグ名 構造体名

したがって共用体名を c とすると次のように指定します

union c_tag c

(1)共用体の参照

プログラム中で共用体中のメンバーを参照する場合には次のように指定します 共用体名メンバー名

したがって「a」または「b」を参照したいときには次のように指定します

ca (int 型) cb (char 型)

メンバー参照方法によって int型として使ったりchar型として利用することができます

28

[プログラム例]

includeltstdiohgt main() union data char a short b int c chk chkc = 0x12345678 printf( char a xyennchka) printf( short b xyennchkb) printf( int c xyennchkc)

chkb(int 型) chkb(short 型) chka(char 型) 12 12 12 34 34 56 78

29

第8章 アルゴリズム コンピュータに何か仕事をさせようとするときは仕事を具体的に実行するための処理や動作

の手順が必要ですこの「手順」がアルゴリズムです アルゴリズムを考えるときは解くべき問題をはっきりと定義することが必要です

8-1 ソート ソートとは与えられたデータを小さい順または大きい順に並べ換えることですソート方法は

いくつかありますが基本的な方法でソートするアルゴリズムを紹介します

includeltstdiohgt int data[10] main()

int data_in() sort() data_in() sort() int data_in() データ入力関数

int a printf(数値入力yenn)

for(a=0alt=9a++) printf( [d]a+1) scanf(dampdata[a]) int sort() ソート処理を行う関数

int cont1cont2tmp1tmp2mim for(cont1=0 cont1lt=9 cont1++) mim=data[cont1] tmp1=cont1 for(cont2=cont1+1 cont2lt=9 cont2++) if(data[cont2] lt mim) mim=data[cont2] tmp1=cont2 tmp2 = data[cont1] data[cont1] = data[tmp1] data[tmp1] = tmp2 printf(結果 yenn)

for (cont1 = 0 cont1 lt= 9 cont1++) printf(d yenn data[cont1])

30

第9章 プリプロセッサ C言語にはプログラムの中でコンパイルについての指示を行う「プリプロセッサ」という機能が

ありますまたプリプロセッサとはコンパイルする前に実行されるためその意味のとおり「前処理」 と呼ばれていますここでは代表的なものをいくつか説明します

9-1 ファイルの挿入 ソースプログラム中に指定されたファイルを挿入します

include ltstdiohgt helliphellip 標準ディレクトリを探します include progh helliphellip 現在のディレクトリを探しなければ標準ディレクトリを探します

includeltstdiohgt によって組み込まれた define EOF (-1) define EOF (-1) define define helliphelliphelliphellip 組み込み helliphelliphelliphellip

main() stdiohファイル

int helliphelliphelliphellip helliphelliphelliphellip

ソースファイル

9-2 文字の置換 プログラム中に使われている文字列を別の文字列に置き換えます

include ltstdiohgt define TRUE 1 define EOF (-1) main() define helliphellip helliphellip

while(TRUE) define TRUE 1 置き換え main() helliphellip helliphellip while(1)

break helliphelliphellip

31

9-3 条件によるコンパイル 識別子が定義されているか否かを判断しコンパイルする範囲を指定します

include ltstdiohgt define UNIX main() ifdef UNIX printf( UNIX yenn) else printf(MS-DOSyenn) endif

include ltstdiohgt define OS UNIX main() if OS == UNIX printf( UNIX yenn) else printf(MS-DOSyenn) endif

32

付 録 1 puts()gets()関数について

行単位に入出力を行う場合には puts() gets() 関数を用います

puts() 標準出力に文字列を出力します

include ltstdiohgt int puts( char s ) puts() は NULL で終る文字列 s を標準出力に出力し最後に改行文字 yenn も出力しま

gets() 標準入力から文字列を入力します

include ltstdiohgt char gets( char s ) 戻り値正常に入力した場合には引数 s の値が返されますエラーやEOFになった場合に

は NULL が返されます gets() は標準入力から復帰文字で終る文字列を入力しs に格納しますこのとき最後の復

帰文字は NULL文字に変更されます

入力行の出力 標準入力から gets() で入力したデータには改行コードは含まれませんまた標準出力へ

puts() で出力を行う場合には必ず改行コードが付加されますgets() を実行したときの戻り値としてファイルの終端を検出した場合には EOF ではなく NULL が返されますので注意して下さい

include ltstdiohgt main() char data[80] while( gets( data ) = NULL )puts( data )

putchar()getchar()関数について putchar() 標準出力に文字を出力します

include ltstdiohgt int putchar(int c ) 戻り値正常に出力できた場合には文字cをエラーの場合にはEOFを返します

33

getchar() 標準入力から文字を入力します

include ltstdiohgt int getchar(void) 戻り値正常に入力した場合には読み込んだ文字を int 型に変換して返しますまたファイ

ルエンドエラーの場合にはEOFを返します

標準入力標準出力

標準入力標準出力はプログラムが開始されるときにはオープンされていますそれぞれのフ

ァイルポインタは stdin stdout になっていますfopen() fclose() をせずとも使用することができます

scanf() 標準出力ストリームからテキストを読み込み解釈します include ltstdiohgt int scanf( const char format [ address ] ) 戻り値正しくスキャンし変換し格納した入力フィールドの数を返しますファイルエンドを読

み込んだ場合は戻り値は EOF となります値を格納したフィールドがなかった場合は戻り値は0となります

一連の入力フィールドをスキャンして1度に1文字ずつストリーム stdin から文字を読み込み

ます次に引き数 format によって指される書式文字列中の書式指定に従って各フィールドを書式化します最後にformat の後に続く各引き数が示しているアドレスに書式化した入力を格納していきます書式文字列中の書式指定の個数はその後に続くアドレスの数と同じでな

ければなりません 書式指定[入力幅][型指定文字] 入力幅 読むべき文字数の最大値 型指定文字 次のとおりです 型指定文字 期待される入力 引き数の型 d 10進整数 int へのポインタ( int arg ) x 16進整数 int へのポインタ( int arg ) f 浮動小数点数 float へのポインタ( float arg ) s 文字列 文字配列へのポインタ( char arg[] ) c 文字 文字へのポインタ( char arg )

printf() フォーマットを指定してテキスト標準出力ストリームに出力します include ltstdiohgt int printf( const char format [ argument ] ) 戻り値出力したバイト数を返しますエラーの場合は EOF を返します

34

format によって指される書式文字列中の書式指定をformat の後に続く各引き数に適用し

書式化されたデータを stdout に出力します書式指定は後に続く引き数と同じ数だけなければなりません

書式指定[印字幅][精度][型指定文字] 印字幅 印字する最小文字数 精度 印字する最大文字数 型指定文字 つぎのとおりです 型指定文字 入力引き数 出力の書式 d 整数 符号付き10進整数 x 整数 符号無し16進整数 f 浮動小数点 符号付きの dddddddd形式の値 c 文字 1個の文字 s 文字列ポインタ ヌル文字に出会うか精度に達するまで 文字をプリントする

fopen()fclose()関数について fopen() ファイルをオープンします

include ltstdiohgt FILE fopen( char filename char mode ) 戻り値正常にファイルのオープンができたらファイルポインタを返しますエラーがあった場

合には NULLを返します 文字列 filename で指定されたファイルをオープンしますオープン後の入出力のモードに

ついては文字列 mode で指定しますmode に指定できる文字は以下のとおりです r 入力モードでオープンします w 出力モードでオープンします a 存在するファイルに追加して出力するモードでオープンします r+ 既に作成してあるファイルを更新(入力出力)するモードでオープンします w+ 新しく作成するファイルを更新モードでオープンします a+ 既に作成してあるファイルの終りから更新用に作成します

以上の文字に b をつけ加えることによりバイナリモードで入出力することができるようになり

ます rb バイナリの入力モードでオープンします wb バイナリの出力モードでオープンします ab 存在するファイルに追加して出力するモード(バイナリ)でオープンします

fclose() 既にオープンしてあるファイルをクローズします include ltstdiohgt fclose( FILE fp ) 既にオープンしているファイルをクローズしますパラメータには fopen() 関数により返された

ファイルポインタを指定します

35

テキストモードとバイナリモード 行の最後はテキストモードの場合改行コードのみとなりバイナリモードの場合には復帰

コードと改行コードの組合わせになります行の最後としてテキストファイルには復帰コード改行

コードが書かれていますがテキストモードでオープンした場合には入力すると改行コードのみに

変換されて入力されますバイナリモードの場合には復帰コード改行コードがそれぞれ入力され

ます

fputs()fgets()関数について fputs() ファイルポインタで指定されるファイルに文字列を出力します

include ltstdiohgt

int fputs( char s FILE fp ) fputs() は NULL で終る文字列 s をファイルポインタに示されるファイルへ出力しますputs()

と違い最後に改行文字 yenn を出力することはありません

fgets() ファイルポインタで指定されるファイルから文字列を入力します include ltstdiohgt char fgets( char s int n FILE fp ) 戻り値正常に入力した場合には引数 s の値が返されますエラーやEOFになった場合に

は NULL が返されます fgets() はファイルポインタで指定されるファイルから ( n - 1 ) 文字または改行文字までの

文字列を入力しs に格納しますgets() と異なり最後に入力された改行文字は NULL 文字に変更されません

標準入力から入力しファイルへ出力する ファイルへ出力あるいは入力を行う場合には改行コードの変換(入力の場合の削除出力の

場合の付加)はされませんしたがって標準入力から入力しファイルへ出力する場合には改行

コードを付加しなければなりません include ltstdiohgt main() char data[80] FILE fp fp = fopen( data w ) while( gets( data ) = NULL ) strcat( data yenn ) 改行コードの付加

fputs( data fp ) fclose( fp )

36

fputc()fgetc()関数について fputc() ファイルポインタで指定されるファイルに1文字出力します

include ltstdiohgt int fputc( int c FILE fp ) 戻り値正常に出力できた場合には文字 c を返しエラーの場合には EOF を返します fputc() は文字 c をファイルポインタで示されるファイルへ出力します

fgetc() ファイルポインタで指定されるファイルから1文字入力します

include ltstdiohgt int fgetc( FILE fp ) 戻り値正常に入力した場合には入力した文字を返しますエラーやEOFになった場合には

EOF が返されます fgetc() はファイルポインタで指定されるファイルから文字を入力します

ファイルの内容の表示 include ltstdiohgt main() FILE fp int ch char fname[30] printf( Key in Fila name gt ) gets( fname ) fp = fopen( fname r ) while( ( ch = fgetc( fp ) ) = EOF )putchar( ch ) fclose( fp )

その他テキスト中で使用された関数について sin() 三角関数の正弦を計算します

include ltmathhgt double sin(double radian) sinはラジアンを単位とする引数 radianの三角関数を計算します

37

strcpy() 文字列を他の文字列へコピーします

include ltstringhgt char strcpy(char string1const char string2) strcpyは引数 string2の指す文字列を null文字まで含めて引数 string1の指す領域にコピ

ーする strcpyは string1を返します

strcat() ある文字列を他の文字列に加えます

include ltstringhgt char strcat( char dest const char src ) 戻り値連結された文字列へのポインタを返します strcat() はsrc のコピーを dest の最後につけ加えます得られる文字列の長さは

strlen(dest)+strlen(src) になります

fabs() 絶対値の計算をします include ltmathhgt double fabs(double z) fabsは倍精度浮動小数の絶対値を計算して返しますつまりzgt=0であれば z をzlt0であ

れば-zを返します exp() 指数関数を計算します

include ltmathhgt double exp(double z) exp は引数zの指数関数つまりezを返すここではeは自然対数の底を表します対数関

数logの逆関数です

38

付 録 2 コンパイルの方法には大きく分けて第4章の実習で学んだようにデータファイルを作成してお

き ccg でコンパイルさせる方法と実行中に対話型でデータを入力していく方法があります ここでは対話型で実行を進めていく方法を紹介します ただしこの方法は計算(cpu)時間が10秒以内のものに限ります10秒を超える計算(cpu)時

間を要する場合はccg でコンパイルをするようにしてください 第4章実習の(2)(p16)までは同様です

コンパイル

コンピュータに処理を依頼します 60us1234boseicc cc rensyuc

所有するファイルの一覧を見てみます

60us1234boseicc ls -l larr 持っているファイルの一覧を見るコマンドです

-rw-r--r-- 1 60us1234 other 128 4月26日 15時14分 rensyuc -rwxr-xr-x 1 60us1234 other 361 4月26日 15時16分 aout

aout という実行形式のファイルが作成されています

実行

60us1234boseicc aout12 35[リターン] データを入力

1 200000 3500000 4200000 実行結果の出力

60us1234boseicc

注意

aout ファイルは印刷することができません実行結果を印刷する場合にはファイルに落とし てから出力するようにしましょう

60us1234boseicc aout gt kekka12 35[リターン] データを入力

60us1234boseicc more kekka 計算結果の確認 60us1234boseicc lpr kekka 計算結果の印刷

39

Page 9: n 第1章 章立ての部分は、書式(PC入門大見出し)を …第2章 数の表現 2-1 2進数 電子計算機の動作原理は0と1で表される2進数です。また、人間が日常生活で扱っている数

第3章 関数 3-1 関数とは

Cではプログラムの単位は関数で定義されますここでいう関数とは数学などで使われる

sincos 関数と同様の概念でありある値を与えると何らかの処理を行いその結果が関数値となるものですもちろんmain() も一つの関数ですその他にも自由に関数を作ることができます

例えば関数

f(x)=4x2+2x+5 を計算するときには次のようにプログラムを分けることができます データxを入力して関数f(x)を呼び出しその結果を印刷するプログラム 関数f(x)を計算するプログラム これをプログラムで表すと次のようになります

include ltstdiohgt main() float x y f() 変数と関数の型の宣言

while( scanf( f ampx ) = EOF ) y = f( x ) 関数の引用

printf( yenn x=f f(x)=f x y ) float f( float x ) 関数の定義

float y y = 40 x x + 20 x + 50 return y 計算を終了し結果を戻します

関数 f(x)は与えられたxの値によりyを計算して main()に結果を返します

3-2 関数の形式 関数を定義する場合には次の形式で定義します

型 関数名(仮引数の並び) float f ( float x )

変数の型宣言 関数内で使用する変数の宣言 プログラム プログラム }

関数の定義で型の指定がない場合にはint 型の関数となりますまた関数名は31文字以内の英数字の組み合わせです

3-3 引数

関数に渡すパラメータを引数といいますmain()関数などのように関数を引用する場合のパラメータを実引数と呼び呼ばれる関数で使用されているパラメータを仮引数と呼びます

include ltstdiohgt

7

main() float x y f() 変数と関数の型の宣言

while( scanf( f ampx ) = EOF ) y = f( x ) 関数の引用x は実引数と呼びます

printf( yenn x=f f(x)=f x y ) float f( float x ) 関数の定義x は仮引数と呼びます

float y y = 40 x x + 20 x + 50 return y 計算を終了し結果を戻します

[入力の終了について]

このプログラムを実行すると永遠とデータ入力を求められてしまいます終了条件が = EOF の場合はキーボードから CTRLキーを押しながら Z を入力することにより while文を抜け入力を終了することができます

複数の引数を受け渡しする場合には引用する側と関数を定義する側とで 引数の並び個数型

を合わせなければなりませんしかし変数名は同じでなくてもかまいません例えば配列 a と bを加算して配列 cに代入する場合には次のようになります

include ltstdiohgt main()

int a[10] = 18 24 56 28 96 51 82 34 65 72 UNIXの場合 static intにする int b[10] = 12 54 69 20 26 84 55 20 44 74 UNIXの場合 static intにする

int c[10] k void matadd() 関数の型宣言

matadd( a b c ) for( k = 0 k lt 10 k++ ) printf( yenn d + d = d a[k] b[k] c[k] ) void matadd( int x[] int y[] int z[] ) 関数の定義

int t for( t = 0 t lt 10 t++ ) z[t] = x[t] + y[t]

演習4 平均値を求める関数average()を作成し10名の数学の得点を読み込みその平均点を求め

るプログラムを作りなさい 「入力例」 「出力例」

45 63900000 78 97

8

この他にも関数にパラメータを渡す方法としてポインタを使用する方法があります文字列を

複写する関数の場合には次のとおりになります関数名は strcopy()最初の引数には複写先の配列名(配列の先頭番地)次の引数には複写元の配列名(配列の先頭番地)です

include ltstdiohgt main() char src[] = tokai dst[80] void strcopy() strcopy( dst src ) printf( syenn dst )

void strcopy( char str1 char str2 ) while( ( str1++ = str2++ ) = yen0 )

また配列の加算を行う関数の場合にもそれぞれの配列名をパラメータとし関数側でポイン

タ型変数として受け取ることができます

include ltstdiohgt main() int a[10] = 18 24 56 28 96 51 82 34 65 72 UNIXの場合 static intにする int b[10] = 12 54 69 20 26 84 55 20 44 74 UNIXの場合 static intにする

int c[10] int k void matadd() matadd( a b c 10 ) for( k = 0 k lt 10 k++ ) printf( d + d = d yenn a[k] b[k] c[k] )

void matadd( int x int y int z int n ) for( n gt 0 n-- ) z++ = x++ + y++

main()関数では配列名(アドレス定数)として引数に指定されていますが関数 matadd()ではポインタ型の変数として使用することができますしたがって変数 xyz は値を変更することができるようになります

配列 a 変数 x

9

配列 b 変数 y 配列 c 変数 x

3-4 戻り値 関数からの戻り値はreturn 文によって返されます整数型文字型の値を返す関数の場合

にはそれぞれ次のように定義します

int sub( int x ) char sub( int x ) int y char z

return y return z

またポインタを返す関数の場合には次のように定義します

int sub( int x ) char sub( int x ) int y char z

return y return z

return文で式の指定がない場合には何も値を返しません

[プログラム例]

文字列(文字型配列)の中に指定した文字があればその位置をポインタで返し無ければ NULLポインタを返す関数を考えてみます

char strfind( char str char ch ) while( str ) if( str == ch )return str str++ return NULL

いくつかのC言語のマニュアルでは関数の説明を以下のように記述しています sin 機能 正弦を求めます 形式 include ltmathhgt double sin( double x ) このとき関数 sin() の戻り値は double 型でありまた指定する引数も double 型でなけれ

ばなりませんそれと同時にこの関数を使用する場合にはinclude ltmathhgt を指定しなければなりません

10

3-5 変数の通用範囲 関数内で宣言された変数はその関数の中でのみ使用可能です他のプログラムからは使用

することはできません

include ltstdiohgt main() int i 変数 i は関数 main() と sub() とでは それぞれ独立に使用することができます main() で変数 i に設定した値は sub() では参照することはできません sub() 逆にsub() で変数 i に設定した値も main() では参照することはできません

int i

それぞれの関数の中でのみ使用可能な変数をローカル変数と呼び他の関数でも使用可能

な変数をグローバル変数と呼びますいくつかの関数で共通に使用するような場合にはグロー

バル変数を使用します グローバル変数を定義する場合には関数の外で宣言します

include ltstdiohgt int i グローバル変数の定義

main() i = 10

sub() extern int i printf( yenn i = d i )

このプログラムではmain() 関数でグローバル変数に値を設定し関数 sub() で変数の値を

参照しています extern 宣言は変数が他のプログラム内で宣言されていることを示しています宣言の形式

は以下のとおりです extern 型 変数並び

演習5 入力された任意の数の倍数を求めるプログラムを作成しなさい入力する数値は2つ倍数 を求めるための任意の数と倍数の上限値ですここでいう上限値とは任意の数の倍数をどの くらいの数まで求めるかということです

11

3-6 動的変数と静的変数 通常Cで使用される変数はその関数の中だけでのみ使用できる変数ですしたがって関数

が実行するときに関数の中で使用する変数の領域を確保し関数の実行が終るときにその領域

を解放するようにしてメモリを効率的に利用していますこのように関数が実行されるときに確

保される変数を動的変数(auto変数 )と呼びます プログラムの中ではその他に常に存在し使用できる変数を定義することができますそのよ

うな変数は静的変数(static変数 )と呼ばれます

func() int a b static int x y

また static 変数には内部的なリンケージの指定の意味もありますつまり関数の外で変数

を宣言すると自動的にグローバル変数となり他のプログラムからも使用することができるようにな

ります ファイル a ファイル b このような場合にはコンパイル単位が異なっていてもextern 宣言を行うことにより変数 abc

を使用することができますところが関数の外で static 宣言をして定義した変数についてはコンパイル単位が違うプログラムからは使用することができなくなります ファイル a ファイル b 同一コンパイル単位(ファイル)に存在する関数 sub()と subd()では変数 abcを使用することが

できますがコンパイル単位(ファイル)が異なる関数 func()では変数 abcを使用することはできません

int abc sub() abc = 10

func() extern int abc printf( ldquo abc =dyennrdquo abc )

static int abc sub() abc = 10 subd() abc++

func() extern int abc printf( ldquo abc =dyennrdquo abc )

12

3-7 スタック プログラム中にはプログラム領域データ領域の他にスタック領域があり一時的な作業領域と

して使用されています関数間での引数の受渡しの時にもこの領域を使用しますスタック領域に

データを格納することを「スタックに積む」ともいいます基本的にはスタック領域に格納されたデ

ータは最後に格納されたデータから順に取り出されることになります以下に格納が行われたとき

のスタックの状態を示します記号は次に格納すべき位置(スタックポインタの値)を示していま

逆にスタックからデータを取り出すときにはスタックポインタが指している位置の一つ下から取

り出すことになりますスタックからデータを取り出すときのスタックの状態は次のようになります

なり

10

20

10

30

20

10

40

30

20

10

10rarr

格納

20rarr

格納

30rarr

格納

40rarr

格納

40rarr 30rarr

関数を呼び出すときには次

逆にそれぞれの関数から

次のようになります

40

30

20

10

取出

main() z = f1( x y )

のようにパラメータがスタ

戻るときにはパラメータで

30

20

10

取出

f1( int a int b ) c = f2( d e

xの値 yの値

xの値 yの値

13

ックに格納されます

使用していたスタック領域は自動的になく

10

20

)

f2( int p int q ) r = p + q

xの値

eの値 dの値

yの値

xの値 yの値

dの値

eの値

3-8 再帰呼び出し 関数の引数の受渡しがスタックを利用して行われることから自分で自分自身の関数を呼び出

すことができます 以下のプログラムは入力した値の階乗を計算するプログラムです

3の階乗を求めることを考えてみます

return 文によって戻るときは次のようにして値を返します kai( 3 ) 3 kai( 3-1 ) 2 kai( 2-1 ) return 1

6 3 (2 1) 2 1 以上の計算から3=6が導き出されます 再帰呼び出しのことをリカーシブコールともいいます

include ltstdiohgt main() int n m kai() scanf( ldquodrdquoampn ) m = kai( n ) printf( ldquod = dyennrdquo n m )

int kai( int k ) if( k == 1 )return 1 else return k kai( k ndash 1 )

kai( 1 )

darr

return 1

kai( 2 )

darr

2 kai( 2-1 )

kai( 3 )

darr

3 kai( 3-1 )

main()

darr

kai( 3 )

3

2

1

2

3

1

2

3 3

32

32

1

2

1

3

3

演習6 1からnまでの総和を再帰呼び出しを使って計算する関数 sowa() を作りなさい n+(n-1)+ +2+1

14

第4章 実習 この章ではプログラムを実際に入力して実行するまでの手順を実習します

4-1 操作手順 (1)ログイン

[スタート]rarr[プログラム(P)]rarr[ネットワーク] Hostの欄に bosei を記述選択 rarr [Telnet(FreeWare)] を選択します して 「OK」 ボタンをクリックします

UP-UXV (Rel42MP) (bosei) (pts41) login 60us1234 larr 各自のログイン名を入力します Password larr パスワードを入力しても画面は何も変化しません 101 60us1234bosei larr セッションが開設されましたこれをプロンプトといいます この状態でコマンドを入力することができます

(2)プログラムの作成 以下のコマンドを入力しテキストエディタを起動します 60us1234boseicc ng rensyuc

すると下図のようにngエディタの画面になります

15

次のように入力します入力ミスの修正はBSキーで行ないます

include ltstdiohgt main() float abc scanf(f f ampaampb) c=ab printf(f f f yenn abc)

CTRL キーを押しながら XCTRL キーを押しながら C を押しますすると次のメッセージが画面下に表示されます

Save file uhomea60us1234rensyuc (y or n)

このメッセージに対して y と答えます

(3)データの作成 以下のコマンドを入力しテキストエディタを起動します 60us1234boseicc ng rensyud

ngエディタの画面になりますので次のように入力します 12 35

CTRLキーを押しながら XCTRLキーを押しながら C を押します save file uhomea60us1234rensyud (y or n)

このメッセージに対して y と答えます

(4)コンパイルと実行 コンピュータに処理を依頼します 60us1234boseicc ccg rensyu

ジョブを投入しましたジョブの状態を見るコマンドは myjobです

16

130 60us1234boseicc myjob ================================================= NQS (R0220) BATCH REQUEST HOST bosei ================================================= REQUEST ID NAME OWNER QUEUE PRI NICE STT PGRP R --------------- -------- -------- -------- ---- --- --- ------ - 99321bosei STDIN 60us1234 A 31 0 RUN 14161 - ---------------------------------------------------------------- ================================================== NQS (R0220) DEVICE REQUEST HOST bosei ジョブは実行中です

================================================== REQUEST ID NAME OWNER QUEUE PRI SIZE STT -------------------------------------------------------------

所有するファイルの一覧を見てみます

60us1234boseicc ls -l larr 持っているファイルの一覧を見るコマンドです

-rw-r--r-- 1 60us1234 other 4 4月26日 15時14分 rensyud -rw-r--r-- 1 60us1234 other 128 4月26日 15時10分 rensyuc -rwxr-xr-x 1 60us1234 other 361 4月26日 15時16分 rensyul

(5)計算結果の確認

計算結果を画面に表示して確認します 60us1234boseicc more rensyul

(6)印刷

計算結果の印刷を行ないます5号館2階のカフェテリア室にある bosei のプリンタに印刷 されます

60us1234boseicc lpr rensyul

(7)ログアウト セッションを終了します 60us1234boseicc logout

(8)実行の流れ

エラー

プログラムの作成 ログイン コンパイル実行

確 認 印 刷 ログアウト

17

第5章 配列 多数の変数をまとめて宣言する方法として配列があります配列の一つ一つは配列要素と呼

ばれ変数と同じ性格を持っています配列の宣言は型宣言と同時に次のように行います int a[5] 配列 a

a[0]

a[1]

a[2]

a[3]

a[4]

二次元配列(一次元配列を複数集めたもの)を宣言する場合には次のようになります int b[3][4] 配列 b

b[0][0] b[0][1] b[0][2] b[0][3]

b[1][0] b[1][1] b[1][2] b[1][3]

b[2][0] b[2][1] b[2][2] b[2][3]

配列要素に数値を代入する場合は次のようになります b[1][2]=10

5-1 二次元配列要素の初期化 変数の型宣言と同じように配列を宣言するときに初期値も同時に設定することができます

複数のデータがある場合には{}記号でくくって指定します int b[3][4] = 2 4 6 8 1 3 5 7 1 2 3 4

文字型配列の場合には以下のようになりますyen0 は文字列の終わりを表わします char univ[3][7] = T O K A I yen0 S I M I Z U yen0 Y O Y O G I yen0

また文字列定数として初期化することもできますこの場合コンパイル時に自動的に yen0 が付加されます

char univ[3][7] = TOKAI SIMIZU YOYOGI

18

[プログラム例] 二次元配列のタテヨコを加算するプログラム

include ltstdiohgt main() int mat[4][3]=123456789101112 int ijytotalttotal[3]total=0 for(j=0jlt3j++)ttotal[j]=0 for (i=0ilt4i++) ytotal=0 for(j=0jlt3j++) ytotal += mat[i][j] ttotal[j] += mat[i][j] total += mat[i][j] printf(3dmat[i][j]) printf( 3dyennytotal) printf(yenn) for(j=0jlt3j++)printf(3dttotal[j]) printf( 3dyenntotal)

[実行結果]

1 2 3 6 4 5 6 15 7 8 9 24 10 11 12 33 22 26 30 78

演習7

a)以下の配列はどのように初期化されるか答えなさい char errmsg[2][15] = Divide Error Overflow Error

b)九九の計算を2次元配列を使って求めなさい

19

第6章 ポインタ型変数 C言語では値を記憶するための変数だけではなく変数または定数の番地を記憶するため

のポインタ型変数を宣言することができますポインタとはデータ項目の一種で「記憶装置(メモ

リ)上の格納番地(アドレス)を指すデータ項目」です アドレス コンピュータの中ではデータ項目の格納番地のことをアドレス(住所)と呼びます 例えば記憶装置という名前のとてつもなく大きなマンションがあるとしますその中から Aさんを捜すときは部屋番号を参照しますマンションでは部屋番号で住居人を参照し ているのと同じようにコンピュータでは記憶装置上に確保された変数は格納番地 (アドレス)で管理されています

マンション 部屋番号 記憶装置 格納番地

Aさん Int a Bさん Cさん AAAさん BBBさん CCCさん

1号室

2号室

3号室

100号室

200号室

300号室

100番地

200番地

300番地

1000番地

2000番地

3000番地

Int b Int c float aaafloat bbbfloat ccc

ポインタ ポインタとは「指し示すもの」の意ですがC言語では記憶装置上のアドレスを指し示す もののことです上のマンションの例では部屋番号を格納するデータ項目ということに なりますAAAさんは100号室に住んでいます100という値をポインタのデータ項目に 記憶するとそのデータ項目は間接的にAAAさんを指すことになります

6-1 ポインタ型変数の宣言および参照 通常の変数と区別するために型宣言時に変数名の前に記号を付けて宣言します int a 整数型ポインタ変数 int b 整数型変数

変数 a は整数型の値を記憶するのではなく整数型の値を持つ変数などの番地を記憶する変数ですまた変数 b は通常の整数型の値を記憶するための変数です

20

include ltstdiohgt main() int a b c a はポインタ型の変数b c は整数型の変数 b = 12 変数 b に値 12 を代入します a = ampb 変数 a には変数 b の番地が代入されます c = a + 10 変数 a の指す変数(b)の内容と10の加算です つまり12 + 10 を変数 c に代入します

変数の型宣言において変数名に記号を付けることによりその変数はポインタ型の変数と

なりますポインタ型の変数は変数名のみを指定した場合には単にその変数の値(通常はメモリ

の番地)を表します変数名に記号を付けて使用した場合にはその変数が指し示している変

数の内容を表します c = a ポインタ型変数 a が指している値を変数 c に代入

ポインタ型の変数に番地を記憶させるためにはプログラム例のように変数名の前に記号を

指定します変数名 によって変数の番地(アドレス)を表します a = ampb 変数 b の番地をポインタ型変数 a に代入します

ポインタ型変数の型はポインタ型変数が指し示す先の変数の型を表しています int a 変数 a 整数型の値 float x 変数 x 実数型の値 char c 変数 c 文字型の値

6-2 ポインタ型変数の初期化 ポインタ型変数も型宣言のときに変数を初期化することができます特に文字型のポインタ変

数の場合によく使います char str = TOKAI University

ポインタ型変数 str は文字列定数 TOKAI University の最初の文字が格納されている番地を初期値として持つことになります

変数 str TOKAI University 文字列定数

[プログラム例]

(1)文字型配列 putchar() 関数を使って一次元の文字型配列を出力します include ltstdiohgt main() char str[6] = TOKAI int i for( i = 0 str[i] = yen0 i++ ) putchar( str[i] )

21

ポインタを使用した場合には以下のようになります include ltstdiohgt main() char str[6] = TOKAI char chp for( chp = str chp = yen0 chp++ ) putchar( chp )

chp str T [0] O K A I yen0 [5]

参照する変数 配列の表現 ポインタの表現 実際のアドレス 1番目の数 str[0] chp CHP 2番目の数 str[1] (chp+1) CHP+1 n番目の数 str[n-1] (chp+n-1) CHP+n-1 6番目の数 str[5] (chp+5) CHP+5

注意実際のアドレス CHPは実行時に決定されます

(2)二次元文字型配列 二次元の文字型配列に定数を設定しそれを出力するプログラムです文字型配列を使用す

ると次のとおりになります include ltstdiohgt main() char str[5][40] = TOKAI shounan campus NEC DEC int i for( i = 0 i lt 5 i++ ) printf( yenns str[i] )

40 バイト str TOKAI shounan campus NEC DEC

22

ポインタ型配列を使用すると次のとおりになります include ltstdiohgt main() char str[6] = TOKAI shounan campus NEC DEC NULL char chp for( chp = str chp = NULL chp++ ) printf( yenns chp ) str

chp 番地 TOKAI 番地 shounan 番地 campus 番地 NEC 番地 DEC

NULL

演習8 キーボードまたはデータファイルから読み込んだ文字列中にrsquoArsquo があったら rsquoarsquo に変換 するプログラムを配列とポインタを使って書きなさい

23

第7章 構造体共用体 7-1 構造体

プログラムの規模が大きくなるにつれて多数の intや floatcharなどのデータ型を扱うようになり複雑になってきますそこで多数のデータを1つにまとめて簡単に扱える機能が構造体です 構造体について住所録のデータを例にあげて考えてみます

住所録の個人データとして氏名住所電話番号年齢の項目を一つのデータとします これをC言語で変数の定義をすると次のようになります 氏名東海太郎 char name[30] 住所平塚市北金目1117 char address[30] 電話番号0463-58-1211 char tel[20] 年齢30 int age 個人の住所録データ C言語での表現 このような住所録の個人データを1つにまとめて新しいデータとして定義する機能を構造体と言

います struct 構造体タグ名 構造体メンバーの並び

「struct」は構造体を表すキーワードです 「構造体タグ名」は構造体の型枠を宣言しますここは自由に名前を定義することができ ます 「構造体メンバーの並び」は構造体の要素です複数指定できます

個人の住所録のデータを構造体で宣言すると次のようになります

struct jusho char name[30] char address[30] 構造体のメンバーの並び char tel[20] (複数可)

int age

上記の宣言では構造体の形式を宣言しているだけでメモリ中で実際の領域を確保している

わけではありません実際に領域を確保するためには次のように定義します

struct 構造体タグ名 構造体名

したがって構造体名を jdata とすると次のように指定します

struct jusho jdata

構造体 jdataは次のように構造体タグ jushoの形式で領域を確保します

24

Jdata name[30]

address[30] tel[20] age

(1)構造体の参照

プログラム中で構造体中のメンバーを参照する場合には次のように指定します 構造体名メンバー名

したがって「名前」を参照したいときには次のように指定します

jdataname

[プログラム例]

名前住所電話番号年齢を定義しそれを印字します include ltstdiohgt include ltstringhgt main() struct jusho char name[30] char address[30] char tel[20] int age struct jusho jdata strcpy( jdataname 東海 太郎) strcpy( jdataaddress 平塚市北金目1117)

strcpy( jdatatel 0463-58-1211) jdataage = 30 printf(yenn氏名 = syenn jdataname) printf(yenn住所 = syenn jdataaddress) printf(yenn電話番号= syenn jdatatel) printf(yenn年齢 = dyenn jdataage)

また構造体の形式の定義と領域の確保は次のように同時におこなうことができます

struct 構造体タグ名 構造体メンバーの並び 構造体名

struct jusho struct jusho char name[30] char name[30] char address[30] char address[30] char tel[30] = char tel[30] int age 同じ int age

jdata struct jusho jdata

型宣言と同時にメモリ上に領域を確保する方法 後からメモリ上に領域を確保する方法

25

(2) 構造体配列 住所録データの場合その中に入るデータは1件ではありませんやはり100件200件のデ

ータが必要になる場合がありますこのように個人単位のデータを多数扱う場合には構造体を配

列として宣言することができます 次の例は個人のデータを100個用意するために構造体を配列として宣言しています struct jusho jdata[100] jdata[0] name[30] address[30] tel[20] age

jdata[99 ] name[30] address[30] tel[20] age

(3)構造体配列の参照

プログラム中で構造体配列中のメンバーを参照する場合には次のように指定します 構造体名[要素番号]メンバー名

したがって10件目の人の「名前」を参照したいときには次のように指定します

jdata[10]name

[プログラム例]

名前住所電話番号年齢を定義しそれを印字します include ltstdiohgt include ltstringhgt main() struct jusho char name[30] char address[30] char tel[20] int age jdata[100] strcpy( jdata[10]name 東海 太郎) strcpy( jdata[10]address 平塚市北金目1117)

strcpy( jdata[10]tel 0463-58-1211) jdata[10]age = 30 printf(yenn氏名 = syenn jdata[10]name) printf(yenn住所 = syenn jdata[10]address) printf(yenn電話番号= syenn jdata[10]tel) printf(yenn年齢 = dyenn jdata[10]age)

26

(4) 構造体のポインタ 変数と同じように構造体へのポインタも定義することができます

変数へのポインタ例 構造体へのポインタ例 またポインタを使用して構造体メンバーを参照するには次のように -> 記号を使って指

定します ポインタ変数名 -> メンバー名

[プログラム例]

名前住所電話番号年齢を定義しそれを印字します include ltstdiohgt include ltstringhgt main() struct jusho char name[30] char address[30] char tel[20] int age jdatakp kp = ampjdata strcpy( kp-gtname 東海 太郎)

strcpy( kp-gtaddress 平塚市北金目1117)

strcpy( kp-gttel 0463-58-1211) kp-gtage = 30 printf(yenn氏名 = syenn kp-gtname) printf(yenn住所 = syenn kp-gtaddress) printf(yenn電話番号= syenn kp-gttel) printf(yenn年齢 = dyenn kp-gtage)

kp jdata

name[30] ポインタ型の変数 address[30]

tel[20]

構造体へのポインタを記憶 age

することができます

int a int b b = ampa

struct name jname struct name np np = ampname

27

7-2 共用体 共用体は構造体と同じようにして宣言しますが共用体は複数のデータ型を同一のアドレスに

割り当てる方法です union 共用体タグ名 共用体メンバーの並び

「union」は共用体を表すキーワードです 「共用体タグ名」は共用体の型枠の名前を宣言しますここは自由に名前を定義することがで

きます 「共用体メンバーの並び」は共用体の要素です複数指定できます

共用体の宣言の例を次に示します

union c_tag int a char b

共用体 cは次のように共用体タグ c_tagの形式で領域を確保します共用体はメモリ上に領域を確保するときは ab ともに同じ領域に割り付けられます これはab という2つのデータが同時に存在するわけではなく cを異なるデータ abで共有す

ることを表しています c a b

上記の宣言だけでは共用体の形式を宣言しているだけでメモリ中で実際の領域を確保して

いるわけではありません実際に領域を確保するためには次のように定義します union 構造体タグ名 構造体名

したがって共用体名を c とすると次のように指定します

union c_tag c

(1)共用体の参照

プログラム中で共用体中のメンバーを参照する場合には次のように指定します 共用体名メンバー名

したがって「a」または「b」を参照したいときには次のように指定します

ca (int 型) cb (char 型)

メンバー参照方法によって int型として使ったりchar型として利用することができます

28

[プログラム例]

includeltstdiohgt main() union data char a short b int c chk chkc = 0x12345678 printf( char a xyennchka) printf( short b xyennchkb) printf( int c xyennchkc)

chkb(int 型) chkb(short 型) chka(char 型) 12 12 12 34 34 56 78

29

第8章 アルゴリズム コンピュータに何か仕事をさせようとするときは仕事を具体的に実行するための処理や動作

の手順が必要ですこの「手順」がアルゴリズムです アルゴリズムを考えるときは解くべき問題をはっきりと定義することが必要です

8-1 ソート ソートとは与えられたデータを小さい順または大きい順に並べ換えることですソート方法は

いくつかありますが基本的な方法でソートするアルゴリズムを紹介します

includeltstdiohgt int data[10] main()

int data_in() sort() data_in() sort() int data_in() データ入力関数

int a printf(数値入力yenn)

for(a=0alt=9a++) printf( [d]a+1) scanf(dampdata[a]) int sort() ソート処理を行う関数

int cont1cont2tmp1tmp2mim for(cont1=0 cont1lt=9 cont1++) mim=data[cont1] tmp1=cont1 for(cont2=cont1+1 cont2lt=9 cont2++) if(data[cont2] lt mim) mim=data[cont2] tmp1=cont2 tmp2 = data[cont1] data[cont1] = data[tmp1] data[tmp1] = tmp2 printf(結果 yenn)

for (cont1 = 0 cont1 lt= 9 cont1++) printf(d yenn data[cont1])

30

第9章 プリプロセッサ C言語にはプログラムの中でコンパイルについての指示を行う「プリプロセッサ」という機能が

ありますまたプリプロセッサとはコンパイルする前に実行されるためその意味のとおり「前処理」 と呼ばれていますここでは代表的なものをいくつか説明します

9-1 ファイルの挿入 ソースプログラム中に指定されたファイルを挿入します

include ltstdiohgt helliphellip 標準ディレクトリを探します include progh helliphellip 現在のディレクトリを探しなければ標準ディレクトリを探します

includeltstdiohgt によって組み込まれた define EOF (-1) define EOF (-1) define define helliphelliphelliphellip 組み込み helliphelliphelliphellip

main() stdiohファイル

int helliphelliphelliphellip helliphelliphelliphellip

ソースファイル

9-2 文字の置換 プログラム中に使われている文字列を別の文字列に置き換えます

include ltstdiohgt define TRUE 1 define EOF (-1) main() define helliphellip helliphellip

while(TRUE) define TRUE 1 置き換え main() helliphellip helliphellip while(1)

break helliphelliphellip

31

9-3 条件によるコンパイル 識別子が定義されているか否かを判断しコンパイルする範囲を指定します

include ltstdiohgt define UNIX main() ifdef UNIX printf( UNIX yenn) else printf(MS-DOSyenn) endif

include ltstdiohgt define OS UNIX main() if OS == UNIX printf( UNIX yenn) else printf(MS-DOSyenn) endif

32

付 録 1 puts()gets()関数について

行単位に入出力を行う場合には puts() gets() 関数を用います

puts() 標準出力に文字列を出力します

include ltstdiohgt int puts( char s ) puts() は NULL で終る文字列 s を標準出力に出力し最後に改行文字 yenn も出力しま

gets() 標準入力から文字列を入力します

include ltstdiohgt char gets( char s ) 戻り値正常に入力した場合には引数 s の値が返されますエラーやEOFになった場合に

は NULL が返されます gets() は標準入力から復帰文字で終る文字列を入力しs に格納しますこのとき最後の復

帰文字は NULL文字に変更されます

入力行の出力 標準入力から gets() で入力したデータには改行コードは含まれませんまた標準出力へ

puts() で出力を行う場合には必ず改行コードが付加されますgets() を実行したときの戻り値としてファイルの終端を検出した場合には EOF ではなく NULL が返されますので注意して下さい

include ltstdiohgt main() char data[80] while( gets( data ) = NULL )puts( data )

putchar()getchar()関数について putchar() 標準出力に文字を出力します

include ltstdiohgt int putchar(int c ) 戻り値正常に出力できた場合には文字cをエラーの場合にはEOFを返します

33

getchar() 標準入力から文字を入力します

include ltstdiohgt int getchar(void) 戻り値正常に入力した場合には読み込んだ文字を int 型に変換して返しますまたファイ

ルエンドエラーの場合にはEOFを返します

標準入力標準出力

標準入力標準出力はプログラムが開始されるときにはオープンされていますそれぞれのフ

ァイルポインタは stdin stdout になっていますfopen() fclose() をせずとも使用することができます

scanf() 標準出力ストリームからテキストを読み込み解釈します include ltstdiohgt int scanf( const char format [ address ] ) 戻り値正しくスキャンし変換し格納した入力フィールドの数を返しますファイルエンドを読

み込んだ場合は戻り値は EOF となります値を格納したフィールドがなかった場合は戻り値は0となります

一連の入力フィールドをスキャンして1度に1文字ずつストリーム stdin から文字を読み込み

ます次に引き数 format によって指される書式文字列中の書式指定に従って各フィールドを書式化します最後にformat の後に続く各引き数が示しているアドレスに書式化した入力を格納していきます書式文字列中の書式指定の個数はその後に続くアドレスの数と同じでな

ければなりません 書式指定[入力幅][型指定文字] 入力幅 読むべき文字数の最大値 型指定文字 次のとおりです 型指定文字 期待される入力 引き数の型 d 10進整数 int へのポインタ( int arg ) x 16進整数 int へのポインタ( int arg ) f 浮動小数点数 float へのポインタ( float arg ) s 文字列 文字配列へのポインタ( char arg[] ) c 文字 文字へのポインタ( char arg )

printf() フォーマットを指定してテキスト標準出力ストリームに出力します include ltstdiohgt int printf( const char format [ argument ] ) 戻り値出力したバイト数を返しますエラーの場合は EOF を返します

34

format によって指される書式文字列中の書式指定をformat の後に続く各引き数に適用し

書式化されたデータを stdout に出力します書式指定は後に続く引き数と同じ数だけなければなりません

書式指定[印字幅][精度][型指定文字] 印字幅 印字する最小文字数 精度 印字する最大文字数 型指定文字 つぎのとおりです 型指定文字 入力引き数 出力の書式 d 整数 符号付き10進整数 x 整数 符号無し16進整数 f 浮動小数点 符号付きの dddddddd形式の値 c 文字 1個の文字 s 文字列ポインタ ヌル文字に出会うか精度に達するまで 文字をプリントする

fopen()fclose()関数について fopen() ファイルをオープンします

include ltstdiohgt FILE fopen( char filename char mode ) 戻り値正常にファイルのオープンができたらファイルポインタを返しますエラーがあった場

合には NULLを返します 文字列 filename で指定されたファイルをオープンしますオープン後の入出力のモードに

ついては文字列 mode で指定しますmode に指定できる文字は以下のとおりです r 入力モードでオープンします w 出力モードでオープンします a 存在するファイルに追加して出力するモードでオープンします r+ 既に作成してあるファイルを更新(入力出力)するモードでオープンします w+ 新しく作成するファイルを更新モードでオープンします a+ 既に作成してあるファイルの終りから更新用に作成します

以上の文字に b をつけ加えることによりバイナリモードで入出力することができるようになり

ます rb バイナリの入力モードでオープンします wb バイナリの出力モードでオープンします ab 存在するファイルに追加して出力するモード(バイナリ)でオープンします

fclose() 既にオープンしてあるファイルをクローズします include ltstdiohgt fclose( FILE fp ) 既にオープンしているファイルをクローズしますパラメータには fopen() 関数により返された

ファイルポインタを指定します

35

テキストモードとバイナリモード 行の最後はテキストモードの場合改行コードのみとなりバイナリモードの場合には復帰

コードと改行コードの組合わせになります行の最後としてテキストファイルには復帰コード改行

コードが書かれていますがテキストモードでオープンした場合には入力すると改行コードのみに

変換されて入力されますバイナリモードの場合には復帰コード改行コードがそれぞれ入力され

ます

fputs()fgets()関数について fputs() ファイルポインタで指定されるファイルに文字列を出力します

include ltstdiohgt

int fputs( char s FILE fp ) fputs() は NULL で終る文字列 s をファイルポインタに示されるファイルへ出力しますputs()

と違い最後に改行文字 yenn を出力することはありません

fgets() ファイルポインタで指定されるファイルから文字列を入力します include ltstdiohgt char fgets( char s int n FILE fp ) 戻り値正常に入力した場合には引数 s の値が返されますエラーやEOFになった場合に

は NULL が返されます fgets() はファイルポインタで指定されるファイルから ( n - 1 ) 文字または改行文字までの

文字列を入力しs に格納しますgets() と異なり最後に入力された改行文字は NULL 文字に変更されません

標準入力から入力しファイルへ出力する ファイルへ出力あるいは入力を行う場合には改行コードの変換(入力の場合の削除出力の

場合の付加)はされませんしたがって標準入力から入力しファイルへ出力する場合には改行

コードを付加しなければなりません include ltstdiohgt main() char data[80] FILE fp fp = fopen( data w ) while( gets( data ) = NULL ) strcat( data yenn ) 改行コードの付加

fputs( data fp ) fclose( fp )

36

fputc()fgetc()関数について fputc() ファイルポインタで指定されるファイルに1文字出力します

include ltstdiohgt int fputc( int c FILE fp ) 戻り値正常に出力できた場合には文字 c を返しエラーの場合には EOF を返します fputc() は文字 c をファイルポインタで示されるファイルへ出力します

fgetc() ファイルポインタで指定されるファイルから1文字入力します

include ltstdiohgt int fgetc( FILE fp ) 戻り値正常に入力した場合には入力した文字を返しますエラーやEOFになった場合には

EOF が返されます fgetc() はファイルポインタで指定されるファイルから文字を入力します

ファイルの内容の表示 include ltstdiohgt main() FILE fp int ch char fname[30] printf( Key in Fila name gt ) gets( fname ) fp = fopen( fname r ) while( ( ch = fgetc( fp ) ) = EOF )putchar( ch ) fclose( fp )

その他テキスト中で使用された関数について sin() 三角関数の正弦を計算します

include ltmathhgt double sin(double radian) sinはラジアンを単位とする引数 radianの三角関数を計算します

37

strcpy() 文字列を他の文字列へコピーします

include ltstringhgt char strcpy(char string1const char string2) strcpyは引数 string2の指す文字列を null文字まで含めて引数 string1の指す領域にコピ

ーする strcpyは string1を返します

strcat() ある文字列を他の文字列に加えます

include ltstringhgt char strcat( char dest const char src ) 戻り値連結された文字列へのポインタを返します strcat() はsrc のコピーを dest の最後につけ加えます得られる文字列の長さは

strlen(dest)+strlen(src) になります

fabs() 絶対値の計算をします include ltmathhgt double fabs(double z) fabsは倍精度浮動小数の絶対値を計算して返しますつまりzgt=0であれば z をzlt0であ

れば-zを返します exp() 指数関数を計算します

include ltmathhgt double exp(double z) exp は引数zの指数関数つまりezを返すここではeは自然対数の底を表します対数関

数logの逆関数です

38

付 録 2 コンパイルの方法には大きく分けて第4章の実習で学んだようにデータファイルを作成してお

き ccg でコンパイルさせる方法と実行中に対話型でデータを入力していく方法があります ここでは対話型で実行を進めていく方法を紹介します ただしこの方法は計算(cpu)時間が10秒以内のものに限ります10秒を超える計算(cpu)時

間を要する場合はccg でコンパイルをするようにしてください 第4章実習の(2)(p16)までは同様です

コンパイル

コンピュータに処理を依頼します 60us1234boseicc cc rensyuc

所有するファイルの一覧を見てみます

60us1234boseicc ls -l larr 持っているファイルの一覧を見るコマンドです

-rw-r--r-- 1 60us1234 other 128 4月26日 15時14分 rensyuc -rwxr-xr-x 1 60us1234 other 361 4月26日 15時16分 aout

aout という実行形式のファイルが作成されています

実行

60us1234boseicc aout12 35[リターン] データを入力

1 200000 3500000 4200000 実行結果の出力

60us1234boseicc

注意

aout ファイルは印刷することができません実行結果を印刷する場合にはファイルに落とし てから出力するようにしましょう

60us1234boseicc aout gt kekka12 35[リターン] データを入力

60us1234boseicc more kekka 計算結果の確認 60us1234boseicc lpr kekka 計算結果の印刷

39

Page 10: n 第1章 章立ての部分は、書式(PC入門大見出し)を …第2章 数の表現 2-1 2進数 電子計算機の動作原理は0と1で表される2進数です。また、人間が日常生活で扱っている数

main() float x y f() 変数と関数の型の宣言

while( scanf( f ampx ) = EOF ) y = f( x ) 関数の引用x は実引数と呼びます

printf( yenn x=f f(x)=f x y ) float f( float x ) 関数の定義x は仮引数と呼びます

float y y = 40 x x + 20 x + 50 return y 計算を終了し結果を戻します

[入力の終了について]

このプログラムを実行すると永遠とデータ入力を求められてしまいます終了条件が = EOF の場合はキーボードから CTRLキーを押しながら Z を入力することにより while文を抜け入力を終了することができます

複数の引数を受け渡しする場合には引用する側と関数を定義する側とで 引数の並び個数型

を合わせなければなりませんしかし変数名は同じでなくてもかまいません例えば配列 a と bを加算して配列 cに代入する場合には次のようになります

include ltstdiohgt main()

int a[10] = 18 24 56 28 96 51 82 34 65 72 UNIXの場合 static intにする int b[10] = 12 54 69 20 26 84 55 20 44 74 UNIXの場合 static intにする

int c[10] k void matadd() 関数の型宣言

matadd( a b c ) for( k = 0 k lt 10 k++ ) printf( yenn d + d = d a[k] b[k] c[k] ) void matadd( int x[] int y[] int z[] ) 関数の定義

int t for( t = 0 t lt 10 t++ ) z[t] = x[t] + y[t]

演習4 平均値を求める関数average()を作成し10名の数学の得点を読み込みその平均点を求め

るプログラムを作りなさい 「入力例」 「出力例」

45 63900000 78 97

8

この他にも関数にパラメータを渡す方法としてポインタを使用する方法があります文字列を

複写する関数の場合には次のとおりになります関数名は strcopy()最初の引数には複写先の配列名(配列の先頭番地)次の引数には複写元の配列名(配列の先頭番地)です

include ltstdiohgt main() char src[] = tokai dst[80] void strcopy() strcopy( dst src ) printf( syenn dst )

void strcopy( char str1 char str2 ) while( ( str1++ = str2++ ) = yen0 )

また配列の加算を行う関数の場合にもそれぞれの配列名をパラメータとし関数側でポイン

タ型変数として受け取ることができます

include ltstdiohgt main() int a[10] = 18 24 56 28 96 51 82 34 65 72 UNIXの場合 static intにする int b[10] = 12 54 69 20 26 84 55 20 44 74 UNIXの場合 static intにする

int c[10] int k void matadd() matadd( a b c 10 ) for( k = 0 k lt 10 k++ ) printf( d + d = d yenn a[k] b[k] c[k] )

void matadd( int x int y int z int n ) for( n gt 0 n-- ) z++ = x++ + y++

main()関数では配列名(アドレス定数)として引数に指定されていますが関数 matadd()ではポインタ型の変数として使用することができますしたがって変数 xyz は値を変更することができるようになります

配列 a 変数 x

9

配列 b 変数 y 配列 c 変数 x

3-4 戻り値 関数からの戻り値はreturn 文によって返されます整数型文字型の値を返す関数の場合

にはそれぞれ次のように定義します

int sub( int x ) char sub( int x ) int y char z

return y return z

またポインタを返す関数の場合には次のように定義します

int sub( int x ) char sub( int x ) int y char z

return y return z

return文で式の指定がない場合には何も値を返しません

[プログラム例]

文字列(文字型配列)の中に指定した文字があればその位置をポインタで返し無ければ NULLポインタを返す関数を考えてみます

char strfind( char str char ch ) while( str ) if( str == ch )return str str++ return NULL

いくつかのC言語のマニュアルでは関数の説明を以下のように記述しています sin 機能 正弦を求めます 形式 include ltmathhgt double sin( double x ) このとき関数 sin() の戻り値は double 型でありまた指定する引数も double 型でなけれ

ばなりませんそれと同時にこの関数を使用する場合にはinclude ltmathhgt を指定しなければなりません

10

3-5 変数の通用範囲 関数内で宣言された変数はその関数の中でのみ使用可能です他のプログラムからは使用

することはできません

include ltstdiohgt main() int i 変数 i は関数 main() と sub() とでは それぞれ独立に使用することができます main() で変数 i に設定した値は sub() では参照することはできません sub() 逆にsub() で変数 i に設定した値も main() では参照することはできません

int i

それぞれの関数の中でのみ使用可能な変数をローカル変数と呼び他の関数でも使用可能

な変数をグローバル変数と呼びますいくつかの関数で共通に使用するような場合にはグロー

バル変数を使用します グローバル変数を定義する場合には関数の外で宣言します

include ltstdiohgt int i グローバル変数の定義

main() i = 10

sub() extern int i printf( yenn i = d i )

このプログラムではmain() 関数でグローバル変数に値を設定し関数 sub() で変数の値を

参照しています extern 宣言は変数が他のプログラム内で宣言されていることを示しています宣言の形式

は以下のとおりです extern 型 変数並び

演習5 入力された任意の数の倍数を求めるプログラムを作成しなさい入力する数値は2つ倍数 を求めるための任意の数と倍数の上限値ですここでいう上限値とは任意の数の倍数をどの くらいの数まで求めるかということです

11

3-6 動的変数と静的変数 通常Cで使用される変数はその関数の中だけでのみ使用できる変数ですしたがって関数

が実行するときに関数の中で使用する変数の領域を確保し関数の実行が終るときにその領域

を解放するようにしてメモリを効率的に利用していますこのように関数が実行されるときに確

保される変数を動的変数(auto変数 )と呼びます プログラムの中ではその他に常に存在し使用できる変数を定義することができますそのよ

うな変数は静的変数(static変数 )と呼ばれます

func() int a b static int x y

また static 変数には内部的なリンケージの指定の意味もありますつまり関数の外で変数

を宣言すると自動的にグローバル変数となり他のプログラムからも使用することができるようにな

ります ファイル a ファイル b このような場合にはコンパイル単位が異なっていてもextern 宣言を行うことにより変数 abc

を使用することができますところが関数の外で static 宣言をして定義した変数についてはコンパイル単位が違うプログラムからは使用することができなくなります ファイル a ファイル b 同一コンパイル単位(ファイル)に存在する関数 sub()と subd()では変数 abcを使用することが

できますがコンパイル単位(ファイル)が異なる関数 func()では変数 abcを使用することはできません

int abc sub() abc = 10

func() extern int abc printf( ldquo abc =dyennrdquo abc )

static int abc sub() abc = 10 subd() abc++

func() extern int abc printf( ldquo abc =dyennrdquo abc )

12

3-7 スタック プログラム中にはプログラム領域データ領域の他にスタック領域があり一時的な作業領域と

して使用されています関数間での引数の受渡しの時にもこの領域を使用しますスタック領域に

データを格納することを「スタックに積む」ともいいます基本的にはスタック領域に格納されたデ

ータは最後に格納されたデータから順に取り出されることになります以下に格納が行われたとき

のスタックの状態を示します記号は次に格納すべき位置(スタックポインタの値)を示していま

逆にスタックからデータを取り出すときにはスタックポインタが指している位置の一つ下から取

り出すことになりますスタックからデータを取り出すときのスタックの状態は次のようになります

なり

10

20

10

30

20

10

40

30

20

10

10rarr

格納

20rarr

格納

30rarr

格納

40rarr

格納

40rarr 30rarr

関数を呼び出すときには次

逆にそれぞれの関数から

次のようになります

40

30

20

10

取出

main() z = f1( x y )

のようにパラメータがスタ

戻るときにはパラメータで

30

20

10

取出

f1( int a int b ) c = f2( d e

xの値 yの値

xの値 yの値

13

ックに格納されます

使用していたスタック領域は自動的になく

10

20

)

f2( int p int q ) r = p + q

xの値

eの値 dの値

yの値

xの値 yの値

dの値

eの値

3-8 再帰呼び出し 関数の引数の受渡しがスタックを利用して行われることから自分で自分自身の関数を呼び出

すことができます 以下のプログラムは入力した値の階乗を計算するプログラムです

3の階乗を求めることを考えてみます

return 文によって戻るときは次のようにして値を返します kai( 3 ) 3 kai( 3-1 ) 2 kai( 2-1 ) return 1

6 3 (2 1) 2 1 以上の計算から3=6が導き出されます 再帰呼び出しのことをリカーシブコールともいいます

include ltstdiohgt main() int n m kai() scanf( ldquodrdquoampn ) m = kai( n ) printf( ldquod = dyennrdquo n m )

int kai( int k ) if( k == 1 )return 1 else return k kai( k ndash 1 )

kai( 1 )

darr

return 1

kai( 2 )

darr

2 kai( 2-1 )

kai( 3 )

darr

3 kai( 3-1 )

main()

darr

kai( 3 )

3

2

1

2

3

1

2

3 3

32

32

1

2

1

3

3

演習6 1からnまでの総和を再帰呼び出しを使って計算する関数 sowa() を作りなさい n+(n-1)+ +2+1

14

第4章 実習 この章ではプログラムを実際に入力して実行するまでの手順を実習します

4-1 操作手順 (1)ログイン

[スタート]rarr[プログラム(P)]rarr[ネットワーク] Hostの欄に bosei を記述選択 rarr [Telnet(FreeWare)] を選択します して 「OK」 ボタンをクリックします

UP-UXV (Rel42MP) (bosei) (pts41) login 60us1234 larr 各自のログイン名を入力します Password larr パスワードを入力しても画面は何も変化しません 101 60us1234bosei larr セッションが開設されましたこれをプロンプトといいます この状態でコマンドを入力することができます

(2)プログラムの作成 以下のコマンドを入力しテキストエディタを起動します 60us1234boseicc ng rensyuc

すると下図のようにngエディタの画面になります

15

次のように入力します入力ミスの修正はBSキーで行ないます

include ltstdiohgt main() float abc scanf(f f ampaampb) c=ab printf(f f f yenn abc)

CTRL キーを押しながら XCTRL キーを押しながら C を押しますすると次のメッセージが画面下に表示されます

Save file uhomea60us1234rensyuc (y or n)

このメッセージに対して y と答えます

(3)データの作成 以下のコマンドを入力しテキストエディタを起動します 60us1234boseicc ng rensyud

ngエディタの画面になりますので次のように入力します 12 35

CTRLキーを押しながら XCTRLキーを押しながら C を押します save file uhomea60us1234rensyud (y or n)

このメッセージに対して y と答えます

(4)コンパイルと実行 コンピュータに処理を依頼します 60us1234boseicc ccg rensyu

ジョブを投入しましたジョブの状態を見るコマンドは myjobです

16

130 60us1234boseicc myjob ================================================= NQS (R0220) BATCH REQUEST HOST bosei ================================================= REQUEST ID NAME OWNER QUEUE PRI NICE STT PGRP R --------------- -------- -------- -------- ---- --- --- ------ - 99321bosei STDIN 60us1234 A 31 0 RUN 14161 - ---------------------------------------------------------------- ================================================== NQS (R0220) DEVICE REQUEST HOST bosei ジョブは実行中です

================================================== REQUEST ID NAME OWNER QUEUE PRI SIZE STT -------------------------------------------------------------

所有するファイルの一覧を見てみます

60us1234boseicc ls -l larr 持っているファイルの一覧を見るコマンドです

-rw-r--r-- 1 60us1234 other 4 4月26日 15時14分 rensyud -rw-r--r-- 1 60us1234 other 128 4月26日 15時10分 rensyuc -rwxr-xr-x 1 60us1234 other 361 4月26日 15時16分 rensyul

(5)計算結果の確認

計算結果を画面に表示して確認します 60us1234boseicc more rensyul

(6)印刷

計算結果の印刷を行ないます5号館2階のカフェテリア室にある bosei のプリンタに印刷 されます

60us1234boseicc lpr rensyul

(7)ログアウト セッションを終了します 60us1234boseicc logout

(8)実行の流れ

エラー

プログラムの作成 ログイン コンパイル実行

確 認 印 刷 ログアウト

17

第5章 配列 多数の変数をまとめて宣言する方法として配列があります配列の一つ一つは配列要素と呼

ばれ変数と同じ性格を持っています配列の宣言は型宣言と同時に次のように行います int a[5] 配列 a

a[0]

a[1]

a[2]

a[3]

a[4]

二次元配列(一次元配列を複数集めたもの)を宣言する場合には次のようになります int b[3][4] 配列 b

b[0][0] b[0][1] b[0][2] b[0][3]

b[1][0] b[1][1] b[1][2] b[1][3]

b[2][0] b[2][1] b[2][2] b[2][3]

配列要素に数値を代入する場合は次のようになります b[1][2]=10

5-1 二次元配列要素の初期化 変数の型宣言と同じように配列を宣言するときに初期値も同時に設定することができます

複数のデータがある場合には{}記号でくくって指定します int b[3][4] = 2 4 6 8 1 3 5 7 1 2 3 4

文字型配列の場合には以下のようになりますyen0 は文字列の終わりを表わします char univ[3][7] = T O K A I yen0 S I M I Z U yen0 Y O Y O G I yen0

また文字列定数として初期化することもできますこの場合コンパイル時に自動的に yen0 が付加されます

char univ[3][7] = TOKAI SIMIZU YOYOGI

18

[プログラム例] 二次元配列のタテヨコを加算するプログラム

include ltstdiohgt main() int mat[4][3]=123456789101112 int ijytotalttotal[3]total=0 for(j=0jlt3j++)ttotal[j]=0 for (i=0ilt4i++) ytotal=0 for(j=0jlt3j++) ytotal += mat[i][j] ttotal[j] += mat[i][j] total += mat[i][j] printf(3dmat[i][j]) printf( 3dyennytotal) printf(yenn) for(j=0jlt3j++)printf(3dttotal[j]) printf( 3dyenntotal)

[実行結果]

1 2 3 6 4 5 6 15 7 8 9 24 10 11 12 33 22 26 30 78

演習7

a)以下の配列はどのように初期化されるか答えなさい char errmsg[2][15] = Divide Error Overflow Error

b)九九の計算を2次元配列を使って求めなさい

19

第6章 ポインタ型変数 C言語では値を記憶するための変数だけではなく変数または定数の番地を記憶するため

のポインタ型変数を宣言することができますポインタとはデータ項目の一種で「記憶装置(メモ

リ)上の格納番地(アドレス)を指すデータ項目」です アドレス コンピュータの中ではデータ項目の格納番地のことをアドレス(住所)と呼びます 例えば記憶装置という名前のとてつもなく大きなマンションがあるとしますその中から Aさんを捜すときは部屋番号を参照しますマンションでは部屋番号で住居人を参照し ているのと同じようにコンピュータでは記憶装置上に確保された変数は格納番地 (アドレス)で管理されています

マンション 部屋番号 記憶装置 格納番地

Aさん Int a Bさん Cさん AAAさん BBBさん CCCさん

1号室

2号室

3号室

100号室

200号室

300号室

100番地

200番地

300番地

1000番地

2000番地

3000番地

Int b Int c float aaafloat bbbfloat ccc

ポインタ ポインタとは「指し示すもの」の意ですがC言語では記憶装置上のアドレスを指し示す もののことです上のマンションの例では部屋番号を格納するデータ項目ということに なりますAAAさんは100号室に住んでいます100という値をポインタのデータ項目に 記憶するとそのデータ項目は間接的にAAAさんを指すことになります

6-1 ポインタ型変数の宣言および参照 通常の変数と区別するために型宣言時に変数名の前に記号を付けて宣言します int a 整数型ポインタ変数 int b 整数型変数

変数 a は整数型の値を記憶するのではなく整数型の値を持つ変数などの番地を記憶する変数ですまた変数 b は通常の整数型の値を記憶するための変数です

20

include ltstdiohgt main() int a b c a はポインタ型の変数b c は整数型の変数 b = 12 変数 b に値 12 を代入します a = ampb 変数 a には変数 b の番地が代入されます c = a + 10 変数 a の指す変数(b)の内容と10の加算です つまり12 + 10 を変数 c に代入します

変数の型宣言において変数名に記号を付けることによりその変数はポインタ型の変数と

なりますポインタ型の変数は変数名のみを指定した場合には単にその変数の値(通常はメモリ

の番地)を表します変数名に記号を付けて使用した場合にはその変数が指し示している変

数の内容を表します c = a ポインタ型変数 a が指している値を変数 c に代入

ポインタ型の変数に番地を記憶させるためにはプログラム例のように変数名の前に記号を

指定します変数名 によって変数の番地(アドレス)を表します a = ampb 変数 b の番地をポインタ型変数 a に代入します

ポインタ型変数の型はポインタ型変数が指し示す先の変数の型を表しています int a 変数 a 整数型の値 float x 変数 x 実数型の値 char c 変数 c 文字型の値

6-2 ポインタ型変数の初期化 ポインタ型変数も型宣言のときに変数を初期化することができます特に文字型のポインタ変

数の場合によく使います char str = TOKAI University

ポインタ型変数 str は文字列定数 TOKAI University の最初の文字が格納されている番地を初期値として持つことになります

変数 str TOKAI University 文字列定数

[プログラム例]

(1)文字型配列 putchar() 関数を使って一次元の文字型配列を出力します include ltstdiohgt main() char str[6] = TOKAI int i for( i = 0 str[i] = yen0 i++ ) putchar( str[i] )

21

ポインタを使用した場合には以下のようになります include ltstdiohgt main() char str[6] = TOKAI char chp for( chp = str chp = yen0 chp++ ) putchar( chp )

chp str T [0] O K A I yen0 [5]

参照する変数 配列の表現 ポインタの表現 実際のアドレス 1番目の数 str[0] chp CHP 2番目の数 str[1] (chp+1) CHP+1 n番目の数 str[n-1] (chp+n-1) CHP+n-1 6番目の数 str[5] (chp+5) CHP+5

注意実際のアドレス CHPは実行時に決定されます

(2)二次元文字型配列 二次元の文字型配列に定数を設定しそれを出力するプログラムです文字型配列を使用す

ると次のとおりになります include ltstdiohgt main() char str[5][40] = TOKAI shounan campus NEC DEC int i for( i = 0 i lt 5 i++ ) printf( yenns str[i] )

40 バイト str TOKAI shounan campus NEC DEC

22

ポインタ型配列を使用すると次のとおりになります include ltstdiohgt main() char str[6] = TOKAI shounan campus NEC DEC NULL char chp for( chp = str chp = NULL chp++ ) printf( yenns chp ) str

chp 番地 TOKAI 番地 shounan 番地 campus 番地 NEC 番地 DEC

NULL

演習8 キーボードまたはデータファイルから読み込んだ文字列中にrsquoArsquo があったら rsquoarsquo に変換 するプログラムを配列とポインタを使って書きなさい

23

第7章 構造体共用体 7-1 構造体

プログラムの規模が大きくなるにつれて多数の intや floatcharなどのデータ型を扱うようになり複雑になってきますそこで多数のデータを1つにまとめて簡単に扱える機能が構造体です 構造体について住所録のデータを例にあげて考えてみます

住所録の個人データとして氏名住所電話番号年齢の項目を一つのデータとします これをC言語で変数の定義をすると次のようになります 氏名東海太郎 char name[30] 住所平塚市北金目1117 char address[30] 電話番号0463-58-1211 char tel[20] 年齢30 int age 個人の住所録データ C言語での表現 このような住所録の個人データを1つにまとめて新しいデータとして定義する機能を構造体と言

います struct 構造体タグ名 構造体メンバーの並び

「struct」は構造体を表すキーワードです 「構造体タグ名」は構造体の型枠を宣言しますここは自由に名前を定義することができ ます 「構造体メンバーの並び」は構造体の要素です複数指定できます

個人の住所録のデータを構造体で宣言すると次のようになります

struct jusho char name[30] char address[30] 構造体のメンバーの並び char tel[20] (複数可)

int age

上記の宣言では構造体の形式を宣言しているだけでメモリ中で実際の領域を確保している

わけではありません実際に領域を確保するためには次のように定義します

struct 構造体タグ名 構造体名

したがって構造体名を jdata とすると次のように指定します

struct jusho jdata

構造体 jdataは次のように構造体タグ jushoの形式で領域を確保します

24

Jdata name[30]

address[30] tel[20] age

(1)構造体の参照

プログラム中で構造体中のメンバーを参照する場合には次のように指定します 構造体名メンバー名

したがって「名前」を参照したいときには次のように指定します

jdataname

[プログラム例]

名前住所電話番号年齢を定義しそれを印字します include ltstdiohgt include ltstringhgt main() struct jusho char name[30] char address[30] char tel[20] int age struct jusho jdata strcpy( jdataname 東海 太郎) strcpy( jdataaddress 平塚市北金目1117)

strcpy( jdatatel 0463-58-1211) jdataage = 30 printf(yenn氏名 = syenn jdataname) printf(yenn住所 = syenn jdataaddress) printf(yenn電話番号= syenn jdatatel) printf(yenn年齢 = dyenn jdataage)

また構造体の形式の定義と領域の確保は次のように同時におこなうことができます

struct 構造体タグ名 構造体メンバーの並び 構造体名

struct jusho struct jusho char name[30] char name[30] char address[30] char address[30] char tel[30] = char tel[30] int age 同じ int age

jdata struct jusho jdata

型宣言と同時にメモリ上に領域を確保する方法 後からメモリ上に領域を確保する方法

25

(2) 構造体配列 住所録データの場合その中に入るデータは1件ではありませんやはり100件200件のデ

ータが必要になる場合がありますこのように個人単位のデータを多数扱う場合には構造体を配

列として宣言することができます 次の例は個人のデータを100個用意するために構造体を配列として宣言しています struct jusho jdata[100] jdata[0] name[30] address[30] tel[20] age

jdata[99 ] name[30] address[30] tel[20] age

(3)構造体配列の参照

プログラム中で構造体配列中のメンバーを参照する場合には次のように指定します 構造体名[要素番号]メンバー名

したがって10件目の人の「名前」を参照したいときには次のように指定します

jdata[10]name

[プログラム例]

名前住所電話番号年齢を定義しそれを印字します include ltstdiohgt include ltstringhgt main() struct jusho char name[30] char address[30] char tel[20] int age jdata[100] strcpy( jdata[10]name 東海 太郎) strcpy( jdata[10]address 平塚市北金目1117)

strcpy( jdata[10]tel 0463-58-1211) jdata[10]age = 30 printf(yenn氏名 = syenn jdata[10]name) printf(yenn住所 = syenn jdata[10]address) printf(yenn電話番号= syenn jdata[10]tel) printf(yenn年齢 = dyenn jdata[10]age)

26

(4) 構造体のポインタ 変数と同じように構造体へのポインタも定義することができます

変数へのポインタ例 構造体へのポインタ例 またポインタを使用して構造体メンバーを参照するには次のように -> 記号を使って指

定します ポインタ変数名 -> メンバー名

[プログラム例]

名前住所電話番号年齢を定義しそれを印字します include ltstdiohgt include ltstringhgt main() struct jusho char name[30] char address[30] char tel[20] int age jdatakp kp = ampjdata strcpy( kp-gtname 東海 太郎)

strcpy( kp-gtaddress 平塚市北金目1117)

strcpy( kp-gttel 0463-58-1211) kp-gtage = 30 printf(yenn氏名 = syenn kp-gtname) printf(yenn住所 = syenn kp-gtaddress) printf(yenn電話番号= syenn kp-gttel) printf(yenn年齢 = dyenn kp-gtage)

kp jdata

name[30] ポインタ型の変数 address[30]

tel[20]

構造体へのポインタを記憶 age

することができます

int a int b b = ampa

struct name jname struct name np np = ampname

27

7-2 共用体 共用体は構造体と同じようにして宣言しますが共用体は複数のデータ型を同一のアドレスに

割り当てる方法です union 共用体タグ名 共用体メンバーの並び

「union」は共用体を表すキーワードです 「共用体タグ名」は共用体の型枠の名前を宣言しますここは自由に名前を定義することがで

きます 「共用体メンバーの並び」は共用体の要素です複数指定できます

共用体の宣言の例を次に示します

union c_tag int a char b

共用体 cは次のように共用体タグ c_tagの形式で領域を確保します共用体はメモリ上に領域を確保するときは ab ともに同じ領域に割り付けられます これはab という2つのデータが同時に存在するわけではなく cを異なるデータ abで共有す

ることを表しています c a b

上記の宣言だけでは共用体の形式を宣言しているだけでメモリ中で実際の領域を確保して

いるわけではありません実際に領域を確保するためには次のように定義します union 構造体タグ名 構造体名

したがって共用体名を c とすると次のように指定します

union c_tag c

(1)共用体の参照

プログラム中で共用体中のメンバーを参照する場合には次のように指定します 共用体名メンバー名

したがって「a」または「b」を参照したいときには次のように指定します

ca (int 型) cb (char 型)

メンバー参照方法によって int型として使ったりchar型として利用することができます

28

[プログラム例]

includeltstdiohgt main() union data char a short b int c chk chkc = 0x12345678 printf( char a xyennchka) printf( short b xyennchkb) printf( int c xyennchkc)

chkb(int 型) chkb(short 型) chka(char 型) 12 12 12 34 34 56 78

29

第8章 アルゴリズム コンピュータに何か仕事をさせようとするときは仕事を具体的に実行するための処理や動作

の手順が必要ですこの「手順」がアルゴリズムです アルゴリズムを考えるときは解くべき問題をはっきりと定義することが必要です

8-1 ソート ソートとは与えられたデータを小さい順または大きい順に並べ換えることですソート方法は

いくつかありますが基本的な方法でソートするアルゴリズムを紹介します

includeltstdiohgt int data[10] main()

int data_in() sort() data_in() sort() int data_in() データ入力関数

int a printf(数値入力yenn)

for(a=0alt=9a++) printf( [d]a+1) scanf(dampdata[a]) int sort() ソート処理を行う関数

int cont1cont2tmp1tmp2mim for(cont1=0 cont1lt=9 cont1++) mim=data[cont1] tmp1=cont1 for(cont2=cont1+1 cont2lt=9 cont2++) if(data[cont2] lt mim) mim=data[cont2] tmp1=cont2 tmp2 = data[cont1] data[cont1] = data[tmp1] data[tmp1] = tmp2 printf(結果 yenn)

for (cont1 = 0 cont1 lt= 9 cont1++) printf(d yenn data[cont1])

30

第9章 プリプロセッサ C言語にはプログラムの中でコンパイルについての指示を行う「プリプロセッサ」という機能が

ありますまたプリプロセッサとはコンパイルする前に実行されるためその意味のとおり「前処理」 と呼ばれていますここでは代表的なものをいくつか説明します

9-1 ファイルの挿入 ソースプログラム中に指定されたファイルを挿入します

include ltstdiohgt helliphellip 標準ディレクトリを探します include progh helliphellip 現在のディレクトリを探しなければ標準ディレクトリを探します

includeltstdiohgt によって組み込まれた define EOF (-1) define EOF (-1) define define helliphelliphelliphellip 組み込み helliphelliphelliphellip

main() stdiohファイル

int helliphelliphelliphellip helliphelliphelliphellip

ソースファイル

9-2 文字の置換 プログラム中に使われている文字列を別の文字列に置き換えます

include ltstdiohgt define TRUE 1 define EOF (-1) main() define helliphellip helliphellip

while(TRUE) define TRUE 1 置き換え main() helliphellip helliphellip while(1)

break helliphelliphellip

31

9-3 条件によるコンパイル 識別子が定義されているか否かを判断しコンパイルする範囲を指定します

include ltstdiohgt define UNIX main() ifdef UNIX printf( UNIX yenn) else printf(MS-DOSyenn) endif

include ltstdiohgt define OS UNIX main() if OS == UNIX printf( UNIX yenn) else printf(MS-DOSyenn) endif

32

付 録 1 puts()gets()関数について

行単位に入出力を行う場合には puts() gets() 関数を用います

puts() 標準出力に文字列を出力します

include ltstdiohgt int puts( char s ) puts() は NULL で終る文字列 s を標準出力に出力し最後に改行文字 yenn も出力しま

gets() 標準入力から文字列を入力します

include ltstdiohgt char gets( char s ) 戻り値正常に入力した場合には引数 s の値が返されますエラーやEOFになった場合に

は NULL が返されます gets() は標準入力から復帰文字で終る文字列を入力しs に格納しますこのとき最後の復

帰文字は NULL文字に変更されます

入力行の出力 標準入力から gets() で入力したデータには改行コードは含まれませんまた標準出力へ

puts() で出力を行う場合には必ず改行コードが付加されますgets() を実行したときの戻り値としてファイルの終端を検出した場合には EOF ではなく NULL が返されますので注意して下さい

include ltstdiohgt main() char data[80] while( gets( data ) = NULL )puts( data )

putchar()getchar()関数について putchar() 標準出力に文字を出力します

include ltstdiohgt int putchar(int c ) 戻り値正常に出力できた場合には文字cをエラーの場合にはEOFを返します

33

getchar() 標準入力から文字を入力します

include ltstdiohgt int getchar(void) 戻り値正常に入力した場合には読み込んだ文字を int 型に変換して返しますまたファイ

ルエンドエラーの場合にはEOFを返します

標準入力標準出力

標準入力標準出力はプログラムが開始されるときにはオープンされていますそれぞれのフ

ァイルポインタは stdin stdout になっていますfopen() fclose() をせずとも使用することができます

scanf() 標準出力ストリームからテキストを読み込み解釈します include ltstdiohgt int scanf( const char format [ address ] ) 戻り値正しくスキャンし変換し格納した入力フィールドの数を返しますファイルエンドを読

み込んだ場合は戻り値は EOF となります値を格納したフィールドがなかった場合は戻り値は0となります

一連の入力フィールドをスキャンして1度に1文字ずつストリーム stdin から文字を読み込み

ます次に引き数 format によって指される書式文字列中の書式指定に従って各フィールドを書式化します最後にformat の後に続く各引き数が示しているアドレスに書式化した入力を格納していきます書式文字列中の書式指定の個数はその後に続くアドレスの数と同じでな

ければなりません 書式指定[入力幅][型指定文字] 入力幅 読むべき文字数の最大値 型指定文字 次のとおりです 型指定文字 期待される入力 引き数の型 d 10進整数 int へのポインタ( int arg ) x 16進整数 int へのポインタ( int arg ) f 浮動小数点数 float へのポインタ( float arg ) s 文字列 文字配列へのポインタ( char arg[] ) c 文字 文字へのポインタ( char arg )

printf() フォーマットを指定してテキスト標準出力ストリームに出力します include ltstdiohgt int printf( const char format [ argument ] ) 戻り値出力したバイト数を返しますエラーの場合は EOF を返します

34

format によって指される書式文字列中の書式指定をformat の後に続く各引き数に適用し

書式化されたデータを stdout に出力します書式指定は後に続く引き数と同じ数だけなければなりません

書式指定[印字幅][精度][型指定文字] 印字幅 印字する最小文字数 精度 印字する最大文字数 型指定文字 つぎのとおりです 型指定文字 入力引き数 出力の書式 d 整数 符号付き10進整数 x 整数 符号無し16進整数 f 浮動小数点 符号付きの dddddddd形式の値 c 文字 1個の文字 s 文字列ポインタ ヌル文字に出会うか精度に達するまで 文字をプリントする

fopen()fclose()関数について fopen() ファイルをオープンします

include ltstdiohgt FILE fopen( char filename char mode ) 戻り値正常にファイルのオープンができたらファイルポインタを返しますエラーがあった場

合には NULLを返します 文字列 filename で指定されたファイルをオープンしますオープン後の入出力のモードに

ついては文字列 mode で指定しますmode に指定できる文字は以下のとおりです r 入力モードでオープンします w 出力モードでオープンします a 存在するファイルに追加して出力するモードでオープンします r+ 既に作成してあるファイルを更新(入力出力)するモードでオープンします w+ 新しく作成するファイルを更新モードでオープンします a+ 既に作成してあるファイルの終りから更新用に作成します

以上の文字に b をつけ加えることによりバイナリモードで入出力することができるようになり

ます rb バイナリの入力モードでオープンします wb バイナリの出力モードでオープンします ab 存在するファイルに追加して出力するモード(バイナリ)でオープンします

fclose() 既にオープンしてあるファイルをクローズします include ltstdiohgt fclose( FILE fp ) 既にオープンしているファイルをクローズしますパラメータには fopen() 関数により返された

ファイルポインタを指定します

35

テキストモードとバイナリモード 行の最後はテキストモードの場合改行コードのみとなりバイナリモードの場合には復帰

コードと改行コードの組合わせになります行の最後としてテキストファイルには復帰コード改行

コードが書かれていますがテキストモードでオープンした場合には入力すると改行コードのみに

変換されて入力されますバイナリモードの場合には復帰コード改行コードがそれぞれ入力され

ます

fputs()fgets()関数について fputs() ファイルポインタで指定されるファイルに文字列を出力します

include ltstdiohgt

int fputs( char s FILE fp ) fputs() は NULL で終る文字列 s をファイルポインタに示されるファイルへ出力しますputs()

と違い最後に改行文字 yenn を出力することはありません

fgets() ファイルポインタで指定されるファイルから文字列を入力します include ltstdiohgt char fgets( char s int n FILE fp ) 戻り値正常に入力した場合には引数 s の値が返されますエラーやEOFになった場合に

は NULL が返されます fgets() はファイルポインタで指定されるファイルから ( n - 1 ) 文字または改行文字までの

文字列を入力しs に格納しますgets() と異なり最後に入力された改行文字は NULL 文字に変更されません

標準入力から入力しファイルへ出力する ファイルへ出力あるいは入力を行う場合には改行コードの変換(入力の場合の削除出力の

場合の付加)はされませんしたがって標準入力から入力しファイルへ出力する場合には改行

コードを付加しなければなりません include ltstdiohgt main() char data[80] FILE fp fp = fopen( data w ) while( gets( data ) = NULL ) strcat( data yenn ) 改行コードの付加

fputs( data fp ) fclose( fp )

36

fputc()fgetc()関数について fputc() ファイルポインタで指定されるファイルに1文字出力します

include ltstdiohgt int fputc( int c FILE fp ) 戻り値正常に出力できた場合には文字 c を返しエラーの場合には EOF を返します fputc() は文字 c をファイルポインタで示されるファイルへ出力します

fgetc() ファイルポインタで指定されるファイルから1文字入力します

include ltstdiohgt int fgetc( FILE fp ) 戻り値正常に入力した場合には入力した文字を返しますエラーやEOFになった場合には

EOF が返されます fgetc() はファイルポインタで指定されるファイルから文字を入力します

ファイルの内容の表示 include ltstdiohgt main() FILE fp int ch char fname[30] printf( Key in Fila name gt ) gets( fname ) fp = fopen( fname r ) while( ( ch = fgetc( fp ) ) = EOF )putchar( ch ) fclose( fp )

その他テキスト中で使用された関数について sin() 三角関数の正弦を計算します

include ltmathhgt double sin(double radian) sinはラジアンを単位とする引数 radianの三角関数を計算します

37

strcpy() 文字列を他の文字列へコピーします

include ltstringhgt char strcpy(char string1const char string2) strcpyは引数 string2の指す文字列を null文字まで含めて引数 string1の指す領域にコピ

ーする strcpyは string1を返します

strcat() ある文字列を他の文字列に加えます

include ltstringhgt char strcat( char dest const char src ) 戻り値連結された文字列へのポインタを返します strcat() はsrc のコピーを dest の最後につけ加えます得られる文字列の長さは

strlen(dest)+strlen(src) になります

fabs() 絶対値の計算をします include ltmathhgt double fabs(double z) fabsは倍精度浮動小数の絶対値を計算して返しますつまりzgt=0であれば z をzlt0であ

れば-zを返します exp() 指数関数を計算します

include ltmathhgt double exp(double z) exp は引数zの指数関数つまりezを返すここではeは自然対数の底を表します対数関

数logの逆関数です

38

付 録 2 コンパイルの方法には大きく分けて第4章の実習で学んだようにデータファイルを作成してお

き ccg でコンパイルさせる方法と実行中に対話型でデータを入力していく方法があります ここでは対話型で実行を進めていく方法を紹介します ただしこの方法は計算(cpu)時間が10秒以内のものに限ります10秒を超える計算(cpu)時

間を要する場合はccg でコンパイルをするようにしてください 第4章実習の(2)(p16)までは同様です

コンパイル

コンピュータに処理を依頼します 60us1234boseicc cc rensyuc

所有するファイルの一覧を見てみます

60us1234boseicc ls -l larr 持っているファイルの一覧を見るコマンドです

-rw-r--r-- 1 60us1234 other 128 4月26日 15時14分 rensyuc -rwxr-xr-x 1 60us1234 other 361 4月26日 15時16分 aout

aout という実行形式のファイルが作成されています

実行

60us1234boseicc aout12 35[リターン] データを入力

1 200000 3500000 4200000 実行結果の出力

60us1234boseicc

注意

aout ファイルは印刷することができません実行結果を印刷する場合にはファイルに落とし てから出力するようにしましょう

60us1234boseicc aout gt kekka12 35[リターン] データを入力

60us1234boseicc more kekka 計算結果の確認 60us1234boseicc lpr kekka 計算結果の印刷

39

Page 11: n 第1章 章立ての部分は、書式(PC入門大見出し)を …第2章 数の表現 2-1 2進数 電子計算機の動作原理は0と1で表される2進数です。また、人間が日常生活で扱っている数

この他にも関数にパラメータを渡す方法としてポインタを使用する方法があります文字列を

複写する関数の場合には次のとおりになります関数名は strcopy()最初の引数には複写先の配列名(配列の先頭番地)次の引数には複写元の配列名(配列の先頭番地)です

include ltstdiohgt main() char src[] = tokai dst[80] void strcopy() strcopy( dst src ) printf( syenn dst )

void strcopy( char str1 char str2 ) while( ( str1++ = str2++ ) = yen0 )

また配列の加算を行う関数の場合にもそれぞれの配列名をパラメータとし関数側でポイン

タ型変数として受け取ることができます

include ltstdiohgt main() int a[10] = 18 24 56 28 96 51 82 34 65 72 UNIXの場合 static intにする int b[10] = 12 54 69 20 26 84 55 20 44 74 UNIXの場合 static intにする

int c[10] int k void matadd() matadd( a b c 10 ) for( k = 0 k lt 10 k++ ) printf( d + d = d yenn a[k] b[k] c[k] )

void matadd( int x int y int z int n ) for( n gt 0 n-- ) z++ = x++ + y++

main()関数では配列名(アドレス定数)として引数に指定されていますが関数 matadd()ではポインタ型の変数として使用することができますしたがって変数 xyz は値を変更することができるようになります

配列 a 変数 x

9

配列 b 変数 y 配列 c 変数 x

3-4 戻り値 関数からの戻り値はreturn 文によって返されます整数型文字型の値を返す関数の場合

にはそれぞれ次のように定義します

int sub( int x ) char sub( int x ) int y char z

return y return z

またポインタを返す関数の場合には次のように定義します

int sub( int x ) char sub( int x ) int y char z

return y return z

return文で式の指定がない場合には何も値を返しません

[プログラム例]

文字列(文字型配列)の中に指定した文字があればその位置をポインタで返し無ければ NULLポインタを返す関数を考えてみます

char strfind( char str char ch ) while( str ) if( str == ch )return str str++ return NULL

いくつかのC言語のマニュアルでは関数の説明を以下のように記述しています sin 機能 正弦を求めます 形式 include ltmathhgt double sin( double x ) このとき関数 sin() の戻り値は double 型でありまた指定する引数も double 型でなけれ

ばなりませんそれと同時にこの関数を使用する場合にはinclude ltmathhgt を指定しなければなりません

10

3-5 変数の通用範囲 関数内で宣言された変数はその関数の中でのみ使用可能です他のプログラムからは使用

することはできません

include ltstdiohgt main() int i 変数 i は関数 main() と sub() とでは それぞれ独立に使用することができます main() で変数 i に設定した値は sub() では参照することはできません sub() 逆にsub() で変数 i に設定した値も main() では参照することはできません

int i

それぞれの関数の中でのみ使用可能な変数をローカル変数と呼び他の関数でも使用可能

な変数をグローバル変数と呼びますいくつかの関数で共通に使用するような場合にはグロー

バル変数を使用します グローバル変数を定義する場合には関数の外で宣言します

include ltstdiohgt int i グローバル変数の定義

main() i = 10

sub() extern int i printf( yenn i = d i )

このプログラムではmain() 関数でグローバル変数に値を設定し関数 sub() で変数の値を

参照しています extern 宣言は変数が他のプログラム内で宣言されていることを示しています宣言の形式

は以下のとおりです extern 型 変数並び

演習5 入力された任意の数の倍数を求めるプログラムを作成しなさい入力する数値は2つ倍数 を求めるための任意の数と倍数の上限値ですここでいう上限値とは任意の数の倍数をどの くらいの数まで求めるかということです

11

3-6 動的変数と静的変数 通常Cで使用される変数はその関数の中だけでのみ使用できる変数ですしたがって関数

が実行するときに関数の中で使用する変数の領域を確保し関数の実行が終るときにその領域

を解放するようにしてメモリを効率的に利用していますこのように関数が実行されるときに確

保される変数を動的変数(auto変数 )と呼びます プログラムの中ではその他に常に存在し使用できる変数を定義することができますそのよ

うな変数は静的変数(static変数 )と呼ばれます

func() int a b static int x y

また static 変数には内部的なリンケージの指定の意味もありますつまり関数の外で変数

を宣言すると自動的にグローバル変数となり他のプログラムからも使用することができるようにな

ります ファイル a ファイル b このような場合にはコンパイル単位が異なっていてもextern 宣言を行うことにより変数 abc

を使用することができますところが関数の外で static 宣言をして定義した変数についてはコンパイル単位が違うプログラムからは使用することができなくなります ファイル a ファイル b 同一コンパイル単位(ファイル)に存在する関数 sub()と subd()では変数 abcを使用することが

できますがコンパイル単位(ファイル)が異なる関数 func()では変数 abcを使用することはできません

int abc sub() abc = 10

func() extern int abc printf( ldquo abc =dyennrdquo abc )

static int abc sub() abc = 10 subd() abc++

func() extern int abc printf( ldquo abc =dyennrdquo abc )

12

3-7 スタック プログラム中にはプログラム領域データ領域の他にスタック領域があり一時的な作業領域と

して使用されています関数間での引数の受渡しの時にもこの領域を使用しますスタック領域に

データを格納することを「スタックに積む」ともいいます基本的にはスタック領域に格納されたデ

ータは最後に格納されたデータから順に取り出されることになります以下に格納が行われたとき

のスタックの状態を示します記号は次に格納すべき位置(スタックポインタの値)を示していま

逆にスタックからデータを取り出すときにはスタックポインタが指している位置の一つ下から取

り出すことになりますスタックからデータを取り出すときのスタックの状態は次のようになります

なり

10

20

10

30

20

10

40

30

20

10

10rarr

格納

20rarr

格納

30rarr

格納

40rarr

格納

40rarr 30rarr

関数を呼び出すときには次

逆にそれぞれの関数から

次のようになります

40

30

20

10

取出

main() z = f1( x y )

のようにパラメータがスタ

戻るときにはパラメータで

30

20

10

取出

f1( int a int b ) c = f2( d e

xの値 yの値

xの値 yの値

13

ックに格納されます

使用していたスタック領域は自動的になく

10

20

)

f2( int p int q ) r = p + q

xの値

eの値 dの値

yの値

xの値 yの値

dの値

eの値

3-8 再帰呼び出し 関数の引数の受渡しがスタックを利用して行われることから自分で自分自身の関数を呼び出

すことができます 以下のプログラムは入力した値の階乗を計算するプログラムです

3の階乗を求めることを考えてみます

return 文によって戻るときは次のようにして値を返します kai( 3 ) 3 kai( 3-1 ) 2 kai( 2-1 ) return 1

6 3 (2 1) 2 1 以上の計算から3=6が導き出されます 再帰呼び出しのことをリカーシブコールともいいます

include ltstdiohgt main() int n m kai() scanf( ldquodrdquoampn ) m = kai( n ) printf( ldquod = dyennrdquo n m )

int kai( int k ) if( k == 1 )return 1 else return k kai( k ndash 1 )

kai( 1 )

darr

return 1

kai( 2 )

darr

2 kai( 2-1 )

kai( 3 )

darr

3 kai( 3-1 )

main()

darr

kai( 3 )

3

2

1

2

3

1

2

3 3

32

32

1

2

1

3

3

演習6 1からnまでの総和を再帰呼び出しを使って計算する関数 sowa() を作りなさい n+(n-1)+ +2+1

14

第4章 実習 この章ではプログラムを実際に入力して実行するまでの手順を実習します

4-1 操作手順 (1)ログイン

[スタート]rarr[プログラム(P)]rarr[ネットワーク] Hostの欄に bosei を記述選択 rarr [Telnet(FreeWare)] を選択します して 「OK」 ボタンをクリックします

UP-UXV (Rel42MP) (bosei) (pts41) login 60us1234 larr 各自のログイン名を入力します Password larr パスワードを入力しても画面は何も変化しません 101 60us1234bosei larr セッションが開設されましたこれをプロンプトといいます この状態でコマンドを入力することができます

(2)プログラムの作成 以下のコマンドを入力しテキストエディタを起動します 60us1234boseicc ng rensyuc

すると下図のようにngエディタの画面になります

15

次のように入力します入力ミスの修正はBSキーで行ないます

include ltstdiohgt main() float abc scanf(f f ampaampb) c=ab printf(f f f yenn abc)

CTRL キーを押しながら XCTRL キーを押しながら C を押しますすると次のメッセージが画面下に表示されます

Save file uhomea60us1234rensyuc (y or n)

このメッセージに対して y と答えます

(3)データの作成 以下のコマンドを入力しテキストエディタを起動します 60us1234boseicc ng rensyud

ngエディタの画面になりますので次のように入力します 12 35

CTRLキーを押しながら XCTRLキーを押しながら C を押します save file uhomea60us1234rensyud (y or n)

このメッセージに対して y と答えます

(4)コンパイルと実行 コンピュータに処理を依頼します 60us1234boseicc ccg rensyu

ジョブを投入しましたジョブの状態を見るコマンドは myjobです

16

130 60us1234boseicc myjob ================================================= NQS (R0220) BATCH REQUEST HOST bosei ================================================= REQUEST ID NAME OWNER QUEUE PRI NICE STT PGRP R --------------- -------- -------- -------- ---- --- --- ------ - 99321bosei STDIN 60us1234 A 31 0 RUN 14161 - ---------------------------------------------------------------- ================================================== NQS (R0220) DEVICE REQUEST HOST bosei ジョブは実行中です

================================================== REQUEST ID NAME OWNER QUEUE PRI SIZE STT -------------------------------------------------------------

所有するファイルの一覧を見てみます

60us1234boseicc ls -l larr 持っているファイルの一覧を見るコマンドです

-rw-r--r-- 1 60us1234 other 4 4月26日 15時14分 rensyud -rw-r--r-- 1 60us1234 other 128 4月26日 15時10分 rensyuc -rwxr-xr-x 1 60us1234 other 361 4月26日 15時16分 rensyul

(5)計算結果の確認

計算結果を画面に表示して確認します 60us1234boseicc more rensyul

(6)印刷

計算結果の印刷を行ないます5号館2階のカフェテリア室にある bosei のプリンタに印刷 されます

60us1234boseicc lpr rensyul

(7)ログアウト セッションを終了します 60us1234boseicc logout

(8)実行の流れ

エラー

プログラムの作成 ログイン コンパイル実行

確 認 印 刷 ログアウト

17

第5章 配列 多数の変数をまとめて宣言する方法として配列があります配列の一つ一つは配列要素と呼

ばれ変数と同じ性格を持っています配列の宣言は型宣言と同時に次のように行います int a[5] 配列 a

a[0]

a[1]

a[2]

a[3]

a[4]

二次元配列(一次元配列を複数集めたもの)を宣言する場合には次のようになります int b[3][4] 配列 b

b[0][0] b[0][1] b[0][2] b[0][3]

b[1][0] b[1][1] b[1][2] b[1][3]

b[2][0] b[2][1] b[2][2] b[2][3]

配列要素に数値を代入する場合は次のようになります b[1][2]=10

5-1 二次元配列要素の初期化 変数の型宣言と同じように配列を宣言するときに初期値も同時に設定することができます

複数のデータがある場合には{}記号でくくって指定します int b[3][4] = 2 4 6 8 1 3 5 7 1 2 3 4

文字型配列の場合には以下のようになりますyen0 は文字列の終わりを表わします char univ[3][7] = T O K A I yen0 S I M I Z U yen0 Y O Y O G I yen0

また文字列定数として初期化することもできますこの場合コンパイル時に自動的に yen0 が付加されます

char univ[3][7] = TOKAI SIMIZU YOYOGI

18

[プログラム例] 二次元配列のタテヨコを加算するプログラム

include ltstdiohgt main() int mat[4][3]=123456789101112 int ijytotalttotal[3]total=0 for(j=0jlt3j++)ttotal[j]=0 for (i=0ilt4i++) ytotal=0 for(j=0jlt3j++) ytotal += mat[i][j] ttotal[j] += mat[i][j] total += mat[i][j] printf(3dmat[i][j]) printf( 3dyennytotal) printf(yenn) for(j=0jlt3j++)printf(3dttotal[j]) printf( 3dyenntotal)

[実行結果]

1 2 3 6 4 5 6 15 7 8 9 24 10 11 12 33 22 26 30 78

演習7

a)以下の配列はどのように初期化されるか答えなさい char errmsg[2][15] = Divide Error Overflow Error

b)九九の計算を2次元配列を使って求めなさい

19

第6章 ポインタ型変数 C言語では値を記憶するための変数だけではなく変数または定数の番地を記憶するため

のポインタ型変数を宣言することができますポインタとはデータ項目の一種で「記憶装置(メモ

リ)上の格納番地(アドレス)を指すデータ項目」です アドレス コンピュータの中ではデータ項目の格納番地のことをアドレス(住所)と呼びます 例えば記憶装置という名前のとてつもなく大きなマンションがあるとしますその中から Aさんを捜すときは部屋番号を参照しますマンションでは部屋番号で住居人を参照し ているのと同じようにコンピュータでは記憶装置上に確保された変数は格納番地 (アドレス)で管理されています

マンション 部屋番号 記憶装置 格納番地

Aさん Int a Bさん Cさん AAAさん BBBさん CCCさん

1号室

2号室

3号室

100号室

200号室

300号室

100番地

200番地

300番地

1000番地

2000番地

3000番地

Int b Int c float aaafloat bbbfloat ccc

ポインタ ポインタとは「指し示すもの」の意ですがC言語では記憶装置上のアドレスを指し示す もののことです上のマンションの例では部屋番号を格納するデータ項目ということに なりますAAAさんは100号室に住んでいます100という値をポインタのデータ項目に 記憶するとそのデータ項目は間接的にAAAさんを指すことになります

6-1 ポインタ型変数の宣言および参照 通常の変数と区別するために型宣言時に変数名の前に記号を付けて宣言します int a 整数型ポインタ変数 int b 整数型変数

変数 a は整数型の値を記憶するのではなく整数型の値を持つ変数などの番地を記憶する変数ですまた変数 b は通常の整数型の値を記憶するための変数です

20

include ltstdiohgt main() int a b c a はポインタ型の変数b c は整数型の変数 b = 12 変数 b に値 12 を代入します a = ampb 変数 a には変数 b の番地が代入されます c = a + 10 変数 a の指す変数(b)の内容と10の加算です つまり12 + 10 を変数 c に代入します

変数の型宣言において変数名に記号を付けることによりその変数はポインタ型の変数と

なりますポインタ型の変数は変数名のみを指定した場合には単にその変数の値(通常はメモリ

の番地)を表します変数名に記号を付けて使用した場合にはその変数が指し示している変

数の内容を表します c = a ポインタ型変数 a が指している値を変数 c に代入

ポインタ型の変数に番地を記憶させるためにはプログラム例のように変数名の前に記号を

指定します変数名 によって変数の番地(アドレス)を表します a = ampb 変数 b の番地をポインタ型変数 a に代入します

ポインタ型変数の型はポインタ型変数が指し示す先の変数の型を表しています int a 変数 a 整数型の値 float x 変数 x 実数型の値 char c 変数 c 文字型の値

6-2 ポインタ型変数の初期化 ポインタ型変数も型宣言のときに変数を初期化することができます特に文字型のポインタ変

数の場合によく使います char str = TOKAI University

ポインタ型変数 str は文字列定数 TOKAI University の最初の文字が格納されている番地を初期値として持つことになります

変数 str TOKAI University 文字列定数

[プログラム例]

(1)文字型配列 putchar() 関数を使って一次元の文字型配列を出力します include ltstdiohgt main() char str[6] = TOKAI int i for( i = 0 str[i] = yen0 i++ ) putchar( str[i] )

21

ポインタを使用した場合には以下のようになります include ltstdiohgt main() char str[6] = TOKAI char chp for( chp = str chp = yen0 chp++ ) putchar( chp )

chp str T [0] O K A I yen0 [5]

参照する変数 配列の表現 ポインタの表現 実際のアドレス 1番目の数 str[0] chp CHP 2番目の数 str[1] (chp+1) CHP+1 n番目の数 str[n-1] (chp+n-1) CHP+n-1 6番目の数 str[5] (chp+5) CHP+5

注意実際のアドレス CHPは実行時に決定されます

(2)二次元文字型配列 二次元の文字型配列に定数を設定しそれを出力するプログラムです文字型配列を使用す

ると次のとおりになります include ltstdiohgt main() char str[5][40] = TOKAI shounan campus NEC DEC int i for( i = 0 i lt 5 i++ ) printf( yenns str[i] )

40 バイト str TOKAI shounan campus NEC DEC

22

ポインタ型配列を使用すると次のとおりになります include ltstdiohgt main() char str[6] = TOKAI shounan campus NEC DEC NULL char chp for( chp = str chp = NULL chp++ ) printf( yenns chp ) str

chp 番地 TOKAI 番地 shounan 番地 campus 番地 NEC 番地 DEC

NULL

演習8 キーボードまたはデータファイルから読み込んだ文字列中にrsquoArsquo があったら rsquoarsquo に変換 するプログラムを配列とポインタを使って書きなさい

23

第7章 構造体共用体 7-1 構造体

プログラムの規模が大きくなるにつれて多数の intや floatcharなどのデータ型を扱うようになり複雑になってきますそこで多数のデータを1つにまとめて簡単に扱える機能が構造体です 構造体について住所録のデータを例にあげて考えてみます

住所録の個人データとして氏名住所電話番号年齢の項目を一つのデータとします これをC言語で変数の定義をすると次のようになります 氏名東海太郎 char name[30] 住所平塚市北金目1117 char address[30] 電話番号0463-58-1211 char tel[20] 年齢30 int age 個人の住所録データ C言語での表現 このような住所録の個人データを1つにまとめて新しいデータとして定義する機能を構造体と言

います struct 構造体タグ名 構造体メンバーの並び

「struct」は構造体を表すキーワードです 「構造体タグ名」は構造体の型枠を宣言しますここは自由に名前を定義することができ ます 「構造体メンバーの並び」は構造体の要素です複数指定できます

個人の住所録のデータを構造体で宣言すると次のようになります

struct jusho char name[30] char address[30] 構造体のメンバーの並び char tel[20] (複数可)

int age

上記の宣言では構造体の形式を宣言しているだけでメモリ中で実際の領域を確保している

わけではありません実際に領域を確保するためには次のように定義します

struct 構造体タグ名 構造体名

したがって構造体名を jdata とすると次のように指定します

struct jusho jdata

構造体 jdataは次のように構造体タグ jushoの形式で領域を確保します

24

Jdata name[30]

address[30] tel[20] age

(1)構造体の参照

プログラム中で構造体中のメンバーを参照する場合には次のように指定します 構造体名メンバー名

したがって「名前」を参照したいときには次のように指定します

jdataname

[プログラム例]

名前住所電話番号年齢を定義しそれを印字します include ltstdiohgt include ltstringhgt main() struct jusho char name[30] char address[30] char tel[20] int age struct jusho jdata strcpy( jdataname 東海 太郎) strcpy( jdataaddress 平塚市北金目1117)

strcpy( jdatatel 0463-58-1211) jdataage = 30 printf(yenn氏名 = syenn jdataname) printf(yenn住所 = syenn jdataaddress) printf(yenn電話番号= syenn jdatatel) printf(yenn年齢 = dyenn jdataage)

また構造体の形式の定義と領域の確保は次のように同時におこなうことができます

struct 構造体タグ名 構造体メンバーの並び 構造体名

struct jusho struct jusho char name[30] char name[30] char address[30] char address[30] char tel[30] = char tel[30] int age 同じ int age

jdata struct jusho jdata

型宣言と同時にメモリ上に領域を確保する方法 後からメモリ上に領域を確保する方法

25

(2) 構造体配列 住所録データの場合その中に入るデータは1件ではありませんやはり100件200件のデ

ータが必要になる場合がありますこのように個人単位のデータを多数扱う場合には構造体を配

列として宣言することができます 次の例は個人のデータを100個用意するために構造体を配列として宣言しています struct jusho jdata[100] jdata[0] name[30] address[30] tel[20] age

jdata[99 ] name[30] address[30] tel[20] age

(3)構造体配列の参照

プログラム中で構造体配列中のメンバーを参照する場合には次のように指定します 構造体名[要素番号]メンバー名

したがって10件目の人の「名前」を参照したいときには次のように指定します

jdata[10]name

[プログラム例]

名前住所電話番号年齢を定義しそれを印字します include ltstdiohgt include ltstringhgt main() struct jusho char name[30] char address[30] char tel[20] int age jdata[100] strcpy( jdata[10]name 東海 太郎) strcpy( jdata[10]address 平塚市北金目1117)

strcpy( jdata[10]tel 0463-58-1211) jdata[10]age = 30 printf(yenn氏名 = syenn jdata[10]name) printf(yenn住所 = syenn jdata[10]address) printf(yenn電話番号= syenn jdata[10]tel) printf(yenn年齢 = dyenn jdata[10]age)

26

(4) 構造体のポインタ 変数と同じように構造体へのポインタも定義することができます

変数へのポインタ例 構造体へのポインタ例 またポインタを使用して構造体メンバーを参照するには次のように -> 記号を使って指

定します ポインタ変数名 -> メンバー名

[プログラム例]

名前住所電話番号年齢を定義しそれを印字します include ltstdiohgt include ltstringhgt main() struct jusho char name[30] char address[30] char tel[20] int age jdatakp kp = ampjdata strcpy( kp-gtname 東海 太郎)

strcpy( kp-gtaddress 平塚市北金目1117)

strcpy( kp-gttel 0463-58-1211) kp-gtage = 30 printf(yenn氏名 = syenn kp-gtname) printf(yenn住所 = syenn kp-gtaddress) printf(yenn電話番号= syenn kp-gttel) printf(yenn年齢 = dyenn kp-gtage)

kp jdata

name[30] ポインタ型の変数 address[30]

tel[20]

構造体へのポインタを記憶 age

することができます

int a int b b = ampa

struct name jname struct name np np = ampname

27

7-2 共用体 共用体は構造体と同じようにして宣言しますが共用体は複数のデータ型を同一のアドレスに

割り当てる方法です union 共用体タグ名 共用体メンバーの並び

「union」は共用体を表すキーワードです 「共用体タグ名」は共用体の型枠の名前を宣言しますここは自由に名前を定義することがで

きます 「共用体メンバーの並び」は共用体の要素です複数指定できます

共用体の宣言の例を次に示します

union c_tag int a char b

共用体 cは次のように共用体タグ c_tagの形式で領域を確保します共用体はメモリ上に領域を確保するときは ab ともに同じ領域に割り付けられます これはab という2つのデータが同時に存在するわけではなく cを異なるデータ abで共有す

ることを表しています c a b

上記の宣言だけでは共用体の形式を宣言しているだけでメモリ中で実際の領域を確保して

いるわけではありません実際に領域を確保するためには次のように定義します union 構造体タグ名 構造体名

したがって共用体名を c とすると次のように指定します

union c_tag c

(1)共用体の参照

プログラム中で共用体中のメンバーを参照する場合には次のように指定します 共用体名メンバー名

したがって「a」または「b」を参照したいときには次のように指定します

ca (int 型) cb (char 型)

メンバー参照方法によって int型として使ったりchar型として利用することができます

28

[プログラム例]

includeltstdiohgt main() union data char a short b int c chk chkc = 0x12345678 printf( char a xyennchka) printf( short b xyennchkb) printf( int c xyennchkc)

chkb(int 型) chkb(short 型) chka(char 型) 12 12 12 34 34 56 78

29

第8章 アルゴリズム コンピュータに何か仕事をさせようとするときは仕事を具体的に実行するための処理や動作

の手順が必要ですこの「手順」がアルゴリズムです アルゴリズムを考えるときは解くべき問題をはっきりと定義することが必要です

8-1 ソート ソートとは与えられたデータを小さい順または大きい順に並べ換えることですソート方法は

いくつかありますが基本的な方法でソートするアルゴリズムを紹介します

includeltstdiohgt int data[10] main()

int data_in() sort() data_in() sort() int data_in() データ入力関数

int a printf(数値入力yenn)

for(a=0alt=9a++) printf( [d]a+1) scanf(dampdata[a]) int sort() ソート処理を行う関数

int cont1cont2tmp1tmp2mim for(cont1=0 cont1lt=9 cont1++) mim=data[cont1] tmp1=cont1 for(cont2=cont1+1 cont2lt=9 cont2++) if(data[cont2] lt mim) mim=data[cont2] tmp1=cont2 tmp2 = data[cont1] data[cont1] = data[tmp1] data[tmp1] = tmp2 printf(結果 yenn)

for (cont1 = 0 cont1 lt= 9 cont1++) printf(d yenn data[cont1])

30

第9章 プリプロセッサ C言語にはプログラムの中でコンパイルについての指示を行う「プリプロセッサ」という機能が

ありますまたプリプロセッサとはコンパイルする前に実行されるためその意味のとおり「前処理」 と呼ばれていますここでは代表的なものをいくつか説明します

9-1 ファイルの挿入 ソースプログラム中に指定されたファイルを挿入します

include ltstdiohgt helliphellip 標準ディレクトリを探します include progh helliphellip 現在のディレクトリを探しなければ標準ディレクトリを探します

includeltstdiohgt によって組み込まれた define EOF (-1) define EOF (-1) define define helliphelliphelliphellip 組み込み helliphelliphelliphellip

main() stdiohファイル

int helliphelliphelliphellip helliphelliphelliphellip

ソースファイル

9-2 文字の置換 プログラム中に使われている文字列を別の文字列に置き換えます

include ltstdiohgt define TRUE 1 define EOF (-1) main() define helliphellip helliphellip

while(TRUE) define TRUE 1 置き換え main() helliphellip helliphellip while(1)

break helliphelliphellip

31

9-3 条件によるコンパイル 識別子が定義されているか否かを判断しコンパイルする範囲を指定します

include ltstdiohgt define UNIX main() ifdef UNIX printf( UNIX yenn) else printf(MS-DOSyenn) endif

include ltstdiohgt define OS UNIX main() if OS == UNIX printf( UNIX yenn) else printf(MS-DOSyenn) endif

32

付 録 1 puts()gets()関数について

行単位に入出力を行う場合には puts() gets() 関数を用います

puts() 標準出力に文字列を出力します

include ltstdiohgt int puts( char s ) puts() は NULL で終る文字列 s を標準出力に出力し最後に改行文字 yenn も出力しま

gets() 標準入力から文字列を入力します

include ltstdiohgt char gets( char s ) 戻り値正常に入力した場合には引数 s の値が返されますエラーやEOFになった場合に

は NULL が返されます gets() は標準入力から復帰文字で終る文字列を入力しs に格納しますこのとき最後の復

帰文字は NULL文字に変更されます

入力行の出力 標準入力から gets() で入力したデータには改行コードは含まれませんまた標準出力へ

puts() で出力を行う場合には必ず改行コードが付加されますgets() を実行したときの戻り値としてファイルの終端を検出した場合には EOF ではなく NULL が返されますので注意して下さい

include ltstdiohgt main() char data[80] while( gets( data ) = NULL )puts( data )

putchar()getchar()関数について putchar() 標準出力に文字を出力します

include ltstdiohgt int putchar(int c ) 戻り値正常に出力できた場合には文字cをエラーの場合にはEOFを返します

33

getchar() 標準入力から文字を入力します

include ltstdiohgt int getchar(void) 戻り値正常に入力した場合には読み込んだ文字を int 型に変換して返しますまたファイ

ルエンドエラーの場合にはEOFを返します

標準入力標準出力

標準入力標準出力はプログラムが開始されるときにはオープンされていますそれぞれのフ

ァイルポインタは stdin stdout になっていますfopen() fclose() をせずとも使用することができます

scanf() 標準出力ストリームからテキストを読み込み解釈します include ltstdiohgt int scanf( const char format [ address ] ) 戻り値正しくスキャンし変換し格納した入力フィールドの数を返しますファイルエンドを読

み込んだ場合は戻り値は EOF となります値を格納したフィールドがなかった場合は戻り値は0となります

一連の入力フィールドをスキャンして1度に1文字ずつストリーム stdin から文字を読み込み

ます次に引き数 format によって指される書式文字列中の書式指定に従って各フィールドを書式化します最後にformat の後に続く各引き数が示しているアドレスに書式化した入力を格納していきます書式文字列中の書式指定の個数はその後に続くアドレスの数と同じでな

ければなりません 書式指定[入力幅][型指定文字] 入力幅 読むべき文字数の最大値 型指定文字 次のとおりです 型指定文字 期待される入力 引き数の型 d 10進整数 int へのポインタ( int arg ) x 16進整数 int へのポインタ( int arg ) f 浮動小数点数 float へのポインタ( float arg ) s 文字列 文字配列へのポインタ( char arg[] ) c 文字 文字へのポインタ( char arg )

printf() フォーマットを指定してテキスト標準出力ストリームに出力します include ltstdiohgt int printf( const char format [ argument ] ) 戻り値出力したバイト数を返しますエラーの場合は EOF を返します

34

format によって指される書式文字列中の書式指定をformat の後に続く各引き数に適用し

書式化されたデータを stdout に出力します書式指定は後に続く引き数と同じ数だけなければなりません

書式指定[印字幅][精度][型指定文字] 印字幅 印字する最小文字数 精度 印字する最大文字数 型指定文字 つぎのとおりです 型指定文字 入力引き数 出力の書式 d 整数 符号付き10進整数 x 整数 符号無し16進整数 f 浮動小数点 符号付きの dddddddd形式の値 c 文字 1個の文字 s 文字列ポインタ ヌル文字に出会うか精度に達するまで 文字をプリントする

fopen()fclose()関数について fopen() ファイルをオープンします

include ltstdiohgt FILE fopen( char filename char mode ) 戻り値正常にファイルのオープンができたらファイルポインタを返しますエラーがあった場

合には NULLを返します 文字列 filename で指定されたファイルをオープンしますオープン後の入出力のモードに

ついては文字列 mode で指定しますmode に指定できる文字は以下のとおりです r 入力モードでオープンします w 出力モードでオープンします a 存在するファイルに追加して出力するモードでオープンします r+ 既に作成してあるファイルを更新(入力出力)するモードでオープンします w+ 新しく作成するファイルを更新モードでオープンします a+ 既に作成してあるファイルの終りから更新用に作成します

以上の文字に b をつけ加えることによりバイナリモードで入出力することができるようになり

ます rb バイナリの入力モードでオープンします wb バイナリの出力モードでオープンします ab 存在するファイルに追加して出力するモード(バイナリ)でオープンします

fclose() 既にオープンしてあるファイルをクローズします include ltstdiohgt fclose( FILE fp ) 既にオープンしているファイルをクローズしますパラメータには fopen() 関数により返された

ファイルポインタを指定します

35

テキストモードとバイナリモード 行の最後はテキストモードの場合改行コードのみとなりバイナリモードの場合には復帰

コードと改行コードの組合わせになります行の最後としてテキストファイルには復帰コード改行

コードが書かれていますがテキストモードでオープンした場合には入力すると改行コードのみに

変換されて入力されますバイナリモードの場合には復帰コード改行コードがそれぞれ入力され

ます

fputs()fgets()関数について fputs() ファイルポインタで指定されるファイルに文字列を出力します

include ltstdiohgt

int fputs( char s FILE fp ) fputs() は NULL で終る文字列 s をファイルポインタに示されるファイルへ出力しますputs()

と違い最後に改行文字 yenn を出力することはありません

fgets() ファイルポインタで指定されるファイルから文字列を入力します include ltstdiohgt char fgets( char s int n FILE fp ) 戻り値正常に入力した場合には引数 s の値が返されますエラーやEOFになった場合に

は NULL が返されます fgets() はファイルポインタで指定されるファイルから ( n - 1 ) 文字または改行文字までの

文字列を入力しs に格納しますgets() と異なり最後に入力された改行文字は NULL 文字に変更されません

標準入力から入力しファイルへ出力する ファイルへ出力あるいは入力を行う場合には改行コードの変換(入力の場合の削除出力の

場合の付加)はされませんしたがって標準入力から入力しファイルへ出力する場合には改行

コードを付加しなければなりません include ltstdiohgt main() char data[80] FILE fp fp = fopen( data w ) while( gets( data ) = NULL ) strcat( data yenn ) 改行コードの付加

fputs( data fp ) fclose( fp )

36

fputc()fgetc()関数について fputc() ファイルポインタで指定されるファイルに1文字出力します

include ltstdiohgt int fputc( int c FILE fp ) 戻り値正常に出力できた場合には文字 c を返しエラーの場合には EOF を返します fputc() は文字 c をファイルポインタで示されるファイルへ出力します

fgetc() ファイルポインタで指定されるファイルから1文字入力します

include ltstdiohgt int fgetc( FILE fp ) 戻り値正常に入力した場合には入力した文字を返しますエラーやEOFになった場合には

EOF が返されます fgetc() はファイルポインタで指定されるファイルから文字を入力します

ファイルの内容の表示 include ltstdiohgt main() FILE fp int ch char fname[30] printf( Key in Fila name gt ) gets( fname ) fp = fopen( fname r ) while( ( ch = fgetc( fp ) ) = EOF )putchar( ch ) fclose( fp )

その他テキスト中で使用された関数について sin() 三角関数の正弦を計算します

include ltmathhgt double sin(double radian) sinはラジアンを単位とする引数 radianの三角関数を計算します

37

strcpy() 文字列を他の文字列へコピーします

include ltstringhgt char strcpy(char string1const char string2) strcpyは引数 string2の指す文字列を null文字まで含めて引数 string1の指す領域にコピ

ーする strcpyは string1を返します

strcat() ある文字列を他の文字列に加えます

include ltstringhgt char strcat( char dest const char src ) 戻り値連結された文字列へのポインタを返します strcat() はsrc のコピーを dest の最後につけ加えます得られる文字列の長さは

strlen(dest)+strlen(src) になります

fabs() 絶対値の計算をします include ltmathhgt double fabs(double z) fabsは倍精度浮動小数の絶対値を計算して返しますつまりzgt=0であれば z をzlt0であ

れば-zを返します exp() 指数関数を計算します

include ltmathhgt double exp(double z) exp は引数zの指数関数つまりezを返すここではeは自然対数の底を表します対数関

数logの逆関数です

38

付 録 2 コンパイルの方法には大きく分けて第4章の実習で学んだようにデータファイルを作成してお

き ccg でコンパイルさせる方法と実行中に対話型でデータを入力していく方法があります ここでは対話型で実行を進めていく方法を紹介します ただしこの方法は計算(cpu)時間が10秒以内のものに限ります10秒を超える計算(cpu)時

間を要する場合はccg でコンパイルをするようにしてください 第4章実習の(2)(p16)までは同様です

コンパイル

コンピュータに処理を依頼します 60us1234boseicc cc rensyuc

所有するファイルの一覧を見てみます

60us1234boseicc ls -l larr 持っているファイルの一覧を見るコマンドです

-rw-r--r-- 1 60us1234 other 128 4月26日 15時14分 rensyuc -rwxr-xr-x 1 60us1234 other 361 4月26日 15時16分 aout

aout という実行形式のファイルが作成されています

実行

60us1234boseicc aout12 35[リターン] データを入力

1 200000 3500000 4200000 実行結果の出力

60us1234boseicc

注意

aout ファイルは印刷することができません実行結果を印刷する場合にはファイルに落とし てから出力するようにしましょう

60us1234boseicc aout gt kekka12 35[リターン] データを入力

60us1234boseicc more kekka 計算結果の確認 60us1234boseicc lpr kekka 計算結果の印刷

39

Page 12: n 第1章 章立ての部分は、書式(PC入門大見出し)を …第2章 数の表現 2-1 2進数 電子計算機の動作原理は0と1で表される2進数です。また、人間が日常生活で扱っている数

3-4 戻り値 関数からの戻り値はreturn 文によって返されます整数型文字型の値を返す関数の場合

にはそれぞれ次のように定義します

int sub( int x ) char sub( int x ) int y char z

return y return z

またポインタを返す関数の場合には次のように定義します

int sub( int x ) char sub( int x ) int y char z

return y return z

return文で式の指定がない場合には何も値を返しません

[プログラム例]

文字列(文字型配列)の中に指定した文字があればその位置をポインタで返し無ければ NULLポインタを返す関数を考えてみます

char strfind( char str char ch ) while( str ) if( str == ch )return str str++ return NULL

いくつかのC言語のマニュアルでは関数の説明を以下のように記述しています sin 機能 正弦を求めます 形式 include ltmathhgt double sin( double x ) このとき関数 sin() の戻り値は double 型でありまた指定する引数も double 型でなけれ

ばなりませんそれと同時にこの関数を使用する場合にはinclude ltmathhgt を指定しなければなりません

10

3-5 変数の通用範囲 関数内で宣言された変数はその関数の中でのみ使用可能です他のプログラムからは使用

することはできません

include ltstdiohgt main() int i 変数 i は関数 main() と sub() とでは それぞれ独立に使用することができます main() で変数 i に設定した値は sub() では参照することはできません sub() 逆にsub() で変数 i に設定した値も main() では参照することはできません

int i

それぞれの関数の中でのみ使用可能な変数をローカル変数と呼び他の関数でも使用可能

な変数をグローバル変数と呼びますいくつかの関数で共通に使用するような場合にはグロー

バル変数を使用します グローバル変数を定義する場合には関数の外で宣言します

include ltstdiohgt int i グローバル変数の定義

main() i = 10

sub() extern int i printf( yenn i = d i )

このプログラムではmain() 関数でグローバル変数に値を設定し関数 sub() で変数の値を

参照しています extern 宣言は変数が他のプログラム内で宣言されていることを示しています宣言の形式

は以下のとおりです extern 型 変数並び

演習5 入力された任意の数の倍数を求めるプログラムを作成しなさい入力する数値は2つ倍数 を求めるための任意の数と倍数の上限値ですここでいう上限値とは任意の数の倍数をどの くらいの数まで求めるかということです

11

3-6 動的変数と静的変数 通常Cで使用される変数はその関数の中だけでのみ使用できる変数ですしたがって関数

が実行するときに関数の中で使用する変数の領域を確保し関数の実行が終るときにその領域

を解放するようにしてメモリを効率的に利用していますこのように関数が実行されるときに確

保される変数を動的変数(auto変数 )と呼びます プログラムの中ではその他に常に存在し使用できる変数を定義することができますそのよ

うな変数は静的変数(static変数 )と呼ばれます

func() int a b static int x y

また static 変数には内部的なリンケージの指定の意味もありますつまり関数の外で変数

を宣言すると自動的にグローバル変数となり他のプログラムからも使用することができるようにな

ります ファイル a ファイル b このような場合にはコンパイル単位が異なっていてもextern 宣言を行うことにより変数 abc

を使用することができますところが関数の外で static 宣言をして定義した変数についてはコンパイル単位が違うプログラムからは使用することができなくなります ファイル a ファイル b 同一コンパイル単位(ファイル)に存在する関数 sub()と subd()では変数 abcを使用することが

できますがコンパイル単位(ファイル)が異なる関数 func()では変数 abcを使用することはできません

int abc sub() abc = 10

func() extern int abc printf( ldquo abc =dyennrdquo abc )

static int abc sub() abc = 10 subd() abc++

func() extern int abc printf( ldquo abc =dyennrdquo abc )

12

3-7 スタック プログラム中にはプログラム領域データ領域の他にスタック領域があり一時的な作業領域と

して使用されています関数間での引数の受渡しの時にもこの領域を使用しますスタック領域に

データを格納することを「スタックに積む」ともいいます基本的にはスタック領域に格納されたデ

ータは最後に格納されたデータから順に取り出されることになります以下に格納が行われたとき

のスタックの状態を示します記号は次に格納すべき位置(スタックポインタの値)を示していま

逆にスタックからデータを取り出すときにはスタックポインタが指している位置の一つ下から取

り出すことになりますスタックからデータを取り出すときのスタックの状態は次のようになります

なり

10

20

10

30

20

10

40

30

20

10

10rarr

格納

20rarr

格納

30rarr

格納

40rarr

格納

40rarr 30rarr

関数を呼び出すときには次

逆にそれぞれの関数から

次のようになります

40

30

20

10

取出

main() z = f1( x y )

のようにパラメータがスタ

戻るときにはパラメータで

30

20

10

取出

f1( int a int b ) c = f2( d e

xの値 yの値

xの値 yの値

13

ックに格納されます

使用していたスタック領域は自動的になく

10

20

)

f2( int p int q ) r = p + q

xの値

eの値 dの値

yの値

xの値 yの値

dの値

eの値

3-8 再帰呼び出し 関数の引数の受渡しがスタックを利用して行われることから自分で自分自身の関数を呼び出

すことができます 以下のプログラムは入力した値の階乗を計算するプログラムです

3の階乗を求めることを考えてみます

return 文によって戻るときは次のようにして値を返します kai( 3 ) 3 kai( 3-1 ) 2 kai( 2-1 ) return 1

6 3 (2 1) 2 1 以上の計算から3=6が導き出されます 再帰呼び出しのことをリカーシブコールともいいます

include ltstdiohgt main() int n m kai() scanf( ldquodrdquoampn ) m = kai( n ) printf( ldquod = dyennrdquo n m )

int kai( int k ) if( k == 1 )return 1 else return k kai( k ndash 1 )

kai( 1 )

darr

return 1

kai( 2 )

darr

2 kai( 2-1 )

kai( 3 )

darr

3 kai( 3-1 )

main()

darr

kai( 3 )

3

2

1

2

3

1

2

3 3

32

32

1

2

1

3

3

演習6 1からnまでの総和を再帰呼び出しを使って計算する関数 sowa() を作りなさい n+(n-1)+ +2+1

14

第4章 実習 この章ではプログラムを実際に入力して実行するまでの手順を実習します

4-1 操作手順 (1)ログイン

[スタート]rarr[プログラム(P)]rarr[ネットワーク] Hostの欄に bosei を記述選択 rarr [Telnet(FreeWare)] を選択します して 「OK」 ボタンをクリックします

UP-UXV (Rel42MP) (bosei) (pts41) login 60us1234 larr 各自のログイン名を入力します Password larr パスワードを入力しても画面は何も変化しません 101 60us1234bosei larr セッションが開設されましたこれをプロンプトといいます この状態でコマンドを入力することができます

(2)プログラムの作成 以下のコマンドを入力しテキストエディタを起動します 60us1234boseicc ng rensyuc

すると下図のようにngエディタの画面になります

15

次のように入力します入力ミスの修正はBSキーで行ないます

include ltstdiohgt main() float abc scanf(f f ampaampb) c=ab printf(f f f yenn abc)

CTRL キーを押しながら XCTRL キーを押しながら C を押しますすると次のメッセージが画面下に表示されます

Save file uhomea60us1234rensyuc (y or n)

このメッセージに対して y と答えます

(3)データの作成 以下のコマンドを入力しテキストエディタを起動します 60us1234boseicc ng rensyud

ngエディタの画面になりますので次のように入力します 12 35

CTRLキーを押しながら XCTRLキーを押しながら C を押します save file uhomea60us1234rensyud (y or n)

このメッセージに対して y と答えます

(4)コンパイルと実行 コンピュータに処理を依頼します 60us1234boseicc ccg rensyu

ジョブを投入しましたジョブの状態を見るコマンドは myjobです

16

130 60us1234boseicc myjob ================================================= NQS (R0220) BATCH REQUEST HOST bosei ================================================= REQUEST ID NAME OWNER QUEUE PRI NICE STT PGRP R --------------- -------- -------- -------- ---- --- --- ------ - 99321bosei STDIN 60us1234 A 31 0 RUN 14161 - ---------------------------------------------------------------- ================================================== NQS (R0220) DEVICE REQUEST HOST bosei ジョブは実行中です

================================================== REQUEST ID NAME OWNER QUEUE PRI SIZE STT -------------------------------------------------------------

所有するファイルの一覧を見てみます

60us1234boseicc ls -l larr 持っているファイルの一覧を見るコマンドです

-rw-r--r-- 1 60us1234 other 4 4月26日 15時14分 rensyud -rw-r--r-- 1 60us1234 other 128 4月26日 15時10分 rensyuc -rwxr-xr-x 1 60us1234 other 361 4月26日 15時16分 rensyul

(5)計算結果の確認

計算結果を画面に表示して確認します 60us1234boseicc more rensyul

(6)印刷

計算結果の印刷を行ないます5号館2階のカフェテリア室にある bosei のプリンタに印刷 されます

60us1234boseicc lpr rensyul

(7)ログアウト セッションを終了します 60us1234boseicc logout

(8)実行の流れ

エラー

プログラムの作成 ログイン コンパイル実行

確 認 印 刷 ログアウト

17

第5章 配列 多数の変数をまとめて宣言する方法として配列があります配列の一つ一つは配列要素と呼

ばれ変数と同じ性格を持っています配列の宣言は型宣言と同時に次のように行います int a[5] 配列 a

a[0]

a[1]

a[2]

a[3]

a[4]

二次元配列(一次元配列を複数集めたもの)を宣言する場合には次のようになります int b[3][4] 配列 b

b[0][0] b[0][1] b[0][2] b[0][3]

b[1][0] b[1][1] b[1][2] b[1][3]

b[2][0] b[2][1] b[2][2] b[2][3]

配列要素に数値を代入する場合は次のようになります b[1][2]=10

5-1 二次元配列要素の初期化 変数の型宣言と同じように配列を宣言するときに初期値も同時に設定することができます

複数のデータがある場合には{}記号でくくって指定します int b[3][4] = 2 4 6 8 1 3 5 7 1 2 3 4

文字型配列の場合には以下のようになりますyen0 は文字列の終わりを表わします char univ[3][7] = T O K A I yen0 S I M I Z U yen0 Y O Y O G I yen0

また文字列定数として初期化することもできますこの場合コンパイル時に自動的に yen0 が付加されます

char univ[3][7] = TOKAI SIMIZU YOYOGI

18

[プログラム例] 二次元配列のタテヨコを加算するプログラム

include ltstdiohgt main() int mat[4][3]=123456789101112 int ijytotalttotal[3]total=0 for(j=0jlt3j++)ttotal[j]=0 for (i=0ilt4i++) ytotal=0 for(j=0jlt3j++) ytotal += mat[i][j] ttotal[j] += mat[i][j] total += mat[i][j] printf(3dmat[i][j]) printf( 3dyennytotal) printf(yenn) for(j=0jlt3j++)printf(3dttotal[j]) printf( 3dyenntotal)

[実行結果]

1 2 3 6 4 5 6 15 7 8 9 24 10 11 12 33 22 26 30 78

演習7

a)以下の配列はどのように初期化されるか答えなさい char errmsg[2][15] = Divide Error Overflow Error

b)九九の計算を2次元配列を使って求めなさい

19

第6章 ポインタ型変数 C言語では値を記憶するための変数だけではなく変数または定数の番地を記憶するため

のポインタ型変数を宣言することができますポインタとはデータ項目の一種で「記憶装置(メモ

リ)上の格納番地(アドレス)を指すデータ項目」です アドレス コンピュータの中ではデータ項目の格納番地のことをアドレス(住所)と呼びます 例えば記憶装置という名前のとてつもなく大きなマンションがあるとしますその中から Aさんを捜すときは部屋番号を参照しますマンションでは部屋番号で住居人を参照し ているのと同じようにコンピュータでは記憶装置上に確保された変数は格納番地 (アドレス)で管理されています

マンション 部屋番号 記憶装置 格納番地

Aさん Int a Bさん Cさん AAAさん BBBさん CCCさん

1号室

2号室

3号室

100号室

200号室

300号室

100番地

200番地

300番地

1000番地

2000番地

3000番地

Int b Int c float aaafloat bbbfloat ccc

ポインタ ポインタとは「指し示すもの」の意ですがC言語では記憶装置上のアドレスを指し示す もののことです上のマンションの例では部屋番号を格納するデータ項目ということに なりますAAAさんは100号室に住んでいます100という値をポインタのデータ項目に 記憶するとそのデータ項目は間接的にAAAさんを指すことになります

6-1 ポインタ型変数の宣言および参照 通常の変数と区別するために型宣言時に変数名の前に記号を付けて宣言します int a 整数型ポインタ変数 int b 整数型変数

変数 a は整数型の値を記憶するのではなく整数型の値を持つ変数などの番地を記憶する変数ですまた変数 b は通常の整数型の値を記憶するための変数です

20

include ltstdiohgt main() int a b c a はポインタ型の変数b c は整数型の変数 b = 12 変数 b に値 12 を代入します a = ampb 変数 a には変数 b の番地が代入されます c = a + 10 変数 a の指す変数(b)の内容と10の加算です つまり12 + 10 を変数 c に代入します

変数の型宣言において変数名に記号を付けることによりその変数はポインタ型の変数と

なりますポインタ型の変数は変数名のみを指定した場合には単にその変数の値(通常はメモリ

の番地)を表します変数名に記号を付けて使用した場合にはその変数が指し示している変

数の内容を表します c = a ポインタ型変数 a が指している値を変数 c に代入

ポインタ型の変数に番地を記憶させるためにはプログラム例のように変数名の前に記号を

指定します変数名 によって変数の番地(アドレス)を表します a = ampb 変数 b の番地をポインタ型変数 a に代入します

ポインタ型変数の型はポインタ型変数が指し示す先の変数の型を表しています int a 変数 a 整数型の値 float x 変数 x 実数型の値 char c 変数 c 文字型の値

6-2 ポインタ型変数の初期化 ポインタ型変数も型宣言のときに変数を初期化することができます特に文字型のポインタ変

数の場合によく使います char str = TOKAI University

ポインタ型変数 str は文字列定数 TOKAI University の最初の文字が格納されている番地を初期値として持つことになります

変数 str TOKAI University 文字列定数

[プログラム例]

(1)文字型配列 putchar() 関数を使って一次元の文字型配列を出力します include ltstdiohgt main() char str[6] = TOKAI int i for( i = 0 str[i] = yen0 i++ ) putchar( str[i] )

21

ポインタを使用した場合には以下のようになります include ltstdiohgt main() char str[6] = TOKAI char chp for( chp = str chp = yen0 chp++ ) putchar( chp )

chp str T [0] O K A I yen0 [5]

参照する変数 配列の表現 ポインタの表現 実際のアドレス 1番目の数 str[0] chp CHP 2番目の数 str[1] (chp+1) CHP+1 n番目の数 str[n-1] (chp+n-1) CHP+n-1 6番目の数 str[5] (chp+5) CHP+5

注意実際のアドレス CHPは実行時に決定されます

(2)二次元文字型配列 二次元の文字型配列に定数を設定しそれを出力するプログラムです文字型配列を使用す

ると次のとおりになります include ltstdiohgt main() char str[5][40] = TOKAI shounan campus NEC DEC int i for( i = 0 i lt 5 i++ ) printf( yenns str[i] )

40 バイト str TOKAI shounan campus NEC DEC

22

ポインタ型配列を使用すると次のとおりになります include ltstdiohgt main() char str[6] = TOKAI shounan campus NEC DEC NULL char chp for( chp = str chp = NULL chp++ ) printf( yenns chp ) str

chp 番地 TOKAI 番地 shounan 番地 campus 番地 NEC 番地 DEC

NULL

演習8 キーボードまたはデータファイルから読み込んだ文字列中にrsquoArsquo があったら rsquoarsquo に変換 するプログラムを配列とポインタを使って書きなさい

23

第7章 構造体共用体 7-1 構造体

プログラムの規模が大きくなるにつれて多数の intや floatcharなどのデータ型を扱うようになり複雑になってきますそこで多数のデータを1つにまとめて簡単に扱える機能が構造体です 構造体について住所録のデータを例にあげて考えてみます

住所録の個人データとして氏名住所電話番号年齢の項目を一つのデータとします これをC言語で変数の定義をすると次のようになります 氏名東海太郎 char name[30] 住所平塚市北金目1117 char address[30] 電話番号0463-58-1211 char tel[20] 年齢30 int age 個人の住所録データ C言語での表現 このような住所録の個人データを1つにまとめて新しいデータとして定義する機能を構造体と言

います struct 構造体タグ名 構造体メンバーの並び

「struct」は構造体を表すキーワードです 「構造体タグ名」は構造体の型枠を宣言しますここは自由に名前を定義することができ ます 「構造体メンバーの並び」は構造体の要素です複数指定できます

個人の住所録のデータを構造体で宣言すると次のようになります

struct jusho char name[30] char address[30] 構造体のメンバーの並び char tel[20] (複数可)

int age

上記の宣言では構造体の形式を宣言しているだけでメモリ中で実際の領域を確保している

わけではありません実際に領域を確保するためには次のように定義します

struct 構造体タグ名 構造体名

したがって構造体名を jdata とすると次のように指定します

struct jusho jdata

構造体 jdataは次のように構造体タグ jushoの形式で領域を確保します

24

Jdata name[30]

address[30] tel[20] age

(1)構造体の参照

プログラム中で構造体中のメンバーを参照する場合には次のように指定します 構造体名メンバー名

したがって「名前」を参照したいときには次のように指定します

jdataname

[プログラム例]

名前住所電話番号年齢を定義しそれを印字します include ltstdiohgt include ltstringhgt main() struct jusho char name[30] char address[30] char tel[20] int age struct jusho jdata strcpy( jdataname 東海 太郎) strcpy( jdataaddress 平塚市北金目1117)

strcpy( jdatatel 0463-58-1211) jdataage = 30 printf(yenn氏名 = syenn jdataname) printf(yenn住所 = syenn jdataaddress) printf(yenn電話番号= syenn jdatatel) printf(yenn年齢 = dyenn jdataage)

また構造体の形式の定義と領域の確保は次のように同時におこなうことができます

struct 構造体タグ名 構造体メンバーの並び 構造体名

struct jusho struct jusho char name[30] char name[30] char address[30] char address[30] char tel[30] = char tel[30] int age 同じ int age

jdata struct jusho jdata

型宣言と同時にメモリ上に領域を確保する方法 後からメモリ上に領域を確保する方法

25

(2) 構造体配列 住所録データの場合その中に入るデータは1件ではありませんやはり100件200件のデ

ータが必要になる場合がありますこのように個人単位のデータを多数扱う場合には構造体を配

列として宣言することができます 次の例は個人のデータを100個用意するために構造体を配列として宣言しています struct jusho jdata[100] jdata[0] name[30] address[30] tel[20] age

jdata[99 ] name[30] address[30] tel[20] age

(3)構造体配列の参照

プログラム中で構造体配列中のメンバーを参照する場合には次のように指定します 構造体名[要素番号]メンバー名

したがって10件目の人の「名前」を参照したいときには次のように指定します

jdata[10]name

[プログラム例]

名前住所電話番号年齢を定義しそれを印字します include ltstdiohgt include ltstringhgt main() struct jusho char name[30] char address[30] char tel[20] int age jdata[100] strcpy( jdata[10]name 東海 太郎) strcpy( jdata[10]address 平塚市北金目1117)

strcpy( jdata[10]tel 0463-58-1211) jdata[10]age = 30 printf(yenn氏名 = syenn jdata[10]name) printf(yenn住所 = syenn jdata[10]address) printf(yenn電話番号= syenn jdata[10]tel) printf(yenn年齢 = dyenn jdata[10]age)

26

(4) 構造体のポインタ 変数と同じように構造体へのポインタも定義することができます

変数へのポインタ例 構造体へのポインタ例 またポインタを使用して構造体メンバーを参照するには次のように -> 記号を使って指

定します ポインタ変数名 -> メンバー名

[プログラム例]

名前住所電話番号年齢を定義しそれを印字します include ltstdiohgt include ltstringhgt main() struct jusho char name[30] char address[30] char tel[20] int age jdatakp kp = ampjdata strcpy( kp-gtname 東海 太郎)

strcpy( kp-gtaddress 平塚市北金目1117)

strcpy( kp-gttel 0463-58-1211) kp-gtage = 30 printf(yenn氏名 = syenn kp-gtname) printf(yenn住所 = syenn kp-gtaddress) printf(yenn電話番号= syenn kp-gttel) printf(yenn年齢 = dyenn kp-gtage)

kp jdata

name[30] ポインタ型の変数 address[30]

tel[20]

構造体へのポインタを記憶 age

することができます

int a int b b = ampa

struct name jname struct name np np = ampname

27

7-2 共用体 共用体は構造体と同じようにして宣言しますが共用体は複数のデータ型を同一のアドレスに

割り当てる方法です union 共用体タグ名 共用体メンバーの並び

「union」は共用体を表すキーワードです 「共用体タグ名」は共用体の型枠の名前を宣言しますここは自由に名前を定義することがで

きます 「共用体メンバーの並び」は共用体の要素です複数指定できます

共用体の宣言の例を次に示します

union c_tag int a char b

共用体 cは次のように共用体タグ c_tagの形式で領域を確保します共用体はメモリ上に領域を確保するときは ab ともに同じ領域に割り付けられます これはab という2つのデータが同時に存在するわけではなく cを異なるデータ abで共有す

ることを表しています c a b

上記の宣言だけでは共用体の形式を宣言しているだけでメモリ中で実際の領域を確保して

いるわけではありません実際に領域を確保するためには次のように定義します union 構造体タグ名 構造体名

したがって共用体名を c とすると次のように指定します

union c_tag c

(1)共用体の参照

プログラム中で共用体中のメンバーを参照する場合には次のように指定します 共用体名メンバー名

したがって「a」または「b」を参照したいときには次のように指定します

ca (int 型) cb (char 型)

メンバー参照方法によって int型として使ったりchar型として利用することができます

28

[プログラム例]

includeltstdiohgt main() union data char a short b int c chk chkc = 0x12345678 printf( char a xyennchka) printf( short b xyennchkb) printf( int c xyennchkc)

chkb(int 型) chkb(short 型) chka(char 型) 12 12 12 34 34 56 78

29

第8章 アルゴリズム コンピュータに何か仕事をさせようとするときは仕事を具体的に実行するための処理や動作

の手順が必要ですこの「手順」がアルゴリズムです アルゴリズムを考えるときは解くべき問題をはっきりと定義することが必要です

8-1 ソート ソートとは与えられたデータを小さい順または大きい順に並べ換えることですソート方法は

いくつかありますが基本的な方法でソートするアルゴリズムを紹介します

includeltstdiohgt int data[10] main()

int data_in() sort() data_in() sort() int data_in() データ入力関数

int a printf(数値入力yenn)

for(a=0alt=9a++) printf( [d]a+1) scanf(dampdata[a]) int sort() ソート処理を行う関数

int cont1cont2tmp1tmp2mim for(cont1=0 cont1lt=9 cont1++) mim=data[cont1] tmp1=cont1 for(cont2=cont1+1 cont2lt=9 cont2++) if(data[cont2] lt mim) mim=data[cont2] tmp1=cont2 tmp2 = data[cont1] data[cont1] = data[tmp1] data[tmp1] = tmp2 printf(結果 yenn)

for (cont1 = 0 cont1 lt= 9 cont1++) printf(d yenn data[cont1])

30

第9章 プリプロセッサ C言語にはプログラムの中でコンパイルについての指示を行う「プリプロセッサ」という機能が

ありますまたプリプロセッサとはコンパイルする前に実行されるためその意味のとおり「前処理」 と呼ばれていますここでは代表的なものをいくつか説明します

9-1 ファイルの挿入 ソースプログラム中に指定されたファイルを挿入します

include ltstdiohgt helliphellip 標準ディレクトリを探します include progh helliphellip 現在のディレクトリを探しなければ標準ディレクトリを探します

includeltstdiohgt によって組み込まれた define EOF (-1) define EOF (-1) define define helliphelliphelliphellip 組み込み helliphelliphelliphellip

main() stdiohファイル

int helliphelliphelliphellip helliphelliphelliphellip

ソースファイル

9-2 文字の置換 プログラム中に使われている文字列を別の文字列に置き換えます

include ltstdiohgt define TRUE 1 define EOF (-1) main() define helliphellip helliphellip

while(TRUE) define TRUE 1 置き換え main() helliphellip helliphellip while(1)

break helliphelliphellip

31

9-3 条件によるコンパイル 識別子が定義されているか否かを判断しコンパイルする範囲を指定します

include ltstdiohgt define UNIX main() ifdef UNIX printf( UNIX yenn) else printf(MS-DOSyenn) endif

include ltstdiohgt define OS UNIX main() if OS == UNIX printf( UNIX yenn) else printf(MS-DOSyenn) endif

32

付 録 1 puts()gets()関数について

行単位に入出力を行う場合には puts() gets() 関数を用います

puts() 標準出力に文字列を出力します

include ltstdiohgt int puts( char s ) puts() は NULL で終る文字列 s を標準出力に出力し最後に改行文字 yenn も出力しま

gets() 標準入力から文字列を入力します

include ltstdiohgt char gets( char s ) 戻り値正常に入力した場合には引数 s の値が返されますエラーやEOFになった場合に

は NULL が返されます gets() は標準入力から復帰文字で終る文字列を入力しs に格納しますこのとき最後の復

帰文字は NULL文字に変更されます

入力行の出力 標準入力から gets() で入力したデータには改行コードは含まれませんまた標準出力へ

puts() で出力を行う場合には必ず改行コードが付加されますgets() を実行したときの戻り値としてファイルの終端を検出した場合には EOF ではなく NULL が返されますので注意して下さい

include ltstdiohgt main() char data[80] while( gets( data ) = NULL )puts( data )

putchar()getchar()関数について putchar() 標準出力に文字を出力します

include ltstdiohgt int putchar(int c ) 戻り値正常に出力できた場合には文字cをエラーの場合にはEOFを返します

33

getchar() 標準入力から文字を入力します

include ltstdiohgt int getchar(void) 戻り値正常に入力した場合には読み込んだ文字を int 型に変換して返しますまたファイ

ルエンドエラーの場合にはEOFを返します

標準入力標準出力

標準入力標準出力はプログラムが開始されるときにはオープンされていますそれぞれのフ

ァイルポインタは stdin stdout になっていますfopen() fclose() をせずとも使用することができます

scanf() 標準出力ストリームからテキストを読み込み解釈します include ltstdiohgt int scanf( const char format [ address ] ) 戻り値正しくスキャンし変換し格納した入力フィールドの数を返しますファイルエンドを読

み込んだ場合は戻り値は EOF となります値を格納したフィールドがなかった場合は戻り値は0となります

一連の入力フィールドをスキャンして1度に1文字ずつストリーム stdin から文字を読み込み

ます次に引き数 format によって指される書式文字列中の書式指定に従って各フィールドを書式化します最後にformat の後に続く各引き数が示しているアドレスに書式化した入力を格納していきます書式文字列中の書式指定の個数はその後に続くアドレスの数と同じでな

ければなりません 書式指定[入力幅][型指定文字] 入力幅 読むべき文字数の最大値 型指定文字 次のとおりです 型指定文字 期待される入力 引き数の型 d 10進整数 int へのポインタ( int arg ) x 16進整数 int へのポインタ( int arg ) f 浮動小数点数 float へのポインタ( float arg ) s 文字列 文字配列へのポインタ( char arg[] ) c 文字 文字へのポインタ( char arg )

printf() フォーマットを指定してテキスト標準出力ストリームに出力します include ltstdiohgt int printf( const char format [ argument ] ) 戻り値出力したバイト数を返しますエラーの場合は EOF を返します

34

format によって指される書式文字列中の書式指定をformat の後に続く各引き数に適用し

書式化されたデータを stdout に出力します書式指定は後に続く引き数と同じ数だけなければなりません

書式指定[印字幅][精度][型指定文字] 印字幅 印字する最小文字数 精度 印字する最大文字数 型指定文字 つぎのとおりです 型指定文字 入力引き数 出力の書式 d 整数 符号付き10進整数 x 整数 符号無し16進整数 f 浮動小数点 符号付きの dddddddd形式の値 c 文字 1個の文字 s 文字列ポインタ ヌル文字に出会うか精度に達するまで 文字をプリントする

fopen()fclose()関数について fopen() ファイルをオープンします

include ltstdiohgt FILE fopen( char filename char mode ) 戻り値正常にファイルのオープンができたらファイルポインタを返しますエラーがあった場

合には NULLを返します 文字列 filename で指定されたファイルをオープンしますオープン後の入出力のモードに

ついては文字列 mode で指定しますmode に指定できる文字は以下のとおりです r 入力モードでオープンします w 出力モードでオープンします a 存在するファイルに追加して出力するモードでオープンします r+ 既に作成してあるファイルを更新(入力出力)するモードでオープンします w+ 新しく作成するファイルを更新モードでオープンします a+ 既に作成してあるファイルの終りから更新用に作成します

以上の文字に b をつけ加えることによりバイナリモードで入出力することができるようになり

ます rb バイナリの入力モードでオープンします wb バイナリの出力モードでオープンします ab 存在するファイルに追加して出力するモード(バイナリ)でオープンします

fclose() 既にオープンしてあるファイルをクローズします include ltstdiohgt fclose( FILE fp ) 既にオープンしているファイルをクローズしますパラメータには fopen() 関数により返された

ファイルポインタを指定します

35

テキストモードとバイナリモード 行の最後はテキストモードの場合改行コードのみとなりバイナリモードの場合には復帰

コードと改行コードの組合わせになります行の最後としてテキストファイルには復帰コード改行

コードが書かれていますがテキストモードでオープンした場合には入力すると改行コードのみに

変換されて入力されますバイナリモードの場合には復帰コード改行コードがそれぞれ入力され

ます

fputs()fgets()関数について fputs() ファイルポインタで指定されるファイルに文字列を出力します

include ltstdiohgt

int fputs( char s FILE fp ) fputs() は NULL で終る文字列 s をファイルポインタに示されるファイルへ出力しますputs()

と違い最後に改行文字 yenn を出力することはありません

fgets() ファイルポインタで指定されるファイルから文字列を入力します include ltstdiohgt char fgets( char s int n FILE fp ) 戻り値正常に入力した場合には引数 s の値が返されますエラーやEOFになった場合に

は NULL が返されます fgets() はファイルポインタで指定されるファイルから ( n - 1 ) 文字または改行文字までの

文字列を入力しs に格納しますgets() と異なり最後に入力された改行文字は NULL 文字に変更されません

標準入力から入力しファイルへ出力する ファイルへ出力あるいは入力を行う場合には改行コードの変換(入力の場合の削除出力の

場合の付加)はされませんしたがって標準入力から入力しファイルへ出力する場合には改行

コードを付加しなければなりません include ltstdiohgt main() char data[80] FILE fp fp = fopen( data w ) while( gets( data ) = NULL ) strcat( data yenn ) 改行コードの付加

fputs( data fp ) fclose( fp )

36

fputc()fgetc()関数について fputc() ファイルポインタで指定されるファイルに1文字出力します

include ltstdiohgt int fputc( int c FILE fp ) 戻り値正常に出力できた場合には文字 c を返しエラーの場合には EOF を返します fputc() は文字 c をファイルポインタで示されるファイルへ出力します

fgetc() ファイルポインタで指定されるファイルから1文字入力します

include ltstdiohgt int fgetc( FILE fp ) 戻り値正常に入力した場合には入力した文字を返しますエラーやEOFになった場合には

EOF が返されます fgetc() はファイルポインタで指定されるファイルから文字を入力します

ファイルの内容の表示 include ltstdiohgt main() FILE fp int ch char fname[30] printf( Key in Fila name gt ) gets( fname ) fp = fopen( fname r ) while( ( ch = fgetc( fp ) ) = EOF )putchar( ch ) fclose( fp )

その他テキスト中で使用された関数について sin() 三角関数の正弦を計算します

include ltmathhgt double sin(double radian) sinはラジアンを単位とする引数 radianの三角関数を計算します

37

strcpy() 文字列を他の文字列へコピーします

include ltstringhgt char strcpy(char string1const char string2) strcpyは引数 string2の指す文字列を null文字まで含めて引数 string1の指す領域にコピ

ーする strcpyは string1を返します

strcat() ある文字列を他の文字列に加えます

include ltstringhgt char strcat( char dest const char src ) 戻り値連結された文字列へのポインタを返します strcat() はsrc のコピーを dest の最後につけ加えます得られる文字列の長さは

strlen(dest)+strlen(src) になります

fabs() 絶対値の計算をします include ltmathhgt double fabs(double z) fabsは倍精度浮動小数の絶対値を計算して返しますつまりzgt=0であれば z をzlt0であ

れば-zを返します exp() 指数関数を計算します

include ltmathhgt double exp(double z) exp は引数zの指数関数つまりezを返すここではeは自然対数の底を表します対数関

数logの逆関数です

38

付 録 2 コンパイルの方法には大きく分けて第4章の実習で学んだようにデータファイルを作成してお

き ccg でコンパイルさせる方法と実行中に対話型でデータを入力していく方法があります ここでは対話型で実行を進めていく方法を紹介します ただしこの方法は計算(cpu)時間が10秒以内のものに限ります10秒を超える計算(cpu)時

間を要する場合はccg でコンパイルをするようにしてください 第4章実習の(2)(p16)までは同様です

コンパイル

コンピュータに処理を依頼します 60us1234boseicc cc rensyuc

所有するファイルの一覧を見てみます

60us1234boseicc ls -l larr 持っているファイルの一覧を見るコマンドです

-rw-r--r-- 1 60us1234 other 128 4月26日 15時14分 rensyuc -rwxr-xr-x 1 60us1234 other 361 4月26日 15時16分 aout

aout という実行形式のファイルが作成されています

実行

60us1234boseicc aout12 35[リターン] データを入力

1 200000 3500000 4200000 実行結果の出力

60us1234boseicc

注意

aout ファイルは印刷することができません実行結果を印刷する場合にはファイルに落とし てから出力するようにしましょう

60us1234boseicc aout gt kekka12 35[リターン] データを入力

60us1234boseicc more kekka 計算結果の確認 60us1234boseicc lpr kekka 計算結果の印刷

39

Page 13: n 第1章 章立ての部分は、書式(PC入門大見出し)を …第2章 数の表現 2-1 2進数 電子計算機の動作原理は0と1で表される2進数です。また、人間が日常生活で扱っている数

3-5 変数の通用範囲 関数内で宣言された変数はその関数の中でのみ使用可能です他のプログラムからは使用

することはできません

include ltstdiohgt main() int i 変数 i は関数 main() と sub() とでは それぞれ独立に使用することができます main() で変数 i に設定した値は sub() では参照することはできません sub() 逆にsub() で変数 i に設定した値も main() では参照することはできません

int i

それぞれの関数の中でのみ使用可能な変数をローカル変数と呼び他の関数でも使用可能

な変数をグローバル変数と呼びますいくつかの関数で共通に使用するような場合にはグロー

バル変数を使用します グローバル変数を定義する場合には関数の外で宣言します

include ltstdiohgt int i グローバル変数の定義

main() i = 10

sub() extern int i printf( yenn i = d i )

このプログラムではmain() 関数でグローバル変数に値を設定し関数 sub() で変数の値を

参照しています extern 宣言は変数が他のプログラム内で宣言されていることを示しています宣言の形式

は以下のとおりです extern 型 変数並び

演習5 入力された任意の数の倍数を求めるプログラムを作成しなさい入力する数値は2つ倍数 を求めるための任意の数と倍数の上限値ですここでいう上限値とは任意の数の倍数をどの くらいの数まで求めるかということです

11

3-6 動的変数と静的変数 通常Cで使用される変数はその関数の中だけでのみ使用できる変数ですしたがって関数

が実行するときに関数の中で使用する変数の領域を確保し関数の実行が終るときにその領域

を解放するようにしてメモリを効率的に利用していますこのように関数が実行されるときに確

保される変数を動的変数(auto変数 )と呼びます プログラムの中ではその他に常に存在し使用できる変数を定義することができますそのよ

うな変数は静的変数(static変数 )と呼ばれます

func() int a b static int x y

また static 変数には内部的なリンケージの指定の意味もありますつまり関数の外で変数

を宣言すると自動的にグローバル変数となり他のプログラムからも使用することができるようにな

ります ファイル a ファイル b このような場合にはコンパイル単位が異なっていてもextern 宣言を行うことにより変数 abc

を使用することができますところが関数の外で static 宣言をして定義した変数についてはコンパイル単位が違うプログラムからは使用することができなくなります ファイル a ファイル b 同一コンパイル単位(ファイル)に存在する関数 sub()と subd()では変数 abcを使用することが

できますがコンパイル単位(ファイル)が異なる関数 func()では変数 abcを使用することはできません

int abc sub() abc = 10

func() extern int abc printf( ldquo abc =dyennrdquo abc )

static int abc sub() abc = 10 subd() abc++

func() extern int abc printf( ldquo abc =dyennrdquo abc )

12

3-7 スタック プログラム中にはプログラム領域データ領域の他にスタック領域があり一時的な作業領域と

して使用されています関数間での引数の受渡しの時にもこの領域を使用しますスタック領域に

データを格納することを「スタックに積む」ともいいます基本的にはスタック領域に格納されたデ

ータは最後に格納されたデータから順に取り出されることになります以下に格納が行われたとき

のスタックの状態を示します記号は次に格納すべき位置(スタックポインタの値)を示していま

逆にスタックからデータを取り出すときにはスタックポインタが指している位置の一つ下から取

り出すことになりますスタックからデータを取り出すときのスタックの状態は次のようになります

なり

10

20

10

30

20

10

40

30

20

10

10rarr

格納

20rarr

格納

30rarr

格納

40rarr

格納

40rarr 30rarr

関数を呼び出すときには次

逆にそれぞれの関数から

次のようになります

40

30

20

10

取出

main() z = f1( x y )

のようにパラメータがスタ

戻るときにはパラメータで

30

20

10

取出

f1( int a int b ) c = f2( d e

xの値 yの値

xの値 yの値

13

ックに格納されます

使用していたスタック領域は自動的になく

10

20

)

f2( int p int q ) r = p + q

xの値

eの値 dの値

yの値

xの値 yの値

dの値

eの値

3-8 再帰呼び出し 関数の引数の受渡しがスタックを利用して行われることから自分で自分自身の関数を呼び出

すことができます 以下のプログラムは入力した値の階乗を計算するプログラムです

3の階乗を求めることを考えてみます

return 文によって戻るときは次のようにして値を返します kai( 3 ) 3 kai( 3-1 ) 2 kai( 2-1 ) return 1

6 3 (2 1) 2 1 以上の計算から3=6が導き出されます 再帰呼び出しのことをリカーシブコールともいいます

include ltstdiohgt main() int n m kai() scanf( ldquodrdquoampn ) m = kai( n ) printf( ldquod = dyennrdquo n m )

int kai( int k ) if( k == 1 )return 1 else return k kai( k ndash 1 )

kai( 1 )

darr

return 1

kai( 2 )

darr

2 kai( 2-1 )

kai( 3 )

darr

3 kai( 3-1 )

main()

darr

kai( 3 )

3

2

1

2

3

1

2

3 3

32

32

1

2

1

3

3

演習6 1からnまでの総和を再帰呼び出しを使って計算する関数 sowa() を作りなさい n+(n-1)+ +2+1

14

第4章 実習 この章ではプログラムを実際に入力して実行するまでの手順を実習します

4-1 操作手順 (1)ログイン

[スタート]rarr[プログラム(P)]rarr[ネットワーク] Hostの欄に bosei を記述選択 rarr [Telnet(FreeWare)] を選択します して 「OK」 ボタンをクリックします

UP-UXV (Rel42MP) (bosei) (pts41) login 60us1234 larr 各自のログイン名を入力します Password larr パスワードを入力しても画面は何も変化しません 101 60us1234bosei larr セッションが開設されましたこれをプロンプトといいます この状態でコマンドを入力することができます

(2)プログラムの作成 以下のコマンドを入力しテキストエディタを起動します 60us1234boseicc ng rensyuc

すると下図のようにngエディタの画面になります

15

次のように入力します入力ミスの修正はBSキーで行ないます

include ltstdiohgt main() float abc scanf(f f ampaampb) c=ab printf(f f f yenn abc)

CTRL キーを押しながら XCTRL キーを押しながら C を押しますすると次のメッセージが画面下に表示されます

Save file uhomea60us1234rensyuc (y or n)

このメッセージに対して y と答えます

(3)データの作成 以下のコマンドを入力しテキストエディタを起動します 60us1234boseicc ng rensyud

ngエディタの画面になりますので次のように入力します 12 35

CTRLキーを押しながら XCTRLキーを押しながら C を押します save file uhomea60us1234rensyud (y or n)

このメッセージに対して y と答えます

(4)コンパイルと実行 コンピュータに処理を依頼します 60us1234boseicc ccg rensyu

ジョブを投入しましたジョブの状態を見るコマンドは myjobです

16

130 60us1234boseicc myjob ================================================= NQS (R0220) BATCH REQUEST HOST bosei ================================================= REQUEST ID NAME OWNER QUEUE PRI NICE STT PGRP R --------------- -------- -------- -------- ---- --- --- ------ - 99321bosei STDIN 60us1234 A 31 0 RUN 14161 - ---------------------------------------------------------------- ================================================== NQS (R0220) DEVICE REQUEST HOST bosei ジョブは実行中です

================================================== REQUEST ID NAME OWNER QUEUE PRI SIZE STT -------------------------------------------------------------

所有するファイルの一覧を見てみます

60us1234boseicc ls -l larr 持っているファイルの一覧を見るコマンドです

-rw-r--r-- 1 60us1234 other 4 4月26日 15時14分 rensyud -rw-r--r-- 1 60us1234 other 128 4月26日 15時10分 rensyuc -rwxr-xr-x 1 60us1234 other 361 4月26日 15時16分 rensyul

(5)計算結果の確認

計算結果を画面に表示して確認します 60us1234boseicc more rensyul

(6)印刷

計算結果の印刷を行ないます5号館2階のカフェテリア室にある bosei のプリンタに印刷 されます

60us1234boseicc lpr rensyul

(7)ログアウト セッションを終了します 60us1234boseicc logout

(8)実行の流れ

エラー

プログラムの作成 ログイン コンパイル実行

確 認 印 刷 ログアウト

17

第5章 配列 多数の変数をまとめて宣言する方法として配列があります配列の一つ一つは配列要素と呼

ばれ変数と同じ性格を持っています配列の宣言は型宣言と同時に次のように行います int a[5] 配列 a

a[0]

a[1]

a[2]

a[3]

a[4]

二次元配列(一次元配列を複数集めたもの)を宣言する場合には次のようになります int b[3][4] 配列 b

b[0][0] b[0][1] b[0][2] b[0][3]

b[1][0] b[1][1] b[1][2] b[1][3]

b[2][0] b[2][1] b[2][2] b[2][3]

配列要素に数値を代入する場合は次のようになります b[1][2]=10

5-1 二次元配列要素の初期化 変数の型宣言と同じように配列を宣言するときに初期値も同時に設定することができます

複数のデータがある場合には{}記号でくくって指定します int b[3][4] = 2 4 6 8 1 3 5 7 1 2 3 4

文字型配列の場合には以下のようになりますyen0 は文字列の終わりを表わします char univ[3][7] = T O K A I yen0 S I M I Z U yen0 Y O Y O G I yen0

また文字列定数として初期化することもできますこの場合コンパイル時に自動的に yen0 が付加されます

char univ[3][7] = TOKAI SIMIZU YOYOGI

18

[プログラム例] 二次元配列のタテヨコを加算するプログラム

include ltstdiohgt main() int mat[4][3]=123456789101112 int ijytotalttotal[3]total=0 for(j=0jlt3j++)ttotal[j]=0 for (i=0ilt4i++) ytotal=0 for(j=0jlt3j++) ytotal += mat[i][j] ttotal[j] += mat[i][j] total += mat[i][j] printf(3dmat[i][j]) printf( 3dyennytotal) printf(yenn) for(j=0jlt3j++)printf(3dttotal[j]) printf( 3dyenntotal)

[実行結果]

1 2 3 6 4 5 6 15 7 8 9 24 10 11 12 33 22 26 30 78

演習7

a)以下の配列はどのように初期化されるか答えなさい char errmsg[2][15] = Divide Error Overflow Error

b)九九の計算を2次元配列を使って求めなさい

19

第6章 ポインタ型変数 C言語では値を記憶するための変数だけではなく変数または定数の番地を記憶するため

のポインタ型変数を宣言することができますポインタとはデータ項目の一種で「記憶装置(メモ

リ)上の格納番地(アドレス)を指すデータ項目」です アドレス コンピュータの中ではデータ項目の格納番地のことをアドレス(住所)と呼びます 例えば記憶装置という名前のとてつもなく大きなマンションがあるとしますその中から Aさんを捜すときは部屋番号を参照しますマンションでは部屋番号で住居人を参照し ているのと同じようにコンピュータでは記憶装置上に確保された変数は格納番地 (アドレス)で管理されています

マンション 部屋番号 記憶装置 格納番地

Aさん Int a Bさん Cさん AAAさん BBBさん CCCさん

1号室

2号室

3号室

100号室

200号室

300号室

100番地

200番地

300番地

1000番地

2000番地

3000番地

Int b Int c float aaafloat bbbfloat ccc

ポインタ ポインタとは「指し示すもの」の意ですがC言語では記憶装置上のアドレスを指し示す もののことです上のマンションの例では部屋番号を格納するデータ項目ということに なりますAAAさんは100号室に住んでいます100という値をポインタのデータ項目に 記憶するとそのデータ項目は間接的にAAAさんを指すことになります

6-1 ポインタ型変数の宣言および参照 通常の変数と区別するために型宣言時に変数名の前に記号を付けて宣言します int a 整数型ポインタ変数 int b 整数型変数

変数 a は整数型の値を記憶するのではなく整数型の値を持つ変数などの番地を記憶する変数ですまた変数 b は通常の整数型の値を記憶するための変数です

20

include ltstdiohgt main() int a b c a はポインタ型の変数b c は整数型の変数 b = 12 変数 b に値 12 を代入します a = ampb 変数 a には変数 b の番地が代入されます c = a + 10 変数 a の指す変数(b)の内容と10の加算です つまり12 + 10 を変数 c に代入します

変数の型宣言において変数名に記号を付けることによりその変数はポインタ型の変数と

なりますポインタ型の変数は変数名のみを指定した場合には単にその変数の値(通常はメモリ

の番地)を表します変数名に記号を付けて使用した場合にはその変数が指し示している変

数の内容を表します c = a ポインタ型変数 a が指している値を変数 c に代入

ポインタ型の変数に番地を記憶させるためにはプログラム例のように変数名の前に記号を

指定します変数名 によって変数の番地(アドレス)を表します a = ampb 変数 b の番地をポインタ型変数 a に代入します

ポインタ型変数の型はポインタ型変数が指し示す先の変数の型を表しています int a 変数 a 整数型の値 float x 変数 x 実数型の値 char c 変数 c 文字型の値

6-2 ポインタ型変数の初期化 ポインタ型変数も型宣言のときに変数を初期化することができます特に文字型のポインタ変

数の場合によく使います char str = TOKAI University

ポインタ型変数 str は文字列定数 TOKAI University の最初の文字が格納されている番地を初期値として持つことになります

変数 str TOKAI University 文字列定数

[プログラム例]

(1)文字型配列 putchar() 関数を使って一次元の文字型配列を出力します include ltstdiohgt main() char str[6] = TOKAI int i for( i = 0 str[i] = yen0 i++ ) putchar( str[i] )

21

ポインタを使用した場合には以下のようになります include ltstdiohgt main() char str[6] = TOKAI char chp for( chp = str chp = yen0 chp++ ) putchar( chp )

chp str T [0] O K A I yen0 [5]

参照する変数 配列の表現 ポインタの表現 実際のアドレス 1番目の数 str[0] chp CHP 2番目の数 str[1] (chp+1) CHP+1 n番目の数 str[n-1] (chp+n-1) CHP+n-1 6番目の数 str[5] (chp+5) CHP+5

注意実際のアドレス CHPは実行時に決定されます

(2)二次元文字型配列 二次元の文字型配列に定数を設定しそれを出力するプログラムです文字型配列を使用す

ると次のとおりになります include ltstdiohgt main() char str[5][40] = TOKAI shounan campus NEC DEC int i for( i = 0 i lt 5 i++ ) printf( yenns str[i] )

40 バイト str TOKAI shounan campus NEC DEC

22

ポインタ型配列を使用すると次のとおりになります include ltstdiohgt main() char str[6] = TOKAI shounan campus NEC DEC NULL char chp for( chp = str chp = NULL chp++ ) printf( yenns chp ) str

chp 番地 TOKAI 番地 shounan 番地 campus 番地 NEC 番地 DEC

NULL

演習8 キーボードまたはデータファイルから読み込んだ文字列中にrsquoArsquo があったら rsquoarsquo に変換 するプログラムを配列とポインタを使って書きなさい

23

第7章 構造体共用体 7-1 構造体

プログラムの規模が大きくなるにつれて多数の intや floatcharなどのデータ型を扱うようになり複雑になってきますそこで多数のデータを1つにまとめて簡単に扱える機能が構造体です 構造体について住所録のデータを例にあげて考えてみます

住所録の個人データとして氏名住所電話番号年齢の項目を一つのデータとします これをC言語で変数の定義をすると次のようになります 氏名東海太郎 char name[30] 住所平塚市北金目1117 char address[30] 電話番号0463-58-1211 char tel[20] 年齢30 int age 個人の住所録データ C言語での表現 このような住所録の個人データを1つにまとめて新しいデータとして定義する機能を構造体と言

います struct 構造体タグ名 構造体メンバーの並び

「struct」は構造体を表すキーワードです 「構造体タグ名」は構造体の型枠を宣言しますここは自由に名前を定義することができ ます 「構造体メンバーの並び」は構造体の要素です複数指定できます

個人の住所録のデータを構造体で宣言すると次のようになります

struct jusho char name[30] char address[30] 構造体のメンバーの並び char tel[20] (複数可)

int age

上記の宣言では構造体の形式を宣言しているだけでメモリ中で実際の領域を確保している

わけではありません実際に領域を確保するためには次のように定義します

struct 構造体タグ名 構造体名

したがって構造体名を jdata とすると次のように指定します

struct jusho jdata

構造体 jdataは次のように構造体タグ jushoの形式で領域を確保します

24

Jdata name[30]

address[30] tel[20] age

(1)構造体の参照

プログラム中で構造体中のメンバーを参照する場合には次のように指定します 構造体名メンバー名

したがって「名前」を参照したいときには次のように指定します

jdataname

[プログラム例]

名前住所電話番号年齢を定義しそれを印字します include ltstdiohgt include ltstringhgt main() struct jusho char name[30] char address[30] char tel[20] int age struct jusho jdata strcpy( jdataname 東海 太郎) strcpy( jdataaddress 平塚市北金目1117)

strcpy( jdatatel 0463-58-1211) jdataage = 30 printf(yenn氏名 = syenn jdataname) printf(yenn住所 = syenn jdataaddress) printf(yenn電話番号= syenn jdatatel) printf(yenn年齢 = dyenn jdataage)

また構造体の形式の定義と領域の確保は次のように同時におこなうことができます

struct 構造体タグ名 構造体メンバーの並び 構造体名

struct jusho struct jusho char name[30] char name[30] char address[30] char address[30] char tel[30] = char tel[30] int age 同じ int age

jdata struct jusho jdata

型宣言と同時にメモリ上に領域を確保する方法 後からメモリ上に領域を確保する方法

25

(2) 構造体配列 住所録データの場合その中に入るデータは1件ではありませんやはり100件200件のデ

ータが必要になる場合がありますこのように個人単位のデータを多数扱う場合には構造体を配

列として宣言することができます 次の例は個人のデータを100個用意するために構造体を配列として宣言しています struct jusho jdata[100] jdata[0] name[30] address[30] tel[20] age

jdata[99 ] name[30] address[30] tel[20] age

(3)構造体配列の参照

プログラム中で構造体配列中のメンバーを参照する場合には次のように指定します 構造体名[要素番号]メンバー名

したがって10件目の人の「名前」を参照したいときには次のように指定します

jdata[10]name

[プログラム例]

名前住所電話番号年齢を定義しそれを印字します include ltstdiohgt include ltstringhgt main() struct jusho char name[30] char address[30] char tel[20] int age jdata[100] strcpy( jdata[10]name 東海 太郎) strcpy( jdata[10]address 平塚市北金目1117)

strcpy( jdata[10]tel 0463-58-1211) jdata[10]age = 30 printf(yenn氏名 = syenn jdata[10]name) printf(yenn住所 = syenn jdata[10]address) printf(yenn電話番号= syenn jdata[10]tel) printf(yenn年齢 = dyenn jdata[10]age)

26

(4) 構造体のポインタ 変数と同じように構造体へのポインタも定義することができます

変数へのポインタ例 構造体へのポインタ例 またポインタを使用して構造体メンバーを参照するには次のように -> 記号を使って指

定します ポインタ変数名 -> メンバー名

[プログラム例]

名前住所電話番号年齢を定義しそれを印字します include ltstdiohgt include ltstringhgt main() struct jusho char name[30] char address[30] char tel[20] int age jdatakp kp = ampjdata strcpy( kp-gtname 東海 太郎)

strcpy( kp-gtaddress 平塚市北金目1117)

strcpy( kp-gttel 0463-58-1211) kp-gtage = 30 printf(yenn氏名 = syenn kp-gtname) printf(yenn住所 = syenn kp-gtaddress) printf(yenn電話番号= syenn kp-gttel) printf(yenn年齢 = dyenn kp-gtage)

kp jdata

name[30] ポインタ型の変数 address[30]

tel[20]

構造体へのポインタを記憶 age

することができます

int a int b b = ampa

struct name jname struct name np np = ampname

27

7-2 共用体 共用体は構造体と同じようにして宣言しますが共用体は複数のデータ型を同一のアドレスに

割り当てる方法です union 共用体タグ名 共用体メンバーの並び

「union」は共用体を表すキーワードです 「共用体タグ名」は共用体の型枠の名前を宣言しますここは自由に名前を定義することがで

きます 「共用体メンバーの並び」は共用体の要素です複数指定できます

共用体の宣言の例を次に示します

union c_tag int a char b

共用体 cは次のように共用体タグ c_tagの形式で領域を確保します共用体はメモリ上に領域を確保するときは ab ともに同じ領域に割り付けられます これはab という2つのデータが同時に存在するわけではなく cを異なるデータ abで共有す

ることを表しています c a b

上記の宣言だけでは共用体の形式を宣言しているだけでメモリ中で実際の領域を確保して

いるわけではありません実際に領域を確保するためには次のように定義します union 構造体タグ名 構造体名

したがって共用体名を c とすると次のように指定します

union c_tag c

(1)共用体の参照

プログラム中で共用体中のメンバーを参照する場合には次のように指定します 共用体名メンバー名

したがって「a」または「b」を参照したいときには次のように指定します

ca (int 型) cb (char 型)

メンバー参照方法によって int型として使ったりchar型として利用することができます

28

[プログラム例]

includeltstdiohgt main() union data char a short b int c chk chkc = 0x12345678 printf( char a xyennchka) printf( short b xyennchkb) printf( int c xyennchkc)

chkb(int 型) chkb(short 型) chka(char 型) 12 12 12 34 34 56 78

29

第8章 アルゴリズム コンピュータに何か仕事をさせようとするときは仕事を具体的に実行するための処理や動作

の手順が必要ですこの「手順」がアルゴリズムです アルゴリズムを考えるときは解くべき問題をはっきりと定義することが必要です

8-1 ソート ソートとは与えられたデータを小さい順または大きい順に並べ換えることですソート方法は

いくつかありますが基本的な方法でソートするアルゴリズムを紹介します

includeltstdiohgt int data[10] main()

int data_in() sort() data_in() sort() int data_in() データ入力関数

int a printf(数値入力yenn)

for(a=0alt=9a++) printf( [d]a+1) scanf(dampdata[a]) int sort() ソート処理を行う関数

int cont1cont2tmp1tmp2mim for(cont1=0 cont1lt=9 cont1++) mim=data[cont1] tmp1=cont1 for(cont2=cont1+1 cont2lt=9 cont2++) if(data[cont2] lt mim) mim=data[cont2] tmp1=cont2 tmp2 = data[cont1] data[cont1] = data[tmp1] data[tmp1] = tmp2 printf(結果 yenn)

for (cont1 = 0 cont1 lt= 9 cont1++) printf(d yenn data[cont1])

30

第9章 プリプロセッサ C言語にはプログラムの中でコンパイルについての指示を行う「プリプロセッサ」という機能が

ありますまたプリプロセッサとはコンパイルする前に実行されるためその意味のとおり「前処理」 と呼ばれていますここでは代表的なものをいくつか説明します

9-1 ファイルの挿入 ソースプログラム中に指定されたファイルを挿入します

include ltstdiohgt helliphellip 標準ディレクトリを探します include progh helliphellip 現在のディレクトリを探しなければ標準ディレクトリを探します

includeltstdiohgt によって組み込まれた define EOF (-1) define EOF (-1) define define helliphelliphelliphellip 組み込み helliphelliphelliphellip

main() stdiohファイル

int helliphelliphelliphellip helliphelliphelliphellip

ソースファイル

9-2 文字の置換 プログラム中に使われている文字列を別の文字列に置き換えます

include ltstdiohgt define TRUE 1 define EOF (-1) main() define helliphellip helliphellip

while(TRUE) define TRUE 1 置き換え main() helliphellip helliphellip while(1)

break helliphelliphellip

31

9-3 条件によるコンパイル 識別子が定義されているか否かを判断しコンパイルする範囲を指定します

include ltstdiohgt define UNIX main() ifdef UNIX printf( UNIX yenn) else printf(MS-DOSyenn) endif

include ltstdiohgt define OS UNIX main() if OS == UNIX printf( UNIX yenn) else printf(MS-DOSyenn) endif

32

付 録 1 puts()gets()関数について

行単位に入出力を行う場合には puts() gets() 関数を用います

puts() 標準出力に文字列を出力します

include ltstdiohgt int puts( char s ) puts() は NULL で終る文字列 s を標準出力に出力し最後に改行文字 yenn も出力しま

gets() 標準入力から文字列を入力します

include ltstdiohgt char gets( char s ) 戻り値正常に入力した場合には引数 s の値が返されますエラーやEOFになった場合に

は NULL が返されます gets() は標準入力から復帰文字で終る文字列を入力しs に格納しますこのとき最後の復

帰文字は NULL文字に変更されます

入力行の出力 標準入力から gets() で入力したデータには改行コードは含まれませんまた標準出力へ

puts() で出力を行う場合には必ず改行コードが付加されますgets() を実行したときの戻り値としてファイルの終端を検出した場合には EOF ではなく NULL が返されますので注意して下さい

include ltstdiohgt main() char data[80] while( gets( data ) = NULL )puts( data )

putchar()getchar()関数について putchar() 標準出力に文字を出力します

include ltstdiohgt int putchar(int c ) 戻り値正常に出力できた場合には文字cをエラーの場合にはEOFを返します

33

getchar() 標準入力から文字を入力します

include ltstdiohgt int getchar(void) 戻り値正常に入力した場合には読み込んだ文字を int 型に変換して返しますまたファイ

ルエンドエラーの場合にはEOFを返します

標準入力標準出力

標準入力標準出力はプログラムが開始されるときにはオープンされていますそれぞれのフ

ァイルポインタは stdin stdout になっていますfopen() fclose() をせずとも使用することができます

scanf() 標準出力ストリームからテキストを読み込み解釈します include ltstdiohgt int scanf( const char format [ address ] ) 戻り値正しくスキャンし変換し格納した入力フィールドの数を返しますファイルエンドを読

み込んだ場合は戻り値は EOF となります値を格納したフィールドがなかった場合は戻り値は0となります

一連の入力フィールドをスキャンして1度に1文字ずつストリーム stdin から文字を読み込み

ます次に引き数 format によって指される書式文字列中の書式指定に従って各フィールドを書式化します最後にformat の後に続く各引き数が示しているアドレスに書式化した入力を格納していきます書式文字列中の書式指定の個数はその後に続くアドレスの数と同じでな

ければなりません 書式指定[入力幅][型指定文字] 入力幅 読むべき文字数の最大値 型指定文字 次のとおりです 型指定文字 期待される入力 引き数の型 d 10進整数 int へのポインタ( int arg ) x 16進整数 int へのポインタ( int arg ) f 浮動小数点数 float へのポインタ( float arg ) s 文字列 文字配列へのポインタ( char arg[] ) c 文字 文字へのポインタ( char arg )

printf() フォーマットを指定してテキスト標準出力ストリームに出力します include ltstdiohgt int printf( const char format [ argument ] ) 戻り値出力したバイト数を返しますエラーの場合は EOF を返します

34

format によって指される書式文字列中の書式指定をformat の後に続く各引き数に適用し

書式化されたデータを stdout に出力します書式指定は後に続く引き数と同じ数だけなければなりません

書式指定[印字幅][精度][型指定文字] 印字幅 印字する最小文字数 精度 印字する最大文字数 型指定文字 つぎのとおりです 型指定文字 入力引き数 出力の書式 d 整数 符号付き10進整数 x 整数 符号無し16進整数 f 浮動小数点 符号付きの dddddddd形式の値 c 文字 1個の文字 s 文字列ポインタ ヌル文字に出会うか精度に達するまで 文字をプリントする

fopen()fclose()関数について fopen() ファイルをオープンします

include ltstdiohgt FILE fopen( char filename char mode ) 戻り値正常にファイルのオープンができたらファイルポインタを返しますエラーがあった場

合には NULLを返します 文字列 filename で指定されたファイルをオープンしますオープン後の入出力のモードに

ついては文字列 mode で指定しますmode に指定できる文字は以下のとおりです r 入力モードでオープンします w 出力モードでオープンします a 存在するファイルに追加して出力するモードでオープンします r+ 既に作成してあるファイルを更新(入力出力)するモードでオープンします w+ 新しく作成するファイルを更新モードでオープンします a+ 既に作成してあるファイルの終りから更新用に作成します

以上の文字に b をつけ加えることによりバイナリモードで入出力することができるようになり

ます rb バイナリの入力モードでオープンします wb バイナリの出力モードでオープンします ab 存在するファイルに追加して出力するモード(バイナリ)でオープンします

fclose() 既にオープンしてあるファイルをクローズします include ltstdiohgt fclose( FILE fp ) 既にオープンしているファイルをクローズしますパラメータには fopen() 関数により返された

ファイルポインタを指定します

35

テキストモードとバイナリモード 行の最後はテキストモードの場合改行コードのみとなりバイナリモードの場合には復帰

コードと改行コードの組合わせになります行の最後としてテキストファイルには復帰コード改行

コードが書かれていますがテキストモードでオープンした場合には入力すると改行コードのみに

変換されて入力されますバイナリモードの場合には復帰コード改行コードがそれぞれ入力され

ます

fputs()fgets()関数について fputs() ファイルポインタで指定されるファイルに文字列を出力します

include ltstdiohgt

int fputs( char s FILE fp ) fputs() は NULL で終る文字列 s をファイルポインタに示されるファイルへ出力しますputs()

と違い最後に改行文字 yenn を出力することはありません

fgets() ファイルポインタで指定されるファイルから文字列を入力します include ltstdiohgt char fgets( char s int n FILE fp ) 戻り値正常に入力した場合には引数 s の値が返されますエラーやEOFになった場合に

は NULL が返されます fgets() はファイルポインタで指定されるファイルから ( n - 1 ) 文字または改行文字までの

文字列を入力しs に格納しますgets() と異なり最後に入力された改行文字は NULL 文字に変更されません

標準入力から入力しファイルへ出力する ファイルへ出力あるいは入力を行う場合には改行コードの変換(入力の場合の削除出力の

場合の付加)はされませんしたがって標準入力から入力しファイルへ出力する場合には改行

コードを付加しなければなりません include ltstdiohgt main() char data[80] FILE fp fp = fopen( data w ) while( gets( data ) = NULL ) strcat( data yenn ) 改行コードの付加

fputs( data fp ) fclose( fp )

36

fputc()fgetc()関数について fputc() ファイルポインタで指定されるファイルに1文字出力します

include ltstdiohgt int fputc( int c FILE fp ) 戻り値正常に出力できた場合には文字 c を返しエラーの場合には EOF を返します fputc() は文字 c をファイルポインタで示されるファイルへ出力します

fgetc() ファイルポインタで指定されるファイルから1文字入力します

include ltstdiohgt int fgetc( FILE fp ) 戻り値正常に入力した場合には入力した文字を返しますエラーやEOFになった場合には

EOF が返されます fgetc() はファイルポインタで指定されるファイルから文字を入力します

ファイルの内容の表示 include ltstdiohgt main() FILE fp int ch char fname[30] printf( Key in Fila name gt ) gets( fname ) fp = fopen( fname r ) while( ( ch = fgetc( fp ) ) = EOF )putchar( ch ) fclose( fp )

その他テキスト中で使用された関数について sin() 三角関数の正弦を計算します

include ltmathhgt double sin(double radian) sinはラジアンを単位とする引数 radianの三角関数を計算します

37

strcpy() 文字列を他の文字列へコピーします

include ltstringhgt char strcpy(char string1const char string2) strcpyは引数 string2の指す文字列を null文字まで含めて引数 string1の指す領域にコピ

ーする strcpyは string1を返します

strcat() ある文字列を他の文字列に加えます

include ltstringhgt char strcat( char dest const char src ) 戻り値連結された文字列へのポインタを返します strcat() はsrc のコピーを dest の最後につけ加えます得られる文字列の長さは

strlen(dest)+strlen(src) になります

fabs() 絶対値の計算をします include ltmathhgt double fabs(double z) fabsは倍精度浮動小数の絶対値を計算して返しますつまりzgt=0であれば z をzlt0であ

れば-zを返します exp() 指数関数を計算します

include ltmathhgt double exp(double z) exp は引数zの指数関数つまりezを返すここではeは自然対数の底を表します対数関

数logの逆関数です

38

付 録 2 コンパイルの方法には大きく分けて第4章の実習で学んだようにデータファイルを作成してお

き ccg でコンパイルさせる方法と実行中に対話型でデータを入力していく方法があります ここでは対話型で実行を進めていく方法を紹介します ただしこの方法は計算(cpu)時間が10秒以内のものに限ります10秒を超える計算(cpu)時

間を要する場合はccg でコンパイルをするようにしてください 第4章実習の(2)(p16)までは同様です

コンパイル

コンピュータに処理を依頼します 60us1234boseicc cc rensyuc

所有するファイルの一覧を見てみます

60us1234boseicc ls -l larr 持っているファイルの一覧を見るコマンドです

-rw-r--r-- 1 60us1234 other 128 4月26日 15時14分 rensyuc -rwxr-xr-x 1 60us1234 other 361 4月26日 15時16分 aout

aout という実行形式のファイルが作成されています

実行

60us1234boseicc aout12 35[リターン] データを入力

1 200000 3500000 4200000 実行結果の出力

60us1234boseicc

注意

aout ファイルは印刷することができません実行結果を印刷する場合にはファイルに落とし てから出力するようにしましょう

60us1234boseicc aout gt kekka12 35[リターン] データを入力

60us1234boseicc more kekka 計算結果の確認 60us1234boseicc lpr kekka 計算結果の印刷

39

Page 14: n 第1章 章立ての部分は、書式(PC入門大見出し)を …第2章 数の表現 2-1 2進数 電子計算機の動作原理は0と1で表される2進数です。また、人間が日常生活で扱っている数

3-6 動的変数と静的変数 通常Cで使用される変数はその関数の中だけでのみ使用できる変数ですしたがって関数

が実行するときに関数の中で使用する変数の領域を確保し関数の実行が終るときにその領域

を解放するようにしてメモリを効率的に利用していますこのように関数が実行されるときに確

保される変数を動的変数(auto変数 )と呼びます プログラムの中ではその他に常に存在し使用できる変数を定義することができますそのよ

うな変数は静的変数(static変数 )と呼ばれます

func() int a b static int x y

また static 変数には内部的なリンケージの指定の意味もありますつまり関数の外で変数

を宣言すると自動的にグローバル変数となり他のプログラムからも使用することができるようにな

ります ファイル a ファイル b このような場合にはコンパイル単位が異なっていてもextern 宣言を行うことにより変数 abc

を使用することができますところが関数の外で static 宣言をして定義した変数についてはコンパイル単位が違うプログラムからは使用することができなくなります ファイル a ファイル b 同一コンパイル単位(ファイル)に存在する関数 sub()と subd()では変数 abcを使用することが

できますがコンパイル単位(ファイル)が異なる関数 func()では変数 abcを使用することはできません

int abc sub() abc = 10

func() extern int abc printf( ldquo abc =dyennrdquo abc )

static int abc sub() abc = 10 subd() abc++

func() extern int abc printf( ldquo abc =dyennrdquo abc )

12

3-7 スタック プログラム中にはプログラム領域データ領域の他にスタック領域があり一時的な作業領域と

して使用されています関数間での引数の受渡しの時にもこの領域を使用しますスタック領域に

データを格納することを「スタックに積む」ともいいます基本的にはスタック領域に格納されたデ

ータは最後に格納されたデータから順に取り出されることになります以下に格納が行われたとき

のスタックの状態を示します記号は次に格納すべき位置(スタックポインタの値)を示していま

逆にスタックからデータを取り出すときにはスタックポインタが指している位置の一つ下から取

り出すことになりますスタックからデータを取り出すときのスタックの状態は次のようになります

なり

10

20

10

30

20

10

40

30

20

10

10rarr

格納

20rarr

格納

30rarr

格納

40rarr

格納

40rarr 30rarr

関数を呼び出すときには次

逆にそれぞれの関数から

次のようになります

40

30

20

10

取出

main() z = f1( x y )

のようにパラメータがスタ

戻るときにはパラメータで

30

20

10

取出

f1( int a int b ) c = f2( d e

xの値 yの値

xの値 yの値

13

ックに格納されます

使用していたスタック領域は自動的になく

10

20

)

f2( int p int q ) r = p + q

xの値

eの値 dの値

yの値

xの値 yの値

dの値

eの値

3-8 再帰呼び出し 関数の引数の受渡しがスタックを利用して行われることから自分で自分自身の関数を呼び出

すことができます 以下のプログラムは入力した値の階乗を計算するプログラムです

3の階乗を求めることを考えてみます

return 文によって戻るときは次のようにして値を返します kai( 3 ) 3 kai( 3-1 ) 2 kai( 2-1 ) return 1

6 3 (2 1) 2 1 以上の計算から3=6が導き出されます 再帰呼び出しのことをリカーシブコールともいいます

include ltstdiohgt main() int n m kai() scanf( ldquodrdquoampn ) m = kai( n ) printf( ldquod = dyennrdquo n m )

int kai( int k ) if( k == 1 )return 1 else return k kai( k ndash 1 )

kai( 1 )

darr

return 1

kai( 2 )

darr

2 kai( 2-1 )

kai( 3 )

darr

3 kai( 3-1 )

main()

darr

kai( 3 )

3

2

1

2

3

1

2

3 3

32

32

1

2

1

3

3

演習6 1からnまでの総和を再帰呼び出しを使って計算する関数 sowa() を作りなさい n+(n-1)+ +2+1

14

第4章 実習 この章ではプログラムを実際に入力して実行するまでの手順を実習します

4-1 操作手順 (1)ログイン

[スタート]rarr[プログラム(P)]rarr[ネットワーク] Hostの欄に bosei を記述選択 rarr [Telnet(FreeWare)] を選択します して 「OK」 ボタンをクリックします

UP-UXV (Rel42MP) (bosei) (pts41) login 60us1234 larr 各自のログイン名を入力します Password larr パスワードを入力しても画面は何も変化しません 101 60us1234bosei larr セッションが開設されましたこれをプロンプトといいます この状態でコマンドを入力することができます

(2)プログラムの作成 以下のコマンドを入力しテキストエディタを起動します 60us1234boseicc ng rensyuc

すると下図のようにngエディタの画面になります

15

次のように入力します入力ミスの修正はBSキーで行ないます

include ltstdiohgt main() float abc scanf(f f ampaampb) c=ab printf(f f f yenn abc)

CTRL キーを押しながら XCTRL キーを押しながら C を押しますすると次のメッセージが画面下に表示されます

Save file uhomea60us1234rensyuc (y or n)

このメッセージに対して y と答えます

(3)データの作成 以下のコマンドを入力しテキストエディタを起動します 60us1234boseicc ng rensyud

ngエディタの画面になりますので次のように入力します 12 35

CTRLキーを押しながら XCTRLキーを押しながら C を押します save file uhomea60us1234rensyud (y or n)

このメッセージに対して y と答えます

(4)コンパイルと実行 コンピュータに処理を依頼します 60us1234boseicc ccg rensyu

ジョブを投入しましたジョブの状態を見るコマンドは myjobです

16

130 60us1234boseicc myjob ================================================= NQS (R0220) BATCH REQUEST HOST bosei ================================================= REQUEST ID NAME OWNER QUEUE PRI NICE STT PGRP R --------------- -------- -------- -------- ---- --- --- ------ - 99321bosei STDIN 60us1234 A 31 0 RUN 14161 - ---------------------------------------------------------------- ================================================== NQS (R0220) DEVICE REQUEST HOST bosei ジョブは実行中です

================================================== REQUEST ID NAME OWNER QUEUE PRI SIZE STT -------------------------------------------------------------

所有するファイルの一覧を見てみます

60us1234boseicc ls -l larr 持っているファイルの一覧を見るコマンドです

-rw-r--r-- 1 60us1234 other 4 4月26日 15時14分 rensyud -rw-r--r-- 1 60us1234 other 128 4月26日 15時10分 rensyuc -rwxr-xr-x 1 60us1234 other 361 4月26日 15時16分 rensyul

(5)計算結果の確認

計算結果を画面に表示して確認します 60us1234boseicc more rensyul

(6)印刷

計算結果の印刷を行ないます5号館2階のカフェテリア室にある bosei のプリンタに印刷 されます

60us1234boseicc lpr rensyul

(7)ログアウト セッションを終了します 60us1234boseicc logout

(8)実行の流れ

エラー

プログラムの作成 ログイン コンパイル実行

確 認 印 刷 ログアウト

17

第5章 配列 多数の変数をまとめて宣言する方法として配列があります配列の一つ一つは配列要素と呼

ばれ変数と同じ性格を持っています配列の宣言は型宣言と同時に次のように行います int a[5] 配列 a

a[0]

a[1]

a[2]

a[3]

a[4]

二次元配列(一次元配列を複数集めたもの)を宣言する場合には次のようになります int b[3][4] 配列 b

b[0][0] b[0][1] b[0][2] b[0][3]

b[1][0] b[1][1] b[1][2] b[1][3]

b[2][0] b[2][1] b[2][2] b[2][3]

配列要素に数値を代入する場合は次のようになります b[1][2]=10

5-1 二次元配列要素の初期化 変数の型宣言と同じように配列を宣言するときに初期値も同時に設定することができます

複数のデータがある場合には{}記号でくくって指定します int b[3][4] = 2 4 6 8 1 3 5 7 1 2 3 4

文字型配列の場合には以下のようになりますyen0 は文字列の終わりを表わします char univ[3][7] = T O K A I yen0 S I M I Z U yen0 Y O Y O G I yen0

また文字列定数として初期化することもできますこの場合コンパイル時に自動的に yen0 が付加されます

char univ[3][7] = TOKAI SIMIZU YOYOGI

18

[プログラム例] 二次元配列のタテヨコを加算するプログラム

include ltstdiohgt main() int mat[4][3]=123456789101112 int ijytotalttotal[3]total=0 for(j=0jlt3j++)ttotal[j]=0 for (i=0ilt4i++) ytotal=0 for(j=0jlt3j++) ytotal += mat[i][j] ttotal[j] += mat[i][j] total += mat[i][j] printf(3dmat[i][j]) printf( 3dyennytotal) printf(yenn) for(j=0jlt3j++)printf(3dttotal[j]) printf( 3dyenntotal)

[実行結果]

1 2 3 6 4 5 6 15 7 8 9 24 10 11 12 33 22 26 30 78

演習7

a)以下の配列はどのように初期化されるか答えなさい char errmsg[2][15] = Divide Error Overflow Error

b)九九の計算を2次元配列を使って求めなさい

19

第6章 ポインタ型変数 C言語では値を記憶するための変数だけではなく変数または定数の番地を記憶するため

のポインタ型変数を宣言することができますポインタとはデータ項目の一種で「記憶装置(メモ

リ)上の格納番地(アドレス)を指すデータ項目」です アドレス コンピュータの中ではデータ項目の格納番地のことをアドレス(住所)と呼びます 例えば記憶装置という名前のとてつもなく大きなマンションがあるとしますその中から Aさんを捜すときは部屋番号を参照しますマンションでは部屋番号で住居人を参照し ているのと同じようにコンピュータでは記憶装置上に確保された変数は格納番地 (アドレス)で管理されています

マンション 部屋番号 記憶装置 格納番地

Aさん Int a Bさん Cさん AAAさん BBBさん CCCさん

1号室

2号室

3号室

100号室

200号室

300号室

100番地

200番地

300番地

1000番地

2000番地

3000番地

Int b Int c float aaafloat bbbfloat ccc

ポインタ ポインタとは「指し示すもの」の意ですがC言語では記憶装置上のアドレスを指し示す もののことです上のマンションの例では部屋番号を格納するデータ項目ということに なりますAAAさんは100号室に住んでいます100という値をポインタのデータ項目に 記憶するとそのデータ項目は間接的にAAAさんを指すことになります

6-1 ポインタ型変数の宣言および参照 通常の変数と区別するために型宣言時に変数名の前に記号を付けて宣言します int a 整数型ポインタ変数 int b 整数型変数

変数 a は整数型の値を記憶するのではなく整数型の値を持つ変数などの番地を記憶する変数ですまた変数 b は通常の整数型の値を記憶するための変数です

20

include ltstdiohgt main() int a b c a はポインタ型の変数b c は整数型の変数 b = 12 変数 b に値 12 を代入します a = ampb 変数 a には変数 b の番地が代入されます c = a + 10 変数 a の指す変数(b)の内容と10の加算です つまり12 + 10 を変数 c に代入します

変数の型宣言において変数名に記号を付けることによりその変数はポインタ型の変数と

なりますポインタ型の変数は変数名のみを指定した場合には単にその変数の値(通常はメモリ

の番地)を表します変数名に記号を付けて使用した場合にはその変数が指し示している変

数の内容を表します c = a ポインタ型変数 a が指している値を変数 c に代入

ポインタ型の変数に番地を記憶させるためにはプログラム例のように変数名の前に記号を

指定します変数名 によって変数の番地(アドレス)を表します a = ampb 変数 b の番地をポインタ型変数 a に代入します

ポインタ型変数の型はポインタ型変数が指し示す先の変数の型を表しています int a 変数 a 整数型の値 float x 変数 x 実数型の値 char c 変数 c 文字型の値

6-2 ポインタ型変数の初期化 ポインタ型変数も型宣言のときに変数を初期化することができます特に文字型のポインタ変

数の場合によく使います char str = TOKAI University

ポインタ型変数 str は文字列定数 TOKAI University の最初の文字が格納されている番地を初期値として持つことになります

変数 str TOKAI University 文字列定数

[プログラム例]

(1)文字型配列 putchar() 関数を使って一次元の文字型配列を出力します include ltstdiohgt main() char str[6] = TOKAI int i for( i = 0 str[i] = yen0 i++ ) putchar( str[i] )

21

ポインタを使用した場合には以下のようになります include ltstdiohgt main() char str[6] = TOKAI char chp for( chp = str chp = yen0 chp++ ) putchar( chp )

chp str T [0] O K A I yen0 [5]

参照する変数 配列の表現 ポインタの表現 実際のアドレス 1番目の数 str[0] chp CHP 2番目の数 str[1] (chp+1) CHP+1 n番目の数 str[n-1] (chp+n-1) CHP+n-1 6番目の数 str[5] (chp+5) CHP+5

注意実際のアドレス CHPは実行時に決定されます

(2)二次元文字型配列 二次元の文字型配列に定数を設定しそれを出力するプログラムです文字型配列を使用す

ると次のとおりになります include ltstdiohgt main() char str[5][40] = TOKAI shounan campus NEC DEC int i for( i = 0 i lt 5 i++ ) printf( yenns str[i] )

40 バイト str TOKAI shounan campus NEC DEC

22

ポインタ型配列を使用すると次のとおりになります include ltstdiohgt main() char str[6] = TOKAI shounan campus NEC DEC NULL char chp for( chp = str chp = NULL chp++ ) printf( yenns chp ) str

chp 番地 TOKAI 番地 shounan 番地 campus 番地 NEC 番地 DEC

NULL

演習8 キーボードまたはデータファイルから読み込んだ文字列中にrsquoArsquo があったら rsquoarsquo に変換 するプログラムを配列とポインタを使って書きなさい

23

第7章 構造体共用体 7-1 構造体

プログラムの規模が大きくなるにつれて多数の intや floatcharなどのデータ型を扱うようになり複雑になってきますそこで多数のデータを1つにまとめて簡単に扱える機能が構造体です 構造体について住所録のデータを例にあげて考えてみます

住所録の個人データとして氏名住所電話番号年齢の項目を一つのデータとします これをC言語で変数の定義をすると次のようになります 氏名東海太郎 char name[30] 住所平塚市北金目1117 char address[30] 電話番号0463-58-1211 char tel[20] 年齢30 int age 個人の住所録データ C言語での表現 このような住所録の個人データを1つにまとめて新しいデータとして定義する機能を構造体と言

います struct 構造体タグ名 構造体メンバーの並び

「struct」は構造体を表すキーワードです 「構造体タグ名」は構造体の型枠を宣言しますここは自由に名前を定義することができ ます 「構造体メンバーの並び」は構造体の要素です複数指定できます

個人の住所録のデータを構造体で宣言すると次のようになります

struct jusho char name[30] char address[30] 構造体のメンバーの並び char tel[20] (複数可)

int age

上記の宣言では構造体の形式を宣言しているだけでメモリ中で実際の領域を確保している

わけではありません実際に領域を確保するためには次のように定義します

struct 構造体タグ名 構造体名

したがって構造体名を jdata とすると次のように指定します

struct jusho jdata

構造体 jdataは次のように構造体タグ jushoの形式で領域を確保します

24

Jdata name[30]

address[30] tel[20] age

(1)構造体の参照

プログラム中で構造体中のメンバーを参照する場合には次のように指定します 構造体名メンバー名

したがって「名前」を参照したいときには次のように指定します

jdataname

[プログラム例]

名前住所電話番号年齢を定義しそれを印字します include ltstdiohgt include ltstringhgt main() struct jusho char name[30] char address[30] char tel[20] int age struct jusho jdata strcpy( jdataname 東海 太郎) strcpy( jdataaddress 平塚市北金目1117)

strcpy( jdatatel 0463-58-1211) jdataage = 30 printf(yenn氏名 = syenn jdataname) printf(yenn住所 = syenn jdataaddress) printf(yenn電話番号= syenn jdatatel) printf(yenn年齢 = dyenn jdataage)

また構造体の形式の定義と領域の確保は次のように同時におこなうことができます

struct 構造体タグ名 構造体メンバーの並び 構造体名

struct jusho struct jusho char name[30] char name[30] char address[30] char address[30] char tel[30] = char tel[30] int age 同じ int age

jdata struct jusho jdata

型宣言と同時にメモリ上に領域を確保する方法 後からメモリ上に領域を確保する方法

25

(2) 構造体配列 住所録データの場合その中に入るデータは1件ではありませんやはり100件200件のデ

ータが必要になる場合がありますこのように個人単位のデータを多数扱う場合には構造体を配

列として宣言することができます 次の例は個人のデータを100個用意するために構造体を配列として宣言しています struct jusho jdata[100] jdata[0] name[30] address[30] tel[20] age

jdata[99 ] name[30] address[30] tel[20] age

(3)構造体配列の参照

プログラム中で構造体配列中のメンバーを参照する場合には次のように指定します 構造体名[要素番号]メンバー名

したがって10件目の人の「名前」を参照したいときには次のように指定します

jdata[10]name

[プログラム例]

名前住所電話番号年齢を定義しそれを印字します include ltstdiohgt include ltstringhgt main() struct jusho char name[30] char address[30] char tel[20] int age jdata[100] strcpy( jdata[10]name 東海 太郎) strcpy( jdata[10]address 平塚市北金目1117)

strcpy( jdata[10]tel 0463-58-1211) jdata[10]age = 30 printf(yenn氏名 = syenn jdata[10]name) printf(yenn住所 = syenn jdata[10]address) printf(yenn電話番号= syenn jdata[10]tel) printf(yenn年齢 = dyenn jdata[10]age)

26

(4) 構造体のポインタ 変数と同じように構造体へのポインタも定義することができます

変数へのポインタ例 構造体へのポインタ例 またポインタを使用して構造体メンバーを参照するには次のように -> 記号を使って指

定します ポインタ変数名 -> メンバー名

[プログラム例]

名前住所電話番号年齢を定義しそれを印字します include ltstdiohgt include ltstringhgt main() struct jusho char name[30] char address[30] char tel[20] int age jdatakp kp = ampjdata strcpy( kp-gtname 東海 太郎)

strcpy( kp-gtaddress 平塚市北金目1117)

strcpy( kp-gttel 0463-58-1211) kp-gtage = 30 printf(yenn氏名 = syenn kp-gtname) printf(yenn住所 = syenn kp-gtaddress) printf(yenn電話番号= syenn kp-gttel) printf(yenn年齢 = dyenn kp-gtage)

kp jdata

name[30] ポインタ型の変数 address[30]

tel[20]

構造体へのポインタを記憶 age

することができます

int a int b b = ampa

struct name jname struct name np np = ampname

27

7-2 共用体 共用体は構造体と同じようにして宣言しますが共用体は複数のデータ型を同一のアドレスに

割り当てる方法です union 共用体タグ名 共用体メンバーの並び

「union」は共用体を表すキーワードです 「共用体タグ名」は共用体の型枠の名前を宣言しますここは自由に名前を定義することがで

きます 「共用体メンバーの並び」は共用体の要素です複数指定できます

共用体の宣言の例を次に示します

union c_tag int a char b

共用体 cは次のように共用体タグ c_tagの形式で領域を確保します共用体はメモリ上に領域を確保するときは ab ともに同じ領域に割り付けられます これはab という2つのデータが同時に存在するわけではなく cを異なるデータ abで共有す

ることを表しています c a b

上記の宣言だけでは共用体の形式を宣言しているだけでメモリ中で実際の領域を確保して

いるわけではありません実際に領域を確保するためには次のように定義します union 構造体タグ名 構造体名

したがって共用体名を c とすると次のように指定します

union c_tag c

(1)共用体の参照

プログラム中で共用体中のメンバーを参照する場合には次のように指定します 共用体名メンバー名

したがって「a」または「b」を参照したいときには次のように指定します

ca (int 型) cb (char 型)

メンバー参照方法によって int型として使ったりchar型として利用することができます

28

[プログラム例]

includeltstdiohgt main() union data char a short b int c chk chkc = 0x12345678 printf( char a xyennchka) printf( short b xyennchkb) printf( int c xyennchkc)

chkb(int 型) chkb(short 型) chka(char 型) 12 12 12 34 34 56 78

29

第8章 アルゴリズム コンピュータに何か仕事をさせようとするときは仕事を具体的に実行するための処理や動作

の手順が必要ですこの「手順」がアルゴリズムです アルゴリズムを考えるときは解くべき問題をはっきりと定義することが必要です

8-1 ソート ソートとは与えられたデータを小さい順または大きい順に並べ換えることですソート方法は

いくつかありますが基本的な方法でソートするアルゴリズムを紹介します

includeltstdiohgt int data[10] main()

int data_in() sort() data_in() sort() int data_in() データ入力関数

int a printf(数値入力yenn)

for(a=0alt=9a++) printf( [d]a+1) scanf(dampdata[a]) int sort() ソート処理を行う関数

int cont1cont2tmp1tmp2mim for(cont1=0 cont1lt=9 cont1++) mim=data[cont1] tmp1=cont1 for(cont2=cont1+1 cont2lt=9 cont2++) if(data[cont2] lt mim) mim=data[cont2] tmp1=cont2 tmp2 = data[cont1] data[cont1] = data[tmp1] data[tmp1] = tmp2 printf(結果 yenn)

for (cont1 = 0 cont1 lt= 9 cont1++) printf(d yenn data[cont1])

30

第9章 プリプロセッサ C言語にはプログラムの中でコンパイルについての指示を行う「プリプロセッサ」という機能が

ありますまたプリプロセッサとはコンパイルする前に実行されるためその意味のとおり「前処理」 と呼ばれていますここでは代表的なものをいくつか説明します

9-1 ファイルの挿入 ソースプログラム中に指定されたファイルを挿入します

include ltstdiohgt helliphellip 標準ディレクトリを探します include progh helliphellip 現在のディレクトリを探しなければ標準ディレクトリを探します

includeltstdiohgt によって組み込まれた define EOF (-1) define EOF (-1) define define helliphelliphelliphellip 組み込み helliphelliphelliphellip

main() stdiohファイル

int helliphelliphelliphellip helliphelliphelliphellip

ソースファイル

9-2 文字の置換 プログラム中に使われている文字列を別の文字列に置き換えます

include ltstdiohgt define TRUE 1 define EOF (-1) main() define helliphellip helliphellip

while(TRUE) define TRUE 1 置き換え main() helliphellip helliphellip while(1)

break helliphelliphellip

31

9-3 条件によるコンパイル 識別子が定義されているか否かを判断しコンパイルする範囲を指定します

include ltstdiohgt define UNIX main() ifdef UNIX printf( UNIX yenn) else printf(MS-DOSyenn) endif

include ltstdiohgt define OS UNIX main() if OS == UNIX printf( UNIX yenn) else printf(MS-DOSyenn) endif

32

付 録 1 puts()gets()関数について

行単位に入出力を行う場合には puts() gets() 関数を用います

puts() 標準出力に文字列を出力します

include ltstdiohgt int puts( char s ) puts() は NULL で終る文字列 s を標準出力に出力し最後に改行文字 yenn も出力しま

gets() 標準入力から文字列を入力します

include ltstdiohgt char gets( char s ) 戻り値正常に入力した場合には引数 s の値が返されますエラーやEOFになった場合に

は NULL が返されます gets() は標準入力から復帰文字で終る文字列を入力しs に格納しますこのとき最後の復

帰文字は NULL文字に変更されます

入力行の出力 標準入力から gets() で入力したデータには改行コードは含まれませんまた標準出力へ

puts() で出力を行う場合には必ず改行コードが付加されますgets() を実行したときの戻り値としてファイルの終端を検出した場合には EOF ではなく NULL が返されますので注意して下さい

include ltstdiohgt main() char data[80] while( gets( data ) = NULL )puts( data )

putchar()getchar()関数について putchar() 標準出力に文字を出力します

include ltstdiohgt int putchar(int c ) 戻り値正常に出力できた場合には文字cをエラーの場合にはEOFを返します

33

getchar() 標準入力から文字を入力します

include ltstdiohgt int getchar(void) 戻り値正常に入力した場合には読み込んだ文字を int 型に変換して返しますまたファイ

ルエンドエラーの場合にはEOFを返します

標準入力標準出力

標準入力標準出力はプログラムが開始されるときにはオープンされていますそれぞれのフ

ァイルポインタは stdin stdout になっていますfopen() fclose() をせずとも使用することができます

scanf() 標準出力ストリームからテキストを読み込み解釈します include ltstdiohgt int scanf( const char format [ address ] ) 戻り値正しくスキャンし変換し格納した入力フィールドの数を返しますファイルエンドを読

み込んだ場合は戻り値は EOF となります値を格納したフィールドがなかった場合は戻り値は0となります

一連の入力フィールドをスキャンして1度に1文字ずつストリーム stdin から文字を読み込み

ます次に引き数 format によって指される書式文字列中の書式指定に従って各フィールドを書式化します最後にformat の後に続く各引き数が示しているアドレスに書式化した入力を格納していきます書式文字列中の書式指定の個数はその後に続くアドレスの数と同じでな

ければなりません 書式指定[入力幅][型指定文字] 入力幅 読むべき文字数の最大値 型指定文字 次のとおりです 型指定文字 期待される入力 引き数の型 d 10進整数 int へのポインタ( int arg ) x 16進整数 int へのポインタ( int arg ) f 浮動小数点数 float へのポインタ( float arg ) s 文字列 文字配列へのポインタ( char arg[] ) c 文字 文字へのポインタ( char arg )

printf() フォーマットを指定してテキスト標準出力ストリームに出力します include ltstdiohgt int printf( const char format [ argument ] ) 戻り値出力したバイト数を返しますエラーの場合は EOF を返します

34

format によって指される書式文字列中の書式指定をformat の後に続く各引き数に適用し

書式化されたデータを stdout に出力します書式指定は後に続く引き数と同じ数だけなければなりません

書式指定[印字幅][精度][型指定文字] 印字幅 印字する最小文字数 精度 印字する最大文字数 型指定文字 つぎのとおりです 型指定文字 入力引き数 出力の書式 d 整数 符号付き10進整数 x 整数 符号無し16進整数 f 浮動小数点 符号付きの dddddddd形式の値 c 文字 1個の文字 s 文字列ポインタ ヌル文字に出会うか精度に達するまで 文字をプリントする

fopen()fclose()関数について fopen() ファイルをオープンします

include ltstdiohgt FILE fopen( char filename char mode ) 戻り値正常にファイルのオープンができたらファイルポインタを返しますエラーがあった場

合には NULLを返します 文字列 filename で指定されたファイルをオープンしますオープン後の入出力のモードに

ついては文字列 mode で指定しますmode に指定できる文字は以下のとおりです r 入力モードでオープンします w 出力モードでオープンします a 存在するファイルに追加して出力するモードでオープンします r+ 既に作成してあるファイルを更新(入力出力)するモードでオープンします w+ 新しく作成するファイルを更新モードでオープンします a+ 既に作成してあるファイルの終りから更新用に作成します

以上の文字に b をつけ加えることによりバイナリモードで入出力することができるようになり

ます rb バイナリの入力モードでオープンします wb バイナリの出力モードでオープンします ab 存在するファイルに追加して出力するモード(バイナリ)でオープンします

fclose() 既にオープンしてあるファイルをクローズします include ltstdiohgt fclose( FILE fp ) 既にオープンしているファイルをクローズしますパラメータには fopen() 関数により返された

ファイルポインタを指定します

35

テキストモードとバイナリモード 行の最後はテキストモードの場合改行コードのみとなりバイナリモードの場合には復帰

コードと改行コードの組合わせになります行の最後としてテキストファイルには復帰コード改行

コードが書かれていますがテキストモードでオープンした場合には入力すると改行コードのみに

変換されて入力されますバイナリモードの場合には復帰コード改行コードがそれぞれ入力され

ます

fputs()fgets()関数について fputs() ファイルポインタで指定されるファイルに文字列を出力します

include ltstdiohgt

int fputs( char s FILE fp ) fputs() は NULL で終る文字列 s をファイルポインタに示されるファイルへ出力しますputs()

と違い最後に改行文字 yenn を出力することはありません

fgets() ファイルポインタで指定されるファイルから文字列を入力します include ltstdiohgt char fgets( char s int n FILE fp ) 戻り値正常に入力した場合には引数 s の値が返されますエラーやEOFになった場合に

は NULL が返されます fgets() はファイルポインタで指定されるファイルから ( n - 1 ) 文字または改行文字までの

文字列を入力しs に格納しますgets() と異なり最後に入力された改行文字は NULL 文字に変更されません

標準入力から入力しファイルへ出力する ファイルへ出力あるいは入力を行う場合には改行コードの変換(入力の場合の削除出力の

場合の付加)はされませんしたがって標準入力から入力しファイルへ出力する場合には改行

コードを付加しなければなりません include ltstdiohgt main() char data[80] FILE fp fp = fopen( data w ) while( gets( data ) = NULL ) strcat( data yenn ) 改行コードの付加

fputs( data fp ) fclose( fp )

36

fputc()fgetc()関数について fputc() ファイルポインタで指定されるファイルに1文字出力します

include ltstdiohgt int fputc( int c FILE fp ) 戻り値正常に出力できた場合には文字 c を返しエラーの場合には EOF を返します fputc() は文字 c をファイルポインタで示されるファイルへ出力します

fgetc() ファイルポインタで指定されるファイルから1文字入力します

include ltstdiohgt int fgetc( FILE fp ) 戻り値正常に入力した場合には入力した文字を返しますエラーやEOFになった場合には

EOF が返されます fgetc() はファイルポインタで指定されるファイルから文字を入力します

ファイルの内容の表示 include ltstdiohgt main() FILE fp int ch char fname[30] printf( Key in Fila name gt ) gets( fname ) fp = fopen( fname r ) while( ( ch = fgetc( fp ) ) = EOF )putchar( ch ) fclose( fp )

その他テキスト中で使用された関数について sin() 三角関数の正弦を計算します

include ltmathhgt double sin(double radian) sinはラジアンを単位とする引数 radianの三角関数を計算します

37

strcpy() 文字列を他の文字列へコピーします

include ltstringhgt char strcpy(char string1const char string2) strcpyは引数 string2の指す文字列を null文字まで含めて引数 string1の指す領域にコピ

ーする strcpyは string1を返します

strcat() ある文字列を他の文字列に加えます

include ltstringhgt char strcat( char dest const char src ) 戻り値連結された文字列へのポインタを返します strcat() はsrc のコピーを dest の最後につけ加えます得られる文字列の長さは

strlen(dest)+strlen(src) になります

fabs() 絶対値の計算をします include ltmathhgt double fabs(double z) fabsは倍精度浮動小数の絶対値を計算して返しますつまりzgt=0であれば z をzlt0であ

れば-zを返します exp() 指数関数を計算します

include ltmathhgt double exp(double z) exp は引数zの指数関数つまりezを返すここではeは自然対数の底を表します対数関

数logの逆関数です

38

付 録 2 コンパイルの方法には大きく分けて第4章の実習で学んだようにデータファイルを作成してお

き ccg でコンパイルさせる方法と実行中に対話型でデータを入力していく方法があります ここでは対話型で実行を進めていく方法を紹介します ただしこの方法は計算(cpu)時間が10秒以内のものに限ります10秒を超える計算(cpu)時

間を要する場合はccg でコンパイルをするようにしてください 第4章実習の(2)(p16)までは同様です

コンパイル

コンピュータに処理を依頼します 60us1234boseicc cc rensyuc

所有するファイルの一覧を見てみます

60us1234boseicc ls -l larr 持っているファイルの一覧を見るコマンドです

-rw-r--r-- 1 60us1234 other 128 4月26日 15時14分 rensyuc -rwxr-xr-x 1 60us1234 other 361 4月26日 15時16分 aout

aout という実行形式のファイルが作成されています

実行

60us1234boseicc aout12 35[リターン] データを入力

1 200000 3500000 4200000 実行結果の出力

60us1234boseicc

注意

aout ファイルは印刷することができません実行結果を印刷する場合にはファイルに落とし てから出力するようにしましょう

60us1234boseicc aout gt kekka12 35[リターン] データを入力

60us1234boseicc more kekka 計算結果の確認 60us1234boseicc lpr kekka 計算結果の印刷

39

Page 15: n 第1章 章立ての部分は、書式(PC入門大見出し)を …第2章 数の表現 2-1 2進数 電子計算機の動作原理は0と1で表される2進数です。また、人間が日常生活で扱っている数

3-7 スタック プログラム中にはプログラム領域データ領域の他にスタック領域があり一時的な作業領域と

して使用されています関数間での引数の受渡しの時にもこの領域を使用しますスタック領域に

データを格納することを「スタックに積む」ともいいます基本的にはスタック領域に格納されたデ

ータは最後に格納されたデータから順に取り出されることになります以下に格納が行われたとき

のスタックの状態を示します記号は次に格納すべき位置(スタックポインタの値)を示していま

逆にスタックからデータを取り出すときにはスタックポインタが指している位置の一つ下から取

り出すことになりますスタックからデータを取り出すときのスタックの状態は次のようになります

なり

10

20

10

30

20

10

40

30

20

10

10rarr

格納

20rarr

格納

30rarr

格納

40rarr

格納

40rarr 30rarr

関数を呼び出すときには次

逆にそれぞれの関数から

次のようになります

40

30

20

10

取出

main() z = f1( x y )

のようにパラメータがスタ

戻るときにはパラメータで

30

20

10

取出

f1( int a int b ) c = f2( d e

xの値 yの値

xの値 yの値

13

ックに格納されます

使用していたスタック領域は自動的になく

10

20

)

f2( int p int q ) r = p + q

xの値

eの値 dの値

yの値

xの値 yの値

dの値

eの値

3-8 再帰呼び出し 関数の引数の受渡しがスタックを利用して行われることから自分で自分自身の関数を呼び出

すことができます 以下のプログラムは入力した値の階乗を計算するプログラムです

3の階乗を求めることを考えてみます

return 文によって戻るときは次のようにして値を返します kai( 3 ) 3 kai( 3-1 ) 2 kai( 2-1 ) return 1

6 3 (2 1) 2 1 以上の計算から3=6が導き出されます 再帰呼び出しのことをリカーシブコールともいいます

include ltstdiohgt main() int n m kai() scanf( ldquodrdquoampn ) m = kai( n ) printf( ldquod = dyennrdquo n m )

int kai( int k ) if( k == 1 )return 1 else return k kai( k ndash 1 )

kai( 1 )

darr

return 1

kai( 2 )

darr

2 kai( 2-1 )

kai( 3 )

darr

3 kai( 3-1 )

main()

darr

kai( 3 )

3

2

1

2

3

1

2

3 3

32

32

1

2

1

3

3

演習6 1からnまでの総和を再帰呼び出しを使って計算する関数 sowa() を作りなさい n+(n-1)+ +2+1

14

第4章 実習 この章ではプログラムを実際に入力して実行するまでの手順を実習します

4-1 操作手順 (1)ログイン

[スタート]rarr[プログラム(P)]rarr[ネットワーク] Hostの欄に bosei を記述選択 rarr [Telnet(FreeWare)] を選択します して 「OK」 ボタンをクリックします

UP-UXV (Rel42MP) (bosei) (pts41) login 60us1234 larr 各自のログイン名を入力します Password larr パスワードを入力しても画面は何も変化しません 101 60us1234bosei larr セッションが開設されましたこれをプロンプトといいます この状態でコマンドを入力することができます

(2)プログラムの作成 以下のコマンドを入力しテキストエディタを起動します 60us1234boseicc ng rensyuc

すると下図のようにngエディタの画面になります

15

次のように入力します入力ミスの修正はBSキーで行ないます

include ltstdiohgt main() float abc scanf(f f ampaampb) c=ab printf(f f f yenn abc)

CTRL キーを押しながら XCTRL キーを押しながら C を押しますすると次のメッセージが画面下に表示されます

Save file uhomea60us1234rensyuc (y or n)

このメッセージに対して y と答えます

(3)データの作成 以下のコマンドを入力しテキストエディタを起動します 60us1234boseicc ng rensyud

ngエディタの画面になりますので次のように入力します 12 35

CTRLキーを押しながら XCTRLキーを押しながら C を押します save file uhomea60us1234rensyud (y or n)

このメッセージに対して y と答えます

(4)コンパイルと実行 コンピュータに処理を依頼します 60us1234boseicc ccg rensyu

ジョブを投入しましたジョブの状態を見るコマンドは myjobです

16

130 60us1234boseicc myjob ================================================= NQS (R0220) BATCH REQUEST HOST bosei ================================================= REQUEST ID NAME OWNER QUEUE PRI NICE STT PGRP R --------------- -------- -------- -------- ---- --- --- ------ - 99321bosei STDIN 60us1234 A 31 0 RUN 14161 - ---------------------------------------------------------------- ================================================== NQS (R0220) DEVICE REQUEST HOST bosei ジョブは実行中です

================================================== REQUEST ID NAME OWNER QUEUE PRI SIZE STT -------------------------------------------------------------

所有するファイルの一覧を見てみます

60us1234boseicc ls -l larr 持っているファイルの一覧を見るコマンドです

-rw-r--r-- 1 60us1234 other 4 4月26日 15時14分 rensyud -rw-r--r-- 1 60us1234 other 128 4月26日 15時10分 rensyuc -rwxr-xr-x 1 60us1234 other 361 4月26日 15時16分 rensyul

(5)計算結果の確認

計算結果を画面に表示して確認します 60us1234boseicc more rensyul

(6)印刷

計算結果の印刷を行ないます5号館2階のカフェテリア室にある bosei のプリンタに印刷 されます

60us1234boseicc lpr rensyul

(7)ログアウト セッションを終了します 60us1234boseicc logout

(8)実行の流れ

エラー

プログラムの作成 ログイン コンパイル実行

確 認 印 刷 ログアウト

17

第5章 配列 多数の変数をまとめて宣言する方法として配列があります配列の一つ一つは配列要素と呼

ばれ変数と同じ性格を持っています配列の宣言は型宣言と同時に次のように行います int a[5] 配列 a

a[0]

a[1]

a[2]

a[3]

a[4]

二次元配列(一次元配列を複数集めたもの)を宣言する場合には次のようになります int b[3][4] 配列 b

b[0][0] b[0][1] b[0][2] b[0][3]

b[1][0] b[1][1] b[1][2] b[1][3]

b[2][0] b[2][1] b[2][2] b[2][3]

配列要素に数値を代入する場合は次のようになります b[1][2]=10

5-1 二次元配列要素の初期化 変数の型宣言と同じように配列を宣言するときに初期値も同時に設定することができます

複数のデータがある場合には{}記号でくくって指定します int b[3][4] = 2 4 6 8 1 3 5 7 1 2 3 4

文字型配列の場合には以下のようになりますyen0 は文字列の終わりを表わします char univ[3][7] = T O K A I yen0 S I M I Z U yen0 Y O Y O G I yen0

また文字列定数として初期化することもできますこの場合コンパイル時に自動的に yen0 が付加されます

char univ[3][7] = TOKAI SIMIZU YOYOGI

18

[プログラム例] 二次元配列のタテヨコを加算するプログラム

include ltstdiohgt main() int mat[4][3]=123456789101112 int ijytotalttotal[3]total=0 for(j=0jlt3j++)ttotal[j]=0 for (i=0ilt4i++) ytotal=0 for(j=0jlt3j++) ytotal += mat[i][j] ttotal[j] += mat[i][j] total += mat[i][j] printf(3dmat[i][j]) printf( 3dyennytotal) printf(yenn) for(j=0jlt3j++)printf(3dttotal[j]) printf( 3dyenntotal)

[実行結果]

1 2 3 6 4 5 6 15 7 8 9 24 10 11 12 33 22 26 30 78

演習7

a)以下の配列はどのように初期化されるか答えなさい char errmsg[2][15] = Divide Error Overflow Error

b)九九の計算を2次元配列を使って求めなさい

19

第6章 ポインタ型変数 C言語では値を記憶するための変数だけではなく変数または定数の番地を記憶するため

のポインタ型変数を宣言することができますポインタとはデータ項目の一種で「記憶装置(メモ

リ)上の格納番地(アドレス)を指すデータ項目」です アドレス コンピュータの中ではデータ項目の格納番地のことをアドレス(住所)と呼びます 例えば記憶装置という名前のとてつもなく大きなマンションがあるとしますその中から Aさんを捜すときは部屋番号を参照しますマンションでは部屋番号で住居人を参照し ているのと同じようにコンピュータでは記憶装置上に確保された変数は格納番地 (アドレス)で管理されています

マンション 部屋番号 記憶装置 格納番地

Aさん Int a Bさん Cさん AAAさん BBBさん CCCさん

1号室

2号室

3号室

100号室

200号室

300号室

100番地

200番地

300番地

1000番地

2000番地

3000番地

Int b Int c float aaafloat bbbfloat ccc

ポインタ ポインタとは「指し示すもの」の意ですがC言語では記憶装置上のアドレスを指し示す もののことです上のマンションの例では部屋番号を格納するデータ項目ということに なりますAAAさんは100号室に住んでいます100という値をポインタのデータ項目に 記憶するとそのデータ項目は間接的にAAAさんを指すことになります

6-1 ポインタ型変数の宣言および参照 通常の変数と区別するために型宣言時に変数名の前に記号を付けて宣言します int a 整数型ポインタ変数 int b 整数型変数

変数 a は整数型の値を記憶するのではなく整数型の値を持つ変数などの番地を記憶する変数ですまた変数 b は通常の整数型の値を記憶するための変数です

20

include ltstdiohgt main() int a b c a はポインタ型の変数b c は整数型の変数 b = 12 変数 b に値 12 を代入します a = ampb 変数 a には変数 b の番地が代入されます c = a + 10 変数 a の指す変数(b)の内容と10の加算です つまり12 + 10 を変数 c に代入します

変数の型宣言において変数名に記号を付けることによりその変数はポインタ型の変数と

なりますポインタ型の変数は変数名のみを指定した場合には単にその変数の値(通常はメモリ

の番地)を表します変数名に記号を付けて使用した場合にはその変数が指し示している変

数の内容を表します c = a ポインタ型変数 a が指している値を変数 c に代入

ポインタ型の変数に番地を記憶させるためにはプログラム例のように変数名の前に記号を

指定します変数名 によって変数の番地(アドレス)を表します a = ampb 変数 b の番地をポインタ型変数 a に代入します

ポインタ型変数の型はポインタ型変数が指し示す先の変数の型を表しています int a 変数 a 整数型の値 float x 変数 x 実数型の値 char c 変数 c 文字型の値

6-2 ポインタ型変数の初期化 ポインタ型変数も型宣言のときに変数を初期化することができます特に文字型のポインタ変

数の場合によく使います char str = TOKAI University

ポインタ型変数 str は文字列定数 TOKAI University の最初の文字が格納されている番地を初期値として持つことになります

変数 str TOKAI University 文字列定数

[プログラム例]

(1)文字型配列 putchar() 関数を使って一次元の文字型配列を出力します include ltstdiohgt main() char str[6] = TOKAI int i for( i = 0 str[i] = yen0 i++ ) putchar( str[i] )

21

ポインタを使用した場合には以下のようになります include ltstdiohgt main() char str[6] = TOKAI char chp for( chp = str chp = yen0 chp++ ) putchar( chp )

chp str T [0] O K A I yen0 [5]

参照する変数 配列の表現 ポインタの表現 実際のアドレス 1番目の数 str[0] chp CHP 2番目の数 str[1] (chp+1) CHP+1 n番目の数 str[n-1] (chp+n-1) CHP+n-1 6番目の数 str[5] (chp+5) CHP+5

注意実際のアドレス CHPは実行時に決定されます

(2)二次元文字型配列 二次元の文字型配列に定数を設定しそれを出力するプログラムです文字型配列を使用す

ると次のとおりになります include ltstdiohgt main() char str[5][40] = TOKAI shounan campus NEC DEC int i for( i = 0 i lt 5 i++ ) printf( yenns str[i] )

40 バイト str TOKAI shounan campus NEC DEC

22

ポインタ型配列を使用すると次のとおりになります include ltstdiohgt main() char str[6] = TOKAI shounan campus NEC DEC NULL char chp for( chp = str chp = NULL chp++ ) printf( yenns chp ) str

chp 番地 TOKAI 番地 shounan 番地 campus 番地 NEC 番地 DEC

NULL

演習8 キーボードまたはデータファイルから読み込んだ文字列中にrsquoArsquo があったら rsquoarsquo に変換 するプログラムを配列とポインタを使って書きなさい

23

第7章 構造体共用体 7-1 構造体

プログラムの規模が大きくなるにつれて多数の intや floatcharなどのデータ型を扱うようになり複雑になってきますそこで多数のデータを1つにまとめて簡単に扱える機能が構造体です 構造体について住所録のデータを例にあげて考えてみます

住所録の個人データとして氏名住所電話番号年齢の項目を一つのデータとします これをC言語で変数の定義をすると次のようになります 氏名東海太郎 char name[30] 住所平塚市北金目1117 char address[30] 電話番号0463-58-1211 char tel[20] 年齢30 int age 個人の住所録データ C言語での表現 このような住所録の個人データを1つにまとめて新しいデータとして定義する機能を構造体と言

います struct 構造体タグ名 構造体メンバーの並び

「struct」は構造体を表すキーワードです 「構造体タグ名」は構造体の型枠を宣言しますここは自由に名前を定義することができ ます 「構造体メンバーの並び」は構造体の要素です複数指定できます

個人の住所録のデータを構造体で宣言すると次のようになります

struct jusho char name[30] char address[30] 構造体のメンバーの並び char tel[20] (複数可)

int age

上記の宣言では構造体の形式を宣言しているだけでメモリ中で実際の領域を確保している

わけではありません実際に領域を確保するためには次のように定義します

struct 構造体タグ名 構造体名

したがって構造体名を jdata とすると次のように指定します

struct jusho jdata

構造体 jdataは次のように構造体タグ jushoの形式で領域を確保します

24

Jdata name[30]

address[30] tel[20] age

(1)構造体の参照

プログラム中で構造体中のメンバーを参照する場合には次のように指定します 構造体名メンバー名

したがって「名前」を参照したいときには次のように指定します

jdataname

[プログラム例]

名前住所電話番号年齢を定義しそれを印字します include ltstdiohgt include ltstringhgt main() struct jusho char name[30] char address[30] char tel[20] int age struct jusho jdata strcpy( jdataname 東海 太郎) strcpy( jdataaddress 平塚市北金目1117)

strcpy( jdatatel 0463-58-1211) jdataage = 30 printf(yenn氏名 = syenn jdataname) printf(yenn住所 = syenn jdataaddress) printf(yenn電話番号= syenn jdatatel) printf(yenn年齢 = dyenn jdataage)

また構造体の形式の定義と領域の確保は次のように同時におこなうことができます

struct 構造体タグ名 構造体メンバーの並び 構造体名

struct jusho struct jusho char name[30] char name[30] char address[30] char address[30] char tel[30] = char tel[30] int age 同じ int age

jdata struct jusho jdata

型宣言と同時にメモリ上に領域を確保する方法 後からメモリ上に領域を確保する方法

25

(2) 構造体配列 住所録データの場合その中に入るデータは1件ではありませんやはり100件200件のデ

ータが必要になる場合がありますこのように個人単位のデータを多数扱う場合には構造体を配

列として宣言することができます 次の例は個人のデータを100個用意するために構造体を配列として宣言しています struct jusho jdata[100] jdata[0] name[30] address[30] tel[20] age

jdata[99 ] name[30] address[30] tel[20] age

(3)構造体配列の参照

プログラム中で構造体配列中のメンバーを参照する場合には次のように指定します 構造体名[要素番号]メンバー名

したがって10件目の人の「名前」を参照したいときには次のように指定します

jdata[10]name

[プログラム例]

名前住所電話番号年齢を定義しそれを印字します include ltstdiohgt include ltstringhgt main() struct jusho char name[30] char address[30] char tel[20] int age jdata[100] strcpy( jdata[10]name 東海 太郎) strcpy( jdata[10]address 平塚市北金目1117)

strcpy( jdata[10]tel 0463-58-1211) jdata[10]age = 30 printf(yenn氏名 = syenn jdata[10]name) printf(yenn住所 = syenn jdata[10]address) printf(yenn電話番号= syenn jdata[10]tel) printf(yenn年齢 = dyenn jdata[10]age)

26

(4) 構造体のポインタ 変数と同じように構造体へのポインタも定義することができます

変数へのポインタ例 構造体へのポインタ例 またポインタを使用して構造体メンバーを参照するには次のように -> 記号を使って指

定します ポインタ変数名 -> メンバー名

[プログラム例]

名前住所電話番号年齢を定義しそれを印字します include ltstdiohgt include ltstringhgt main() struct jusho char name[30] char address[30] char tel[20] int age jdatakp kp = ampjdata strcpy( kp-gtname 東海 太郎)

strcpy( kp-gtaddress 平塚市北金目1117)

strcpy( kp-gttel 0463-58-1211) kp-gtage = 30 printf(yenn氏名 = syenn kp-gtname) printf(yenn住所 = syenn kp-gtaddress) printf(yenn電話番号= syenn kp-gttel) printf(yenn年齢 = dyenn kp-gtage)

kp jdata

name[30] ポインタ型の変数 address[30]

tel[20]

構造体へのポインタを記憶 age

することができます

int a int b b = ampa

struct name jname struct name np np = ampname

27

7-2 共用体 共用体は構造体と同じようにして宣言しますが共用体は複数のデータ型を同一のアドレスに

割り当てる方法です union 共用体タグ名 共用体メンバーの並び

「union」は共用体を表すキーワードです 「共用体タグ名」は共用体の型枠の名前を宣言しますここは自由に名前を定義することがで

きます 「共用体メンバーの並び」は共用体の要素です複数指定できます

共用体の宣言の例を次に示します

union c_tag int a char b

共用体 cは次のように共用体タグ c_tagの形式で領域を確保します共用体はメモリ上に領域を確保するときは ab ともに同じ領域に割り付けられます これはab という2つのデータが同時に存在するわけではなく cを異なるデータ abで共有す

ることを表しています c a b

上記の宣言だけでは共用体の形式を宣言しているだけでメモリ中で実際の領域を確保して

いるわけではありません実際に領域を確保するためには次のように定義します union 構造体タグ名 構造体名

したがって共用体名を c とすると次のように指定します

union c_tag c

(1)共用体の参照

プログラム中で共用体中のメンバーを参照する場合には次のように指定します 共用体名メンバー名

したがって「a」または「b」を参照したいときには次のように指定します

ca (int 型) cb (char 型)

メンバー参照方法によって int型として使ったりchar型として利用することができます

28

[プログラム例]

includeltstdiohgt main() union data char a short b int c chk chkc = 0x12345678 printf( char a xyennchka) printf( short b xyennchkb) printf( int c xyennchkc)

chkb(int 型) chkb(short 型) chka(char 型) 12 12 12 34 34 56 78

29

第8章 アルゴリズム コンピュータに何か仕事をさせようとするときは仕事を具体的に実行するための処理や動作

の手順が必要ですこの「手順」がアルゴリズムです アルゴリズムを考えるときは解くべき問題をはっきりと定義することが必要です

8-1 ソート ソートとは与えられたデータを小さい順または大きい順に並べ換えることですソート方法は

いくつかありますが基本的な方法でソートするアルゴリズムを紹介します

includeltstdiohgt int data[10] main()

int data_in() sort() data_in() sort() int data_in() データ入力関数

int a printf(数値入力yenn)

for(a=0alt=9a++) printf( [d]a+1) scanf(dampdata[a]) int sort() ソート処理を行う関数

int cont1cont2tmp1tmp2mim for(cont1=0 cont1lt=9 cont1++) mim=data[cont1] tmp1=cont1 for(cont2=cont1+1 cont2lt=9 cont2++) if(data[cont2] lt mim) mim=data[cont2] tmp1=cont2 tmp2 = data[cont1] data[cont1] = data[tmp1] data[tmp1] = tmp2 printf(結果 yenn)

for (cont1 = 0 cont1 lt= 9 cont1++) printf(d yenn data[cont1])

30

第9章 プリプロセッサ C言語にはプログラムの中でコンパイルについての指示を行う「プリプロセッサ」という機能が

ありますまたプリプロセッサとはコンパイルする前に実行されるためその意味のとおり「前処理」 と呼ばれていますここでは代表的なものをいくつか説明します

9-1 ファイルの挿入 ソースプログラム中に指定されたファイルを挿入します

include ltstdiohgt helliphellip 標準ディレクトリを探します include progh helliphellip 現在のディレクトリを探しなければ標準ディレクトリを探します

includeltstdiohgt によって組み込まれた define EOF (-1) define EOF (-1) define define helliphelliphelliphellip 組み込み helliphelliphelliphellip

main() stdiohファイル

int helliphelliphelliphellip helliphelliphelliphellip

ソースファイル

9-2 文字の置換 プログラム中に使われている文字列を別の文字列に置き換えます

include ltstdiohgt define TRUE 1 define EOF (-1) main() define helliphellip helliphellip

while(TRUE) define TRUE 1 置き換え main() helliphellip helliphellip while(1)

break helliphelliphellip

31

9-3 条件によるコンパイル 識別子が定義されているか否かを判断しコンパイルする範囲を指定します

include ltstdiohgt define UNIX main() ifdef UNIX printf( UNIX yenn) else printf(MS-DOSyenn) endif

include ltstdiohgt define OS UNIX main() if OS == UNIX printf( UNIX yenn) else printf(MS-DOSyenn) endif

32

付 録 1 puts()gets()関数について

行単位に入出力を行う場合には puts() gets() 関数を用います

puts() 標準出力に文字列を出力します

include ltstdiohgt int puts( char s ) puts() は NULL で終る文字列 s を標準出力に出力し最後に改行文字 yenn も出力しま

gets() 標準入力から文字列を入力します

include ltstdiohgt char gets( char s ) 戻り値正常に入力した場合には引数 s の値が返されますエラーやEOFになった場合に

は NULL が返されます gets() は標準入力から復帰文字で終る文字列を入力しs に格納しますこのとき最後の復

帰文字は NULL文字に変更されます

入力行の出力 標準入力から gets() で入力したデータには改行コードは含まれませんまた標準出力へ

puts() で出力を行う場合には必ず改行コードが付加されますgets() を実行したときの戻り値としてファイルの終端を検出した場合には EOF ではなく NULL が返されますので注意して下さい

include ltstdiohgt main() char data[80] while( gets( data ) = NULL )puts( data )

putchar()getchar()関数について putchar() 標準出力に文字を出力します

include ltstdiohgt int putchar(int c ) 戻り値正常に出力できた場合には文字cをエラーの場合にはEOFを返します

33

getchar() 標準入力から文字を入力します

include ltstdiohgt int getchar(void) 戻り値正常に入力した場合には読み込んだ文字を int 型に変換して返しますまたファイ

ルエンドエラーの場合にはEOFを返します

標準入力標準出力

標準入力標準出力はプログラムが開始されるときにはオープンされていますそれぞれのフ

ァイルポインタは stdin stdout になっていますfopen() fclose() をせずとも使用することができます

scanf() 標準出力ストリームからテキストを読み込み解釈します include ltstdiohgt int scanf( const char format [ address ] ) 戻り値正しくスキャンし変換し格納した入力フィールドの数を返しますファイルエンドを読

み込んだ場合は戻り値は EOF となります値を格納したフィールドがなかった場合は戻り値は0となります

一連の入力フィールドをスキャンして1度に1文字ずつストリーム stdin から文字を読み込み

ます次に引き数 format によって指される書式文字列中の書式指定に従って各フィールドを書式化します最後にformat の後に続く各引き数が示しているアドレスに書式化した入力を格納していきます書式文字列中の書式指定の個数はその後に続くアドレスの数と同じでな

ければなりません 書式指定[入力幅][型指定文字] 入力幅 読むべき文字数の最大値 型指定文字 次のとおりです 型指定文字 期待される入力 引き数の型 d 10進整数 int へのポインタ( int arg ) x 16進整数 int へのポインタ( int arg ) f 浮動小数点数 float へのポインタ( float arg ) s 文字列 文字配列へのポインタ( char arg[] ) c 文字 文字へのポインタ( char arg )

printf() フォーマットを指定してテキスト標準出力ストリームに出力します include ltstdiohgt int printf( const char format [ argument ] ) 戻り値出力したバイト数を返しますエラーの場合は EOF を返します

34

format によって指される書式文字列中の書式指定をformat の後に続く各引き数に適用し

書式化されたデータを stdout に出力します書式指定は後に続く引き数と同じ数だけなければなりません

書式指定[印字幅][精度][型指定文字] 印字幅 印字する最小文字数 精度 印字する最大文字数 型指定文字 つぎのとおりです 型指定文字 入力引き数 出力の書式 d 整数 符号付き10進整数 x 整数 符号無し16進整数 f 浮動小数点 符号付きの dddddddd形式の値 c 文字 1個の文字 s 文字列ポインタ ヌル文字に出会うか精度に達するまで 文字をプリントする

fopen()fclose()関数について fopen() ファイルをオープンします

include ltstdiohgt FILE fopen( char filename char mode ) 戻り値正常にファイルのオープンができたらファイルポインタを返しますエラーがあった場

合には NULLを返します 文字列 filename で指定されたファイルをオープンしますオープン後の入出力のモードに

ついては文字列 mode で指定しますmode に指定できる文字は以下のとおりです r 入力モードでオープンします w 出力モードでオープンします a 存在するファイルに追加して出力するモードでオープンします r+ 既に作成してあるファイルを更新(入力出力)するモードでオープンします w+ 新しく作成するファイルを更新モードでオープンします a+ 既に作成してあるファイルの終りから更新用に作成します

以上の文字に b をつけ加えることによりバイナリモードで入出力することができるようになり

ます rb バイナリの入力モードでオープンします wb バイナリの出力モードでオープンします ab 存在するファイルに追加して出力するモード(バイナリ)でオープンします

fclose() 既にオープンしてあるファイルをクローズします include ltstdiohgt fclose( FILE fp ) 既にオープンしているファイルをクローズしますパラメータには fopen() 関数により返された

ファイルポインタを指定します

35

テキストモードとバイナリモード 行の最後はテキストモードの場合改行コードのみとなりバイナリモードの場合には復帰

コードと改行コードの組合わせになります行の最後としてテキストファイルには復帰コード改行

コードが書かれていますがテキストモードでオープンした場合には入力すると改行コードのみに

変換されて入力されますバイナリモードの場合には復帰コード改行コードがそれぞれ入力され

ます

fputs()fgets()関数について fputs() ファイルポインタで指定されるファイルに文字列を出力します

include ltstdiohgt

int fputs( char s FILE fp ) fputs() は NULL で終る文字列 s をファイルポインタに示されるファイルへ出力しますputs()

と違い最後に改行文字 yenn を出力することはありません

fgets() ファイルポインタで指定されるファイルから文字列を入力します include ltstdiohgt char fgets( char s int n FILE fp ) 戻り値正常に入力した場合には引数 s の値が返されますエラーやEOFになった場合に

は NULL が返されます fgets() はファイルポインタで指定されるファイルから ( n - 1 ) 文字または改行文字までの

文字列を入力しs に格納しますgets() と異なり最後に入力された改行文字は NULL 文字に変更されません

標準入力から入力しファイルへ出力する ファイルへ出力あるいは入力を行う場合には改行コードの変換(入力の場合の削除出力の

場合の付加)はされませんしたがって標準入力から入力しファイルへ出力する場合には改行

コードを付加しなければなりません include ltstdiohgt main() char data[80] FILE fp fp = fopen( data w ) while( gets( data ) = NULL ) strcat( data yenn ) 改行コードの付加

fputs( data fp ) fclose( fp )

36

fputc()fgetc()関数について fputc() ファイルポインタで指定されるファイルに1文字出力します

include ltstdiohgt int fputc( int c FILE fp ) 戻り値正常に出力できた場合には文字 c を返しエラーの場合には EOF を返します fputc() は文字 c をファイルポインタで示されるファイルへ出力します

fgetc() ファイルポインタで指定されるファイルから1文字入力します

include ltstdiohgt int fgetc( FILE fp ) 戻り値正常に入力した場合には入力した文字を返しますエラーやEOFになった場合には

EOF が返されます fgetc() はファイルポインタで指定されるファイルから文字を入力します

ファイルの内容の表示 include ltstdiohgt main() FILE fp int ch char fname[30] printf( Key in Fila name gt ) gets( fname ) fp = fopen( fname r ) while( ( ch = fgetc( fp ) ) = EOF )putchar( ch ) fclose( fp )

その他テキスト中で使用された関数について sin() 三角関数の正弦を計算します

include ltmathhgt double sin(double radian) sinはラジアンを単位とする引数 radianの三角関数を計算します

37

strcpy() 文字列を他の文字列へコピーします

include ltstringhgt char strcpy(char string1const char string2) strcpyは引数 string2の指す文字列を null文字まで含めて引数 string1の指す領域にコピ

ーする strcpyは string1を返します

strcat() ある文字列を他の文字列に加えます

include ltstringhgt char strcat( char dest const char src ) 戻り値連結された文字列へのポインタを返します strcat() はsrc のコピーを dest の最後につけ加えます得られる文字列の長さは

strlen(dest)+strlen(src) になります

fabs() 絶対値の計算をします include ltmathhgt double fabs(double z) fabsは倍精度浮動小数の絶対値を計算して返しますつまりzgt=0であれば z をzlt0であ

れば-zを返します exp() 指数関数を計算します

include ltmathhgt double exp(double z) exp は引数zの指数関数つまりezを返すここではeは自然対数の底を表します対数関

数logの逆関数です

38

付 録 2 コンパイルの方法には大きく分けて第4章の実習で学んだようにデータファイルを作成してお

き ccg でコンパイルさせる方法と実行中に対話型でデータを入力していく方法があります ここでは対話型で実行を進めていく方法を紹介します ただしこの方法は計算(cpu)時間が10秒以内のものに限ります10秒を超える計算(cpu)時

間を要する場合はccg でコンパイルをするようにしてください 第4章実習の(2)(p16)までは同様です

コンパイル

コンピュータに処理を依頼します 60us1234boseicc cc rensyuc

所有するファイルの一覧を見てみます

60us1234boseicc ls -l larr 持っているファイルの一覧を見るコマンドです

-rw-r--r-- 1 60us1234 other 128 4月26日 15時14分 rensyuc -rwxr-xr-x 1 60us1234 other 361 4月26日 15時16分 aout

aout という実行形式のファイルが作成されています

実行

60us1234boseicc aout12 35[リターン] データを入力

1 200000 3500000 4200000 実行結果の出力

60us1234boseicc

注意

aout ファイルは印刷することができません実行結果を印刷する場合にはファイルに落とし てから出力するようにしましょう

60us1234boseicc aout gt kekka12 35[リターン] データを入力

60us1234boseicc more kekka 計算結果の確認 60us1234boseicc lpr kekka 計算結果の印刷

39

Page 16: n 第1章 章立ての部分は、書式(PC入門大見出し)を …第2章 数の表現 2-1 2進数 電子計算機の動作原理は0と1で表される2進数です。また、人間が日常生活で扱っている数

3-8 再帰呼び出し 関数の引数の受渡しがスタックを利用して行われることから自分で自分自身の関数を呼び出

すことができます 以下のプログラムは入力した値の階乗を計算するプログラムです

3の階乗を求めることを考えてみます

return 文によって戻るときは次のようにして値を返します kai( 3 ) 3 kai( 3-1 ) 2 kai( 2-1 ) return 1

6 3 (2 1) 2 1 以上の計算から3=6が導き出されます 再帰呼び出しのことをリカーシブコールともいいます

include ltstdiohgt main() int n m kai() scanf( ldquodrdquoampn ) m = kai( n ) printf( ldquod = dyennrdquo n m )

int kai( int k ) if( k == 1 )return 1 else return k kai( k ndash 1 )

kai( 1 )

darr

return 1

kai( 2 )

darr

2 kai( 2-1 )

kai( 3 )

darr

3 kai( 3-1 )

main()

darr

kai( 3 )

3

2

1

2

3

1

2

3 3

32

32

1

2

1

3

3

演習6 1からnまでの総和を再帰呼び出しを使って計算する関数 sowa() を作りなさい n+(n-1)+ +2+1

14

第4章 実習 この章ではプログラムを実際に入力して実行するまでの手順を実習します

4-1 操作手順 (1)ログイン

[スタート]rarr[プログラム(P)]rarr[ネットワーク] Hostの欄に bosei を記述選択 rarr [Telnet(FreeWare)] を選択します して 「OK」 ボタンをクリックします

UP-UXV (Rel42MP) (bosei) (pts41) login 60us1234 larr 各自のログイン名を入力します Password larr パスワードを入力しても画面は何も変化しません 101 60us1234bosei larr セッションが開設されましたこれをプロンプトといいます この状態でコマンドを入力することができます

(2)プログラムの作成 以下のコマンドを入力しテキストエディタを起動します 60us1234boseicc ng rensyuc

すると下図のようにngエディタの画面になります

15

次のように入力します入力ミスの修正はBSキーで行ないます

include ltstdiohgt main() float abc scanf(f f ampaampb) c=ab printf(f f f yenn abc)

CTRL キーを押しながら XCTRL キーを押しながら C を押しますすると次のメッセージが画面下に表示されます

Save file uhomea60us1234rensyuc (y or n)

このメッセージに対して y と答えます

(3)データの作成 以下のコマンドを入力しテキストエディタを起動します 60us1234boseicc ng rensyud

ngエディタの画面になりますので次のように入力します 12 35

CTRLキーを押しながら XCTRLキーを押しながら C を押します save file uhomea60us1234rensyud (y or n)

このメッセージに対して y と答えます

(4)コンパイルと実行 コンピュータに処理を依頼します 60us1234boseicc ccg rensyu

ジョブを投入しましたジョブの状態を見るコマンドは myjobです

16

130 60us1234boseicc myjob ================================================= NQS (R0220) BATCH REQUEST HOST bosei ================================================= REQUEST ID NAME OWNER QUEUE PRI NICE STT PGRP R --------------- -------- -------- -------- ---- --- --- ------ - 99321bosei STDIN 60us1234 A 31 0 RUN 14161 - ---------------------------------------------------------------- ================================================== NQS (R0220) DEVICE REQUEST HOST bosei ジョブは実行中です

================================================== REQUEST ID NAME OWNER QUEUE PRI SIZE STT -------------------------------------------------------------

所有するファイルの一覧を見てみます

60us1234boseicc ls -l larr 持っているファイルの一覧を見るコマンドです

-rw-r--r-- 1 60us1234 other 4 4月26日 15時14分 rensyud -rw-r--r-- 1 60us1234 other 128 4月26日 15時10分 rensyuc -rwxr-xr-x 1 60us1234 other 361 4月26日 15時16分 rensyul

(5)計算結果の確認

計算結果を画面に表示して確認します 60us1234boseicc more rensyul

(6)印刷

計算結果の印刷を行ないます5号館2階のカフェテリア室にある bosei のプリンタに印刷 されます

60us1234boseicc lpr rensyul

(7)ログアウト セッションを終了します 60us1234boseicc logout

(8)実行の流れ

エラー

プログラムの作成 ログイン コンパイル実行

確 認 印 刷 ログアウト

17

第5章 配列 多数の変数をまとめて宣言する方法として配列があります配列の一つ一つは配列要素と呼

ばれ変数と同じ性格を持っています配列の宣言は型宣言と同時に次のように行います int a[5] 配列 a

a[0]

a[1]

a[2]

a[3]

a[4]

二次元配列(一次元配列を複数集めたもの)を宣言する場合には次のようになります int b[3][4] 配列 b

b[0][0] b[0][1] b[0][2] b[0][3]

b[1][0] b[1][1] b[1][2] b[1][3]

b[2][0] b[2][1] b[2][2] b[2][3]

配列要素に数値を代入する場合は次のようになります b[1][2]=10

5-1 二次元配列要素の初期化 変数の型宣言と同じように配列を宣言するときに初期値も同時に設定することができます

複数のデータがある場合には{}記号でくくって指定します int b[3][4] = 2 4 6 8 1 3 5 7 1 2 3 4

文字型配列の場合には以下のようになりますyen0 は文字列の終わりを表わします char univ[3][7] = T O K A I yen0 S I M I Z U yen0 Y O Y O G I yen0

また文字列定数として初期化することもできますこの場合コンパイル時に自動的に yen0 が付加されます

char univ[3][7] = TOKAI SIMIZU YOYOGI

18

[プログラム例] 二次元配列のタテヨコを加算するプログラム

include ltstdiohgt main() int mat[4][3]=123456789101112 int ijytotalttotal[3]total=0 for(j=0jlt3j++)ttotal[j]=0 for (i=0ilt4i++) ytotal=0 for(j=0jlt3j++) ytotal += mat[i][j] ttotal[j] += mat[i][j] total += mat[i][j] printf(3dmat[i][j]) printf( 3dyennytotal) printf(yenn) for(j=0jlt3j++)printf(3dttotal[j]) printf( 3dyenntotal)

[実行結果]

1 2 3 6 4 5 6 15 7 8 9 24 10 11 12 33 22 26 30 78

演習7

a)以下の配列はどのように初期化されるか答えなさい char errmsg[2][15] = Divide Error Overflow Error

b)九九の計算を2次元配列を使って求めなさい

19

第6章 ポインタ型変数 C言語では値を記憶するための変数だけではなく変数または定数の番地を記憶するため

のポインタ型変数を宣言することができますポインタとはデータ項目の一種で「記憶装置(メモ

リ)上の格納番地(アドレス)を指すデータ項目」です アドレス コンピュータの中ではデータ項目の格納番地のことをアドレス(住所)と呼びます 例えば記憶装置という名前のとてつもなく大きなマンションがあるとしますその中から Aさんを捜すときは部屋番号を参照しますマンションでは部屋番号で住居人を参照し ているのと同じようにコンピュータでは記憶装置上に確保された変数は格納番地 (アドレス)で管理されています

マンション 部屋番号 記憶装置 格納番地

Aさん Int a Bさん Cさん AAAさん BBBさん CCCさん

1号室

2号室

3号室

100号室

200号室

300号室

100番地

200番地

300番地

1000番地

2000番地

3000番地

Int b Int c float aaafloat bbbfloat ccc

ポインタ ポインタとは「指し示すもの」の意ですがC言語では記憶装置上のアドレスを指し示す もののことです上のマンションの例では部屋番号を格納するデータ項目ということに なりますAAAさんは100号室に住んでいます100という値をポインタのデータ項目に 記憶するとそのデータ項目は間接的にAAAさんを指すことになります

6-1 ポインタ型変数の宣言および参照 通常の変数と区別するために型宣言時に変数名の前に記号を付けて宣言します int a 整数型ポインタ変数 int b 整数型変数

変数 a は整数型の値を記憶するのではなく整数型の値を持つ変数などの番地を記憶する変数ですまた変数 b は通常の整数型の値を記憶するための変数です

20

include ltstdiohgt main() int a b c a はポインタ型の変数b c は整数型の変数 b = 12 変数 b に値 12 を代入します a = ampb 変数 a には変数 b の番地が代入されます c = a + 10 変数 a の指す変数(b)の内容と10の加算です つまり12 + 10 を変数 c に代入します

変数の型宣言において変数名に記号を付けることによりその変数はポインタ型の変数と

なりますポインタ型の変数は変数名のみを指定した場合には単にその変数の値(通常はメモリ

の番地)を表します変数名に記号を付けて使用した場合にはその変数が指し示している変

数の内容を表します c = a ポインタ型変数 a が指している値を変数 c に代入

ポインタ型の変数に番地を記憶させるためにはプログラム例のように変数名の前に記号を

指定します変数名 によって変数の番地(アドレス)を表します a = ampb 変数 b の番地をポインタ型変数 a に代入します

ポインタ型変数の型はポインタ型変数が指し示す先の変数の型を表しています int a 変数 a 整数型の値 float x 変数 x 実数型の値 char c 変数 c 文字型の値

6-2 ポインタ型変数の初期化 ポインタ型変数も型宣言のときに変数を初期化することができます特に文字型のポインタ変

数の場合によく使います char str = TOKAI University

ポインタ型変数 str は文字列定数 TOKAI University の最初の文字が格納されている番地を初期値として持つことになります

変数 str TOKAI University 文字列定数

[プログラム例]

(1)文字型配列 putchar() 関数を使って一次元の文字型配列を出力します include ltstdiohgt main() char str[6] = TOKAI int i for( i = 0 str[i] = yen0 i++ ) putchar( str[i] )

21

ポインタを使用した場合には以下のようになります include ltstdiohgt main() char str[6] = TOKAI char chp for( chp = str chp = yen0 chp++ ) putchar( chp )

chp str T [0] O K A I yen0 [5]

参照する変数 配列の表現 ポインタの表現 実際のアドレス 1番目の数 str[0] chp CHP 2番目の数 str[1] (chp+1) CHP+1 n番目の数 str[n-1] (chp+n-1) CHP+n-1 6番目の数 str[5] (chp+5) CHP+5

注意実際のアドレス CHPは実行時に決定されます

(2)二次元文字型配列 二次元の文字型配列に定数を設定しそれを出力するプログラムです文字型配列を使用す

ると次のとおりになります include ltstdiohgt main() char str[5][40] = TOKAI shounan campus NEC DEC int i for( i = 0 i lt 5 i++ ) printf( yenns str[i] )

40 バイト str TOKAI shounan campus NEC DEC

22

ポインタ型配列を使用すると次のとおりになります include ltstdiohgt main() char str[6] = TOKAI shounan campus NEC DEC NULL char chp for( chp = str chp = NULL chp++ ) printf( yenns chp ) str

chp 番地 TOKAI 番地 shounan 番地 campus 番地 NEC 番地 DEC

NULL

演習8 キーボードまたはデータファイルから読み込んだ文字列中にrsquoArsquo があったら rsquoarsquo に変換 するプログラムを配列とポインタを使って書きなさい

23

第7章 構造体共用体 7-1 構造体

プログラムの規模が大きくなるにつれて多数の intや floatcharなどのデータ型を扱うようになり複雑になってきますそこで多数のデータを1つにまとめて簡単に扱える機能が構造体です 構造体について住所録のデータを例にあげて考えてみます

住所録の個人データとして氏名住所電話番号年齢の項目を一つのデータとします これをC言語で変数の定義をすると次のようになります 氏名東海太郎 char name[30] 住所平塚市北金目1117 char address[30] 電話番号0463-58-1211 char tel[20] 年齢30 int age 個人の住所録データ C言語での表現 このような住所録の個人データを1つにまとめて新しいデータとして定義する機能を構造体と言

います struct 構造体タグ名 構造体メンバーの並び

「struct」は構造体を表すキーワードです 「構造体タグ名」は構造体の型枠を宣言しますここは自由に名前を定義することができ ます 「構造体メンバーの並び」は構造体の要素です複数指定できます

個人の住所録のデータを構造体で宣言すると次のようになります

struct jusho char name[30] char address[30] 構造体のメンバーの並び char tel[20] (複数可)

int age

上記の宣言では構造体の形式を宣言しているだけでメモリ中で実際の領域を確保している

わけではありません実際に領域を確保するためには次のように定義します

struct 構造体タグ名 構造体名

したがって構造体名を jdata とすると次のように指定します

struct jusho jdata

構造体 jdataは次のように構造体タグ jushoの形式で領域を確保します

24

Jdata name[30]

address[30] tel[20] age

(1)構造体の参照

プログラム中で構造体中のメンバーを参照する場合には次のように指定します 構造体名メンバー名

したがって「名前」を参照したいときには次のように指定します

jdataname

[プログラム例]

名前住所電話番号年齢を定義しそれを印字します include ltstdiohgt include ltstringhgt main() struct jusho char name[30] char address[30] char tel[20] int age struct jusho jdata strcpy( jdataname 東海 太郎) strcpy( jdataaddress 平塚市北金目1117)

strcpy( jdatatel 0463-58-1211) jdataage = 30 printf(yenn氏名 = syenn jdataname) printf(yenn住所 = syenn jdataaddress) printf(yenn電話番号= syenn jdatatel) printf(yenn年齢 = dyenn jdataage)

また構造体の形式の定義と領域の確保は次のように同時におこなうことができます

struct 構造体タグ名 構造体メンバーの並び 構造体名

struct jusho struct jusho char name[30] char name[30] char address[30] char address[30] char tel[30] = char tel[30] int age 同じ int age

jdata struct jusho jdata

型宣言と同時にメモリ上に領域を確保する方法 後からメモリ上に領域を確保する方法

25

(2) 構造体配列 住所録データの場合その中に入るデータは1件ではありませんやはり100件200件のデ

ータが必要になる場合がありますこのように個人単位のデータを多数扱う場合には構造体を配

列として宣言することができます 次の例は個人のデータを100個用意するために構造体を配列として宣言しています struct jusho jdata[100] jdata[0] name[30] address[30] tel[20] age

jdata[99 ] name[30] address[30] tel[20] age

(3)構造体配列の参照

プログラム中で構造体配列中のメンバーを参照する場合には次のように指定します 構造体名[要素番号]メンバー名

したがって10件目の人の「名前」を参照したいときには次のように指定します

jdata[10]name

[プログラム例]

名前住所電話番号年齢を定義しそれを印字します include ltstdiohgt include ltstringhgt main() struct jusho char name[30] char address[30] char tel[20] int age jdata[100] strcpy( jdata[10]name 東海 太郎) strcpy( jdata[10]address 平塚市北金目1117)

strcpy( jdata[10]tel 0463-58-1211) jdata[10]age = 30 printf(yenn氏名 = syenn jdata[10]name) printf(yenn住所 = syenn jdata[10]address) printf(yenn電話番号= syenn jdata[10]tel) printf(yenn年齢 = dyenn jdata[10]age)

26

(4) 構造体のポインタ 変数と同じように構造体へのポインタも定義することができます

変数へのポインタ例 構造体へのポインタ例 またポインタを使用して構造体メンバーを参照するには次のように -> 記号を使って指

定します ポインタ変数名 -> メンバー名

[プログラム例]

名前住所電話番号年齢を定義しそれを印字します include ltstdiohgt include ltstringhgt main() struct jusho char name[30] char address[30] char tel[20] int age jdatakp kp = ampjdata strcpy( kp-gtname 東海 太郎)

strcpy( kp-gtaddress 平塚市北金目1117)

strcpy( kp-gttel 0463-58-1211) kp-gtage = 30 printf(yenn氏名 = syenn kp-gtname) printf(yenn住所 = syenn kp-gtaddress) printf(yenn電話番号= syenn kp-gttel) printf(yenn年齢 = dyenn kp-gtage)

kp jdata

name[30] ポインタ型の変数 address[30]

tel[20]

構造体へのポインタを記憶 age

することができます

int a int b b = ampa

struct name jname struct name np np = ampname

27

7-2 共用体 共用体は構造体と同じようにして宣言しますが共用体は複数のデータ型を同一のアドレスに

割り当てる方法です union 共用体タグ名 共用体メンバーの並び

「union」は共用体を表すキーワードです 「共用体タグ名」は共用体の型枠の名前を宣言しますここは自由に名前を定義することがで

きます 「共用体メンバーの並び」は共用体の要素です複数指定できます

共用体の宣言の例を次に示します

union c_tag int a char b

共用体 cは次のように共用体タグ c_tagの形式で領域を確保します共用体はメモリ上に領域を確保するときは ab ともに同じ領域に割り付けられます これはab という2つのデータが同時に存在するわけではなく cを異なるデータ abで共有す

ることを表しています c a b

上記の宣言だけでは共用体の形式を宣言しているだけでメモリ中で実際の領域を確保して

いるわけではありません実際に領域を確保するためには次のように定義します union 構造体タグ名 構造体名

したがって共用体名を c とすると次のように指定します

union c_tag c

(1)共用体の参照

プログラム中で共用体中のメンバーを参照する場合には次のように指定します 共用体名メンバー名

したがって「a」または「b」を参照したいときには次のように指定します

ca (int 型) cb (char 型)

メンバー参照方法によって int型として使ったりchar型として利用することができます

28

[プログラム例]

includeltstdiohgt main() union data char a short b int c chk chkc = 0x12345678 printf( char a xyennchka) printf( short b xyennchkb) printf( int c xyennchkc)

chkb(int 型) chkb(short 型) chka(char 型) 12 12 12 34 34 56 78

29

第8章 アルゴリズム コンピュータに何か仕事をさせようとするときは仕事を具体的に実行するための処理や動作

の手順が必要ですこの「手順」がアルゴリズムです アルゴリズムを考えるときは解くべき問題をはっきりと定義することが必要です

8-1 ソート ソートとは与えられたデータを小さい順または大きい順に並べ換えることですソート方法は

いくつかありますが基本的な方法でソートするアルゴリズムを紹介します

includeltstdiohgt int data[10] main()

int data_in() sort() data_in() sort() int data_in() データ入力関数

int a printf(数値入力yenn)

for(a=0alt=9a++) printf( [d]a+1) scanf(dampdata[a]) int sort() ソート処理を行う関数

int cont1cont2tmp1tmp2mim for(cont1=0 cont1lt=9 cont1++) mim=data[cont1] tmp1=cont1 for(cont2=cont1+1 cont2lt=9 cont2++) if(data[cont2] lt mim) mim=data[cont2] tmp1=cont2 tmp2 = data[cont1] data[cont1] = data[tmp1] data[tmp1] = tmp2 printf(結果 yenn)

for (cont1 = 0 cont1 lt= 9 cont1++) printf(d yenn data[cont1])

30

第9章 プリプロセッサ C言語にはプログラムの中でコンパイルについての指示を行う「プリプロセッサ」という機能が

ありますまたプリプロセッサとはコンパイルする前に実行されるためその意味のとおり「前処理」 と呼ばれていますここでは代表的なものをいくつか説明します

9-1 ファイルの挿入 ソースプログラム中に指定されたファイルを挿入します

include ltstdiohgt helliphellip 標準ディレクトリを探します include progh helliphellip 現在のディレクトリを探しなければ標準ディレクトリを探します

includeltstdiohgt によって組み込まれた define EOF (-1) define EOF (-1) define define helliphelliphelliphellip 組み込み helliphelliphelliphellip

main() stdiohファイル

int helliphelliphelliphellip helliphelliphelliphellip

ソースファイル

9-2 文字の置換 プログラム中に使われている文字列を別の文字列に置き換えます

include ltstdiohgt define TRUE 1 define EOF (-1) main() define helliphellip helliphellip

while(TRUE) define TRUE 1 置き換え main() helliphellip helliphellip while(1)

break helliphelliphellip

31

9-3 条件によるコンパイル 識別子が定義されているか否かを判断しコンパイルする範囲を指定します

include ltstdiohgt define UNIX main() ifdef UNIX printf( UNIX yenn) else printf(MS-DOSyenn) endif

include ltstdiohgt define OS UNIX main() if OS == UNIX printf( UNIX yenn) else printf(MS-DOSyenn) endif

32

付 録 1 puts()gets()関数について

行単位に入出力を行う場合には puts() gets() 関数を用います

puts() 標準出力に文字列を出力します

include ltstdiohgt int puts( char s ) puts() は NULL で終る文字列 s を標準出力に出力し最後に改行文字 yenn も出力しま

gets() 標準入力から文字列を入力します

include ltstdiohgt char gets( char s ) 戻り値正常に入力した場合には引数 s の値が返されますエラーやEOFになった場合に

は NULL が返されます gets() は標準入力から復帰文字で終る文字列を入力しs に格納しますこのとき最後の復

帰文字は NULL文字に変更されます

入力行の出力 標準入力から gets() で入力したデータには改行コードは含まれませんまた標準出力へ

puts() で出力を行う場合には必ず改行コードが付加されますgets() を実行したときの戻り値としてファイルの終端を検出した場合には EOF ではなく NULL が返されますので注意して下さい

include ltstdiohgt main() char data[80] while( gets( data ) = NULL )puts( data )

putchar()getchar()関数について putchar() 標準出力に文字を出力します

include ltstdiohgt int putchar(int c ) 戻り値正常に出力できた場合には文字cをエラーの場合にはEOFを返します

33

getchar() 標準入力から文字を入力します

include ltstdiohgt int getchar(void) 戻り値正常に入力した場合には読み込んだ文字を int 型に変換して返しますまたファイ

ルエンドエラーの場合にはEOFを返します

標準入力標準出力

標準入力標準出力はプログラムが開始されるときにはオープンされていますそれぞれのフ

ァイルポインタは stdin stdout になっていますfopen() fclose() をせずとも使用することができます

scanf() 標準出力ストリームからテキストを読み込み解釈します include ltstdiohgt int scanf( const char format [ address ] ) 戻り値正しくスキャンし変換し格納した入力フィールドの数を返しますファイルエンドを読

み込んだ場合は戻り値は EOF となります値を格納したフィールドがなかった場合は戻り値は0となります

一連の入力フィールドをスキャンして1度に1文字ずつストリーム stdin から文字を読み込み

ます次に引き数 format によって指される書式文字列中の書式指定に従って各フィールドを書式化します最後にformat の後に続く各引き数が示しているアドレスに書式化した入力を格納していきます書式文字列中の書式指定の個数はその後に続くアドレスの数と同じでな

ければなりません 書式指定[入力幅][型指定文字] 入力幅 読むべき文字数の最大値 型指定文字 次のとおりです 型指定文字 期待される入力 引き数の型 d 10進整数 int へのポインタ( int arg ) x 16進整数 int へのポインタ( int arg ) f 浮動小数点数 float へのポインタ( float arg ) s 文字列 文字配列へのポインタ( char arg[] ) c 文字 文字へのポインタ( char arg )

printf() フォーマットを指定してテキスト標準出力ストリームに出力します include ltstdiohgt int printf( const char format [ argument ] ) 戻り値出力したバイト数を返しますエラーの場合は EOF を返します

34

format によって指される書式文字列中の書式指定をformat の後に続く各引き数に適用し

書式化されたデータを stdout に出力します書式指定は後に続く引き数と同じ数だけなければなりません

書式指定[印字幅][精度][型指定文字] 印字幅 印字する最小文字数 精度 印字する最大文字数 型指定文字 つぎのとおりです 型指定文字 入力引き数 出力の書式 d 整数 符号付き10進整数 x 整数 符号無し16進整数 f 浮動小数点 符号付きの dddddddd形式の値 c 文字 1個の文字 s 文字列ポインタ ヌル文字に出会うか精度に達するまで 文字をプリントする

fopen()fclose()関数について fopen() ファイルをオープンします

include ltstdiohgt FILE fopen( char filename char mode ) 戻り値正常にファイルのオープンができたらファイルポインタを返しますエラーがあった場

合には NULLを返します 文字列 filename で指定されたファイルをオープンしますオープン後の入出力のモードに

ついては文字列 mode で指定しますmode に指定できる文字は以下のとおりです r 入力モードでオープンします w 出力モードでオープンします a 存在するファイルに追加して出力するモードでオープンします r+ 既に作成してあるファイルを更新(入力出力)するモードでオープンします w+ 新しく作成するファイルを更新モードでオープンします a+ 既に作成してあるファイルの終りから更新用に作成します

以上の文字に b をつけ加えることによりバイナリモードで入出力することができるようになり

ます rb バイナリの入力モードでオープンします wb バイナリの出力モードでオープンします ab 存在するファイルに追加して出力するモード(バイナリ)でオープンします

fclose() 既にオープンしてあるファイルをクローズします include ltstdiohgt fclose( FILE fp ) 既にオープンしているファイルをクローズしますパラメータには fopen() 関数により返された

ファイルポインタを指定します

35

テキストモードとバイナリモード 行の最後はテキストモードの場合改行コードのみとなりバイナリモードの場合には復帰

コードと改行コードの組合わせになります行の最後としてテキストファイルには復帰コード改行

コードが書かれていますがテキストモードでオープンした場合には入力すると改行コードのみに

変換されて入力されますバイナリモードの場合には復帰コード改行コードがそれぞれ入力され

ます

fputs()fgets()関数について fputs() ファイルポインタで指定されるファイルに文字列を出力します

include ltstdiohgt

int fputs( char s FILE fp ) fputs() は NULL で終る文字列 s をファイルポインタに示されるファイルへ出力しますputs()

と違い最後に改行文字 yenn を出力することはありません

fgets() ファイルポインタで指定されるファイルから文字列を入力します include ltstdiohgt char fgets( char s int n FILE fp ) 戻り値正常に入力した場合には引数 s の値が返されますエラーやEOFになった場合に

は NULL が返されます fgets() はファイルポインタで指定されるファイルから ( n - 1 ) 文字または改行文字までの

文字列を入力しs に格納しますgets() と異なり最後に入力された改行文字は NULL 文字に変更されません

標準入力から入力しファイルへ出力する ファイルへ出力あるいは入力を行う場合には改行コードの変換(入力の場合の削除出力の

場合の付加)はされませんしたがって標準入力から入力しファイルへ出力する場合には改行

コードを付加しなければなりません include ltstdiohgt main() char data[80] FILE fp fp = fopen( data w ) while( gets( data ) = NULL ) strcat( data yenn ) 改行コードの付加

fputs( data fp ) fclose( fp )

36

fputc()fgetc()関数について fputc() ファイルポインタで指定されるファイルに1文字出力します

include ltstdiohgt int fputc( int c FILE fp ) 戻り値正常に出力できた場合には文字 c を返しエラーの場合には EOF を返します fputc() は文字 c をファイルポインタで示されるファイルへ出力します

fgetc() ファイルポインタで指定されるファイルから1文字入力します

include ltstdiohgt int fgetc( FILE fp ) 戻り値正常に入力した場合には入力した文字を返しますエラーやEOFになった場合には

EOF が返されます fgetc() はファイルポインタで指定されるファイルから文字を入力します

ファイルの内容の表示 include ltstdiohgt main() FILE fp int ch char fname[30] printf( Key in Fila name gt ) gets( fname ) fp = fopen( fname r ) while( ( ch = fgetc( fp ) ) = EOF )putchar( ch ) fclose( fp )

その他テキスト中で使用された関数について sin() 三角関数の正弦を計算します

include ltmathhgt double sin(double radian) sinはラジアンを単位とする引数 radianの三角関数を計算します

37

strcpy() 文字列を他の文字列へコピーします

include ltstringhgt char strcpy(char string1const char string2) strcpyは引数 string2の指す文字列を null文字まで含めて引数 string1の指す領域にコピ

ーする strcpyは string1を返します

strcat() ある文字列を他の文字列に加えます

include ltstringhgt char strcat( char dest const char src ) 戻り値連結された文字列へのポインタを返します strcat() はsrc のコピーを dest の最後につけ加えます得られる文字列の長さは

strlen(dest)+strlen(src) になります

fabs() 絶対値の計算をします include ltmathhgt double fabs(double z) fabsは倍精度浮動小数の絶対値を計算して返しますつまりzgt=0であれば z をzlt0であ

れば-zを返します exp() 指数関数を計算します

include ltmathhgt double exp(double z) exp は引数zの指数関数つまりezを返すここではeは自然対数の底を表します対数関

数logの逆関数です

38

付 録 2 コンパイルの方法には大きく分けて第4章の実習で学んだようにデータファイルを作成してお

き ccg でコンパイルさせる方法と実行中に対話型でデータを入力していく方法があります ここでは対話型で実行を進めていく方法を紹介します ただしこの方法は計算(cpu)時間が10秒以内のものに限ります10秒を超える計算(cpu)時

間を要する場合はccg でコンパイルをするようにしてください 第4章実習の(2)(p16)までは同様です

コンパイル

コンピュータに処理を依頼します 60us1234boseicc cc rensyuc

所有するファイルの一覧を見てみます

60us1234boseicc ls -l larr 持っているファイルの一覧を見るコマンドです

-rw-r--r-- 1 60us1234 other 128 4月26日 15時14分 rensyuc -rwxr-xr-x 1 60us1234 other 361 4月26日 15時16分 aout

aout という実行形式のファイルが作成されています

実行

60us1234boseicc aout12 35[リターン] データを入力

1 200000 3500000 4200000 実行結果の出力

60us1234boseicc

注意

aout ファイルは印刷することができません実行結果を印刷する場合にはファイルに落とし てから出力するようにしましょう

60us1234boseicc aout gt kekka12 35[リターン] データを入力

60us1234boseicc more kekka 計算結果の確認 60us1234boseicc lpr kekka 計算結果の印刷

39

Page 17: n 第1章 章立ての部分は、書式(PC入門大見出し)を …第2章 数の表現 2-1 2進数 電子計算機の動作原理は0と1で表される2進数です。また、人間が日常生活で扱っている数

第4章 実習 この章ではプログラムを実際に入力して実行するまでの手順を実習します

4-1 操作手順 (1)ログイン

[スタート]rarr[プログラム(P)]rarr[ネットワーク] Hostの欄に bosei を記述選択 rarr [Telnet(FreeWare)] を選択します して 「OK」 ボタンをクリックします

UP-UXV (Rel42MP) (bosei) (pts41) login 60us1234 larr 各自のログイン名を入力します Password larr パスワードを入力しても画面は何も変化しません 101 60us1234bosei larr セッションが開設されましたこれをプロンプトといいます この状態でコマンドを入力することができます

(2)プログラムの作成 以下のコマンドを入力しテキストエディタを起動します 60us1234boseicc ng rensyuc

すると下図のようにngエディタの画面になります

15

次のように入力します入力ミスの修正はBSキーで行ないます

include ltstdiohgt main() float abc scanf(f f ampaampb) c=ab printf(f f f yenn abc)

CTRL キーを押しながら XCTRL キーを押しながら C を押しますすると次のメッセージが画面下に表示されます

Save file uhomea60us1234rensyuc (y or n)

このメッセージに対して y と答えます

(3)データの作成 以下のコマンドを入力しテキストエディタを起動します 60us1234boseicc ng rensyud

ngエディタの画面になりますので次のように入力します 12 35

CTRLキーを押しながら XCTRLキーを押しながら C を押します save file uhomea60us1234rensyud (y or n)

このメッセージに対して y と答えます

(4)コンパイルと実行 コンピュータに処理を依頼します 60us1234boseicc ccg rensyu

ジョブを投入しましたジョブの状態を見るコマンドは myjobです

16

130 60us1234boseicc myjob ================================================= NQS (R0220) BATCH REQUEST HOST bosei ================================================= REQUEST ID NAME OWNER QUEUE PRI NICE STT PGRP R --------------- -------- -------- -------- ---- --- --- ------ - 99321bosei STDIN 60us1234 A 31 0 RUN 14161 - ---------------------------------------------------------------- ================================================== NQS (R0220) DEVICE REQUEST HOST bosei ジョブは実行中です

================================================== REQUEST ID NAME OWNER QUEUE PRI SIZE STT -------------------------------------------------------------

所有するファイルの一覧を見てみます

60us1234boseicc ls -l larr 持っているファイルの一覧を見るコマンドです

-rw-r--r-- 1 60us1234 other 4 4月26日 15時14分 rensyud -rw-r--r-- 1 60us1234 other 128 4月26日 15時10分 rensyuc -rwxr-xr-x 1 60us1234 other 361 4月26日 15時16分 rensyul

(5)計算結果の確認

計算結果を画面に表示して確認します 60us1234boseicc more rensyul

(6)印刷

計算結果の印刷を行ないます5号館2階のカフェテリア室にある bosei のプリンタに印刷 されます

60us1234boseicc lpr rensyul

(7)ログアウト セッションを終了します 60us1234boseicc logout

(8)実行の流れ

エラー

プログラムの作成 ログイン コンパイル実行

確 認 印 刷 ログアウト

17

第5章 配列 多数の変数をまとめて宣言する方法として配列があります配列の一つ一つは配列要素と呼

ばれ変数と同じ性格を持っています配列の宣言は型宣言と同時に次のように行います int a[5] 配列 a

a[0]

a[1]

a[2]

a[3]

a[4]

二次元配列(一次元配列を複数集めたもの)を宣言する場合には次のようになります int b[3][4] 配列 b

b[0][0] b[0][1] b[0][2] b[0][3]

b[1][0] b[1][1] b[1][2] b[1][3]

b[2][0] b[2][1] b[2][2] b[2][3]

配列要素に数値を代入する場合は次のようになります b[1][2]=10

5-1 二次元配列要素の初期化 変数の型宣言と同じように配列を宣言するときに初期値も同時に設定することができます

複数のデータがある場合には{}記号でくくって指定します int b[3][4] = 2 4 6 8 1 3 5 7 1 2 3 4

文字型配列の場合には以下のようになりますyen0 は文字列の終わりを表わします char univ[3][7] = T O K A I yen0 S I M I Z U yen0 Y O Y O G I yen0

また文字列定数として初期化することもできますこの場合コンパイル時に自動的に yen0 が付加されます

char univ[3][7] = TOKAI SIMIZU YOYOGI

18

[プログラム例] 二次元配列のタテヨコを加算するプログラム

include ltstdiohgt main() int mat[4][3]=123456789101112 int ijytotalttotal[3]total=0 for(j=0jlt3j++)ttotal[j]=0 for (i=0ilt4i++) ytotal=0 for(j=0jlt3j++) ytotal += mat[i][j] ttotal[j] += mat[i][j] total += mat[i][j] printf(3dmat[i][j]) printf( 3dyennytotal) printf(yenn) for(j=0jlt3j++)printf(3dttotal[j]) printf( 3dyenntotal)

[実行結果]

1 2 3 6 4 5 6 15 7 8 9 24 10 11 12 33 22 26 30 78

演習7

a)以下の配列はどのように初期化されるか答えなさい char errmsg[2][15] = Divide Error Overflow Error

b)九九の計算を2次元配列を使って求めなさい

19

第6章 ポインタ型変数 C言語では値を記憶するための変数だけではなく変数または定数の番地を記憶するため

のポインタ型変数を宣言することができますポインタとはデータ項目の一種で「記憶装置(メモ

リ)上の格納番地(アドレス)を指すデータ項目」です アドレス コンピュータの中ではデータ項目の格納番地のことをアドレス(住所)と呼びます 例えば記憶装置という名前のとてつもなく大きなマンションがあるとしますその中から Aさんを捜すときは部屋番号を参照しますマンションでは部屋番号で住居人を参照し ているのと同じようにコンピュータでは記憶装置上に確保された変数は格納番地 (アドレス)で管理されています

マンション 部屋番号 記憶装置 格納番地

Aさん Int a Bさん Cさん AAAさん BBBさん CCCさん

1号室

2号室

3号室

100号室

200号室

300号室

100番地

200番地

300番地

1000番地

2000番地

3000番地

Int b Int c float aaafloat bbbfloat ccc

ポインタ ポインタとは「指し示すもの」の意ですがC言語では記憶装置上のアドレスを指し示す もののことです上のマンションの例では部屋番号を格納するデータ項目ということに なりますAAAさんは100号室に住んでいます100という値をポインタのデータ項目に 記憶するとそのデータ項目は間接的にAAAさんを指すことになります

6-1 ポインタ型変数の宣言および参照 通常の変数と区別するために型宣言時に変数名の前に記号を付けて宣言します int a 整数型ポインタ変数 int b 整数型変数

変数 a は整数型の値を記憶するのではなく整数型の値を持つ変数などの番地を記憶する変数ですまた変数 b は通常の整数型の値を記憶するための変数です

20

include ltstdiohgt main() int a b c a はポインタ型の変数b c は整数型の変数 b = 12 変数 b に値 12 を代入します a = ampb 変数 a には変数 b の番地が代入されます c = a + 10 変数 a の指す変数(b)の内容と10の加算です つまり12 + 10 を変数 c に代入します

変数の型宣言において変数名に記号を付けることによりその変数はポインタ型の変数と

なりますポインタ型の変数は変数名のみを指定した場合には単にその変数の値(通常はメモリ

の番地)を表します変数名に記号を付けて使用した場合にはその変数が指し示している変

数の内容を表します c = a ポインタ型変数 a が指している値を変数 c に代入

ポインタ型の変数に番地を記憶させるためにはプログラム例のように変数名の前に記号を

指定します変数名 によって変数の番地(アドレス)を表します a = ampb 変数 b の番地をポインタ型変数 a に代入します

ポインタ型変数の型はポインタ型変数が指し示す先の変数の型を表しています int a 変数 a 整数型の値 float x 変数 x 実数型の値 char c 変数 c 文字型の値

6-2 ポインタ型変数の初期化 ポインタ型変数も型宣言のときに変数を初期化することができます特に文字型のポインタ変

数の場合によく使います char str = TOKAI University

ポインタ型変数 str は文字列定数 TOKAI University の最初の文字が格納されている番地を初期値として持つことになります

変数 str TOKAI University 文字列定数

[プログラム例]

(1)文字型配列 putchar() 関数を使って一次元の文字型配列を出力します include ltstdiohgt main() char str[6] = TOKAI int i for( i = 0 str[i] = yen0 i++ ) putchar( str[i] )

21

ポインタを使用した場合には以下のようになります include ltstdiohgt main() char str[6] = TOKAI char chp for( chp = str chp = yen0 chp++ ) putchar( chp )

chp str T [0] O K A I yen0 [5]

参照する変数 配列の表現 ポインタの表現 実際のアドレス 1番目の数 str[0] chp CHP 2番目の数 str[1] (chp+1) CHP+1 n番目の数 str[n-1] (chp+n-1) CHP+n-1 6番目の数 str[5] (chp+5) CHP+5

注意実際のアドレス CHPは実行時に決定されます

(2)二次元文字型配列 二次元の文字型配列に定数を設定しそれを出力するプログラムです文字型配列を使用す

ると次のとおりになります include ltstdiohgt main() char str[5][40] = TOKAI shounan campus NEC DEC int i for( i = 0 i lt 5 i++ ) printf( yenns str[i] )

40 バイト str TOKAI shounan campus NEC DEC

22

ポインタ型配列を使用すると次のとおりになります include ltstdiohgt main() char str[6] = TOKAI shounan campus NEC DEC NULL char chp for( chp = str chp = NULL chp++ ) printf( yenns chp ) str

chp 番地 TOKAI 番地 shounan 番地 campus 番地 NEC 番地 DEC

NULL

演習8 キーボードまたはデータファイルから読み込んだ文字列中にrsquoArsquo があったら rsquoarsquo に変換 するプログラムを配列とポインタを使って書きなさい

23

第7章 構造体共用体 7-1 構造体

プログラムの規模が大きくなるにつれて多数の intや floatcharなどのデータ型を扱うようになり複雑になってきますそこで多数のデータを1つにまとめて簡単に扱える機能が構造体です 構造体について住所録のデータを例にあげて考えてみます

住所録の個人データとして氏名住所電話番号年齢の項目を一つのデータとします これをC言語で変数の定義をすると次のようになります 氏名東海太郎 char name[30] 住所平塚市北金目1117 char address[30] 電話番号0463-58-1211 char tel[20] 年齢30 int age 個人の住所録データ C言語での表現 このような住所録の個人データを1つにまとめて新しいデータとして定義する機能を構造体と言

います struct 構造体タグ名 構造体メンバーの並び

「struct」は構造体を表すキーワードです 「構造体タグ名」は構造体の型枠を宣言しますここは自由に名前を定義することができ ます 「構造体メンバーの並び」は構造体の要素です複数指定できます

個人の住所録のデータを構造体で宣言すると次のようになります

struct jusho char name[30] char address[30] 構造体のメンバーの並び char tel[20] (複数可)

int age

上記の宣言では構造体の形式を宣言しているだけでメモリ中で実際の領域を確保している

わけではありません実際に領域を確保するためには次のように定義します

struct 構造体タグ名 構造体名

したがって構造体名を jdata とすると次のように指定します

struct jusho jdata

構造体 jdataは次のように構造体タグ jushoの形式で領域を確保します

24

Jdata name[30]

address[30] tel[20] age

(1)構造体の参照

プログラム中で構造体中のメンバーを参照する場合には次のように指定します 構造体名メンバー名

したがって「名前」を参照したいときには次のように指定します

jdataname

[プログラム例]

名前住所電話番号年齢を定義しそれを印字します include ltstdiohgt include ltstringhgt main() struct jusho char name[30] char address[30] char tel[20] int age struct jusho jdata strcpy( jdataname 東海 太郎) strcpy( jdataaddress 平塚市北金目1117)

strcpy( jdatatel 0463-58-1211) jdataage = 30 printf(yenn氏名 = syenn jdataname) printf(yenn住所 = syenn jdataaddress) printf(yenn電話番号= syenn jdatatel) printf(yenn年齢 = dyenn jdataage)

また構造体の形式の定義と領域の確保は次のように同時におこなうことができます

struct 構造体タグ名 構造体メンバーの並び 構造体名

struct jusho struct jusho char name[30] char name[30] char address[30] char address[30] char tel[30] = char tel[30] int age 同じ int age

jdata struct jusho jdata

型宣言と同時にメモリ上に領域を確保する方法 後からメモリ上に領域を確保する方法

25

(2) 構造体配列 住所録データの場合その中に入るデータは1件ではありませんやはり100件200件のデ

ータが必要になる場合がありますこのように個人単位のデータを多数扱う場合には構造体を配

列として宣言することができます 次の例は個人のデータを100個用意するために構造体を配列として宣言しています struct jusho jdata[100] jdata[0] name[30] address[30] tel[20] age

jdata[99 ] name[30] address[30] tel[20] age

(3)構造体配列の参照

プログラム中で構造体配列中のメンバーを参照する場合には次のように指定します 構造体名[要素番号]メンバー名

したがって10件目の人の「名前」を参照したいときには次のように指定します

jdata[10]name

[プログラム例]

名前住所電話番号年齢を定義しそれを印字します include ltstdiohgt include ltstringhgt main() struct jusho char name[30] char address[30] char tel[20] int age jdata[100] strcpy( jdata[10]name 東海 太郎) strcpy( jdata[10]address 平塚市北金目1117)

strcpy( jdata[10]tel 0463-58-1211) jdata[10]age = 30 printf(yenn氏名 = syenn jdata[10]name) printf(yenn住所 = syenn jdata[10]address) printf(yenn電話番号= syenn jdata[10]tel) printf(yenn年齢 = dyenn jdata[10]age)

26

(4) 構造体のポインタ 変数と同じように構造体へのポインタも定義することができます

変数へのポインタ例 構造体へのポインタ例 またポインタを使用して構造体メンバーを参照するには次のように -> 記号を使って指

定します ポインタ変数名 -> メンバー名

[プログラム例]

名前住所電話番号年齢を定義しそれを印字します include ltstdiohgt include ltstringhgt main() struct jusho char name[30] char address[30] char tel[20] int age jdatakp kp = ampjdata strcpy( kp-gtname 東海 太郎)

strcpy( kp-gtaddress 平塚市北金目1117)

strcpy( kp-gttel 0463-58-1211) kp-gtage = 30 printf(yenn氏名 = syenn kp-gtname) printf(yenn住所 = syenn kp-gtaddress) printf(yenn電話番号= syenn kp-gttel) printf(yenn年齢 = dyenn kp-gtage)

kp jdata

name[30] ポインタ型の変数 address[30]

tel[20]

構造体へのポインタを記憶 age

することができます

int a int b b = ampa

struct name jname struct name np np = ampname

27

7-2 共用体 共用体は構造体と同じようにして宣言しますが共用体は複数のデータ型を同一のアドレスに

割り当てる方法です union 共用体タグ名 共用体メンバーの並び

「union」は共用体を表すキーワードです 「共用体タグ名」は共用体の型枠の名前を宣言しますここは自由に名前を定義することがで

きます 「共用体メンバーの並び」は共用体の要素です複数指定できます

共用体の宣言の例を次に示します

union c_tag int a char b

共用体 cは次のように共用体タグ c_tagの形式で領域を確保します共用体はメモリ上に領域を確保するときは ab ともに同じ領域に割り付けられます これはab という2つのデータが同時に存在するわけではなく cを異なるデータ abで共有す

ることを表しています c a b

上記の宣言だけでは共用体の形式を宣言しているだけでメモリ中で実際の領域を確保して

いるわけではありません実際に領域を確保するためには次のように定義します union 構造体タグ名 構造体名

したがって共用体名を c とすると次のように指定します

union c_tag c

(1)共用体の参照

プログラム中で共用体中のメンバーを参照する場合には次のように指定します 共用体名メンバー名

したがって「a」または「b」を参照したいときには次のように指定します

ca (int 型) cb (char 型)

メンバー参照方法によって int型として使ったりchar型として利用することができます

28

[プログラム例]

includeltstdiohgt main() union data char a short b int c chk chkc = 0x12345678 printf( char a xyennchka) printf( short b xyennchkb) printf( int c xyennchkc)

chkb(int 型) chkb(short 型) chka(char 型) 12 12 12 34 34 56 78

29

第8章 アルゴリズム コンピュータに何か仕事をさせようとするときは仕事を具体的に実行するための処理や動作

の手順が必要ですこの「手順」がアルゴリズムです アルゴリズムを考えるときは解くべき問題をはっきりと定義することが必要です

8-1 ソート ソートとは与えられたデータを小さい順または大きい順に並べ換えることですソート方法は

いくつかありますが基本的な方法でソートするアルゴリズムを紹介します

includeltstdiohgt int data[10] main()

int data_in() sort() data_in() sort() int data_in() データ入力関数

int a printf(数値入力yenn)

for(a=0alt=9a++) printf( [d]a+1) scanf(dampdata[a]) int sort() ソート処理を行う関数

int cont1cont2tmp1tmp2mim for(cont1=0 cont1lt=9 cont1++) mim=data[cont1] tmp1=cont1 for(cont2=cont1+1 cont2lt=9 cont2++) if(data[cont2] lt mim) mim=data[cont2] tmp1=cont2 tmp2 = data[cont1] data[cont1] = data[tmp1] data[tmp1] = tmp2 printf(結果 yenn)

for (cont1 = 0 cont1 lt= 9 cont1++) printf(d yenn data[cont1])

30

第9章 プリプロセッサ C言語にはプログラムの中でコンパイルについての指示を行う「プリプロセッサ」という機能が

ありますまたプリプロセッサとはコンパイルする前に実行されるためその意味のとおり「前処理」 と呼ばれていますここでは代表的なものをいくつか説明します

9-1 ファイルの挿入 ソースプログラム中に指定されたファイルを挿入します

include ltstdiohgt helliphellip 標準ディレクトリを探します include progh helliphellip 現在のディレクトリを探しなければ標準ディレクトリを探します

includeltstdiohgt によって組み込まれた define EOF (-1) define EOF (-1) define define helliphelliphelliphellip 組み込み helliphelliphelliphellip

main() stdiohファイル

int helliphelliphelliphellip helliphelliphelliphellip

ソースファイル

9-2 文字の置換 プログラム中に使われている文字列を別の文字列に置き換えます

include ltstdiohgt define TRUE 1 define EOF (-1) main() define helliphellip helliphellip

while(TRUE) define TRUE 1 置き換え main() helliphellip helliphellip while(1)

break helliphelliphellip

31

9-3 条件によるコンパイル 識別子が定義されているか否かを判断しコンパイルする範囲を指定します

include ltstdiohgt define UNIX main() ifdef UNIX printf( UNIX yenn) else printf(MS-DOSyenn) endif

include ltstdiohgt define OS UNIX main() if OS == UNIX printf( UNIX yenn) else printf(MS-DOSyenn) endif

32

付 録 1 puts()gets()関数について

行単位に入出力を行う場合には puts() gets() 関数を用います

puts() 標準出力に文字列を出力します

include ltstdiohgt int puts( char s ) puts() は NULL で終る文字列 s を標準出力に出力し最後に改行文字 yenn も出力しま

gets() 標準入力から文字列を入力します

include ltstdiohgt char gets( char s ) 戻り値正常に入力した場合には引数 s の値が返されますエラーやEOFになった場合に

は NULL が返されます gets() は標準入力から復帰文字で終る文字列を入力しs に格納しますこのとき最後の復

帰文字は NULL文字に変更されます

入力行の出力 標準入力から gets() で入力したデータには改行コードは含まれませんまた標準出力へ

puts() で出力を行う場合には必ず改行コードが付加されますgets() を実行したときの戻り値としてファイルの終端を検出した場合には EOF ではなく NULL が返されますので注意して下さい

include ltstdiohgt main() char data[80] while( gets( data ) = NULL )puts( data )

putchar()getchar()関数について putchar() 標準出力に文字を出力します

include ltstdiohgt int putchar(int c ) 戻り値正常に出力できた場合には文字cをエラーの場合にはEOFを返します

33

getchar() 標準入力から文字を入力します

include ltstdiohgt int getchar(void) 戻り値正常に入力した場合には読み込んだ文字を int 型に変換して返しますまたファイ

ルエンドエラーの場合にはEOFを返します

標準入力標準出力

標準入力標準出力はプログラムが開始されるときにはオープンされていますそれぞれのフ

ァイルポインタは stdin stdout になっていますfopen() fclose() をせずとも使用することができます

scanf() 標準出力ストリームからテキストを読み込み解釈します include ltstdiohgt int scanf( const char format [ address ] ) 戻り値正しくスキャンし変換し格納した入力フィールドの数を返しますファイルエンドを読

み込んだ場合は戻り値は EOF となります値を格納したフィールドがなかった場合は戻り値は0となります

一連の入力フィールドをスキャンして1度に1文字ずつストリーム stdin から文字を読み込み

ます次に引き数 format によって指される書式文字列中の書式指定に従って各フィールドを書式化します最後にformat の後に続く各引き数が示しているアドレスに書式化した入力を格納していきます書式文字列中の書式指定の個数はその後に続くアドレスの数と同じでな

ければなりません 書式指定[入力幅][型指定文字] 入力幅 読むべき文字数の最大値 型指定文字 次のとおりです 型指定文字 期待される入力 引き数の型 d 10進整数 int へのポインタ( int arg ) x 16進整数 int へのポインタ( int arg ) f 浮動小数点数 float へのポインタ( float arg ) s 文字列 文字配列へのポインタ( char arg[] ) c 文字 文字へのポインタ( char arg )

printf() フォーマットを指定してテキスト標準出力ストリームに出力します include ltstdiohgt int printf( const char format [ argument ] ) 戻り値出力したバイト数を返しますエラーの場合は EOF を返します

34

format によって指される書式文字列中の書式指定をformat の後に続く各引き数に適用し

書式化されたデータを stdout に出力します書式指定は後に続く引き数と同じ数だけなければなりません

書式指定[印字幅][精度][型指定文字] 印字幅 印字する最小文字数 精度 印字する最大文字数 型指定文字 つぎのとおりです 型指定文字 入力引き数 出力の書式 d 整数 符号付き10進整数 x 整数 符号無し16進整数 f 浮動小数点 符号付きの dddddddd形式の値 c 文字 1個の文字 s 文字列ポインタ ヌル文字に出会うか精度に達するまで 文字をプリントする

fopen()fclose()関数について fopen() ファイルをオープンします

include ltstdiohgt FILE fopen( char filename char mode ) 戻り値正常にファイルのオープンができたらファイルポインタを返しますエラーがあった場

合には NULLを返します 文字列 filename で指定されたファイルをオープンしますオープン後の入出力のモードに

ついては文字列 mode で指定しますmode に指定できる文字は以下のとおりです r 入力モードでオープンします w 出力モードでオープンします a 存在するファイルに追加して出力するモードでオープンします r+ 既に作成してあるファイルを更新(入力出力)するモードでオープンします w+ 新しく作成するファイルを更新モードでオープンします a+ 既に作成してあるファイルの終りから更新用に作成します

以上の文字に b をつけ加えることによりバイナリモードで入出力することができるようになり

ます rb バイナリの入力モードでオープンします wb バイナリの出力モードでオープンします ab 存在するファイルに追加して出力するモード(バイナリ)でオープンします

fclose() 既にオープンしてあるファイルをクローズします include ltstdiohgt fclose( FILE fp ) 既にオープンしているファイルをクローズしますパラメータには fopen() 関数により返された

ファイルポインタを指定します

35

テキストモードとバイナリモード 行の最後はテキストモードの場合改行コードのみとなりバイナリモードの場合には復帰

コードと改行コードの組合わせになります行の最後としてテキストファイルには復帰コード改行

コードが書かれていますがテキストモードでオープンした場合には入力すると改行コードのみに

変換されて入力されますバイナリモードの場合には復帰コード改行コードがそれぞれ入力され

ます

fputs()fgets()関数について fputs() ファイルポインタで指定されるファイルに文字列を出力します

include ltstdiohgt

int fputs( char s FILE fp ) fputs() は NULL で終る文字列 s をファイルポインタに示されるファイルへ出力しますputs()

と違い最後に改行文字 yenn を出力することはありません

fgets() ファイルポインタで指定されるファイルから文字列を入力します include ltstdiohgt char fgets( char s int n FILE fp ) 戻り値正常に入力した場合には引数 s の値が返されますエラーやEOFになった場合に

は NULL が返されます fgets() はファイルポインタで指定されるファイルから ( n - 1 ) 文字または改行文字までの

文字列を入力しs に格納しますgets() と異なり最後に入力された改行文字は NULL 文字に変更されません

標準入力から入力しファイルへ出力する ファイルへ出力あるいは入力を行う場合には改行コードの変換(入力の場合の削除出力の

場合の付加)はされませんしたがって標準入力から入力しファイルへ出力する場合には改行

コードを付加しなければなりません include ltstdiohgt main() char data[80] FILE fp fp = fopen( data w ) while( gets( data ) = NULL ) strcat( data yenn ) 改行コードの付加

fputs( data fp ) fclose( fp )

36

fputc()fgetc()関数について fputc() ファイルポインタで指定されるファイルに1文字出力します

include ltstdiohgt int fputc( int c FILE fp ) 戻り値正常に出力できた場合には文字 c を返しエラーの場合には EOF を返します fputc() は文字 c をファイルポインタで示されるファイルへ出力します

fgetc() ファイルポインタで指定されるファイルから1文字入力します

include ltstdiohgt int fgetc( FILE fp ) 戻り値正常に入力した場合には入力した文字を返しますエラーやEOFになった場合には

EOF が返されます fgetc() はファイルポインタで指定されるファイルから文字を入力します

ファイルの内容の表示 include ltstdiohgt main() FILE fp int ch char fname[30] printf( Key in Fila name gt ) gets( fname ) fp = fopen( fname r ) while( ( ch = fgetc( fp ) ) = EOF )putchar( ch ) fclose( fp )

その他テキスト中で使用された関数について sin() 三角関数の正弦を計算します

include ltmathhgt double sin(double radian) sinはラジアンを単位とする引数 radianの三角関数を計算します

37

strcpy() 文字列を他の文字列へコピーします

include ltstringhgt char strcpy(char string1const char string2) strcpyは引数 string2の指す文字列を null文字まで含めて引数 string1の指す領域にコピ

ーする strcpyは string1を返します

strcat() ある文字列を他の文字列に加えます

include ltstringhgt char strcat( char dest const char src ) 戻り値連結された文字列へのポインタを返します strcat() はsrc のコピーを dest の最後につけ加えます得られる文字列の長さは

strlen(dest)+strlen(src) になります

fabs() 絶対値の計算をします include ltmathhgt double fabs(double z) fabsは倍精度浮動小数の絶対値を計算して返しますつまりzgt=0であれば z をzlt0であ

れば-zを返します exp() 指数関数を計算します

include ltmathhgt double exp(double z) exp は引数zの指数関数つまりezを返すここではeは自然対数の底を表します対数関

数logの逆関数です

38

付 録 2 コンパイルの方法には大きく分けて第4章の実習で学んだようにデータファイルを作成してお

き ccg でコンパイルさせる方法と実行中に対話型でデータを入力していく方法があります ここでは対話型で実行を進めていく方法を紹介します ただしこの方法は計算(cpu)時間が10秒以内のものに限ります10秒を超える計算(cpu)時

間を要する場合はccg でコンパイルをするようにしてください 第4章実習の(2)(p16)までは同様です

コンパイル

コンピュータに処理を依頼します 60us1234boseicc cc rensyuc

所有するファイルの一覧を見てみます

60us1234boseicc ls -l larr 持っているファイルの一覧を見るコマンドです

-rw-r--r-- 1 60us1234 other 128 4月26日 15時14分 rensyuc -rwxr-xr-x 1 60us1234 other 361 4月26日 15時16分 aout

aout という実行形式のファイルが作成されています

実行

60us1234boseicc aout12 35[リターン] データを入力

1 200000 3500000 4200000 実行結果の出力

60us1234boseicc

注意

aout ファイルは印刷することができません実行結果を印刷する場合にはファイルに落とし てから出力するようにしましょう

60us1234boseicc aout gt kekka12 35[リターン] データを入力

60us1234boseicc more kekka 計算結果の確認 60us1234boseicc lpr kekka 計算結果の印刷

39

Page 18: n 第1章 章立ての部分は、書式(PC入門大見出し)を …第2章 数の表現 2-1 2進数 電子計算機の動作原理は0と1で表される2進数です。また、人間が日常生活で扱っている数

次のように入力します入力ミスの修正はBSキーで行ないます

include ltstdiohgt main() float abc scanf(f f ampaampb) c=ab printf(f f f yenn abc)

CTRL キーを押しながら XCTRL キーを押しながら C を押しますすると次のメッセージが画面下に表示されます

Save file uhomea60us1234rensyuc (y or n)

このメッセージに対して y と答えます

(3)データの作成 以下のコマンドを入力しテキストエディタを起動します 60us1234boseicc ng rensyud

ngエディタの画面になりますので次のように入力します 12 35

CTRLキーを押しながら XCTRLキーを押しながら C を押します save file uhomea60us1234rensyud (y or n)

このメッセージに対して y と答えます

(4)コンパイルと実行 コンピュータに処理を依頼します 60us1234boseicc ccg rensyu

ジョブを投入しましたジョブの状態を見るコマンドは myjobです

16

130 60us1234boseicc myjob ================================================= NQS (R0220) BATCH REQUEST HOST bosei ================================================= REQUEST ID NAME OWNER QUEUE PRI NICE STT PGRP R --------------- -------- -------- -------- ---- --- --- ------ - 99321bosei STDIN 60us1234 A 31 0 RUN 14161 - ---------------------------------------------------------------- ================================================== NQS (R0220) DEVICE REQUEST HOST bosei ジョブは実行中です

================================================== REQUEST ID NAME OWNER QUEUE PRI SIZE STT -------------------------------------------------------------

所有するファイルの一覧を見てみます

60us1234boseicc ls -l larr 持っているファイルの一覧を見るコマンドです

-rw-r--r-- 1 60us1234 other 4 4月26日 15時14分 rensyud -rw-r--r-- 1 60us1234 other 128 4月26日 15時10分 rensyuc -rwxr-xr-x 1 60us1234 other 361 4月26日 15時16分 rensyul

(5)計算結果の確認

計算結果を画面に表示して確認します 60us1234boseicc more rensyul

(6)印刷

計算結果の印刷を行ないます5号館2階のカフェテリア室にある bosei のプリンタに印刷 されます

60us1234boseicc lpr rensyul

(7)ログアウト セッションを終了します 60us1234boseicc logout

(8)実行の流れ

エラー

プログラムの作成 ログイン コンパイル実行

確 認 印 刷 ログアウト

17

第5章 配列 多数の変数をまとめて宣言する方法として配列があります配列の一つ一つは配列要素と呼

ばれ変数と同じ性格を持っています配列の宣言は型宣言と同時に次のように行います int a[5] 配列 a

a[0]

a[1]

a[2]

a[3]

a[4]

二次元配列(一次元配列を複数集めたもの)を宣言する場合には次のようになります int b[3][4] 配列 b

b[0][0] b[0][1] b[0][2] b[0][3]

b[1][0] b[1][1] b[1][2] b[1][3]

b[2][0] b[2][1] b[2][2] b[2][3]

配列要素に数値を代入する場合は次のようになります b[1][2]=10

5-1 二次元配列要素の初期化 変数の型宣言と同じように配列を宣言するときに初期値も同時に設定することができます

複数のデータがある場合には{}記号でくくって指定します int b[3][4] = 2 4 6 8 1 3 5 7 1 2 3 4

文字型配列の場合には以下のようになりますyen0 は文字列の終わりを表わします char univ[3][7] = T O K A I yen0 S I M I Z U yen0 Y O Y O G I yen0

また文字列定数として初期化することもできますこの場合コンパイル時に自動的に yen0 が付加されます

char univ[3][7] = TOKAI SIMIZU YOYOGI

18

[プログラム例] 二次元配列のタテヨコを加算するプログラム

include ltstdiohgt main() int mat[4][3]=123456789101112 int ijytotalttotal[3]total=0 for(j=0jlt3j++)ttotal[j]=0 for (i=0ilt4i++) ytotal=0 for(j=0jlt3j++) ytotal += mat[i][j] ttotal[j] += mat[i][j] total += mat[i][j] printf(3dmat[i][j]) printf( 3dyennytotal) printf(yenn) for(j=0jlt3j++)printf(3dttotal[j]) printf( 3dyenntotal)

[実行結果]

1 2 3 6 4 5 6 15 7 8 9 24 10 11 12 33 22 26 30 78

演習7

a)以下の配列はどのように初期化されるか答えなさい char errmsg[2][15] = Divide Error Overflow Error

b)九九の計算を2次元配列を使って求めなさい

19

第6章 ポインタ型変数 C言語では値を記憶するための変数だけではなく変数または定数の番地を記憶するため

のポインタ型変数を宣言することができますポインタとはデータ項目の一種で「記憶装置(メモ

リ)上の格納番地(アドレス)を指すデータ項目」です アドレス コンピュータの中ではデータ項目の格納番地のことをアドレス(住所)と呼びます 例えば記憶装置という名前のとてつもなく大きなマンションがあるとしますその中から Aさんを捜すときは部屋番号を参照しますマンションでは部屋番号で住居人を参照し ているのと同じようにコンピュータでは記憶装置上に確保された変数は格納番地 (アドレス)で管理されています

マンション 部屋番号 記憶装置 格納番地

Aさん Int a Bさん Cさん AAAさん BBBさん CCCさん

1号室

2号室

3号室

100号室

200号室

300号室

100番地

200番地

300番地

1000番地

2000番地

3000番地

Int b Int c float aaafloat bbbfloat ccc

ポインタ ポインタとは「指し示すもの」の意ですがC言語では記憶装置上のアドレスを指し示す もののことです上のマンションの例では部屋番号を格納するデータ項目ということに なりますAAAさんは100号室に住んでいます100という値をポインタのデータ項目に 記憶するとそのデータ項目は間接的にAAAさんを指すことになります

6-1 ポインタ型変数の宣言および参照 通常の変数と区別するために型宣言時に変数名の前に記号を付けて宣言します int a 整数型ポインタ変数 int b 整数型変数

変数 a は整数型の値を記憶するのではなく整数型の値を持つ変数などの番地を記憶する変数ですまた変数 b は通常の整数型の値を記憶するための変数です

20

include ltstdiohgt main() int a b c a はポインタ型の変数b c は整数型の変数 b = 12 変数 b に値 12 を代入します a = ampb 変数 a には変数 b の番地が代入されます c = a + 10 変数 a の指す変数(b)の内容と10の加算です つまり12 + 10 を変数 c に代入します

変数の型宣言において変数名に記号を付けることによりその変数はポインタ型の変数と

なりますポインタ型の変数は変数名のみを指定した場合には単にその変数の値(通常はメモリ

の番地)を表します変数名に記号を付けて使用した場合にはその変数が指し示している変

数の内容を表します c = a ポインタ型変数 a が指している値を変数 c に代入

ポインタ型の変数に番地を記憶させるためにはプログラム例のように変数名の前に記号を

指定します変数名 によって変数の番地(アドレス)を表します a = ampb 変数 b の番地をポインタ型変数 a に代入します

ポインタ型変数の型はポインタ型変数が指し示す先の変数の型を表しています int a 変数 a 整数型の値 float x 変数 x 実数型の値 char c 変数 c 文字型の値

6-2 ポインタ型変数の初期化 ポインタ型変数も型宣言のときに変数を初期化することができます特に文字型のポインタ変

数の場合によく使います char str = TOKAI University

ポインタ型変数 str は文字列定数 TOKAI University の最初の文字が格納されている番地を初期値として持つことになります

変数 str TOKAI University 文字列定数

[プログラム例]

(1)文字型配列 putchar() 関数を使って一次元の文字型配列を出力します include ltstdiohgt main() char str[6] = TOKAI int i for( i = 0 str[i] = yen0 i++ ) putchar( str[i] )

21

ポインタを使用した場合には以下のようになります include ltstdiohgt main() char str[6] = TOKAI char chp for( chp = str chp = yen0 chp++ ) putchar( chp )

chp str T [0] O K A I yen0 [5]

参照する変数 配列の表現 ポインタの表現 実際のアドレス 1番目の数 str[0] chp CHP 2番目の数 str[1] (chp+1) CHP+1 n番目の数 str[n-1] (chp+n-1) CHP+n-1 6番目の数 str[5] (chp+5) CHP+5

注意実際のアドレス CHPは実行時に決定されます

(2)二次元文字型配列 二次元の文字型配列に定数を設定しそれを出力するプログラムです文字型配列を使用す

ると次のとおりになります include ltstdiohgt main() char str[5][40] = TOKAI shounan campus NEC DEC int i for( i = 0 i lt 5 i++ ) printf( yenns str[i] )

40 バイト str TOKAI shounan campus NEC DEC

22

ポインタ型配列を使用すると次のとおりになります include ltstdiohgt main() char str[6] = TOKAI shounan campus NEC DEC NULL char chp for( chp = str chp = NULL chp++ ) printf( yenns chp ) str

chp 番地 TOKAI 番地 shounan 番地 campus 番地 NEC 番地 DEC

NULL

演習8 キーボードまたはデータファイルから読み込んだ文字列中にrsquoArsquo があったら rsquoarsquo に変換 するプログラムを配列とポインタを使って書きなさい

23

第7章 構造体共用体 7-1 構造体

プログラムの規模が大きくなるにつれて多数の intや floatcharなどのデータ型を扱うようになり複雑になってきますそこで多数のデータを1つにまとめて簡単に扱える機能が構造体です 構造体について住所録のデータを例にあげて考えてみます

住所録の個人データとして氏名住所電話番号年齢の項目を一つのデータとします これをC言語で変数の定義をすると次のようになります 氏名東海太郎 char name[30] 住所平塚市北金目1117 char address[30] 電話番号0463-58-1211 char tel[20] 年齢30 int age 個人の住所録データ C言語での表現 このような住所録の個人データを1つにまとめて新しいデータとして定義する機能を構造体と言

います struct 構造体タグ名 構造体メンバーの並び

「struct」は構造体を表すキーワードです 「構造体タグ名」は構造体の型枠を宣言しますここは自由に名前を定義することができ ます 「構造体メンバーの並び」は構造体の要素です複数指定できます

個人の住所録のデータを構造体で宣言すると次のようになります

struct jusho char name[30] char address[30] 構造体のメンバーの並び char tel[20] (複数可)

int age

上記の宣言では構造体の形式を宣言しているだけでメモリ中で実際の領域を確保している

わけではありません実際に領域を確保するためには次のように定義します

struct 構造体タグ名 構造体名

したがって構造体名を jdata とすると次のように指定します

struct jusho jdata

構造体 jdataは次のように構造体タグ jushoの形式で領域を確保します

24

Jdata name[30]

address[30] tel[20] age

(1)構造体の参照

プログラム中で構造体中のメンバーを参照する場合には次のように指定します 構造体名メンバー名

したがって「名前」を参照したいときには次のように指定します

jdataname

[プログラム例]

名前住所電話番号年齢を定義しそれを印字します include ltstdiohgt include ltstringhgt main() struct jusho char name[30] char address[30] char tel[20] int age struct jusho jdata strcpy( jdataname 東海 太郎) strcpy( jdataaddress 平塚市北金目1117)

strcpy( jdatatel 0463-58-1211) jdataage = 30 printf(yenn氏名 = syenn jdataname) printf(yenn住所 = syenn jdataaddress) printf(yenn電話番号= syenn jdatatel) printf(yenn年齢 = dyenn jdataage)

また構造体の形式の定義と領域の確保は次のように同時におこなうことができます

struct 構造体タグ名 構造体メンバーの並び 構造体名

struct jusho struct jusho char name[30] char name[30] char address[30] char address[30] char tel[30] = char tel[30] int age 同じ int age

jdata struct jusho jdata

型宣言と同時にメモリ上に領域を確保する方法 後からメモリ上に領域を確保する方法

25

(2) 構造体配列 住所録データの場合その中に入るデータは1件ではありませんやはり100件200件のデ

ータが必要になる場合がありますこのように個人単位のデータを多数扱う場合には構造体を配

列として宣言することができます 次の例は個人のデータを100個用意するために構造体を配列として宣言しています struct jusho jdata[100] jdata[0] name[30] address[30] tel[20] age

jdata[99 ] name[30] address[30] tel[20] age

(3)構造体配列の参照

プログラム中で構造体配列中のメンバーを参照する場合には次のように指定します 構造体名[要素番号]メンバー名

したがって10件目の人の「名前」を参照したいときには次のように指定します

jdata[10]name

[プログラム例]

名前住所電話番号年齢を定義しそれを印字します include ltstdiohgt include ltstringhgt main() struct jusho char name[30] char address[30] char tel[20] int age jdata[100] strcpy( jdata[10]name 東海 太郎) strcpy( jdata[10]address 平塚市北金目1117)

strcpy( jdata[10]tel 0463-58-1211) jdata[10]age = 30 printf(yenn氏名 = syenn jdata[10]name) printf(yenn住所 = syenn jdata[10]address) printf(yenn電話番号= syenn jdata[10]tel) printf(yenn年齢 = dyenn jdata[10]age)

26

(4) 構造体のポインタ 変数と同じように構造体へのポインタも定義することができます

変数へのポインタ例 構造体へのポインタ例 またポインタを使用して構造体メンバーを参照するには次のように -> 記号を使って指

定します ポインタ変数名 -> メンバー名

[プログラム例]

名前住所電話番号年齢を定義しそれを印字します include ltstdiohgt include ltstringhgt main() struct jusho char name[30] char address[30] char tel[20] int age jdatakp kp = ampjdata strcpy( kp-gtname 東海 太郎)

strcpy( kp-gtaddress 平塚市北金目1117)

strcpy( kp-gttel 0463-58-1211) kp-gtage = 30 printf(yenn氏名 = syenn kp-gtname) printf(yenn住所 = syenn kp-gtaddress) printf(yenn電話番号= syenn kp-gttel) printf(yenn年齢 = dyenn kp-gtage)

kp jdata

name[30] ポインタ型の変数 address[30]

tel[20]

構造体へのポインタを記憶 age

することができます

int a int b b = ampa

struct name jname struct name np np = ampname

27

7-2 共用体 共用体は構造体と同じようにして宣言しますが共用体は複数のデータ型を同一のアドレスに

割り当てる方法です union 共用体タグ名 共用体メンバーの並び

「union」は共用体を表すキーワードです 「共用体タグ名」は共用体の型枠の名前を宣言しますここは自由に名前を定義することがで

きます 「共用体メンバーの並び」は共用体の要素です複数指定できます

共用体の宣言の例を次に示します

union c_tag int a char b

共用体 cは次のように共用体タグ c_tagの形式で領域を確保します共用体はメモリ上に領域を確保するときは ab ともに同じ領域に割り付けられます これはab という2つのデータが同時に存在するわけではなく cを異なるデータ abで共有す

ることを表しています c a b

上記の宣言だけでは共用体の形式を宣言しているだけでメモリ中で実際の領域を確保して

いるわけではありません実際に領域を確保するためには次のように定義します union 構造体タグ名 構造体名

したがって共用体名を c とすると次のように指定します

union c_tag c

(1)共用体の参照

プログラム中で共用体中のメンバーを参照する場合には次のように指定します 共用体名メンバー名

したがって「a」または「b」を参照したいときには次のように指定します

ca (int 型) cb (char 型)

メンバー参照方法によって int型として使ったりchar型として利用することができます

28

[プログラム例]

includeltstdiohgt main() union data char a short b int c chk chkc = 0x12345678 printf( char a xyennchka) printf( short b xyennchkb) printf( int c xyennchkc)

chkb(int 型) chkb(short 型) chka(char 型) 12 12 12 34 34 56 78

29

第8章 アルゴリズム コンピュータに何か仕事をさせようとするときは仕事を具体的に実行するための処理や動作

の手順が必要ですこの「手順」がアルゴリズムです アルゴリズムを考えるときは解くべき問題をはっきりと定義することが必要です

8-1 ソート ソートとは与えられたデータを小さい順または大きい順に並べ換えることですソート方法は

いくつかありますが基本的な方法でソートするアルゴリズムを紹介します

includeltstdiohgt int data[10] main()

int data_in() sort() data_in() sort() int data_in() データ入力関数

int a printf(数値入力yenn)

for(a=0alt=9a++) printf( [d]a+1) scanf(dampdata[a]) int sort() ソート処理を行う関数

int cont1cont2tmp1tmp2mim for(cont1=0 cont1lt=9 cont1++) mim=data[cont1] tmp1=cont1 for(cont2=cont1+1 cont2lt=9 cont2++) if(data[cont2] lt mim) mim=data[cont2] tmp1=cont2 tmp2 = data[cont1] data[cont1] = data[tmp1] data[tmp1] = tmp2 printf(結果 yenn)

for (cont1 = 0 cont1 lt= 9 cont1++) printf(d yenn data[cont1])

30

第9章 プリプロセッサ C言語にはプログラムの中でコンパイルについての指示を行う「プリプロセッサ」という機能が

ありますまたプリプロセッサとはコンパイルする前に実行されるためその意味のとおり「前処理」 と呼ばれていますここでは代表的なものをいくつか説明します

9-1 ファイルの挿入 ソースプログラム中に指定されたファイルを挿入します

include ltstdiohgt helliphellip 標準ディレクトリを探します include progh helliphellip 現在のディレクトリを探しなければ標準ディレクトリを探します

includeltstdiohgt によって組み込まれた define EOF (-1) define EOF (-1) define define helliphelliphelliphellip 組み込み helliphelliphelliphellip

main() stdiohファイル

int helliphelliphelliphellip helliphelliphelliphellip

ソースファイル

9-2 文字の置換 プログラム中に使われている文字列を別の文字列に置き換えます

include ltstdiohgt define TRUE 1 define EOF (-1) main() define helliphellip helliphellip

while(TRUE) define TRUE 1 置き換え main() helliphellip helliphellip while(1)

break helliphelliphellip

31

9-3 条件によるコンパイル 識別子が定義されているか否かを判断しコンパイルする範囲を指定します

include ltstdiohgt define UNIX main() ifdef UNIX printf( UNIX yenn) else printf(MS-DOSyenn) endif

include ltstdiohgt define OS UNIX main() if OS == UNIX printf( UNIX yenn) else printf(MS-DOSyenn) endif

32

付 録 1 puts()gets()関数について

行単位に入出力を行う場合には puts() gets() 関数を用います

puts() 標準出力に文字列を出力します

include ltstdiohgt int puts( char s ) puts() は NULL で終る文字列 s を標準出力に出力し最後に改行文字 yenn も出力しま

gets() 標準入力から文字列を入力します

include ltstdiohgt char gets( char s ) 戻り値正常に入力した場合には引数 s の値が返されますエラーやEOFになった場合に

は NULL が返されます gets() は標準入力から復帰文字で終る文字列を入力しs に格納しますこのとき最後の復

帰文字は NULL文字に変更されます

入力行の出力 標準入力から gets() で入力したデータには改行コードは含まれませんまた標準出力へ

puts() で出力を行う場合には必ず改行コードが付加されますgets() を実行したときの戻り値としてファイルの終端を検出した場合には EOF ではなく NULL が返されますので注意して下さい

include ltstdiohgt main() char data[80] while( gets( data ) = NULL )puts( data )

putchar()getchar()関数について putchar() 標準出力に文字を出力します

include ltstdiohgt int putchar(int c ) 戻り値正常に出力できた場合には文字cをエラーの場合にはEOFを返します

33

getchar() 標準入力から文字を入力します

include ltstdiohgt int getchar(void) 戻り値正常に入力した場合には読み込んだ文字を int 型に変換して返しますまたファイ

ルエンドエラーの場合にはEOFを返します

標準入力標準出力

標準入力標準出力はプログラムが開始されるときにはオープンされていますそれぞれのフ

ァイルポインタは stdin stdout になっていますfopen() fclose() をせずとも使用することができます

scanf() 標準出力ストリームからテキストを読み込み解釈します include ltstdiohgt int scanf( const char format [ address ] ) 戻り値正しくスキャンし変換し格納した入力フィールドの数を返しますファイルエンドを読

み込んだ場合は戻り値は EOF となります値を格納したフィールドがなかった場合は戻り値は0となります

一連の入力フィールドをスキャンして1度に1文字ずつストリーム stdin から文字を読み込み

ます次に引き数 format によって指される書式文字列中の書式指定に従って各フィールドを書式化します最後にformat の後に続く各引き数が示しているアドレスに書式化した入力を格納していきます書式文字列中の書式指定の個数はその後に続くアドレスの数と同じでな

ければなりません 書式指定[入力幅][型指定文字] 入力幅 読むべき文字数の最大値 型指定文字 次のとおりです 型指定文字 期待される入力 引き数の型 d 10進整数 int へのポインタ( int arg ) x 16進整数 int へのポインタ( int arg ) f 浮動小数点数 float へのポインタ( float arg ) s 文字列 文字配列へのポインタ( char arg[] ) c 文字 文字へのポインタ( char arg )

printf() フォーマットを指定してテキスト標準出力ストリームに出力します include ltstdiohgt int printf( const char format [ argument ] ) 戻り値出力したバイト数を返しますエラーの場合は EOF を返します

34

format によって指される書式文字列中の書式指定をformat の後に続く各引き数に適用し

書式化されたデータを stdout に出力します書式指定は後に続く引き数と同じ数だけなければなりません

書式指定[印字幅][精度][型指定文字] 印字幅 印字する最小文字数 精度 印字する最大文字数 型指定文字 つぎのとおりです 型指定文字 入力引き数 出力の書式 d 整数 符号付き10進整数 x 整数 符号無し16進整数 f 浮動小数点 符号付きの dddddddd形式の値 c 文字 1個の文字 s 文字列ポインタ ヌル文字に出会うか精度に達するまで 文字をプリントする

fopen()fclose()関数について fopen() ファイルをオープンします

include ltstdiohgt FILE fopen( char filename char mode ) 戻り値正常にファイルのオープンができたらファイルポインタを返しますエラーがあった場

合には NULLを返します 文字列 filename で指定されたファイルをオープンしますオープン後の入出力のモードに

ついては文字列 mode で指定しますmode に指定できる文字は以下のとおりです r 入力モードでオープンします w 出力モードでオープンします a 存在するファイルに追加して出力するモードでオープンします r+ 既に作成してあるファイルを更新(入力出力)するモードでオープンします w+ 新しく作成するファイルを更新モードでオープンします a+ 既に作成してあるファイルの終りから更新用に作成します

以上の文字に b をつけ加えることによりバイナリモードで入出力することができるようになり

ます rb バイナリの入力モードでオープンします wb バイナリの出力モードでオープンします ab 存在するファイルに追加して出力するモード(バイナリ)でオープンします

fclose() 既にオープンしてあるファイルをクローズします include ltstdiohgt fclose( FILE fp ) 既にオープンしているファイルをクローズしますパラメータには fopen() 関数により返された

ファイルポインタを指定します

35

テキストモードとバイナリモード 行の最後はテキストモードの場合改行コードのみとなりバイナリモードの場合には復帰

コードと改行コードの組合わせになります行の最後としてテキストファイルには復帰コード改行

コードが書かれていますがテキストモードでオープンした場合には入力すると改行コードのみに

変換されて入力されますバイナリモードの場合には復帰コード改行コードがそれぞれ入力され

ます

fputs()fgets()関数について fputs() ファイルポインタで指定されるファイルに文字列を出力します

include ltstdiohgt

int fputs( char s FILE fp ) fputs() は NULL で終る文字列 s をファイルポインタに示されるファイルへ出力しますputs()

と違い最後に改行文字 yenn を出力することはありません

fgets() ファイルポインタで指定されるファイルから文字列を入力します include ltstdiohgt char fgets( char s int n FILE fp ) 戻り値正常に入力した場合には引数 s の値が返されますエラーやEOFになった場合に

は NULL が返されます fgets() はファイルポインタで指定されるファイルから ( n - 1 ) 文字または改行文字までの

文字列を入力しs に格納しますgets() と異なり最後に入力された改行文字は NULL 文字に変更されません

標準入力から入力しファイルへ出力する ファイルへ出力あるいは入力を行う場合には改行コードの変換(入力の場合の削除出力の

場合の付加)はされませんしたがって標準入力から入力しファイルへ出力する場合には改行

コードを付加しなければなりません include ltstdiohgt main() char data[80] FILE fp fp = fopen( data w ) while( gets( data ) = NULL ) strcat( data yenn ) 改行コードの付加

fputs( data fp ) fclose( fp )

36

fputc()fgetc()関数について fputc() ファイルポインタで指定されるファイルに1文字出力します

include ltstdiohgt int fputc( int c FILE fp ) 戻り値正常に出力できた場合には文字 c を返しエラーの場合には EOF を返します fputc() は文字 c をファイルポインタで示されるファイルへ出力します

fgetc() ファイルポインタで指定されるファイルから1文字入力します

include ltstdiohgt int fgetc( FILE fp ) 戻り値正常に入力した場合には入力した文字を返しますエラーやEOFになった場合には

EOF が返されます fgetc() はファイルポインタで指定されるファイルから文字を入力します

ファイルの内容の表示 include ltstdiohgt main() FILE fp int ch char fname[30] printf( Key in Fila name gt ) gets( fname ) fp = fopen( fname r ) while( ( ch = fgetc( fp ) ) = EOF )putchar( ch ) fclose( fp )

その他テキスト中で使用された関数について sin() 三角関数の正弦を計算します

include ltmathhgt double sin(double radian) sinはラジアンを単位とする引数 radianの三角関数を計算します

37

strcpy() 文字列を他の文字列へコピーします

include ltstringhgt char strcpy(char string1const char string2) strcpyは引数 string2の指す文字列を null文字まで含めて引数 string1の指す領域にコピ

ーする strcpyは string1を返します

strcat() ある文字列を他の文字列に加えます

include ltstringhgt char strcat( char dest const char src ) 戻り値連結された文字列へのポインタを返します strcat() はsrc のコピーを dest の最後につけ加えます得られる文字列の長さは

strlen(dest)+strlen(src) になります

fabs() 絶対値の計算をします include ltmathhgt double fabs(double z) fabsは倍精度浮動小数の絶対値を計算して返しますつまりzgt=0であれば z をzlt0であ

れば-zを返します exp() 指数関数を計算します

include ltmathhgt double exp(double z) exp は引数zの指数関数つまりezを返すここではeは自然対数の底を表します対数関

数logの逆関数です

38

付 録 2 コンパイルの方法には大きく分けて第4章の実習で学んだようにデータファイルを作成してお

き ccg でコンパイルさせる方法と実行中に対話型でデータを入力していく方法があります ここでは対話型で実行を進めていく方法を紹介します ただしこの方法は計算(cpu)時間が10秒以内のものに限ります10秒を超える計算(cpu)時

間を要する場合はccg でコンパイルをするようにしてください 第4章実習の(2)(p16)までは同様です

コンパイル

コンピュータに処理を依頼します 60us1234boseicc cc rensyuc

所有するファイルの一覧を見てみます

60us1234boseicc ls -l larr 持っているファイルの一覧を見るコマンドです

-rw-r--r-- 1 60us1234 other 128 4月26日 15時14分 rensyuc -rwxr-xr-x 1 60us1234 other 361 4月26日 15時16分 aout

aout という実行形式のファイルが作成されています

実行

60us1234boseicc aout12 35[リターン] データを入力

1 200000 3500000 4200000 実行結果の出力

60us1234boseicc

注意

aout ファイルは印刷することができません実行結果を印刷する場合にはファイルに落とし てから出力するようにしましょう

60us1234boseicc aout gt kekka12 35[リターン] データを入力

60us1234boseicc more kekka 計算結果の確認 60us1234boseicc lpr kekka 計算結果の印刷

39

Page 19: n 第1章 章立ての部分は、書式(PC入門大見出し)を …第2章 数の表現 2-1 2進数 電子計算機の動作原理は0と1で表される2進数です。また、人間が日常生活で扱っている数

130 60us1234boseicc myjob ================================================= NQS (R0220) BATCH REQUEST HOST bosei ================================================= REQUEST ID NAME OWNER QUEUE PRI NICE STT PGRP R --------------- -------- -------- -------- ---- --- --- ------ - 99321bosei STDIN 60us1234 A 31 0 RUN 14161 - ---------------------------------------------------------------- ================================================== NQS (R0220) DEVICE REQUEST HOST bosei ジョブは実行中です

================================================== REQUEST ID NAME OWNER QUEUE PRI SIZE STT -------------------------------------------------------------

所有するファイルの一覧を見てみます

60us1234boseicc ls -l larr 持っているファイルの一覧を見るコマンドです

-rw-r--r-- 1 60us1234 other 4 4月26日 15時14分 rensyud -rw-r--r-- 1 60us1234 other 128 4月26日 15時10分 rensyuc -rwxr-xr-x 1 60us1234 other 361 4月26日 15時16分 rensyul

(5)計算結果の確認

計算結果を画面に表示して確認します 60us1234boseicc more rensyul

(6)印刷

計算結果の印刷を行ないます5号館2階のカフェテリア室にある bosei のプリンタに印刷 されます

60us1234boseicc lpr rensyul

(7)ログアウト セッションを終了します 60us1234boseicc logout

(8)実行の流れ

エラー

プログラムの作成 ログイン コンパイル実行

確 認 印 刷 ログアウト

17

第5章 配列 多数の変数をまとめて宣言する方法として配列があります配列の一つ一つは配列要素と呼

ばれ変数と同じ性格を持っています配列の宣言は型宣言と同時に次のように行います int a[5] 配列 a

a[0]

a[1]

a[2]

a[3]

a[4]

二次元配列(一次元配列を複数集めたもの)を宣言する場合には次のようになります int b[3][4] 配列 b

b[0][0] b[0][1] b[0][2] b[0][3]

b[1][0] b[1][1] b[1][2] b[1][3]

b[2][0] b[2][1] b[2][2] b[2][3]

配列要素に数値を代入する場合は次のようになります b[1][2]=10

5-1 二次元配列要素の初期化 変数の型宣言と同じように配列を宣言するときに初期値も同時に設定することができます

複数のデータがある場合には{}記号でくくって指定します int b[3][4] = 2 4 6 8 1 3 5 7 1 2 3 4

文字型配列の場合には以下のようになりますyen0 は文字列の終わりを表わします char univ[3][7] = T O K A I yen0 S I M I Z U yen0 Y O Y O G I yen0

また文字列定数として初期化することもできますこの場合コンパイル時に自動的に yen0 が付加されます

char univ[3][7] = TOKAI SIMIZU YOYOGI

18

[プログラム例] 二次元配列のタテヨコを加算するプログラム

include ltstdiohgt main() int mat[4][3]=123456789101112 int ijytotalttotal[3]total=0 for(j=0jlt3j++)ttotal[j]=0 for (i=0ilt4i++) ytotal=0 for(j=0jlt3j++) ytotal += mat[i][j] ttotal[j] += mat[i][j] total += mat[i][j] printf(3dmat[i][j]) printf( 3dyennytotal) printf(yenn) for(j=0jlt3j++)printf(3dttotal[j]) printf( 3dyenntotal)

[実行結果]

1 2 3 6 4 5 6 15 7 8 9 24 10 11 12 33 22 26 30 78

演習7

a)以下の配列はどのように初期化されるか答えなさい char errmsg[2][15] = Divide Error Overflow Error

b)九九の計算を2次元配列を使って求めなさい

19

第6章 ポインタ型変数 C言語では値を記憶するための変数だけではなく変数または定数の番地を記憶するため

のポインタ型変数を宣言することができますポインタとはデータ項目の一種で「記憶装置(メモ

リ)上の格納番地(アドレス)を指すデータ項目」です アドレス コンピュータの中ではデータ項目の格納番地のことをアドレス(住所)と呼びます 例えば記憶装置という名前のとてつもなく大きなマンションがあるとしますその中から Aさんを捜すときは部屋番号を参照しますマンションでは部屋番号で住居人を参照し ているのと同じようにコンピュータでは記憶装置上に確保された変数は格納番地 (アドレス)で管理されています

マンション 部屋番号 記憶装置 格納番地

Aさん Int a Bさん Cさん AAAさん BBBさん CCCさん

1号室

2号室

3号室

100号室

200号室

300号室

100番地

200番地

300番地

1000番地

2000番地

3000番地

Int b Int c float aaafloat bbbfloat ccc

ポインタ ポインタとは「指し示すもの」の意ですがC言語では記憶装置上のアドレスを指し示す もののことです上のマンションの例では部屋番号を格納するデータ項目ということに なりますAAAさんは100号室に住んでいます100という値をポインタのデータ項目に 記憶するとそのデータ項目は間接的にAAAさんを指すことになります

6-1 ポインタ型変数の宣言および参照 通常の変数と区別するために型宣言時に変数名の前に記号を付けて宣言します int a 整数型ポインタ変数 int b 整数型変数

変数 a は整数型の値を記憶するのではなく整数型の値を持つ変数などの番地を記憶する変数ですまた変数 b は通常の整数型の値を記憶するための変数です

20

include ltstdiohgt main() int a b c a はポインタ型の変数b c は整数型の変数 b = 12 変数 b に値 12 を代入します a = ampb 変数 a には変数 b の番地が代入されます c = a + 10 変数 a の指す変数(b)の内容と10の加算です つまり12 + 10 を変数 c に代入します

変数の型宣言において変数名に記号を付けることによりその変数はポインタ型の変数と

なりますポインタ型の変数は変数名のみを指定した場合には単にその変数の値(通常はメモリ

の番地)を表します変数名に記号を付けて使用した場合にはその変数が指し示している変

数の内容を表します c = a ポインタ型変数 a が指している値を変数 c に代入

ポインタ型の変数に番地を記憶させるためにはプログラム例のように変数名の前に記号を

指定します変数名 によって変数の番地(アドレス)を表します a = ampb 変数 b の番地をポインタ型変数 a に代入します

ポインタ型変数の型はポインタ型変数が指し示す先の変数の型を表しています int a 変数 a 整数型の値 float x 変数 x 実数型の値 char c 変数 c 文字型の値

6-2 ポインタ型変数の初期化 ポインタ型変数も型宣言のときに変数を初期化することができます特に文字型のポインタ変

数の場合によく使います char str = TOKAI University

ポインタ型変数 str は文字列定数 TOKAI University の最初の文字が格納されている番地を初期値として持つことになります

変数 str TOKAI University 文字列定数

[プログラム例]

(1)文字型配列 putchar() 関数を使って一次元の文字型配列を出力します include ltstdiohgt main() char str[6] = TOKAI int i for( i = 0 str[i] = yen0 i++ ) putchar( str[i] )

21

ポインタを使用した場合には以下のようになります include ltstdiohgt main() char str[6] = TOKAI char chp for( chp = str chp = yen0 chp++ ) putchar( chp )

chp str T [0] O K A I yen0 [5]

参照する変数 配列の表現 ポインタの表現 実際のアドレス 1番目の数 str[0] chp CHP 2番目の数 str[1] (chp+1) CHP+1 n番目の数 str[n-1] (chp+n-1) CHP+n-1 6番目の数 str[5] (chp+5) CHP+5

注意実際のアドレス CHPは実行時に決定されます

(2)二次元文字型配列 二次元の文字型配列に定数を設定しそれを出力するプログラムです文字型配列を使用す

ると次のとおりになります include ltstdiohgt main() char str[5][40] = TOKAI shounan campus NEC DEC int i for( i = 0 i lt 5 i++ ) printf( yenns str[i] )

40 バイト str TOKAI shounan campus NEC DEC

22

ポインタ型配列を使用すると次のとおりになります include ltstdiohgt main() char str[6] = TOKAI shounan campus NEC DEC NULL char chp for( chp = str chp = NULL chp++ ) printf( yenns chp ) str

chp 番地 TOKAI 番地 shounan 番地 campus 番地 NEC 番地 DEC

NULL

演習8 キーボードまたはデータファイルから読み込んだ文字列中にrsquoArsquo があったら rsquoarsquo に変換 するプログラムを配列とポインタを使って書きなさい

23

第7章 構造体共用体 7-1 構造体

プログラムの規模が大きくなるにつれて多数の intや floatcharなどのデータ型を扱うようになり複雑になってきますそこで多数のデータを1つにまとめて簡単に扱える機能が構造体です 構造体について住所録のデータを例にあげて考えてみます

住所録の個人データとして氏名住所電話番号年齢の項目を一つのデータとします これをC言語で変数の定義をすると次のようになります 氏名東海太郎 char name[30] 住所平塚市北金目1117 char address[30] 電話番号0463-58-1211 char tel[20] 年齢30 int age 個人の住所録データ C言語での表現 このような住所録の個人データを1つにまとめて新しいデータとして定義する機能を構造体と言

います struct 構造体タグ名 構造体メンバーの並び

「struct」は構造体を表すキーワードです 「構造体タグ名」は構造体の型枠を宣言しますここは自由に名前を定義することができ ます 「構造体メンバーの並び」は構造体の要素です複数指定できます

個人の住所録のデータを構造体で宣言すると次のようになります

struct jusho char name[30] char address[30] 構造体のメンバーの並び char tel[20] (複数可)

int age

上記の宣言では構造体の形式を宣言しているだけでメモリ中で実際の領域を確保している

わけではありません実際に領域を確保するためには次のように定義します

struct 構造体タグ名 構造体名

したがって構造体名を jdata とすると次のように指定します

struct jusho jdata

構造体 jdataは次のように構造体タグ jushoの形式で領域を確保します

24

Jdata name[30]

address[30] tel[20] age

(1)構造体の参照

プログラム中で構造体中のメンバーを参照する場合には次のように指定します 構造体名メンバー名

したがって「名前」を参照したいときには次のように指定します

jdataname

[プログラム例]

名前住所電話番号年齢を定義しそれを印字します include ltstdiohgt include ltstringhgt main() struct jusho char name[30] char address[30] char tel[20] int age struct jusho jdata strcpy( jdataname 東海 太郎) strcpy( jdataaddress 平塚市北金目1117)

strcpy( jdatatel 0463-58-1211) jdataage = 30 printf(yenn氏名 = syenn jdataname) printf(yenn住所 = syenn jdataaddress) printf(yenn電話番号= syenn jdatatel) printf(yenn年齢 = dyenn jdataage)

また構造体の形式の定義と領域の確保は次のように同時におこなうことができます

struct 構造体タグ名 構造体メンバーの並び 構造体名

struct jusho struct jusho char name[30] char name[30] char address[30] char address[30] char tel[30] = char tel[30] int age 同じ int age

jdata struct jusho jdata

型宣言と同時にメモリ上に領域を確保する方法 後からメモリ上に領域を確保する方法

25

(2) 構造体配列 住所録データの場合その中に入るデータは1件ではありませんやはり100件200件のデ

ータが必要になる場合がありますこのように個人単位のデータを多数扱う場合には構造体を配

列として宣言することができます 次の例は個人のデータを100個用意するために構造体を配列として宣言しています struct jusho jdata[100] jdata[0] name[30] address[30] tel[20] age

jdata[99 ] name[30] address[30] tel[20] age

(3)構造体配列の参照

プログラム中で構造体配列中のメンバーを参照する場合には次のように指定します 構造体名[要素番号]メンバー名

したがって10件目の人の「名前」を参照したいときには次のように指定します

jdata[10]name

[プログラム例]

名前住所電話番号年齢を定義しそれを印字します include ltstdiohgt include ltstringhgt main() struct jusho char name[30] char address[30] char tel[20] int age jdata[100] strcpy( jdata[10]name 東海 太郎) strcpy( jdata[10]address 平塚市北金目1117)

strcpy( jdata[10]tel 0463-58-1211) jdata[10]age = 30 printf(yenn氏名 = syenn jdata[10]name) printf(yenn住所 = syenn jdata[10]address) printf(yenn電話番号= syenn jdata[10]tel) printf(yenn年齢 = dyenn jdata[10]age)

26

(4) 構造体のポインタ 変数と同じように構造体へのポインタも定義することができます

変数へのポインタ例 構造体へのポインタ例 またポインタを使用して構造体メンバーを参照するには次のように -> 記号を使って指

定します ポインタ変数名 -> メンバー名

[プログラム例]

名前住所電話番号年齢を定義しそれを印字します include ltstdiohgt include ltstringhgt main() struct jusho char name[30] char address[30] char tel[20] int age jdatakp kp = ampjdata strcpy( kp-gtname 東海 太郎)

strcpy( kp-gtaddress 平塚市北金目1117)

strcpy( kp-gttel 0463-58-1211) kp-gtage = 30 printf(yenn氏名 = syenn kp-gtname) printf(yenn住所 = syenn kp-gtaddress) printf(yenn電話番号= syenn kp-gttel) printf(yenn年齢 = dyenn kp-gtage)

kp jdata

name[30] ポインタ型の変数 address[30]

tel[20]

構造体へのポインタを記憶 age

することができます

int a int b b = ampa

struct name jname struct name np np = ampname

27

7-2 共用体 共用体は構造体と同じようにして宣言しますが共用体は複数のデータ型を同一のアドレスに

割り当てる方法です union 共用体タグ名 共用体メンバーの並び

「union」は共用体を表すキーワードです 「共用体タグ名」は共用体の型枠の名前を宣言しますここは自由に名前を定義することがで

きます 「共用体メンバーの並び」は共用体の要素です複数指定できます

共用体の宣言の例を次に示します

union c_tag int a char b

共用体 cは次のように共用体タグ c_tagの形式で領域を確保します共用体はメモリ上に領域を確保するときは ab ともに同じ領域に割り付けられます これはab という2つのデータが同時に存在するわけではなく cを異なるデータ abで共有す

ることを表しています c a b

上記の宣言だけでは共用体の形式を宣言しているだけでメモリ中で実際の領域を確保して

いるわけではありません実際に領域を確保するためには次のように定義します union 構造体タグ名 構造体名

したがって共用体名を c とすると次のように指定します

union c_tag c

(1)共用体の参照

プログラム中で共用体中のメンバーを参照する場合には次のように指定します 共用体名メンバー名

したがって「a」または「b」を参照したいときには次のように指定します

ca (int 型) cb (char 型)

メンバー参照方法によって int型として使ったりchar型として利用することができます

28

[プログラム例]

includeltstdiohgt main() union data char a short b int c chk chkc = 0x12345678 printf( char a xyennchka) printf( short b xyennchkb) printf( int c xyennchkc)

chkb(int 型) chkb(short 型) chka(char 型) 12 12 12 34 34 56 78

29

第8章 アルゴリズム コンピュータに何か仕事をさせようとするときは仕事を具体的に実行するための処理や動作

の手順が必要ですこの「手順」がアルゴリズムです アルゴリズムを考えるときは解くべき問題をはっきりと定義することが必要です

8-1 ソート ソートとは与えられたデータを小さい順または大きい順に並べ換えることですソート方法は

いくつかありますが基本的な方法でソートするアルゴリズムを紹介します

includeltstdiohgt int data[10] main()

int data_in() sort() data_in() sort() int data_in() データ入力関数

int a printf(数値入力yenn)

for(a=0alt=9a++) printf( [d]a+1) scanf(dampdata[a]) int sort() ソート処理を行う関数

int cont1cont2tmp1tmp2mim for(cont1=0 cont1lt=9 cont1++) mim=data[cont1] tmp1=cont1 for(cont2=cont1+1 cont2lt=9 cont2++) if(data[cont2] lt mim) mim=data[cont2] tmp1=cont2 tmp2 = data[cont1] data[cont1] = data[tmp1] data[tmp1] = tmp2 printf(結果 yenn)

for (cont1 = 0 cont1 lt= 9 cont1++) printf(d yenn data[cont1])

30

第9章 プリプロセッサ C言語にはプログラムの中でコンパイルについての指示を行う「プリプロセッサ」という機能が

ありますまたプリプロセッサとはコンパイルする前に実行されるためその意味のとおり「前処理」 と呼ばれていますここでは代表的なものをいくつか説明します

9-1 ファイルの挿入 ソースプログラム中に指定されたファイルを挿入します

include ltstdiohgt helliphellip 標準ディレクトリを探します include progh helliphellip 現在のディレクトリを探しなければ標準ディレクトリを探します

includeltstdiohgt によって組み込まれた define EOF (-1) define EOF (-1) define define helliphelliphelliphellip 組み込み helliphelliphelliphellip

main() stdiohファイル

int helliphelliphelliphellip helliphelliphelliphellip

ソースファイル

9-2 文字の置換 プログラム中に使われている文字列を別の文字列に置き換えます

include ltstdiohgt define TRUE 1 define EOF (-1) main() define helliphellip helliphellip

while(TRUE) define TRUE 1 置き換え main() helliphellip helliphellip while(1)

break helliphelliphellip

31

9-3 条件によるコンパイル 識別子が定義されているか否かを判断しコンパイルする範囲を指定します

include ltstdiohgt define UNIX main() ifdef UNIX printf( UNIX yenn) else printf(MS-DOSyenn) endif

include ltstdiohgt define OS UNIX main() if OS == UNIX printf( UNIX yenn) else printf(MS-DOSyenn) endif

32

付 録 1 puts()gets()関数について

行単位に入出力を行う場合には puts() gets() 関数を用います

puts() 標準出力に文字列を出力します

include ltstdiohgt int puts( char s ) puts() は NULL で終る文字列 s を標準出力に出力し最後に改行文字 yenn も出力しま

gets() 標準入力から文字列を入力します

include ltstdiohgt char gets( char s ) 戻り値正常に入力した場合には引数 s の値が返されますエラーやEOFになった場合に

は NULL が返されます gets() は標準入力から復帰文字で終る文字列を入力しs に格納しますこのとき最後の復

帰文字は NULL文字に変更されます

入力行の出力 標準入力から gets() で入力したデータには改行コードは含まれませんまた標準出力へ

puts() で出力を行う場合には必ず改行コードが付加されますgets() を実行したときの戻り値としてファイルの終端を検出した場合には EOF ではなく NULL が返されますので注意して下さい

include ltstdiohgt main() char data[80] while( gets( data ) = NULL )puts( data )

putchar()getchar()関数について putchar() 標準出力に文字を出力します

include ltstdiohgt int putchar(int c ) 戻り値正常に出力できた場合には文字cをエラーの場合にはEOFを返します

33

getchar() 標準入力から文字を入力します

include ltstdiohgt int getchar(void) 戻り値正常に入力した場合には読み込んだ文字を int 型に変換して返しますまたファイ

ルエンドエラーの場合にはEOFを返します

標準入力標準出力

標準入力標準出力はプログラムが開始されるときにはオープンされていますそれぞれのフ

ァイルポインタは stdin stdout になっていますfopen() fclose() をせずとも使用することができます

scanf() 標準出力ストリームからテキストを読み込み解釈します include ltstdiohgt int scanf( const char format [ address ] ) 戻り値正しくスキャンし変換し格納した入力フィールドの数を返しますファイルエンドを読

み込んだ場合は戻り値は EOF となります値を格納したフィールドがなかった場合は戻り値は0となります

一連の入力フィールドをスキャンして1度に1文字ずつストリーム stdin から文字を読み込み

ます次に引き数 format によって指される書式文字列中の書式指定に従って各フィールドを書式化します最後にformat の後に続く各引き数が示しているアドレスに書式化した入力を格納していきます書式文字列中の書式指定の個数はその後に続くアドレスの数と同じでな

ければなりません 書式指定[入力幅][型指定文字] 入力幅 読むべき文字数の最大値 型指定文字 次のとおりです 型指定文字 期待される入力 引き数の型 d 10進整数 int へのポインタ( int arg ) x 16進整数 int へのポインタ( int arg ) f 浮動小数点数 float へのポインタ( float arg ) s 文字列 文字配列へのポインタ( char arg[] ) c 文字 文字へのポインタ( char arg )

printf() フォーマットを指定してテキスト標準出力ストリームに出力します include ltstdiohgt int printf( const char format [ argument ] ) 戻り値出力したバイト数を返しますエラーの場合は EOF を返します

34

format によって指される書式文字列中の書式指定をformat の後に続く各引き数に適用し

書式化されたデータを stdout に出力します書式指定は後に続く引き数と同じ数だけなければなりません

書式指定[印字幅][精度][型指定文字] 印字幅 印字する最小文字数 精度 印字する最大文字数 型指定文字 つぎのとおりです 型指定文字 入力引き数 出力の書式 d 整数 符号付き10進整数 x 整数 符号無し16進整数 f 浮動小数点 符号付きの dddddddd形式の値 c 文字 1個の文字 s 文字列ポインタ ヌル文字に出会うか精度に達するまで 文字をプリントする

fopen()fclose()関数について fopen() ファイルをオープンします

include ltstdiohgt FILE fopen( char filename char mode ) 戻り値正常にファイルのオープンができたらファイルポインタを返しますエラーがあった場

合には NULLを返します 文字列 filename で指定されたファイルをオープンしますオープン後の入出力のモードに

ついては文字列 mode で指定しますmode に指定できる文字は以下のとおりです r 入力モードでオープンします w 出力モードでオープンします a 存在するファイルに追加して出力するモードでオープンします r+ 既に作成してあるファイルを更新(入力出力)するモードでオープンします w+ 新しく作成するファイルを更新モードでオープンします a+ 既に作成してあるファイルの終りから更新用に作成します

以上の文字に b をつけ加えることによりバイナリモードで入出力することができるようになり

ます rb バイナリの入力モードでオープンします wb バイナリの出力モードでオープンします ab 存在するファイルに追加して出力するモード(バイナリ)でオープンします

fclose() 既にオープンしてあるファイルをクローズします include ltstdiohgt fclose( FILE fp ) 既にオープンしているファイルをクローズしますパラメータには fopen() 関数により返された

ファイルポインタを指定します

35

テキストモードとバイナリモード 行の最後はテキストモードの場合改行コードのみとなりバイナリモードの場合には復帰

コードと改行コードの組合わせになります行の最後としてテキストファイルには復帰コード改行

コードが書かれていますがテキストモードでオープンした場合には入力すると改行コードのみに

変換されて入力されますバイナリモードの場合には復帰コード改行コードがそれぞれ入力され

ます

fputs()fgets()関数について fputs() ファイルポインタで指定されるファイルに文字列を出力します

include ltstdiohgt

int fputs( char s FILE fp ) fputs() は NULL で終る文字列 s をファイルポインタに示されるファイルへ出力しますputs()

と違い最後に改行文字 yenn を出力することはありません

fgets() ファイルポインタで指定されるファイルから文字列を入力します include ltstdiohgt char fgets( char s int n FILE fp ) 戻り値正常に入力した場合には引数 s の値が返されますエラーやEOFになった場合に

は NULL が返されます fgets() はファイルポインタで指定されるファイルから ( n - 1 ) 文字または改行文字までの

文字列を入力しs に格納しますgets() と異なり最後に入力された改行文字は NULL 文字に変更されません

標準入力から入力しファイルへ出力する ファイルへ出力あるいは入力を行う場合には改行コードの変換(入力の場合の削除出力の

場合の付加)はされませんしたがって標準入力から入力しファイルへ出力する場合には改行

コードを付加しなければなりません include ltstdiohgt main() char data[80] FILE fp fp = fopen( data w ) while( gets( data ) = NULL ) strcat( data yenn ) 改行コードの付加

fputs( data fp ) fclose( fp )

36

fputc()fgetc()関数について fputc() ファイルポインタで指定されるファイルに1文字出力します

include ltstdiohgt int fputc( int c FILE fp ) 戻り値正常に出力できた場合には文字 c を返しエラーの場合には EOF を返します fputc() は文字 c をファイルポインタで示されるファイルへ出力します

fgetc() ファイルポインタで指定されるファイルから1文字入力します

include ltstdiohgt int fgetc( FILE fp ) 戻り値正常に入力した場合には入力した文字を返しますエラーやEOFになった場合には

EOF が返されます fgetc() はファイルポインタで指定されるファイルから文字を入力します

ファイルの内容の表示 include ltstdiohgt main() FILE fp int ch char fname[30] printf( Key in Fila name gt ) gets( fname ) fp = fopen( fname r ) while( ( ch = fgetc( fp ) ) = EOF )putchar( ch ) fclose( fp )

その他テキスト中で使用された関数について sin() 三角関数の正弦を計算します

include ltmathhgt double sin(double radian) sinはラジアンを単位とする引数 radianの三角関数を計算します

37

strcpy() 文字列を他の文字列へコピーします

include ltstringhgt char strcpy(char string1const char string2) strcpyは引数 string2の指す文字列を null文字まで含めて引数 string1の指す領域にコピ

ーする strcpyは string1を返します

strcat() ある文字列を他の文字列に加えます

include ltstringhgt char strcat( char dest const char src ) 戻り値連結された文字列へのポインタを返します strcat() はsrc のコピーを dest の最後につけ加えます得られる文字列の長さは

strlen(dest)+strlen(src) になります

fabs() 絶対値の計算をします include ltmathhgt double fabs(double z) fabsは倍精度浮動小数の絶対値を計算して返しますつまりzgt=0であれば z をzlt0であ

れば-zを返します exp() 指数関数を計算します

include ltmathhgt double exp(double z) exp は引数zの指数関数つまりezを返すここではeは自然対数の底を表します対数関

数logの逆関数です

38

付 録 2 コンパイルの方法には大きく分けて第4章の実習で学んだようにデータファイルを作成してお

き ccg でコンパイルさせる方法と実行中に対話型でデータを入力していく方法があります ここでは対話型で実行を進めていく方法を紹介します ただしこの方法は計算(cpu)時間が10秒以内のものに限ります10秒を超える計算(cpu)時

間を要する場合はccg でコンパイルをするようにしてください 第4章実習の(2)(p16)までは同様です

コンパイル

コンピュータに処理を依頼します 60us1234boseicc cc rensyuc

所有するファイルの一覧を見てみます

60us1234boseicc ls -l larr 持っているファイルの一覧を見るコマンドです

-rw-r--r-- 1 60us1234 other 128 4月26日 15時14分 rensyuc -rwxr-xr-x 1 60us1234 other 361 4月26日 15時16分 aout

aout という実行形式のファイルが作成されています

実行

60us1234boseicc aout12 35[リターン] データを入力

1 200000 3500000 4200000 実行結果の出力

60us1234boseicc

注意

aout ファイルは印刷することができません実行結果を印刷する場合にはファイルに落とし てから出力するようにしましょう

60us1234boseicc aout gt kekka12 35[リターン] データを入力

60us1234boseicc more kekka 計算結果の確認 60us1234boseicc lpr kekka 計算結果の印刷

39

Page 20: n 第1章 章立ての部分は、書式(PC入門大見出し)を …第2章 数の表現 2-1 2進数 電子計算機の動作原理は0と1で表される2進数です。また、人間が日常生活で扱っている数

第5章 配列 多数の変数をまとめて宣言する方法として配列があります配列の一つ一つは配列要素と呼

ばれ変数と同じ性格を持っています配列の宣言は型宣言と同時に次のように行います int a[5] 配列 a

a[0]

a[1]

a[2]

a[3]

a[4]

二次元配列(一次元配列を複数集めたもの)を宣言する場合には次のようになります int b[3][4] 配列 b

b[0][0] b[0][1] b[0][2] b[0][3]

b[1][0] b[1][1] b[1][2] b[1][3]

b[2][0] b[2][1] b[2][2] b[2][3]

配列要素に数値を代入する場合は次のようになります b[1][2]=10

5-1 二次元配列要素の初期化 変数の型宣言と同じように配列を宣言するときに初期値も同時に設定することができます

複数のデータがある場合には{}記号でくくって指定します int b[3][4] = 2 4 6 8 1 3 5 7 1 2 3 4

文字型配列の場合には以下のようになりますyen0 は文字列の終わりを表わします char univ[3][7] = T O K A I yen0 S I M I Z U yen0 Y O Y O G I yen0

また文字列定数として初期化することもできますこの場合コンパイル時に自動的に yen0 が付加されます

char univ[3][7] = TOKAI SIMIZU YOYOGI

18

[プログラム例] 二次元配列のタテヨコを加算するプログラム

include ltstdiohgt main() int mat[4][3]=123456789101112 int ijytotalttotal[3]total=0 for(j=0jlt3j++)ttotal[j]=0 for (i=0ilt4i++) ytotal=0 for(j=0jlt3j++) ytotal += mat[i][j] ttotal[j] += mat[i][j] total += mat[i][j] printf(3dmat[i][j]) printf( 3dyennytotal) printf(yenn) for(j=0jlt3j++)printf(3dttotal[j]) printf( 3dyenntotal)

[実行結果]

1 2 3 6 4 5 6 15 7 8 9 24 10 11 12 33 22 26 30 78

演習7

a)以下の配列はどのように初期化されるか答えなさい char errmsg[2][15] = Divide Error Overflow Error

b)九九の計算を2次元配列を使って求めなさい

19

第6章 ポインタ型変数 C言語では値を記憶するための変数だけではなく変数または定数の番地を記憶するため

のポインタ型変数を宣言することができますポインタとはデータ項目の一種で「記憶装置(メモ

リ)上の格納番地(アドレス)を指すデータ項目」です アドレス コンピュータの中ではデータ項目の格納番地のことをアドレス(住所)と呼びます 例えば記憶装置という名前のとてつもなく大きなマンションがあるとしますその中から Aさんを捜すときは部屋番号を参照しますマンションでは部屋番号で住居人を参照し ているのと同じようにコンピュータでは記憶装置上に確保された変数は格納番地 (アドレス)で管理されています

マンション 部屋番号 記憶装置 格納番地

Aさん Int a Bさん Cさん AAAさん BBBさん CCCさん

1号室

2号室

3号室

100号室

200号室

300号室

100番地

200番地

300番地

1000番地

2000番地

3000番地

Int b Int c float aaafloat bbbfloat ccc

ポインタ ポインタとは「指し示すもの」の意ですがC言語では記憶装置上のアドレスを指し示す もののことです上のマンションの例では部屋番号を格納するデータ項目ということに なりますAAAさんは100号室に住んでいます100という値をポインタのデータ項目に 記憶するとそのデータ項目は間接的にAAAさんを指すことになります

6-1 ポインタ型変数の宣言および参照 通常の変数と区別するために型宣言時に変数名の前に記号を付けて宣言します int a 整数型ポインタ変数 int b 整数型変数

変数 a は整数型の値を記憶するのではなく整数型の値を持つ変数などの番地を記憶する変数ですまた変数 b は通常の整数型の値を記憶するための変数です

20

include ltstdiohgt main() int a b c a はポインタ型の変数b c は整数型の変数 b = 12 変数 b に値 12 を代入します a = ampb 変数 a には変数 b の番地が代入されます c = a + 10 変数 a の指す変数(b)の内容と10の加算です つまり12 + 10 を変数 c に代入します

変数の型宣言において変数名に記号を付けることによりその変数はポインタ型の変数と

なりますポインタ型の変数は変数名のみを指定した場合には単にその変数の値(通常はメモリ

の番地)を表します変数名に記号を付けて使用した場合にはその変数が指し示している変

数の内容を表します c = a ポインタ型変数 a が指している値を変数 c に代入

ポインタ型の変数に番地を記憶させるためにはプログラム例のように変数名の前に記号を

指定します変数名 によって変数の番地(アドレス)を表します a = ampb 変数 b の番地をポインタ型変数 a に代入します

ポインタ型変数の型はポインタ型変数が指し示す先の変数の型を表しています int a 変数 a 整数型の値 float x 変数 x 実数型の値 char c 変数 c 文字型の値

6-2 ポインタ型変数の初期化 ポインタ型変数も型宣言のときに変数を初期化することができます特に文字型のポインタ変

数の場合によく使います char str = TOKAI University

ポインタ型変数 str は文字列定数 TOKAI University の最初の文字が格納されている番地を初期値として持つことになります

変数 str TOKAI University 文字列定数

[プログラム例]

(1)文字型配列 putchar() 関数を使って一次元の文字型配列を出力します include ltstdiohgt main() char str[6] = TOKAI int i for( i = 0 str[i] = yen0 i++ ) putchar( str[i] )

21

ポインタを使用した場合には以下のようになります include ltstdiohgt main() char str[6] = TOKAI char chp for( chp = str chp = yen0 chp++ ) putchar( chp )

chp str T [0] O K A I yen0 [5]

参照する変数 配列の表現 ポインタの表現 実際のアドレス 1番目の数 str[0] chp CHP 2番目の数 str[1] (chp+1) CHP+1 n番目の数 str[n-1] (chp+n-1) CHP+n-1 6番目の数 str[5] (chp+5) CHP+5

注意実際のアドレス CHPは実行時に決定されます

(2)二次元文字型配列 二次元の文字型配列に定数を設定しそれを出力するプログラムです文字型配列を使用す

ると次のとおりになります include ltstdiohgt main() char str[5][40] = TOKAI shounan campus NEC DEC int i for( i = 0 i lt 5 i++ ) printf( yenns str[i] )

40 バイト str TOKAI shounan campus NEC DEC

22

ポインタ型配列を使用すると次のとおりになります include ltstdiohgt main() char str[6] = TOKAI shounan campus NEC DEC NULL char chp for( chp = str chp = NULL chp++ ) printf( yenns chp ) str

chp 番地 TOKAI 番地 shounan 番地 campus 番地 NEC 番地 DEC

NULL

演習8 キーボードまたはデータファイルから読み込んだ文字列中にrsquoArsquo があったら rsquoarsquo に変換 するプログラムを配列とポインタを使って書きなさい

23

第7章 構造体共用体 7-1 構造体

プログラムの規模が大きくなるにつれて多数の intや floatcharなどのデータ型を扱うようになり複雑になってきますそこで多数のデータを1つにまとめて簡単に扱える機能が構造体です 構造体について住所録のデータを例にあげて考えてみます

住所録の個人データとして氏名住所電話番号年齢の項目を一つのデータとします これをC言語で変数の定義をすると次のようになります 氏名東海太郎 char name[30] 住所平塚市北金目1117 char address[30] 電話番号0463-58-1211 char tel[20] 年齢30 int age 個人の住所録データ C言語での表現 このような住所録の個人データを1つにまとめて新しいデータとして定義する機能を構造体と言

います struct 構造体タグ名 構造体メンバーの並び

「struct」は構造体を表すキーワードです 「構造体タグ名」は構造体の型枠を宣言しますここは自由に名前を定義することができ ます 「構造体メンバーの並び」は構造体の要素です複数指定できます

個人の住所録のデータを構造体で宣言すると次のようになります

struct jusho char name[30] char address[30] 構造体のメンバーの並び char tel[20] (複数可)

int age

上記の宣言では構造体の形式を宣言しているだけでメモリ中で実際の領域を確保している

わけではありません実際に領域を確保するためには次のように定義します

struct 構造体タグ名 構造体名

したがって構造体名を jdata とすると次のように指定します

struct jusho jdata

構造体 jdataは次のように構造体タグ jushoの形式で領域を確保します

24

Jdata name[30]

address[30] tel[20] age

(1)構造体の参照

プログラム中で構造体中のメンバーを参照する場合には次のように指定します 構造体名メンバー名

したがって「名前」を参照したいときには次のように指定します

jdataname

[プログラム例]

名前住所電話番号年齢を定義しそれを印字します include ltstdiohgt include ltstringhgt main() struct jusho char name[30] char address[30] char tel[20] int age struct jusho jdata strcpy( jdataname 東海 太郎) strcpy( jdataaddress 平塚市北金目1117)

strcpy( jdatatel 0463-58-1211) jdataage = 30 printf(yenn氏名 = syenn jdataname) printf(yenn住所 = syenn jdataaddress) printf(yenn電話番号= syenn jdatatel) printf(yenn年齢 = dyenn jdataage)

また構造体の形式の定義と領域の確保は次のように同時におこなうことができます

struct 構造体タグ名 構造体メンバーの並び 構造体名

struct jusho struct jusho char name[30] char name[30] char address[30] char address[30] char tel[30] = char tel[30] int age 同じ int age

jdata struct jusho jdata

型宣言と同時にメモリ上に領域を確保する方法 後からメモリ上に領域を確保する方法

25

(2) 構造体配列 住所録データの場合その中に入るデータは1件ではありませんやはり100件200件のデ

ータが必要になる場合がありますこのように個人単位のデータを多数扱う場合には構造体を配

列として宣言することができます 次の例は個人のデータを100個用意するために構造体を配列として宣言しています struct jusho jdata[100] jdata[0] name[30] address[30] tel[20] age

jdata[99 ] name[30] address[30] tel[20] age

(3)構造体配列の参照

プログラム中で構造体配列中のメンバーを参照する場合には次のように指定します 構造体名[要素番号]メンバー名

したがって10件目の人の「名前」を参照したいときには次のように指定します

jdata[10]name

[プログラム例]

名前住所電話番号年齢を定義しそれを印字します include ltstdiohgt include ltstringhgt main() struct jusho char name[30] char address[30] char tel[20] int age jdata[100] strcpy( jdata[10]name 東海 太郎) strcpy( jdata[10]address 平塚市北金目1117)

strcpy( jdata[10]tel 0463-58-1211) jdata[10]age = 30 printf(yenn氏名 = syenn jdata[10]name) printf(yenn住所 = syenn jdata[10]address) printf(yenn電話番号= syenn jdata[10]tel) printf(yenn年齢 = dyenn jdata[10]age)

26

(4) 構造体のポインタ 変数と同じように構造体へのポインタも定義することができます

変数へのポインタ例 構造体へのポインタ例 またポインタを使用して構造体メンバーを参照するには次のように -> 記号を使って指

定します ポインタ変数名 -> メンバー名

[プログラム例]

名前住所電話番号年齢を定義しそれを印字します include ltstdiohgt include ltstringhgt main() struct jusho char name[30] char address[30] char tel[20] int age jdatakp kp = ampjdata strcpy( kp-gtname 東海 太郎)

strcpy( kp-gtaddress 平塚市北金目1117)

strcpy( kp-gttel 0463-58-1211) kp-gtage = 30 printf(yenn氏名 = syenn kp-gtname) printf(yenn住所 = syenn kp-gtaddress) printf(yenn電話番号= syenn kp-gttel) printf(yenn年齢 = dyenn kp-gtage)

kp jdata

name[30] ポインタ型の変数 address[30]

tel[20]

構造体へのポインタを記憶 age

することができます

int a int b b = ampa

struct name jname struct name np np = ampname

27

7-2 共用体 共用体は構造体と同じようにして宣言しますが共用体は複数のデータ型を同一のアドレスに

割り当てる方法です union 共用体タグ名 共用体メンバーの並び

「union」は共用体を表すキーワードです 「共用体タグ名」は共用体の型枠の名前を宣言しますここは自由に名前を定義することがで

きます 「共用体メンバーの並び」は共用体の要素です複数指定できます

共用体の宣言の例を次に示します

union c_tag int a char b

共用体 cは次のように共用体タグ c_tagの形式で領域を確保します共用体はメモリ上に領域を確保するときは ab ともに同じ領域に割り付けられます これはab という2つのデータが同時に存在するわけではなく cを異なるデータ abで共有す

ることを表しています c a b

上記の宣言だけでは共用体の形式を宣言しているだけでメモリ中で実際の領域を確保して

いるわけではありません実際に領域を確保するためには次のように定義します union 構造体タグ名 構造体名

したがって共用体名を c とすると次のように指定します

union c_tag c

(1)共用体の参照

プログラム中で共用体中のメンバーを参照する場合には次のように指定します 共用体名メンバー名

したがって「a」または「b」を参照したいときには次のように指定します

ca (int 型) cb (char 型)

メンバー参照方法によって int型として使ったりchar型として利用することができます

28

[プログラム例]

includeltstdiohgt main() union data char a short b int c chk chkc = 0x12345678 printf( char a xyennchka) printf( short b xyennchkb) printf( int c xyennchkc)

chkb(int 型) chkb(short 型) chka(char 型) 12 12 12 34 34 56 78

29

第8章 アルゴリズム コンピュータに何か仕事をさせようとするときは仕事を具体的に実行するための処理や動作

の手順が必要ですこの「手順」がアルゴリズムです アルゴリズムを考えるときは解くべき問題をはっきりと定義することが必要です

8-1 ソート ソートとは与えられたデータを小さい順または大きい順に並べ換えることですソート方法は

いくつかありますが基本的な方法でソートするアルゴリズムを紹介します

includeltstdiohgt int data[10] main()

int data_in() sort() data_in() sort() int data_in() データ入力関数

int a printf(数値入力yenn)

for(a=0alt=9a++) printf( [d]a+1) scanf(dampdata[a]) int sort() ソート処理を行う関数

int cont1cont2tmp1tmp2mim for(cont1=0 cont1lt=9 cont1++) mim=data[cont1] tmp1=cont1 for(cont2=cont1+1 cont2lt=9 cont2++) if(data[cont2] lt mim) mim=data[cont2] tmp1=cont2 tmp2 = data[cont1] data[cont1] = data[tmp1] data[tmp1] = tmp2 printf(結果 yenn)

for (cont1 = 0 cont1 lt= 9 cont1++) printf(d yenn data[cont1])

30

第9章 プリプロセッサ C言語にはプログラムの中でコンパイルについての指示を行う「プリプロセッサ」という機能が

ありますまたプリプロセッサとはコンパイルする前に実行されるためその意味のとおり「前処理」 と呼ばれていますここでは代表的なものをいくつか説明します

9-1 ファイルの挿入 ソースプログラム中に指定されたファイルを挿入します

include ltstdiohgt helliphellip 標準ディレクトリを探します include progh helliphellip 現在のディレクトリを探しなければ標準ディレクトリを探します

includeltstdiohgt によって組み込まれた define EOF (-1) define EOF (-1) define define helliphelliphelliphellip 組み込み helliphelliphelliphellip

main() stdiohファイル

int helliphelliphelliphellip helliphelliphelliphellip

ソースファイル

9-2 文字の置換 プログラム中に使われている文字列を別の文字列に置き換えます

include ltstdiohgt define TRUE 1 define EOF (-1) main() define helliphellip helliphellip

while(TRUE) define TRUE 1 置き換え main() helliphellip helliphellip while(1)

break helliphelliphellip

31

9-3 条件によるコンパイル 識別子が定義されているか否かを判断しコンパイルする範囲を指定します

include ltstdiohgt define UNIX main() ifdef UNIX printf( UNIX yenn) else printf(MS-DOSyenn) endif

include ltstdiohgt define OS UNIX main() if OS == UNIX printf( UNIX yenn) else printf(MS-DOSyenn) endif

32

付 録 1 puts()gets()関数について

行単位に入出力を行う場合には puts() gets() 関数を用います

puts() 標準出力に文字列を出力します

include ltstdiohgt int puts( char s ) puts() は NULL で終る文字列 s を標準出力に出力し最後に改行文字 yenn も出力しま

gets() 標準入力から文字列を入力します

include ltstdiohgt char gets( char s ) 戻り値正常に入力した場合には引数 s の値が返されますエラーやEOFになった場合に

は NULL が返されます gets() は標準入力から復帰文字で終る文字列を入力しs に格納しますこのとき最後の復

帰文字は NULL文字に変更されます

入力行の出力 標準入力から gets() で入力したデータには改行コードは含まれませんまた標準出力へ

puts() で出力を行う場合には必ず改行コードが付加されますgets() を実行したときの戻り値としてファイルの終端を検出した場合には EOF ではなく NULL が返されますので注意して下さい

include ltstdiohgt main() char data[80] while( gets( data ) = NULL )puts( data )

putchar()getchar()関数について putchar() 標準出力に文字を出力します

include ltstdiohgt int putchar(int c ) 戻り値正常に出力できた場合には文字cをエラーの場合にはEOFを返します

33

getchar() 標準入力から文字を入力します

include ltstdiohgt int getchar(void) 戻り値正常に入力した場合には読み込んだ文字を int 型に変換して返しますまたファイ

ルエンドエラーの場合にはEOFを返します

標準入力標準出力

標準入力標準出力はプログラムが開始されるときにはオープンされていますそれぞれのフ

ァイルポインタは stdin stdout になっていますfopen() fclose() をせずとも使用することができます

scanf() 標準出力ストリームからテキストを読み込み解釈します include ltstdiohgt int scanf( const char format [ address ] ) 戻り値正しくスキャンし変換し格納した入力フィールドの数を返しますファイルエンドを読

み込んだ場合は戻り値は EOF となります値を格納したフィールドがなかった場合は戻り値は0となります

一連の入力フィールドをスキャンして1度に1文字ずつストリーム stdin から文字を読み込み

ます次に引き数 format によって指される書式文字列中の書式指定に従って各フィールドを書式化します最後にformat の後に続く各引き数が示しているアドレスに書式化した入力を格納していきます書式文字列中の書式指定の個数はその後に続くアドレスの数と同じでな

ければなりません 書式指定[入力幅][型指定文字] 入力幅 読むべき文字数の最大値 型指定文字 次のとおりです 型指定文字 期待される入力 引き数の型 d 10進整数 int へのポインタ( int arg ) x 16進整数 int へのポインタ( int arg ) f 浮動小数点数 float へのポインタ( float arg ) s 文字列 文字配列へのポインタ( char arg[] ) c 文字 文字へのポインタ( char arg )

printf() フォーマットを指定してテキスト標準出力ストリームに出力します include ltstdiohgt int printf( const char format [ argument ] ) 戻り値出力したバイト数を返しますエラーの場合は EOF を返します

34

format によって指される書式文字列中の書式指定をformat の後に続く各引き数に適用し

書式化されたデータを stdout に出力します書式指定は後に続く引き数と同じ数だけなければなりません

書式指定[印字幅][精度][型指定文字] 印字幅 印字する最小文字数 精度 印字する最大文字数 型指定文字 つぎのとおりです 型指定文字 入力引き数 出力の書式 d 整数 符号付き10進整数 x 整数 符号無し16進整数 f 浮動小数点 符号付きの dddddddd形式の値 c 文字 1個の文字 s 文字列ポインタ ヌル文字に出会うか精度に達するまで 文字をプリントする

fopen()fclose()関数について fopen() ファイルをオープンします

include ltstdiohgt FILE fopen( char filename char mode ) 戻り値正常にファイルのオープンができたらファイルポインタを返しますエラーがあった場

合には NULLを返します 文字列 filename で指定されたファイルをオープンしますオープン後の入出力のモードに

ついては文字列 mode で指定しますmode に指定できる文字は以下のとおりです r 入力モードでオープンします w 出力モードでオープンします a 存在するファイルに追加して出力するモードでオープンします r+ 既に作成してあるファイルを更新(入力出力)するモードでオープンします w+ 新しく作成するファイルを更新モードでオープンします a+ 既に作成してあるファイルの終りから更新用に作成します

以上の文字に b をつけ加えることによりバイナリモードで入出力することができるようになり

ます rb バイナリの入力モードでオープンします wb バイナリの出力モードでオープンします ab 存在するファイルに追加して出力するモード(バイナリ)でオープンします

fclose() 既にオープンしてあるファイルをクローズします include ltstdiohgt fclose( FILE fp ) 既にオープンしているファイルをクローズしますパラメータには fopen() 関数により返された

ファイルポインタを指定します

35

テキストモードとバイナリモード 行の最後はテキストモードの場合改行コードのみとなりバイナリモードの場合には復帰

コードと改行コードの組合わせになります行の最後としてテキストファイルには復帰コード改行

コードが書かれていますがテキストモードでオープンした場合には入力すると改行コードのみに

変換されて入力されますバイナリモードの場合には復帰コード改行コードがそれぞれ入力され

ます

fputs()fgets()関数について fputs() ファイルポインタで指定されるファイルに文字列を出力します

include ltstdiohgt

int fputs( char s FILE fp ) fputs() は NULL で終る文字列 s をファイルポインタに示されるファイルへ出力しますputs()

と違い最後に改行文字 yenn を出力することはありません

fgets() ファイルポインタで指定されるファイルから文字列を入力します include ltstdiohgt char fgets( char s int n FILE fp ) 戻り値正常に入力した場合には引数 s の値が返されますエラーやEOFになった場合に

は NULL が返されます fgets() はファイルポインタで指定されるファイルから ( n - 1 ) 文字または改行文字までの

文字列を入力しs に格納しますgets() と異なり最後に入力された改行文字は NULL 文字に変更されません

標準入力から入力しファイルへ出力する ファイルへ出力あるいは入力を行う場合には改行コードの変換(入力の場合の削除出力の

場合の付加)はされませんしたがって標準入力から入力しファイルへ出力する場合には改行

コードを付加しなければなりません include ltstdiohgt main() char data[80] FILE fp fp = fopen( data w ) while( gets( data ) = NULL ) strcat( data yenn ) 改行コードの付加

fputs( data fp ) fclose( fp )

36

fputc()fgetc()関数について fputc() ファイルポインタで指定されるファイルに1文字出力します

include ltstdiohgt int fputc( int c FILE fp ) 戻り値正常に出力できた場合には文字 c を返しエラーの場合には EOF を返します fputc() は文字 c をファイルポインタで示されるファイルへ出力します

fgetc() ファイルポインタで指定されるファイルから1文字入力します

include ltstdiohgt int fgetc( FILE fp ) 戻り値正常に入力した場合には入力した文字を返しますエラーやEOFになった場合には

EOF が返されます fgetc() はファイルポインタで指定されるファイルから文字を入力します

ファイルの内容の表示 include ltstdiohgt main() FILE fp int ch char fname[30] printf( Key in Fila name gt ) gets( fname ) fp = fopen( fname r ) while( ( ch = fgetc( fp ) ) = EOF )putchar( ch ) fclose( fp )

その他テキスト中で使用された関数について sin() 三角関数の正弦を計算します

include ltmathhgt double sin(double radian) sinはラジアンを単位とする引数 radianの三角関数を計算します

37

strcpy() 文字列を他の文字列へコピーします

include ltstringhgt char strcpy(char string1const char string2) strcpyは引数 string2の指す文字列を null文字まで含めて引数 string1の指す領域にコピ

ーする strcpyは string1を返します

strcat() ある文字列を他の文字列に加えます

include ltstringhgt char strcat( char dest const char src ) 戻り値連結された文字列へのポインタを返します strcat() はsrc のコピーを dest の最後につけ加えます得られる文字列の長さは

strlen(dest)+strlen(src) になります

fabs() 絶対値の計算をします include ltmathhgt double fabs(double z) fabsは倍精度浮動小数の絶対値を計算して返しますつまりzgt=0であれば z をzlt0であ

れば-zを返します exp() 指数関数を計算します

include ltmathhgt double exp(double z) exp は引数zの指数関数つまりezを返すここではeは自然対数の底を表します対数関

数logの逆関数です

38

付 録 2 コンパイルの方法には大きく分けて第4章の実習で学んだようにデータファイルを作成してお

き ccg でコンパイルさせる方法と実行中に対話型でデータを入力していく方法があります ここでは対話型で実行を進めていく方法を紹介します ただしこの方法は計算(cpu)時間が10秒以内のものに限ります10秒を超える計算(cpu)時

間を要する場合はccg でコンパイルをするようにしてください 第4章実習の(2)(p16)までは同様です

コンパイル

コンピュータに処理を依頼します 60us1234boseicc cc rensyuc

所有するファイルの一覧を見てみます

60us1234boseicc ls -l larr 持っているファイルの一覧を見るコマンドです

-rw-r--r-- 1 60us1234 other 128 4月26日 15時14分 rensyuc -rwxr-xr-x 1 60us1234 other 361 4月26日 15時16分 aout

aout という実行形式のファイルが作成されています

実行

60us1234boseicc aout12 35[リターン] データを入力

1 200000 3500000 4200000 実行結果の出力

60us1234boseicc

注意

aout ファイルは印刷することができません実行結果を印刷する場合にはファイルに落とし てから出力するようにしましょう

60us1234boseicc aout gt kekka12 35[リターン] データを入力

60us1234boseicc more kekka 計算結果の確認 60us1234boseicc lpr kekka 計算結果の印刷

39

Page 21: n 第1章 章立ての部分は、書式(PC入門大見出し)を …第2章 数の表現 2-1 2進数 電子計算機の動作原理は0と1で表される2進数です。また、人間が日常生活で扱っている数

[プログラム例] 二次元配列のタテヨコを加算するプログラム

include ltstdiohgt main() int mat[4][3]=123456789101112 int ijytotalttotal[3]total=0 for(j=0jlt3j++)ttotal[j]=0 for (i=0ilt4i++) ytotal=0 for(j=0jlt3j++) ytotal += mat[i][j] ttotal[j] += mat[i][j] total += mat[i][j] printf(3dmat[i][j]) printf( 3dyennytotal) printf(yenn) for(j=0jlt3j++)printf(3dttotal[j]) printf( 3dyenntotal)

[実行結果]

1 2 3 6 4 5 6 15 7 8 9 24 10 11 12 33 22 26 30 78

演習7

a)以下の配列はどのように初期化されるか答えなさい char errmsg[2][15] = Divide Error Overflow Error

b)九九の計算を2次元配列を使って求めなさい

19

第6章 ポインタ型変数 C言語では値を記憶するための変数だけではなく変数または定数の番地を記憶するため

のポインタ型変数を宣言することができますポインタとはデータ項目の一種で「記憶装置(メモ

リ)上の格納番地(アドレス)を指すデータ項目」です アドレス コンピュータの中ではデータ項目の格納番地のことをアドレス(住所)と呼びます 例えば記憶装置という名前のとてつもなく大きなマンションがあるとしますその中から Aさんを捜すときは部屋番号を参照しますマンションでは部屋番号で住居人を参照し ているのと同じようにコンピュータでは記憶装置上に確保された変数は格納番地 (アドレス)で管理されています

マンション 部屋番号 記憶装置 格納番地

Aさん Int a Bさん Cさん AAAさん BBBさん CCCさん

1号室

2号室

3号室

100号室

200号室

300号室

100番地

200番地

300番地

1000番地

2000番地

3000番地

Int b Int c float aaafloat bbbfloat ccc

ポインタ ポインタとは「指し示すもの」の意ですがC言語では記憶装置上のアドレスを指し示す もののことです上のマンションの例では部屋番号を格納するデータ項目ということに なりますAAAさんは100号室に住んでいます100という値をポインタのデータ項目に 記憶するとそのデータ項目は間接的にAAAさんを指すことになります

6-1 ポインタ型変数の宣言および参照 通常の変数と区別するために型宣言時に変数名の前に記号を付けて宣言します int a 整数型ポインタ変数 int b 整数型変数

変数 a は整数型の値を記憶するのではなく整数型の値を持つ変数などの番地を記憶する変数ですまた変数 b は通常の整数型の値を記憶するための変数です

20

include ltstdiohgt main() int a b c a はポインタ型の変数b c は整数型の変数 b = 12 変数 b に値 12 を代入します a = ampb 変数 a には変数 b の番地が代入されます c = a + 10 変数 a の指す変数(b)の内容と10の加算です つまり12 + 10 を変数 c に代入します

変数の型宣言において変数名に記号を付けることによりその変数はポインタ型の変数と

なりますポインタ型の変数は変数名のみを指定した場合には単にその変数の値(通常はメモリ

の番地)を表します変数名に記号を付けて使用した場合にはその変数が指し示している変

数の内容を表します c = a ポインタ型変数 a が指している値を変数 c に代入

ポインタ型の変数に番地を記憶させるためにはプログラム例のように変数名の前に記号を

指定します変数名 によって変数の番地(アドレス)を表します a = ampb 変数 b の番地をポインタ型変数 a に代入します

ポインタ型変数の型はポインタ型変数が指し示す先の変数の型を表しています int a 変数 a 整数型の値 float x 変数 x 実数型の値 char c 変数 c 文字型の値

6-2 ポインタ型変数の初期化 ポインタ型変数も型宣言のときに変数を初期化することができます特に文字型のポインタ変

数の場合によく使います char str = TOKAI University

ポインタ型変数 str は文字列定数 TOKAI University の最初の文字が格納されている番地を初期値として持つことになります

変数 str TOKAI University 文字列定数

[プログラム例]

(1)文字型配列 putchar() 関数を使って一次元の文字型配列を出力します include ltstdiohgt main() char str[6] = TOKAI int i for( i = 0 str[i] = yen0 i++ ) putchar( str[i] )

21

ポインタを使用した場合には以下のようになります include ltstdiohgt main() char str[6] = TOKAI char chp for( chp = str chp = yen0 chp++ ) putchar( chp )

chp str T [0] O K A I yen0 [5]

参照する変数 配列の表現 ポインタの表現 実際のアドレス 1番目の数 str[0] chp CHP 2番目の数 str[1] (chp+1) CHP+1 n番目の数 str[n-1] (chp+n-1) CHP+n-1 6番目の数 str[5] (chp+5) CHP+5

注意実際のアドレス CHPは実行時に決定されます

(2)二次元文字型配列 二次元の文字型配列に定数を設定しそれを出力するプログラムです文字型配列を使用す

ると次のとおりになります include ltstdiohgt main() char str[5][40] = TOKAI shounan campus NEC DEC int i for( i = 0 i lt 5 i++ ) printf( yenns str[i] )

40 バイト str TOKAI shounan campus NEC DEC

22

ポインタ型配列を使用すると次のとおりになります include ltstdiohgt main() char str[6] = TOKAI shounan campus NEC DEC NULL char chp for( chp = str chp = NULL chp++ ) printf( yenns chp ) str

chp 番地 TOKAI 番地 shounan 番地 campus 番地 NEC 番地 DEC

NULL

演習8 キーボードまたはデータファイルから読み込んだ文字列中にrsquoArsquo があったら rsquoarsquo に変換 するプログラムを配列とポインタを使って書きなさい

23

第7章 構造体共用体 7-1 構造体

プログラムの規模が大きくなるにつれて多数の intや floatcharなどのデータ型を扱うようになり複雑になってきますそこで多数のデータを1つにまとめて簡単に扱える機能が構造体です 構造体について住所録のデータを例にあげて考えてみます

住所録の個人データとして氏名住所電話番号年齢の項目を一つのデータとします これをC言語で変数の定義をすると次のようになります 氏名東海太郎 char name[30] 住所平塚市北金目1117 char address[30] 電話番号0463-58-1211 char tel[20] 年齢30 int age 個人の住所録データ C言語での表現 このような住所録の個人データを1つにまとめて新しいデータとして定義する機能を構造体と言

います struct 構造体タグ名 構造体メンバーの並び

「struct」は構造体を表すキーワードです 「構造体タグ名」は構造体の型枠を宣言しますここは自由に名前を定義することができ ます 「構造体メンバーの並び」は構造体の要素です複数指定できます

個人の住所録のデータを構造体で宣言すると次のようになります

struct jusho char name[30] char address[30] 構造体のメンバーの並び char tel[20] (複数可)

int age

上記の宣言では構造体の形式を宣言しているだけでメモリ中で実際の領域を確保している

わけではありません実際に領域を確保するためには次のように定義します

struct 構造体タグ名 構造体名

したがって構造体名を jdata とすると次のように指定します

struct jusho jdata

構造体 jdataは次のように構造体タグ jushoの形式で領域を確保します

24

Jdata name[30]

address[30] tel[20] age

(1)構造体の参照

プログラム中で構造体中のメンバーを参照する場合には次のように指定します 構造体名メンバー名

したがって「名前」を参照したいときには次のように指定します

jdataname

[プログラム例]

名前住所電話番号年齢を定義しそれを印字します include ltstdiohgt include ltstringhgt main() struct jusho char name[30] char address[30] char tel[20] int age struct jusho jdata strcpy( jdataname 東海 太郎) strcpy( jdataaddress 平塚市北金目1117)

strcpy( jdatatel 0463-58-1211) jdataage = 30 printf(yenn氏名 = syenn jdataname) printf(yenn住所 = syenn jdataaddress) printf(yenn電話番号= syenn jdatatel) printf(yenn年齢 = dyenn jdataage)

また構造体の形式の定義と領域の確保は次のように同時におこなうことができます

struct 構造体タグ名 構造体メンバーの並び 構造体名

struct jusho struct jusho char name[30] char name[30] char address[30] char address[30] char tel[30] = char tel[30] int age 同じ int age

jdata struct jusho jdata

型宣言と同時にメモリ上に領域を確保する方法 後からメモリ上に領域を確保する方法

25

(2) 構造体配列 住所録データの場合その中に入るデータは1件ではありませんやはり100件200件のデ

ータが必要になる場合がありますこのように個人単位のデータを多数扱う場合には構造体を配

列として宣言することができます 次の例は個人のデータを100個用意するために構造体を配列として宣言しています struct jusho jdata[100] jdata[0] name[30] address[30] tel[20] age

jdata[99 ] name[30] address[30] tel[20] age

(3)構造体配列の参照

プログラム中で構造体配列中のメンバーを参照する場合には次のように指定します 構造体名[要素番号]メンバー名

したがって10件目の人の「名前」を参照したいときには次のように指定します

jdata[10]name

[プログラム例]

名前住所電話番号年齢を定義しそれを印字します include ltstdiohgt include ltstringhgt main() struct jusho char name[30] char address[30] char tel[20] int age jdata[100] strcpy( jdata[10]name 東海 太郎) strcpy( jdata[10]address 平塚市北金目1117)

strcpy( jdata[10]tel 0463-58-1211) jdata[10]age = 30 printf(yenn氏名 = syenn jdata[10]name) printf(yenn住所 = syenn jdata[10]address) printf(yenn電話番号= syenn jdata[10]tel) printf(yenn年齢 = dyenn jdata[10]age)

26

(4) 構造体のポインタ 変数と同じように構造体へのポインタも定義することができます

変数へのポインタ例 構造体へのポインタ例 またポインタを使用して構造体メンバーを参照するには次のように -> 記号を使って指

定します ポインタ変数名 -> メンバー名

[プログラム例]

名前住所電話番号年齢を定義しそれを印字します include ltstdiohgt include ltstringhgt main() struct jusho char name[30] char address[30] char tel[20] int age jdatakp kp = ampjdata strcpy( kp-gtname 東海 太郎)

strcpy( kp-gtaddress 平塚市北金目1117)

strcpy( kp-gttel 0463-58-1211) kp-gtage = 30 printf(yenn氏名 = syenn kp-gtname) printf(yenn住所 = syenn kp-gtaddress) printf(yenn電話番号= syenn kp-gttel) printf(yenn年齢 = dyenn kp-gtage)

kp jdata

name[30] ポインタ型の変数 address[30]

tel[20]

構造体へのポインタを記憶 age

することができます

int a int b b = ampa

struct name jname struct name np np = ampname

27

7-2 共用体 共用体は構造体と同じようにして宣言しますが共用体は複数のデータ型を同一のアドレスに

割り当てる方法です union 共用体タグ名 共用体メンバーの並び

「union」は共用体を表すキーワードです 「共用体タグ名」は共用体の型枠の名前を宣言しますここは自由に名前を定義することがで

きます 「共用体メンバーの並び」は共用体の要素です複数指定できます

共用体の宣言の例を次に示します

union c_tag int a char b

共用体 cは次のように共用体タグ c_tagの形式で領域を確保します共用体はメモリ上に領域を確保するときは ab ともに同じ領域に割り付けられます これはab という2つのデータが同時に存在するわけではなく cを異なるデータ abで共有す

ることを表しています c a b

上記の宣言だけでは共用体の形式を宣言しているだけでメモリ中で実際の領域を確保して

いるわけではありません実際に領域を確保するためには次のように定義します union 構造体タグ名 構造体名

したがって共用体名を c とすると次のように指定します

union c_tag c

(1)共用体の参照

プログラム中で共用体中のメンバーを参照する場合には次のように指定します 共用体名メンバー名

したがって「a」または「b」を参照したいときには次のように指定します

ca (int 型) cb (char 型)

メンバー参照方法によって int型として使ったりchar型として利用することができます

28

[プログラム例]

includeltstdiohgt main() union data char a short b int c chk chkc = 0x12345678 printf( char a xyennchka) printf( short b xyennchkb) printf( int c xyennchkc)

chkb(int 型) chkb(short 型) chka(char 型) 12 12 12 34 34 56 78

29

第8章 アルゴリズム コンピュータに何か仕事をさせようとするときは仕事を具体的に実行するための処理や動作

の手順が必要ですこの「手順」がアルゴリズムです アルゴリズムを考えるときは解くべき問題をはっきりと定義することが必要です

8-1 ソート ソートとは与えられたデータを小さい順または大きい順に並べ換えることですソート方法は

いくつかありますが基本的な方法でソートするアルゴリズムを紹介します

includeltstdiohgt int data[10] main()

int data_in() sort() data_in() sort() int data_in() データ入力関数

int a printf(数値入力yenn)

for(a=0alt=9a++) printf( [d]a+1) scanf(dampdata[a]) int sort() ソート処理を行う関数

int cont1cont2tmp1tmp2mim for(cont1=0 cont1lt=9 cont1++) mim=data[cont1] tmp1=cont1 for(cont2=cont1+1 cont2lt=9 cont2++) if(data[cont2] lt mim) mim=data[cont2] tmp1=cont2 tmp2 = data[cont1] data[cont1] = data[tmp1] data[tmp1] = tmp2 printf(結果 yenn)

for (cont1 = 0 cont1 lt= 9 cont1++) printf(d yenn data[cont1])

30

第9章 プリプロセッサ C言語にはプログラムの中でコンパイルについての指示を行う「プリプロセッサ」という機能が

ありますまたプリプロセッサとはコンパイルする前に実行されるためその意味のとおり「前処理」 と呼ばれていますここでは代表的なものをいくつか説明します

9-1 ファイルの挿入 ソースプログラム中に指定されたファイルを挿入します

include ltstdiohgt helliphellip 標準ディレクトリを探します include progh helliphellip 現在のディレクトリを探しなければ標準ディレクトリを探します

includeltstdiohgt によって組み込まれた define EOF (-1) define EOF (-1) define define helliphelliphelliphellip 組み込み helliphelliphelliphellip

main() stdiohファイル

int helliphelliphelliphellip helliphelliphelliphellip

ソースファイル

9-2 文字の置換 プログラム中に使われている文字列を別の文字列に置き換えます

include ltstdiohgt define TRUE 1 define EOF (-1) main() define helliphellip helliphellip

while(TRUE) define TRUE 1 置き換え main() helliphellip helliphellip while(1)

break helliphelliphellip

31

9-3 条件によるコンパイル 識別子が定義されているか否かを判断しコンパイルする範囲を指定します

include ltstdiohgt define UNIX main() ifdef UNIX printf( UNIX yenn) else printf(MS-DOSyenn) endif

include ltstdiohgt define OS UNIX main() if OS == UNIX printf( UNIX yenn) else printf(MS-DOSyenn) endif

32

付 録 1 puts()gets()関数について

行単位に入出力を行う場合には puts() gets() 関数を用います

puts() 標準出力に文字列を出力します

include ltstdiohgt int puts( char s ) puts() は NULL で終る文字列 s を標準出力に出力し最後に改行文字 yenn も出力しま

gets() 標準入力から文字列を入力します

include ltstdiohgt char gets( char s ) 戻り値正常に入力した場合には引数 s の値が返されますエラーやEOFになった場合に

は NULL が返されます gets() は標準入力から復帰文字で終る文字列を入力しs に格納しますこのとき最後の復

帰文字は NULL文字に変更されます

入力行の出力 標準入力から gets() で入力したデータには改行コードは含まれませんまた標準出力へ

puts() で出力を行う場合には必ず改行コードが付加されますgets() を実行したときの戻り値としてファイルの終端を検出した場合には EOF ではなく NULL が返されますので注意して下さい

include ltstdiohgt main() char data[80] while( gets( data ) = NULL )puts( data )

putchar()getchar()関数について putchar() 標準出力に文字を出力します

include ltstdiohgt int putchar(int c ) 戻り値正常に出力できた場合には文字cをエラーの場合にはEOFを返します

33

getchar() 標準入力から文字を入力します

include ltstdiohgt int getchar(void) 戻り値正常に入力した場合には読み込んだ文字を int 型に変換して返しますまたファイ

ルエンドエラーの場合にはEOFを返します

標準入力標準出力

標準入力標準出力はプログラムが開始されるときにはオープンされていますそれぞれのフ

ァイルポインタは stdin stdout になっていますfopen() fclose() をせずとも使用することができます

scanf() 標準出力ストリームからテキストを読み込み解釈します include ltstdiohgt int scanf( const char format [ address ] ) 戻り値正しくスキャンし変換し格納した入力フィールドの数を返しますファイルエンドを読

み込んだ場合は戻り値は EOF となります値を格納したフィールドがなかった場合は戻り値は0となります

一連の入力フィールドをスキャンして1度に1文字ずつストリーム stdin から文字を読み込み

ます次に引き数 format によって指される書式文字列中の書式指定に従って各フィールドを書式化します最後にformat の後に続く各引き数が示しているアドレスに書式化した入力を格納していきます書式文字列中の書式指定の個数はその後に続くアドレスの数と同じでな

ければなりません 書式指定[入力幅][型指定文字] 入力幅 読むべき文字数の最大値 型指定文字 次のとおりです 型指定文字 期待される入力 引き数の型 d 10進整数 int へのポインタ( int arg ) x 16進整数 int へのポインタ( int arg ) f 浮動小数点数 float へのポインタ( float arg ) s 文字列 文字配列へのポインタ( char arg[] ) c 文字 文字へのポインタ( char arg )

printf() フォーマットを指定してテキスト標準出力ストリームに出力します include ltstdiohgt int printf( const char format [ argument ] ) 戻り値出力したバイト数を返しますエラーの場合は EOF を返します

34

format によって指される書式文字列中の書式指定をformat の後に続く各引き数に適用し

書式化されたデータを stdout に出力します書式指定は後に続く引き数と同じ数だけなければなりません

書式指定[印字幅][精度][型指定文字] 印字幅 印字する最小文字数 精度 印字する最大文字数 型指定文字 つぎのとおりです 型指定文字 入力引き数 出力の書式 d 整数 符号付き10進整数 x 整数 符号無し16進整数 f 浮動小数点 符号付きの dddddddd形式の値 c 文字 1個の文字 s 文字列ポインタ ヌル文字に出会うか精度に達するまで 文字をプリントする

fopen()fclose()関数について fopen() ファイルをオープンします

include ltstdiohgt FILE fopen( char filename char mode ) 戻り値正常にファイルのオープンができたらファイルポインタを返しますエラーがあった場

合には NULLを返します 文字列 filename で指定されたファイルをオープンしますオープン後の入出力のモードに

ついては文字列 mode で指定しますmode に指定できる文字は以下のとおりです r 入力モードでオープンします w 出力モードでオープンします a 存在するファイルに追加して出力するモードでオープンします r+ 既に作成してあるファイルを更新(入力出力)するモードでオープンします w+ 新しく作成するファイルを更新モードでオープンします a+ 既に作成してあるファイルの終りから更新用に作成します

以上の文字に b をつけ加えることによりバイナリモードで入出力することができるようになり

ます rb バイナリの入力モードでオープンします wb バイナリの出力モードでオープンします ab 存在するファイルに追加して出力するモード(バイナリ)でオープンします

fclose() 既にオープンしてあるファイルをクローズします include ltstdiohgt fclose( FILE fp ) 既にオープンしているファイルをクローズしますパラメータには fopen() 関数により返された

ファイルポインタを指定します

35

テキストモードとバイナリモード 行の最後はテキストモードの場合改行コードのみとなりバイナリモードの場合には復帰

コードと改行コードの組合わせになります行の最後としてテキストファイルには復帰コード改行

コードが書かれていますがテキストモードでオープンした場合には入力すると改行コードのみに

変換されて入力されますバイナリモードの場合には復帰コード改行コードがそれぞれ入力され

ます

fputs()fgets()関数について fputs() ファイルポインタで指定されるファイルに文字列を出力します

include ltstdiohgt

int fputs( char s FILE fp ) fputs() は NULL で終る文字列 s をファイルポインタに示されるファイルへ出力しますputs()

と違い最後に改行文字 yenn を出力することはありません

fgets() ファイルポインタで指定されるファイルから文字列を入力します include ltstdiohgt char fgets( char s int n FILE fp ) 戻り値正常に入力した場合には引数 s の値が返されますエラーやEOFになった場合に

は NULL が返されます fgets() はファイルポインタで指定されるファイルから ( n - 1 ) 文字または改行文字までの

文字列を入力しs に格納しますgets() と異なり最後に入力された改行文字は NULL 文字に変更されません

標準入力から入力しファイルへ出力する ファイルへ出力あるいは入力を行う場合には改行コードの変換(入力の場合の削除出力の

場合の付加)はされませんしたがって標準入力から入力しファイルへ出力する場合には改行

コードを付加しなければなりません include ltstdiohgt main() char data[80] FILE fp fp = fopen( data w ) while( gets( data ) = NULL ) strcat( data yenn ) 改行コードの付加

fputs( data fp ) fclose( fp )

36

fputc()fgetc()関数について fputc() ファイルポインタで指定されるファイルに1文字出力します

include ltstdiohgt int fputc( int c FILE fp ) 戻り値正常に出力できた場合には文字 c を返しエラーの場合には EOF を返します fputc() は文字 c をファイルポインタで示されるファイルへ出力します

fgetc() ファイルポインタで指定されるファイルから1文字入力します

include ltstdiohgt int fgetc( FILE fp ) 戻り値正常に入力した場合には入力した文字を返しますエラーやEOFになった場合には

EOF が返されます fgetc() はファイルポインタで指定されるファイルから文字を入力します

ファイルの内容の表示 include ltstdiohgt main() FILE fp int ch char fname[30] printf( Key in Fila name gt ) gets( fname ) fp = fopen( fname r ) while( ( ch = fgetc( fp ) ) = EOF )putchar( ch ) fclose( fp )

その他テキスト中で使用された関数について sin() 三角関数の正弦を計算します

include ltmathhgt double sin(double radian) sinはラジアンを単位とする引数 radianの三角関数を計算します

37

strcpy() 文字列を他の文字列へコピーします

include ltstringhgt char strcpy(char string1const char string2) strcpyは引数 string2の指す文字列を null文字まで含めて引数 string1の指す領域にコピ

ーする strcpyは string1を返します

strcat() ある文字列を他の文字列に加えます

include ltstringhgt char strcat( char dest const char src ) 戻り値連結された文字列へのポインタを返します strcat() はsrc のコピーを dest の最後につけ加えます得られる文字列の長さは

strlen(dest)+strlen(src) になります

fabs() 絶対値の計算をします include ltmathhgt double fabs(double z) fabsは倍精度浮動小数の絶対値を計算して返しますつまりzgt=0であれば z をzlt0であ

れば-zを返します exp() 指数関数を計算します

include ltmathhgt double exp(double z) exp は引数zの指数関数つまりezを返すここではeは自然対数の底を表します対数関

数logの逆関数です

38

付 録 2 コンパイルの方法には大きく分けて第4章の実習で学んだようにデータファイルを作成してお

き ccg でコンパイルさせる方法と実行中に対話型でデータを入力していく方法があります ここでは対話型で実行を進めていく方法を紹介します ただしこの方法は計算(cpu)時間が10秒以内のものに限ります10秒を超える計算(cpu)時

間を要する場合はccg でコンパイルをするようにしてください 第4章実習の(2)(p16)までは同様です

コンパイル

コンピュータに処理を依頼します 60us1234boseicc cc rensyuc

所有するファイルの一覧を見てみます

60us1234boseicc ls -l larr 持っているファイルの一覧を見るコマンドです

-rw-r--r-- 1 60us1234 other 128 4月26日 15時14分 rensyuc -rwxr-xr-x 1 60us1234 other 361 4月26日 15時16分 aout

aout という実行形式のファイルが作成されています

実行

60us1234boseicc aout12 35[リターン] データを入力

1 200000 3500000 4200000 実行結果の出力

60us1234boseicc

注意

aout ファイルは印刷することができません実行結果を印刷する場合にはファイルに落とし てから出力するようにしましょう

60us1234boseicc aout gt kekka12 35[リターン] データを入力

60us1234boseicc more kekka 計算結果の確認 60us1234boseicc lpr kekka 計算結果の印刷

39

Page 22: n 第1章 章立ての部分は、書式(PC入門大見出し)を …第2章 数の表現 2-1 2進数 電子計算機の動作原理は0と1で表される2進数です。また、人間が日常生活で扱っている数

第6章 ポインタ型変数 C言語では値を記憶するための変数だけではなく変数または定数の番地を記憶するため

のポインタ型変数を宣言することができますポインタとはデータ項目の一種で「記憶装置(メモ

リ)上の格納番地(アドレス)を指すデータ項目」です アドレス コンピュータの中ではデータ項目の格納番地のことをアドレス(住所)と呼びます 例えば記憶装置という名前のとてつもなく大きなマンションがあるとしますその中から Aさんを捜すときは部屋番号を参照しますマンションでは部屋番号で住居人を参照し ているのと同じようにコンピュータでは記憶装置上に確保された変数は格納番地 (アドレス)で管理されています

マンション 部屋番号 記憶装置 格納番地

Aさん Int a Bさん Cさん AAAさん BBBさん CCCさん

1号室

2号室

3号室

100号室

200号室

300号室

100番地

200番地

300番地

1000番地

2000番地

3000番地

Int b Int c float aaafloat bbbfloat ccc

ポインタ ポインタとは「指し示すもの」の意ですがC言語では記憶装置上のアドレスを指し示す もののことです上のマンションの例では部屋番号を格納するデータ項目ということに なりますAAAさんは100号室に住んでいます100という値をポインタのデータ項目に 記憶するとそのデータ項目は間接的にAAAさんを指すことになります

6-1 ポインタ型変数の宣言および参照 通常の変数と区別するために型宣言時に変数名の前に記号を付けて宣言します int a 整数型ポインタ変数 int b 整数型変数

変数 a は整数型の値を記憶するのではなく整数型の値を持つ変数などの番地を記憶する変数ですまた変数 b は通常の整数型の値を記憶するための変数です

20

include ltstdiohgt main() int a b c a はポインタ型の変数b c は整数型の変数 b = 12 変数 b に値 12 を代入します a = ampb 変数 a には変数 b の番地が代入されます c = a + 10 変数 a の指す変数(b)の内容と10の加算です つまり12 + 10 を変数 c に代入します

変数の型宣言において変数名に記号を付けることによりその変数はポインタ型の変数と

なりますポインタ型の変数は変数名のみを指定した場合には単にその変数の値(通常はメモリ

の番地)を表します変数名に記号を付けて使用した場合にはその変数が指し示している変

数の内容を表します c = a ポインタ型変数 a が指している値を変数 c に代入

ポインタ型の変数に番地を記憶させるためにはプログラム例のように変数名の前に記号を

指定します変数名 によって変数の番地(アドレス)を表します a = ampb 変数 b の番地をポインタ型変数 a に代入します

ポインタ型変数の型はポインタ型変数が指し示す先の変数の型を表しています int a 変数 a 整数型の値 float x 変数 x 実数型の値 char c 変数 c 文字型の値

6-2 ポインタ型変数の初期化 ポインタ型変数も型宣言のときに変数を初期化することができます特に文字型のポインタ変

数の場合によく使います char str = TOKAI University

ポインタ型変数 str は文字列定数 TOKAI University の最初の文字が格納されている番地を初期値として持つことになります

変数 str TOKAI University 文字列定数

[プログラム例]

(1)文字型配列 putchar() 関数を使って一次元の文字型配列を出力します include ltstdiohgt main() char str[6] = TOKAI int i for( i = 0 str[i] = yen0 i++ ) putchar( str[i] )

21

ポインタを使用した場合には以下のようになります include ltstdiohgt main() char str[6] = TOKAI char chp for( chp = str chp = yen0 chp++ ) putchar( chp )

chp str T [0] O K A I yen0 [5]

参照する変数 配列の表現 ポインタの表現 実際のアドレス 1番目の数 str[0] chp CHP 2番目の数 str[1] (chp+1) CHP+1 n番目の数 str[n-1] (chp+n-1) CHP+n-1 6番目の数 str[5] (chp+5) CHP+5

注意実際のアドレス CHPは実行時に決定されます

(2)二次元文字型配列 二次元の文字型配列に定数を設定しそれを出力するプログラムです文字型配列を使用す

ると次のとおりになります include ltstdiohgt main() char str[5][40] = TOKAI shounan campus NEC DEC int i for( i = 0 i lt 5 i++ ) printf( yenns str[i] )

40 バイト str TOKAI shounan campus NEC DEC

22

ポインタ型配列を使用すると次のとおりになります include ltstdiohgt main() char str[6] = TOKAI shounan campus NEC DEC NULL char chp for( chp = str chp = NULL chp++ ) printf( yenns chp ) str

chp 番地 TOKAI 番地 shounan 番地 campus 番地 NEC 番地 DEC

NULL

演習8 キーボードまたはデータファイルから読み込んだ文字列中にrsquoArsquo があったら rsquoarsquo に変換 するプログラムを配列とポインタを使って書きなさい

23

第7章 構造体共用体 7-1 構造体

プログラムの規模が大きくなるにつれて多数の intや floatcharなどのデータ型を扱うようになり複雑になってきますそこで多数のデータを1つにまとめて簡単に扱える機能が構造体です 構造体について住所録のデータを例にあげて考えてみます

住所録の個人データとして氏名住所電話番号年齢の項目を一つのデータとします これをC言語で変数の定義をすると次のようになります 氏名東海太郎 char name[30] 住所平塚市北金目1117 char address[30] 電話番号0463-58-1211 char tel[20] 年齢30 int age 個人の住所録データ C言語での表現 このような住所録の個人データを1つにまとめて新しいデータとして定義する機能を構造体と言

います struct 構造体タグ名 構造体メンバーの並び

「struct」は構造体を表すキーワードです 「構造体タグ名」は構造体の型枠を宣言しますここは自由に名前を定義することができ ます 「構造体メンバーの並び」は構造体の要素です複数指定できます

個人の住所録のデータを構造体で宣言すると次のようになります

struct jusho char name[30] char address[30] 構造体のメンバーの並び char tel[20] (複数可)

int age

上記の宣言では構造体の形式を宣言しているだけでメモリ中で実際の領域を確保している

わけではありません実際に領域を確保するためには次のように定義します

struct 構造体タグ名 構造体名

したがって構造体名を jdata とすると次のように指定します

struct jusho jdata

構造体 jdataは次のように構造体タグ jushoの形式で領域を確保します

24

Jdata name[30]

address[30] tel[20] age

(1)構造体の参照

プログラム中で構造体中のメンバーを参照する場合には次のように指定します 構造体名メンバー名

したがって「名前」を参照したいときには次のように指定します

jdataname

[プログラム例]

名前住所電話番号年齢を定義しそれを印字します include ltstdiohgt include ltstringhgt main() struct jusho char name[30] char address[30] char tel[20] int age struct jusho jdata strcpy( jdataname 東海 太郎) strcpy( jdataaddress 平塚市北金目1117)

strcpy( jdatatel 0463-58-1211) jdataage = 30 printf(yenn氏名 = syenn jdataname) printf(yenn住所 = syenn jdataaddress) printf(yenn電話番号= syenn jdatatel) printf(yenn年齢 = dyenn jdataage)

また構造体の形式の定義と領域の確保は次のように同時におこなうことができます

struct 構造体タグ名 構造体メンバーの並び 構造体名

struct jusho struct jusho char name[30] char name[30] char address[30] char address[30] char tel[30] = char tel[30] int age 同じ int age

jdata struct jusho jdata

型宣言と同時にメモリ上に領域を確保する方法 後からメモリ上に領域を確保する方法

25

(2) 構造体配列 住所録データの場合その中に入るデータは1件ではありませんやはり100件200件のデ

ータが必要になる場合がありますこのように個人単位のデータを多数扱う場合には構造体を配

列として宣言することができます 次の例は個人のデータを100個用意するために構造体を配列として宣言しています struct jusho jdata[100] jdata[0] name[30] address[30] tel[20] age

jdata[99 ] name[30] address[30] tel[20] age

(3)構造体配列の参照

プログラム中で構造体配列中のメンバーを参照する場合には次のように指定します 構造体名[要素番号]メンバー名

したがって10件目の人の「名前」を参照したいときには次のように指定します

jdata[10]name

[プログラム例]

名前住所電話番号年齢を定義しそれを印字します include ltstdiohgt include ltstringhgt main() struct jusho char name[30] char address[30] char tel[20] int age jdata[100] strcpy( jdata[10]name 東海 太郎) strcpy( jdata[10]address 平塚市北金目1117)

strcpy( jdata[10]tel 0463-58-1211) jdata[10]age = 30 printf(yenn氏名 = syenn jdata[10]name) printf(yenn住所 = syenn jdata[10]address) printf(yenn電話番号= syenn jdata[10]tel) printf(yenn年齢 = dyenn jdata[10]age)

26

(4) 構造体のポインタ 変数と同じように構造体へのポインタも定義することができます

変数へのポインタ例 構造体へのポインタ例 またポインタを使用して構造体メンバーを参照するには次のように -> 記号を使って指

定します ポインタ変数名 -> メンバー名

[プログラム例]

名前住所電話番号年齢を定義しそれを印字します include ltstdiohgt include ltstringhgt main() struct jusho char name[30] char address[30] char tel[20] int age jdatakp kp = ampjdata strcpy( kp-gtname 東海 太郎)

strcpy( kp-gtaddress 平塚市北金目1117)

strcpy( kp-gttel 0463-58-1211) kp-gtage = 30 printf(yenn氏名 = syenn kp-gtname) printf(yenn住所 = syenn kp-gtaddress) printf(yenn電話番号= syenn kp-gttel) printf(yenn年齢 = dyenn kp-gtage)

kp jdata

name[30] ポインタ型の変数 address[30]

tel[20]

構造体へのポインタを記憶 age

することができます

int a int b b = ampa

struct name jname struct name np np = ampname

27

7-2 共用体 共用体は構造体と同じようにして宣言しますが共用体は複数のデータ型を同一のアドレスに

割り当てる方法です union 共用体タグ名 共用体メンバーの並び

「union」は共用体を表すキーワードです 「共用体タグ名」は共用体の型枠の名前を宣言しますここは自由に名前を定義することがで

きます 「共用体メンバーの並び」は共用体の要素です複数指定できます

共用体の宣言の例を次に示します

union c_tag int a char b

共用体 cは次のように共用体タグ c_tagの形式で領域を確保します共用体はメモリ上に領域を確保するときは ab ともに同じ領域に割り付けられます これはab という2つのデータが同時に存在するわけではなく cを異なるデータ abで共有す

ることを表しています c a b

上記の宣言だけでは共用体の形式を宣言しているだけでメモリ中で実際の領域を確保して

いるわけではありません実際に領域を確保するためには次のように定義します union 構造体タグ名 構造体名

したがって共用体名を c とすると次のように指定します

union c_tag c

(1)共用体の参照

プログラム中で共用体中のメンバーを参照する場合には次のように指定します 共用体名メンバー名

したがって「a」または「b」を参照したいときには次のように指定します

ca (int 型) cb (char 型)

メンバー参照方法によって int型として使ったりchar型として利用することができます

28

[プログラム例]

includeltstdiohgt main() union data char a short b int c chk chkc = 0x12345678 printf( char a xyennchka) printf( short b xyennchkb) printf( int c xyennchkc)

chkb(int 型) chkb(short 型) chka(char 型) 12 12 12 34 34 56 78

29

第8章 アルゴリズム コンピュータに何か仕事をさせようとするときは仕事を具体的に実行するための処理や動作

の手順が必要ですこの「手順」がアルゴリズムです アルゴリズムを考えるときは解くべき問題をはっきりと定義することが必要です

8-1 ソート ソートとは与えられたデータを小さい順または大きい順に並べ換えることですソート方法は

いくつかありますが基本的な方法でソートするアルゴリズムを紹介します

includeltstdiohgt int data[10] main()

int data_in() sort() data_in() sort() int data_in() データ入力関数

int a printf(数値入力yenn)

for(a=0alt=9a++) printf( [d]a+1) scanf(dampdata[a]) int sort() ソート処理を行う関数

int cont1cont2tmp1tmp2mim for(cont1=0 cont1lt=9 cont1++) mim=data[cont1] tmp1=cont1 for(cont2=cont1+1 cont2lt=9 cont2++) if(data[cont2] lt mim) mim=data[cont2] tmp1=cont2 tmp2 = data[cont1] data[cont1] = data[tmp1] data[tmp1] = tmp2 printf(結果 yenn)

for (cont1 = 0 cont1 lt= 9 cont1++) printf(d yenn data[cont1])

30

第9章 プリプロセッサ C言語にはプログラムの中でコンパイルについての指示を行う「プリプロセッサ」という機能が

ありますまたプリプロセッサとはコンパイルする前に実行されるためその意味のとおり「前処理」 と呼ばれていますここでは代表的なものをいくつか説明します

9-1 ファイルの挿入 ソースプログラム中に指定されたファイルを挿入します

include ltstdiohgt helliphellip 標準ディレクトリを探します include progh helliphellip 現在のディレクトリを探しなければ標準ディレクトリを探します

includeltstdiohgt によって組み込まれた define EOF (-1) define EOF (-1) define define helliphelliphelliphellip 組み込み helliphelliphelliphellip

main() stdiohファイル

int helliphelliphelliphellip helliphelliphelliphellip

ソースファイル

9-2 文字の置換 プログラム中に使われている文字列を別の文字列に置き換えます

include ltstdiohgt define TRUE 1 define EOF (-1) main() define helliphellip helliphellip

while(TRUE) define TRUE 1 置き換え main() helliphellip helliphellip while(1)

break helliphelliphellip

31

9-3 条件によるコンパイル 識別子が定義されているか否かを判断しコンパイルする範囲を指定します

include ltstdiohgt define UNIX main() ifdef UNIX printf( UNIX yenn) else printf(MS-DOSyenn) endif

include ltstdiohgt define OS UNIX main() if OS == UNIX printf( UNIX yenn) else printf(MS-DOSyenn) endif

32

付 録 1 puts()gets()関数について

行単位に入出力を行う場合には puts() gets() 関数を用います

puts() 標準出力に文字列を出力します

include ltstdiohgt int puts( char s ) puts() は NULL で終る文字列 s を標準出力に出力し最後に改行文字 yenn も出力しま

gets() 標準入力から文字列を入力します

include ltstdiohgt char gets( char s ) 戻り値正常に入力した場合には引数 s の値が返されますエラーやEOFになった場合に

は NULL が返されます gets() は標準入力から復帰文字で終る文字列を入力しs に格納しますこのとき最後の復

帰文字は NULL文字に変更されます

入力行の出力 標準入力から gets() で入力したデータには改行コードは含まれませんまた標準出力へ

puts() で出力を行う場合には必ず改行コードが付加されますgets() を実行したときの戻り値としてファイルの終端を検出した場合には EOF ではなく NULL が返されますので注意して下さい

include ltstdiohgt main() char data[80] while( gets( data ) = NULL )puts( data )

putchar()getchar()関数について putchar() 標準出力に文字を出力します

include ltstdiohgt int putchar(int c ) 戻り値正常に出力できた場合には文字cをエラーの場合にはEOFを返します

33

getchar() 標準入力から文字を入力します

include ltstdiohgt int getchar(void) 戻り値正常に入力した場合には読み込んだ文字を int 型に変換して返しますまたファイ

ルエンドエラーの場合にはEOFを返します

標準入力標準出力

標準入力標準出力はプログラムが開始されるときにはオープンされていますそれぞれのフ

ァイルポインタは stdin stdout になっていますfopen() fclose() をせずとも使用することができます

scanf() 標準出力ストリームからテキストを読み込み解釈します include ltstdiohgt int scanf( const char format [ address ] ) 戻り値正しくスキャンし変換し格納した入力フィールドの数を返しますファイルエンドを読

み込んだ場合は戻り値は EOF となります値を格納したフィールドがなかった場合は戻り値は0となります

一連の入力フィールドをスキャンして1度に1文字ずつストリーム stdin から文字を読み込み

ます次に引き数 format によって指される書式文字列中の書式指定に従って各フィールドを書式化します最後にformat の後に続く各引き数が示しているアドレスに書式化した入力を格納していきます書式文字列中の書式指定の個数はその後に続くアドレスの数と同じでな

ければなりません 書式指定[入力幅][型指定文字] 入力幅 読むべき文字数の最大値 型指定文字 次のとおりです 型指定文字 期待される入力 引き数の型 d 10進整数 int へのポインタ( int arg ) x 16進整数 int へのポインタ( int arg ) f 浮動小数点数 float へのポインタ( float arg ) s 文字列 文字配列へのポインタ( char arg[] ) c 文字 文字へのポインタ( char arg )

printf() フォーマットを指定してテキスト標準出力ストリームに出力します include ltstdiohgt int printf( const char format [ argument ] ) 戻り値出力したバイト数を返しますエラーの場合は EOF を返します

34

format によって指される書式文字列中の書式指定をformat の後に続く各引き数に適用し

書式化されたデータを stdout に出力します書式指定は後に続く引き数と同じ数だけなければなりません

書式指定[印字幅][精度][型指定文字] 印字幅 印字する最小文字数 精度 印字する最大文字数 型指定文字 つぎのとおりです 型指定文字 入力引き数 出力の書式 d 整数 符号付き10進整数 x 整数 符号無し16進整数 f 浮動小数点 符号付きの dddddddd形式の値 c 文字 1個の文字 s 文字列ポインタ ヌル文字に出会うか精度に達するまで 文字をプリントする

fopen()fclose()関数について fopen() ファイルをオープンします

include ltstdiohgt FILE fopen( char filename char mode ) 戻り値正常にファイルのオープンができたらファイルポインタを返しますエラーがあった場

合には NULLを返します 文字列 filename で指定されたファイルをオープンしますオープン後の入出力のモードに

ついては文字列 mode で指定しますmode に指定できる文字は以下のとおりです r 入力モードでオープンします w 出力モードでオープンします a 存在するファイルに追加して出力するモードでオープンします r+ 既に作成してあるファイルを更新(入力出力)するモードでオープンします w+ 新しく作成するファイルを更新モードでオープンします a+ 既に作成してあるファイルの終りから更新用に作成します

以上の文字に b をつけ加えることによりバイナリモードで入出力することができるようになり

ます rb バイナリの入力モードでオープンします wb バイナリの出力モードでオープンします ab 存在するファイルに追加して出力するモード(バイナリ)でオープンします

fclose() 既にオープンしてあるファイルをクローズします include ltstdiohgt fclose( FILE fp ) 既にオープンしているファイルをクローズしますパラメータには fopen() 関数により返された

ファイルポインタを指定します

35

テキストモードとバイナリモード 行の最後はテキストモードの場合改行コードのみとなりバイナリモードの場合には復帰

コードと改行コードの組合わせになります行の最後としてテキストファイルには復帰コード改行

コードが書かれていますがテキストモードでオープンした場合には入力すると改行コードのみに

変換されて入力されますバイナリモードの場合には復帰コード改行コードがそれぞれ入力され

ます

fputs()fgets()関数について fputs() ファイルポインタで指定されるファイルに文字列を出力します

include ltstdiohgt

int fputs( char s FILE fp ) fputs() は NULL で終る文字列 s をファイルポインタに示されるファイルへ出力しますputs()

と違い最後に改行文字 yenn を出力することはありません

fgets() ファイルポインタで指定されるファイルから文字列を入力します include ltstdiohgt char fgets( char s int n FILE fp ) 戻り値正常に入力した場合には引数 s の値が返されますエラーやEOFになった場合に

は NULL が返されます fgets() はファイルポインタで指定されるファイルから ( n - 1 ) 文字または改行文字までの

文字列を入力しs に格納しますgets() と異なり最後に入力された改行文字は NULL 文字に変更されません

標準入力から入力しファイルへ出力する ファイルへ出力あるいは入力を行う場合には改行コードの変換(入力の場合の削除出力の

場合の付加)はされませんしたがって標準入力から入力しファイルへ出力する場合には改行

コードを付加しなければなりません include ltstdiohgt main() char data[80] FILE fp fp = fopen( data w ) while( gets( data ) = NULL ) strcat( data yenn ) 改行コードの付加

fputs( data fp ) fclose( fp )

36

fputc()fgetc()関数について fputc() ファイルポインタで指定されるファイルに1文字出力します

include ltstdiohgt int fputc( int c FILE fp ) 戻り値正常に出力できた場合には文字 c を返しエラーの場合には EOF を返します fputc() は文字 c をファイルポインタで示されるファイルへ出力します

fgetc() ファイルポインタで指定されるファイルから1文字入力します

include ltstdiohgt int fgetc( FILE fp ) 戻り値正常に入力した場合には入力した文字を返しますエラーやEOFになった場合には

EOF が返されます fgetc() はファイルポインタで指定されるファイルから文字を入力します

ファイルの内容の表示 include ltstdiohgt main() FILE fp int ch char fname[30] printf( Key in Fila name gt ) gets( fname ) fp = fopen( fname r ) while( ( ch = fgetc( fp ) ) = EOF )putchar( ch ) fclose( fp )

その他テキスト中で使用された関数について sin() 三角関数の正弦を計算します

include ltmathhgt double sin(double radian) sinはラジアンを単位とする引数 radianの三角関数を計算します

37

strcpy() 文字列を他の文字列へコピーします

include ltstringhgt char strcpy(char string1const char string2) strcpyは引数 string2の指す文字列を null文字まで含めて引数 string1の指す領域にコピ

ーする strcpyは string1を返します

strcat() ある文字列を他の文字列に加えます

include ltstringhgt char strcat( char dest const char src ) 戻り値連結された文字列へのポインタを返します strcat() はsrc のコピーを dest の最後につけ加えます得られる文字列の長さは

strlen(dest)+strlen(src) になります

fabs() 絶対値の計算をします include ltmathhgt double fabs(double z) fabsは倍精度浮動小数の絶対値を計算して返しますつまりzgt=0であれば z をzlt0であ

れば-zを返します exp() 指数関数を計算します

include ltmathhgt double exp(double z) exp は引数zの指数関数つまりezを返すここではeは自然対数の底を表します対数関

数logの逆関数です

38

付 録 2 コンパイルの方法には大きく分けて第4章の実習で学んだようにデータファイルを作成してお

き ccg でコンパイルさせる方法と実行中に対話型でデータを入力していく方法があります ここでは対話型で実行を進めていく方法を紹介します ただしこの方法は計算(cpu)時間が10秒以内のものに限ります10秒を超える計算(cpu)時

間を要する場合はccg でコンパイルをするようにしてください 第4章実習の(2)(p16)までは同様です

コンパイル

コンピュータに処理を依頼します 60us1234boseicc cc rensyuc

所有するファイルの一覧を見てみます

60us1234boseicc ls -l larr 持っているファイルの一覧を見るコマンドです

-rw-r--r-- 1 60us1234 other 128 4月26日 15時14分 rensyuc -rwxr-xr-x 1 60us1234 other 361 4月26日 15時16分 aout

aout という実行形式のファイルが作成されています

実行

60us1234boseicc aout12 35[リターン] データを入力

1 200000 3500000 4200000 実行結果の出力

60us1234boseicc

注意

aout ファイルは印刷することができません実行結果を印刷する場合にはファイルに落とし てから出力するようにしましょう

60us1234boseicc aout gt kekka12 35[リターン] データを入力

60us1234boseicc more kekka 計算結果の確認 60us1234boseicc lpr kekka 計算結果の印刷

39

Page 23: n 第1章 章立ての部分は、書式(PC入門大見出し)を …第2章 数の表現 2-1 2進数 電子計算機の動作原理は0と1で表される2進数です。また、人間が日常生活で扱っている数

include ltstdiohgt main() int a b c a はポインタ型の変数b c は整数型の変数 b = 12 変数 b に値 12 を代入します a = ampb 変数 a には変数 b の番地が代入されます c = a + 10 変数 a の指す変数(b)の内容と10の加算です つまり12 + 10 を変数 c に代入します

変数の型宣言において変数名に記号を付けることによりその変数はポインタ型の変数と

なりますポインタ型の変数は変数名のみを指定した場合には単にその変数の値(通常はメモリ

の番地)を表します変数名に記号を付けて使用した場合にはその変数が指し示している変

数の内容を表します c = a ポインタ型変数 a が指している値を変数 c に代入

ポインタ型の変数に番地を記憶させるためにはプログラム例のように変数名の前に記号を

指定します変数名 によって変数の番地(アドレス)を表します a = ampb 変数 b の番地をポインタ型変数 a に代入します

ポインタ型変数の型はポインタ型変数が指し示す先の変数の型を表しています int a 変数 a 整数型の値 float x 変数 x 実数型の値 char c 変数 c 文字型の値

6-2 ポインタ型変数の初期化 ポインタ型変数も型宣言のときに変数を初期化することができます特に文字型のポインタ変

数の場合によく使います char str = TOKAI University

ポインタ型変数 str は文字列定数 TOKAI University の最初の文字が格納されている番地を初期値として持つことになります

変数 str TOKAI University 文字列定数

[プログラム例]

(1)文字型配列 putchar() 関数を使って一次元の文字型配列を出力します include ltstdiohgt main() char str[6] = TOKAI int i for( i = 0 str[i] = yen0 i++ ) putchar( str[i] )

21

ポインタを使用した場合には以下のようになります include ltstdiohgt main() char str[6] = TOKAI char chp for( chp = str chp = yen0 chp++ ) putchar( chp )

chp str T [0] O K A I yen0 [5]

参照する変数 配列の表現 ポインタの表現 実際のアドレス 1番目の数 str[0] chp CHP 2番目の数 str[1] (chp+1) CHP+1 n番目の数 str[n-1] (chp+n-1) CHP+n-1 6番目の数 str[5] (chp+5) CHP+5

注意実際のアドレス CHPは実行時に決定されます

(2)二次元文字型配列 二次元の文字型配列に定数を設定しそれを出力するプログラムです文字型配列を使用す

ると次のとおりになります include ltstdiohgt main() char str[5][40] = TOKAI shounan campus NEC DEC int i for( i = 0 i lt 5 i++ ) printf( yenns str[i] )

40 バイト str TOKAI shounan campus NEC DEC

22

ポインタ型配列を使用すると次のとおりになります include ltstdiohgt main() char str[6] = TOKAI shounan campus NEC DEC NULL char chp for( chp = str chp = NULL chp++ ) printf( yenns chp ) str

chp 番地 TOKAI 番地 shounan 番地 campus 番地 NEC 番地 DEC

NULL

演習8 キーボードまたはデータファイルから読み込んだ文字列中にrsquoArsquo があったら rsquoarsquo に変換 するプログラムを配列とポインタを使って書きなさい

23

第7章 構造体共用体 7-1 構造体

プログラムの規模が大きくなるにつれて多数の intや floatcharなどのデータ型を扱うようになり複雑になってきますそこで多数のデータを1つにまとめて簡単に扱える機能が構造体です 構造体について住所録のデータを例にあげて考えてみます

住所録の個人データとして氏名住所電話番号年齢の項目を一つのデータとします これをC言語で変数の定義をすると次のようになります 氏名東海太郎 char name[30] 住所平塚市北金目1117 char address[30] 電話番号0463-58-1211 char tel[20] 年齢30 int age 個人の住所録データ C言語での表現 このような住所録の個人データを1つにまとめて新しいデータとして定義する機能を構造体と言

います struct 構造体タグ名 構造体メンバーの並び

「struct」は構造体を表すキーワードです 「構造体タグ名」は構造体の型枠を宣言しますここは自由に名前を定義することができ ます 「構造体メンバーの並び」は構造体の要素です複数指定できます

個人の住所録のデータを構造体で宣言すると次のようになります

struct jusho char name[30] char address[30] 構造体のメンバーの並び char tel[20] (複数可)

int age

上記の宣言では構造体の形式を宣言しているだけでメモリ中で実際の領域を確保している

わけではありません実際に領域を確保するためには次のように定義します

struct 構造体タグ名 構造体名

したがって構造体名を jdata とすると次のように指定します

struct jusho jdata

構造体 jdataは次のように構造体タグ jushoの形式で領域を確保します

24

Jdata name[30]

address[30] tel[20] age

(1)構造体の参照

プログラム中で構造体中のメンバーを参照する場合には次のように指定します 構造体名メンバー名

したがって「名前」を参照したいときには次のように指定します

jdataname

[プログラム例]

名前住所電話番号年齢を定義しそれを印字します include ltstdiohgt include ltstringhgt main() struct jusho char name[30] char address[30] char tel[20] int age struct jusho jdata strcpy( jdataname 東海 太郎) strcpy( jdataaddress 平塚市北金目1117)

strcpy( jdatatel 0463-58-1211) jdataage = 30 printf(yenn氏名 = syenn jdataname) printf(yenn住所 = syenn jdataaddress) printf(yenn電話番号= syenn jdatatel) printf(yenn年齢 = dyenn jdataage)

また構造体の形式の定義と領域の確保は次のように同時におこなうことができます

struct 構造体タグ名 構造体メンバーの並び 構造体名

struct jusho struct jusho char name[30] char name[30] char address[30] char address[30] char tel[30] = char tel[30] int age 同じ int age

jdata struct jusho jdata

型宣言と同時にメモリ上に領域を確保する方法 後からメモリ上に領域を確保する方法

25

(2) 構造体配列 住所録データの場合その中に入るデータは1件ではありませんやはり100件200件のデ

ータが必要になる場合がありますこのように個人単位のデータを多数扱う場合には構造体を配

列として宣言することができます 次の例は個人のデータを100個用意するために構造体を配列として宣言しています struct jusho jdata[100] jdata[0] name[30] address[30] tel[20] age

jdata[99 ] name[30] address[30] tel[20] age

(3)構造体配列の参照

プログラム中で構造体配列中のメンバーを参照する場合には次のように指定します 構造体名[要素番号]メンバー名

したがって10件目の人の「名前」を参照したいときには次のように指定します

jdata[10]name

[プログラム例]

名前住所電話番号年齢を定義しそれを印字します include ltstdiohgt include ltstringhgt main() struct jusho char name[30] char address[30] char tel[20] int age jdata[100] strcpy( jdata[10]name 東海 太郎) strcpy( jdata[10]address 平塚市北金目1117)

strcpy( jdata[10]tel 0463-58-1211) jdata[10]age = 30 printf(yenn氏名 = syenn jdata[10]name) printf(yenn住所 = syenn jdata[10]address) printf(yenn電話番号= syenn jdata[10]tel) printf(yenn年齢 = dyenn jdata[10]age)

26

(4) 構造体のポインタ 変数と同じように構造体へのポインタも定義することができます

変数へのポインタ例 構造体へのポインタ例 またポインタを使用して構造体メンバーを参照するには次のように -> 記号を使って指

定します ポインタ変数名 -> メンバー名

[プログラム例]

名前住所電話番号年齢を定義しそれを印字します include ltstdiohgt include ltstringhgt main() struct jusho char name[30] char address[30] char tel[20] int age jdatakp kp = ampjdata strcpy( kp-gtname 東海 太郎)

strcpy( kp-gtaddress 平塚市北金目1117)

strcpy( kp-gttel 0463-58-1211) kp-gtage = 30 printf(yenn氏名 = syenn kp-gtname) printf(yenn住所 = syenn kp-gtaddress) printf(yenn電話番号= syenn kp-gttel) printf(yenn年齢 = dyenn kp-gtage)

kp jdata

name[30] ポインタ型の変数 address[30]

tel[20]

構造体へのポインタを記憶 age

することができます

int a int b b = ampa

struct name jname struct name np np = ampname

27

7-2 共用体 共用体は構造体と同じようにして宣言しますが共用体は複数のデータ型を同一のアドレスに

割り当てる方法です union 共用体タグ名 共用体メンバーの並び

「union」は共用体を表すキーワードです 「共用体タグ名」は共用体の型枠の名前を宣言しますここは自由に名前を定義することがで

きます 「共用体メンバーの並び」は共用体の要素です複数指定できます

共用体の宣言の例を次に示します

union c_tag int a char b

共用体 cは次のように共用体タグ c_tagの形式で領域を確保します共用体はメモリ上に領域を確保するときは ab ともに同じ領域に割り付けられます これはab という2つのデータが同時に存在するわけではなく cを異なるデータ abで共有す

ることを表しています c a b

上記の宣言だけでは共用体の形式を宣言しているだけでメモリ中で実際の領域を確保して

いるわけではありません実際に領域を確保するためには次のように定義します union 構造体タグ名 構造体名

したがって共用体名を c とすると次のように指定します

union c_tag c

(1)共用体の参照

プログラム中で共用体中のメンバーを参照する場合には次のように指定します 共用体名メンバー名

したがって「a」または「b」を参照したいときには次のように指定します

ca (int 型) cb (char 型)

メンバー参照方法によって int型として使ったりchar型として利用することができます

28

[プログラム例]

includeltstdiohgt main() union data char a short b int c chk chkc = 0x12345678 printf( char a xyennchka) printf( short b xyennchkb) printf( int c xyennchkc)

chkb(int 型) chkb(short 型) chka(char 型) 12 12 12 34 34 56 78

29

第8章 アルゴリズム コンピュータに何か仕事をさせようとするときは仕事を具体的に実行するための処理や動作

の手順が必要ですこの「手順」がアルゴリズムです アルゴリズムを考えるときは解くべき問題をはっきりと定義することが必要です

8-1 ソート ソートとは与えられたデータを小さい順または大きい順に並べ換えることですソート方法は

いくつかありますが基本的な方法でソートするアルゴリズムを紹介します

includeltstdiohgt int data[10] main()

int data_in() sort() data_in() sort() int data_in() データ入力関数

int a printf(数値入力yenn)

for(a=0alt=9a++) printf( [d]a+1) scanf(dampdata[a]) int sort() ソート処理を行う関数

int cont1cont2tmp1tmp2mim for(cont1=0 cont1lt=9 cont1++) mim=data[cont1] tmp1=cont1 for(cont2=cont1+1 cont2lt=9 cont2++) if(data[cont2] lt mim) mim=data[cont2] tmp1=cont2 tmp2 = data[cont1] data[cont1] = data[tmp1] data[tmp1] = tmp2 printf(結果 yenn)

for (cont1 = 0 cont1 lt= 9 cont1++) printf(d yenn data[cont1])

30

第9章 プリプロセッサ C言語にはプログラムの中でコンパイルについての指示を行う「プリプロセッサ」という機能が

ありますまたプリプロセッサとはコンパイルする前に実行されるためその意味のとおり「前処理」 と呼ばれていますここでは代表的なものをいくつか説明します

9-1 ファイルの挿入 ソースプログラム中に指定されたファイルを挿入します

include ltstdiohgt helliphellip 標準ディレクトリを探します include progh helliphellip 現在のディレクトリを探しなければ標準ディレクトリを探します

includeltstdiohgt によって組み込まれた define EOF (-1) define EOF (-1) define define helliphelliphelliphellip 組み込み helliphelliphelliphellip

main() stdiohファイル

int helliphelliphelliphellip helliphelliphelliphellip

ソースファイル

9-2 文字の置換 プログラム中に使われている文字列を別の文字列に置き換えます

include ltstdiohgt define TRUE 1 define EOF (-1) main() define helliphellip helliphellip

while(TRUE) define TRUE 1 置き換え main() helliphellip helliphellip while(1)

break helliphelliphellip

31

9-3 条件によるコンパイル 識別子が定義されているか否かを判断しコンパイルする範囲を指定します

include ltstdiohgt define UNIX main() ifdef UNIX printf( UNIX yenn) else printf(MS-DOSyenn) endif

include ltstdiohgt define OS UNIX main() if OS == UNIX printf( UNIX yenn) else printf(MS-DOSyenn) endif

32

付 録 1 puts()gets()関数について

行単位に入出力を行う場合には puts() gets() 関数を用います

puts() 標準出力に文字列を出力します

include ltstdiohgt int puts( char s ) puts() は NULL で終る文字列 s を標準出力に出力し最後に改行文字 yenn も出力しま

gets() 標準入力から文字列を入力します

include ltstdiohgt char gets( char s ) 戻り値正常に入力した場合には引数 s の値が返されますエラーやEOFになった場合に

は NULL が返されます gets() は標準入力から復帰文字で終る文字列を入力しs に格納しますこのとき最後の復

帰文字は NULL文字に変更されます

入力行の出力 標準入力から gets() で入力したデータには改行コードは含まれませんまた標準出力へ

puts() で出力を行う場合には必ず改行コードが付加されますgets() を実行したときの戻り値としてファイルの終端を検出した場合には EOF ではなく NULL が返されますので注意して下さい

include ltstdiohgt main() char data[80] while( gets( data ) = NULL )puts( data )

putchar()getchar()関数について putchar() 標準出力に文字を出力します

include ltstdiohgt int putchar(int c ) 戻り値正常に出力できた場合には文字cをエラーの場合にはEOFを返します

33

getchar() 標準入力から文字を入力します

include ltstdiohgt int getchar(void) 戻り値正常に入力した場合には読み込んだ文字を int 型に変換して返しますまたファイ

ルエンドエラーの場合にはEOFを返します

標準入力標準出力

標準入力標準出力はプログラムが開始されるときにはオープンされていますそれぞれのフ

ァイルポインタは stdin stdout になっていますfopen() fclose() をせずとも使用することができます

scanf() 標準出力ストリームからテキストを読み込み解釈します include ltstdiohgt int scanf( const char format [ address ] ) 戻り値正しくスキャンし変換し格納した入力フィールドの数を返しますファイルエンドを読

み込んだ場合は戻り値は EOF となります値を格納したフィールドがなかった場合は戻り値は0となります

一連の入力フィールドをスキャンして1度に1文字ずつストリーム stdin から文字を読み込み

ます次に引き数 format によって指される書式文字列中の書式指定に従って各フィールドを書式化します最後にformat の後に続く各引き数が示しているアドレスに書式化した入力を格納していきます書式文字列中の書式指定の個数はその後に続くアドレスの数と同じでな

ければなりません 書式指定[入力幅][型指定文字] 入力幅 読むべき文字数の最大値 型指定文字 次のとおりです 型指定文字 期待される入力 引き数の型 d 10進整数 int へのポインタ( int arg ) x 16進整数 int へのポインタ( int arg ) f 浮動小数点数 float へのポインタ( float arg ) s 文字列 文字配列へのポインタ( char arg[] ) c 文字 文字へのポインタ( char arg )

printf() フォーマットを指定してテキスト標準出力ストリームに出力します include ltstdiohgt int printf( const char format [ argument ] ) 戻り値出力したバイト数を返しますエラーの場合は EOF を返します

34

format によって指される書式文字列中の書式指定をformat の後に続く各引き数に適用し

書式化されたデータを stdout に出力します書式指定は後に続く引き数と同じ数だけなければなりません

書式指定[印字幅][精度][型指定文字] 印字幅 印字する最小文字数 精度 印字する最大文字数 型指定文字 つぎのとおりです 型指定文字 入力引き数 出力の書式 d 整数 符号付き10進整数 x 整数 符号無し16進整数 f 浮動小数点 符号付きの dddddddd形式の値 c 文字 1個の文字 s 文字列ポインタ ヌル文字に出会うか精度に達するまで 文字をプリントする

fopen()fclose()関数について fopen() ファイルをオープンします

include ltstdiohgt FILE fopen( char filename char mode ) 戻り値正常にファイルのオープンができたらファイルポインタを返しますエラーがあった場

合には NULLを返します 文字列 filename で指定されたファイルをオープンしますオープン後の入出力のモードに

ついては文字列 mode で指定しますmode に指定できる文字は以下のとおりです r 入力モードでオープンします w 出力モードでオープンします a 存在するファイルに追加して出力するモードでオープンします r+ 既に作成してあるファイルを更新(入力出力)するモードでオープンします w+ 新しく作成するファイルを更新モードでオープンします a+ 既に作成してあるファイルの終りから更新用に作成します

以上の文字に b をつけ加えることによりバイナリモードで入出力することができるようになり

ます rb バイナリの入力モードでオープンします wb バイナリの出力モードでオープンします ab 存在するファイルに追加して出力するモード(バイナリ)でオープンします

fclose() 既にオープンしてあるファイルをクローズします include ltstdiohgt fclose( FILE fp ) 既にオープンしているファイルをクローズしますパラメータには fopen() 関数により返された

ファイルポインタを指定します

35

テキストモードとバイナリモード 行の最後はテキストモードの場合改行コードのみとなりバイナリモードの場合には復帰

コードと改行コードの組合わせになります行の最後としてテキストファイルには復帰コード改行

コードが書かれていますがテキストモードでオープンした場合には入力すると改行コードのみに

変換されて入力されますバイナリモードの場合には復帰コード改行コードがそれぞれ入力され

ます

fputs()fgets()関数について fputs() ファイルポインタで指定されるファイルに文字列を出力します

include ltstdiohgt

int fputs( char s FILE fp ) fputs() は NULL で終る文字列 s をファイルポインタに示されるファイルへ出力しますputs()

と違い最後に改行文字 yenn を出力することはありません

fgets() ファイルポインタで指定されるファイルから文字列を入力します include ltstdiohgt char fgets( char s int n FILE fp ) 戻り値正常に入力した場合には引数 s の値が返されますエラーやEOFになった場合に

は NULL が返されます fgets() はファイルポインタで指定されるファイルから ( n - 1 ) 文字または改行文字までの

文字列を入力しs に格納しますgets() と異なり最後に入力された改行文字は NULL 文字に変更されません

標準入力から入力しファイルへ出力する ファイルへ出力あるいは入力を行う場合には改行コードの変換(入力の場合の削除出力の

場合の付加)はされませんしたがって標準入力から入力しファイルへ出力する場合には改行

コードを付加しなければなりません include ltstdiohgt main() char data[80] FILE fp fp = fopen( data w ) while( gets( data ) = NULL ) strcat( data yenn ) 改行コードの付加

fputs( data fp ) fclose( fp )

36

fputc()fgetc()関数について fputc() ファイルポインタで指定されるファイルに1文字出力します

include ltstdiohgt int fputc( int c FILE fp ) 戻り値正常に出力できた場合には文字 c を返しエラーの場合には EOF を返します fputc() は文字 c をファイルポインタで示されるファイルへ出力します

fgetc() ファイルポインタで指定されるファイルから1文字入力します

include ltstdiohgt int fgetc( FILE fp ) 戻り値正常に入力した場合には入力した文字を返しますエラーやEOFになった場合には

EOF が返されます fgetc() はファイルポインタで指定されるファイルから文字を入力します

ファイルの内容の表示 include ltstdiohgt main() FILE fp int ch char fname[30] printf( Key in Fila name gt ) gets( fname ) fp = fopen( fname r ) while( ( ch = fgetc( fp ) ) = EOF )putchar( ch ) fclose( fp )

その他テキスト中で使用された関数について sin() 三角関数の正弦を計算します

include ltmathhgt double sin(double radian) sinはラジアンを単位とする引数 radianの三角関数を計算します

37

strcpy() 文字列を他の文字列へコピーします

include ltstringhgt char strcpy(char string1const char string2) strcpyは引数 string2の指す文字列を null文字まで含めて引数 string1の指す領域にコピ

ーする strcpyは string1を返します

strcat() ある文字列を他の文字列に加えます

include ltstringhgt char strcat( char dest const char src ) 戻り値連結された文字列へのポインタを返します strcat() はsrc のコピーを dest の最後につけ加えます得られる文字列の長さは

strlen(dest)+strlen(src) になります

fabs() 絶対値の計算をします include ltmathhgt double fabs(double z) fabsは倍精度浮動小数の絶対値を計算して返しますつまりzgt=0であれば z をzlt0であ

れば-zを返します exp() 指数関数を計算します

include ltmathhgt double exp(double z) exp は引数zの指数関数つまりezを返すここではeは自然対数の底を表します対数関

数logの逆関数です

38

付 録 2 コンパイルの方法には大きく分けて第4章の実習で学んだようにデータファイルを作成してお

き ccg でコンパイルさせる方法と実行中に対話型でデータを入力していく方法があります ここでは対話型で実行を進めていく方法を紹介します ただしこの方法は計算(cpu)時間が10秒以内のものに限ります10秒を超える計算(cpu)時

間を要する場合はccg でコンパイルをするようにしてください 第4章実習の(2)(p16)までは同様です

コンパイル

コンピュータに処理を依頼します 60us1234boseicc cc rensyuc

所有するファイルの一覧を見てみます

60us1234boseicc ls -l larr 持っているファイルの一覧を見るコマンドです

-rw-r--r-- 1 60us1234 other 128 4月26日 15時14分 rensyuc -rwxr-xr-x 1 60us1234 other 361 4月26日 15時16分 aout

aout という実行形式のファイルが作成されています

実行

60us1234boseicc aout12 35[リターン] データを入力

1 200000 3500000 4200000 実行結果の出力

60us1234boseicc

注意

aout ファイルは印刷することができません実行結果を印刷する場合にはファイルに落とし てから出力するようにしましょう

60us1234boseicc aout gt kekka12 35[リターン] データを入力

60us1234boseicc more kekka 計算結果の確認 60us1234boseicc lpr kekka 計算結果の印刷

39

Page 24: n 第1章 章立ての部分は、書式(PC入門大見出し)を …第2章 数の表現 2-1 2進数 電子計算機の動作原理は0と1で表される2進数です。また、人間が日常生活で扱っている数

ポインタを使用した場合には以下のようになります include ltstdiohgt main() char str[6] = TOKAI char chp for( chp = str chp = yen0 chp++ ) putchar( chp )

chp str T [0] O K A I yen0 [5]

参照する変数 配列の表現 ポインタの表現 実際のアドレス 1番目の数 str[0] chp CHP 2番目の数 str[1] (chp+1) CHP+1 n番目の数 str[n-1] (chp+n-1) CHP+n-1 6番目の数 str[5] (chp+5) CHP+5

注意実際のアドレス CHPは実行時に決定されます

(2)二次元文字型配列 二次元の文字型配列に定数を設定しそれを出力するプログラムです文字型配列を使用す

ると次のとおりになります include ltstdiohgt main() char str[5][40] = TOKAI shounan campus NEC DEC int i for( i = 0 i lt 5 i++ ) printf( yenns str[i] )

40 バイト str TOKAI shounan campus NEC DEC

22

ポインタ型配列を使用すると次のとおりになります include ltstdiohgt main() char str[6] = TOKAI shounan campus NEC DEC NULL char chp for( chp = str chp = NULL chp++ ) printf( yenns chp ) str

chp 番地 TOKAI 番地 shounan 番地 campus 番地 NEC 番地 DEC

NULL

演習8 キーボードまたはデータファイルから読み込んだ文字列中にrsquoArsquo があったら rsquoarsquo に変換 するプログラムを配列とポインタを使って書きなさい

23

第7章 構造体共用体 7-1 構造体

プログラムの規模が大きくなるにつれて多数の intや floatcharなどのデータ型を扱うようになり複雑になってきますそこで多数のデータを1つにまとめて簡単に扱える機能が構造体です 構造体について住所録のデータを例にあげて考えてみます

住所録の個人データとして氏名住所電話番号年齢の項目を一つのデータとします これをC言語で変数の定義をすると次のようになります 氏名東海太郎 char name[30] 住所平塚市北金目1117 char address[30] 電話番号0463-58-1211 char tel[20] 年齢30 int age 個人の住所録データ C言語での表現 このような住所録の個人データを1つにまとめて新しいデータとして定義する機能を構造体と言

います struct 構造体タグ名 構造体メンバーの並び

「struct」は構造体を表すキーワードです 「構造体タグ名」は構造体の型枠を宣言しますここは自由に名前を定義することができ ます 「構造体メンバーの並び」は構造体の要素です複数指定できます

個人の住所録のデータを構造体で宣言すると次のようになります

struct jusho char name[30] char address[30] 構造体のメンバーの並び char tel[20] (複数可)

int age

上記の宣言では構造体の形式を宣言しているだけでメモリ中で実際の領域を確保している

わけではありません実際に領域を確保するためには次のように定義します

struct 構造体タグ名 構造体名

したがって構造体名を jdata とすると次のように指定します

struct jusho jdata

構造体 jdataは次のように構造体タグ jushoの形式で領域を確保します

24

Jdata name[30]

address[30] tel[20] age

(1)構造体の参照

プログラム中で構造体中のメンバーを参照する場合には次のように指定します 構造体名メンバー名

したがって「名前」を参照したいときには次のように指定します

jdataname

[プログラム例]

名前住所電話番号年齢を定義しそれを印字します include ltstdiohgt include ltstringhgt main() struct jusho char name[30] char address[30] char tel[20] int age struct jusho jdata strcpy( jdataname 東海 太郎) strcpy( jdataaddress 平塚市北金目1117)

strcpy( jdatatel 0463-58-1211) jdataage = 30 printf(yenn氏名 = syenn jdataname) printf(yenn住所 = syenn jdataaddress) printf(yenn電話番号= syenn jdatatel) printf(yenn年齢 = dyenn jdataage)

また構造体の形式の定義と領域の確保は次のように同時におこなうことができます

struct 構造体タグ名 構造体メンバーの並び 構造体名

struct jusho struct jusho char name[30] char name[30] char address[30] char address[30] char tel[30] = char tel[30] int age 同じ int age

jdata struct jusho jdata

型宣言と同時にメモリ上に領域を確保する方法 後からメモリ上に領域を確保する方法

25

(2) 構造体配列 住所録データの場合その中に入るデータは1件ではありませんやはり100件200件のデ

ータが必要になる場合がありますこのように個人単位のデータを多数扱う場合には構造体を配

列として宣言することができます 次の例は個人のデータを100個用意するために構造体を配列として宣言しています struct jusho jdata[100] jdata[0] name[30] address[30] tel[20] age

jdata[99 ] name[30] address[30] tel[20] age

(3)構造体配列の参照

プログラム中で構造体配列中のメンバーを参照する場合には次のように指定します 構造体名[要素番号]メンバー名

したがって10件目の人の「名前」を参照したいときには次のように指定します

jdata[10]name

[プログラム例]

名前住所電話番号年齢を定義しそれを印字します include ltstdiohgt include ltstringhgt main() struct jusho char name[30] char address[30] char tel[20] int age jdata[100] strcpy( jdata[10]name 東海 太郎) strcpy( jdata[10]address 平塚市北金目1117)

strcpy( jdata[10]tel 0463-58-1211) jdata[10]age = 30 printf(yenn氏名 = syenn jdata[10]name) printf(yenn住所 = syenn jdata[10]address) printf(yenn電話番号= syenn jdata[10]tel) printf(yenn年齢 = dyenn jdata[10]age)

26

(4) 構造体のポインタ 変数と同じように構造体へのポインタも定義することができます

変数へのポインタ例 構造体へのポインタ例 またポインタを使用して構造体メンバーを参照するには次のように -> 記号を使って指

定します ポインタ変数名 -> メンバー名

[プログラム例]

名前住所電話番号年齢を定義しそれを印字します include ltstdiohgt include ltstringhgt main() struct jusho char name[30] char address[30] char tel[20] int age jdatakp kp = ampjdata strcpy( kp-gtname 東海 太郎)

strcpy( kp-gtaddress 平塚市北金目1117)

strcpy( kp-gttel 0463-58-1211) kp-gtage = 30 printf(yenn氏名 = syenn kp-gtname) printf(yenn住所 = syenn kp-gtaddress) printf(yenn電話番号= syenn kp-gttel) printf(yenn年齢 = dyenn kp-gtage)

kp jdata

name[30] ポインタ型の変数 address[30]

tel[20]

構造体へのポインタを記憶 age

することができます

int a int b b = ampa

struct name jname struct name np np = ampname

27

7-2 共用体 共用体は構造体と同じようにして宣言しますが共用体は複数のデータ型を同一のアドレスに

割り当てる方法です union 共用体タグ名 共用体メンバーの並び

「union」は共用体を表すキーワードです 「共用体タグ名」は共用体の型枠の名前を宣言しますここは自由に名前を定義することがで

きます 「共用体メンバーの並び」は共用体の要素です複数指定できます

共用体の宣言の例を次に示します

union c_tag int a char b

共用体 cは次のように共用体タグ c_tagの形式で領域を確保します共用体はメモリ上に領域を確保するときは ab ともに同じ領域に割り付けられます これはab という2つのデータが同時に存在するわけではなく cを異なるデータ abで共有す

ることを表しています c a b

上記の宣言だけでは共用体の形式を宣言しているだけでメモリ中で実際の領域を確保して

いるわけではありません実際に領域を確保するためには次のように定義します union 構造体タグ名 構造体名

したがって共用体名を c とすると次のように指定します

union c_tag c

(1)共用体の参照

プログラム中で共用体中のメンバーを参照する場合には次のように指定します 共用体名メンバー名

したがって「a」または「b」を参照したいときには次のように指定します

ca (int 型) cb (char 型)

メンバー参照方法によって int型として使ったりchar型として利用することができます

28

[プログラム例]

includeltstdiohgt main() union data char a short b int c chk chkc = 0x12345678 printf( char a xyennchka) printf( short b xyennchkb) printf( int c xyennchkc)

chkb(int 型) chkb(short 型) chka(char 型) 12 12 12 34 34 56 78

29

第8章 アルゴリズム コンピュータに何か仕事をさせようとするときは仕事を具体的に実行するための処理や動作

の手順が必要ですこの「手順」がアルゴリズムです アルゴリズムを考えるときは解くべき問題をはっきりと定義することが必要です

8-1 ソート ソートとは与えられたデータを小さい順または大きい順に並べ換えることですソート方法は

いくつかありますが基本的な方法でソートするアルゴリズムを紹介します

includeltstdiohgt int data[10] main()

int data_in() sort() data_in() sort() int data_in() データ入力関数

int a printf(数値入力yenn)

for(a=0alt=9a++) printf( [d]a+1) scanf(dampdata[a]) int sort() ソート処理を行う関数

int cont1cont2tmp1tmp2mim for(cont1=0 cont1lt=9 cont1++) mim=data[cont1] tmp1=cont1 for(cont2=cont1+1 cont2lt=9 cont2++) if(data[cont2] lt mim) mim=data[cont2] tmp1=cont2 tmp2 = data[cont1] data[cont1] = data[tmp1] data[tmp1] = tmp2 printf(結果 yenn)

for (cont1 = 0 cont1 lt= 9 cont1++) printf(d yenn data[cont1])

30

第9章 プリプロセッサ C言語にはプログラムの中でコンパイルについての指示を行う「プリプロセッサ」という機能が

ありますまたプリプロセッサとはコンパイルする前に実行されるためその意味のとおり「前処理」 と呼ばれていますここでは代表的なものをいくつか説明します

9-1 ファイルの挿入 ソースプログラム中に指定されたファイルを挿入します

include ltstdiohgt helliphellip 標準ディレクトリを探します include progh helliphellip 現在のディレクトリを探しなければ標準ディレクトリを探します

includeltstdiohgt によって組み込まれた define EOF (-1) define EOF (-1) define define helliphelliphelliphellip 組み込み helliphelliphelliphellip

main() stdiohファイル

int helliphelliphelliphellip helliphelliphelliphellip

ソースファイル

9-2 文字の置換 プログラム中に使われている文字列を別の文字列に置き換えます

include ltstdiohgt define TRUE 1 define EOF (-1) main() define helliphellip helliphellip

while(TRUE) define TRUE 1 置き換え main() helliphellip helliphellip while(1)

break helliphelliphellip

31

9-3 条件によるコンパイル 識別子が定義されているか否かを判断しコンパイルする範囲を指定します

include ltstdiohgt define UNIX main() ifdef UNIX printf( UNIX yenn) else printf(MS-DOSyenn) endif

include ltstdiohgt define OS UNIX main() if OS == UNIX printf( UNIX yenn) else printf(MS-DOSyenn) endif

32

付 録 1 puts()gets()関数について

行単位に入出力を行う場合には puts() gets() 関数を用います

puts() 標準出力に文字列を出力します

include ltstdiohgt int puts( char s ) puts() は NULL で終る文字列 s を標準出力に出力し最後に改行文字 yenn も出力しま

gets() 標準入力から文字列を入力します

include ltstdiohgt char gets( char s ) 戻り値正常に入力した場合には引数 s の値が返されますエラーやEOFになった場合に

は NULL が返されます gets() は標準入力から復帰文字で終る文字列を入力しs に格納しますこのとき最後の復

帰文字は NULL文字に変更されます

入力行の出力 標準入力から gets() で入力したデータには改行コードは含まれませんまた標準出力へ

puts() で出力を行う場合には必ず改行コードが付加されますgets() を実行したときの戻り値としてファイルの終端を検出した場合には EOF ではなく NULL が返されますので注意して下さい

include ltstdiohgt main() char data[80] while( gets( data ) = NULL )puts( data )

putchar()getchar()関数について putchar() 標準出力に文字を出力します

include ltstdiohgt int putchar(int c ) 戻り値正常に出力できた場合には文字cをエラーの場合にはEOFを返します

33

getchar() 標準入力から文字を入力します

include ltstdiohgt int getchar(void) 戻り値正常に入力した場合には読み込んだ文字を int 型に変換して返しますまたファイ

ルエンドエラーの場合にはEOFを返します

標準入力標準出力

標準入力標準出力はプログラムが開始されるときにはオープンされていますそれぞれのフ

ァイルポインタは stdin stdout になっていますfopen() fclose() をせずとも使用することができます

scanf() 標準出力ストリームからテキストを読み込み解釈します include ltstdiohgt int scanf( const char format [ address ] ) 戻り値正しくスキャンし変換し格納した入力フィールドの数を返しますファイルエンドを読

み込んだ場合は戻り値は EOF となります値を格納したフィールドがなかった場合は戻り値は0となります

一連の入力フィールドをスキャンして1度に1文字ずつストリーム stdin から文字を読み込み

ます次に引き数 format によって指される書式文字列中の書式指定に従って各フィールドを書式化します最後にformat の後に続く各引き数が示しているアドレスに書式化した入力を格納していきます書式文字列中の書式指定の個数はその後に続くアドレスの数と同じでな

ければなりません 書式指定[入力幅][型指定文字] 入力幅 読むべき文字数の最大値 型指定文字 次のとおりです 型指定文字 期待される入力 引き数の型 d 10進整数 int へのポインタ( int arg ) x 16進整数 int へのポインタ( int arg ) f 浮動小数点数 float へのポインタ( float arg ) s 文字列 文字配列へのポインタ( char arg[] ) c 文字 文字へのポインタ( char arg )

printf() フォーマットを指定してテキスト標準出力ストリームに出力します include ltstdiohgt int printf( const char format [ argument ] ) 戻り値出力したバイト数を返しますエラーの場合は EOF を返します

34

format によって指される書式文字列中の書式指定をformat の後に続く各引き数に適用し

書式化されたデータを stdout に出力します書式指定は後に続く引き数と同じ数だけなければなりません

書式指定[印字幅][精度][型指定文字] 印字幅 印字する最小文字数 精度 印字する最大文字数 型指定文字 つぎのとおりです 型指定文字 入力引き数 出力の書式 d 整数 符号付き10進整数 x 整数 符号無し16進整数 f 浮動小数点 符号付きの dddddddd形式の値 c 文字 1個の文字 s 文字列ポインタ ヌル文字に出会うか精度に達するまで 文字をプリントする

fopen()fclose()関数について fopen() ファイルをオープンします

include ltstdiohgt FILE fopen( char filename char mode ) 戻り値正常にファイルのオープンができたらファイルポインタを返しますエラーがあった場

合には NULLを返します 文字列 filename で指定されたファイルをオープンしますオープン後の入出力のモードに

ついては文字列 mode で指定しますmode に指定できる文字は以下のとおりです r 入力モードでオープンします w 出力モードでオープンします a 存在するファイルに追加して出力するモードでオープンします r+ 既に作成してあるファイルを更新(入力出力)するモードでオープンします w+ 新しく作成するファイルを更新モードでオープンします a+ 既に作成してあるファイルの終りから更新用に作成します

以上の文字に b をつけ加えることによりバイナリモードで入出力することができるようになり

ます rb バイナリの入力モードでオープンします wb バイナリの出力モードでオープンします ab 存在するファイルに追加して出力するモード(バイナリ)でオープンします

fclose() 既にオープンしてあるファイルをクローズします include ltstdiohgt fclose( FILE fp ) 既にオープンしているファイルをクローズしますパラメータには fopen() 関数により返された

ファイルポインタを指定します

35

テキストモードとバイナリモード 行の最後はテキストモードの場合改行コードのみとなりバイナリモードの場合には復帰

コードと改行コードの組合わせになります行の最後としてテキストファイルには復帰コード改行

コードが書かれていますがテキストモードでオープンした場合には入力すると改行コードのみに

変換されて入力されますバイナリモードの場合には復帰コード改行コードがそれぞれ入力され

ます

fputs()fgets()関数について fputs() ファイルポインタで指定されるファイルに文字列を出力します

include ltstdiohgt

int fputs( char s FILE fp ) fputs() は NULL で終る文字列 s をファイルポインタに示されるファイルへ出力しますputs()

と違い最後に改行文字 yenn を出力することはありません

fgets() ファイルポインタで指定されるファイルから文字列を入力します include ltstdiohgt char fgets( char s int n FILE fp ) 戻り値正常に入力した場合には引数 s の値が返されますエラーやEOFになった場合に

は NULL が返されます fgets() はファイルポインタで指定されるファイルから ( n - 1 ) 文字または改行文字までの

文字列を入力しs に格納しますgets() と異なり最後に入力された改行文字は NULL 文字に変更されません

標準入力から入力しファイルへ出力する ファイルへ出力あるいは入力を行う場合には改行コードの変換(入力の場合の削除出力の

場合の付加)はされませんしたがって標準入力から入力しファイルへ出力する場合には改行

コードを付加しなければなりません include ltstdiohgt main() char data[80] FILE fp fp = fopen( data w ) while( gets( data ) = NULL ) strcat( data yenn ) 改行コードの付加

fputs( data fp ) fclose( fp )

36

fputc()fgetc()関数について fputc() ファイルポインタで指定されるファイルに1文字出力します

include ltstdiohgt int fputc( int c FILE fp ) 戻り値正常に出力できた場合には文字 c を返しエラーの場合には EOF を返します fputc() は文字 c をファイルポインタで示されるファイルへ出力します

fgetc() ファイルポインタで指定されるファイルから1文字入力します

include ltstdiohgt int fgetc( FILE fp ) 戻り値正常に入力した場合には入力した文字を返しますエラーやEOFになった場合には

EOF が返されます fgetc() はファイルポインタで指定されるファイルから文字を入力します

ファイルの内容の表示 include ltstdiohgt main() FILE fp int ch char fname[30] printf( Key in Fila name gt ) gets( fname ) fp = fopen( fname r ) while( ( ch = fgetc( fp ) ) = EOF )putchar( ch ) fclose( fp )

その他テキスト中で使用された関数について sin() 三角関数の正弦を計算します

include ltmathhgt double sin(double radian) sinはラジアンを単位とする引数 radianの三角関数を計算します

37

strcpy() 文字列を他の文字列へコピーします

include ltstringhgt char strcpy(char string1const char string2) strcpyは引数 string2の指す文字列を null文字まで含めて引数 string1の指す領域にコピ

ーする strcpyは string1を返します

strcat() ある文字列を他の文字列に加えます

include ltstringhgt char strcat( char dest const char src ) 戻り値連結された文字列へのポインタを返します strcat() はsrc のコピーを dest の最後につけ加えます得られる文字列の長さは

strlen(dest)+strlen(src) になります

fabs() 絶対値の計算をします include ltmathhgt double fabs(double z) fabsは倍精度浮動小数の絶対値を計算して返しますつまりzgt=0であれば z をzlt0であ

れば-zを返します exp() 指数関数を計算します

include ltmathhgt double exp(double z) exp は引数zの指数関数つまりezを返すここではeは自然対数の底を表します対数関

数logの逆関数です

38

付 録 2 コンパイルの方法には大きく分けて第4章の実習で学んだようにデータファイルを作成してお

き ccg でコンパイルさせる方法と実行中に対話型でデータを入力していく方法があります ここでは対話型で実行を進めていく方法を紹介します ただしこの方法は計算(cpu)時間が10秒以内のものに限ります10秒を超える計算(cpu)時

間を要する場合はccg でコンパイルをするようにしてください 第4章実習の(2)(p16)までは同様です

コンパイル

コンピュータに処理を依頼します 60us1234boseicc cc rensyuc

所有するファイルの一覧を見てみます

60us1234boseicc ls -l larr 持っているファイルの一覧を見るコマンドです

-rw-r--r-- 1 60us1234 other 128 4月26日 15時14分 rensyuc -rwxr-xr-x 1 60us1234 other 361 4月26日 15時16分 aout

aout という実行形式のファイルが作成されています

実行

60us1234boseicc aout12 35[リターン] データを入力

1 200000 3500000 4200000 実行結果の出力

60us1234boseicc

注意

aout ファイルは印刷することができません実行結果を印刷する場合にはファイルに落とし てから出力するようにしましょう

60us1234boseicc aout gt kekka12 35[リターン] データを入力

60us1234boseicc more kekka 計算結果の確認 60us1234boseicc lpr kekka 計算結果の印刷

39

Page 25: n 第1章 章立ての部分は、書式(PC入門大見出し)を …第2章 数の表現 2-1 2進数 電子計算機の動作原理は0と1で表される2進数です。また、人間が日常生活で扱っている数

ポインタ型配列を使用すると次のとおりになります include ltstdiohgt main() char str[6] = TOKAI shounan campus NEC DEC NULL char chp for( chp = str chp = NULL chp++ ) printf( yenns chp ) str

chp 番地 TOKAI 番地 shounan 番地 campus 番地 NEC 番地 DEC

NULL

演習8 キーボードまたはデータファイルから読み込んだ文字列中にrsquoArsquo があったら rsquoarsquo に変換 するプログラムを配列とポインタを使って書きなさい

23

第7章 構造体共用体 7-1 構造体

プログラムの規模が大きくなるにつれて多数の intや floatcharなどのデータ型を扱うようになり複雑になってきますそこで多数のデータを1つにまとめて簡単に扱える機能が構造体です 構造体について住所録のデータを例にあげて考えてみます

住所録の個人データとして氏名住所電話番号年齢の項目を一つのデータとします これをC言語で変数の定義をすると次のようになります 氏名東海太郎 char name[30] 住所平塚市北金目1117 char address[30] 電話番号0463-58-1211 char tel[20] 年齢30 int age 個人の住所録データ C言語での表現 このような住所録の個人データを1つにまとめて新しいデータとして定義する機能を構造体と言

います struct 構造体タグ名 構造体メンバーの並び

「struct」は構造体を表すキーワードです 「構造体タグ名」は構造体の型枠を宣言しますここは自由に名前を定義することができ ます 「構造体メンバーの並び」は構造体の要素です複数指定できます

個人の住所録のデータを構造体で宣言すると次のようになります

struct jusho char name[30] char address[30] 構造体のメンバーの並び char tel[20] (複数可)

int age

上記の宣言では構造体の形式を宣言しているだけでメモリ中で実際の領域を確保している

わけではありません実際に領域を確保するためには次のように定義します

struct 構造体タグ名 構造体名

したがって構造体名を jdata とすると次のように指定します

struct jusho jdata

構造体 jdataは次のように構造体タグ jushoの形式で領域を確保します

24

Jdata name[30]

address[30] tel[20] age

(1)構造体の参照

プログラム中で構造体中のメンバーを参照する場合には次のように指定します 構造体名メンバー名

したがって「名前」を参照したいときには次のように指定します

jdataname

[プログラム例]

名前住所電話番号年齢を定義しそれを印字します include ltstdiohgt include ltstringhgt main() struct jusho char name[30] char address[30] char tel[20] int age struct jusho jdata strcpy( jdataname 東海 太郎) strcpy( jdataaddress 平塚市北金目1117)

strcpy( jdatatel 0463-58-1211) jdataage = 30 printf(yenn氏名 = syenn jdataname) printf(yenn住所 = syenn jdataaddress) printf(yenn電話番号= syenn jdatatel) printf(yenn年齢 = dyenn jdataage)

また構造体の形式の定義と領域の確保は次のように同時におこなうことができます

struct 構造体タグ名 構造体メンバーの並び 構造体名

struct jusho struct jusho char name[30] char name[30] char address[30] char address[30] char tel[30] = char tel[30] int age 同じ int age

jdata struct jusho jdata

型宣言と同時にメモリ上に領域を確保する方法 後からメモリ上に領域を確保する方法

25

(2) 構造体配列 住所録データの場合その中に入るデータは1件ではありませんやはり100件200件のデ

ータが必要になる場合がありますこのように個人単位のデータを多数扱う場合には構造体を配

列として宣言することができます 次の例は個人のデータを100個用意するために構造体を配列として宣言しています struct jusho jdata[100] jdata[0] name[30] address[30] tel[20] age

jdata[99 ] name[30] address[30] tel[20] age

(3)構造体配列の参照

プログラム中で構造体配列中のメンバーを参照する場合には次のように指定します 構造体名[要素番号]メンバー名

したがって10件目の人の「名前」を参照したいときには次のように指定します

jdata[10]name

[プログラム例]

名前住所電話番号年齢を定義しそれを印字します include ltstdiohgt include ltstringhgt main() struct jusho char name[30] char address[30] char tel[20] int age jdata[100] strcpy( jdata[10]name 東海 太郎) strcpy( jdata[10]address 平塚市北金目1117)

strcpy( jdata[10]tel 0463-58-1211) jdata[10]age = 30 printf(yenn氏名 = syenn jdata[10]name) printf(yenn住所 = syenn jdata[10]address) printf(yenn電話番号= syenn jdata[10]tel) printf(yenn年齢 = dyenn jdata[10]age)

26

(4) 構造体のポインタ 変数と同じように構造体へのポインタも定義することができます

変数へのポインタ例 構造体へのポインタ例 またポインタを使用して構造体メンバーを参照するには次のように -> 記号を使って指

定します ポインタ変数名 -> メンバー名

[プログラム例]

名前住所電話番号年齢を定義しそれを印字します include ltstdiohgt include ltstringhgt main() struct jusho char name[30] char address[30] char tel[20] int age jdatakp kp = ampjdata strcpy( kp-gtname 東海 太郎)

strcpy( kp-gtaddress 平塚市北金目1117)

strcpy( kp-gttel 0463-58-1211) kp-gtage = 30 printf(yenn氏名 = syenn kp-gtname) printf(yenn住所 = syenn kp-gtaddress) printf(yenn電話番号= syenn kp-gttel) printf(yenn年齢 = dyenn kp-gtage)

kp jdata

name[30] ポインタ型の変数 address[30]

tel[20]

構造体へのポインタを記憶 age

することができます

int a int b b = ampa

struct name jname struct name np np = ampname

27

7-2 共用体 共用体は構造体と同じようにして宣言しますが共用体は複数のデータ型を同一のアドレスに

割り当てる方法です union 共用体タグ名 共用体メンバーの並び

「union」は共用体を表すキーワードです 「共用体タグ名」は共用体の型枠の名前を宣言しますここは自由に名前を定義することがで

きます 「共用体メンバーの並び」は共用体の要素です複数指定できます

共用体の宣言の例を次に示します

union c_tag int a char b

共用体 cは次のように共用体タグ c_tagの形式で領域を確保します共用体はメモリ上に領域を確保するときは ab ともに同じ領域に割り付けられます これはab という2つのデータが同時に存在するわけではなく cを異なるデータ abで共有す

ることを表しています c a b

上記の宣言だけでは共用体の形式を宣言しているだけでメモリ中で実際の領域を確保して

いるわけではありません実際に領域を確保するためには次のように定義します union 構造体タグ名 構造体名

したがって共用体名を c とすると次のように指定します

union c_tag c

(1)共用体の参照

プログラム中で共用体中のメンバーを参照する場合には次のように指定します 共用体名メンバー名

したがって「a」または「b」を参照したいときには次のように指定します

ca (int 型) cb (char 型)

メンバー参照方法によって int型として使ったりchar型として利用することができます

28

[プログラム例]

includeltstdiohgt main() union data char a short b int c chk chkc = 0x12345678 printf( char a xyennchka) printf( short b xyennchkb) printf( int c xyennchkc)

chkb(int 型) chkb(short 型) chka(char 型) 12 12 12 34 34 56 78

29

第8章 アルゴリズム コンピュータに何か仕事をさせようとするときは仕事を具体的に実行するための処理や動作

の手順が必要ですこの「手順」がアルゴリズムです アルゴリズムを考えるときは解くべき問題をはっきりと定義することが必要です

8-1 ソート ソートとは与えられたデータを小さい順または大きい順に並べ換えることですソート方法は

いくつかありますが基本的な方法でソートするアルゴリズムを紹介します

includeltstdiohgt int data[10] main()

int data_in() sort() data_in() sort() int data_in() データ入力関数

int a printf(数値入力yenn)

for(a=0alt=9a++) printf( [d]a+1) scanf(dampdata[a]) int sort() ソート処理を行う関数

int cont1cont2tmp1tmp2mim for(cont1=0 cont1lt=9 cont1++) mim=data[cont1] tmp1=cont1 for(cont2=cont1+1 cont2lt=9 cont2++) if(data[cont2] lt mim) mim=data[cont2] tmp1=cont2 tmp2 = data[cont1] data[cont1] = data[tmp1] data[tmp1] = tmp2 printf(結果 yenn)

for (cont1 = 0 cont1 lt= 9 cont1++) printf(d yenn data[cont1])

30

第9章 プリプロセッサ C言語にはプログラムの中でコンパイルについての指示を行う「プリプロセッサ」という機能が

ありますまたプリプロセッサとはコンパイルする前に実行されるためその意味のとおり「前処理」 と呼ばれていますここでは代表的なものをいくつか説明します

9-1 ファイルの挿入 ソースプログラム中に指定されたファイルを挿入します

include ltstdiohgt helliphellip 標準ディレクトリを探します include progh helliphellip 現在のディレクトリを探しなければ標準ディレクトリを探します

includeltstdiohgt によって組み込まれた define EOF (-1) define EOF (-1) define define helliphelliphelliphellip 組み込み helliphelliphelliphellip

main() stdiohファイル

int helliphelliphelliphellip helliphelliphelliphellip

ソースファイル

9-2 文字の置換 プログラム中に使われている文字列を別の文字列に置き換えます

include ltstdiohgt define TRUE 1 define EOF (-1) main() define helliphellip helliphellip

while(TRUE) define TRUE 1 置き換え main() helliphellip helliphellip while(1)

break helliphelliphellip

31

9-3 条件によるコンパイル 識別子が定義されているか否かを判断しコンパイルする範囲を指定します

include ltstdiohgt define UNIX main() ifdef UNIX printf( UNIX yenn) else printf(MS-DOSyenn) endif

include ltstdiohgt define OS UNIX main() if OS == UNIX printf( UNIX yenn) else printf(MS-DOSyenn) endif

32

付 録 1 puts()gets()関数について

行単位に入出力を行う場合には puts() gets() 関数を用います

puts() 標準出力に文字列を出力します

include ltstdiohgt int puts( char s ) puts() は NULL で終る文字列 s を標準出力に出力し最後に改行文字 yenn も出力しま

gets() 標準入力から文字列を入力します

include ltstdiohgt char gets( char s ) 戻り値正常に入力した場合には引数 s の値が返されますエラーやEOFになった場合に

は NULL が返されます gets() は標準入力から復帰文字で終る文字列を入力しs に格納しますこのとき最後の復

帰文字は NULL文字に変更されます

入力行の出力 標準入力から gets() で入力したデータには改行コードは含まれませんまた標準出力へ

puts() で出力を行う場合には必ず改行コードが付加されますgets() を実行したときの戻り値としてファイルの終端を検出した場合には EOF ではなく NULL が返されますので注意して下さい

include ltstdiohgt main() char data[80] while( gets( data ) = NULL )puts( data )

putchar()getchar()関数について putchar() 標準出力に文字を出力します

include ltstdiohgt int putchar(int c ) 戻り値正常に出力できた場合には文字cをエラーの場合にはEOFを返します

33

getchar() 標準入力から文字を入力します

include ltstdiohgt int getchar(void) 戻り値正常に入力した場合には読み込んだ文字を int 型に変換して返しますまたファイ

ルエンドエラーの場合にはEOFを返します

標準入力標準出力

標準入力標準出力はプログラムが開始されるときにはオープンされていますそれぞれのフ

ァイルポインタは stdin stdout になっていますfopen() fclose() をせずとも使用することができます

scanf() 標準出力ストリームからテキストを読み込み解釈します include ltstdiohgt int scanf( const char format [ address ] ) 戻り値正しくスキャンし変換し格納した入力フィールドの数を返しますファイルエンドを読

み込んだ場合は戻り値は EOF となります値を格納したフィールドがなかった場合は戻り値は0となります

一連の入力フィールドをスキャンして1度に1文字ずつストリーム stdin から文字を読み込み

ます次に引き数 format によって指される書式文字列中の書式指定に従って各フィールドを書式化します最後にformat の後に続く各引き数が示しているアドレスに書式化した入力を格納していきます書式文字列中の書式指定の個数はその後に続くアドレスの数と同じでな

ければなりません 書式指定[入力幅][型指定文字] 入力幅 読むべき文字数の最大値 型指定文字 次のとおりです 型指定文字 期待される入力 引き数の型 d 10進整数 int へのポインタ( int arg ) x 16進整数 int へのポインタ( int arg ) f 浮動小数点数 float へのポインタ( float arg ) s 文字列 文字配列へのポインタ( char arg[] ) c 文字 文字へのポインタ( char arg )

printf() フォーマットを指定してテキスト標準出力ストリームに出力します include ltstdiohgt int printf( const char format [ argument ] ) 戻り値出力したバイト数を返しますエラーの場合は EOF を返します

34

format によって指される書式文字列中の書式指定をformat の後に続く各引き数に適用し

書式化されたデータを stdout に出力します書式指定は後に続く引き数と同じ数だけなければなりません

書式指定[印字幅][精度][型指定文字] 印字幅 印字する最小文字数 精度 印字する最大文字数 型指定文字 つぎのとおりです 型指定文字 入力引き数 出力の書式 d 整数 符号付き10進整数 x 整数 符号無し16進整数 f 浮動小数点 符号付きの dddddddd形式の値 c 文字 1個の文字 s 文字列ポインタ ヌル文字に出会うか精度に達するまで 文字をプリントする

fopen()fclose()関数について fopen() ファイルをオープンします

include ltstdiohgt FILE fopen( char filename char mode ) 戻り値正常にファイルのオープンができたらファイルポインタを返しますエラーがあった場

合には NULLを返します 文字列 filename で指定されたファイルをオープンしますオープン後の入出力のモードに

ついては文字列 mode で指定しますmode に指定できる文字は以下のとおりです r 入力モードでオープンします w 出力モードでオープンします a 存在するファイルに追加して出力するモードでオープンします r+ 既に作成してあるファイルを更新(入力出力)するモードでオープンします w+ 新しく作成するファイルを更新モードでオープンします a+ 既に作成してあるファイルの終りから更新用に作成します

以上の文字に b をつけ加えることによりバイナリモードで入出力することができるようになり

ます rb バイナリの入力モードでオープンします wb バイナリの出力モードでオープンします ab 存在するファイルに追加して出力するモード(バイナリ)でオープンします

fclose() 既にオープンしてあるファイルをクローズします include ltstdiohgt fclose( FILE fp ) 既にオープンしているファイルをクローズしますパラメータには fopen() 関数により返された

ファイルポインタを指定します

35

テキストモードとバイナリモード 行の最後はテキストモードの場合改行コードのみとなりバイナリモードの場合には復帰

コードと改行コードの組合わせになります行の最後としてテキストファイルには復帰コード改行

コードが書かれていますがテキストモードでオープンした場合には入力すると改行コードのみに

変換されて入力されますバイナリモードの場合には復帰コード改行コードがそれぞれ入力され

ます

fputs()fgets()関数について fputs() ファイルポインタで指定されるファイルに文字列を出力します

include ltstdiohgt

int fputs( char s FILE fp ) fputs() は NULL で終る文字列 s をファイルポインタに示されるファイルへ出力しますputs()

と違い最後に改行文字 yenn を出力することはありません

fgets() ファイルポインタで指定されるファイルから文字列を入力します include ltstdiohgt char fgets( char s int n FILE fp ) 戻り値正常に入力した場合には引数 s の値が返されますエラーやEOFになった場合に

は NULL が返されます fgets() はファイルポインタで指定されるファイルから ( n - 1 ) 文字または改行文字までの

文字列を入力しs に格納しますgets() と異なり最後に入力された改行文字は NULL 文字に変更されません

標準入力から入力しファイルへ出力する ファイルへ出力あるいは入力を行う場合には改行コードの変換(入力の場合の削除出力の

場合の付加)はされませんしたがって標準入力から入力しファイルへ出力する場合には改行

コードを付加しなければなりません include ltstdiohgt main() char data[80] FILE fp fp = fopen( data w ) while( gets( data ) = NULL ) strcat( data yenn ) 改行コードの付加

fputs( data fp ) fclose( fp )

36

fputc()fgetc()関数について fputc() ファイルポインタで指定されるファイルに1文字出力します

include ltstdiohgt int fputc( int c FILE fp ) 戻り値正常に出力できた場合には文字 c を返しエラーの場合には EOF を返します fputc() は文字 c をファイルポインタで示されるファイルへ出力します

fgetc() ファイルポインタで指定されるファイルから1文字入力します

include ltstdiohgt int fgetc( FILE fp ) 戻り値正常に入力した場合には入力した文字を返しますエラーやEOFになった場合には

EOF が返されます fgetc() はファイルポインタで指定されるファイルから文字を入力します

ファイルの内容の表示 include ltstdiohgt main() FILE fp int ch char fname[30] printf( Key in Fila name gt ) gets( fname ) fp = fopen( fname r ) while( ( ch = fgetc( fp ) ) = EOF )putchar( ch ) fclose( fp )

その他テキスト中で使用された関数について sin() 三角関数の正弦を計算します

include ltmathhgt double sin(double radian) sinはラジアンを単位とする引数 radianの三角関数を計算します

37

strcpy() 文字列を他の文字列へコピーします

include ltstringhgt char strcpy(char string1const char string2) strcpyは引数 string2の指す文字列を null文字まで含めて引数 string1の指す領域にコピ

ーする strcpyは string1を返します

strcat() ある文字列を他の文字列に加えます

include ltstringhgt char strcat( char dest const char src ) 戻り値連結された文字列へのポインタを返します strcat() はsrc のコピーを dest の最後につけ加えます得られる文字列の長さは

strlen(dest)+strlen(src) になります

fabs() 絶対値の計算をします include ltmathhgt double fabs(double z) fabsは倍精度浮動小数の絶対値を計算して返しますつまりzgt=0であれば z をzlt0であ

れば-zを返します exp() 指数関数を計算します

include ltmathhgt double exp(double z) exp は引数zの指数関数つまりezを返すここではeは自然対数の底を表します対数関

数logの逆関数です

38

付 録 2 コンパイルの方法には大きく分けて第4章の実習で学んだようにデータファイルを作成してお

き ccg でコンパイルさせる方法と実行中に対話型でデータを入力していく方法があります ここでは対話型で実行を進めていく方法を紹介します ただしこの方法は計算(cpu)時間が10秒以内のものに限ります10秒を超える計算(cpu)時

間を要する場合はccg でコンパイルをするようにしてください 第4章実習の(2)(p16)までは同様です

コンパイル

コンピュータに処理を依頼します 60us1234boseicc cc rensyuc

所有するファイルの一覧を見てみます

60us1234boseicc ls -l larr 持っているファイルの一覧を見るコマンドです

-rw-r--r-- 1 60us1234 other 128 4月26日 15時14分 rensyuc -rwxr-xr-x 1 60us1234 other 361 4月26日 15時16分 aout

aout という実行形式のファイルが作成されています

実行

60us1234boseicc aout12 35[リターン] データを入力

1 200000 3500000 4200000 実行結果の出力

60us1234boseicc

注意

aout ファイルは印刷することができません実行結果を印刷する場合にはファイルに落とし てから出力するようにしましょう

60us1234boseicc aout gt kekka12 35[リターン] データを入力

60us1234boseicc more kekka 計算結果の確認 60us1234boseicc lpr kekka 計算結果の印刷

39

Page 26: n 第1章 章立ての部分は、書式(PC入門大見出し)を …第2章 数の表現 2-1 2進数 電子計算機の動作原理は0と1で表される2進数です。また、人間が日常生活で扱っている数

第7章 構造体共用体 7-1 構造体

プログラムの規模が大きくなるにつれて多数の intや floatcharなどのデータ型を扱うようになり複雑になってきますそこで多数のデータを1つにまとめて簡単に扱える機能が構造体です 構造体について住所録のデータを例にあげて考えてみます

住所録の個人データとして氏名住所電話番号年齢の項目を一つのデータとします これをC言語で変数の定義をすると次のようになります 氏名東海太郎 char name[30] 住所平塚市北金目1117 char address[30] 電話番号0463-58-1211 char tel[20] 年齢30 int age 個人の住所録データ C言語での表現 このような住所録の個人データを1つにまとめて新しいデータとして定義する機能を構造体と言

います struct 構造体タグ名 構造体メンバーの並び

「struct」は構造体を表すキーワードです 「構造体タグ名」は構造体の型枠を宣言しますここは自由に名前を定義することができ ます 「構造体メンバーの並び」は構造体の要素です複数指定できます

個人の住所録のデータを構造体で宣言すると次のようになります

struct jusho char name[30] char address[30] 構造体のメンバーの並び char tel[20] (複数可)

int age

上記の宣言では構造体の形式を宣言しているだけでメモリ中で実際の領域を確保している

わけではありません実際に領域を確保するためには次のように定義します

struct 構造体タグ名 構造体名

したがって構造体名を jdata とすると次のように指定します

struct jusho jdata

構造体 jdataは次のように構造体タグ jushoの形式で領域を確保します

24

Jdata name[30]

address[30] tel[20] age

(1)構造体の参照

プログラム中で構造体中のメンバーを参照する場合には次のように指定します 構造体名メンバー名

したがって「名前」を参照したいときには次のように指定します

jdataname

[プログラム例]

名前住所電話番号年齢を定義しそれを印字します include ltstdiohgt include ltstringhgt main() struct jusho char name[30] char address[30] char tel[20] int age struct jusho jdata strcpy( jdataname 東海 太郎) strcpy( jdataaddress 平塚市北金目1117)

strcpy( jdatatel 0463-58-1211) jdataage = 30 printf(yenn氏名 = syenn jdataname) printf(yenn住所 = syenn jdataaddress) printf(yenn電話番号= syenn jdatatel) printf(yenn年齢 = dyenn jdataage)

また構造体の形式の定義と領域の確保は次のように同時におこなうことができます

struct 構造体タグ名 構造体メンバーの並び 構造体名

struct jusho struct jusho char name[30] char name[30] char address[30] char address[30] char tel[30] = char tel[30] int age 同じ int age

jdata struct jusho jdata

型宣言と同時にメモリ上に領域を確保する方法 後からメモリ上に領域を確保する方法

25

(2) 構造体配列 住所録データの場合その中に入るデータは1件ではありませんやはり100件200件のデ

ータが必要になる場合がありますこのように個人単位のデータを多数扱う場合には構造体を配

列として宣言することができます 次の例は個人のデータを100個用意するために構造体を配列として宣言しています struct jusho jdata[100] jdata[0] name[30] address[30] tel[20] age

jdata[99 ] name[30] address[30] tel[20] age

(3)構造体配列の参照

プログラム中で構造体配列中のメンバーを参照する場合には次のように指定します 構造体名[要素番号]メンバー名

したがって10件目の人の「名前」を参照したいときには次のように指定します

jdata[10]name

[プログラム例]

名前住所電話番号年齢を定義しそれを印字します include ltstdiohgt include ltstringhgt main() struct jusho char name[30] char address[30] char tel[20] int age jdata[100] strcpy( jdata[10]name 東海 太郎) strcpy( jdata[10]address 平塚市北金目1117)

strcpy( jdata[10]tel 0463-58-1211) jdata[10]age = 30 printf(yenn氏名 = syenn jdata[10]name) printf(yenn住所 = syenn jdata[10]address) printf(yenn電話番号= syenn jdata[10]tel) printf(yenn年齢 = dyenn jdata[10]age)

26

(4) 構造体のポインタ 変数と同じように構造体へのポインタも定義することができます

変数へのポインタ例 構造体へのポインタ例 またポインタを使用して構造体メンバーを参照するには次のように -> 記号を使って指

定します ポインタ変数名 -> メンバー名

[プログラム例]

名前住所電話番号年齢を定義しそれを印字します include ltstdiohgt include ltstringhgt main() struct jusho char name[30] char address[30] char tel[20] int age jdatakp kp = ampjdata strcpy( kp-gtname 東海 太郎)

strcpy( kp-gtaddress 平塚市北金目1117)

strcpy( kp-gttel 0463-58-1211) kp-gtage = 30 printf(yenn氏名 = syenn kp-gtname) printf(yenn住所 = syenn kp-gtaddress) printf(yenn電話番号= syenn kp-gttel) printf(yenn年齢 = dyenn kp-gtage)

kp jdata

name[30] ポインタ型の変数 address[30]

tel[20]

構造体へのポインタを記憶 age

することができます

int a int b b = ampa

struct name jname struct name np np = ampname

27

7-2 共用体 共用体は構造体と同じようにして宣言しますが共用体は複数のデータ型を同一のアドレスに

割り当てる方法です union 共用体タグ名 共用体メンバーの並び

「union」は共用体を表すキーワードです 「共用体タグ名」は共用体の型枠の名前を宣言しますここは自由に名前を定義することがで

きます 「共用体メンバーの並び」は共用体の要素です複数指定できます

共用体の宣言の例を次に示します

union c_tag int a char b

共用体 cは次のように共用体タグ c_tagの形式で領域を確保します共用体はメモリ上に領域を確保するときは ab ともに同じ領域に割り付けられます これはab という2つのデータが同時に存在するわけではなく cを異なるデータ abで共有す

ることを表しています c a b

上記の宣言だけでは共用体の形式を宣言しているだけでメモリ中で実際の領域を確保して

いるわけではありません実際に領域を確保するためには次のように定義します union 構造体タグ名 構造体名

したがって共用体名を c とすると次のように指定します

union c_tag c

(1)共用体の参照

プログラム中で共用体中のメンバーを参照する場合には次のように指定します 共用体名メンバー名

したがって「a」または「b」を参照したいときには次のように指定します

ca (int 型) cb (char 型)

メンバー参照方法によって int型として使ったりchar型として利用することができます

28

[プログラム例]

includeltstdiohgt main() union data char a short b int c chk chkc = 0x12345678 printf( char a xyennchka) printf( short b xyennchkb) printf( int c xyennchkc)

chkb(int 型) chkb(short 型) chka(char 型) 12 12 12 34 34 56 78

29

第8章 アルゴリズム コンピュータに何か仕事をさせようとするときは仕事を具体的に実行するための処理や動作

の手順が必要ですこの「手順」がアルゴリズムです アルゴリズムを考えるときは解くべき問題をはっきりと定義することが必要です

8-1 ソート ソートとは与えられたデータを小さい順または大きい順に並べ換えることですソート方法は

いくつかありますが基本的な方法でソートするアルゴリズムを紹介します

includeltstdiohgt int data[10] main()

int data_in() sort() data_in() sort() int data_in() データ入力関数

int a printf(数値入力yenn)

for(a=0alt=9a++) printf( [d]a+1) scanf(dampdata[a]) int sort() ソート処理を行う関数

int cont1cont2tmp1tmp2mim for(cont1=0 cont1lt=9 cont1++) mim=data[cont1] tmp1=cont1 for(cont2=cont1+1 cont2lt=9 cont2++) if(data[cont2] lt mim) mim=data[cont2] tmp1=cont2 tmp2 = data[cont1] data[cont1] = data[tmp1] data[tmp1] = tmp2 printf(結果 yenn)

for (cont1 = 0 cont1 lt= 9 cont1++) printf(d yenn data[cont1])

30

第9章 プリプロセッサ C言語にはプログラムの中でコンパイルについての指示を行う「プリプロセッサ」という機能が

ありますまたプリプロセッサとはコンパイルする前に実行されるためその意味のとおり「前処理」 と呼ばれていますここでは代表的なものをいくつか説明します

9-1 ファイルの挿入 ソースプログラム中に指定されたファイルを挿入します

include ltstdiohgt helliphellip 標準ディレクトリを探します include progh helliphellip 現在のディレクトリを探しなければ標準ディレクトリを探します

includeltstdiohgt によって組み込まれた define EOF (-1) define EOF (-1) define define helliphelliphelliphellip 組み込み helliphelliphelliphellip

main() stdiohファイル

int helliphelliphelliphellip helliphelliphelliphellip

ソースファイル

9-2 文字の置換 プログラム中に使われている文字列を別の文字列に置き換えます

include ltstdiohgt define TRUE 1 define EOF (-1) main() define helliphellip helliphellip

while(TRUE) define TRUE 1 置き換え main() helliphellip helliphellip while(1)

break helliphelliphellip

31

9-3 条件によるコンパイル 識別子が定義されているか否かを判断しコンパイルする範囲を指定します

include ltstdiohgt define UNIX main() ifdef UNIX printf( UNIX yenn) else printf(MS-DOSyenn) endif

include ltstdiohgt define OS UNIX main() if OS == UNIX printf( UNIX yenn) else printf(MS-DOSyenn) endif

32

付 録 1 puts()gets()関数について

行単位に入出力を行う場合には puts() gets() 関数を用います

puts() 標準出力に文字列を出力します

include ltstdiohgt int puts( char s ) puts() は NULL で終る文字列 s を標準出力に出力し最後に改行文字 yenn も出力しま

gets() 標準入力から文字列を入力します

include ltstdiohgt char gets( char s ) 戻り値正常に入力した場合には引数 s の値が返されますエラーやEOFになった場合に

は NULL が返されます gets() は標準入力から復帰文字で終る文字列を入力しs に格納しますこのとき最後の復

帰文字は NULL文字に変更されます

入力行の出力 標準入力から gets() で入力したデータには改行コードは含まれませんまた標準出力へ

puts() で出力を行う場合には必ず改行コードが付加されますgets() を実行したときの戻り値としてファイルの終端を検出した場合には EOF ではなく NULL が返されますので注意して下さい

include ltstdiohgt main() char data[80] while( gets( data ) = NULL )puts( data )

putchar()getchar()関数について putchar() 標準出力に文字を出力します

include ltstdiohgt int putchar(int c ) 戻り値正常に出力できた場合には文字cをエラーの場合にはEOFを返します

33

getchar() 標準入力から文字を入力します

include ltstdiohgt int getchar(void) 戻り値正常に入力した場合には読み込んだ文字を int 型に変換して返しますまたファイ

ルエンドエラーの場合にはEOFを返します

標準入力標準出力

標準入力標準出力はプログラムが開始されるときにはオープンされていますそれぞれのフ

ァイルポインタは stdin stdout になっていますfopen() fclose() をせずとも使用することができます

scanf() 標準出力ストリームからテキストを読み込み解釈します include ltstdiohgt int scanf( const char format [ address ] ) 戻り値正しくスキャンし変換し格納した入力フィールドの数を返しますファイルエンドを読

み込んだ場合は戻り値は EOF となります値を格納したフィールドがなかった場合は戻り値は0となります

一連の入力フィールドをスキャンして1度に1文字ずつストリーム stdin から文字を読み込み

ます次に引き数 format によって指される書式文字列中の書式指定に従って各フィールドを書式化します最後にformat の後に続く各引き数が示しているアドレスに書式化した入力を格納していきます書式文字列中の書式指定の個数はその後に続くアドレスの数と同じでな

ければなりません 書式指定[入力幅][型指定文字] 入力幅 読むべき文字数の最大値 型指定文字 次のとおりです 型指定文字 期待される入力 引き数の型 d 10進整数 int へのポインタ( int arg ) x 16進整数 int へのポインタ( int arg ) f 浮動小数点数 float へのポインタ( float arg ) s 文字列 文字配列へのポインタ( char arg[] ) c 文字 文字へのポインタ( char arg )

printf() フォーマットを指定してテキスト標準出力ストリームに出力します include ltstdiohgt int printf( const char format [ argument ] ) 戻り値出力したバイト数を返しますエラーの場合は EOF を返します

34

format によって指される書式文字列中の書式指定をformat の後に続く各引き数に適用し

書式化されたデータを stdout に出力します書式指定は後に続く引き数と同じ数だけなければなりません

書式指定[印字幅][精度][型指定文字] 印字幅 印字する最小文字数 精度 印字する最大文字数 型指定文字 つぎのとおりです 型指定文字 入力引き数 出力の書式 d 整数 符号付き10進整数 x 整数 符号無し16進整数 f 浮動小数点 符号付きの dddddddd形式の値 c 文字 1個の文字 s 文字列ポインタ ヌル文字に出会うか精度に達するまで 文字をプリントする

fopen()fclose()関数について fopen() ファイルをオープンします

include ltstdiohgt FILE fopen( char filename char mode ) 戻り値正常にファイルのオープンができたらファイルポインタを返しますエラーがあった場

合には NULLを返します 文字列 filename で指定されたファイルをオープンしますオープン後の入出力のモードに

ついては文字列 mode で指定しますmode に指定できる文字は以下のとおりです r 入力モードでオープンします w 出力モードでオープンします a 存在するファイルに追加して出力するモードでオープンします r+ 既に作成してあるファイルを更新(入力出力)するモードでオープンします w+ 新しく作成するファイルを更新モードでオープンします a+ 既に作成してあるファイルの終りから更新用に作成します

以上の文字に b をつけ加えることによりバイナリモードで入出力することができるようになり

ます rb バイナリの入力モードでオープンします wb バイナリの出力モードでオープンします ab 存在するファイルに追加して出力するモード(バイナリ)でオープンします

fclose() 既にオープンしてあるファイルをクローズします include ltstdiohgt fclose( FILE fp ) 既にオープンしているファイルをクローズしますパラメータには fopen() 関数により返された

ファイルポインタを指定します

35

テキストモードとバイナリモード 行の最後はテキストモードの場合改行コードのみとなりバイナリモードの場合には復帰

コードと改行コードの組合わせになります行の最後としてテキストファイルには復帰コード改行

コードが書かれていますがテキストモードでオープンした場合には入力すると改行コードのみに

変換されて入力されますバイナリモードの場合には復帰コード改行コードがそれぞれ入力され

ます

fputs()fgets()関数について fputs() ファイルポインタで指定されるファイルに文字列を出力します

include ltstdiohgt

int fputs( char s FILE fp ) fputs() は NULL で終る文字列 s をファイルポインタに示されるファイルへ出力しますputs()

と違い最後に改行文字 yenn を出力することはありません

fgets() ファイルポインタで指定されるファイルから文字列を入力します include ltstdiohgt char fgets( char s int n FILE fp ) 戻り値正常に入力した場合には引数 s の値が返されますエラーやEOFになった場合に

は NULL が返されます fgets() はファイルポインタで指定されるファイルから ( n - 1 ) 文字または改行文字までの

文字列を入力しs に格納しますgets() と異なり最後に入力された改行文字は NULL 文字に変更されません

標準入力から入力しファイルへ出力する ファイルへ出力あるいは入力を行う場合には改行コードの変換(入力の場合の削除出力の

場合の付加)はされませんしたがって標準入力から入力しファイルへ出力する場合には改行

コードを付加しなければなりません include ltstdiohgt main() char data[80] FILE fp fp = fopen( data w ) while( gets( data ) = NULL ) strcat( data yenn ) 改行コードの付加

fputs( data fp ) fclose( fp )

36

fputc()fgetc()関数について fputc() ファイルポインタで指定されるファイルに1文字出力します

include ltstdiohgt int fputc( int c FILE fp ) 戻り値正常に出力できた場合には文字 c を返しエラーの場合には EOF を返します fputc() は文字 c をファイルポインタで示されるファイルへ出力します

fgetc() ファイルポインタで指定されるファイルから1文字入力します

include ltstdiohgt int fgetc( FILE fp ) 戻り値正常に入力した場合には入力した文字を返しますエラーやEOFになった場合には

EOF が返されます fgetc() はファイルポインタで指定されるファイルから文字を入力します

ファイルの内容の表示 include ltstdiohgt main() FILE fp int ch char fname[30] printf( Key in Fila name gt ) gets( fname ) fp = fopen( fname r ) while( ( ch = fgetc( fp ) ) = EOF )putchar( ch ) fclose( fp )

その他テキスト中で使用された関数について sin() 三角関数の正弦を計算します

include ltmathhgt double sin(double radian) sinはラジアンを単位とする引数 radianの三角関数を計算します

37

strcpy() 文字列を他の文字列へコピーします

include ltstringhgt char strcpy(char string1const char string2) strcpyは引数 string2の指す文字列を null文字まで含めて引数 string1の指す領域にコピ

ーする strcpyは string1を返します

strcat() ある文字列を他の文字列に加えます

include ltstringhgt char strcat( char dest const char src ) 戻り値連結された文字列へのポインタを返します strcat() はsrc のコピーを dest の最後につけ加えます得られる文字列の長さは

strlen(dest)+strlen(src) になります

fabs() 絶対値の計算をします include ltmathhgt double fabs(double z) fabsは倍精度浮動小数の絶対値を計算して返しますつまりzgt=0であれば z をzlt0であ

れば-zを返します exp() 指数関数を計算します

include ltmathhgt double exp(double z) exp は引数zの指数関数つまりezを返すここではeは自然対数の底を表します対数関

数logの逆関数です

38

付 録 2 コンパイルの方法には大きく分けて第4章の実習で学んだようにデータファイルを作成してお

き ccg でコンパイルさせる方法と実行中に対話型でデータを入力していく方法があります ここでは対話型で実行を進めていく方法を紹介します ただしこの方法は計算(cpu)時間が10秒以内のものに限ります10秒を超える計算(cpu)時

間を要する場合はccg でコンパイルをするようにしてください 第4章実習の(2)(p16)までは同様です

コンパイル

コンピュータに処理を依頼します 60us1234boseicc cc rensyuc

所有するファイルの一覧を見てみます

60us1234boseicc ls -l larr 持っているファイルの一覧を見るコマンドです

-rw-r--r-- 1 60us1234 other 128 4月26日 15時14分 rensyuc -rwxr-xr-x 1 60us1234 other 361 4月26日 15時16分 aout

aout という実行形式のファイルが作成されています

実行

60us1234boseicc aout12 35[リターン] データを入力

1 200000 3500000 4200000 実行結果の出力

60us1234boseicc

注意

aout ファイルは印刷することができません実行結果を印刷する場合にはファイルに落とし てから出力するようにしましょう

60us1234boseicc aout gt kekka12 35[リターン] データを入力

60us1234boseicc more kekka 計算結果の確認 60us1234boseicc lpr kekka 計算結果の印刷

39

Page 27: n 第1章 章立ての部分は、書式(PC入門大見出し)を …第2章 数の表現 2-1 2進数 電子計算機の動作原理は0と1で表される2進数です。また、人間が日常生活で扱っている数

Jdata name[30]

address[30] tel[20] age

(1)構造体の参照

プログラム中で構造体中のメンバーを参照する場合には次のように指定します 構造体名メンバー名

したがって「名前」を参照したいときには次のように指定します

jdataname

[プログラム例]

名前住所電話番号年齢を定義しそれを印字します include ltstdiohgt include ltstringhgt main() struct jusho char name[30] char address[30] char tel[20] int age struct jusho jdata strcpy( jdataname 東海 太郎) strcpy( jdataaddress 平塚市北金目1117)

strcpy( jdatatel 0463-58-1211) jdataage = 30 printf(yenn氏名 = syenn jdataname) printf(yenn住所 = syenn jdataaddress) printf(yenn電話番号= syenn jdatatel) printf(yenn年齢 = dyenn jdataage)

また構造体の形式の定義と領域の確保は次のように同時におこなうことができます

struct 構造体タグ名 構造体メンバーの並び 構造体名

struct jusho struct jusho char name[30] char name[30] char address[30] char address[30] char tel[30] = char tel[30] int age 同じ int age

jdata struct jusho jdata

型宣言と同時にメモリ上に領域を確保する方法 後からメモリ上に領域を確保する方法

25

(2) 構造体配列 住所録データの場合その中に入るデータは1件ではありませんやはり100件200件のデ

ータが必要になる場合がありますこのように個人単位のデータを多数扱う場合には構造体を配

列として宣言することができます 次の例は個人のデータを100個用意するために構造体を配列として宣言しています struct jusho jdata[100] jdata[0] name[30] address[30] tel[20] age

jdata[99 ] name[30] address[30] tel[20] age

(3)構造体配列の参照

プログラム中で構造体配列中のメンバーを参照する場合には次のように指定します 構造体名[要素番号]メンバー名

したがって10件目の人の「名前」を参照したいときには次のように指定します

jdata[10]name

[プログラム例]

名前住所電話番号年齢を定義しそれを印字します include ltstdiohgt include ltstringhgt main() struct jusho char name[30] char address[30] char tel[20] int age jdata[100] strcpy( jdata[10]name 東海 太郎) strcpy( jdata[10]address 平塚市北金目1117)

strcpy( jdata[10]tel 0463-58-1211) jdata[10]age = 30 printf(yenn氏名 = syenn jdata[10]name) printf(yenn住所 = syenn jdata[10]address) printf(yenn電話番号= syenn jdata[10]tel) printf(yenn年齢 = dyenn jdata[10]age)

26

(4) 構造体のポインタ 変数と同じように構造体へのポインタも定義することができます

変数へのポインタ例 構造体へのポインタ例 またポインタを使用して構造体メンバーを参照するには次のように -> 記号を使って指

定します ポインタ変数名 -> メンバー名

[プログラム例]

名前住所電話番号年齢を定義しそれを印字します include ltstdiohgt include ltstringhgt main() struct jusho char name[30] char address[30] char tel[20] int age jdatakp kp = ampjdata strcpy( kp-gtname 東海 太郎)

strcpy( kp-gtaddress 平塚市北金目1117)

strcpy( kp-gttel 0463-58-1211) kp-gtage = 30 printf(yenn氏名 = syenn kp-gtname) printf(yenn住所 = syenn kp-gtaddress) printf(yenn電話番号= syenn kp-gttel) printf(yenn年齢 = dyenn kp-gtage)

kp jdata

name[30] ポインタ型の変数 address[30]

tel[20]

構造体へのポインタを記憶 age

することができます

int a int b b = ampa

struct name jname struct name np np = ampname

27

7-2 共用体 共用体は構造体と同じようにして宣言しますが共用体は複数のデータ型を同一のアドレスに

割り当てる方法です union 共用体タグ名 共用体メンバーの並び

「union」は共用体を表すキーワードです 「共用体タグ名」は共用体の型枠の名前を宣言しますここは自由に名前を定義することがで

きます 「共用体メンバーの並び」は共用体の要素です複数指定できます

共用体の宣言の例を次に示します

union c_tag int a char b

共用体 cは次のように共用体タグ c_tagの形式で領域を確保します共用体はメモリ上に領域を確保するときは ab ともに同じ領域に割り付けられます これはab という2つのデータが同時に存在するわけではなく cを異なるデータ abで共有す

ることを表しています c a b

上記の宣言だけでは共用体の形式を宣言しているだけでメモリ中で実際の領域を確保して

いるわけではありません実際に領域を確保するためには次のように定義します union 構造体タグ名 構造体名

したがって共用体名を c とすると次のように指定します

union c_tag c

(1)共用体の参照

プログラム中で共用体中のメンバーを参照する場合には次のように指定します 共用体名メンバー名

したがって「a」または「b」を参照したいときには次のように指定します

ca (int 型) cb (char 型)

メンバー参照方法によって int型として使ったりchar型として利用することができます

28

[プログラム例]

includeltstdiohgt main() union data char a short b int c chk chkc = 0x12345678 printf( char a xyennchka) printf( short b xyennchkb) printf( int c xyennchkc)

chkb(int 型) chkb(short 型) chka(char 型) 12 12 12 34 34 56 78

29

第8章 アルゴリズム コンピュータに何か仕事をさせようとするときは仕事を具体的に実行するための処理や動作

の手順が必要ですこの「手順」がアルゴリズムです アルゴリズムを考えるときは解くべき問題をはっきりと定義することが必要です

8-1 ソート ソートとは与えられたデータを小さい順または大きい順に並べ換えることですソート方法は

いくつかありますが基本的な方法でソートするアルゴリズムを紹介します

includeltstdiohgt int data[10] main()

int data_in() sort() data_in() sort() int data_in() データ入力関数

int a printf(数値入力yenn)

for(a=0alt=9a++) printf( [d]a+1) scanf(dampdata[a]) int sort() ソート処理を行う関数

int cont1cont2tmp1tmp2mim for(cont1=0 cont1lt=9 cont1++) mim=data[cont1] tmp1=cont1 for(cont2=cont1+1 cont2lt=9 cont2++) if(data[cont2] lt mim) mim=data[cont2] tmp1=cont2 tmp2 = data[cont1] data[cont1] = data[tmp1] data[tmp1] = tmp2 printf(結果 yenn)

for (cont1 = 0 cont1 lt= 9 cont1++) printf(d yenn data[cont1])

30

第9章 プリプロセッサ C言語にはプログラムの中でコンパイルについての指示を行う「プリプロセッサ」という機能が

ありますまたプリプロセッサとはコンパイルする前に実行されるためその意味のとおり「前処理」 と呼ばれていますここでは代表的なものをいくつか説明します

9-1 ファイルの挿入 ソースプログラム中に指定されたファイルを挿入します

include ltstdiohgt helliphellip 標準ディレクトリを探します include progh helliphellip 現在のディレクトリを探しなければ標準ディレクトリを探します

includeltstdiohgt によって組み込まれた define EOF (-1) define EOF (-1) define define helliphelliphelliphellip 組み込み helliphelliphelliphellip

main() stdiohファイル

int helliphelliphelliphellip helliphelliphelliphellip

ソースファイル

9-2 文字の置換 プログラム中に使われている文字列を別の文字列に置き換えます

include ltstdiohgt define TRUE 1 define EOF (-1) main() define helliphellip helliphellip

while(TRUE) define TRUE 1 置き換え main() helliphellip helliphellip while(1)

break helliphelliphellip

31

9-3 条件によるコンパイル 識別子が定義されているか否かを判断しコンパイルする範囲を指定します

include ltstdiohgt define UNIX main() ifdef UNIX printf( UNIX yenn) else printf(MS-DOSyenn) endif

include ltstdiohgt define OS UNIX main() if OS == UNIX printf( UNIX yenn) else printf(MS-DOSyenn) endif

32

付 録 1 puts()gets()関数について

行単位に入出力を行う場合には puts() gets() 関数を用います

puts() 標準出力に文字列を出力します

include ltstdiohgt int puts( char s ) puts() は NULL で終る文字列 s を標準出力に出力し最後に改行文字 yenn も出力しま

gets() 標準入力から文字列を入力します

include ltstdiohgt char gets( char s ) 戻り値正常に入力した場合には引数 s の値が返されますエラーやEOFになった場合に

は NULL が返されます gets() は標準入力から復帰文字で終る文字列を入力しs に格納しますこのとき最後の復

帰文字は NULL文字に変更されます

入力行の出力 標準入力から gets() で入力したデータには改行コードは含まれませんまた標準出力へ

puts() で出力を行う場合には必ず改行コードが付加されますgets() を実行したときの戻り値としてファイルの終端を検出した場合には EOF ではなく NULL が返されますので注意して下さい

include ltstdiohgt main() char data[80] while( gets( data ) = NULL )puts( data )

putchar()getchar()関数について putchar() 標準出力に文字を出力します

include ltstdiohgt int putchar(int c ) 戻り値正常に出力できた場合には文字cをエラーの場合にはEOFを返します

33

getchar() 標準入力から文字を入力します

include ltstdiohgt int getchar(void) 戻り値正常に入力した場合には読み込んだ文字を int 型に変換して返しますまたファイ

ルエンドエラーの場合にはEOFを返します

標準入力標準出力

標準入力標準出力はプログラムが開始されるときにはオープンされていますそれぞれのフ

ァイルポインタは stdin stdout になっていますfopen() fclose() をせずとも使用することができます

scanf() 標準出力ストリームからテキストを読み込み解釈します include ltstdiohgt int scanf( const char format [ address ] ) 戻り値正しくスキャンし変換し格納した入力フィールドの数を返しますファイルエンドを読

み込んだ場合は戻り値は EOF となります値を格納したフィールドがなかった場合は戻り値は0となります

一連の入力フィールドをスキャンして1度に1文字ずつストリーム stdin から文字を読み込み

ます次に引き数 format によって指される書式文字列中の書式指定に従って各フィールドを書式化します最後にformat の後に続く各引き数が示しているアドレスに書式化した入力を格納していきます書式文字列中の書式指定の個数はその後に続くアドレスの数と同じでな

ければなりません 書式指定[入力幅][型指定文字] 入力幅 読むべき文字数の最大値 型指定文字 次のとおりです 型指定文字 期待される入力 引き数の型 d 10進整数 int へのポインタ( int arg ) x 16進整数 int へのポインタ( int arg ) f 浮動小数点数 float へのポインタ( float arg ) s 文字列 文字配列へのポインタ( char arg[] ) c 文字 文字へのポインタ( char arg )

printf() フォーマットを指定してテキスト標準出力ストリームに出力します include ltstdiohgt int printf( const char format [ argument ] ) 戻り値出力したバイト数を返しますエラーの場合は EOF を返します

34

format によって指される書式文字列中の書式指定をformat の後に続く各引き数に適用し

書式化されたデータを stdout に出力します書式指定は後に続く引き数と同じ数だけなければなりません

書式指定[印字幅][精度][型指定文字] 印字幅 印字する最小文字数 精度 印字する最大文字数 型指定文字 つぎのとおりです 型指定文字 入力引き数 出力の書式 d 整数 符号付き10進整数 x 整数 符号無し16進整数 f 浮動小数点 符号付きの dddddddd形式の値 c 文字 1個の文字 s 文字列ポインタ ヌル文字に出会うか精度に達するまで 文字をプリントする

fopen()fclose()関数について fopen() ファイルをオープンします

include ltstdiohgt FILE fopen( char filename char mode ) 戻り値正常にファイルのオープンができたらファイルポインタを返しますエラーがあった場

合には NULLを返します 文字列 filename で指定されたファイルをオープンしますオープン後の入出力のモードに

ついては文字列 mode で指定しますmode に指定できる文字は以下のとおりです r 入力モードでオープンします w 出力モードでオープンします a 存在するファイルに追加して出力するモードでオープンします r+ 既に作成してあるファイルを更新(入力出力)するモードでオープンします w+ 新しく作成するファイルを更新モードでオープンします a+ 既に作成してあるファイルの終りから更新用に作成します

以上の文字に b をつけ加えることによりバイナリモードで入出力することができるようになり

ます rb バイナリの入力モードでオープンします wb バイナリの出力モードでオープンします ab 存在するファイルに追加して出力するモード(バイナリ)でオープンします

fclose() 既にオープンしてあるファイルをクローズします include ltstdiohgt fclose( FILE fp ) 既にオープンしているファイルをクローズしますパラメータには fopen() 関数により返された

ファイルポインタを指定します

35

テキストモードとバイナリモード 行の最後はテキストモードの場合改行コードのみとなりバイナリモードの場合には復帰

コードと改行コードの組合わせになります行の最後としてテキストファイルには復帰コード改行

コードが書かれていますがテキストモードでオープンした場合には入力すると改行コードのみに

変換されて入力されますバイナリモードの場合には復帰コード改行コードがそれぞれ入力され

ます

fputs()fgets()関数について fputs() ファイルポインタで指定されるファイルに文字列を出力します

include ltstdiohgt

int fputs( char s FILE fp ) fputs() は NULL で終る文字列 s をファイルポインタに示されるファイルへ出力しますputs()

と違い最後に改行文字 yenn を出力することはありません

fgets() ファイルポインタで指定されるファイルから文字列を入力します include ltstdiohgt char fgets( char s int n FILE fp ) 戻り値正常に入力した場合には引数 s の値が返されますエラーやEOFになった場合に

は NULL が返されます fgets() はファイルポインタで指定されるファイルから ( n - 1 ) 文字または改行文字までの

文字列を入力しs に格納しますgets() と異なり最後に入力された改行文字は NULL 文字に変更されません

標準入力から入力しファイルへ出力する ファイルへ出力あるいは入力を行う場合には改行コードの変換(入力の場合の削除出力の

場合の付加)はされませんしたがって標準入力から入力しファイルへ出力する場合には改行

コードを付加しなければなりません include ltstdiohgt main() char data[80] FILE fp fp = fopen( data w ) while( gets( data ) = NULL ) strcat( data yenn ) 改行コードの付加

fputs( data fp ) fclose( fp )

36

fputc()fgetc()関数について fputc() ファイルポインタで指定されるファイルに1文字出力します

include ltstdiohgt int fputc( int c FILE fp ) 戻り値正常に出力できた場合には文字 c を返しエラーの場合には EOF を返します fputc() は文字 c をファイルポインタで示されるファイルへ出力します

fgetc() ファイルポインタで指定されるファイルから1文字入力します

include ltstdiohgt int fgetc( FILE fp ) 戻り値正常に入力した場合には入力した文字を返しますエラーやEOFになった場合には

EOF が返されます fgetc() はファイルポインタで指定されるファイルから文字を入力します

ファイルの内容の表示 include ltstdiohgt main() FILE fp int ch char fname[30] printf( Key in Fila name gt ) gets( fname ) fp = fopen( fname r ) while( ( ch = fgetc( fp ) ) = EOF )putchar( ch ) fclose( fp )

その他テキスト中で使用された関数について sin() 三角関数の正弦を計算します

include ltmathhgt double sin(double radian) sinはラジアンを単位とする引数 radianの三角関数を計算します

37

strcpy() 文字列を他の文字列へコピーします

include ltstringhgt char strcpy(char string1const char string2) strcpyは引数 string2の指す文字列を null文字まで含めて引数 string1の指す領域にコピ

ーする strcpyは string1を返します

strcat() ある文字列を他の文字列に加えます

include ltstringhgt char strcat( char dest const char src ) 戻り値連結された文字列へのポインタを返します strcat() はsrc のコピーを dest の最後につけ加えます得られる文字列の長さは

strlen(dest)+strlen(src) になります

fabs() 絶対値の計算をします include ltmathhgt double fabs(double z) fabsは倍精度浮動小数の絶対値を計算して返しますつまりzgt=0であれば z をzlt0であ

れば-zを返します exp() 指数関数を計算します

include ltmathhgt double exp(double z) exp は引数zの指数関数つまりezを返すここではeは自然対数の底を表します対数関

数logの逆関数です

38

付 録 2 コンパイルの方法には大きく分けて第4章の実習で学んだようにデータファイルを作成してお

き ccg でコンパイルさせる方法と実行中に対話型でデータを入力していく方法があります ここでは対話型で実行を進めていく方法を紹介します ただしこの方法は計算(cpu)時間が10秒以内のものに限ります10秒を超える計算(cpu)時

間を要する場合はccg でコンパイルをするようにしてください 第4章実習の(2)(p16)までは同様です

コンパイル

コンピュータに処理を依頼します 60us1234boseicc cc rensyuc

所有するファイルの一覧を見てみます

60us1234boseicc ls -l larr 持っているファイルの一覧を見るコマンドです

-rw-r--r-- 1 60us1234 other 128 4月26日 15時14分 rensyuc -rwxr-xr-x 1 60us1234 other 361 4月26日 15時16分 aout

aout という実行形式のファイルが作成されています

実行

60us1234boseicc aout12 35[リターン] データを入力

1 200000 3500000 4200000 実行結果の出力

60us1234boseicc

注意

aout ファイルは印刷することができません実行結果を印刷する場合にはファイルに落とし てから出力するようにしましょう

60us1234boseicc aout gt kekka12 35[リターン] データを入力

60us1234boseicc more kekka 計算結果の確認 60us1234boseicc lpr kekka 計算結果の印刷

39

Page 28: n 第1章 章立ての部分は、書式(PC入門大見出し)を …第2章 数の表現 2-1 2進数 電子計算機の動作原理は0と1で表される2進数です。また、人間が日常生活で扱っている数

(2) 構造体配列 住所録データの場合その中に入るデータは1件ではありませんやはり100件200件のデ

ータが必要になる場合がありますこのように個人単位のデータを多数扱う場合には構造体を配

列として宣言することができます 次の例は個人のデータを100個用意するために構造体を配列として宣言しています struct jusho jdata[100] jdata[0] name[30] address[30] tel[20] age

jdata[99 ] name[30] address[30] tel[20] age

(3)構造体配列の参照

プログラム中で構造体配列中のメンバーを参照する場合には次のように指定します 構造体名[要素番号]メンバー名

したがって10件目の人の「名前」を参照したいときには次のように指定します

jdata[10]name

[プログラム例]

名前住所電話番号年齢を定義しそれを印字します include ltstdiohgt include ltstringhgt main() struct jusho char name[30] char address[30] char tel[20] int age jdata[100] strcpy( jdata[10]name 東海 太郎) strcpy( jdata[10]address 平塚市北金目1117)

strcpy( jdata[10]tel 0463-58-1211) jdata[10]age = 30 printf(yenn氏名 = syenn jdata[10]name) printf(yenn住所 = syenn jdata[10]address) printf(yenn電話番号= syenn jdata[10]tel) printf(yenn年齢 = dyenn jdata[10]age)

26

(4) 構造体のポインタ 変数と同じように構造体へのポインタも定義することができます

変数へのポインタ例 構造体へのポインタ例 またポインタを使用して構造体メンバーを参照するには次のように -> 記号を使って指

定します ポインタ変数名 -> メンバー名

[プログラム例]

名前住所電話番号年齢を定義しそれを印字します include ltstdiohgt include ltstringhgt main() struct jusho char name[30] char address[30] char tel[20] int age jdatakp kp = ampjdata strcpy( kp-gtname 東海 太郎)

strcpy( kp-gtaddress 平塚市北金目1117)

strcpy( kp-gttel 0463-58-1211) kp-gtage = 30 printf(yenn氏名 = syenn kp-gtname) printf(yenn住所 = syenn kp-gtaddress) printf(yenn電話番号= syenn kp-gttel) printf(yenn年齢 = dyenn kp-gtage)

kp jdata

name[30] ポインタ型の変数 address[30]

tel[20]

構造体へのポインタを記憶 age

することができます

int a int b b = ampa

struct name jname struct name np np = ampname

27

7-2 共用体 共用体は構造体と同じようにして宣言しますが共用体は複数のデータ型を同一のアドレスに

割り当てる方法です union 共用体タグ名 共用体メンバーの並び

「union」は共用体を表すキーワードです 「共用体タグ名」は共用体の型枠の名前を宣言しますここは自由に名前を定義することがで

きます 「共用体メンバーの並び」は共用体の要素です複数指定できます

共用体の宣言の例を次に示します

union c_tag int a char b

共用体 cは次のように共用体タグ c_tagの形式で領域を確保します共用体はメモリ上に領域を確保するときは ab ともに同じ領域に割り付けられます これはab という2つのデータが同時に存在するわけではなく cを異なるデータ abで共有す

ることを表しています c a b

上記の宣言だけでは共用体の形式を宣言しているだけでメモリ中で実際の領域を確保して

いるわけではありません実際に領域を確保するためには次のように定義します union 構造体タグ名 構造体名

したがって共用体名を c とすると次のように指定します

union c_tag c

(1)共用体の参照

プログラム中で共用体中のメンバーを参照する場合には次のように指定します 共用体名メンバー名

したがって「a」または「b」を参照したいときには次のように指定します

ca (int 型) cb (char 型)

メンバー参照方法によって int型として使ったりchar型として利用することができます

28

[プログラム例]

includeltstdiohgt main() union data char a short b int c chk chkc = 0x12345678 printf( char a xyennchka) printf( short b xyennchkb) printf( int c xyennchkc)

chkb(int 型) chkb(short 型) chka(char 型) 12 12 12 34 34 56 78

29

第8章 アルゴリズム コンピュータに何か仕事をさせようとするときは仕事を具体的に実行するための処理や動作

の手順が必要ですこの「手順」がアルゴリズムです アルゴリズムを考えるときは解くべき問題をはっきりと定義することが必要です

8-1 ソート ソートとは与えられたデータを小さい順または大きい順に並べ換えることですソート方法は

いくつかありますが基本的な方法でソートするアルゴリズムを紹介します

includeltstdiohgt int data[10] main()

int data_in() sort() data_in() sort() int data_in() データ入力関数

int a printf(数値入力yenn)

for(a=0alt=9a++) printf( [d]a+1) scanf(dampdata[a]) int sort() ソート処理を行う関数

int cont1cont2tmp1tmp2mim for(cont1=0 cont1lt=9 cont1++) mim=data[cont1] tmp1=cont1 for(cont2=cont1+1 cont2lt=9 cont2++) if(data[cont2] lt mim) mim=data[cont2] tmp1=cont2 tmp2 = data[cont1] data[cont1] = data[tmp1] data[tmp1] = tmp2 printf(結果 yenn)

for (cont1 = 0 cont1 lt= 9 cont1++) printf(d yenn data[cont1])

30

第9章 プリプロセッサ C言語にはプログラムの中でコンパイルについての指示を行う「プリプロセッサ」という機能が

ありますまたプリプロセッサとはコンパイルする前に実行されるためその意味のとおり「前処理」 と呼ばれていますここでは代表的なものをいくつか説明します

9-1 ファイルの挿入 ソースプログラム中に指定されたファイルを挿入します

include ltstdiohgt helliphellip 標準ディレクトリを探します include progh helliphellip 現在のディレクトリを探しなければ標準ディレクトリを探します

includeltstdiohgt によって組み込まれた define EOF (-1) define EOF (-1) define define helliphelliphelliphellip 組み込み helliphelliphelliphellip

main() stdiohファイル

int helliphelliphelliphellip helliphelliphelliphellip

ソースファイル

9-2 文字の置換 プログラム中に使われている文字列を別の文字列に置き換えます

include ltstdiohgt define TRUE 1 define EOF (-1) main() define helliphellip helliphellip

while(TRUE) define TRUE 1 置き換え main() helliphellip helliphellip while(1)

break helliphelliphellip

31

9-3 条件によるコンパイル 識別子が定義されているか否かを判断しコンパイルする範囲を指定します

include ltstdiohgt define UNIX main() ifdef UNIX printf( UNIX yenn) else printf(MS-DOSyenn) endif

include ltstdiohgt define OS UNIX main() if OS == UNIX printf( UNIX yenn) else printf(MS-DOSyenn) endif

32

付 録 1 puts()gets()関数について

行単位に入出力を行う場合には puts() gets() 関数を用います

puts() 標準出力に文字列を出力します

include ltstdiohgt int puts( char s ) puts() は NULL で終る文字列 s を標準出力に出力し最後に改行文字 yenn も出力しま

gets() 標準入力から文字列を入力します

include ltstdiohgt char gets( char s ) 戻り値正常に入力した場合には引数 s の値が返されますエラーやEOFになった場合に

は NULL が返されます gets() は標準入力から復帰文字で終る文字列を入力しs に格納しますこのとき最後の復

帰文字は NULL文字に変更されます

入力行の出力 標準入力から gets() で入力したデータには改行コードは含まれませんまた標準出力へ

puts() で出力を行う場合には必ず改行コードが付加されますgets() を実行したときの戻り値としてファイルの終端を検出した場合には EOF ではなく NULL が返されますので注意して下さい

include ltstdiohgt main() char data[80] while( gets( data ) = NULL )puts( data )

putchar()getchar()関数について putchar() 標準出力に文字を出力します

include ltstdiohgt int putchar(int c ) 戻り値正常に出力できた場合には文字cをエラーの場合にはEOFを返します

33

getchar() 標準入力から文字を入力します

include ltstdiohgt int getchar(void) 戻り値正常に入力した場合には読み込んだ文字を int 型に変換して返しますまたファイ

ルエンドエラーの場合にはEOFを返します

標準入力標準出力

標準入力標準出力はプログラムが開始されるときにはオープンされていますそれぞれのフ

ァイルポインタは stdin stdout になっていますfopen() fclose() をせずとも使用することができます

scanf() 標準出力ストリームからテキストを読み込み解釈します include ltstdiohgt int scanf( const char format [ address ] ) 戻り値正しくスキャンし変換し格納した入力フィールドの数を返しますファイルエンドを読

み込んだ場合は戻り値は EOF となります値を格納したフィールドがなかった場合は戻り値は0となります

一連の入力フィールドをスキャンして1度に1文字ずつストリーム stdin から文字を読み込み

ます次に引き数 format によって指される書式文字列中の書式指定に従って各フィールドを書式化します最後にformat の後に続く各引き数が示しているアドレスに書式化した入力を格納していきます書式文字列中の書式指定の個数はその後に続くアドレスの数と同じでな

ければなりません 書式指定[入力幅][型指定文字] 入力幅 読むべき文字数の最大値 型指定文字 次のとおりです 型指定文字 期待される入力 引き数の型 d 10進整数 int へのポインタ( int arg ) x 16進整数 int へのポインタ( int arg ) f 浮動小数点数 float へのポインタ( float arg ) s 文字列 文字配列へのポインタ( char arg[] ) c 文字 文字へのポインタ( char arg )

printf() フォーマットを指定してテキスト標準出力ストリームに出力します include ltstdiohgt int printf( const char format [ argument ] ) 戻り値出力したバイト数を返しますエラーの場合は EOF を返します

34

format によって指される書式文字列中の書式指定をformat の後に続く各引き数に適用し

書式化されたデータを stdout に出力します書式指定は後に続く引き数と同じ数だけなければなりません

書式指定[印字幅][精度][型指定文字] 印字幅 印字する最小文字数 精度 印字する最大文字数 型指定文字 つぎのとおりです 型指定文字 入力引き数 出力の書式 d 整数 符号付き10進整数 x 整数 符号無し16進整数 f 浮動小数点 符号付きの dddddddd形式の値 c 文字 1個の文字 s 文字列ポインタ ヌル文字に出会うか精度に達するまで 文字をプリントする

fopen()fclose()関数について fopen() ファイルをオープンします

include ltstdiohgt FILE fopen( char filename char mode ) 戻り値正常にファイルのオープンができたらファイルポインタを返しますエラーがあった場

合には NULLを返します 文字列 filename で指定されたファイルをオープンしますオープン後の入出力のモードに

ついては文字列 mode で指定しますmode に指定できる文字は以下のとおりです r 入力モードでオープンします w 出力モードでオープンします a 存在するファイルに追加して出力するモードでオープンします r+ 既に作成してあるファイルを更新(入力出力)するモードでオープンします w+ 新しく作成するファイルを更新モードでオープンします a+ 既に作成してあるファイルの終りから更新用に作成します

以上の文字に b をつけ加えることによりバイナリモードで入出力することができるようになり

ます rb バイナリの入力モードでオープンします wb バイナリの出力モードでオープンします ab 存在するファイルに追加して出力するモード(バイナリ)でオープンします

fclose() 既にオープンしてあるファイルをクローズします include ltstdiohgt fclose( FILE fp ) 既にオープンしているファイルをクローズしますパラメータには fopen() 関数により返された

ファイルポインタを指定します

35

テキストモードとバイナリモード 行の最後はテキストモードの場合改行コードのみとなりバイナリモードの場合には復帰

コードと改行コードの組合わせになります行の最後としてテキストファイルには復帰コード改行

コードが書かれていますがテキストモードでオープンした場合には入力すると改行コードのみに

変換されて入力されますバイナリモードの場合には復帰コード改行コードがそれぞれ入力され

ます

fputs()fgets()関数について fputs() ファイルポインタで指定されるファイルに文字列を出力します

include ltstdiohgt

int fputs( char s FILE fp ) fputs() は NULL で終る文字列 s をファイルポインタに示されるファイルへ出力しますputs()

と違い最後に改行文字 yenn を出力することはありません

fgets() ファイルポインタで指定されるファイルから文字列を入力します include ltstdiohgt char fgets( char s int n FILE fp ) 戻り値正常に入力した場合には引数 s の値が返されますエラーやEOFになった場合に

は NULL が返されます fgets() はファイルポインタで指定されるファイルから ( n - 1 ) 文字または改行文字までの

文字列を入力しs に格納しますgets() と異なり最後に入力された改行文字は NULL 文字に変更されません

標準入力から入力しファイルへ出力する ファイルへ出力あるいは入力を行う場合には改行コードの変換(入力の場合の削除出力の

場合の付加)はされませんしたがって標準入力から入力しファイルへ出力する場合には改行

コードを付加しなければなりません include ltstdiohgt main() char data[80] FILE fp fp = fopen( data w ) while( gets( data ) = NULL ) strcat( data yenn ) 改行コードの付加

fputs( data fp ) fclose( fp )

36

fputc()fgetc()関数について fputc() ファイルポインタで指定されるファイルに1文字出力します

include ltstdiohgt int fputc( int c FILE fp ) 戻り値正常に出力できた場合には文字 c を返しエラーの場合には EOF を返します fputc() は文字 c をファイルポインタで示されるファイルへ出力します

fgetc() ファイルポインタで指定されるファイルから1文字入力します

include ltstdiohgt int fgetc( FILE fp ) 戻り値正常に入力した場合には入力した文字を返しますエラーやEOFになった場合には

EOF が返されます fgetc() はファイルポインタで指定されるファイルから文字を入力します

ファイルの内容の表示 include ltstdiohgt main() FILE fp int ch char fname[30] printf( Key in Fila name gt ) gets( fname ) fp = fopen( fname r ) while( ( ch = fgetc( fp ) ) = EOF )putchar( ch ) fclose( fp )

その他テキスト中で使用された関数について sin() 三角関数の正弦を計算します

include ltmathhgt double sin(double radian) sinはラジアンを単位とする引数 radianの三角関数を計算します

37

strcpy() 文字列を他の文字列へコピーします

include ltstringhgt char strcpy(char string1const char string2) strcpyは引数 string2の指す文字列を null文字まで含めて引数 string1の指す領域にコピ

ーする strcpyは string1を返します

strcat() ある文字列を他の文字列に加えます

include ltstringhgt char strcat( char dest const char src ) 戻り値連結された文字列へのポインタを返します strcat() はsrc のコピーを dest の最後につけ加えます得られる文字列の長さは

strlen(dest)+strlen(src) になります

fabs() 絶対値の計算をします include ltmathhgt double fabs(double z) fabsは倍精度浮動小数の絶対値を計算して返しますつまりzgt=0であれば z をzlt0であ

れば-zを返します exp() 指数関数を計算します

include ltmathhgt double exp(double z) exp は引数zの指数関数つまりezを返すここではeは自然対数の底を表します対数関

数logの逆関数です

38

付 録 2 コンパイルの方法には大きく分けて第4章の実習で学んだようにデータファイルを作成してお

き ccg でコンパイルさせる方法と実行中に対話型でデータを入力していく方法があります ここでは対話型で実行を進めていく方法を紹介します ただしこの方法は計算(cpu)時間が10秒以内のものに限ります10秒を超える計算(cpu)時

間を要する場合はccg でコンパイルをするようにしてください 第4章実習の(2)(p16)までは同様です

コンパイル

コンピュータに処理を依頼します 60us1234boseicc cc rensyuc

所有するファイルの一覧を見てみます

60us1234boseicc ls -l larr 持っているファイルの一覧を見るコマンドです

-rw-r--r-- 1 60us1234 other 128 4月26日 15時14分 rensyuc -rwxr-xr-x 1 60us1234 other 361 4月26日 15時16分 aout

aout という実行形式のファイルが作成されています

実行

60us1234boseicc aout12 35[リターン] データを入力

1 200000 3500000 4200000 実行結果の出力

60us1234boseicc

注意

aout ファイルは印刷することができません実行結果を印刷する場合にはファイルに落とし てから出力するようにしましょう

60us1234boseicc aout gt kekka12 35[リターン] データを入力

60us1234boseicc more kekka 計算結果の確認 60us1234boseicc lpr kekka 計算結果の印刷

39

Page 29: n 第1章 章立ての部分は、書式(PC入門大見出し)を …第2章 数の表現 2-1 2進数 電子計算機の動作原理は0と1で表される2進数です。また、人間が日常生活で扱っている数

(4) 構造体のポインタ 変数と同じように構造体へのポインタも定義することができます

変数へのポインタ例 構造体へのポインタ例 またポインタを使用して構造体メンバーを参照するには次のように -> 記号を使って指

定します ポインタ変数名 -> メンバー名

[プログラム例]

名前住所電話番号年齢を定義しそれを印字します include ltstdiohgt include ltstringhgt main() struct jusho char name[30] char address[30] char tel[20] int age jdatakp kp = ampjdata strcpy( kp-gtname 東海 太郎)

strcpy( kp-gtaddress 平塚市北金目1117)

strcpy( kp-gttel 0463-58-1211) kp-gtage = 30 printf(yenn氏名 = syenn kp-gtname) printf(yenn住所 = syenn kp-gtaddress) printf(yenn電話番号= syenn kp-gttel) printf(yenn年齢 = dyenn kp-gtage)

kp jdata

name[30] ポインタ型の変数 address[30]

tel[20]

構造体へのポインタを記憶 age

することができます

int a int b b = ampa

struct name jname struct name np np = ampname

27

7-2 共用体 共用体は構造体と同じようにして宣言しますが共用体は複数のデータ型を同一のアドレスに

割り当てる方法です union 共用体タグ名 共用体メンバーの並び

「union」は共用体を表すキーワードです 「共用体タグ名」は共用体の型枠の名前を宣言しますここは自由に名前を定義することがで

きます 「共用体メンバーの並び」は共用体の要素です複数指定できます

共用体の宣言の例を次に示します

union c_tag int a char b

共用体 cは次のように共用体タグ c_tagの形式で領域を確保します共用体はメモリ上に領域を確保するときは ab ともに同じ領域に割り付けられます これはab という2つのデータが同時に存在するわけではなく cを異なるデータ abで共有す

ることを表しています c a b

上記の宣言だけでは共用体の形式を宣言しているだけでメモリ中で実際の領域を確保して

いるわけではありません実際に領域を確保するためには次のように定義します union 構造体タグ名 構造体名

したがって共用体名を c とすると次のように指定します

union c_tag c

(1)共用体の参照

プログラム中で共用体中のメンバーを参照する場合には次のように指定します 共用体名メンバー名

したがって「a」または「b」を参照したいときには次のように指定します

ca (int 型) cb (char 型)

メンバー参照方法によって int型として使ったりchar型として利用することができます

28

[プログラム例]

includeltstdiohgt main() union data char a short b int c chk chkc = 0x12345678 printf( char a xyennchka) printf( short b xyennchkb) printf( int c xyennchkc)

chkb(int 型) chkb(short 型) chka(char 型) 12 12 12 34 34 56 78

29

第8章 アルゴリズム コンピュータに何か仕事をさせようとするときは仕事を具体的に実行するための処理や動作

の手順が必要ですこの「手順」がアルゴリズムです アルゴリズムを考えるときは解くべき問題をはっきりと定義することが必要です

8-1 ソート ソートとは与えられたデータを小さい順または大きい順に並べ換えることですソート方法は

いくつかありますが基本的な方法でソートするアルゴリズムを紹介します

includeltstdiohgt int data[10] main()

int data_in() sort() data_in() sort() int data_in() データ入力関数

int a printf(数値入力yenn)

for(a=0alt=9a++) printf( [d]a+1) scanf(dampdata[a]) int sort() ソート処理を行う関数

int cont1cont2tmp1tmp2mim for(cont1=0 cont1lt=9 cont1++) mim=data[cont1] tmp1=cont1 for(cont2=cont1+1 cont2lt=9 cont2++) if(data[cont2] lt mim) mim=data[cont2] tmp1=cont2 tmp2 = data[cont1] data[cont1] = data[tmp1] data[tmp1] = tmp2 printf(結果 yenn)

for (cont1 = 0 cont1 lt= 9 cont1++) printf(d yenn data[cont1])

30

第9章 プリプロセッサ C言語にはプログラムの中でコンパイルについての指示を行う「プリプロセッサ」という機能が

ありますまたプリプロセッサとはコンパイルする前に実行されるためその意味のとおり「前処理」 と呼ばれていますここでは代表的なものをいくつか説明します

9-1 ファイルの挿入 ソースプログラム中に指定されたファイルを挿入します

include ltstdiohgt helliphellip 標準ディレクトリを探します include progh helliphellip 現在のディレクトリを探しなければ標準ディレクトリを探します

includeltstdiohgt によって組み込まれた define EOF (-1) define EOF (-1) define define helliphelliphelliphellip 組み込み helliphelliphelliphellip

main() stdiohファイル

int helliphelliphelliphellip helliphelliphelliphellip

ソースファイル

9-2 文字の置換 プログラム中に使われている文字列を別の文字列に置き換えます

include ltstdiohgt define TRUE 1 define EOF (-1) main() define helliphellip helliphellip

while(TRUE) define TRUE 1 置き換え main() helliphellip helliphellip while(1)

break helliphelliphellip

31

9-3 条件によるコンパイル 識別子が定義されているか否かを判断しコンパイルする範囲を指定します

include ltstdiohgt define UNIX main() ifdef UNIX printf( UNIX yenn) else printf(MS-DOSyenn) endif

include ltstdiohgt define OS UNIX main() if OS == UNIX printf( UNIX yenn) else printf(MS-DOSyenn) endif

32

付 録 1 puts()gets()関数について

行単位に入出力を行う場合には puts() gets() 関数を用います

puts() 標準出力に文字列を出力します

include ltstdiohgt int puts( char s ) puts() は NULL で終る文字列 s を標準出力に出力し最後に改行文字 yenn も出力しま

gets() 標準入力から文字列を入力します

include ltstdiohgt char gets( char s ) 戻り値正常に入力した場合には引数 s の値が返されますエラーやEOFになった場合に

は NULL が返されます gets() は標準入力から復帰文字で終る文字列を入力しs に格納しますこのとき最後の復

帰文字は NULL文字に変更されます

入力行の出力 標準入力から gets() で入力したデータには改行コードは含まれませんまた標準出力へ

puts() で出力を行う場合には必ず改行コードが付加されますgets() を実行したときの戻り値としてファイルの終端を検出した場合には EOF ではなく NULL が返されますので注意して下さい

include ltstdiohgt main() char data[80] while( gets( data ) = NULL )puts( data )

putchar()getchar()関数について putchar() 標準出力に文字を出力します

include ltstdiohgt int putchar(int c ) 戻り値正常に出力できた場合には文字cをエラーの場合にはEOFを返します

33

getchar() 標準入力から文字を入力します

include ltstdiohgt int getchar(void) 戻り値正常に入力した場合には読み込んだ文字を int 型に変換して返しますまたファイ

ルエンドエラーの場合にはEOFを返します

標準入力標準出力

標準入力標準出力はプログラムが開始されるときにはオープンされていますそれぞれのフ

ァイルポインタは stdin stdout になっていますfopen() fclose() をせずとも使用することができます

scanf() 標準出力ストリームからテキストを読み込み解釈します include ltstdiohgt int scanf( const char format [ address ] ) 戻り値正しくスキャンし変換し格納した入力フィールドの数を返しますファイルエンドを読

み込んだ場合は戻り値は EOF となります値を格納したフィールドがなかった場合は戻り値は0となります

一連の入力フィールドをスキャンして1度に1文字ずつストリーム stdin から文字を読み込み

ます次に引き数 format によって指される書式文字列中の書式指定に従って各フィールドを書式化します最後にformat の後に続く各引き数が示しているアドレスに書式化した入力を格納していきます書式文字列中の書式指定の個数はその後に続くアドレスの数と同じでな

ければなりません 書式指定[入力幅][型指定文字] 入力幅 読むべき文字数の最大値 型指定文字 次のとおりです 型指定文字 期待される入力 引き数の型 d 10進整数 int へのポインタ( int arg ) x 16進整数 int へのポインタ( int arg ) f 浮動小数点数 float へのポインタ( float arg ) s 文字列 文字配列へのポインタ( char arg[] ) c 文字 文字へのポインタ( char arg )

printf() フォーマットを指定してテキスト標準出力ストリームに出力します include ltstdiohgt int printf( const char format [ argument ] ) 戻り値出力したバイト数を返しますエラーの場合は EOF を返します

34

format によって指される書式文字列中の書式指定をformat の後に続く各引き数に適用し

書式化されたデータを stdout に出力します書式指定は後に続く引き数と同じ数だけなければなりません

書式指定[印字幅][精度][型指定文字] 印字幅 印字する最小文字数 精度 印字する最大文字数 型指定文字 つぎのとおりです 型指定文字 入力引き数 出力の書式 d 整数 符号付き10進整数 x 整数 符号無し16進整数 f 浮動小数点 符号付きの dddddddd形式の値 c 文字 1個の文字 s 文字列ポインタ ヌル文字に出会うか精度に達するまで 文字をプリントする

fopen()fclose()関数について fopen() ファイルをオープンします

include ltstdiohgt FILE fopen( char filename char mode ) 戻り値正常にファイルのオープンができたらファイルポインタを返しますエラーがあった場

合には NULLを返します 文字列 filename で指定されたファイルをオープンしますオープン後の入出力のモードに

ついては文字列 mode で指定しますmode に指定できる文字は以下のとおりです r 入力モードでオープンします w 出力モードでオープンします a 存在するファイルに追加して出力するモードでオープンします r+ 既に作成してあるファイルを更新(入力出力)するモードでオープンします w+ 新しく作成するファイルを更新モードでオープンします a+ 既に作成してあるファイルの終りから更新用に作成します

以上の文字に b をつけ加えることによりバイナリモードで入出力することができるようになり

ます rb バイナリの入力モードでオープンします wb バイナリの出力モードでオープンします ab 存在するファイルに追加して出力するモード(バイナリ)でオープンします

fclose() 既にオープンしてあるファイルをクローズします include ltstdiohgt fclose( FILE fp ) 既にオープンしているファイルをクローズしますパラメータには fopen() 関数により返された

ファイルポインタを指定します

35

テキストモードとバイナリモード 行の最後はテキストモードの場合改行コードのみとなりバイナリモードの場合には復帰

コードと改行コードの組合わせになります行の最後としてテキストファイルには復帰コード改行

コードが書かれていますがテキストモードでオープンした場合には入力すると改行コードのみに

変換されて入力されますバイナリモードの場合には復帰コード改行コードがそれぞれ入力され

ます

fputs()fgets()関数について fputs() ファイルポインタで指定されるファイルに文字列を出力します

include ltstdiohgt

int fputs( char s FILE fp ) fputs() は NULL で終る文字列 s をファイルポインタに示されるファイルへ出力しますputs()

と違い最後に改行文字 yenn を出力することはありません

fgets() ファイルポインタで指定されるファイルから文字列を入力します include ltstdiohgt char fgets( char s int n FILE fp ) 戻り値正常に入力した場合には引数 s の値が返されますエラーやEOFになった場合に

は NULL が返されます fgets() はファイルポインタで指定されるファイルから ( n - 1 ) 文字または改行文字までの

文字列を入力しs に格納しますgets() と異なり最後に入力された改行文字は NULL 文字に変更されません

標準入力から入力しファイルへ出力する ファイルへ出力あるいは入力を行う場合には改行コードの変換(入力の場合の削除出力の

場合の付加)はされませんしたがって標準入力から入力しファイルへ出力する場合には改行

コードを付加しなければなりません include ltstdiohgt main() char data[80] FILE fp fp = fopen( data w ) while( gets( data ) = NULL ) strcat( data yenn ) 改行コードの付加

fputs( data fp ) fclose( fp )

36

fputc()fgetc()関数について fputc() ファイルポインタで指定されるファイルに1文字出力します

include ltstdiohgt int fputc( int c FILE fp ) 戻り値正常に出力できた場合には文字 c を返しエラーの場合には EOF を返します fputc() は文字 c をファイルポインタで示されるファイルへ出力します

fgetc() ファイルポインタで指定されるファイルから1文字入力します

include ltstdiohgt int fgetc( FILE fp ) 戻り値正常に入力した場合には入力した文字を返しますエラーやEOFになった場合には

EOF が返されます fgetc() はファイルポインタで指定されるファイルから文字を入力します

ファイルの内容の表示 include ltstdiohgt main() FILE fp int ch char fname[30] printf( Key in Fila name gt ) gets( fname ) fp = fopen( fname r ) while( ( ch = fgetc( fp ) ) = EOF )putchar( ch ) fclose( fp )

その他テキスト中で使用された関数について sin() 三角関数の正弦を計算します

include ltmathhgt double sin(double radian) sinはラジアンを単位とする引数 radianの三角関数を計算します

37

strcpy() 文字列を他の文字列へコピーします

include ltstringhgt char strcpy(char string1const char string2) strcpyは引数 string2の指す文字列を null文字まで含めて引数 string1の指す領域にコピ

ーする strcpyは string1を返します

strcat() ある文字列を他の文字列に加えます

include ltstringhgt char strcat( char dest const char src ) 戻り値連結された文字列へのポインタを返します strcat() はsrc のコピーを dest の最後につけ加えます得られる文字列の長さは

strlen(dest)+strlen(src) になります

fabs() 絶対値の計算をします include ltmathhgt double fabs(double z) fabsは倍精度浮動小数の絶対値を計算して返しますつまりzgt=0であれば z をzlt0であ

れば-zを返します exp() 指数関数を計算します

include ltmathhgt double exp(double z) exp は引数zの指数関数つまりezを返すここではeは自然対数の底を表します対数関

数logの逆関数です

38

付 録 2 コンパイルの方法には大きく分けて第4章の実習で学んだようにデータファイルを作成してお

き ccg でコンパイルさせる方法と実行中に対話型でデータを入力していく方法があります ここでは対話型で実行を進めていく方法を紹介します ただしこの方法は計算(cpu)時間が10秒以内のものに限ります10秒を超える計算(cpu)時

間を要する場合はccg でコンパイルをするようにしてください 第4章実習の(2)(p16)までは同様です

コンパイル

コンピュータに処理を依頼します 60us1234boseicc cc rensyuc

所有するファイルの一覧を見てみます

60us1234boseicc ls -l larr 持っているファイルの一覧を見るコマンドです

-rw-r--r-- 1 60us1234 other 128 4月26日 15時14分 rensyuc -rwxr-xr-x 1 60us1234 other 361 4月26日 15時16分 aout

aout という実行形式のファイルが作成されています

実行

60us1234boseicc aout12 35[リターン] データを入力

1 200000 3500000 4200000 実行結果の出力

60us1234boseicc

注意

aout ファイルは印刷することができません実行結果を印刷する場合にはファイルに落とし てから出力するようにしましょう

60us1234boseicc aout gt kekka12 35[リターン] データを入力

60us1234boseicc more kekka 計算結果の確認 60us1234boseicc lpr kekka 計算結果の印刷

39

Page 30: n 第1章 章立ての部分は、書式(PC入門大見出し)を …第2章 数の表現 2-1 2進数 電子計算機の動作原理は0と1で表される2進数です。また、人間が日常生活で扱っている数

7-2 共用体 共用体は構造体と同じようにして宣言しますが共用体は複数のデータ型を同一のアドレスに

割り当てる方法です union 共用体タグ名 共用体メンバーの並び

「union」は共用体を表すキーワードです 「共用体タグ名」は共用体の型枠の名前を宣言しますここは自由に名前を定義することがで

きます 「共用体メンバーの並び」は共用体の要素です複数指定できます

共用体の宣言の例を次に示します

union c_tag int a char b

共用体 cは次のように共用体タグ c_tagの形式で領域を確保します共用体はメモリ上に領域を確保するときは ab ともに同じ領域に割り付けられます これはab という2つのデータが同時に存在するわけではなく cを異なるデータ abで共有す

ることを表しています c a b

上記の宣言だけでは共用体の形式を宣言しているだけでメモリ中で実際の領域を確保して

いるわけではありません実際に領域を確保するためには次のように定義します union 構造体タグ名 構造体名

したがって共用体名を c とすると次のように指定します

union c_tag c

(1)共用体の参照

プログラム中で共用体中のメンバーを参照する場合には次のように指定します 共用体名メンバー名

したがって「a」または「b」を参照したいときには次のように指定します

ca (int 型) cb (char 型)

メンバー参照方法によって int型として使ったりchar型として利用することができます

28

[プログラム例]

includeltstdiohgt main() union data char a short b int c chk chkc = 0x12345678 printf( char a xyennchka) printf( short b xyennchkb) printf( int c xyennchkc)

chkb(int 型) chkb(short 型) chka(char 型) 12 12 12 34 34 56 78

29

第8章 アルゴリズム コンピュータに何か仕事をさせようとするときは仕事を具体的に実行するための処理や動作

の手順が必要ですこの「手順」がアルゴリズムです アルゴリズムを考えるときは解くべき問題をはっきりと定義することが必要です

8-1 ソート ソートとは与えられたデータを小さい順または大きい順に並べ換えることですソート方法は

いくつかありますが基本的な方法でソートするアルゴリズムを紹介します

includeltstdiohgt int data[10] main()

int data_in() sort() data_in() sort() int data_in() データ入力関数

int a printf(数値入力yenn)

for(a=0alt=9a++) printf( [d]a+1) scanf(dampdata[a]) int sort() ソート処理を行う関数

int cont1cont2tmp1tmp2mim for(cont1=0 cont1lt=9 cont1++) mim=data[cont1] tmp1=cont1 for(cont2=cont1+1 cont2lt=9 cont2++) if(data[cont2] lt mim) mim=data[cont2] tmp1=cont2 tmp2 = data[cont1] data[cont1] = data[tmp1] data[tmp1] = tmp2 printf(結果 yenn)

for (cont1 = 0 cont1 lt= 9 cont1++) printf(d yenn data[cont1])

30

第9章 プリプロセッサ C言語にはプログラムの中でコンパイルについての指示を行う「プリプロセッサ」という機能が

ありますまたプリプロセッサとはコンパイルする前に実行されるためその意味のとおり「前処理」 と呼ばれていますここでは代表的なものをいくつか説明します

9-1 ファイルの挿入 ソースプログラム中に指定されたファイルを挿入します

include ltstdiohgt helliphellip 標準ディレクトリを探します include progh helliphellip 現在のディレクトリを探しなければ標準ディレクトリを探します

includeltstdiohgt によって組み込まれた define EOF (-1) define EOF (-1) define define helliphelliphelliphellip 組み込み helliphelliphelliphellip

main() stdiohファイル

int helliphelliphelliphellip helliphelliphelliphellip

ソースファイル

9-2 文字の置換 プログラム中に使われている文字列を別の文字列に置き換えます

include ltstdiohgt define TRUE 1 define EOF (-1) main() define helliphellip helliphellip

while(TRUE) define TRUE 1 置き換え main() helliphellip helliphellip while(1)

break helliphelliphellip

31

9-3 条件によるコンパイル 識別子が定義されているか否かを判断しコンパイルする範囲を指定します

include ltstdiohgt define UNIX main() ifdef UNIX printf( UNIX yenn) else printf(MS-DOSyenn) endif

include ltstdiohgt define OS UNIX main() if OS == UNIX printf( UNIX yenn) else printf(MS-DOSyenn) endif

32

付 録 1 puts()gets()関数について

行単位に入出力を行う場合には puts() gets() 関数を用います

puts() 標準出力に文字列を出力します

include ltstdiohgt int puts( char s ) puts() は NULL で終る文字列 s を標準出力に出力し最後に改行文字 yenn も出力しま

gets() 標準入力から文字列を入力します

include ltstdiohgt char gets( char s ) 戻り値正常に入力した場合には引数 s の値が返されますエラーやEOFになった場合に

は NULL が返されます gets() は標準入力から復帰文字で終る文字列を入力しs に格納しますこのとき最後の復

帰文字は NULL文字に変更されます

入力行の出力 標準入力から gets() で入力したデータには改行コードは含まれませんまた標準出力へ

puts() で出力を行う場合には必ず改行コードが付加されますgets() を実行したときの戻り値としてファイルの終端を検出した場合には EOF ではなく NULL が返されますので注意して下さい

include ltstdiohgt main() char data[80] while( gets( data ) = NULL )puts( data )

putchar()getchar()関数について putchar() 標準出力に文字を出力します

include ltstdiohgt int putchar(int c ) 戻り値正常に出力できた場合には文字cをエラーの場合にはEOFを返します

33

getchar() 標準入力から文字を入力します

include ltstdiohgt int getchar(void) 戻り値正常に入力した場合には読み込んだ文字を int 型に変換して返しますまたファイ

ルエンドエラーの場合にはEOFを返します

標準入力標準出力

標準入力標準出力はプログラムが開始されるときにはオープンされていますそれぞれのフ

ァイルポインタは stdin stdout になっていますfopen() fclose() をせずとも使用することができます

scanf() 標準出力ストリームからテキストを読み込み解釈します include ltstdiohgt int scanf( const char format [ address ] ) 戻り値正しくスキャンし変換し格納した入力フィールドの数を返しますファイルエンドを読

み込んだ場合は戻り値は EOF となります値を格納したフィールドがなかった場合は戻り値は0となります

一連の入力フィールドをスキャンして1度に1文字ずつストリーム stdin から文字を読み込み

ます次に引き数 format によって指される書式文字列中の書式指定に従って各フィールドを書式化します最後にformat の後に続く各引き数が示しているアドレスに書式化した入力を格納していきます書式文字列中の書式指定の個数はその後に続くアドレスの数と同じでな

ければなりません 書式指定[入力幅][型指定文字] 入力幅 読むべき文字数の最大値 型指定文字 次のとおりです 型指定文字 期待される入力 引き数の型 d 10進整数 int へのポインタ( int arg ) x 16進整数 int へのポインタ( int arg ) f 浮動小数点数 float へのポインタ( float arg ) s 文字列 文字配列へのポインタ( char arg[] ) c 文字 文字へのポインタ( char arg )

printf() フォーマットを指定してテキスト標準出力ストリームに出力します include ltstdiohgt int printf( const char format [ argument ] ) 戻り値出力したバイト数を返しますエラーの場合は EOF を返します

34

format によって指される書式文字列中の書式指定をformat の後に続く各引き数に適用し

書式化されたデータを stdout に出力します書式指定は後に続く引き数と同じ数だけなければなりません

書式指定[印字幅][精度][型指定文字] 印字幅 印字する最小文字数 精度 印字する最大文字数 型指定文字 つぎのとおりです 型指定文字 入力引き数 出力の書式 d 整数 符号付き10進整数 x 整数 符号無し16進整数 f 浮動小数点 符号付きの dddddddd形式の値 c 文字 1個の文字 s 文字列ポインタ ヌル文字に出会うか精度に達するまで 文字をプリントする

fopen()fclose()関数について fopen() ファイルをオープンします

include ltstdiohgt FILE fopen( char filename char mode ) 戻り値正常にファイルのオープンができたらファイルポインタを返しますエラーがあった場

合には NULLを返します 文字列 filename で指定されたファイルをオープンしますオープン後の入出力のモードに

ついては文字列 mode で指定しますmode に指定できる文字は以下のとおりです r 入力モードでオープンします w 出力モードでオープンします a 存在するファイルに追加して出力するモードでオープンします r+ 既に作成してあるファイルを更新(入力出力)するモードでオープンします w+ 新しく作成するファイルを更新モードでオープンします a+ 既に作成してあるファイルの終りから更新用に作成します

以上の文字に b をつけ加えることによりバイナリモードで入出力することができるようになり

ます rb バイナリの入力モードでオープンします wb バイナリの出力モードでオープンします ab 存在するファイルに追加して出力するモード(バイナリ)でオープンします

fclose() 既にオープンしてあるファイルをクローズします include ltstdiohgt fclose( FILE fp ) 既にオープンしているファイルをクローズしますパラメータには fopen() 関数により返された

ファイルポインタを指定します

35

テキストモードとバイナリモード 行の最後はテキストモードの場合改行コードのみとなりバイナリモードの場合には復帰

コードと改行コードの組合わせになります行の最後としてテキストファイルには復帰コード改行

コードが書かれていますがテキストモードでオープンした場合には入力すると改行コードのみに

変換されて入力されますバイナリモードの場合には復帰コード改行コードがそれぞれ入力され

ます

fputs()fgets()関数について fputs() ファイルポインタで指定されるファイルに文字列を出力します

include ltstdiohgt

int fputs( char s FILE fp ) fputs() は NULL で終る文字列 s をファイルポインタに示されるファイルへ出力しますputs()

と違い最後に改行文字 yenn を出力することはありません

fgets() ファイルポインタで指定されるファイルから文字列を入力します include ltstdiohgt char fgets( char s int n FILE fp ) 戻り値正常に入力した場合には引数 s の値が返されますエラーやEOFになった場合に

は NULL が返されます fgets() はファイルポインタで指定されるファイルから ( n - 1 ) 文字または改行文字までの

文字列を入力しs に格納しますgets() と異なり最後に入力された改行文字は NULL 文字に変更されません

標準入力から入力しファイルへ出力する ファイルへ出力あるいは入力を行う場合には改行コードの変換(入力の場合の削除出力の

場合の付加)はされませんしたがって標準入力から入力しファイルへ出力する場合には改行

コードを付加しなければなりません include ltstdiohgt main() char data[80] FILE fp fp = fopen( data w ) while( gets( data ) = NULL ) strcat( data yenn ) 改行コードの付加

fputs( data fp ) fclose( fp )

36

fputc()fgetc()関数について fputc() ファイルポインタで指定されるファイルに1文字出力します

include ltstdiohgt int fputc( int c FILE fp ) 戻り値正常に出力できた場合には文字 c を返しエラーの場合には EOF を返します fputc() は文字 c をファイルポインタで示されるファイルへ出力します

fgetc() ファイルポインタで指定されるファイルから1文字入力します

include ltstdiohgt int fgetc( FILE fp ) 戻り値正常に入力した場合には入力した文字を返しますエラーやEOFになった場合には

EOF が返されます fgetc() はファイルポインタで指定されるファイルから文字を入力します

ファイルの内容の表示 include ltstdiohgt main() FILE fp int ch char fname[30] printf( Key in Fila name gt ) gets( fname ) fp = fopen( fname r ) while( ( ch = fgetc( fp ) ) = EOF )putchar( ch ) fclose( fp )

その他テキスト中で使用された関数について sin() 三角関数の正弦を計算します

include ltmathhgt double sin(double radian) sinはラジアンを単位とする引数 radianの三角関数を計算します

37

strcpy() 文字列を他の文字列へコピーします

include ltstringhgt char strcpy(char string1const char string2) strcpyは引数 string2の指す文字列を null文字まで含めて引数 string1の指す領域にコピ

ーする strcpyは string1を返します

strcat() ある文字列を他の文字列に加えます

include ltstringhgt char strcat( char dest const char src ) 戻り値連結された文字列へのポインタを返します strcat() はsrc のコピーを dest の最後につけ加えます得られる文字列の長さは

strlen(dest)+strlen(src) になります

fabs() 絶対値の計算をします include ltmathhgt double fabs(double z) fabsは倍精度浮動小数の絶対値を計算して返しますつまりzgt=0であれば z をzlt0であ

れば-zを返します exp() 指数関数を計算します

include ltmathhgt double exp(double z) exp は引数zの指数関数つまりezを返すここではeは自然対数の底を表します対数関

数logの逆関数です

38

付 録 2 コンパイルの方法には大きく分けて第4章の実習で学んだようにデータファイルを作成してお

き ccg でコンパイルさせる方法と実行中に対話型でデータを入力していく方法があります ここでは対話型で実行を進めていく方法を紹介します ただしこの方法は計算(cpu)時間が10秒以内のものに限ります10秒を超える計算(cpu)時

間を要する場合はccg でコンパイルをするようにしてください 第4章実習の(2)(p16)までは同様です

コンパイル

コンピュータに処理を依頼します 60us1234boseicc cc rensyuc

所有するファイルの一覧を見てみます

60us1234boseicc ls -l larr 持っているファイルの一覧を見るコマンドです

-rw-r--r-- 1 60us1234 other 128 4月26日 15時14分 rensyuc -rwxr-xr-x 1 60us1234 other 361 4月26日 15時16分 aout

aout という実行形式のファイルが作成されています

実行

60us1234boseicc aout12 35[リターン] データを入力

1 200000 3500000 4200000 実行結果の出力

60us1234boseicc

注意

aout ファイルは印刷することができません実行結果を印刷する場合にはファイルに落とし てから出力するようにしましょう

60us1234boseicc aout gt kekka12 35[リターン] データを入力

60us1234boseicc more kekka 計算結果の確認 60us1234boseicc lpr kekka 計算結果の印刷

39

Page 31: n 第1章 章立ての部分は、書式(PC入門大見出し)を …第2章 数の表現 2-1 2進数 電子計算機の動作原理は0と1で表される2進数です。また、人間が日常生活で扱っている数

[プログラム例]

includeltstdiohgt main() union data char a short b int c chk chkc = 0x12345678 printf( char a xyennchka) printf( short b xyennchkb) printf( int c xyennchkc)

chkb(int 型) chkb(short 型) chka(char 型) 12 12 12 34 34 56 78

29

第8章 アルゴリズム コンピュータに何か仕事をさせようとするときは仕事を具体的に実行するための処理や動作

の手順が必要ですこの「手順」がアルゴリズムです アルゴリズムを考えるときは解くべき問題をはっきりと定義することが必要です

8-1 ソート ソートとは与えられたデータを小さい順または大きい順に並べ換えることですソート方法は

いくつかありますが基本的な方法でソートするアルゴリズムを紹介します

includeltstdiohgt int data[10] main()

int data_in() sort() data_in() sort() int data_in() データ入力関数

int a printf(数値入力yenn)

for(a=0alt=9a++) printf( [d]a+1) scanf(dampdata[a]) int sort() ソート処理を行う関数

int cont1cont2tmp1tmp2mim for(cont1=0 cont1lt=9 cont1++) mim=data[cont1] tmp1=cont1 for(cont2=cont1+1 cont2lt=9 cont2++) if(data[cont2] lt mim) mim=data[cont2] tmp1=cont2 tmp2 = data[cont1] data[cont1] = data[tmp1] data[tmp1] = tmp2 printf(結果 yenn)

for (cont1 = 0 cont1 lt= 9 cont1++) printf(d yenn data[cont1])

30

第9章 プリプロセッサ C言語にはプログラムの中でコンパイルについての指示を行う「プリプロセッサ」という機能が

ありますまたプリプロセッサとはコンパイルする前に実行されるためその意味のとおり「前処理」 と呼ばれていますここでは代表的なものをいくつか説明します

9-1 ファイルの挿入 ソースプログラム中に指定されたファイルを挿入します

include ltstdiohgt helliphellip 標準ディレクトリを探します include progh helliphellip 現在のディレクトリを探しなければ標準ディレクトリを探します

includeltstdiohgt によって組み込まれた define EOF (-1) define EOF (-1) define define helliphelliphelliphellip 組み込み helliphelliphelliphellip

main() stdiohファイル

int helliphelliphelliphellip helliphelliphelliphellip

ソースファイル

9-2 文字の置換 プログラム中に使われている文字列を別の文字列に置き換えます

include ltstdiohgt define TRUE 1 define EOF (-1) main() define helliphellip helliphellip

while(TRUE) define TRUE 1 置き換え main() helliphellip helliphellip while(1)

break helliphelliphellip

31

9-3 条件によるコンパイル 識別子が定義されているか否かを判断しコンパイルする範囲を指定します

include ltstdiohgt define UNIX main() ifdef UNIX printf( UNIX yenn) else printf(MS-DOSyenn) endif

include ltstdiohgt define OS UNIX main() if OS == UNIX printf( UNIX yenn) else printf(MS-DOSyenn) endif

32

付 録 1 puts()gets()関数について

行単位に入出力を行う場合には puts() gets() 関数を用います

puts() 標準出力に文字列を出力します

include ltstdiohgt int puts( char s ) puts() は NULL で終る文字列 s を標準出力に出力し最後に改行文字 yenn も出力しま

gets() 標準入力から文字列を入力します

include ltstdiohgt char gets( char s ) 戻り値正常に入力した場合には引数 s の値が返されますエラーやEOFになった場合に

は NULL が返されます gets() は標準入力から復帰文字で終る文字列を入力しs に格納しますこのとき最後の復

帰文字は NULL文字に変更されます

入力行の出力 標準入力から gets() で入力したデータには改行コードは含まれませんまた標準出力へ

puts() で出力を行う場合には必ず改行コードが付加されますgets() を実行したときの戻り値としてファイルの終端を検出した場合には EOF ではなく NULL が返されますので注意して下さい

include ltstdiohgt main() char data[80] while( gets( data ) = NULL )puts( data )

putchar()getchar()関数について putchar() 標準出力に文字を出力します

include ltstdiohgt int putchar(int c ) 戻り値正常に出力できた場合には文字cをエラーの場合にはEOFを返します

33

getchar() 標準入力から文字を入力します

include ltstdiohgt int getchar(void) 戻り値正常に入力した場合には読み込んだ文字を int 型に変換して返しますまたファイ

ルエンドエラーの場合にはEOFを返します

標準入力標準出力

標準入力標準出力はプログラムが開始されるときにはオープンされていますそれぞれのフ

ァイルポインタは stdin stdout になっていますfopen() fclose() をせずとも使用することができます

scanf() 標準出力ストリームからテキストを読み込み解釈します include ltstdiohgt int scanf( const char format [ address ] ) 戻り値正しくスキャンし変換し格納した入力フィールドの数を返しますファイルエンドを読

み込んだ場合は戻り値は EOF となります値を格納したフィールドがなかった場合は戻り値は0となります

一連の入力フィールドをスキャンして1度に1文字ずつストリーム stdin から文字を読み込み

ます次に引き数 format によって指される書式文字列中の書式指定に従って各フィールドを書式化します最後にformat の後に続く各引き数が示しているアドレスに書式化した入力を格納していきます書式文字列中の書式指定の個数はその後に続くアドレスの数と同じでな

ければなりません 書式指定[入力幅][型指定文字] 入力幅 読むべき文字数の最大値 型指定文字 次のとおりです 型指定文字 期待される入力 引き数の型 d 10進整数 int へのポインタ( int arg ) x 16進整数 int へのポインタ( int arg ) f 浮動小数点数 float へのポインタ( float arg ) s 文字列 文字配列へのポインタ( char arg[] ) c 文字 文字へのポインタ( char arg )

printf() フォーマットを指定してテキスト標準出力ストリームに出力します include ltstdiohgt int printf( const char format [ argument ] ) 戻り値出力したバイト数を返しますエラーの場合は EOF を返します

34

format によって指される書式文字列中の書式指定をformat の後に続く各引き数に適用し

書式化されたデータを stdout に出力します書式指定は後に続く引き数と同じ数だけなければなりません

書式指定[印字幅][精度][型指定文字] 印字幅 印字する最小文字数 精度 印字する最大文字数 型指定文字 つぎのとおりです 型指定文字 入力引き数 出力の書式 d 整数 符号付き10進整数 x 整数 符号無し16進整数 f 浮動小数点 符号付きの dddddddd形式の値 c 文字 1個の文字 s 文字列ポインタ ヌル文字に出会うか精度に達するまで 文字をプリントする

fopen()fclose()関数について fopen() ファイルをオープンします

include ltstdiohgt FILE fopen( char filename char mode ) 戻り値正常にファイルのオープンができたらファイルポインタを返しますエラーがあった場

合には NULLを返します 文字列 filename で指定されたファイルをオープンしますオープン後の入出力のモードに

ついては文字列 mode で指定しますmode に指定できる文字は以下のとおりです r 入力モードでオープンします w 出力モードでオープンします a 存在するファイルに追加して出力するモードでオープンします r+ 既に作成してあるファイルを更新(入力出力)するモードでオープンします w+ 新しく作成するファイルを更新モードでオープンします a+ 既に作成してあるファイルの終りから更新用に作成します

以上の文字に b をつけ加えることによりバイナリモードで入出力することができるようになり

ます rb バイナリの入力モードでオープンします wb バイナリの出力モードでオープンします ab 存在するファイルに追加して出力するモード(バイナリ)でオープンします

fclose() 既にオープンしてあるファイルをクローズします include ltstdiohgt fclose( FILE fp ) 既にオープンしているファイルをクローズしますパラメータには fopen() 関数により返された

ファイルポインタを指定します

35

テキストモードとバイナリモード 行の最後はテキストモードの場合改行コードのみとなりバイナリモードの場合には復帰

コードと改行コードの組合わせになります行の最後としてテキストファイルには復帰コード改行

コードが書かれていますがテキストモードでオープンした場合には入力すると改行コードのみに

変換されて入力されますバイナリモードの場合には復帰コード改行コードがそれぞれ入力され

ます

fputs()fgets()関数について fputs() ファイルポインタで指定されるファイルに文字列を出力します

include ltstdiohgt

int fputs( char s FILE fp ) fputs() は NULL で終る文字列 s をファイルポインタに示されるファイルへ出力しますputs()

と違い最後に改行文字 yenn を出力することはありません

fgets() ファイルポインタで指定されるファイルから文字列を入力します include ltstdiohgt char fgets( char s int n FILE fp ) 戻り値正常に入力した場合には引数 s の値が返されますエラーやEOFになった場合に

は NULL が返されます fgets() はファイルポインタで指定されるファイルから ( n - 1 ) 文字または改行文字までの

文字列を入力しs に格納しますgets() と異なり最後に入力された改行文字は NULL 文字に変更されません

標準入力から入力しファイルへ出力する ファイルへ出力あるいは入力を行う場合には改行コードの変換(入力の場合の削除出力の

場合の付加)はされませんしたがって標準入力から入力しファイルへ出力する場合には改行

コードを付加しなければなりません include ltstdiohgt main() char data[80] FILE fp fp = fopen( data w ) while( gets( data ) = NULL ) strcat( data yenn ) 改行コードの付加

fputs( data fp ) fclose( fp )

36

fputc()fgetc()関数について fputc() ファイルポインタで指定されるファイルに1文字出力します

include ltstdiohgt int fputc( int c FILE fp ) 戻り値正常に出力できた場合には文字 c を返しエラーの場合には EOF を返します fputc() は文字 c をファイルポインタで示されるファイルへ出力します

fgetc() ファイルポインタで指定されるファイルから1文字入力します

include ltstdiohgt int fgetc( FILE fp ) 戻り値正常に入力した場合には入力した文字を返しますエラーやEOFになった場合には

EOF が返されます fgetc() はファイルポインタで指定されるファイルから文字を入力します

ファイルの内容の表示 include ltstdiohgt main() FILE fp int ch char fname[30] printf( Key in Fila name gt ) gets( fname ) fp = fopen( fname r ) while( ( ch = fgetc( fp ) ) = EOF )putchar( ch ) fclose( fp )

その他テキスト中で使用された関数について sin() 三角関数の正弦を計算します

include ltmathhgt double sin(double radian) sinはラジアンを単位とする引数 radianの三角関数を計算します

37

strcpy() 文字列を他の文字列へコピーします

include ltstringhgt char strcpy(char string1const char string2) strcpyは引数 string2の指す文字列を null文字まで含めて引数 string1の指す領域にコピ

ーする strcpyは string1を返します

strcat() ある文字列を他の文字列に加えます

include ltstringhgt char strcat( char dest const char src ) 戻り値連結された文字列へのポインタを返します strcat() はsrc のコピーを dest の最後につけ加えます得られる文字列の長さは

strlen(dest)+strlen(src) になります

fabs() 絶対値の計算をします include ltmathhgt double fabs(double z) fabsは倍精度浮動小数の絶対値を計算して返しますつまりzgt=0であれば z をzlt0であ

れば-zを返します exp() 指数関数を計算します

include ltmathhgt double exp(double z) exp は引数zの指数関数つまりezを返すここではeは自然対数の底を表します対数関

数logの逆関数です

38

付 録 2 コンパイルの方法には大きく分けて第4章の実習で学んだようにデータファイルを作成してお

き ccg でコンパイルさせる方法と実行中に対話型でデータを入力していく方法があります ここでは対話型で実行を進めていく方法を紹介します ただしこの方法は計算(cpu)時間が10秒以内のものに限ります10秒を超える計算(cpu)時

間を要する場合はccg でコンパイルをするようにしてください 第4章実習の(2)(p16)までは同様です

コンパイル

コンピュータに処理を依頼します 60us1234boseicc cc rensyuc

所有するファイルの一覧を見てみます

60us1234boseicc ls -l larr 持っているファイルの一覧を見るコマンドです

-rw-r--r-- 1 60us1234 other 128 4月26日 15時14分 rensyuc -rwxr-xr-x 1 60us1234 other 361 4月26日 15時16分 aout

aout という実行形式のファイルが作成されています

実行

60us1234boseicc aout12 35[リターン] データを入力

1 200000 3500000 4200000 実行結果の出力

60us1234boseicc

注意

aout ファイルは印刷することができません実行結果を印刷する場合にはファイルに落とし てから出力するようにしましょう

60us1234boseicc aout gt kekka12 35[リターン] データを入力

60us1234boseicc more kekka 計算結果の確認 60us1234boseicc lpr kekka 計算結果の印刷

39

Page 32: n 第1章 章立ての部分は、書式(PC入門大見出し)を …第2章 数の表現 2-1 2進数 電子計算機の動作原理は0と1で表される2進数です。また、人間が日常生活で扱っている数

第8章 アルゴリズム コンピュータに何か仕事をさせようとするときは仕事を具体的に実行するための処理や動作

の手順が必要ですこの「手順」がアルゴリズムです アルゴリズムを考えるときは解くべき問題をはっきりと定義することが必要です

8-1 ソート ソートとは与えられたデータを小さい順または大きい順に並べ換えることですソート方法は

いくつかありますが基本的な方法でソートするアルゴリズムを紹介します

includeltstdiohgt int data[10] main()

int data_in() sort() data_in() sort() int data_in() データ入力関数

int a printf(数値入力yenn)

for(a=0alt=9a++) printf( [d]a+1) scanf(dampdata[a]) int sort() ソート処理を行う関数

int cont1cont2tmp1tmp2mim for(cont1=0 cont1lt=9 cont1++) mim=data[cont1] tmp1=cont1 for(cont2=cont1+1 cont2lt=9 cont2++) if(data[cont2] lt mim) mim=data[cont2] tmp1=cont2 tmp2 = data[cont1] data[cont1] = data[tmp1] data[tmp1] = tmp2 printf(結果 yenn)

for (cont1 = 0 cont1 lt= 9 cont1++) printf(d yenn data[cont1])

30

第9章 プリプロセッサ C言語にはプログラムの中でコンパイルについての指示を行う「プリプロセッサ」という機能が

ありますまたプリプロセッサとはコンパイルする前に実行されるためその意味のとおり「前処理」 と呼ばれていますここでは代表的なものをいくつか説明します

9-1 ファイルの挿入 ソースプログラム中に指定されたファイルを挿入します

include ltstdiohgt helliphellip 標準ディレクトリを探します include progh helliphellip 現在のディレクトリを探しなければ標準ディレクトリを探します

includeltstdiohgt によって組み込まれた define EOF (-1) define EOF (-1) define define helliphelliphelliphellip 組み込み helliphelliphelliphellip

main() stdiohファイル

int helliphelliphelliphellip helliphelliphelliphellip

ソースファイル

9-2 文字の置換 プログラム中に使われている文字列を別の文字列に置き換えます

include ltstdiohgt define TRUE 1 define EOF (-1) main() define helliphellip helliphellip

while(TRUE) define TRUE 1 置き換え main() helliphellip helliphellip while(1)

break helliphelliphellip

31

9-3 条件によるコンパイル 識別子が定義されているか否かを判断しコンパイルする範囲を指定します

include ltstdiohgt define UNIX main() ifdef UNIX printf( UNIX yenn) else printf(MS-DOSyenn) endif

include ltstdiohgt define OS UNIX main() if OS == UNIX printf( UNIX yenn) else printf(MS-DOSyenn) endif

32

付 録 1 puts()gets()関数について

行単位に入出力を行う場合には puts() gets() 関数を用います

puts() 標準出力に文字列を出力します

include ltstdiohgt int puts( char s ) puts() は NULL で終る文字列 s を標準出力に出力し最後に改行文字 yenn も出力しま

gets() 標準入力から文字列を入力します

include ltstdiohgt char gets( char s ) 戻り値正常に入力した場合には引数 s の値が返されますエラーやEOFになった場合に

は NULL が返されます gets() は標準入力から復帰文字で終る文字列を入力しs に格納しますこのとき最後の復

帰文字は NULL文字に変更されます

入力行の出力 標準入力から gets() で入力したデータには改行コードは含まれませんまた標準出力へ

puts() で出力を行う場合には必ず改行コードが付加されますgets() を実行したときの戻り値としてファイルの終端を検出した場合には EOF ではなく NULL が返されますので注意して下さい

include ltstdiohgt main() char data[80] while( gets( data ) = NULL )puts( data )

putchar()getchar()関数について putchar() 標準出力に文字を出力します

include ltstdiohgt int putchar(int c ) 戻り値正常に出力できた場合には文字cをエラーの場合にはEOFを返します

33

getchar() 標準入力から文字を入力します

include ltstdiohgt int getchar(void) 戻り値正常に入力した場合には読み込んだ文字を int 型に変換して返しますまたファイ

ルエンドエラーの場合にはEOFを返します

標準入力標準出力

標準入力標準出力はプログラムが開始されるときにはオープンされていますそれぞれのフ

ァイルポインタは stdin stdout になっていますfopen() fclose() をせずとも使用することができます

scanf() 標準出力ストリームからテキストを読み込み解釈します include ltstdiohgt int scanf( const char format [ address ] ) 戻り値正しくスキャンし変換し格納した入力フィールドの数を返しますファイルエンドを読

み込んだ場合は戻り値は EOF となります値を格納したフィールドがなかった場合は戻り値は0となります

一連の入力フィールドをスキャンして1度に1文字ずつストリーム stdin から文字を読み込み

ます次に引き数 format によって指される書式文字列中の書式指定に従って各フィールドを書式化します最後にformat の後に続く各引き数が示しているアドレスに書式化した入力を格納していきます書式文字列中の書式指定の個数はその後に続くアドレスの数と同じでな

ければなりません 書式指定[入力幅][型指定文字] 入力幅 読むべき文字数の最大値 型指定文字 次のとおりです 型指定文字 期待される入力 引き数の型 d 10進整数 int へのポインタ( int arg ) x 16進整数 int へのポインタ( int arg ) f 浮動小数点数 float へのポインタ( float arg ) s 文字列 文字配列へのポインタ( char arg[] ) c 文字 文字へのポインタ( char arg )

printf() フォーマットを指定してテキスト標準出力ストリームに出力します include ltstdiohgt int printf( const char format [ argument ] ) 戻り値出力したバイト数を返しますエラーの場合は EOF を返します

34

format によって指される書式文字列中の書式指定をformat の後に続く各引き数に適用し

書式化されたデータを stdout に出力します書式指定は後に続く引き数と同じ数だけなければなりません

書式指定[印字幅][精度][型指定文字] 印字幅 印字する最小文字数 精度 印字する最大文字数 型指定文字 つぎのとおりです 型指定文字 入力引き数 出力の書式 d 整数 符号付き10進整数 x 整数 符号無し16進整数 f 浮動小数点 符号付きの dddddddd形式の値 c 文字 1個の文字 s 文字列ポインタ ヌル文字に出会うか精度に達するまで 文字をプリントする

fopen()fclose()関数について fopen() ファイルをオープンします

include ltstdiohgt FILE fopen( char filename char mode ) 戻り値正常にファイルのオープンができたらファイルポインタを返しますエラーがあった場

合には NULLを返します 文字列 filename で指定されたファイルをオープンしますオープン後の入出力のモードに

ついては文字列 mode で指定しますmode に指定できる文字は以下のとおりです r 入力モードでオープンします w 出力モードでオープンします a 存在するファイルに追加して出力するモードでオープンします r+ 既に作成してあるファイルを更新(入力出力)するモードでオープンします w+ 新しく作成するファイルを更新モードでオープンします a+ 既に作成してあるファイルの終りから更新用に作成します

以上の文字に b をつけ加えることによりバイナリモードで入出力することができるようになり

ます rb バイナリの入力モードでオープンします wb バイナリの出力モードでオープンします ab 存在するファイルに追加して出力するモード(バイナリ)でオープンします

fclose() 既にオープンしてあるファイルをクローズします include ltstdiohgt fclose( FILE fp ) 既にオープンしているファイルをクローズしますパラメータには fopen() 関数により返された

ファイルポインタを指定します

35

テキストモードとバイナリモード 行の最後はテキストモードの場合改行コードのみとなりバイナリモードの場合には復帰

コードと改行コードの組合わせになります行の最後としてテキストファイルには復帰コード改行

コードが書かれていますがテキストモードでオープンした場合には入力すると改行コードのみに

変換されて入力されますバイナリモードの場合には復帰コード改行コードがそれぞれ入力され

ます

fputs()fgets()関数について fputs() ファイルポインタで指定されるファイルに文字列を出力します

include ltstdiohgt

int fputs( char s FILE fp ) fputs() は NULL で終る文字列 s をファイルポインタに示されるファイルへ出力しますputs()

と違い最後に改行文字 yenn を出力することはありません

fgets() ファイルポインタで指定されるファイルから文字列を入力します include ltstdiohgt char fgets( char s int n FILE fp ) 戻り値正常に入力した場合には引数 s の値が返されますエラーやEOFになった場合に

は NULL が返されます fgets() はファイルポインタで指定されるファイルから ( n - 1 ) 文字または改行文字までの

文字列を入力しs に格納しますgets() と異なり最後に入力された改行文字は NULL 文字に変更されません

標準入力から入力しファイルへ出力する ファイルへ出力あるいは入力を行う場合には改行コードの変換(入力の場合の削除出力の

場合の付加)はされませんしたがって標準入力から入力しファイルへ出力する場合には改行

コードを付加しなければなりません include ltstdiohgt main() char data[80] FILE fp fp = fopen( data w ) while( gets( data ) = NULL ) strcat( data yenn ) 改行コードの付加

fputs( data fp ) fclose( fp )

36

fputc()fgetc()関数について fputc() ファイルポインタで指定されるファイルに1文字出力します

include ltstdiohgt int fputc( int c FILE fp ) 戻り値正常に出力できた場合には文字 c を返しエラーの場合には EOF を返します fputc() は文字 c をファイルポインタで示されるファイルへ出力します

fgetc() ファイルポインタで指定されるファイルから1文字入力します

include ltstdiohgt int fgetc( FILE fp ) 戻り値正常に入力した場合には入力した文字を返しますエラーやEOFになった場合には

EOF が返されます fgetc() はファイルポインタで指定されるファイルから文字を入力します

ファイルの内容の表示 include ltstdiohgt main() FILE fp int ch char fname[30] printf( Key in Fila name gt ) gets( fname ) fp = fopen( fname r ) while( ( ch = fgetc( fp ) ) = EOF )putchar( ch ) fclose( fp )

その他テキスト中で使用された関数について sin() 三角関数の正弦を計算します

include ltmathhgt double sin(double radian) sinはラジアンを単位とする引数 radianの三角関数を計算します

37

strcpy() 文字列を他の文字列へコピーします

include ltstringhgt char strcpy(char string1const char string2) strcpyは引数 string2の指す文字列を null文字まで含めて引数 string1の指す領域にコピ

ーする strcpyは string1を返します

strcat() ある文字列を他の文字列に加えます

include ltstringhgt char strcat( char dest const char src ) 戻り値連結された文字列へのポインタを返します strcat() はsrc のコピーを dest の最後につけ加えます得られる文字列の長さは

strlen(dest)+strlen(src) になります

fabs() 絶対値の計算をします include ltmathhgt double fabs(double z) fabsは倍精度浮動小数の絶対値を計算して返しますつまりzgt=0であれば z をzlt0であ

れば-zを返します exp() 指数関数を計算します

include ltmathhgt double exp(double z) exp は引数zの指数関数つまりezを返すここではeは自然対数の底を表します対数関

数logの逆関数です

38

付 録 2 コンパイルの方法には大きく分けて第4章の実習で学んだようにデータファイルを作成してお

き ccg でコンパイルさせる方法と実行中に対話型でデータを入力していく方法があります ここでは対話型で実行を進めていく方法を紹介します ただしこの方法は計算(cpu)時間が10秒以内のものに限ります10秒を超える計算(cpu)時

間を要する場合はccg でコンパイルをするようにしてください 第4章実習の(2)(p16)までは同様です

コンパイル

コンピュータに処理を依頼します 60us1234boseicc cc rensyuc

所有するファイルの一覧を見てみます

60us1234boseicc ls -l larr 持っているファイルの一覧を見るコマンドです

-rw-r--r-- 1 60us1234 other 128 4月26日 15時14分 rensyuc -rwxr-xr-x 1 60us1234 other 361 4月26日 15時16分 aout

aout という実行形式のファイルが作成されています

実行

60us1234boseicc aout12 35[リターン] データを入力

1 200000 3500000 4200000 実行結果の出力

60us1234boseicc

注意

aout ファイルは印刷することができません実行結果を印刷する場合にはファイルに落とし てから出力するようにしましょう

60us1234boseicc aout gt kekka12 35[リターン] データを入力

60us1234boseicc more kekka 計算結果の確認 60us1234boseicc lpr kekka 計算結果の印刷

39

Page 33: n 第1章 章立ての部分は、書式(PC入門大見出し)を …第2章 数の表現 2-1 2進数 電子計算機の動作原理は0と1で表される2進数です。また、人間が日常生活で扱っている数

第9章 プリプロセッサ C言語にはプログラムの中でコンパイルについての指示を行う「プリプロセッサ」という機能が

ありますまたプリプロセッサとはコンパイルする前に実行されるためその意味のとおり「前処理」 と呼ばれていますここでは代表的なものをいくつか説明します

9-1 ファイルの挿入 ソースプログラム中に指定されたファイルを挿入します

include ltstdiohgt helliphellip 標準ディレクトリを探します include progh helliphellip 現在のディレクトリを探しなければ標準ディレクトリを探します

includeltstdiohgt によって組み込まれた define EOF (-1) define EOF (-1) define define helliphelliphelliphellip 組み込み helliphelliphelliphellip

main() stdiohファイル

int helliphelliphelliphellip helliphelliphelliphellip

ソースファイル

9-2 文字の置換 プログラム中に使われている文字列を別の文字列に置き換えます

include ltstdiohgt define TRUE 1 define EOF (-1) main() define helliphellip helliphellip

while(TRUE) define TRUE 1 置き換え main() helliphellip helliphellip while(1)

break helliphelliphellip

31

9-3 条件によるコンパイル 識別子が定義されているか否かを判断しコンパイルする範囲を指定します

include ltstdiohgt define UNIX main() ifdef UNIX printf( UNIX yenn) else printf(MS-DOSyenn) endif

include ltstdiohgt define OS UNIX main() if OS == UNIX printf( UNIX yenn) else printf(MS-DOSyenn) endif

32

付 録 1 puts()gets()関数について

行単位に入出力を行う場合には puts() gets() 関数を用います

puts() 標準出力に文字列を出力します

include ltstdiohgt int puts( char s ) puts() は NULL で終る文字列 s を標準出力に出力し最後に改行文字 yenn も出力しま

gets() 標準入力から文字列を入力します

include ltstdiohgt char gets( char s ) 戻り値正常に入力した場合には引数 s の値が返されますエラーやEOFになった場合に

は NULL が返されます gets() は標準入力から復帰文字で終る文字列を入力しs に格納しますこのとき最後の復

帰文字は NULL文字に変更されます

入力行の出力 標準入力から gets() で入力したデータには改行コードは含まれませんまた標準出力へ

puts() で出力を行う場合には必ず改行コードが付加されますgets() を実行したときの戻り値としてファイルの終端を検出した場合には EOF ではなく NULL が返されますので注意して下さい

include ltstdiohgt main() char data[80] while( gets( data ) = NULL )puts( data )

putchar()getchar()関数について putchar() 標準出力に文字を出力します

include ltstdiohgt int putchar(int c ) 戻り値正常に出力できた場合には文字cをエラーの場合にはEOFを返します

33

getchar() 標準入力から文字を入力します

include ltstdiohgt int getchar(void) 戻り値正常に入力した場合には読み込んだ文字を int 型に変換して返しますまたファイ

ルエンドエラーの場合にはEOFを返します

標準入力標準出力

標準入力標準出力はプログラムが開始されるときにはオープンされていますそれぞれのフ

ァイルポインタは stdin stdout になっていますfopen() fclose() をせずとも使用することができます

scanf() 標準出力ストリームからテキストを読み込み解釈します include ltstdiohgt int scanf( const char format [ address ] ) 戻り値正しくスキャンし変換し格納した入力フィールドの数を返しますファイルエンドを読

み込んだ場合は戻り値は EOF となります値を格納したフィールドがなかった場合は戻り値は0となります

一連の入力フィールドをスキャンして1度に1文字ずつストリーム stdin から文字を読み込み

ます次に引き数 format によって指される書式文字列中の書式指定に従って各フィールドを書式化します最後にformat の後に続く各引き数が示しているアドレスに書式化した入力を格納していきます書式文字列中の書式指定の個数はその後に続くアドレスの数と同じでな

ければなりません 書式指定[入力幅][型指定文字] 入力幅 読むべき文字数の最大値 型指定文字 次のとおりです 型指定文字 期待される入力 引き数の型 d 10進整数 int へのポインタ( int arg ) x 16進整数 int へのポインタ( int arg ) f 浮動小数点数 float へのポインタ( float arg ) s 文字列 文字配列へのポインタ( char arg[] ) c 文字 文字へのポインタ( char arg )

printf() フォーマットを指定してテキスト標準出力ストリームに出力します include ltstdiohgt int printf( const char format [ argument ] ) 戻り値出力したバイト数を返しますエラーの場合は EOF を返します

34

format によって指される書式文字列中の書式指定をformat の後に続く各引き数に適用し

書式化されたデータを stdout に出力します書式指定は後に続く引き数と同じ数だけなければなりません

書式指定[印字幅][精度][型指定文字] 印字幅 印字する最小文字数 精度 印字する最大文字数 型指定文字 つぎのとおりです 型指定文字 入力引き数 出力の書式 d 整数 符号付き10進整数 x 整数 符号無し16進整数 f 浮動小数点 符号付きの dddddddd形式の値 c 文字 1個の文字 s 文字列ポインタ ヌル文字に出会うか精度に達するまで 文字をプリントする

fopen()fclose()関数について fopen() ファイルをオープンします

include ltstdiohgt FILE fopen( char filename char mode ) 戻り値正常にファイルのオープンができたらファイルポインタを返しますエラーがあった場

合には NULLを返します 文字列 filename で指定されたファイルをオープンしますオープン後の入出力のモードに

ついては文字列 mode で指定しますmode に指定できる文字は以下のとおりです r 入力モードでオープンします w 出力モードでオープンします a 存在するファイルに追加して出力するモードでオープンします r+ 既に作成してあるファイルを更新(入力出力)するモードでオープンします w+ 新しく作成するファイルを更新モードでオープンします a+ 既に作成してあるファイルの終りから更新用に作成します

以上の文字に b をつけ加えることによりバイナリモードで入出力することができるようになり

ます rb バイナリの入力モードでオープンします wb バイナリの出力モードでオープンします ab 存在するファイルに追加して出力するモード(バイナリ)でオープンします

fclose() 既にオープンしてあるファイルをクローズします include ltstdiohgt fclose( FILE fp ) 既にオープンしているファイルをクローズしますパラメータには fopen() 関数により返された

ファイルポインタを指定します

35

テキストモードとバイナリモード 行の最後はテキストモードの場合改行コードのみとなりバイナリモードの場合には復帰

コードと改行コードの組合わせになります行の最後としてテキストファイルには復帰コード改行

コードが書かれていますがテキストモードでオープンした場合には入力すると改行コードのみに

変換されて入力されますバイナリモードの場合には復帰コード改行コードがそれぞれ入力され

ます

fputs()fgets()関数について fputs() ファイルポインタで指定されるファイルに文字列を出力します

include ltstdiohgt

int fputs( char s FILE fp ) fputs() は NULL で終る文字列 s をファイルポインタに示されるファイルへ出力しますputs()

と違い最後に改行文字 yenn を出力することはありません

fgets() ファイルポインタで指定されるファイルから文字列を入力します include ltstdiohgt char fgets( char s int n FILE fp ) 戻り値正常に入力した場合には引数 s の値が返されますエラーやEOFになった場合に

は NULL が返されます fgets() はファイルポインタで指定されるファイルから ( n - 1 ) 文字または改行文字までの

文字列を入力しs に格納しますgets() と異なり最後に入力された改行文字は NULL 文字に変更されません

標準入力から入力しファイルへ出力する ファイルへ出力あるいは入力を行う場合には改行コードの変換(入力の場合の削除出力の

場合の付加)はされませんしたがって標準入力から入力しファイルへ出力する場合には改行

コードを付加しなければなりません include ltstdiohgt main() char data[80] FILE fp fp = fopen( data w ) while( gets( data ) = NULL ) strcat( data yenn ) 改行コードの付加

fputs( data fp ) fclose( fp )

36

fputc()fgetc()関数について fputc() ファイルポインタで指定されるファイルに1文字出力します

include ltstdiohgt int fputc( int c FILE fp ) 戻り値正常に出力できた場合には文字 c を返しエラーの場合には EOF を返します fputc() は文字 c をファイルポインタで示されるファイルへ出力します

fgetc() ファイルポインタで指定されるファイルから1文字入力します

include ltstdiohgt int fgetc( FILE fp ) 戻り値正常に入力した場合には入力した文字を返しますエラーやEOFになった場合には

EOF が返されます fgetc() はファイルポインタで指定されるファイルから文字を入力します

ファイルの内容の表示 include ltstdiohgt main() FILE fp int ch char fname[30] printf( Key in Fila name gt ) gets( fname ) fp = fopen( fname r ) while( ( ch = fgetc( fp ) ) = EOF )putchar( ch ) fclose( fp )

その他テキスト中で使用された関数について sin() 三角関数の正弦を計算します

include ltmathhgt double sin(double radian) sinはラジアンを単位とする引数 radianの三角関数を計算します

37

strcpy() 文字列を他の文字列へコピーします

include ltstringhgt char strcpy(char string1const char string2) strcpyは引数 string2の指す文字列を null文字まで含めて引数 string1の指す領域にコピ

ーする strcpyは string1を返します

strcat() ある文字列を他の文字列に加えます

include ltstringhgt char strcat( char dest const char src ) 戻り値連結された文字列へのポインタを返します strcat() はsrc のコピーを dest の最後につけ加えます得られる文字列の長さは

strlen(dest)+strlen(src) になります

fabs() 絶対値の計算をします include ltmathhgt double fabs(double z) fabsは倍精度浮動小数の絶対値を計算して返しますつまりzgt=0であれば z をzlt0であ

れば-zを返します exp() 指数関数を計算します

include ltmathhgt double exp(double z) exp は引数zの指数関数つまりezを返すここではeは自然対数の底を表します対数関

数logの逆関数です

38

付 録 2 コンパイルの方法には大きく分けて第4章の実習で学んだようにデータファイルを作成してお

き ccg でコンパイルさせる方法と実行中に対話型でデータを入力していく方法があります ここでは対話型で実行を進めていく方法を紹介します ただしこの方法は計算(cpu)時間が10秒以内のものに限ります10秒を超える計算(cpu)時

間を要する場合はccg でコンパイルをするようにしてください 第4章実習の(2)(p16)までは同様です

コンパイル

コンピュータに処理を依頼します 60us1234boseicc cc rensyuc

所有するファイルの一覧を見てみます

60us1234boseicc ls -l larr 持っているファイルの一覧を見るコマンドです

-rw-r--r-- 1 60us1234 other 128 4月26日 15時14分 rensyuc -rwxr-xr-x 1 60us1234 other 361 4月26日 15時16分 aout

aout という実行形式のファイルが作成されています

実行

60us1234boseicc aout12 35[リターン] データを入力

1 200000 3500000 4200000 実行結果の出力

60us1234boseicc

注意

aout ファイルは印刷することができません実行結果を印刷する場合にはファイルに落とし てから出力するようにしましょう

60us1234boseicc aout gt kekka12 35[リターン] データを入力

60us1234boseicc more kekka 計算結果の確認 60us1234boseicc lpr kekka 計算結果の印刷

39

Page 34: n 第1章 章立ての部分は、書式(PC入門大見出し)を …第2章 数の表現 2-1 2進数 電子計算機の動作原理は0と1で表される2進数です。また、人間が日常生活で扱っている数

9-3 条件によるコンパイル 識別子が定義されているか否かを判断しコンパイルする範囲を指定します

include ltstdiohgt define UNIX main() ifdef UNIX printf( UNIX yenn) else printf(MS-DOSyenn) endif

include ltstdiohgt define OS UNIX main() if OS == UNIX printf( UNIX yenn) else printf(MS-DOSyenn) endif

32

付 録 1 puts()gets()関数について

行単位に入出力を行う場合には puts() gets() 関数を用います

puts() 標準出力に文字列を出力します

include ltstdiohgt int puts( char s ) puts() は NULL で終る文字列 s を標準出力に出力し最後に改行文字 yenn も出力しま

gets() 標準入力から文字列を入力します

include ltstdiohgt char gets( char s ) 戻り値正常に入力した場合には引数 s の値が返されますエラーやEOFになった場合に

は NULL が返されます gets() は標準入力から復帰文字で終る文字列を入力しs に格納しますこのとき最後の復

帰文字は NULL文字に変更されます

入力行の出力 標準入力から gets() で入力したデータには改行コードは含まれませんまた標準出力へ

puts() で出力を行う場合には必ず改行コードが付加されますgets() を実行したときの戻り値としてファイルの終端を検出した場合には EOF ではなく NULL が返されますので注意して下さい

include ltstdiohgt main() char data[80] while( gets( data ) = NULL )puts( data )

putchar()getchar()関数について putchar() 標準出力に文字を出力します

include ltstdiohgt int putchar(int c ) 戻り値正常に出力できた場合には文字cをエラーの場合にはEOFを返します

33

getchar() 標準入力から文字を入力します

include ltstdiohgt int getchar(void) 戻り値正常に入力した場合には読み込んだ文字を int 型に変換して返しますまたファイ

ルエンドエラーの場合にはEOFを返します

標準入力標準出力

標準入力標準出力はプログラムが開始されるときにはオープンされていますそれぞれのフ

ァイルポインタは stdin stdout になっていますfopen() fclose() をせずとも使用することができます

scanf() 標準出力ストリームからテキストを読み込み解釈します include ltstdiohgt int scanf( const char format [ address ] ) 戻り値正しくスキャンし変換し格納した入力フィールドの数を返しますファイルエンドを読

み込んだ場合は戻り値は EOF となります値を格納したフィールドがなかった場合は戻り値は0となります

一連の入力フィールドをスキャンして1度に1文字ずつストリーム stdin から文字を読み込み

ます次に引き数 format によって指される書式文字列中の書式指定に従って各フィールドを書式化します最後にformat の後に続く各引き数が示しているアドレスに書式化した入力を格納していきます書式文字列中の書式指定の個数はその後に続くアドレスの数と同じでな

ければなりません 書式指定[入力幅][型指定文字] 入力幅 読むべき文字数の最大値 型指定文字 次のとおりです 型指定文字 期待される入力 引き数の型 d 10進整数 int へのポインタ( int arg ) x 16進整数 int へのポインタ( int arg ) f 浮動小数点数 float へのポインタ( float arg ) s 文字列 文字配列へのポインタ( char arg[] ) c 文字 文字へのポインタ( char arg )

printf() フォーマットを指定してテキスト標準出力ストリームに出力します include ltstdiohgt int printf( const char format [ argument ] ) 戻り値出力したバイト数を返しますエラーの場合は EOF を返します

34

format によって指される書式文字列中の書式指定をformat の後に続く各引き数に適用し

書式化されたデータを stdout に出力します書式指定は後に続く引き数と同じ数だけなければなりません

書式指定[印字幅][精度][型指定文字] 印字幅 印字する最小文字数 精度 印字する最大文字数 型指定文字 つぎのとおりです 型指定文字 入力引き数 出力の書式 d 整数 符号付き10進整数 x 整数 符号無し16進整数 f 浮動小数点 符号付きの dddddddd形式の値 c 文字 1個の文字 s 文字列ポインタ ヌル文字に出会うか精度に達するまで 文字をプリントする

fopen()fclose()関数について fopen() ファイルをオープンします

include ltstdiohgt FILE fopen( char filename char mode ) 戻り値正常にファイルのオープンができたらファイルポインタを返しますエラーがあった場

合には NULLを返します 文字列 filename で指定されたファイルをオープンしますオープン後の入出力のモードに

ついては文字列 mode で指定しますmode に指定できる文字は以下のとおりです r 入力モードでオープンします w 出力モードでオープンします a 存在するファイルに追加して出力するモードでオープンします r+ 既に作成してあるファイルを更新(入力出力)するモードでオープンします w+ 新しく作成するファイルを更新モードでオープンします a+ 既に作成してあるファイルの終りから更新用に作成します

以上の文字に b をつけ加えることによりバイナリモードで入出力することができるようになり

ます rb バイナリの入力モードでオープンします wb バイナリの出力モードでオープンします ab 存在するファイルに追加して出力するモード(バイナリ)でオープンします

fclose() 既にオープンしてあるファイルをクローズします include ltstdiohgt fclose( FILE fp ) 既にオープンしているファイルをクローズしますパラメータには fopen() 関数により返された

ファイルポインタを指定します

35

テキストモードとバイナリモード 行の最後はテキストモードの場合改行コードのみとなりバイナリモードの場合には復帰

コードと改行コードの組合わせになります行の最後としてテキストファイルには復帰コード改行

コードが書かれていますがテキストモードでオープンした場合には入力すると改行コードのみに

変換されて入力されますバイナリモードの場合には復帰コード改行コードがそれぞれ入力され

ます

fputs()fgets()関数について fputs() ファイルポインタで指定されるファイルに文字列を出力します

include ltstdiohgt

int fputs( char s FILE fp ) fputs() は NULL で終る文字列 s をファイルポインタに示されるファイルへ出力しますputs()

と違い最後に改行文字 yenn を出力することはありません

fgets() ファイルポインタで指定されるファイルから文字列を入力します include ltstdiohgt char fgets( char s int n FILE fp ) 戻り値正常に入力した場合には引数 s の値が返されますエラーやEOFになった場合に

は NULL が返されます fgets() はファイルポインタで指定されるファイルから ( n - 1 ) 文字または改行文字までの

文字列を入力しs に格納しますgets() と異なり最後に入力された改行文字は NULL 文字に変更されません

標準入力から入力しファイルへ出力する ファイルへ出力あるいは入力を行う場合には改行コードの変換(入力の場合の削除出力の

場合の付加)はされませんしたがって標準入力から入力しファイルへ出力する場合には改行

コードを付加しなければなりません include ltstdiohgt main() char data[80] FILE fp fp = fopen( data w ) while( gets( data ) = NULL ) strcat( data yenn ) 改行コードの付加

fputs( data fp ) fclose( fp )

36

fputc()fgetc()関数について fputc() ファイルポインタで指定されるファイルに1文字出力します

include ltstdiohgt int fputc( int c FILE fp ) 戻り値正常に出力できた場合には文字 c を返しエラーの場合には EOF を返します fputc() は文字 c をファイルポインタで示されるファイルへ出力します

fgetc() ファイルポインタで指定されるファイルから1文字入力します

include ltstdiohgt int fgetc( FILE fp ) 戻り値正常に入力した場合には入力した文字を返しますエラーやEOFになった場合には

EOF が返されます fgetc() はファイルポインタで指定されるファイルから文字を入力します

ファイルの内容の表示 include ltstdiohgt main() FILE fp int ch char fname[30] printf( Key in Fila name gt ) gets( fname ) fp = fopen( fname r ) while( ( ch = fgetc( fp ) ) = EOF )putchar( ch ) fclose( fp )

その他テキスト中で使用された関数について sin() 三角関数の正弦を計算します

include ltmathhgt double sin(double radian) sinはラジアンを単位とする引数 radianの三角関数を計算します

37

strcpy() 文字列を他の文字列へコピーします

include ltstringhgt char strcpy(char string1const char string2) strcpyは引数 string2の指す文字列を null文字まで含めて引数 string1の指す領域にコピ

ーする strcpyは string1を返します

strcat() ある文字列を他の文字列に加えます

include ltstringhgt char strcat( char dest const char src ) 戻り値連結された文字列へのポインタを返します strcat() はsrc のコピーを dest の最後につけ加えます得られる文字列の長さは

strlen(dest)+strlen(src) になります

fabs() 絶対値の計算をします include ltmathhgt double fabs(double z) fabsは倍精度浮動小数の絶対値を計算して返しますつまりzgt=0であれば z をzlt0であ

れば-zを返します exp() 指数関数を計算します

include ltmathhgt double exp(double z) exp は引数zの指数関数つまりezを返すここではeは自然対数の底を表します対数関

数logの逆関数です

38

付 録 2 コンパイルの方法には大きく分けて第4章の実習で学んだようにデータファイルを作成してお

き ccg でコンパイルさせる方法と実行中に対話型でデータを入力していく方法があります ここでは対話型で実行を進めていく方法を紹介します ただしこの方法は計算(cpu)時間が10秒以内のものに限ります10秒を超える計算(cpu)時

間を要する場合はccg でコンパイルをするようにしてください 第4章実習の(2)(p16)までは同様です

コンパイル

コンピュータに処理を依頼します 60us1234boseicc cc rensyuc

所有するファイルの一覧を見てみます

60us1234boseicc ls -l larr 持っているファイルの一覧を見るコマンドです

-rw-r--r-- 1 60us1234 other 128 4月26日 15時14分 rensyuc -rwxr-xr-x 1 60us1234 other 361 4月26日 15時16分 aout

aout という実行形式のファイルが作成されています

実行

60us1234boseicc aout12 35[リターン] データを入力

1 200000 3500000 4200000 実行結果の出力

60us1234boseicc

注意

aout ファイルは印刷することができません実行結果を印刷する場合にはファイルに落とし てから出力するようにしましょう

60us1234boseicc aout gt kekka12 35[リターン] データを入力

60us1234boseicc more kekka 計算結果の確認 60us1234boseicc lpr kekka 計算結果の印刷

39

Page 35: n 第1章 章立ての部分は、書式(PC入門大見出し)を …第2章 数の表現 2-1 2進数 電子計算機の動作原理は0と1で表される2進数です。また、人間が日常生活で扱っている数

付 録 1 puts()gets()関数について

行単位に入出力を行う場合には puts() gets() 関数を用います

puts() 標準出力に文字列を出力します

include ltstdiohgt int puts( char s ) puts() は NULL で終る文字列 s を標準出力に出力し最後に改行文字 yenn も出力しま

gets() 標準入力から文字列を入力します

include ltstdiohgt char gets( char s ) 戻り値正常に入力した場合には引数 s の値が返されますエラーやEOFになった場合に

は NULL が返されます gets() は標準入力から復帰文字で終る文字列を入力しs に格納しますこのとき最後の復

帰文字は NULL文字に変更されます

入力行の出力 標準入力から gets() で入力したデータには改行コードは含まれませんまた標準出力へ

puts() で出力を行う場合には必ず改行コードが付加されますgets() を実行したときの戻り値としてファイルの終端を検出した場合には EOF ではなく NULL が返されますので注意して下さい

include ltstdiohgt main() char data[80] while( gets( data ) = NULL )puts( data )

putchar()getchar()関数について putchar() 標準出力に文字を出力します

include ltstdiohgt int putchar(int c ) 戻り値正常に出力できた場合には文字cをエラーの場合にはEOFを返します

33

getchar() 標準入力から文字を入力します

include ltstdiohgt int getchar(void) 戻り値正常に入力した場合には読み込んだ文字を int 型に変換して返しますまたファイ

ルエンドエラーの場合にはEOFを返します

標準入力標準出力

標準入力標準出力はプログラムが開始されるときにはオープンされていますそれぞれのフ

ァイルポインタは stdin stdout になっていますfopen() fclose() をせずとも使用することができます

scanf() 標準出力ストリームからテキストを読み込み解釈します include ltstdiohgt int scanf( const char format [ address ] ) 戻り値正しくスキャンし変換し格納した入力フィールドの数を返しますファイルエンドを読

み込んだ場合は戻り値は EOF となります値を格納したフィールドがなかった場合は戻り値は0となります

一連の入力フィールドをスキャンして1度に1文字ずつストリーム stdin から文字を読み込み

ます次に引き数 format によって指される書式文字列中の書式指定に従って各フィールドを書式化します最後にformat の後に続く各引き数が示しているアドレスに書式化した入力を格納していきます書式文字列中の書式指定の個数はその後に続くアドレスの数と同じでな

ければなりません 書式指定[入力幅][型指定文字] 入力幅 読むべき文字数の最大値 型指定文字 次のとおりです 型指定文字 期待される入力 引き数の型 d 10進整数 int へのポインタ( int arg ) x 16進整数 int へのポインタ( int arg ) f 浮動小数点数 float へのポインタ( float arg ) s 文字列 文字配列へのポインタ( char arg[] ) c 文字 文字へのポインタ( char arg )

printf() フォーマットを指定してテキスト標準出力ストリームに出力します include ltstdiohgt int printf( const char format [ argument ] ) 戻り値出力したバイト数を返しますエラーの場合は EOF を返します

34

format によって指される書式文字列中の書式指定をformat の後に続く各引き数に適用し

書式化されたデータを stdout に出力します書式指定は後に続く引き数と同じ数だけなければなりません

書式指定[印字幅][精度][型指定文字] 印字幅 印字する最小文字数 精度 印字する最大文字数 型指定文字 つぎのとおりです 型指定文字 入力引き数 出力の書式 d 整数 符号付き10進整数 x 整数 符号無し16進整数 f 浮動小数点 符号付きの dddddddd形式の値 c 文字 1個の文字 s 文字列ポインタ ヌル文字に出会うか精度に達するまで 文字をプリントする

fopen()fclose()関数について fopen() ファイルをオープンします

include ltstdiohgt FILE fopen( char filename char mode ) 戻り値正常にファイルのオープンができたらファイルポインタを返しますエラーがあった場

合には NULLを返します 文字列 filename で指定されたファイルをオープンしますオープン後の入出力のモードに

ついては文字列 mode で指定しますmode に指定できる文字は以下のとおりです r 入力モードでオープンします w 出力モードでオープンします a 存在するファイルに追加して出力するモードでオープンします r+ 既に作成してあるファイルを更新(入力出力)するモードでオープンします w+ 新しく作成するファイルを更新モードでオープンします a+ 既に作成してあるファイルの終りから更新用に作成します

以上の文字に b をつけ加えることによりバイナリモードで入出力することができるようになり

ます rb バイナリの入力モードでオープンします wb バイナリの出力モードでオープンします ab 存在するファイルに追加して出力するモード(バイナリ)でオープンします

fclose() 既にオープンしてあるファイルをクローズします include ltstdiohgt fclose( FILE fp ) 既にオープンしているファイルをクローズしますパラメータには fopen() 関数により返された

ファイルポインタを指定します

35

テキストモードとバイナリモード 行の最後はテキストモードの場合改行コードのみとなりバイナリモードの場合には復帰

コードと改行コードの組合わせになります行の最後としてテキストファイルには復帰コード改行

コードが書かれていますがテキストモードでオープンした場合には入力すると改行コードのみに

変換されて入力されますバイナリモードの場合には復帰コード改行コードがそれぞれ入力され

ます

fputs()fgets()関数について fputs() ファイルポインタで指定されるファイルに文字列を出力します

include ltstdiohgt

int fputs( char s FILE fp ) fputs() は NULL で終る文字列 s をファイルポインタに示されるファイルへ出力しますputs()

と違い最後に改行文字 yenn を出力することはありません

fgets() ファイルポインタで指定されるファイルから文字列を入力します include ltstdiohgt char fgets( char s int n FILE fp ) 戻り値正常に入力した場合には引数 s の値が返されますエラーやEOFになった場合に

は NULL が返されます fgets() はファイルポインタで指定されるファイルから ( n - 1 ) 文字または改行文字までの

文字列を入力しs に格納しますgets() と異なり最後に入力された改行文字は NULL 文字に変更されません

標準入力から入力しファイルへ出力する ファイルへ出力あるいは入力を行う場合には改行コードの変換(入力の場合の削除出力の

場合の付加)はされませんしたがって標準入力から入力しファイルへ出力する場合には改行

コードを付加しなければなりません include ltstdiohgt main() char data[80] FILE fp fp = fopen( data w ) while( gets( data ) = NULL ) strcat( data yenn ) 改行コードの付加

fputs( data fp ) fclose( fp )

36

fputc()fgetc()関数について fputc() ファイルポインタで指定されるファイルに1文字出力します

include ltstdiohgt int fputc( int c FILE fp ) 戻り値正常に出力できた場合には文字 c を返しエラーの場合には EOF を返します fputc() は文字 c をファイルポインタで示されるファイルへ出力します

fgetc() ファイルポインタで指定されるファイルから1文字入力します

include ltstdiohgt int fgetc( FILE fp ) 戻り値正常に入力した場合には入力した文字を返しますエラーやEOFになった場合には

EOF が返されます fgetc() はファイルポインタで指定されるファイルから文字を入力します

ファイルの内容の表示 include ltstdiohgt main() FILE fp int ch char fname[30] printf( Key in Fila name gt ) gets( fname ) fp = fopen( fname r ) while( ( ch = fgetc( fp ) ) = EOF )putchar( ch ) fclose( fp )

その他テキスト中で使用された関数について sin() 三角関数の正弦を計算します

include ltmathhgt double sin(double radian) sinはラジアンを単位とする引数 radianの三角関数を計算します

37

strcpy() 文字列を他の文字列へコピーします

include ltstringhgt char strcpy(char string1const char string2) strcpyは引数 string2の指す文字列を null文字まで含めて引数 string1の指す領域にコピ

ーする strcpyは string1を返します

strcat() ある文字列を他の文字列に加えます

include ltstringhgt char strcat( char dest const char src ) 戻り値連結された文字列へのポインタを返します strcat() はsrc のコピーを dest の最後につけ加えます得られる文字列の長さは

strlen(dest)+strlen(src) になります

fabs() 絶対値の計算をします include ltmathhgt double fabs(double z) fabsは倍精度浮動小数の絶対値を計算して返しますつまりzgt=0であれば z をzlt0であ

れば-zを返します exp() 指数関数を計算します

include ltmathhgt double exp(double z) exp は引数zの指数関数つまりezを返すここではeは自然対数の底を表します対数関

数logの逆関数です

38

付 録 2 コンパイルの方法には大きく分けて第4章の実習で学んだようにデータファイルを作成してお

き ccg でコンパイルさせる方法と実行中に対話型でデータを入力していく方法があります ここでは対話型で実行を進めていく方法を紹介します ただしこの方法は計算(cpu)時間が10秒以内のものに限ります10秒を超える計算(cpu)時

間を要する場合はccg でコンパイルをするようにしてください 第4章実習の(2)(p16)までは同様です

コンパイル

コンピュータに処理を依頼します 60us1234boseicc cc rensyuc

所有するファイルの一覧を見てみます

60us1234boseicc ls -l larr 持っているファイルの一覧を見るコマンドです

-rw-r--r-- 1 60us1234 other 128 4月26日 15時14分 rensyuc -rwxr-xr-x 1 60us1234 other 361 4月26日 15時16分 aout

aout という実行形式のファイルが作成されています

実行

60us1234boseicc aout12 35[リターン] データを入力

1 200000 3500000 4200000 実行結果の出力

60us1234boseicc

注意

aout ファイルは印刷することができません実行結果を印刷する場合にはファイルに落とし てから出力するようにしましょう

60us1234boseicc aout gt kekka12 35[リターン] データを入力

60us1234boseicc more kekka 計算結果の確認 60us1234boseicc lpr kekka 計算結果の印刷

39

Page 36: n 第1章 章立ての部分は、書式(PC入門大見出し)を …第2章 数の表現 2-1 2進数 電子計算機の動作原理は0と1で表される2進数です。また、人間が日常生活で扱っている数

getchar() 標準入力から文字を入力します

include ltstdiohgt int getchar(void) 戻り値正常に入力した場合には読み込んだ文字を int 型に変換して返しますまたファイ

ルエンドエラーの場合にはEOFを返します

標準入力標準出力

標準入力標準出力はプログラムが開始されるときにはオープンされていますそれぞれのフ

ァイルポインタは stdin stdout になっていますfopen() fclose() をせずとも使用することができます

scanf() 標準出力ストリームからテキストを読み込み解釈します include ltstdiohgt int scanf( const char format [ address ] ) 戻り値正しくスキャンし変換し格納した入力フィールドの数を返しますファイルエンドを読

み込んだ場合は戻り値は EOF となります値を格納したフィールドがなかった場合は戻り値は0となります

一連の入力フィールドをスキャンして1度に1文字ずつストリーム stdin から文字を読み込み

ます次に引き数 format によって指される書式文字列中の書式指定に従って各フィールドを書式化します最後にformat の後に続く各引き数が示しているアドレスに書式化した入力を格納していきます書式文字列中の書式指定の個数はその後に続くアドレスの数と同じでな

ければなりません 書式指定[入力幅][型指定文字] 入力幅 読むべき文字数の最大値 型指定文字 次のとおりです 型指定文字 期待される入力 引き数の型 d 10進整数 int へのポインタ( int arg ) x 16進整数 int へのポインタ( int arg ) f 浮動小数点数 float へのポインタ( float arg ) s 文字列 文字配列へのポインタ( char arg[] ) c 文字 文字へのポインタ( char arg )

printf() フォーマットを指定してテキスト標準出力ストリームに出力します include ltstdiohgt int printf( const char format [ argument ] ) 戻り値出力したバイト数を返しますエラーの場合は EOF を返します

34

format によって指される書式文字列中の書式指定をformat の後に続く各引き数に適用し

書式化されたデータを stdout に出力します書式指定は後に続く引き数と同じ数だけなければなりません

書式指定[印字幅][精度][型指定文字] 印字幅 印字する最小文字数 精度 印字する最大文字数 型指定文字 つぎのとおりです 型指定文字 入力引き数 出力の書式 d 整数 符号付き10進整数 x 整数 符号無し16進整数 f 浮動小数点 符号付きの dddddddd形式の値 c 文字 1個の文字 s 文字列ポインタ ヌル文字に出会うか精度に達するまで 文字をプリントする

fopen()fclose()関数について fopen() ファイルをオープンします

include ltstdiohgt FILE fopen( char filename char mode ) 戻り値正常にファイルのオープンができたらファイルポインタを返しますエラーがあった場

合には NULLを返します 文字列 filename で指定されたファイルをオープンしますオープン後の入出力のモードに

ついては文字列 mode で指定しますmode に指定できる文字は以下のとおりです r 入力モードでオープンします w 出力モードでオープンします a 存在するファイルに追加して出力するモードでオープンします r+ 既に作成してあるファイルを更新(入力出力)するモードでオープンします w+ 新しく作成するファイルを更新モードでオープンします a+ 既に作成してあるファイルの終りから更新用に作成します

以上の文字に b をつけ加えることによりバイナリモードで入出力することができるようになり

ます rb バイナリの入力モードでオープンします wb バイナリの出力モードでオープンします ab 存在するファイルに追加して出力するモード(バイナリ)でオープンします

fclose() 既にオープンしてあるファイルをクローズします include ltstdiohgt fclose( FILE fp ) 既にオープンしているファイルをクローズしますパラメータには fopen() 関数により返された

ファイルポインタを指定します

35

テキストモードとバイナリモード 行の最後はテキストモードの場合改行コードのみとなりバイナリモードの場合には復帰

コードと改行コードの組合わせになります行の最後としてテキストファイルには復帰コード改行

コードが書かれていますがテキストモードでオープンした場合には入力すると改行コードのみに

変換されて入力されますバイナリモードの場合には復帰コード改行コードがそれぞれ入力され

ます

fputs()fgets()関数について fputs() ファイルポインタで指定されるファイルに文字列を出力します

include ltstdiohgt

int fputs( char s FILE fp ) fputs() は NULL で終る文字列 s をファイルポインタに示されるファイルへ出力しますputs()

と違い最後に改行文字 yenn を出力することはありません

fgets() ファイルポインタで指定されるファイルから文字列を入力します include ltstdiohgt char fgets( char s int n FILE fp ) 戻り値正常に入力した場合には引数 s の値が返されますエラーやEOFになった場合に

は NULL が返されます fgets() はファイルポインタで指定されるファイルから ( n - 1 ) 文字または改行文字までの

文字列を入力しs に格納しますgets() と異なり最後に入力された改行文字は NULL 文字に変更されません

標準入力から入力しファイルへ出力する ファイルへ出力あるいは入力を行う場合には改行コードの変換(入力の場合の削除出力の

場合の付加)はされませんしたがって標準入力から入力しファイルへ出力する場合には改行

コードを付加しなければなりません include ltstdiohgt main() char data[80] FILE fp fp = fopen( data w ) while( gets( data ) = NULL ) strcat( data yenn ) 改行コードの付加

fputs( data fp ) fclose( fp )

36

fputc()fgetc()関数について fputc() ファイルポインタで指定されるファイルに1文字出力します

include ltstdiohgt int fputc( int c FILE fp ) 戻り値正常に出力できた場合には文字 c を返しエラーの場合には EOF を返します fputc() は文字 c をファイルポインタで示されるファイルへ出力します

fgetc() ファイルポインタで指定されるファイルから1文字入力します

include ltstdiohgt int fgetc( FILE fp ) 戻り値正常に入力した場合には入力した文字を返しますエラーやEOFになった場合には

EOF が返されます fgetc() はファイルポインタで指定されるファイルから文字を入力します

ファイルの内容の表示 include ltstdiohgt main() FILE fp int ch char fname[30] printf( Key in Fila name gt ) gets( fname ) fp = fopen( fname r ) while( ( ch = fgetc( fp ) ) = EOF )putchar( ch ) fclose( fp )

その他テキスト中で使用された関数について sin() 三角関数の正弦を計算します

include ltmathhgt double sin(double radian) sinはラジアンを単位とする引数 radianの三角関数を計算します

37

strcpy() 文字列を他の文字列へコピーします

include ltstringhgt char strcpy(char string1const char string2) strcpyは引数 string2の指す文字列を null文字まで含めて引数 string1の指す領域にコピ

ーする strcpyは string1を返します

strcat() ある文字列を他の文字列に加えます

include ltstringhgt char strcat( char dest const char src ) 戻り値連結された文字列へのポインタを返します strcat() はsrc のコピーを dest の最後につけ加えます得られる文字列の長さは

strlen(dest)+strlen(src) になります

fabs() 絶対値の計算をします include ltmathhgt double fabs(double z) fabsは倍精度浮動小数の絶対値を計算して返しますつまりzgt=0であれば z をzlt0であ

れば-zを返します exp() 指数関数を計算します

include ltmathhgt double exp(double z) exp は引数zの指数関数つまりezを返すここではeは自然対数の底を表します対数関

数logの逆関数です

38

付 録 2 コンパイルの方法には大きく分けて第4章の実習で学んだようにデータファイルを作成してお

き ccg でコンパイルさせる方法と実行中に対話型でデータを入力していく方法があります ここでは対話型で実行を進めていく方法を紹介します ただしこの方法は計算(cpu)時間が10秒以内のものに限ります10秒を超える計算(cpu)時

間を要する場合はccg でコンパイルをするようにしてください 第4章実習の(2)(p16)までは同様です

コンパイル

コンピュータに処理を依頼します 60us1234boseicc cc rensyuc

所有するファイルの一覧を見てみます

60us1234boseicc ls -l larr 持っているファイルの一覧を見るコマンドです

-rw-r--r-- 1 60us1234 other 128 4月26日 15時14分 rensyuc -rwxr-xr-x 1 60us1234 other 361 4月26日 15時16分 aout

aout という実行形式のファイルが作成されています

実行

60us1234boseicc aout12 35[リターン] データを入力

1 200000 3500000 4200000 実行結果の出力

60us1234boseicc

注意

aout ファイルは印刷することができません実行結果を印刷する場合にはファイルに落とし てから出力するようにしましょう

60us1234boseicc aout gt kekka12 35[リターン] データを入力

60us1234boseicc more kekka 計算結果の確認 60us1234boseicc lpr kekka 計算結果の印刷

39

Page 37: n 第1章 章立ての部分は、書式(PC入門大見出し)を …第2章 数の表現 2-1 2進数 電子計算機の動作原理は0と1で表される2進数です。また、人間が日常生活で扱っている数

format によって指される書式文字列中の書式指定をformat の後に続く各引き数に適用し

書式化されたデータを stdout に出力します書式指定は後に続く引き数と同じ数だけなければなりません

書式指定[印字幅][精度][型指定文字] 印字幅 印字する最小文字数 精度 印字する最大文字数 型指定文字 つぎのとおりです 型指定文字 入力引き数 出力の書式 d 整数 符号付き10進整数 x 整数 符号無し16進整数 f 浮動小数点 符号付きの dddddddd形式の値 c 文字 1個の文字 s 文字列ポインタ ヌル文字に出会うか精度に達するまで 文字をプリントする

fopen()fclose()関数について fopen() ファイルをオープンします

include ltstdiohgt FILE fopen( char filename char mode ) 戻り値正常にファイルのオープンができたらファイルポインタを返しますエラーがあった場

合には NULLを返します 文字列 filename で指定されたファイルをオープンしますオープン後の入出力のモードに

ついては文字列 mode で指定しますmode に指定できる文字は以下のとおりです r 入力モードでオープンします w 出力モードでオープンします a 存在するファイルに追加して出力するモードでオープンします r+ 既に作成してあるファイルを更新(入力出力)するモードでオープンします w+ 新しく作成するファイルを更新モードでオープンします a+ 既に作成してあるファイルの終りから更新用に作成します

以上の文字に b をつけ加えることによりバイナリモードで入出力することができるようになり

ます rb バイナリの入力モードでオープンします wb バイナリの出力モードでオープンします ab 存在するファイルに追加して出力するモード(バイナリ)でオープンします

fclose() 既にオープンしてあるファイルをクローズします include ltstdiohgt fclose( FILE fp ) 既にオープンしているファイルをクローズしますパラメータには fopen() 関数により返された

ファイルポインタを指定します

35

テキストモードとバイナリモード 行の最後はテキストモードの場合改行コードのみとなりバイナリモードの場合には復帰

コードと改行コードの組合わせになります行の最後としてテキストファイルには復帰コード改行

コードが書かれていますがテキストモードでオープンした場合には入力すると改行コードのみに

変換されて入力されますバイナリモードの場合には復帰コード改行コードがそれぞれ入力され

ます

fputs()fgets()関数について fputs() ファイルポインタで指定されるファイルに文字列を出力します

include ltstdiohgt

int fputs( char s FILE fp ) fputs() は NULL で終る文字列 s をファイルポインタに示されるファイルへ出力しますputs()

と違い最後に改行文字 yenn を出力することはありません

fgets() ファイルポインタで指定されるファイルから文字列を入力します include ltstdiohgt char fgets( char s int n FILE fp ) 戻り値正常に入力した場合には引数 s の値が返されますエラーやEOFになった場合に

は NULL が返されます fgets() はファイルポインタで指定されるファイルから ( n - 1 ) 文字または改行文字までの

文字列を入力しs に格納しますgets() と異なり最後に入力された改行文字は NULL 文字に変更されません

標準入力から入力しファイルへ出力する ファイルへ出力あるいは入力を行う場合には改行コードの変換(入力の場合の削除出力の

場合の付加)はされませんしたがって標準入力から入力しファイルへ出力する場合には改行

コードを付加しなければなりません include ltstdiohgt main() char data[80] FILE fp fp = fopen( data w ) while( gets( data ) = NULL ) strcat( data yenn ) 改行コードの付加

fputs( data fp ) fclose( fp )

36

fputc()fgetc()関数について fputc() ファイルポインタで指定されるファイルに1文字出力します

include ltstdiohgt int fputc( int c FILE fp ) 戻り値正常に出力できた場合には文字 c を返しエラーの場合には EOF を返します fputc() は文字 c をファイルポインタで示されるファイルへ出力します

fgetc() ファイルポインタで指定されるファイルから1文字入力します

include ltstdiohgt int fgetc( FILE fp ) 戻り値正常に入力した場合には入力した文字を返しますエラーやEOFになった場合には

EOF が返されます fgetc() はファイルポインタで指定されるファイルから文字を入力します

ファイルの内容の表示 include ltstdiohgt main() FILE fp int ch char fname[30] printf( Key in Fila name gt ) gets( fname ) fp = fopen( fname r ) while( ( ch = fgetc( fp ) ) = EOF )putchar( ch ) fclose( fp )

その他テキスト中で使用された関数について sin() 三角関数の正弦を計算します

include ltmathhgt double sin(double radian) sinはラジアンを単位とする引数 radianの三角関数を計算します

37

strcpy() 文字列を他の文字列へコピーします

include ltstringhgt char strcpy(char string1const char string2) strcpyは引数 string2の指す文字列を null文字まで含めて引数 string1の指す領域にコピ

ーする strcpyは string1を返します

strcat() ある文字列を他の文字列に加えます

include ltstringhgt char strcat( char dest const char src ) 戻り値連結された文字列へのポインタを返します strcat() はsrc のコピーを dest の最後につけ加えます得られる文字列の長さは

strlen(dest)+strlen(src) になります

fabs() 絶対値の計算をします include ltmathhgt double fabs(double z) fabsは倍精度浮動小数の絶対値を計算して返しますつまりzgt=0であれば z をzlt0であ

れば-zを返します exp() 指数関数を計算します

include ltmathhgt double exp(double z) exp は引数zの指数関数つまりezを返すここではeは自然対数の底を表します対数関

数logの逆関数です

38

付 録 2 コンパイルの方法には大きく分けて第4章の実習で学んだようにデータファイルを作成してお

き ccg でコンパイルさせる方法と実行中に対話型でデータを入力していく方法があります ここでは対話型で実行を進めていく方法を紹介します ただしこの方法は計算(cpu)時間が10秒以内のものに限ります10秒を超える計算(cpu)時

間を要する場合はccg でコンパイルをするようにしてください 第4章実習の(2)(p16)までは同様です

コンパイル

コンピュータに処理を依頼します 60us1234boseicc cc rensyuc

所有するファイルの一覧を見てみます

60us1234boseicc ls -l larr 持っているファイルの一覧を見るコマンドです

-rw-r--r-- 1 60us1234 other 128 4月26日 15時14分 rensyuc -rwxr-xr-x 1 60us1234 other 361 4月26日 15時16分 aout

aout という実行形式のファイルが作成されています

実行

60us1234boseicc aout12 35[リターン] データを入力

1 200000 3500000 4200000 実行結果の出力

60us1234boseicc

注意

aout ファイルは印刷することができません実行結果を印刷する場合にはファイルに落とし てから出力するようにしましょう

60us1234boseicc aout gt kekka12 35[リターン] データを入力

60us1234boseicc more kekka 計算結果の確認 60us1234boseicc lpr kekka 計算結果の印刷

39

Page 38: n 第1章 章立ての部分は、書式(PC入門大見出し)を …第2章 数の表現 2-1 2進数 電子計算機の動作原理は0と1で表される2進数です。また、人間が日常生活で扱っている数

テキストモードとバイナリモード 行の最後はテキストモードの場合改行コードのみとなりバイナリモードの場合には復帰

コードと改行コードの組合わせになります行の最後としてテキストファイルには復帰コード改行

コードが書かれていますがテキストモードでオープンした場合には入力すると改行コードのみに

変換されて入力されますバイナリモードの場合には復帰コード改行コードがそれぞれ入力され

ます

fputs()fgets()関数について fputs() ファイルポインタで指定されるファイルに文字列を出力します

include ltstdiohgt

int fputs( char s FILE fp ) fputs() は NULL で終る文字列 s をファイルポインタに示されるファイルへ出力しますputs()

と違い最後に改行文字 yenn を出力することはありません

fgets() ファイルポインタで指定されるファイルから文字列を入力します include ltstdiohgt char fgets( char s int n FILE fp ) 戻り値正常に入力した場合には引数 s の値が返されますエラーやEOFになった場合に

は NULL が返されます fgets() はファイルポインタで指定されるファイルから ( n - 1 ) 文字または改行文字までの

文字列を入力しs に格納しますgets() と異なり最後に入力された改行文字は NULL 文字に変更されません

標準入力から入力しファイルへ出力する ファイルへ出力あるいは入力を行う場合には改行コードの変換(入力の場合の削除出力の

場合の付加)はされませんしたがって標準入力から入力しファイルへ出力する場合には改行

コードを付加しなければなりません include ltstdiohgt main() char data[80] FILE fp fp = fopen( data w ) while( gets( data ) = NULL ) strcat( data yenn ) 改行コードの付加

fputs( data fp ) fclose( fp )

36

fputc()fgetc()関数について fputc() ファイルポインタで指定されるファイルに1文字出力します

include ltstdiohgt int fputc( int c FILE fp ) 戻り値正常に出力できた場合には文字 c を返しエラーの場合には EOF を返します fputc() は文字 c をファイルポインタで示されるファイルへ出力します

fgetc() ファイルポインタで指定されるファイルから1文字入力します

include ltstdiohgt int fgetc( FILE fp ) 戻り値正常に入力した場合には入力した文字を返しますエラーやEOFになった場合には

EOF が返されます fgetc() はファイルポインタで指定されるファイルから文字を入力します

ファイルの内容の表示 include ltstdiohgt main() FILE fp int ch char fname[30] printf( Key in Fila name gt ) gets( fname ) fp = fopen( fname r ) while( ( ch = fgetc( fp ) ) = EOF )putchar( ch ) fclose( fp )

その他テキスト中で使用された関数について sin() 三角関数の正弦を計算します

include ltmathhgt double sin(double radian) sinはラジアンを単位とする引数 radianの三角関数を計算します

37

strcpy() 文字列を他の文字列へコピーします

include ltstringhgt char strcpy(char string1const char string2) strcpyは引数 string2の指す文字列を null文字まで含めて引数 string1の指す領域にコピ

ーする strcpyは string1を返します

strcat() ある文字列を他の文字列に加えます

include ltstringhgt char strcat( char dest const char src ) 戻り値連結された文字列へのポインタを返します strcat() はsrc のコピーを dest の最後につけ加えます得られる文字列の長さは

strlen(dest)+strlen(src) になります

fabs() 絶対値の計算をします include ltmathhgt double fabs(double z) fabsは倍精度浮動小数の絶対値を計算して返しますつまりzgt=0であれば z をzlt0であ

れば-zを返します exp() 指数関数を計算します

include ltmathhgt double exp(double z) exp は引数zの指数関数つまりezを返すここではeは自然対数の底を表します対数関

数logの逆関数です

38

付 録 2 コンパイルの方法には大きく分けて第4章の実習で学んだようにデータファイルを作成してお

き ccg でコンパイルさせる方法と実行中に対話型でデータを入力していく方法があります ここでは対話型で実行を進めていく方法を紹介します ただしこの方法は計算(cpu)時間が10秒以内のものに限ります10秒を超える計算(cpu)時

間を要する場合はccg でコンパイルをするようにしてください 第4章実習の(2)(p16)までは同様です

コンパイル

コンピュータに処理を依頼します 60us1234boseicc cc rensyuc

所有するファイルの一覧を見てみます

60us1234boseicc ls -l larr 持っているファイルの一覧を見るコマンドです

-rw-r--r-- 1 60us1234 other 128 4月26日 15時14分 rensyuc -rwxr-xr-x 1 60us1234 other 361 4月26日 15時16分 aout

aout という実行形式のファイルが作成されています

実行

60us1234boseicc aout12 35[リターン] データを入力

1 200000 3500000 4200000 実行結果の出力

60us1234boseicc

注意

aout ファイルは印刷することができません実行結果を印刷する場合にはファイルに落とし てから出力するようにしましょう

60us1234boseicc aout gt kekka12 35[リターン] データを入力

60us1234boseicc more kekka 計算結果の確認 60us1234boseicc lpr kekka 計算結果の印刷

39

Page 39: n 第1章 章立ての部分は、書式(PC入門大見出し)を …第2章 数の表現 2-1 2進数 電子計算機の動作原理は0と1で表される2進数です。また、人間が日常生活で扱っている数

fputc()fgetc()関数について fputc() ファイルポインタで指定されるファイルに1文字出力します

include ltstdiohgt int fputc( int c FILE fp ) 戻り値正常に出力できた場合には文字 c を返しエラーの場合には EOF を返します fputc() は文字 c をファイルポインタで示されるファイルへ出力します

fgetc() ファイルポインタで指定されるファイルから1文字入力します

include ltstdiohgt int fgetc( FILE fp ) 戻り値正常に入力した場合には入力した文字を返しますエラーやEOFになった場合には

EOF が返されます fgetc() はファイルポインタで指定されるファイルから文字を入力します

ファイルの内容の表示 include ltstdiohgt main() FILE fp int ch char fname[30] printf( Key in Fila name gt ) gets( fname ) fp = fopen( fname r ) while( ( ch = fgetc( fp ) ) = EOF )putchar( ch ) fclose( fp )

その他テキスト中で使用された関数について sin() 三角関数の正弦を計算します

include ltmathhgt double sin(double radian) sinはラジアンを単位とする引数 radianの三角関数を計算します

37

strcpy() 文字列を他の文字列へコピーします

include ltstringhgt char strcpy(char string1const char string2) strcpyは引数 string2の指す文字列を null文字まで含めて引数 string1の指す領域にコピ

ーする strcpyは string1を返します

strcat() ある文字列を他の文字列に加えます

include ltstringhgt char strcat( char dest const char src ) 戻り値連結された文字列へのポインタを返します strcat() はsrc のコピーを dest の最後につけ加えます得られる文字列の長さは

strlen(dest)+strlen(src) になります

fabs() 絶対値の計算をします include ltmathhgt double fabs(double z) fabsは倍精度浮動小数の絶対値を計算して返しますつまりzgt=0であれば z をzlt0であ

れば-zを返します exp() 指数関数を計算します

include ltmathhgt double exp(double z) exp は引数zの指数関数つまりezを返すここではeは自然対数の底を表します対数関

数logの逆関数です

38

付 録 2 コンパイルの方法には大きく分けて第4章の実習で学んだようにデータファイルを作成してお

き ccg でコンパイルさせる方法と実行中に対話型でデータを入力していく方法があります ここでは対話型で実行を進めていく方法を紹介します ただしこの方法は計算(cpu)時間が10秒以内のものに限ります10秒を超える計算(cpu)時

間を要する場合はccg でコンパイルをするようにしてください 第4章実習の(2)(p16)までは同様です

コンパイル

コンピュータに処理を依頼します 60us1234boseicc cc rensyuc

所有するファイルの一覧を見てみます

60us1234boseicc ls -l larr 持っているファイルの一覧を見るコマンドです

-rw-r--r-- 1 60us1234 other 128 4月26日 15時14分 rensyuc -rwxr-xr-x 1 60us1234 other 361 4月26日 15時16分 aout

aout という実行形式のファイルが作成されています

実行

60us1234boseicc aout12 35[リターン] データを入力

1 200000 3500000 4200000 実行結果の出力

60us1234boseicc

注意

aout ファイルは印刷することができません実行結果を印刷する場合にはファイルに落とし てから出力するようにしましょう

60us1234boseicc aout gt kekka12 35[リターン] データを入力

60us1234boseicc more kekka 計算結果の確認 60us1234boseicc lpr kekka 計算結果の印刷

39

Page 40: n 第1章 章立ての部分は、書式(PC入門大見出し)を …第2章 数の表現 2-1 2進数 電子計算機の動作原理は0と1で表される2進数です。また、人間が日常生活で扱っている数

strcpy() 文字列を他の文字列へコピーします

include ltstringhgt char strcpy(char string1const char string2) strcpyは引数 string2の指す文字列を null文字まで含めて引数 string1の指す領域にコピ

ーする strcpyは string1を返します

strcat() ある文字列を他の文字列に加えます

include ltstringhgt char strcat( char dest const char src ) 戻り値連結された文字列へのポインタを返します strcat() はsrc のコピーを dest の最後につけ加えます得られる文字列の長さは

strlen(dest)+strlen(src) になります

fabs() 絶対値の計算をします include ltmathhgt double fabs(double z) fabsは倍精度浮動小数の絶対値を計算して返しますつまりzgt=0であれば z をzlt0であ

れば-zを返します exp() 指数関数を計算します

include ltmathhgt double exp(double z) exp は引数zの指数関数つまりezを返すここではeは自然対数の底を表します対数関

数logの逆関数です

38

付 録 2 コンパイルの方法には大きく分けて第4章の実習で学んだようにデータファイルを作成してお

き ccg でコンパイルさせる方法と実行中に対話型でデータを入力していく方法があります ここでは対話型で実行を進めていく方法を紹介します ただしこの方法は計算(cpu)時間が10秒以内のものに限ります10秒を超える計算(cpu)時

間を要する場合はccg でコンパイルをするようにしてください 第4章実習の(2)(p16)までは同様です

コンパイル

コンピュータに処理を依頼します 60us1234boseicc cc rensyuc

所有するファイルの一覧を見てみます

60us1234boseicc ls -l larr 持っているファイルの一覧を見るコマンドです

-rw-r--r-- 1 60us1234 other 128 4月26日 15時14分 rensyuc -rwxr-xr-x 1 60us1234 other 361 4月26日 15時16分 aout

aout という実行形式のファイルが作成されています

実行

60us1234boseicc aout12 35[リターン] データを入力

1 200000 3500000 4200000 実行結果の出力

60us1234boseicc

注意

aout ファイルは印刷することができません実行結果を印刷する場合にはファイルに落とし てから出力するようにしましょう

60us1234boseicc aout gt kekka12 35[リターン] データを入力

60us1234boseicc more kekka 計算結果の確認 60us1234boseicc lpr kekka 計算結果の印刷

39

Page 41: n 第1章 章立ての部分は、書式(PC入門大見出し)を …第2章 数の表現 2-1 2進数 電子計算機の動作原理は0と1で表される2進数です。また、人間が日常生活で扱っている数

付 録 2 コンパイルの方法には大きく分けて第4章の実習で学んだようにデータファイルを作成してお

き ccg でコンパイルさせる方法と実行中に対話型でデータを入力していく方法があります ここでは対話型で実行を進めていく方法を紹介します ただしこの方法は計算(cpu)時間が10秒以内のものに限ります10秒を超える計算(cpu)時

間を要する場合はccg でコンパイルをするようにしてください 第4章実習の(2)(p16)までは同様です

コンパイル

コンピュータに処理を依頼します 60us1234boseicc cc rensyuc

所有するファイルの一覧を見てみます

60us1234boseicc ls -l larr 持っているファイルの一覧を見るコマンドです

-rw-r--r-- 1 60us1234 other 128 4月26日 15時14分 rensyuc -rwxr-xr-x 1 60us1234 other 361 4月26日 15時16分 aout

aout という実行形式のファイルが作成されています

実行

60us1234boseicc aout12 35[リターン] データを入力

1 200000 3500000 4200000 実行結果の出力

60us1234boseicc

注意

aout ファイルは印刷することができません実行結果を印刷する場合にはファイルに落とし てから出力するようにしましょう

60us1234boseicc aout gt kekka12 35[リターン] データを入力

60us1234boseicc more kekka 計算結果の確認 60us1234boseicc lpr kekka 計算結果の印刷

39