c言語の特徴• 低水準な処理も可能な高水準言語

c言語
数値計算のためのc言語• 汎用構造化言語• オブジェクト指向言語(c++, java)の基礎• ソフトウェア技術者の教養的知識• 最新のライブラリ(過去の資産は使えない)• 数値計算には不向き(FORTRANに比べて)

1

2

プログラムの基本構成

プログラムの基本構成#include <stdio.h>#include <math.h>int main(void) {double x, y;
printf("Hello, world.\n");x = 0.1;
y = sin(x);printf("SIN(%lf) = %lf\n", x, y);return 0;}##include<stdio.h>#include <math.h#
int main(void) {double x,, y;;printf("Hello,("world.\n");\n");x = 0.1;. ;y = sin(x);( );printf("SIN(%lf)("= %lf\n",\n", x,, y););return 0;;}

Linux等でコンパイル・実行する場合$ gcc this_file.c -lm• 用意されているキーワード(予約語)

34プログラムの基本構成

プログラムの基本構成#include <stdio.h>#include <math.h
int main(void) {double x,x y;yprintf("Hello,Hello, world.\n");world.\nx = 0.1;
0.1
y = sin(x);printf("SIN(%lf)"SIN(%lf) = %lf\n",%lf\n" x,x y);yreturn 0;0}#include <stdio.h>#include <math.h><math.h
int main(void) {double x, y;
printf("Hello, world.\n");printfx = 0.1;
y = sinsin(x);
printf("SIN(%lf) = %lf\n", x, y);printfreturn 0;}• ユーザ定義名前付きオブジェクト• ユーザ定義リテラル
5• システムに依存するリテラル• 標準入出力ライブラリ• 標準数学ライブラリ
6

プログラムの基本構成

プログラムの基本構成#include <stdio.h>#include <math.h><math.h
int main(void) {double x, y;
printf("Hello, world.\n");x = 0.1;
y = sin(x);printf("SIN(%lf) = %lf\n", x, y);return 0;}#include <stdio.h>#include <math.h
int main(void) {double x, y;
printf("Hello, world.\n");x = 0.1;
y = sin(x);printf("SIN(%lf) = %lf\n", x, y);return 0;}• プリプロセッサにより1行（レコード）毎に処理される• コンパイラで処理される「 」(ホワイトスペース)「;」「{」「}」「/*・・・*/」で区切られたバイト• 「#キーワード」のフィールドから始める

列

7

8

文とブロックプログラムの基本構成#プリプロセッサ命令#include <stdio.h>#include <math.h>int main(void) {ブロック
double x, y;
printf(”Hello, world.\n”);
x = 0.1;
y = sin(x);文
printf(”SIN(%lf) = %lf\n”, x, y);return 0;}#定数マクロ定義
int main(コマンドライン引き数) {変数の型 変数名; /*変数宣言*/
実行すべき処理;
return 0;}

9

プログラミング言語の一般論•データ型（定数と変数、 配列）•代入・基本演算（四則演算）
•入出力
•条件分岐
•繰返処理
•関数、外部手続き
11

10

キーワード（予約語）• データタイプchar int ﬂoat double enum struct union typedef• データタイプ修飾子

signed unsigned short long const void• データ記憶クラス

auto static extern volatile register• 制御構造if else do while for switch case break default return
continue goto

• 演算子, 記号

sizeof + - * / % & | , ; : [ ] ( ) { } #12

変数変数• データ（ビット列）を入れることができる箱‣ 名前がついている• 文字型 [通常 8bit]char• 整数型 [通常16bit or 32bit]‣ 大きさが決まっている‣ 実行時に用意される（実行中ではない）

int• 拡大整数型 [通常32bit以上]
long int, long• 実数型(単精度浮動小数点数)[通常doubleと同一]

'a'c

ﬂoat

1026
n3.141592
pi• 倍精度実数型(倍精度浮動小数点数)[通常64bit]
double

13

14

変数

変数宣言

Local Rule.1:• 変数は全て32bit符号付き整数 (int orlong int) と64bit実数 (double) を使う• 32bit符号付き整数–2147483648〜2147483647• 64bit実数

データ型 変数名；

データ型 変数名，変数名，．．．
；
データ型 変数名＝初期値;
整数型

倍精度実数型

int a;
int a, b;
int n=10;

double x;
double x, y, z;
double pi = 3.141592;

1516定数

記号定数 (マクロ置換)•整数（拡大整数）

0, -1, 1234，(123456789L)• 倍精度実数型(倍精度浮動小数点数)
0.0, 1., 123.4, 1.234e-3
1.234e-3 = 1.234×10−3 = 0.001234• 文字列定数（文字列リテラル）"Hello world\n"17• 表に名前、裏に値（定数）の書かれたカード‣ プリプロセッサの機能を利用する‣ 厳密な意味ではユーザ定義名前付きオブジェ
クトではない#define 記号名 置換すべきテキスト#define N 1000
#define PI 3.141592
double pi2;
pi2 = 2.*PI;18

PI 3.141592

四則演算と代入
変数 ＝ 変数(定数)演算子

変数(定和y=a+b

差

y=a–b

y=a-b

積

y=a×b

y=a*b

商

y=a÷b

y=a/b剰余y = a mod b

y=a%b

y=a+b

四則演算と代入

整数 = 整数 + 整数;
整数 = 整数 - 整数;
整数 = 整数 * 整数;
整数 = 整数 / 整数;

整数 = 整数 % 整数;

実数 = 実数 + 実数;
実数 = 実数 - 実数;
実数 = 実数 * 実数;
実数 = 実数 / 実数;

Local Rule.2:• 代入文の右辺と左辺の型を明示的に一致させる• 自動的な型変換を用いず，常に明示的にキャストを行う
int n;
double a, x;x = a / n;

int n;
double a, x;x = a / (double) n;

1920

配列

一次元配列とベクトル•配列名と数字(添字)で指定される変数の集まり

double b[3];double a[100];b[1] = 2.0;

double b[10][5];'H' c[1]'e' c[2]'l' c[3]'l' c[4]'o' c[5]\0c[0]a[0] = 1.0;b[0] = 1.0;b[2] = 1.0;
double b[3]={1.0, 2.0, 3.0};a[1] = 2.0;m[0][0]m[0][1]m[0][2]a[99] = 5.0;m[1][0]m[1][1]m[1][2]b[0][0] = 1.2;

m[2][0]m[2][1]m[2][2]2.0,b[9][4] = 0.0;m[3][0]m[3][1]m[3][2]3.0};

double b[3]=22

一次元配列と数列

二次元配列と行列

double a[2][2];#define N 100

a[0][0] =int n;a[0][1] = -1.0;c[n] = a*pow(r, n-1);

Cn = arn−1!

c[0] = a;c[n] = r*c[n-1];⎞1⃗ =⎝ 2 ⎠B
1{1.0,21

double a, r, c[N];⎛C0 = 0Cn = rCn−1

1.0;

a[1][0] = -1.0;
a[1][1] =2.0;

double a[2][2]={{1.0, -1.0}, {-1.0, 2.0}};
double a[2][2]={{1.0, -1.0},{-1.0, 2.0} };

23

24

A=!

1−1−12"

配列に関する注意• 入力関数

int x[2][3] = { {0, 1, 2}, {4, 8, 16}} ;
XX00

XX02

XX04

XX06

x[0][0]x[0][1]x[0][2]x[1][0]

0

XX00
x[0]

XX06
x[1]

XX00x

12XX0AXX08x[1][1]
8 x[1][2]16x[1][1]x[1][2]

4XX0C

入出力

getchar, getc, fgetc; 一文字入力

gets, fgets, fread; 文字列(データ列)入力

scanf, fscanf, sscanf; 書式付入力• 出力関数

Local rule:• 配列の要素のアドレスを直接意識するようなプログラムにはしない。

• 必ずすべての（二次元なら2つ、三次元なら3つ）の添え字を指定する。

putchar, putc, fputc; 一文字出力

puts, fputs, fwrite; 文字列(データ列)出力

printf, fprintf, sprintf; 書式付出力
Local Rule.3:• 入力は行わず，データはプログラム中に直接書く．

• 出力はprintfのみ．

2526

printf 関数

書式制御文字列

int printf (const char *, 変数, 変数,...);

int n = 578;

書式制御文字列リテラル• %\"以外はそのまま出力• "%+数字+文字"1

その他%d整数を出力%f

固定小数点実数を出力%e

浮動小数点実数を出力

printf("%d\n", n);%i%o%u, %c, %s%x, %X%E, %g, %G• "%%" %自体を出力

2

34

5

6

printf("%8d\n", n);printf("%2d\n", n); 5 7 8

書式制御文字列

double x = -57.89;

double x = -57.89;

printf("%f\n", x);

45678

910- 5 7 . 8 9 0 0 0 0

printf("%9.3\n", x);- 5 7 . 8 9 0

printf("%6.3d\n", x); - 5 7 . 8 9 0
printf("%6.1d\n", x);29- 5 7 . 9

10

printf("%08d\n", n); 0 0 0 0 0 5 7 8

書式制御文字列3

95 7 828285 7 827

17

1 2 3 4 5 6 7 8 9 10 11 12 13 14 15

printf("%e\n", x);-5.789000e+01

printf("%15.7e\n", x);
printf("%10.1e\n", x);-5.7890000e+01-5.8e+01

printf("%27.20e\n", x);5.78900000000000005684e+0130

printf 関数

c言語の制御構造

int printf (const char *, 変数, 変数,...);
書式制御文字列リテラル• 単純if文• if-else文 (ブロックif文)

Local Rule.4• else-if文• 原則• switch-case文%d整数%f実数• while文%15.7e実数• do-while文を使用する• for文31

32

単純(ブロック)if文

条件式

if (条件式) {処理;}/* 例 a=|a| */

条件処理

成立

不成立

if (a < 0.) {a = -a;}•数値の大小関係の比較
a>ba≥ba<ba≤bn=mn≠ma>ba >= ba<ba <= bn == mn != m

Rule: 整数にしか使わない！

3334

条件式if文論理和

T1 ⊕ T2, T1 ∨ T2(T1) || (T2)

論理積

T1 ⊗ T2, T1 ∧ T2

(T1) && (T2)

論理否定

¬T! (T)•論理演算

条件式 ≠ 0

True (真)条件式 = 0

False (偽)Local Rule:• 条件式の値は使用しない
35•単純if文の例

double b, d;
if (d >= 0.) b = -d;
int i, j, n;if ((i - 1) < 0) j = i -1 + n;
int k, l; double d, eps;
if ((k == l) && (d < eps)) return 0;36

if-else文

else-if文
if (条件式1) {•ブロックif文

処理T1;/* 例 a=|a| */条件if (a >= 0.) {a = a;}
else {a = -a;
}

処理A

成立

条件1}
else if (条件式2) {
処理T2;

不成立

条件1}
.....
else if (条件式n) {

処理B

成立

処理T1

成立

処理T2

成立

処理Tn

不成立

不成立

条件n

処理Tn;

不成立

処理F}
else{
処理F;}

37

38

switch-case文

while文•条件前置型ループ

swich (式) {case A: 処理1;
case B: 処理2;
処理3;
break;
case C: 処理4;
処理5;
break;
default: 処理6;

分類A

処理1

式 分類B
・変数
を 分類C
分類

処理2

while (条件式) {
条件処理;

処理3
処理4

成立

処理不成立}

処理5

その他• Local Rule:

処理6

break;

無限ループを避けるためfor文を使用}• Local Rule: else-ifを使う

39

40

do-while文

for文
for(前処理; 条件式; 次処理){•条件後置型ループ

処理;

do {処理;処理} while (条件式);
条件成立

前処理;

無限ループを避けるためfor文を使用
41

条件

while (条件式){

不成立• Local Rule:

前処理}

不成立

処理;次処理;
}

42

成立

処理
次処理

forループ

forループ•1+2+3+4+...+100を計算する

Local Rule:for( 制御変数 = 1;

#define N 100
int i, s;s=0;for (i=1; i<=N; i=i+1) s = s + i;
Local rule:• --, +=, /=, *=等は使わない

制御変数 <= 制御変数の上限;制御変数++) {処理;}for( 配列の添字 = 0;配列の添字 < 配列の大きさ;配列の添字++) {処理;}• ++のみ使うの形のforループのみを使用

for (i=1, s=0; i<=N; i++) s+=i;

使用例

43

44

forループforループ使用例• 特定の処理をＮ回繰り返す• 配列各要素について処理を行う#define N 100#define N 100

int i;

int i; double a[N];for (i=1; i<=N; i++){for (i=0; i<N; i++){printf(”Loop %6d\n”, i);
}

整数型変数

printf(”A(%3d)=%15.7f\n”, i, a[i]);}45forループ使用上の注意• 制御変数増加型のループのみ使用• 制御変数をループ内で変更しない• 制御変数は整数型を用いる• 初期値は０か１

46forループの例• 配列の値を初期化する#define N 10
int i;
double a[N];• 増分は１のみ

for (i=0; i<N; i++){• 処理は必ずブロックにする}

47

a[i]=1.0;

48

•forループの例

forループの例• 配列に数列を代入する

二次元配列に単位行列を代入する

int i;

int i, j;double a, r, c[N];double a[N][N];for (i=0; i<N; i++){for (j=0; j<N; j++){if (i==0) {for (i=0; i<N; i++){c!n = arnc0 = acn = rcn−1c[i] = a;if (i==j) { a[i][j]=1.0;}

}

else

else {{ a[i][j]=0.0;}}c[i] = r*c[i-1];
}

}
}

49

50

forループの例

forループの例• 配列の総和を求める
int i;
double s, c[N], *p;

S=N−1!

• 配列の最大要素を求める
cii=0

s = 0.0;for (i=0; i<N; i++) {s = s + c[i];}for (p=c, i=0, s=0.0; i<N; i++, s+=*p++);int i, imax;
double vmax, val[N];imax = 0;
vmax = val[0];for (i=1; i<N; i++){if (val[i]>vmax) {imax = i;vmax = val[i];
}
}

51

52

forループの例⃗a = (a0 , a1 , · · · , an−1 )⃗b = (b0 , b1 , · · · , bn−1 )n−1!
⃗a · ⃗b = a0 b0 + a0 b0 + · · · an−1 bn−1 =ai bi•i=0

ベクトルの内積の計算

int i;
double c, a[N], b[N];c = 0.0;for (i=0; i<N; i++){c = c + a[i]*b[i];}53forループの例• 行列の積の計算

int i, j, k;double a[N][N], b[N][N], c[N][N];for (i=0; i<N; i++){for (j=0; j<N; j++){c[i][j] = 0.0;
for (k=0; k<N; k++){c[i][j] = c[i][j] + a[i][k]*b[k][j];
}
N−1}
!
}
Cij =Aik Bkj
k=054

forループの例

forループの例• 周期境界条件を用いる• 周期境界条件を用いる

int j, k;double a[N], b[N], c[N];for (k=0; k<N; k++){c[k] = 0.0;
for (j=0; j<N; j++){c[k] = c[k] + a[j]*b[j+k];
N−1!
}
ck =
aj bj+k}ck =aj bj+k
int j, k;j=0
double a[N], b[N], c[N];for (k=0; k<N; k++){bk+N = bk
c[k] = 0.0;
for (j=0; j<N; j++){jp = j + k;
if (jp >= N) jp = jp - N;c[k] = c[k] + a[j]*b[jp];
}
}

j=0

bk+N = bk

N−1!

55

56

breakとcontinue関数•標準ライブラリ関数(ANSI/POSIX)

前処理

前処理
条件

条件

成立

不成立

不成立

• 環境依存ライブラリ関数(API)成立

break;

continue;

次処理

次処理

• ユーザ定義関数• 値を返す（数学関数など）• 値を返さない（サブルーチン）

57

58

標準数学関数標準数学関数• math.h に定義されている• 使用するときには #include <math.h>
注意: 全て，引数も返り値もdouble型
平方根√xsqrt(x)指数関数

exexp(x)ただし、x ≥ 0

自然対数 ln x, loge xlog(x)ただし、 x > 0

常用対数log10 x

log10(x)ただし、 x > 0

絶対値|x|

fabs(x)59•三角関数・逆三角関数
正弦

sin x

sin(x)

余弦

cos x

cos(x)

正接

tan xtan(x)

戻り値をzとおくと、

逆正弦

arcsin x

asin(x)|x| ≤ 1, −π/2 ≤ z ≤ π/2

逆余弦

arccos x

acos(x)|x| ≤ 1, 0 ≤ z ≤ π

逆正接arctan xatan(x)−π/2 ≤ z ≤ π/2

arctan (x / y) atan2(x, y)60−π ≤ z ≤ π標準数学関数

ユーザ定義関数• 双曲線関数sinh x = (ex – e–x )/2sinh(x)cosh x = (ex+ e–x )/2cosh(x)tanh x = sinh x/cosh xtanh(x)• 切り捨て・切り上げ
floor (x)n–2ceil (x)xn–1nn+1• プロトタイプ宣言

戻り値の型 関数の名前(引数の型, 引数の型, ...);

n+1nceil (x)xn–1 floor(x)• 関数の呼び出し

変数 = 関数の名前(引数, 引数, ...);• 関数の定義

戻り値の型 関数の名前(引数の型 仮引数, ...) {
処理;

n–2

ceil (x)floor (x)return 戻り値;
}

61

62

値を返さない関数

関数の例• プロトタイプ宣言• 単純な初等関数の組み合わせ

void 関数の名前(引数の型, 引数の型, ...);

f(x) = e–x – 1• 関数の呼び出し

double fnct(double);関数の名前(引数, 引数, ...);• 関数の定義

double fnct(double x){double f;
f = exp(-x) - 1.;
return f;}

void 関数の名前(引数の型 仮引数, ...) {処理;}
FORTRANやPascalのサブルーチンに相当する

63

64

関数の例

関数の例

• 単純な初等関数の組み合わせ（2変数）• 配列の要素の最大値

double maxelement(double a[], int n) {f(x, y) = x6 – y3

int i; double maxval;

double fnct(double, double);double fnct(double x, double y){
double x3, x6, y3, f;
x3 = x*x*x;y3 = y*y*y;x6 = x3*x3;
return (x6 - y3);}65

maxval = a[0];for (i=1; i<n; i++) {if (a[i] > maxval) maxval = a[i];}return maxval;}

66

def_const.h#define N 3
int last(int*);

main.cmain.cmain.c#define N 3

main.c#define N 3#define N 3

int last(int*);#include "def_const.h"
int main(void){
int b,a[N]={1,2,3};b=last(a);printf("%d\n",b);return 0;}

int last(int*);
int main(void){
int b,a[N]={1,2,3};b=last(a);printf("%d\n",b);return 0;}

int last(int*, int);
int main(void){
int b,a[N]={1,2,3};b=last(a, N);
printf("%d\n",b);return 0;}

int main(void){
int b,a[N]={1,2,3};b=last(a);printf("%d\n",b);return 0;}function.cfunction.cfunction.cfunction.c#define N 3
int last(int c[]){return c[N-1];}#include "def_const.h"
int last(int c[]){return c[N-1];}#define N 3
int last(int c[]){return c[N-1];}

int last(int c[],int m){return c[m-1];
}

67

68

関数と配列

関数と配列

#define N 2#define M 3
int last(int c[][M]);int main(void){
int b, a[N][M] = {{11, 12, 13},{21, 22, 23}};b = last(a);printf(”%d\n”, b);a[0][3] = {11, 12, 13};return 0;a[1][3] = {21, 22, 23};}a[2] = {a[0],int last(int c[][M]){a[1]}return c[N-1][M-1];}

Rocal Rule:• 1次元配列の大きさは明示するか関数に引数として渡す• 2次元配列の大きさは配列初期化や関数宣言，プロトタイプ宣言でも明示する

69

70

関数と引数

int main(void){
int a=関数と引数

int main(void){1 ;int a[] = {1};func(a);func(a);printf("%d\n",a);return 0;

1%}
void func(int c){printf("%d\n",cc= c

printf("%d\n",a[0]);% a.out
1

return 0;}
void func(int c[]){);

printf("%d\n",c[0]);+ 1;c[0] = c[0] + 1;

}

}

71

72

% a.out12%関数の例• 行列の積を計算する

void mulmat(double a[N][N],double b[N][N],double c[N][N]){int i, j, k;for (i=0; i<N; i++) { /* l3 */for (j=0; j<N; j++) { /* l2 */
c[i][j] = 0.;
for (k=0; k<N; k++) { /* l1 */
c[i][j] = c[i][j] + a[i][k]*b[k][j];} /* l1 */} /* l2 */} /* l3 */}

73

関数と引数

• 呼び出された側(callee)の引数への処理は，呼び出した側(caller)には反映されない(call by value)• 引数が配列名のときには，呼び出された側(callee)の引数への処理が，呼び出した側(caller)に反映される(疑似的call by reference)
74