C ⾔語の初歩
C ⾔語で学ぶ Fortran の初歩

兵庫県⽴⼤学 シミュレーション学研究科
⼤野1. コンパイラ
コンピュータに、何か仕事をさせたい。そのためには、コンピュータに指示をしなければならない。その指示のあつまりが、プログラムである。
では、何でプログラムを書けばよいのかュータは、日本

も

もフランス

も理

日本
できない。理たぶん 100010001111000 など。これは、おそらく常人

フランス

コンピ

できるのは機械

であり、

つねびと

には理

できない。

(一 人)が理 できる形でプログラムを書くのは不可 なのか
プログラミングを使えば可 である。ただし、人 が書いたプログラムを機械 に直す機(コンパイラ)が必 である。
人

プログラミングといっても、いろいろな種

Fortran 77, Fortran90、Java、etc。それぞれのラが必である(Fortran のコンパイラで、Cがある。たとえば、C/C++、
は、それぞれの用のコンパイで書かれたプログラムはコンパイル

できない)1。

2. プログラミング
プログラミングは人 が理 可 であるが、というくらいなので文法がある。
やフランス のように、文法を えないとプログラムが書けない。コンピュータはが利かないので、すこしでもうと、コンパイルできない。 会 は、少しくらい文法や単 をっても、アメリカ人やイギリス人は理 してくれる。
ここまでをまとめると、プログラミングの文法に従い、プログラム(ソースコー
ド2と呼ぶ)を書き、それをコンパイルするとコンピュータが実 できる実 ファイルができる。
コンピュータの基礎では、Cの基礎を学ぶ。C

の学

に最低

必

なもの

は、
z

テキストエディタ( Windows ならサクラエディタ、秀丸エディタ、MIFES、
TeraPad、Linux なら vi、emacs、nedit、gedit など)z

C コンパイラ

コンパイルが必 ないプログラミング(インタプリタと呼ばれる。コンパイラが必 なは、コンパイラと呼ばれる)も存在する。たとえば、Perl や昔の BASIC。これらのは、
実 時に機械 にされながら実 される。そのため、一 的には、コンパイラで書かれたものより い。Java は、その中 かもしれない。 味がある人は べてみよう。
1

2

テキストファイル

文字コードのみでされているである。テキストファイルとは、メモ帳などによって くことができるファイルである。Word の docx ファイルは文章であるがテキストフ
ァイルではない。

である。ここでは、Windows + Cygwin で Cを学ぶ。Cygwin とは、Windows 上で動作する Linux と えればよく、フリ”で入手可
ストールできる

家のパソコンにも無料でインである。また、C/C++コンパイラ、Fortran コンパイラ、テキストエ

ディタもインストールすることができる。

3. C g i でのソースコード入力、コンパイル、実実

室の PC で、Cygwin を動してみる。

スタートボタン→ すべてのプログラム→ Cygwin-X→Xwin server
で X サーバを 動

たぶん xterm→→ Cygwin-X→ Xterm

xterm の窓の中で
nedit␣&と入力すると、nedit というエディタが
ド

プログラム

を実

動する。&をつける意味は、Linux でコマン

すると、そのコマンドができない。しかし、コマンドの最後に&をつけて実グラウンドで実すると、そのコマンドはバックされるので、すぐに次のコマンドを実

バックグラウンドで実を了するまで、次のコマンドが実することで、nedit をできる。nedit に&をつけて了することなく、つまりソースコード

しつつ、そのソースコードをコンパイルをすることができる。

nedit で次のプログラムを入力してみよう。

#i c de␣< di .h>
i ␣ ai (i ␣a gc,␣cha ␣*a g [ ])i f("He
e

,␣

d

を

す

");

␣0;

ただし、
改

␣:スペースを入力がすエディタの中では、¥はバックスラッシュになる

了したら、hello.c として保存する(File → Save As)。

hello.c をいよいよコンパイルする。cygwin には、gcc というフリーの C コンパイラがインストールされているので、それを使用する。
xterm で、
gcc␣-o␣hello␣hello.c⏎とすると、hello.c がコンパイルされ、hello.exe という実
これを実
./he

ファイルが出来る。

するには

.e e⏎

とする。カレントディレクトリをす ./ をつけなければいけないことに注意。普Linux では、hello.exe ではなく、hello という実のファイルができる。

単に
gcc␣he.c⏎とすると、a.exe(普 の Linux では a.out)という実4. Cファイルができる。

のプログラムの基 と き の#i c de␣< di .h>⏎i ␣ ai (i ␣a gc, cha ␣*a g [])⏎⏎i f("He ,d ");⏎e␣0;⏎
hello c⏎main(){….}を main 数と呼ぶ。Cや C++
では、mainって実 し、main 数が 了したら、プログラムが 了する。

数を上から下に向か

書き方の注意点としては、大文字と小文字を区別し、半文字で入力すること。全

文字は使わないこと。

文の最後に、「;」 (セミコロン)を入れること。
Python と
は、
i

ai (i

い改

やスペースは、比a gc,

的由にできる。例えば先ほどのメイン

cha *a g [ ])i f( heと書いても文法的に

,

d

);

いではない。

eでも、0;にくいので、やめよう

数

ただし、
i

ai (i

句の

中での改

a gc, cha *a g [ ])i f( hedやスペースはだめ。ダメな例

); e

,

0;

1.

問

hello.c について、下 を実
1. 「Hello, World」 の

せよ。

分を

々変えて、コンパイル・実

してみよう。

2. printf をもっと入れてみよう。
3. Hello, world¥n の¥n は、改を

printf("…")が、" "で囲まれた分をす。¥n を消して、コンパイル・実
示する機う。printf のような一つのまとまった機いう

数を命令と呼ぶ

標準で用意されている。

では数と呼ぶ。(C でもある)。printf 以外にも、さまざまな機

数名、"hello, world¥n"が引数である。mainがを持つことが容易に想像できると思をもつものを C

数の呼び出し方は、

してみよう

を持った

数が、

数名(引数); printf の例では、printf
数以外にも

分で

数を作成することもできる
main
どこで宣

数以外の

数は、使用する前に宣されているのか

stdio.h の中である。stdio.h の中で printf の宣れており(printf 以外にも数多くのースコードのをしなければならない。では、 printf は、

数の宣

が書か

が書かれている)、#include <stdio.h>をソに書くことで、ソースコード内で printf が使用可になる (stdio.h のようなファイルをヘッダファイルと呼ぶ)。
stdio.h の他にも、stdlib.h や math.h などのヘッダファイルがあり、それぞれ多くの数の宣が書かれている。Cする場合、その5. 変数が宣で標準で用意されている数をプログラムで使用されているヘッダファイルをインクルードする必

がある。

とデータ型

変数とは、コンピュータに、何か 憶させたい時に使う 憶の箱。いろいろなデータ型があり、 憶させるデータの種 によって、使い分けなければならない。例えば、
char 型 1 バイト

文字や文字列
列使用時 を 憶させることができる。整数 -128 127 を 憶させることもできる。

int 型 4 バイト

整数を 憶させることができる。2009 とか 558000 とか。小数点がつく数値は 憶できない。

float 型(4 バイト、単精度)
double 型
度
1
2
3
4
5
6
7
8
9
10

実 数 を 憶 さ せ る こ と が で き る 。 5.5 と か
8 バ イ ト 、 倍 精 3.14159 など。float 型は 6 桁くらい、double
型は、15 桁くらいまで 憶できる。

#i c de < di .h>⏎⏎iai (i a gc, cha *a g [ ])⏎⏎i a;⏎d b e b;⏎a = 1; b = 3.14159;⏎
i f("a = %d, b = %f ", a, b);⏎
e
0;⏎
var c
⏎

5,6

目の i

aや d

b e b は、変数の宣 であり、ある3。a, b は、変数の名前であり、宣

数の上のほうでしておく必

したのち、型にあったデータをとができる。たとえば、a には整数、b には実数を

が

憶させるこ

憶させるとこができる。

変数のネーミングはアルファベット・数字・アンダーバー( _ )等を使い由にできる。単純な a や b などより、分かりやすい、意味のある名前にしたほうが、プログラ
ムのミスを減らせる。
例

db e PI = 3.14159; /*ただし、数字が先例

d、円周率 */に来ることはされない。

b e 10g;

つぎに、7目の a=1; や b=3.14159;であるが、これは の右にある数字が、a やb の中にセットされる。a = 1 は、
「a が 1 に等しい」という意味ではなく、「a に 1 を代入する」という意味。
8i f では、a と b の中目の型は%f で示させている。i

型は%d、 db e 型や f a

示できる。

i f("a = %d, b = %f

3を", a, b);

正確には、ブロックの上のほうで宣 する。ブロックについては れないが、 味のある人は べ

ること。

2

問

a 1.c につき、下

を実

せよ。

1. a, b にいろいろな数値を代入してみよう
2. a = 3.14159;
3. b = 5; e c
f a と d.

b e の精度のに代入してどのようないにも気を付けよう。次の例は、同じ数字を f a と dいが出るか確するプログラムである。

#i c de < di .h>
i

ai (i

a gc, cha *a g [ ])db e id = 3.14159265358979;

f a

if = 3.14159265358979;

i f(" id = %.14f
e

0;

実

果

if = %.14f", id, if);$ ./a.e e
id = 3.14159265358979
if = 3.14159274101257
f a 型の精度では、上の π をすべて憶できていないことがわかる。

6.
算用の

号

+

し算
引き算

*

掛け算。×の代わり/割り算。÷の代わり%余り。5%4 を()括弧。何算すると答えは 1.。整数のみの算のみに有効。

になっても( )を使い、中括弧{ }は使用しない。

be3 calc1.c の 5

問

目の式の右

をいろいろ変えて実

に

算して

みる。
1. a = 5%2+5;
2. a = (1+(2+4)*3)*2;
3. a = 5/2;
1

#i c de < di .h>

2

i

ai (i

a gc, cha *a g [])

3
4

i a;
a = 5*2+1;
i f( a=%d
e
0;

5
6
7

,a);

8

calc1.c4

問

calc2.c の 5目の式の右をいろいろ変えて実に算してみる。

1. a = 5%2+5;
2. a = 5.0/2.0;
3. a = 5/2;
etc….
1#i c de < di .h>

2

i

ai (i

a gc, cha *a g [])

3
4
5
6
7

d b e a;a = 5.0*2.2+1.5;
i f( a=%f ,a);e
0;

8calc2.c

2 番と 3 番の 果の いに注意せよ。整数のみのが出てくる 算はしてくれない。
また、整数、実数などのれる
例 1算の場合、割り算をしても小数点算が混在する場合は、大きいほうに変換されたのちに

5*2.0 → 5.0*2.0 (整数 5 が実数 5.0 に変換される)

算さ

例 2

5*2+1.5 → 10+1.5 → 10.0+1.5 →11.5 明示的に型変換することもできる

例 (double)5→5.0, (int)5.3→5
実数(5.0 など)は、基本的に double 型として扱われる。float 型として扱ってほしいときは、5.0f または(float)5.0 などとする。
例 float a; a=3.14159 → 3.14159f → a = 3.14159f
Fortran では、5.0 と書いたら、単精度の 5.0 とみなされるプログラム作成段

では、

算

果の

示がおかしいときがある。次の例をてみる、#i c de < di .h>iai (i a gc, cha *a g [])f a , , ;= 1.0; = 0.0;
= / ;i f("%f ", );e0;

1.0 を 0.0 で割った 果を、n に代入している。これ printf で示するとどうなるか$ ./a.exe
inf
もう一つのサンプル。
#i c de < di .h>#i c de < a h.h>i
ai (i a gc, cha *a g [])d b e a, b;
b=-1.0;a=(b);i f("%f ", a);
e
0;

sqrt

数は、平方根を求める数。-1.0 の平方根を求めようとすると$ ./a.exenaninf (無大)や nan(not a number)というと。ちなみに 0.0/0.0 でも nan がでる。

示が出たら、上のようなバグを疑うこ次に、文字変数のサンプルプログラムを示す。
1#i c de␣ < di .h>⏎⏎i ␣ ai (i a gc, cha *a g []) ⏎cha ␣a;⏎a = 'A';⏎i f("a = %c(a cii␣c de = %d) ", a, a);⏎e
␣0;⏎var2.c
⏎

2
3
4
5
6
7
8

5

目の、文字の代入式に注意。シングルクォーテーションで、文字を囲む。また、変数 a は、実は数字(-128

127)を憶している。

5

問

var2.c の 5

目の右 をいろいろ変えてみる。

1. a = 65;
2. a = ‘B‘;
3. a = ‘a‘ + 1;
etc
半 文字には、ascii コード( 番号のようなもの)がつけられており、char 型は、その番号を 憶しているに ぎない。 (「 番号 1 のすごい奴」を べてみよう。)
ここで、printf の使い方について、少ししく%c, %d, %f で、1 文字、整数、実数を

示する

明する。

%2d や%10.2f などの指定も可%2d は、整数

示のため、あらかじめ 2 桁用意する。たとえば、%2d で 1 を示すると ␣1 となる。
%10.2f は、実数を 10 桁
する(整数

小数点含む

で

示そのうち小数点以下を 2 桁

分が 7 桁となる)。%10.5f とすると、小数点以下が 5 桁、整数

分が 4 桁。
%e で指数形式で実数を示することも可

0.0543: %f の場合 0.0543, %e の場合 5.43E-2

7.

2

次のプログラムの果はどうなるだろうか示

1 #i c de␣< di .h>⏎2 ⏎3 i ␣ ai (i ␣a gc, cha ␣*a g [ ])⏎4⏎
5 d b e␣a = 1.0;⏎
6 d b e␣b;⏎
7 a+1.0;⏎8i f( a=%f\ ,a); ⏎9 b=a+5.0;⏎
10
i f("a=%f, b=%f ",a,b);⏎
11 e
␣0;⏎
12 ⏎

実

果は、 a=1.000000

a=1.000000,b=6.000000となる。9 目で b=a+5.0 という式は、a に 5.0 した数値を b に代入するという意
味で、変数 a 体に 5.0 がたされるわけではない。7 目の a+1.0 という式も同じ。
1 #i c de␣< di .h>2
3 i ␣ ai (ia gc, cha *a g [ ])

4
5

d

6

b=a+5.0;
i f( a=%f, b=%f78b e␣b;",a,b);

a=a+2.0;
i f( a=%f, b=%f910b e␣a = 1.0; de",a,b);

␣0;

11
実

果は、

a=1.000000,b=6.000000
a=3.000000,b=6.000000
7目で b=a+5.0 を実したあと、a の値を変化させても、b の値は変化しない。

#b=a+5.0 という式で、b を定しているわけではない。

#a=a+2.0 は、a に 2.0 を した数値を改めて a に代入している。この手の式はよく使う。a+2 と a が等しいという意味ではない。
算号の省略形
a=a+b → a += b
a=a-b → a -= b

インクリメント、デクリメント演算子
i++, ++i → i=i+1
i--, --i → i=i-1
厳密には、++や--が変数の前にくるか後ろにくるかで、動作が変わるので注意。単独で i++や ++i とする場合は 果は同じ。

8. キーボードからの入力
まず、次のプログラムをよう#i c de < di .h>⏎⏎i ␣ ai (i a gc, cha *a g [])⏎c
␣d b e␣PI = 3.14159265358979;⏎
d b e␣ adi = 5.1;⏎
d b e␣a ea, ci c ;⏎ci c
= 2.0*PI* adi ;⏎a ea = PI* adi * adi ;⏎i f( E h = %f, Me e i=%f ",ci c ,a ea);⏎
e
␣0;⏎
⏎

circ area c

これは、円周と円の積を求めるプログラムである。しかし、異なる半径の円の積・円周を求めるとき、radius を変更後、再コンパイルが必とはえない。プログラム実

scanf

数(stdio.h をインクルード)を使うとよい。下をせる。(const 修で、実用的なプログラム

後に、半径を入力するようにしたい。このような時、に、scanf のサンプルプログラム

子をつけた変数は、内容を変更できない。変更しようとすると、コンパイル時にエラーまたは告が出る)#i c de␣< di .h>
i ␣ ai (i ␣a gc, cha ␣*a g [])i ␣i;
f a ␣f;d b e␣d;ca f("%d",&i);
変数の前に&がつくことに注意
ca f("%f",&f);double 型は%f ではなく%lf(エルエフ)
ca f("% f",&d);i f("i=%d␣f=%f␣d=%f ",i,f,d);
e
␣0;

実

すると

$ ./a.exe⏎
5⏎
キーボードからの入力

1.0⏎
2.0⏎

i=5 f=1.000000 d=2.000000
scanf("%d",&i); scanf("%f",&f);scanf("%lf",&d); を
scanf("%d%f%lf",%i,&f,&d);と 1

で書くことも可。

少なくともプログラムが完成するまでは、scanf でとりこんだ数値を printf でようにすること。
問6

circ_area.c に

9.

件分

示する

して、半径(radius)の値をキーボードから入力するように修正せよ。

1(if

)

「もし(if)、天気が晴れならとができる。

り、なら映画」のように、条件により処理を変えるこ

基本形
if(条件式){ 処理}

else { 処理 B }条件式が真ならば A を実、偽ならば B を実する。

else 以下は省略可。 → if(条件式){ 処理

条件式で使える比演算子は、下}のとおりである。

意味

意味

A> B

A は B より大きい

A <= B

A は B 以下 (≦)

A >= B

A は B 以上

A == BA と B は等しい(※)

A< B

A は B より小さい

A != BA と B は異なる

※A=B と書くと、B を≧≠に代入という意味になるので注意

if(a+2 > 100)のように、if のかっこの中に、算式を入れてもよい。

if の使用例
if(a>b) a が b より大きいならばif(a%2==0) a が偶数ならば。(2 で割ると余りがゼロ)
if(a%2==1) a が奇数ならば。(2 で割ると余りが 1)
7

問

下 のプログラムを入力し、いろいろな整数を入力して、動作を確式やメッセージを変えて実 せよ。

せよ。また、条件#i c de␣< di .h>
i ␣ ai (i ␣a gc, cha ␣*a g [ ])i ␣i;i f("iabe : ");

ca f("%d", &i);
if(i > 5)i f("I i bigge ha 5

");

e e
i f("I iebigge ha 5

");

0;

if 文は、分岐を多数書くこともできる。
「もし(if)晴れたらり、晴れなかった場合、もし曇りならハイキング、どちらでもない場合、家で寝てる」のように、2 分岐以上も可

である

if(

基本形
if(条件式 1){ 処理 A){

} else if (){} else if (条件式 2) { 処理 B
} else { 処理 C

} else {}else if をたくさん入れることもできる。

}

多分岐のサンプルプログラム
実#include <stdio.h>

例$ ./a.exe

int main(int argc, char *argv[])

input a number(a): 5{

input a number(b): 5

int a, b;a is equal to b

printf("input a number(a): ");$ ./a.exe

scanf("%d", &a);

input a number(a): 6

printf("input a number(b): ");input a number(b): 3

scanf("%d", &b);

a is bigger than bif(a > b){
printf("a is bigger than b¥n");} else if(a == b){
printf("a is equal to b¥n");} else {printf("a is smaller than b¥n");}下}
comp_int.c

return 0;のような条件をえる

1. もし晴れたら、あるいは
2. もし晴れて、かつったら、…..

ひとつなかったら、…

3. もし晴れなかったら
AND や OR を使うと、簡単に条件式で使用できる

理演算子

現できそうである。

A || BA あるいは B (A か B どちらか一方で ORも正しければ)A && BA かつ B(A と B 両方正しければ)

AND(&や|ではなく&&, ||なことに注意4)
!A

否定を

これらの

理演算子を使うと、先す(A が正しくなければ)

NOT

した条件式は、次のように現できる。

1. if(晴れ || 曇り){…………..}
2. if (晴れ &&ひとつない){……………}

3. if(!晴れ){……………..} また、if(a>b && b<c && a>c ..) のように 3 個以上並べること
もできる。
問

8下

プログラムを実すると、どのメッセージが示されるか#i c de < di .h>iai (i a gc, cha *a g [])i a, b, c;
a = 10; b = 8; c = 4;
if(a>b b < c) i f("N .1 ie ");if(a>b && b < c) i f("N .2 ie ");if(!(a>b)) i f("N .3 i
e ");
e
0;

条件式を()で囲むこともできる。
Se e

算の時のように、優先される 。

1

数字の 0 は偽とみなされる。その他の数字は真とみなされる。
サンプルプログラム

4&や|と書くと、ビット演算子になってしまうので注意すること。コンパイルは る可 性がある。

#i c de < di .h>実

i-10:trueai (ia gc, cha *a g [ ])果-9:trueii;….

f (i = -10;i<11;i++)if(i)i f("%d:e eee-1:true",i);i f("%d:fa e

0:false",i);1:true….

0;10:truefor は、のちほど登場する。
S

e e

2

ある変数の範囲が ある区 の範囲に入っているか、判定する場合を
数 r が、0.1 から 0.2 に入っているかどうか確かめたいとき、える。例えば、変if(0.1 < r <0.2) { …. }と書きたくなると思うが、Python とちがい、これはいである。

#include <stdio.h>
int main(int argc, char *argv[ ]){double r=0.0;
if( 0.1 < r < 0.2){
printf("0.1 < r < 0.2 is true¥n");}return 0;}
上のプログラムを実すると$ ./a.exe
0.1 < r < 0.2 is trueとなる。これは、まず 0.1 < r がき換わり、次に 0 < 0.2 が価され、r=0.0 なので、偽である。この価される。これは真なので、printf が実

果は、0 とされてしま果になる。コンパイルはされるが、作成した人の意図

りには動かない。正しくは、

理演算子を使いif(0.1 < r && r < 0.2) { …}
と書く。
S

e e

3

if(i<5) {printf("i<5¥n");} を
if(i<5) printf("i<5¥n");と書くのはいではない。1 文しかない時は、中括弧は書かなくてもよい。しかし、

if(i<5) {printf("I is less");
printf("than 5¥n");}をif(i<5) printf("I is less ");printf("than 5¥n");と書くのはい。なぜか えてみよう。この 則は、後で出てくる for や while など
でも 用される。初めのうちは、めんどうくさがらずに中括弧を書いていれば、
いは
ない。

10.

件分

2(

i ch)

if の他に、switch 文で、多分岐させることができる。基本形は、
switch(式){⏎case␣定数式 1:⏎
処理1
break; ⏎case␣定数式 2:⏎
処理2
break; ⏎..
default: ⏎処理D⏎
break;⏎}⏎：
switch(a){⏎case␣1:⏎i f( a=1
break; ⏎case␣2:⏎i f( a=2
break; ⏎..
default:⏎i f( defa
break;⏎
}⏎

);⏎

);⏎

)⏎

式が定数式に等しいか判断して分岐する。式が定数式 1 と等しければ処理 1、定数式 2に等しければ処理 2, ,,,, どれとも等しくない時は、処理を実する、ただし、式および定数式は、整数や文字でなければならない(if 文では、浮動小数点なども使用できる)問
下9

プログラムの if 文を switch で書き換えよ。
#i c de␣< di .h>⏎⏎i ␣ ai (i ␣a gc, cha ␣*a g [ ])⏎⏎i ch ice;⏎⏎
i f("Iabe (1-3): ");⏎
ca f("%d",&ch ice);⏎⏎if(ch ice == 1) ⏎i f(" e ");⏎e e if(ch ice == 2) ⏎
i f("
");⏎
e e if(ch ice == 3) ⏎i f(" h ee ");⏎e e ⏎i f("1,2 3 i e i ed ");⏎
⏎
⏎
e
␣0;⏎
⏎

S

e e

s itchc

1switch で break がないとどうなるのだろうか#include <stdio.h>
int main(int argc, char *argv[]){
int choice;for(choice=1;choice<5;choice++){switch(choice){case 1:

次のプログラムでしてみよう。

printf("one¥n");case 2:
printf("two¥n");case 3:printf("three¥n");default:
printf("default¥n");}}return 0;}
実

果$ ./a.exe one
two
three
default two
three
default threedefault default※break がないと、

11.

り

し実

択されたものから下がすべて実されることが分かる。

1(f )シミュレ”ションでは、何らかの処理を り し実 することが必ず必 になる。
hello.c を える。Hello World と 10 回 示させるには、どうしたらよいだろうかもっとも単純な答えは、printf を 10 個並べることであろう。しかし、 1 万回 示させた
いときは、どうしたらよいだろうか
上の方法だと、1 万
printf をコピーアンドペー
ストすることになり、まったくばかげている。このような時は、for を使うとよい。
基本形
for(初期処理;
り

条件; 処理){したい内容}
1. 整数型の変数 i を用意
2. for の初期処理で、i に 0 を代入

3.

条件 (i<10) が成立していれば、{ }で囲んだら分、つまり printf を実わる。

4. for の下の}まできたら、処理 i++ を実 。3 に戻る具体的には、下のように書く

int i; for(i=0;i<10;i++){printf( Hello, World¥n );}Hello,World を 10 回 示するプログラムは、下のようになる。

#i c de < di .h>
i

ai (i

a gc, cha *a g [])i i;
f (i=0;i<10;i++)i f( i=%d:He , W
e

d

,i);

0;
hello

問
1. 100 回

c10示するプログラムに直してみよう

2. if を使用し、i が偶数のときだけ printf を実するようにしてみよう

以下に for 文の例を書く
for(i=0;i<10;i=i+2){…….
}
i は 0 から始まり、2 ずつり上がる。i が 10 以上になったら、 了

for(i=10; i>0; i--){…….
}i は 10 から始まり、1 ずつ小さくなる。i が 0 になったら
for(i=0; i<10; i++){ ….
for(k=0; k<3; k++){ …….
}….
}、 i≧10 な了

上のように for 文は、入れ子にすることができる
問

11

かけ算九九のを示するプログラムを作成せよ

for 文の

り

しを

中で

ヒント

for を入れ子にする

了させたり、特定の回だけ処理を回することもできる。

break

z

¾ ループから抜け出る
continuez¾ ループのその回の処理(continue より下にある分)をスキップする break や

continue は、if と一 に用いられることが多い。break と continue の働きを図示す
ると
for(i=0;i<10;i++){
処理 1;
if(条件) continue;
処理 2;}
条件が成立すると、continue より下(処理 2)をわない

for(i=0;i<10;i++){処理;
if(条件) break;}
条件成立でループ了

break, continue のサンプルプログラムとその実

果は、

#i c de < di .h>
i

ai (i

i

a gc, cha *a g [])果$ ./a.exei;i=0

f (i=0;i<10;i++)i=1

if(i==5) b ea ;i f("i = %de実", i);

i=2
i=3
i=4

0;

#i c de < di .h>
i

ai (i
i

a gc, cha *a g [])果$ ./a.exei;i=5f (i=0;i<10;i++)if(i<5) cii f("i = %d
e

実

i=6

e;
", i);

i=7
i=8
i=9

0;

Ad a cedfor(初期処理;
り

条件; 処理){したい内容}
1. 初期条件や2.

条件、処理は、「,」(カンマ)で区切ることで条件のところで、if 文の時に勉強した
グラム

数書くことができる

理演算子なども使用できるサンプルプロ

#i c de < di .h>
i

ai (i
i

a gc, cha *a g [ ])i, j;f (i=0, j=1; i < 10 && j < 10; i++,j++)i f("i=%d j=%de

12.

",i,j);0;り し実

2( hi e, dhi e)while や do-while 文を使用すると、ともできる。

条件のみを指定して、

り

し実

させるこ

基本形は、
while (

条件)

処理例
int i=0;
while (i<10)printf("i=%d:hello, world¥n",i)i++;i++がないとループから抜けられない。なぜかことができる。

えよう。for 文は while 文で書き直す

for (A; B; C){D;A
while (B){D;C}

do - while 文は、while 文の変形版で、条件をあとから文と少しう。

べるという点が、 whilehi e (A)
B;
Aを

べる

d
B;
hi e (A);
B を実

B を実

Aを

Aを

B を実

べる

べる

…..

…..
#include <stdio.h>#include <stdio.h>

int main(int argc, char *argv[])

int main(int argc, char*argv[ ]){{int i=10;

int i=10;

while(i<10)

do {

{

printf("hello¥n");printf("hello¥n");} while (i<10);}return 0;

return 0;

}

}

実
実

果

果

$ ./a.exe$ ./a.exe

Hello

12 次の動作をするプログラムを作成せよ

問

1. 摂氏温度(temperature in Celsius)をキーボードから入力すると、その温度を度(temperature in Fahrenheit)に変換して示する。

2. 1. を摂氏 300 度を上回る温度が入力されるまで

り

3.

示しない。

対

度を下回る温度が入力された場合、何もす。

氏温度(Fahrenheit) = 1.8×摂氏温度(Celsius) + 32.0
対度 -273.15℃

Hint
while, if, break, scanf

氏温13. ファイル入出力
シミュレーションでは、実りする。

時にデータをみんだり、果をファイルに書き出した

リダイレクト
今まで作成したプログラムは、
標準出力(ディスプレイ)に何か出力し、標準入力(キーボード)から何か入力した。(printf:標準出力, scanf:標準入力)
OS のリダイレクトとう機

で、簡単にファイルへ出力、ファイルから入力に切り替えることができる。Linux でも、Windows の DOS プロンプトでも使える。
例$ ./a.exe > out.txt
出力を out.txt にする ディスプレイに 示せず、out.txt というファイルに出力する 。out.txt と うファイルが存在しない場合は、新たに作成される。すでに out.txt が存在する場合は、上書きされる。
$ ./a.exe < in.txt
入力を in.txt にする(キーボードからでなく、in.txt とする)うファイルから入力$ ./a.exe < in.txt > out.txt
次のプログラムと radius.txt というファイルを例に、リダイレクトの実す。
#include␣<stdio.h>⏎⏎int␣main(int argc, char *argv[]){⏎
const␣double␣PI = 3.14159265358979;⏎
double␣radius, area;⏎ca f( % f , &radius); ⏎i f( adi = %f , adi ); ⏎area = PI*radius*radius;⏎
i f( Me e i=%f , a ea);⏎
return␣0;⏎
}⏎
5.0⏎

adi

.

果を示

実

例 1

$./a.exe < radius.txt
radius = 5.000000
Menseki=78.539816
実

例 2$ ./a.exe > result.txt
2.0$ cat␣result.txt 5
radius = 2.000000
Menseki=12.566371
実

例 3$ ./a.exe < radius.txt > result.txt$ cat␣result.txt
radius = 5.000000
Menseki=78.539816
実

例 4$ ls␣-l > lslog.txt$ cat␣lslog.txt⏎
合3-rw-r--r-- 1 ohno None 0 Jun 2 15:33 lslog.txt-rw-r--r-- 1 ohno None 199 Apr 15 13:21 prac1.c-rw-r--r-- 1 ohno None 344 Apr 15 13:28 prac2.c-rw-r--r-- 1 ohno None 705 Apr 15 16:30 prac3.c
リダイレクトで、出力を既に存在しているファイルにすると、上書きされるが、「>>」を使ってリダイレクトすると、ファイルの末尾に 果が 加される実 例$ ls␣-l > lslog.txt⏎$ ls␣-l >> lslog.txt⏎$ cat␣lslog.txt ⏎合3-rw-r--r-- 1 ohno None 0 Jun 2 15:39 lslog.txt-rw-r--r-- 1 ohno None 199 Apr 15 13:21 prac1.c-rw-r--r-- 1 ohno None 344 Apr 15 13:28 prac2.c5cat コマンドで、テキストファイルの内容を 示できる。

-rw-r--r-- 1 ohno None 705 Apr 15 16:30 prac3.c
合4-rw-r--r-- 1 ohno None 203 Jun 2 15:39 lslog.txt-rw-r--r-- 1 ohno None 199 Apr 15 13:21 prac1.c-rw-r--r-- 1 ohno None 344 Apr 15 13:28 prac2.c-rw-r--r-- 1 ohno None 705 Apr 15 16:30 prac3.c
加書きみにしたため、2 度の ls の 果がされている。

Ad a ced>&により、標準エラー出力もリダイレクトできる。
実

例

$ ls⏎
lslog.txt prac1.c prac2.c prac3.c$ ls␣ohno⏎
ls: ohno にアクセスできません: No such file or directory ←エラーを こした$ ls␣ohno > error.txt⏎
ls: ohno にアクセスできません: No such file or directory ←標準エラー出力をリダイレクトしても、画 に 示される

$ ls␣ohno >& error.txt$ cat␣error.txt
ls: ohno にアクセスできません: No such file or directory(>&で標準エラー出力もリダイレクトできることを確できた)

ファイル入出力Cには、ファイルを指定して、データをる。

みんだり、書き出したりする方法があファイル指定の決まり文句は、
1. FILE *fp;
2. fp = fopen( data.txt , w );3. fclose(fp);
1.ファイルをくための変数の宣2. data.txt というファイルをオープンし、変数 fp に付ける。ファイル名のところには、ディレクトリもかける。例:fopen( ../data/data.txt , w )。 w の意味するところは、書き み(write)であるが、w の他に a や r の場合もある。
w : 書きみ(write)ファイルが存在しない場合
ファイルが存在する場合
a :

加書き

r :

み出し(read)

生成される
上書きされるみ(append)

3. ファイルをじるファイルがオープンされていると、printf, scanf の仲 の fprintf や facanf で、オープンされているファイルからデータを書き出したり、 み むことができる。fprintf、
fscanf の使い方は、printf, scanf とほぼ同じ。
次のプログラムを1てみよう。

#i c de < di .h>

2
3

i

ai (i

a gc, cha *a g [])4

FILE␣*f ; i i;f = f e ( he . ,);f (i=0;i<10;i++)if(i%2==0) f i f(f , i=%d:He

5
6
7
8

fc
e

7

d

, i);

e(f );
0;

目で、he

.

するように、he

付ける。8

目で he

う。f でファイルを区別している。 i f で画

に文字を

示

みの例を示したプログラムをてを書き出し專用にオープンし、f にに対して、書き出しを
みよう。

,W

.

に文字を出力する次に、み.

1 #i c de < di .h>
2
3 i

ai (i

a gc, cha *a g [])4
5

FILE *f ;

6

i

i;

7

d

b e f;

8 f =f e ("da a.
9 f (i=0;i<5;i++)", " ");

f ca f(f , "% f", &f);

10

i f("%d: %f

11", f);

1213

fc

e(f );

14

e

0;

15
8 目で data.txt を み出し用にオープンし、fp に付ける。data.txt から、実数の数値を み む。scanf でキーボードから数値を入力するように、data.txt から数値を入力する
上の例では、ファイルは 1 つしかオープンしていないが、数のファイルを同時にオープンすることもできる。その場合、FILE 型の変数でファイルを区別する。
問

13

次の動作をするプログラムを作成せよ
1. 摂氏温度(temperature in Celsius)を cel.txt からみ

み、その温度を(temperature in Fahrenheit)に変換して fah.txt に書き出す。
2. 1. を 300 度を上回る温度が入力されるまで
cel.txt の内容は、
50.5⏎
23.4⏎
65.1⏎
23.1⏎
350.0⏎

り

す。

氏温度

S

e e

1

fprintf, fscanf のファイルポインタ(FILE *fp の fp)の代わりに、以下も使うことができる
stdout標準出力(ディスプレイ)
stdin
標準入力(キーボード)
stderr
標準エラー出力(ディスプレイ)#i c de < di .h>
i

ai (i

a gc,cha *a g [])d b e c,f;
f i f( d , "E e a e e a e (Ce i ): ");f ca f( di , "% f", &c);
f=1.8*c+32.0;
f i f( d , "%f (Ce i ) i %f (Fah e hei ) ",c,f);e
0;
このプログラムは、キーボードから数値度に換算した数値を 示する。
S

e e

摂氏温度

を入力し、ディスプレイに2

fopen は、ファイルオープンに失敗すると、NULL を
次のようにするとよい。
if((fp=fopen("data.txt", "r"))==NULL){
fprintf(stderr, "file open error¥n");exit(1);}….
fclose(fp);
これは、次と同じ意味である。
fp=fopen("data.txt", "r");if(fp==NULL){
fprintf(stderr, "file open error¥n");exit(1);}

氏温すので、ファイルオープンは、

もし、ファイルオープンに失敗すると、fp に NULL が代入される。そこで、if 文により fp が NULL かどうか

べて、もし NULL(失敗した)であれば、「file open error」というメッセージを標準エラー出力に出力して、プログラムをばれると、そこでプログラムが了する。exit

了する(exit数が呼数を使うには、stdlib.h をインクルー

ドすることが必 )14.

列

int i や double cel と宣したのでは、変数は一つしか用意されない。同じ変数を用意したい場合がある。たとえば、クラスの生徒

40 人のテストの点数を数憶する

変数がほしい。
int score0, score1, ….. ,score39;
学年全体(360 人)ならこの方法で宣するのは効率的である。

int score[40];こう書くと、一気に int 型の変数が 40 個できる。int score[360]とすれば、一気に360 個確保できる。
列
int a[5]を えてみる。このような宣 をすると、指定したデータ型 この場合 intの変数が、[ ]の中の数字で指定した数(この場合 5 個)だけ、用意される。また、メモリの中ではしている。イメージは、
a[0]

a[1]

a[2]

a[3]

a[4]

使い方
a[0] a[4] を普 の int 型の変数として、使うことができる。(1 からでなく 0 からということに注意) たとえば、
a[0] = 80; a[4] = 50;
printf("a[1]=%d¥n",a[1]);普の変数と同様に、宣と同時に値を代入することもできる。

int a[5] = {1, 2, 3, 4, 5};double b[3] ={1.2, 4.55, 6.332};など、中かっこ { } を使い、カンマ , で区切る。
例
int a[5] = {1,2,3,4,5};
double b[3] ={1.2, 4.55, 6.332};

printf("a[2]=%d, b[1]=%f¥n", a[2], b[1]);→ a[2]=3, b[1]=4.550000
文字列

代入したい文字列の数+1 以上のサイズにする
TEST とう 4 文字の文字列を char 型の分のサイズの列を宣し、TEST に列に代入したい時は、4 文字+1 の 5 文字

き、¥0 を代入する例

char s[5]={'T', 'E', 'S', 'T', '¥0'}※ ¥0 は、文字列の

端を

す文字

列のみ、特別な代入の仕方がある

char s[5] = "TEST"( 動的に¥0 が最後に付加される)
また、
strcpy という数

string.h のインクルードが必を使うと、容易に文字列の代入ができる( 端に¥0 も代入される) 例
char s[5];strcpy(s, "TEST");※s[0] = 'T'; s[1]= 'E'; s[2]= 'S'; s[3]= 'T'; s[4]= '¥0';と同じ
fprintf, printf, scanf, fscanf などを使い文字列を示したりするときは、%s を使う(1 文字の時は%c)
char carray[64];scanf("%s", carray)
printf("%s¥n", carray);scanf の 2 つ目の引数に、&がついていないことに注意。変数の前に&をつけると、変数のメモリ中のアドレスをあらわす。 列の名前は、 列の先素のアドレスを すので、&をつける必 はない。つけたい場合は、&carray[0]とする
問
下14の動作をするプログラムを作成せよ

ファイル score.txt から、テストの点数(整数型)を 10 人分(学生番号 1
でいる)

みみ平均点(浮動小数点型)をいる学生番号を pass.txt に書き出す。
score.txt の中

10 の

に並ん

算し、平均点と平均点以上の点数を取って

75⏎
45⏎
63⏎
55⏎
43⏎
98⏎
87⏎
75⏎
68⏎
78⏎

15. 多

元 列

2 次元

列 int a[4][5]を宣すると、下のようなイメージで、変数が用意される

a[0][0]a[0][1]a[0][2]a[0][3]a[0][4]a[1][0]a[1][1]a[1][2]a[1][3]a[1][4]a[2][0]a[2][1]a[2][2]a[2][3]a[2][4]a[3][0]a[3][1]a[3][2]a[3][3]a[3][4]

使い方は、1 次元のときと同じ。例次元以上の 列も作れる
多次元

列も、宣

a[0][0]=1; m=a[2][1]。3 次元、4 次元列など、3と同時に値を代入するこができる。例

int a[2][3] = { 1, 2, 3, 4, 5, 6}; ⇒ a[0][0] = 1; a[0][1] = 2; a[0][2] = 3; a[1][0] = 4;a[1][1] = 5; a[1][2] = 6; //後ろの添え字が優先される{ }を入れ子にするとわかりやすい
int a[2][3] = { {1, 2, 3}, {4, 5, 6} };どちらでもよいが、後の方がわかりやすい

3 次元以上では、{ }を入れ子にしても、わかりにくい変数を用いて、

列を宣

int NUM = 10;
int score[NUM]; /*ただし、const 修

することはできない。
い */がされていれば可(例外あり)

const int NUM = 10;
int score[NUM]; /* int score[10]と同じ*/

( 列の 素数に らないが)生の数字をソースコードに入れる(ハードコーディング)のではなく、わかりやすい名前(変数が保持する値の意味)を付けた変数など使うといが少なくなる。例えば、
問
14 の 答例を下 のようにすると、意味が分かりやすくなる。
#i c de < di .h>iai (i a gc, cha *a g [ ])i NUM_STUDENTS = 10;

c
i i;
i
c e[NUM_STUDENTS]; d
FILE *f ;f = f e (" c e.
a e = 0.0;b e a e;", " ");

f (i=0;i< NUM_STUDENTS;i++)f ca f(f , "%d", & c e[i]);a e += c e[i];fc e(f );a e /= NUM_STUDENTS;
f = f e (" a . ", " ");f i f(f , "a e age = %f ",a e);/* i f("a e age = %f ",a e); */f (i=0;i< NUM_STUDENTS;i++)if( c e[i] >= a e) f i f(f , "%d ", i+1);/* if( c e[i] >= a e) i f("*"); e e i f(" ");i f("%2d:%d ",i+1, c e[i]);*/
fce

e(f );
0;pass.c

こうすると、生徒 20 人バージョンも、一カ所直すだけですぐに作成することができる。1 次元 列の 列名は、 列の先 アドレスを した。
Examplechar carray[64] carray == &carray[0]2 次元の場合
int a[2][3];a[0] ⇒ &a[0][0], a[1] ⇒ &a[1][0]を意味する。

15

問scoredata.txt は、 1 クラス(10 人)ぶんの名前、でされている生徒の名前 [Tab]、数学、科学の点数が下の[Tab] 数学 [Tab] 科学⏎scoredata.txt を み み、
、数学、科学すべての点数(整数)が、それぞれの教科のクラスの平均点以上獲得した生徒の名前を result.txt に出力せよ。
Seiko 85
Akina 77
Noriko 88
Ken75
MasashiNobunaga
Cha
74
TomoyoJohn 74
George 84
S

e e

96
45
55
75
86
75
87
45
45
45

80⏎
86⏎
85⏎
78⏎
90
45
65⏎
36
87⏎
94⏎

90⏎
58⏎
45⏎
scoredata.txt

1: i e f 演算子

変数のサイズ

何バイトなのか

や、

列の

素数を確

できる

int a[4];printf(“sizeof(char) = %d¥n”,sizeof(char)); /* 1 */printf(“sizeof(int) = %d¥n”,sizeof(int)); /* 4 : 処理系により異なる*/
printf(“sizeof(float) = %d¥n”,sizeof(float)); /* 4 : 処理系により異なる */printf(“sizeof(double) = %d¥n”,sizeof(double)); /* 8 : 処理系により異なる */printf(“sizeof(a) = %d¥n”,sizeof(a)); /* 16(4×4) : 処理系により異なる */printf(“num of elements of a =%d¥n”,sizeof(a)/sizeof(int)); /* 4 */
S

e e

2

C

では、ハードコーディングを#define を使う場合も多い。

けるために、const をつけた変数の他に、

#i c de < di .h>#defi e NUM_STUDENTS 10
i

ai (i
i
i

a gc, cha *a g [])i;c e[NUM_STUDENTS];d b e a e;
FILE *f ;f = f e (" c e. ", " ");a e = 0.0;
f (i=0;i< NUM_STUDENTS;i++)f ca f(f , "%d", & c e[i]); a e += c e[i];fc e(f );a e /= NUM_STUDENTS;
f = f e (" a . ", " ");f i f(f , "a e age = %f ",a e);f (i=0;i< NUM_STUDENTS;i++)if( c e[i] >= a e) f i f(f , "%d ", i+1);fcee(f );
0;上の例では、コンパイル時に 厳密にはコンパイル前に NUM_STUDENTS がすべて10 に き換わる。NUM_STUDENTS と 10 の に = がないことや、最後にセミコロンがないことに注意。

16.
プログラムを作る時、まとまった処理ごとに 数を作って 特に何度も同じ処理が必な場合 、それを呼び出すようにすると、いが少ないし、すっきりする。main 数
が 1 万 あるようなプログラムは作らないように数の書き方は、基本的に main 数と同じ。ただし、main 数のようにされるわけではなく、明示的に呼び出さないと実 されない。

動的に実

例 1
仮引数、戻り値、いずれもない場合。
Main 数内の下 のところで、hello_world2 が呼び出される。 数の名前の後に( )がついていることに注意。

#include <stdio.h>void hello_world2( ){int i;
for(i=0;i<2;i++){printf("Hello, World¥n");}return;}int main(int argc, char *argv[ ]){int i;
for(i=0;i<10;i++){hello_world2( );}return 0;}

hello_wrold2 を実した後、元の場所に戻る(正確には「;」のうしろ)
main 数と hello_world2 数内に、同じ名前の変数 i があるが、別々の 数内にある変数は互いに一切影 を及ぼさない。 名前と型は同じだが、全くの別物
数の定
void

法

戻り値、引数なしの場合

数の名前( ) {処理}
数のネーミングは、変数の時と同じ。ただし、C が用意している標準の 数と同じ名前は使わない方が い

例2
仮引数あり、戻り値なしの場合#i c de < di .h>
ida (i ␣

)i i;
f (i=0;i<;i++)cha ('*');cha ('¥ ');
e
;

i

ai (i

a gc, cha *a g [])i i;
f (i=0;i<10;i++)a (i);e

0;

数の仮引数は、型と名前をかく
変数の宣 と同じ 。 数の引数を取る場合は、仮引
数を「,」カンマ で区切って書く。
例
void star(int num, char c)
i=3のとき star(i) は star(3) として呼ばれ値がコピーされる。star
数は、 num に 3 が代入された状態で、実 される。
また、 数を呼び出すときは、引数の型だけが 一していればよい。
main 内でわざわざ num という int 型の変数を使用
する必 はない。
例: int i=1; star(i)整数を直接書いてもよい。
例 star(0)なお、仮引数 num であるが、 star
数以外の 数で num と う変数があっても、無 係である。

ちなみに、putchar

数は、1 文字出力する 数で、stdio.h のインクルードが必

例 3
引数に渡した変数の内容#i c de < di .h>
id

a (i

)

i i;
f (i=0;i<;i++)cha ('*');cha ('¥ ');= 100;e;実
果$ ./a.exe
*****
i=5
$

呼び出した側の 数の変数の内容(この場合 i ) を、呼び出された数で変更することはできない。
num は 100 に変わってい
る。 。
※

i

ai (i a gc, cha *a g [ ])i i=5;
a (i);i f("i=%d ", i);e0;

によっては変わるものもある

り しになるが、star の仮引数
は num であるが、呼び出す側では、num という名前の変数を用意す
る必 はない。 型さえ 一 してい
ればよい

4
仮引数、

り値、いずれもある場合#i c de < di .h>
i

(i

a, i

b)

り値
数は、一つだけ値を すことができる。戻り値がある 数をつくるときは、数の名前の前に、 void にかわi c;c = a + b;e␣c;

り、 り値の型をかく。(点
る)

i

ai (i
i

で囲んでい

a gc, cha *a g [])i, j, ;i f("E ei ege : ");ca f("%d%d",&i,&j);=(i, j);i f("%d + %d = %d ", i, j, );e0;

また、 す値は、
return␣ に き、変数なり数値などを直接書く。 実 で囲んでいる)。

例 5グローバル変数#i c de < di .h>cha a;
id

a (i

)

i i;
f (i=0;i<;i++)cha (a);
cha (
e
;

id he
i

');

ai (i

()

戻り値がない場合、return は省略可",a);a gc, cha *a g [ ])a = '*';a (10);
he ();e0;

実

果$ ./a.exe **********
a = 10

数外で宣 された変数は大域変数(global variable)と呼ばれ、 数 で共 に使用できる。 点 で囲んでいる
局所変数にグローバル変数と同じ名
前の変数がある場合は、局所変数が優先される。実 で囲んでいる

a=10;
i f("a = %di

数内で宣 された変数は局所変数(local variable)と呼ばれ、他の 数からはアクセスできない。

例 6
静的

数

#i c de < di .h>
id c

()

a ic i i = 0;i++;i f( cha bee ca ed fistatic をつけた変数は、プログ
ラムが 了するまで値が保持さ
れる。

ai (i

%d i ea gc, cha *a g [])i i;
f (i=0;i<10;i++)
c
();

e

実

0;

果

$ ./a.exe
count has been called for 1 times
count has been called for 2 times
count has been called for 3 times
count has been called for 4 times
count has been called for 5 times
count has been called for 6 times
count has been called for 7 times
count has been called for 8 times
count has been called for 9 times
count has been called for 10 times", i);

宣 と同時の初期化は、初めに呼び出されたとき、1 回だけ実される。

宣と同時に わない初期化

static int i;i=0;

こう書くと毎度初期化される。

例 8
プロトタイプ宣#i c de < di .h>$ gcc example8.cifunc6.c:12:8: error: conflicting types for‘half'ai (ia c, cha *a g [])i i;d b e d;i=5;
d = ha f(i);i f("%d/2 = %fe
0;d b e ha f(id b e d;d = i/2.0;
ed;func6.c:7:6: note: previous implicit
declaration of ‘half ’ was here", i, d);数は、使用する前に定 を書いておかな
ければならない。定 が出てくる前に呼ぶと、コンパイラは戻り値を int 型とみなす
ので、実 の戻り値が int でないとコンパ
イラによってはコンパイル時にエラーが出る。 コンパイルが っても、動作はおかしなものになる場合がある

i)

F nc ion Pro o pe

プロトタイプ宣
プロトタイプ宣をうことで、定の前に数を呼ぶことができる。

#i c de < di .h>

プロトタイプdi);

実 で囲んだ 分がプロトタイプ宣 。
数の戻り値、 数の名前、仮引数をかく。

ai (i a c, cha *a g [])i i;d b e d;i=5;
d = ha f(i);i f("%d/2 = %f ", i, d);e0;

下のところ(+ セミコロン)をかくと思えばよい。

ib e ha f(id b e ha f(id b e d;d = i/2.0;
e
d;

i)

コンパイルは る。

Function Prototype

Cの書籍では、標準数の明に、プロトタイプを含めた下の●の様なものが書かれている。
exitz

インクルードファイル名 stdlib.hzvoid exit(int status)¾ 戻り値なし、引数は 1 つで int 型。
¾ stdlib.h をインクルードする必

あり

fputs
z

インクルードファイル名 stdio.hz

int fputs(const char *string, FILE *stream)¾ 戻り値 int 型、引数は 2 つ。
¾ stdio.h をインクルードする必¾

あり。

const char *string は文字列か、文字

列を渡す

….
ここまでくれば、数を使って、円の分で有用な数を探して使用することができると思う。

積を求めるプログラムを書き換えてみる。

#i c de < di .h>db e ca c_a ea(dbe )cd b e PI = 3.141592653589793;
d b e a ea;
a ea = PI* * ;
e
a ea;

i

ai (i

a gc, cha *a g [])db e ad, a ea;
hi e(1)i f("E e a adi : ");ca f("% f", & ad);if( ad < 0.0) b ea ;a ea = ca c_a ea( ad);i f("A ea = %f ", a ea);
e

0;

問

16

1.

問

13 の切歯温度を可

2.

問

14 の平均点を求める

S

e e

1

e

温度に変換する
分を

分を

数化せよ

数化せよ

について

数は、最初に return にても、 了する。

した時点で、たとえその下にまだ処理が残されていたとし

id
i

a (i

)

i;
e

;

f (i=0;i<;i++)cha ('*');cha ('');= 100;e;上数は、整数型の変数を 1 つ宣

S

e e

2

しただけで

了する。

列の引数について

普 の変数は引数の内容を変えることはできないが、る。

列の内容は変えることができ

これは、 列を呼び出す 数に渡す時は、全ての 素を渡すのではなく、先ス、型などの情報を渡す。 すべての 素を渡すのは 効率であるなので、 列に っては、呼び出した側と同じなり、内容が変わってしまう。

列変数のアドレスを操作することに列でなくとも、変数のアドレスを渡すようにすれば、呼び出した
内容を変えることができる。 例 scanf
列の
は、C

アドレ

数から、変数の素を渡したときは、当然内容は変えられない。 例 func(s[3][2]);や C++の入 書の、「ポインタ」の を参照すること。

しく#i c de < di .h>
id cha ge(ii[5])

i; f (i=0;i<5;i++)[i] = - [i];
実

i

ai (i
i

果

$ ./a.e e-1 -2 -3 -4 -5

a gc, cha *a g [])a[5] = 1,2,3,4,5 ;cha ge(a);i f("%d %d %d %d %d",a[0],a[1],a[2],a[3],a[4]);
e

17.

0;

体

データにまとまりをもたせたいことがある。例えば、
問
前、の点、数学の点、科学の点 など。別々に変数を宣
すっきりする。

15 の学生のデータ 名
するより、まとめた方が前回の例だと、const int N_STUDENTS = 100; /*100 人*/ ……..
char name[NUM][64];int score_eng[NUM];
int score_math[NUM];
int score_sci[NUM];問はないが、、、、

このようなデータをまとめるために、構いる。前の例は、構 体を使うとstruct student{
char name[64];int socre_eng;
int score_math;体と呼ばれるものが Cには用意されてint score_sci;};
として、student という体 student の定分だけのデータ型をつくることができる。(上の) student 型を定

分は、構

したら、

struct student data[NUM];というようにして、変数を用意できる。
列でなくとも、もちろんよい 使い方
は、”.”(ピリオド)で、中の変数にアクセスするということ以外は、普 の変数や、
とおなじ。

列

data[0].score_eng = 75;
やint a = data[2].score_mat;
printf(“%s¥n”,data[30].name);など
問

17

問

15 のプログラムを構

体を使いもう一度作成せよ。

18. バイナリモードでのファイルの み
ここまでは、fprintf で、テキスト形式で

き

果を目に

える形で保存してきた。

Cには、 列などの内容を内現のまま保存したり、意されている。下 の 数を使用する

み

んだりする

数も用

size_t fwrite(const void *p, size_t size, size_t n, FILE *stream)p:書きむデータの先size: 書き
n: 書き

アドレス

むデータ一つ分の大きさ。sizeof 演算子を使うとよい

むデータの数

size_t fread(void *p, size_t size, size_t n, FILE *stream)p:書きむデータを格納するメモリ

size:

み

n:

み

アドレス

むデータ一つ分の大きさ。sizeof 演算子を使うとよい

むデータの数

fwrite, fread とも、stdio.h のインクルードが必上の整数の型と域の先。また size_t という型は、今は 0 以

えておいても差し支えない(と思う) fopen でファイルをオープンするとき、書き

むとき “w” → “wb”

みむとき “r” → “rb”

とする。b をつけないと、Windows の Visual Studio などで、問 がる。
書き

こる場合があみの例#i c de < di .h>

書き み#i c de < d ib.h>

一様乱数を 100 個発生させ、それをrand.dat として保存する。

i

ai (i
i

i;

i

a[100];

a gc, cha *a g [])FILE *f ;f (i=0;i<100;i++)

バイナリモード

列 a の先 から(1 次元 列の名前

a[i] = a d();

は、先

f =f

int 型の大きさのデータを(4 とかの生の数字を入れないこと)

e (" a d.da ", " b");fi e(a, i e f(i ), 100, f );fc

e(f );e0;

素のアドレスを意味)

100 個
fp で指定されたファイルに書き む

み

みの例

#i c de < di .h>#i c de < d ib.h>
i

ai (i

み み
rand.dat を み み、一様乱数を 100 個発

a gc, cha *a g [])生させ比 する 同じはず

i

i, ;

i

a[100];

バイナリモード

FILE *f ;f =fe (" a d.da ", " b");

列 a の先 から(1 次元 列の名前

f ead(a, i e f(i ), 100, f );fc

は、先素のアドレスを意味)

e(f );

f (i=0;i<100;i++)int 型の大きさのデータを= a d();i f(" =%d, a[%d]=%d: ", , i, a[i]);if( ==a[i])e eei f(" a e

i f("

a e

100 個

");
");

fp で指定されたファイルに

み む

0;

19. これからここまでの知で、だいぶ実用的なプログラムが作れるはずである。

を、まずはどのような流れで
み立てる

くか

こうとする問え、小さな処理に分割して、プログラムををすること。他人が書いたプログラムを

んだり、実

に

分で何か作

ったりするとよい。
さらに C

の学

を

めるのであれば、

z

ポインタ

z

動的メモリ確保z

プログラムを複数のファイルに分けるを勉強して、その後 C++にである( g++ )。

むとのがおすすめ。C++コンパイラも cygwin で使用可Ae di 1canf について
scanf, fscanf 数で 数の数値や文字列を み取る場合、デフォルトでは、スペース、
タブ、改 で区切る。この性 からスペースを含んだ文字列を み取ることはできない。
#i c de < di .h>実

i$ ./a.e eSi
a i S d ieai (ia gc, cha *a g [])例' e e e ed
cha

[Si

[80];

ai

S d ie ].

ca f("% ", );i f("e' e e e ed [% ].

", );

0;

$ ./a.e eSiai␣S die' e e e ed [Siai].

スペースを入れると、区切られているとされる

次の例は、数値を入力するとき、1 個ずつ改 しなければいけないイメージがある#i c de < di .h>iai (i a gc, cha *a g [])i i, j, ;ca f("%d",&i);ca f("%d",&j);ca f("%d",& );i f("' e e e ed %d, %d a d %de0;.",i,j, );次の例は、3 個並べなければいけないイメージがある。
#include <stdio.h>
int main(int argc, char *argv[]){
int i, j, k;scanf("%d%d%d",&i,&j,&k);printf("you've entered %d, %d and %d.¥n",i,j,k);
return 0;
}

しかし、
実

例 1

実

$ ./a.e e
1
2
3

例 2

$ ./a.e e
1␣2␣3' e e e ed 1, 2 a d 3

実' e e e ed 1, 2 a d 3

例 3$ ./a.e e
1␣2
3' e e e ed 1, 2 a d 3.

実

果はどちらでも同じである。改Aもスペースも、単なる区切り文字にぎない。

e di 2: バッファリング
標準入出力やファイル入出力では、バッファリングがわれる。

キーボードから入力された文字列は、まずメモリ内に確保されているバッファ 域に入り、その後 scanf などで使用される。バッファ 域に入ったデータが実 に処理されるタイミング はバッファ
改前のページの域が満タンになったときしたとき

果をバッファリングとあわせてえてみよう 。

キーボードからの入力やディスプレイへの出力は、付加されている。まず、出力のほうを える。

常にいので、このような機#i c de < di .h>#i c de < d ib.h>
i

ai (i

a gc, cha *a g [])i f("He, ");ee (1); /* 秒(カッコ内の数値)休止する 数。 d ib.h をインクルードする必 がある*/i f("W
e

0;

d

");

が

実

すると、Hello,と 示され、1 秒後に World と実

して 1 秒後に Hello,World と一気に入りすぐにはすべてが示されず、World の後の改示されるような気がする。しかし、示される。最初の Hello,はバッファ

域にで、ようやく処理に回され、 Hello,World示される。

#i c de < di .h>#i c de < d ib.h>
i

ai (i

a gc, cha *a g [ ])i f("He , ");ff h( d );ee (1);i f("W d ");e0;

ただし、int fflush(FILE *): バッファ内の中(stdout)だけでなく、普を強制的に出力させる数。標準出力のファイルに対しても使える。ファイルの場合、 fclose すれば、バッファの内容はフラッシュされるので、クローズしても出力されていないデータがあるのではという心(こんどこそ)実は無用。

すると、まず Hello,と 示され、1 秒後に World と示される。

Hello,を fflush で強制的に出力している。また、標準エラー出力はバッファリングされないようなので、fprintf(stderr,”Hello,”);とすれば、fflush はいらない。
次に入力をえる。キーボードから入力した文字列で、scanf で使用されなかった文字

列は、バッファ域に残る。この性

数だったりする(もちろんとはない)。

い少佐ががあるため、 scanf や fscanf は、少し危うように、使い方をならなければどうというこ#i c de < di .h>ii

実ai (i a gc, cha *a g [])i = 0;
hi e(1)ca f("%d",&i);i f("' e e e ed %d. ",i);if(i<0) b ea ;例
ae eou ve enteredou ve enteredou ve entered

e

0;

しかし、

って A を入力すると、A は整数ではないので、scanf(“%d”,&i)の実

敗する(おそらく A はバッファに残る)。失敗後 printf,if をに失し(i にはすでに 2 が入っている)、scanf (“%d”,&i)に戻るが、バッファに”A”が残っているためなのか、また
scanf に失敗する。そして printf, if….というように、永久にループする。
これ以外にも、おかしくなる例は 構ある 改
グラムによっては妙な動作をする、など 。
無

ループに

る実

がバッファに残っていることで、プロ例$ ./a.exe
1
you've entered 1.
2
you've entered 2.
A
you've entered 2.
you've entered 2.
you've entered 2.
…(無 ループ) /*ctrl+c で止めよう*/
安全対策の一つとしては、fgets と sscanf を使うことが えられる。
char *fgets(char *buf, int size, FILE *s)
ファイルから、1あるいは size-1 文字 み

み、末尾に¥0 をつけてbuf に格納する
sscanf(const char *buf, ….)
scanf, fscanf の仲
標準入力やファイルからでなく、buf で指定された文字を み取る

列から数値など

いずれも、stdio.h のインクルードが必。これらを使って書き直したプログラムは、#i c de < di .h>iai (i a gc, cha *a g [ ])実cha b f[256];i i = 0;hi e(1)fge (b f, i e f(b f), di );ca f(b f, "%d",&i);i f("' e e e ed %d. ",i);if(i<0) b ea ;
e

fgets

例
ae e

ou ve enteredou ve enteredAou ve enteredou ve entered

0;

数で、1

ずつ文字

列 buf に入力した文字列を格納しているので、バッファには何も残らない。ゆえに A を入力しても無Ae di 3:ループにはならない

コード

コード (Newline character)

改

Windows

CR+LF

昔の MacCR

Linux (Cygwin 含む) Mac(MAC OS X)

LF

改

コードが

いたとき、改例Linux で作ったテキストを Windows のメモ帳で・改うと、テキストエディタでされない場合がある。

く対処例

コードを変換する

・いろいろな改 コードに対応したテキストエディタを使用する
サクラエディタ、秀丸エディタ(有償)Ae di 4: ai
main

の

と

り値

数の引数について
int main(int argc, char *argv[])
プログラム実時のコマンドライン引数の情報が入る

argc には 引数の数(int 型、プログラムファイルの名前含む)
argv には、実に入力された文字列(char 型)

Exmaple$ ./a.exe␣first␣second␣third

argc = 4
argv[0][03]: ./a (argv[0]の中

argv[1][05]: first¥0

argv[2][06]: second¥0

argv[3][05]: third¥0は、処理系によりいがある)

プログラムで、argc と argv の内容を確 することができる。

下#i c de < di .h>
i

ai (i
i

a gc, cha *a g [])i;i f("a gc = %d", a gc);

f (i=0;i<a gc;i++)i f("%d:%e", i, a g [i]);0;コマンドライン上で$ ./a.exe␣15としても、”15”(argv[1][0”2])は、あくまで文字列である。整数として扱いたい場合は、
atoi

数で整数に変換する必がある

int a;
a=atoi(argv[1]); /*to integer*/実数の場合は(例$ ./a.exe␣15.256 )、atof6 数を使う

double b;b=atof(argv[1]);/*to floating point number*/atoi, atof数を使用するには stdlib.h をインクルードする必

では、戻り値はどうか…. int main(int argc, char *argv[]){ ….
return 0;
6

sscanf を使う方法も えられるがある

}
上の return 0 の 0 はどこへ
数でも、

これは、

了ステータスとして、OS に了のきは 0、それ以外の時はる。慣例として、正常は、exitくのか

了ステータスがせる(exit

0 の値を

数の引数が

す。 return 以外で了ステータスになる)。

#i c de < di .h>

このプログラムを実$ ./a.e e 3

i

e

ai (i
i

a gc, cha *a g [])a =a i(a g [1]);
e

%d

すると

3

$ ech $?
3a;i f(" eされ", a);$ ./a.e e 10

a;

e

10

$ ech $?
10「$?」には直のともできる。Wi d
タスを了ステータスが入っている。シェルスクリプトなどから利用するこ
では、ech %ee e %。 ちなみに、

コマンドの

了ステー

てみる。

$
2 d
$ ech $?
0$a e
: a e にアクセスできません: N

ch fi edi ec

$ ech $?
2
存在しないファイル名を指定してエラーをこしたところ、了ステータスが 2 になった。

Ae di 6:

学

C には、c i e, i e や平方根を 算するためので用意されている。それらを使うには

数など、様々な数学

数が標準

a h.h をインクルードする必コンパイルには、例e aがある(ハイフン エル エム)が必

e.c#i c de < di .h>#i c de < a h.h>
i

ai (i
d

a gc, cha *a g [])b e c;

c=c(3.14159/3.0);

i f( ce(3.14159/3.0) = %f0;

コンパイルは > gcc␣e a

A

,c);

e.c␣ lm

e di 7: インデント
プログラムを やすくするために、タブやスペースを使い、字さげしたり、改 をいれたりしよう。この 料では、あえてほとんどインデントは使っていない。
どんな字さげスタイルがあるか、インターネットで べてみよう。indent コマンドなるものが使える場合もある。
また、プログラムの 明コメント(/*と*/で囲む)も積極的に入れて、他人がやすいコーディングに気を付けよう。

ても理

し

まとめ問
1. bool 型、short 型、long 型についてても べよ。

べよ。また符号なし(unsigned)の変数につい2. int 型が、最大どのくらいの整数を扱えるか
3. 度 degree

であらわされている度を戻り値(double)としてす

べよ。

度を引数(double 型)でうけとり、ラジアンでの数を作成せよ。

度(ラジアン) =

度(度)×

π/180
4. 3 次元ベクトルの内積を算する数を作成せよ。double 型の 列 2 つ(3 次元ベクトル)を受け取り、それらの内積を算、戻り値(double)とする。

a=(ax,ay,az)、b=(bx,by,bz)とすると、a と b の内積 a・b=axbx+ayby+azbz
5. n!を算する数を作成せよ。N を引数として受け取り

果を戻り値とする。

ただし、n は 0 以上の整数で、n! = n × (n”1) × (n”2) × … 2×1 ただし n=0 のとき 0!=1 である。
6. Napier 数 = 1+1/1!+1/2!+1/3!+1/4!+…である。7 で作成したNapier 数を 算するプログラムを作成せよ。(もちろんるように作る)7.

暦 x 年がうるう年か否か数を用いて、

当なところで算をやめべるプログラムを作成せよ。うるう年は「x が400 で割り切れる」あるいは「4 で割り切れるが 100 では割り切れない」年である。
8. rand() 数(0 RAND_MAX の整数の疑似乱数発生
ウォークのプログラムを作成しよう。

数)を使って、2 次元ランダム

ルール:Rules
1. 原点からスタート

initial position is the origin

2. 毎ステップ x、-x、y または-y 方向に 1 ずつ
3. 位

むは、整数型とする。

9. 一様乱数を使って、π の
とり囲む一

の

さ

似値を求めよう。原点を中心とした半径の正方形をえる。-1.0(x,y)が円の中に入った否か確かめる。
る。何度かこれをを推定せよ。ヒント

り

1.0 の

の乱数を振り(x,y)とする。

積比より、円の中に入る確率は π/4 であし、円の中に入った回数/
rand, srandの円とそれを数が π/4 に等しいとして、π数、RAND_MAX
10. 8 のランダムウォークを拡張することをを 0.0

える。移動する方向を全方向、移動する

5.0 にせよ。rand() 数を使って、0-5.0 の範囲と, 0 2 ×π の範囲の乱数を発生させ(前を r, 後を theta とする)、 x=x+r*cos(theta),

y=y+r*sin(theta)で移動するようにする。[理系向き]
11. じゃんけんプログラムを作成せよ。ユーザーとコンピュータの対戦。10 回戦で、何度勝ったかも 示させる。
12. 台形公式により(下の図参照) 数(y=f(x))を定積分するプログラムを作成し、 分で定 した 数を定積分し、きざみの幅をいろいろ変えて、手 算の場合とどれだけうか確 せよ。[理系の人向け]…..

FROM CCFORTRANとの対比で、Fortran90 の初歩の初歩を引に対比させることによって生じた不正確な

する。大

の偏

と、無理やり強もあることはご了承いただきたい。

なお、Fortran90 のソースコードも cygwin でコンパイル可である。コマンドは

gfortran である。
プログラムの基事

FORTRAN 90

C

基本的に 1 文は 1 に収める。1 にかけるのは 132 文字。1 に収まらな
い時は、文の最後に&をつけて改 する。
文の最後にセミコロンはいらない。ただし、1 に 数の分を書きたい時は、セミコロンで区切る。

中で改 することも可 。文字列の中とかは改 できない。

セミコロン必変数の名前などは、大文字小文字は区 大文字小文字は区別される。
別されない。 文字列の中とかはもちろん区別される 。変数などの名前付けてよい

則はだいたい C と同じとえかもコメントは、! の後全 。改するまで /* と */で囲む

ファイルの拡張子は f90

拡張子は cCygwin でのコンパイラのコマンド
gfortran

Cygwin でのコンパイラのコマンド
C コンパイラ
ラ:g++プログラムの基本形は、
program␣プログラムの名前変数の宣処理
end␣program␣プログラムの名前である。上から下に向かって、処理が実される。

gcc, C++コンパイ

Hello, World を作ってみるとprogram␣hello_world
print␣*, "Hello, World"end␣program␣hello_worldとなる。大文字と小文字は区別されないので、
PROGRAM␣HELLO_WORLDPRINT␣*, "Hello, World"
End␣Program␣HELLO_WORLDと書いてもよい。各
変の味に応じて決めればよい。

とデータ型
C

FORTRAN 90

文字型

char

character

整数型

int

integer

単精度実数型

float

real
dp を整数型とする

倍精度実数型
doubledp=selected_real_kind(14)real(kind=dp)

bool

理型

logical“

素数型

complex

変数の変更をできconst
ないようにする

parameter

暗

あり

の型宣

変数宣

なし

方法を次のプログラムでてみる。

program␣var
implicit␣none
integer␣::␣i
integer, parameter␣::␣dp = selected_real_kind(14)real␣::␣srreal(kind = dp)␣::␣dr1, dr2

dr1 = 3.141592653589793
dr2 = 3.141592653589793_dp
print␣*, "dr1 = ", dr1
print␣*, "dr2 = ", dr2
end␣program␣var
実果$ ./a.exe
dr1 =3.1415927410125732

dr2 =

3.1415926535897931

implicit none とは、暗
は、暗

の型宣

と

う

の型宣

を無効にするためのものである。 FORTRAN でなしで i,j,…n で始まる名前の変数は整数型、則があり、宣

それ以外は実数型として使える。しかし、ミスの原因になるので、このして、使用する変数はすべて宣
変数の宣

する方が

則は無効に

い。

方法は、基本的には、型名をかいて、:: (コロン 2 個)につづき、変数名を書く7。
int a [C]→ integer :: a [Fortran90]

数書きたい時は、カンマで区切る。また、宣と同時に初期化したいときは、Cと同様に、= 値と ける。 ただし、宣 と同時に初期化すると、後save 属性(C でいう static)がつくことになる みたい。
的に 。
parameter は、型の後にカンマにする

けて書く。変数 dp は、変更しないので、parameter を使っている。
const int a = 1 [C]→ integer, parameter :: a = 1[Fortran90]

selected_real_kind の括弧の中の 14 は、少なくとも 14 桁の精度 と うのを意味している ということは倍精度。単精度の変数では、そこまでの精度はない 。 実数の定数であるが、何もしないと、単精度として扱われるので、倍精度実数の変数に代入しても、 果がよろしくない(実果参照)。倍精度の定数にするには、倍精度実数の変数の宣 で使った dp を数字の後に”_dp”のようにして付ける。878

これ以外の宣 方法もある
dp には、8 が入っていると思うが、全ての処理系でそうとは らないらしいので、

selected_real_kind で求めたものを入れるとよい。

logical 型は.true.と.false.がある(Cの bool 型では true と false).

次に、文字

てみよう。

列のサンプルプログラムを

program char
implicit none character :: acharacter(len = 11) :: ba= "a"
b= 'john lennon'
print *,aprint *,b
end program char
実

果$ ./a.exeajohn lennon
a は一文字、b は 11 文字

憶できる

len=は省略可

。C

のように、

では strcpy

はしなくていいし、"で囲んでも、'で囲んでもよい9。また、C心数を使わなければできないようなことも、Fortran 90 では手端文字のにできる(b への文字列の代入参照)。

C

FORTRAN90

し算

+

+

引き算

-

-

掛け算

*

*

割り算

/

/

%

み み 数 mod(i,j) 整数
i を整数 j で割った余り

余り
冪

pow

括弧

()

Fortran90 では、簡単に冪の

数

**
()

算ができる。また、Cと同様、異なる型の混在する

算では、小さい型の数値が大きい型の方に変換されてから9

もちろん細かい 則はあるので、常にどちらでもいいとは えない算される。ただし、

Fortran では、実数より精度の素数のほうが大きい型である。しかも、倍精度実数より、単素数の型が大きいとみなされる。

次のプログラムの果をてみよう

program calc1
implicit none
integer :: i, j, kreal :: a, b, c
i = 5; j = 2
a = 2.0k = mod(i, j)
b= a**2
c= a**0.5
print *, k
print *, b
print *, cend program calc1
実果$ ./calc1.exe
1 ← 5÷2 のあまり
4.0000000 ← 2.0 の二乗
1.4142135 ←2.0 の 0.5 乗(平方根)
Fortran90 には、数多くの数学系の 数があり、それらも使用可 である。実数が引数の場合、単精度か倍精度かで、内 で使用する 数が ってくる 倍精度の数値を渡せ
ば倍精度用の 数、単精度の実数を渡せば単精度用の 数を 動で んでくれるので、精度はあまり気にせず使用できる 。
ここで、0 で割ったらどのような数値が出るか、次のプログラムでprogram inf
real :: v,m,n
v = 1.0; m = 0.0;
n = v/mprint *, n

してみある。

end program inf$ ./a.exe+Infinity-1.0 の平方根はprogram nan
implicit none
real :: a,bb = -1.0;
a = sqrt(b)print *, aend program nan$ ./a.exe
NaN
Infinity(無大)や NaN(not a number)が出たら注意。0.0/0.0 でも NaN がでる。

キーボードからの入力
C

では、scanf を使って、標準入力から数値などを入力するようにしていたが、Fortran90 でこれを実現するのは、read である。read を使った数値の入力は、以下のサンプルプログラムをてもらいたい。

program indata
implicit none
integer, parameter :: dp = selected_real_kind(14)integer :: ireal :: rreal(kind=dp) :: dread *, i, r, dprint *, i, r, d
end program indata実

例$ ./a.exe
1 2.0 3.0⏎
1 2.0000000

3.0000000000000000$ ./a.exe
1⏎2⏎3⏎
1 2.0000000

3.0000000000000000$ ./a.exe
1,2,3.5⏎ ← カンマでも区切ってよい
1 2.0000000
実3.5000000000000000

ると、ほぼ scanf と同様な動きをすると例をに細かい書式(“%f%d”など)は必るのでではなく、並んでいる変数で判断して代入してくれ構楽である。scanf と異なる挙動を示すプログラムの例

program indata2
implicit none
integer, parameter :: dp = selected_real_kind(14)integer :: i, jreal :: rreal(kind=dp) :: dread *, i, r, dread *, jprint *, i, r, dprint *, j
end program indata2
実

えてよい。さらに、scanf のよう例$ ./a.exe
1 2.0 3.0 4 5 6
7
1 2.0000000
73.0000000000000000

4 5 6 が無くとき)。

された。まったく scanf と同じだと思ってはいけない(特に数値を並べて書半径を受け取り、円の積と円周を求めるプログラムは、

program circarea
implicit none
integer, parameter :: dp=selected_real_kind(14)real(kind=dp),parameter :: pi = 3.14159265358979_dp
real(kind=dp) :: radiusreal(kind=dp) :: area, circum
print *,"Enter a radius "read *, radius
circum = 2.0_dp * pi * radius area
= pi*(radius**2)
print *,"Enshu = ", circum, "Menseki = ", area
end program circarea
件分
数値を比

1(IF)
のための演算子の比CFORTRAN 90

A は B より大きい

A> B

A > B または A .gt. B

A は B 以上

A >= BA >= B または A .ge. B

A は B より小さい

A< B

A < B または A .lt. B

A は B 以下 (≦)

A <= BA <= B または A .le. B

A と B は等しい

A == BA == B または A .eq. B

A と B は異なる(≠)

A != BA /= B または A .ne. B≧

最後の 1 つだけ新たけ憶えれば、あとは Cと同じ号が使える。

理演算子の比ORCFORTRAN 90

A || B

A .or B

AND

A && BA .and. B

NOT!A.not. ACと 号は うが、and や or の前後にピリオドをつけるだけなので、さほどるのに 労はない。

えFortran 90 の if の基本形は、
if(条件 1) then
処理 1
else␣if(条件 2) then処理 2else␣if(条件 3) then
処理 3
else
処理 n
end␣ifである。中括弧{ } で囲まない代わりに、then と end if が来るのがCと同じと えてよい。

うだけで、あとは

もちろん、else if や else は必ずしも使わなくてもよい。例えば
if(条件) then処理
end ifやif(条件 1) then
処理 1
else
処理 2
end ifのような形でも使うことができる。例として、comp_int.c を Fortran 90 で書き換えてみると、下のようになる。

program compint
implicit none
integer :: a, b
print *, "input a number(a)"read *, aprint *, "input a number(b)"read *, b
if (a > b) thenprint *, "a is bigger than b"else if(a==b) thenprint *, "a is equal to b"
else
print *, "a is smaller than b"
end ifend program compint
なお 1でわる程度のものならif(条件) 処理とう書き方もできる件分

2 (CASE)

Fortran90 には、Cの switch と同様な働きをする case 構文がある。しかも、範囲指定ができるなど、switch より多機である。 case 構文の基本形は、

select␣case(式)case(値 1)
処理 1case(値 2)
処理 2…..
case␣default
処理 nend␣select
式は、整数、文字、理が使用できる

実数系は Cでも目だった 。また、 Cの break にあたるものは入れなくてよい。値のところは、範囲指定も可である。

例えば、値 A:値 B とすると、A B、値 A: とすると、A 、: 値 B とするとい。

Bをす。範囲指定する場合は、する区があってはならな

例として、switch123.c を Fortran90 に直すと、program switch123
implicit none
integer :: choiceprint *,"input a number"read *, choiceselect case(choice)case (1)print *,"one"case (2)print *,"two"case (3)print *,"three"case default
print *,"1,2 or 3 is required"
end selectend program switch123となる。範囲指定を使い少し書き換えるとprogram switch123_kai
implicit none
integer :: choiceprint *,"input a number"read *, choiceselect case(choice)case (:1)
print *,"LE1"case (2:3)
print *,"two or three"case (4:)
print *,"GE4"

end selectend program switch123_kai

りCし実の for にあたるものとして、do

変数=初期値,

end do がある。基本形は、 do␣[制御界値[ , 増分]]処理
end␣do
制御変数とは、Cの for でいうと、for(i=0;…の i のことである。増分は省略可

で、省略したときは制御変数が+1 される。さらに書くと、do の後の制御変数=初期値、なども省略可である。

program hello10
implicit none
integer :: ido i=1, 10
print *,"i=",i , "Hello, World"end doend program hello10
Cでは、ループを抜け出たりするための、break や continue があった。

Fortran 90 でもそれに対応したものはある。
C

FORTRAN90

break

exit

continue

cycle

program hello10_kai
implicit none
integer :: i = 1
doif (mod(i, 2) == 1) then
i=i+1
cycle
end ifprint *, "i=",i ,"Hello, World"
if (i == 10) thenexit
end ifi=i+1
end doend program hello10_kai
実果$ ./a.exei=2 Hello, Worldi=

4 Hello, Worldi=

6 Hello, Worldi=

8 Hello, Worldi=

10 Hello, Worldi が奇数のとき、cycle により Hello, World をよりループを 了している。

示せず、が 10 になったら、exit に

すでに気づいていると思うが、print を実すると、改される。また、文字列と一に数値をわない。print にも C示すると、どうも示が気にうに、書式を指定できる。
書式指定子の対比
C

FORTRAN90

文字、文字列%c (1 文字), %s(文字列)

A

整数

%d

I (Iw)

実数%f

F (Fw.d)%e, %EE (Ew.d)

“

X

実数(指数
空白

示)

の printf のよw:フィールドの幅、d:小数点以下の桁。Fw.d は、「w 桁の幅をとって、そこに実数を示する。小数点以下は 5 桁に整数を示する。」という意味。Iw は「w 桁の幅をとって、そこ示する。」という意味。

C では、%w.df や%wd となっていたところが、Fw.d や Iw となったと思えばよい。また nFw.d(たとえば 2F10.5)と書くことで、n 個の Fw.d という意味になり、同じような数値を 示したいとき便利である。空白の場合は、空白が一つでも 1X と書かなければならない。また Cと い、w や d は必ず書かなければいけない。
サンプルをてみる。*があった分に、書式を入れている。(今回は大文字で)

PROGRAM Form1
INTEGER :: A
REAL :: B, C
CHARACTER(11) :: D
A = 100
B = 1.41421
C = 1.73205

D = "John"
PRINT "(2X, I5, 2F10.5, 2X, A)", A, B, C, D
END PROGRAM Form1
次のような指定もできる。
PROGRAM Form1_KAI
INTEGER :: A
REAL :: B, C
CHARACTER(11) :: D
A = 100
B = 1.41421
C = 1.73205
D = "John Lennon"
PRINT 100, A, B, C, D
100 FORMAT(2X, I5, 2F10.5, 2X, a)

END PROGRAM Form1_KAI
PRINT 100,a,b,c,d とは、文番号 100 に書式がありますよ、という意味になる。文番号
は 5 桁以下の正の整数で 由につけられる。FORMAT のところは、特に何かが実 されるわけではない。
また、書式では、(2X, I5, 2(F10.5, 2X), a)のような指定も可う意味になる。
り

し実、(F10.5,2X)が 2 個とい2(do while)Cの while に対応しているのが、Fortran90 の do while である。制御変数の操作
は、プログラマに任せられている。
基本形は
do while(条件)処理
end do
これを使うと、hello10 はprogram hello10_2
implicit none
integer :: i = 1
do while(i<=10)
print *,"i=",i, "hello, world"
i=i+1
end doend program hello10_2
ファイル入出力
ファイルへの書きみ、ファイルからのC

FORTRAN90

printfprint, write

scanf

read

fprintf

write

fscanfread

print はすでに出てきているのでする。
write および read は

み

みにしては、次の対応があると思う。

read も出ているけど 、write と read について、

write (制御指定子) 変数

数ある時は、カンマで区切っていく

read (制御指定子) 変数

数ある時は、カンマで区切っていくである。制御指定子は、
zunit =

別子z

fmt = 書式

別子

zadvance : 改

するか否かなどがある。
別子は、整数の番号。ただし、z0: 標準エラー出力 (stderr)z5: 標準入力 (stdin)z

6: 標準出力 (stdout)

なので、これ以外の番号を使用する。これは Cの fp と思えばよく、ファイルなど

をこれで区別する。書式

別子は、print のところですでに介した。句は、”yes”または”no”とする。これは改するか否かである。デフォルトでは yes となっていて、改される。例えば
write(unit=6, fmt=“(2x, 2f10.5)”) x, y
unit や fmt は * を くことで省略できる
せたいとき 。

画に示したり、キーボードから入力さ

例えばprint *,"i=",i,"hello, world" → write(*,*),"i=",i,"hello, world"
ファイルのオープン、クローズは、 C

では fopen, fclose

open(オープン指定子)
close(クローズ指定子)
でう。

オープン指定子は、以下のようなものがある
z

unit=

z

file=フィル名(文字列)番号zstatus ”old”(すでにファイルが存在する。 み むとき), “new” 新たにファイルを作るとき。書き むとき , “replace” 既に存在するファイルを消して新たにファイルを作る のどれか。

zaction=入出力動作ziostat”read”, “write”, “readwrite”のどれか

ファイルオープンに成功すると句が 0、失敗すると正の数値

クローズ指定子は、以下のようなものがある
z

unit=

書き

番号もちろんこれ以外にもあるが、最初はこれだけでよい。

みのサンプルとして、hello10_2 をファイルに書きむように修正してみる。

program hello10_2f
implicit none
integer :: i = 1, iostatusopen(unit=10, file="hello.txt", status="new", &action="write", iostat = iostatus)
if(iostatus > 0) stop "can't open file"
do while(i<=10)
write(unit=10, fmt="(a, i2, 2x, a)") "i=", i, "hello, world"
i=i+1
end doclose(unit=10)
end program hello10_2f
if は、ファイルがオープンに成功したがどうかいる(stop でプログラムはC

べて、失敗したら了するようにして了する)。

で fp=fopen… ; if(fp==NULL){ … exit(1);}をしていると思えばよい。

次に、 み みのサンプルとして、、体に書き出すプログラムを作成してみる。
program calcbmi
implicit none
integer :: iostatusreal :: height, weight, bmi

のデータを

み

み、BMI を算して画open(unit=10, file="data.txt", status="old", action="read", &iostat = iostatus)
if(iostatus > 0) stop "can't open file"
doread (unit=10, fmt=*, iostat = iostatus) height, weightif(iostatus < 0 .or. height < 0.0 .or. weight < 0.0) then! read all data or less than zeroexit
end ifbmi = weight/height**2
print "(a, f5.1)", " bmi is ", bmi
end doclose(unit=10)
end program calcbmi※ ファイルの最後まで

くと、iostat は の値になることを利用している.

ここで、print の書式を例えば(a, f2.1)に変えて実 してみると、数値がアスタリスクに代わっていることがわかる。 Fortran90 では、書式に指定した幅に収まりきれない時、アスタリスクに変えて出力する10。
列Fortran90 での 1 次元

列の宣

方法は、

型, dimension( 素数) :: 変数11整数型の場合Integer, dimension(5) :: aである。こうすることで、
a(1) a(5)まで整数型として使える。C
では、[ ] であったが、Fortran では、普の( )を使う。また、インデックスが 0 からではなく、1 からのことに注意12。
Cでは幅が りなくても無理やり 示する
これ以外の宣 方法もある
12 インデックスが 1 からにしない方法もある
1011

値の代入は Cと同様にa(1) = -1; a(2) = 3などとする。一気に代入する方法もあり、 a= (/1,2, 3, 4, 5/) とすると、
a(1) = 1; a(2)=2; a(3)=3; a(4)=4; a(5)=5 としたことと同じ。
列の宣は、生の数字を使ってハードコーディングせず、

integer, parameter :: n = 5
integer, dimension(n) :: aとすることもできる。ここまで
ラムを作ると、介したことをすべて使って意味のないサンプルプログ

program array1
implicit none
integer, parameter :: n = 5
integer, dimension(n) :: ainteger :: ia = (/1,2,3,4,5/)
do i=1, n
print *, a(i)end doend program array1
実

果$ ./a.exe
1
2
3
4
5
多次元

列の宣

は、

integer, parameter :: nx = 5, ny=4, nz=3
integer, dimension(nx, ny, nz) :: aなどとする。使い方は a(1,1,2) = 2 などなど13。メモリの中では、一番左の添え字からに並んでいる(Cは一番右)。多次元

列への一括の値代入は、もう少し知なので割愛する。
列のまとめとして、pass.c の Fortran90 版を作ってみる
program passf90
implicit none
integer, parameter :: numstudents = 10
integer, parameter :: unitnum = 10
integer, parameter :: dp = selected_real_kind(14)real(kind=dp) :: ave = 0.0_dp
integer, dimension(numstudents) :: score
integer :: iostatus, iopen(unitnum, file = "score.txt", status = "old",&
action="read", iostat=iostatus)
if(iostatus > 0) stop "can't open file"
do i=1, numstudents
read (unitnum, *) score(i)ave = ave + score(i)end doclose(unitnum)
ave = ave/numstudents
open(unitnum, file = "pass.txt", status = "new",&
action="write", iostat=iostatus)
if(iostatus > 0) stop "can't open file"write(unitnum, "(1x, a, f5.1)") "average = ", ave
do i=1, numstudents
if(score(i) >= ave) thenwrite(unitnum, "(1x, i3)") i13

Cでは各次元のインデックスを[ ] で囲んだが必

end ifend doclose(unitnum)end program passf90
なお、Fortran には、べること。

列を操作するみ

み

数などが富に用意されているので、サブルーチンとCの数にあたるものに、サブルーチンや数がある。

サブルーチン基本形は、
subroutine 名前(引数並び)変数などの宣処理
end subroutine 名前
呼び出す時は、 call サブルーチンの名前(引数) とする。
以下に BMI を算するサンプルプログラムを示す。

program caclBMI_s
implicit none
real :: height, weight, bmi
write(6,"(2x, a)", advance="no") "input height (m) and weight (kg): "read *, height, weightcall calcbmi(height, weight, bmi)
write(6, "(a, f5.1)") "bmi is ", bmi
end program celtofah_s
subroutine calcbmi(h, w, bmi)

implicit none
real, intent(in) :: h, w
real, intent(out) :: bmi
bmi = w/h**2
end subroutine calcBMI_s
Cと い、引数の内容を変えることができる。CalcBMI 中で、BMI の値を書き変えて、呼び出し元に戻している。また、
real, intent(in) :: h, w
real, intent(out) :: bmi
で、引数の型や属性をしている。intent(in)な仮引数は、サブルーチン内で書き変えられない。受け取るだけ。intent(out)は、書き変えて、呼び出し元に値を戻すことができる。この他に、intent(inout)という、受け取りかつ書き変え可

な属性もある。

指定しないと、intent(inout)扱いになる。out や inout 属性の引数は、C++でいう参照渡しであろう。

サブルーチンは、引数を じて値を していたが、名前で 果を すことができるも Fortran90 に存在する。 数を使って上のプログラムを書き変えると、
program calcBMI_f
implicit none
real :: height, weight, bmi
real :: calcbmif
write(6,"(2x, a)", advance="no") "input height(m) and weight(kg): "read *, height, weight
bmi = calcbmif(height, weight)
write(6, "(a, f5.1)") "bmi is ", bmi
end program calcbmi_ffunction calcbmif(h, w)
implicit none数real, intent(in) :: h, w
real :: calcbmif
calcbmif = w/h**2
end function calcBMI_f
数は、C
ライクな呼び出しができる。呼び出し元でも calcBMIF を宣 しなければならない。また、 数内では、 数と同じ名前の変数の値が、呼び出し元に される
14(intent(out)属性の引数で値を すこともできちゃうみたいだけど)。
ここまでは、メインとなるプログラムの外に、サブルーチンや 数を書いてきたが、この書き方だと、コンパイラは引数の型のチェック等をすることができない。使い方をらなければ問 ないが、Cのプロトタイプ宣 のようなことをすると、コンパイ
ラがチェックすることができる。以下はその例。
program calcBMI_I
implicit none
real :: height, weight, bmi
interface
function calcbmif(h, w)
real, intent(in) :: h, w
real :: calcbmif
end function calcbmif
end interface
write(6,"(2x, a)", advance="no") "input height(m) and weight (kg): "read *, height, weight
bmi = calcbmif(h, w)
write(6, "(a, f5.1)") "bmi is ", bmi
end program calcbmi_ifunction calcbmif(h, w)

14

これがいやなら、result という句を使って、別な変数の値が戻るようにできる。

implicit none
real, intent(in) :: h, w
real :: calcbmif
calcbmif = w/h**2
end function calcBMI_I
interface end interface のあいだに、を書く(Cとほぼ同じだ)。
また、サブルーチンや数の引数の型や戻り値の型などの情報の分

数は、プログラム本体に収めることもできる。メインのプロ

グラムのうしろに、contains と書いて、それにけて(かつ end program より前)に数やサブルーチンを書く。
program calcBMI_IN
implicit none
real :: height, weight, bmi
write(6,"(2x, a)", advance="no") "input height(m) and weight (kg): "read *, height, weight
bmi = calcbmif(h, w)
write(6, "(a, f5.1)") "bmi is ", bmi
contains
function calcbmif(h, w)
implicit none
real, intent(in) :: h, w
real :: calcbmif
calcbmif = w/h**2
end function calcbmif
end program calcBMI_IN

数やサブルーチンをメインのプログラムの内書いたり、戻り値の型宣もしなくてに書くと、interface で引用の仕様をい。また、こうすると、内サブルーチンからメインのプログラムの変数に、Cクセスできるようになる。C

と同様、

あれば、そちらが優先される。また、にいたのグローバル変数のようにア数やサブルーチン内に同じ名前の数やサブルーチン内の変数は、クセスできない。 ミスの元なので、数やサブルーチンから大域プログラムを書くのは、やめたほうがい 。

型, save :: 変数 = 初期値と同時の初期化が必。たとえば、
integer, save :: i = 0

save をつけると、 数やサブルーチン内の変数の値が保存される。
体
Fortan90 でも構体を使用することができる。構体の定は

type␣型名
変数…
end␣type␣型名とかく。この型の変数宣

は、type(型名) :: 変数名
でよい。内

の

素にアクセスるには、%を使う。まとめると

C

FORTRAN90

structtype

アクセスするときは、 .

%例struct student{
char name[64];int socre_eng;
int score_math;int score_sci;

数が

元からはア

素にアクセスする

では Cの 的変数(static をつけた変数)は、Fortran90 でどうすればよいかのようにすればよい。
宣

数や

次

};
を Fortran では、
type(student)
character(64) :: nameinteger :: score_eng
integer :: socre_math
integer :: score_sci
end type student
student が型名にあたる
type(student) :: personとしたならば、

素へのアクセスは、%を使ってperson%score_eng = 87のようにする。
バイナリモードでのファイルのみき

open のところに、form=“unformatted”といれ、read, write のところに、書式引数を書かない。整数型のプログラムを下
書き

みは下

素 100 個の 列を書きむプログラムとそれを

に示す。

プログラム

program write_bin
implicit none
integer, parameter :: n = 100
integer, parameter :: unitnum = 10
integer, dimension(n) :: ainteger :: iostatus, i
do i=1, 100a(i) = iend doopen(unitnum, file = "bin.dat", status = "new",&
action="write", iostat=iostatus, form="unformatted")if(iostatus > 0) stop "can't open file"

係の
み

む

write (unitnum) aclose(unitnum)end program write_bin
み

みは下

プログラム

program read_bin
implicit none
integer, parameter :: n = 100
integer, parameter :: unitnum = 10
integer, dimension(n) :: ainteger :: iostatus, iopen(unitnum, file = "bin.dat", status = "old",&
action="read", iostat=iostatus, form="unformatted")if(iostatus > 0) stop "can't open file"
read (unitnum) aclose(unitnum)
write(*, "(100i4)") a
end program read_bin
実果$ ./write_bin.exe$./read_bin.exe
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25
26 27 28 29 30 31 32 33 34
35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51
52 53 54 55 56 57 58 59 60 61 62 63 64 65 66 67 68
69 70 71 72 73 74 75 76 77 78 79 80 81 82 83 84 85
86 87 88 89 90 91 92 93 94 95 96 97 98 99 100

確かに み書きできた。しかし、ls –l を実 してみると bin.dat のファイルサイズが、少し大きい-rw-r—r-- 1 ohno None 408 Jul 24 12:55 bin.dat
整数型 100 個なので、ファイルサイズは 400 バイトのはずが、408 バイトになっている。これは、データにそれぞれ 4 バイトのヘッダとフッタが付加されたからである15。
これは、変数ごとにつく。例えば
write(unitnum) A
write(unitnum) Bとすると、全体のはじめと最後に 4 バイト付く(ヘッダ+A+B+フッタ)のではなく、Aの前後と B の前後に 4 バイトずつ付き(ヘッダ+A+フッタ+ヘッダ+B+フッタ)、合16 バイト大きくなる。
Fortran で み むのは問 ないが、Cで作ったプログラムで初と最後の 4 バイトを み ばさなければいけない。

み

むときは、最form = “unformatted”ではなく、form=“binary”とすると、このヘッダとフッタの付加をさせないこともできるが、全てのコンパイラでこれが使用可とうわけではない。

(gfortran ではコンパイル時にエラーが出る。SGI サーバーの Intel コンパイラではった)
これからここまでで、初歩の範囲はカバーしているのでないかと思う。さらに Fortran の学をめるのであれば、モジュール、割り付け列(Cの動的メモリ確保に相当(すると思う))などを勉強するとよい。
この 料には、
いが含まれている可 性は大いにあります 人 のすることなので 。特に Fortran の 分は短時 で作成して、プログラムは Word に張り付けてから、整形したり変数の名前を変えたりしているので、動作しないものが含まれているかもしれません。
い探しをするつもりで、勉強するといいかも。
問C

15のところにある

ファイルサイズが

問

、まとめ問

を全

Fortran でいてみるされている。8 バイトずつつく処理系もあるとか。

参
1. 大 盛広,「C
ました)

入

」,

東社 (1995) (名だと思います。これで Cを憶え

2. ラリー・ニーホフ, サンフォード・リーストマー, 渡 了介 (), ドキュメント
システム (), 「入 Fortran90」,ピアソンエデュケーション (2001)

・2012 年 7 月 25 日 初版・2012 年 8 月 1 日 修正・2021 年 3 月 26 日 修正・2021 年 5 月 30 日 修正