ひずみ

C言語の復習
コンパイルと実行
エディタでソースファイル hello.c を作成
#include <stdio.h>
int main()
{
test.c
printf("Hello!\n");
return 0;
}
コンパイラ
コンパイル
$ cc hello.c
実行
$ ./a.out
Hello!
a.out
実行可能ファイルの名前を指定する場合:
$ cc -o hello hello.c
$ ./hello
ソースファイル
実行可能ファイル
画面へ出力
printf(書式,変数,変数,..);
#include <stdio.h>
%f
%d
%s
double
int
char* (文字列)
int main()
\n
{
\t
double x;
int n;
x = 1.234;
n = 987;
printf("x = %f\tn = %d\n", x, n);
return 0;
}
改行
タブ
書式の詳しい指定
#include <stdio.h>
int main()
{
int n = 12345;
double x = 12.12345678;
printf("%d\n",n);
12345
printf("%8d\n",n);
12345
printf("%f\n",x);
12.123457
printf("%.3f\n",x);
12.123
printf("%9.3f\n",x);
12.123
return 0;
}
メモリと変数
番地 データ
1000
1001
1002
1003
1004
1005
1006
1007
…
番地 データ
23
int x;
int y;
56
x = 23;
y = 56;
x 1000
y 1004
変数とポインタ
番地 データ
x 1000
y 1004
z 1008
23
int *p;
56
99
x = 23;
y = 56;
z = x;
23
p = &x;
…
p 2000
int x, y, z;
&x : 変数 x の「番地」
printf("%d\n",*p);
1004
1000
23
*p : ポインタ p の指す番地に
記憶されているデータの値
p = &y;
printf("%d\n",*p);
56
*p = 99;
printf("%d\n",y);
99
キーボードから入力
scanf(”書式”, &変数, &変数, ..);
#include <stdio.h>
%lf double
int main()
%d
int
{
%s
char* (文字列)
double x;
int n;
printf("Enter double and int: ");
scanf("%lf %d", &x, &n);
%f ではだめ!
printf("x = %f\tn = %d\n", x, n);
return 0;
}
scanf() には変数の値ではなく変数のアドレス(番地) を渡す
double を入力する際はかならず書式に %lf を使う
加減乗除
+
-
#include <stdio.h>
int main()
{
int n, m;
printf("Enter n,m:
scanf("%d %d", &n,
printf("%d waru %d
n, m, n/m,
return 0;
}
*
/
%
");
&m);
= %d amari %d\n",
n%m);
整数 / 整数 は少数点以下を切り捨てた整数
整数 % 整数 は割り算の「余り」
インチをセンチメートルに変換
キーボードからインチ単位の数値を入力し
センチメートルに換算して出力する
プログラムを作成せよ。
1 inch = 2.54 cm
実行例
$ ./a.out
inch ? 3.3
3.30 inch = 8.38 cm
$
$ はシェルのプロンプト
太字がキーボードからの入力
if 文
#include <stdio.h>
int main()
{
int m;
printf("Enter m: ");
scanf("%d", &m);
if( m % 2 == 0 ) {
printf("%d is even.\n", m);
}
else {
printf("%d is odd.\n", m);
}
return 0;
}
m % 2 は m を2で割った余り
比較と条件式
等しいか? ==
!=
大小比較 >
>=
<
かつ、または &&
||
#include <stdio.h>
int main()
{
int m;
printf("Enter month: ");
scanf("%d", &m);
if( m >= 1 && m <= 12 ) {
printf("OK.\n");
}
else {
printf("error! no month: %d\n", m);
}
return 0;
}
<=
if … else if … else …
if(条件1) {
条件1が成り立てばここを実行
}
else if(条件2) {
条件1は成り立たないが、条件2は成り立つ場合
}
else {
それ以外(条件1も条件2も成り立たない場合)
}
else if() {
else {
} は2つ以上あっても良い。
} は無くても良い。
西暦 --> 和暦変換
#include <stdio.h>
平成元年 = 1989 年
int main()
昭和元年 = 1926 年
{
int seireki;
printf("seireki?: ");
scanf("%d", &seireki);
if( seireki > 1988 ) {
printf("Heisei %d nen\n", seireki-1988);
}
else if( seireki > 1925 ){
printf("Showa %d nen", seireki-1925);
}
else {
printf("Wakarimasen\n");
}
return 0;
}
西暦 --> 和暦
大正、明治まで対応出来るように拡張してみよ。
大正元年 = 1912 年
明治元年 = 1868 年
うるう年
グレゴリオ歴
•4で割り切れれば原則うるう年(それ以外は平年)だが、
•100でも割り切れる年は平年
•さらに400でも割り切れる年はうるう年
1900
2000
2100
1904
2004
2104
1908
2008
2106
..
..
..
1996
2096
2196
言い換えると
•西暦が400で割り切れる年はうるう年
•それ以外で100で割り切れる年は平年
•それ以外で4で割り切れる年はうるう年
•それ以外(4で割り切れない年)は平年
キーボードから西暦を入力し、うるう年かどうかを
判定するプログラムを作成せよ。
コメント
/*
*/
で囲った部分はコメント
#include <stdio.h>
/* comment test */
int main()
{
/*
comments can span two
or more lines
*/
return 0;
}
/* no error */
for 文による繰り返し
for(初期化; 条件; 更新処理) {
文1;
文2;
.. ..
}
初期化を実行
条件が成り立つ限り
文1
文2
....
更新処理
を繰り返し実行
#include <stdio.h>
int main()
{
int j;
for(j=0; j<10; ++j) {
printf("%3d %6d\n", j, j*j);
}
return 0;
}
x += 3, ++j など
x
x
x
x
=
=
=
=
x + a;
x - a;
x*a;
x/a;
x += 1;
x -= 1;
を
を
x
x
x
x
+=
-=
*=
/=
a;
a;
a;
a;
と略記出来る
++x;
x++;
--x; あるいは x--;
と略記出来る
x = 3;
y = ++x;
x = 3;
y = x++;
x = 4;
y = 4;
x = 4;
y = 3;
x を増やしてから y に代入
x をy に代入してから x を増やす
出力のリダイレクト
printf() は "標準出力" への出力。
通常は端末の画面に出力されるが、
リダイレクトにより出力先をファイルに変更できる。
$ command > filename
$ ./a.out
2ページ前のプログラムを実行
0
0
1
1
出力は画面に出る
...
9
81
$ ./a.out > out.txt
出力を out.txt へリダイレクト
$ cat out.txt
0
0
1
1
...
9
81
1 から n までの和を計算
#include <stdio.h>
int main()
{
int n, k, sum;
printf("Enter n: ");
scanf("%d", &n);
最初に 0 にするのを
忘れずに!
sum = sum + k
sum = 0;
と同じ
for(k=1; k<=n; ++k) {
sum += k;
printf("%4d %6d\n", k, sum);
}
return 0;
}
fprintf() 標準出力以外への出力
fprintf(出力先, 書式, 変数, 変数, ..);
printf() と全く同じ
出力先として使えるのは
stdout
stderr
標準出力
標準エラー出力
リダイレクトしなければ
どちらも画面へ出力される
fprintf(stdout,...); は printf(...); と同じ
fprintf(stderr,...);
はエラーメッセージ等の出力に使う
プログラム中から特定のファイルを開いてそれを出力先に指定することも可能。
(この講義では扱わない。興味があればfopen() の使い方を参照して下さい。)
出力先を使い分ける
#include <stdio.h>
int main()
{
int n, k, sum;
fprintf(stderr, "Enter n: ");
scanf("%d", &n);
stderr へ出力
sum = 0;
for(k=1; k<=n; ++k) {
sum += k;
printf("%4d %6d\n", k, sum);
}
stdout へ出力
return 0;
}
標準出力だけリダイレクトする
$ ./a.out > sum.txt
Enter n: 10
$ cat sum.txt
1
1
2
3
3
6
4
10
5
15
6
21
7
28
8
36
9
45
10
55
$
stdout をリダイレクト
stderr に出力した
Enter n:
は画面に出力される
stdout に出力したものは
ファイルに保存されている
while 文
while(条件) {
条件が成り立つ限りこの部分を繰り返し実行
}
#include <stdio.h>
#include <unistd.h>
int main()
{
int k;
k = 10;
while( k > 0 ) {
printf("%3d\n", k);
sleep(1);
--k;
}
printf("%3d Go!\n", k);
return 0;
}
sleep() を使うのに必要
1秒間待つ
銀行預金
#include <stdio.h>
int main()
{
double yokin, riritsu, mokuhyo;
int nen;
fprintf(stderr, "Enter riritsu: ");
scanf("%lf", &riritsu);
100万円が200万円以上に
yokin = 100.0;
なるには何年かかるか?
mokuhyo = 2.0*yokin;
nen = 0;
while( yokin < mokuhyo ) {
yokin += yokin*riritsu;
1年複利
++nen;
printf("%6d %10.2f\n",nen, yokin);
}
return 0;
}
不定個数のデータの入力
データの個数があらかじめ解っていない場合どうするか
#include <stdio.h>
int main()
データの読み込みを試み、
{
正しく読める限り繰り返す
double x, sum;
sum = 0.0;
while( scanf("%lf", &x) == 1 ) {
sum += x;
}
printf("total = %f\n",sum);
return 0;
}
scanf() の戻り値は正しく読み込めたデータの個数
実行してみる
ctrl-D
を入力
$ ./a.out
1.1
3.3
2.2
total = 6.600000
$
最後に ctrl-D を入力すると、最後の入力データまで
読んだと見なされて終了する。
入力のリダイレクト
scanf() は "標準入力" からの入力。
通常は端末のキーボードから入力するが、
リダイレクトにより入力元をファイルに変更できる。
$ command < filename
data.txt というファイルにデータを入力しておく
$ cat data.txt
1.1
3.3
2.2
$ ./a.out < data.txt
total = 6.600000
$
演習
標準入力からデータを読み込み、
•データの個数
•データの総合計
•データの平均
を出力するプログラムを作る。
数学ライブラリ
平方根
べき乗 xy
三角関数
立方根 cbrt(x)
sqrt(x)
pow(x,y)
sin(x)
cos(x)
tan(x)
逆三角関数 asin(x) acos(x) atan(x) atan2(y,x)
指数関数
絶対値
exp(x)
自然対数 log(x)
fabs(x)
#include <math.h> が必要
コンパイル時(正確にはリンク時)にオプション -lm が必要
$ cc xxxx.c -lm
例
#include <stdio.h>
#include <math.h>
int main()
{
double x;
printf("Enter x: ");
scanf("%lf", &x);
printf("%f\n", sqrt(x));
return 0;
}
$ cc root.c -lm
$ ./a.out
Enter x: 2
1.414214
平均と標準偏差
x1, x2 , x3 ,..., xN
N 個のデータ
があるとする
N
平均
1
M  x   xk
N k 1
分散
x  x 
V
2

1 N
  xk  x
N k 1

2

1 N 2
2
  xk  2 x xk  x
N k 1
1 N 2
1 N
  xk  2 x
xk  x

N k 1
N k 1
2
x
x
2
 x
2
 x
2
平均と標準偏差
あるいは
V
x  x 
 x
分散
2
2 x x  x
2
V x
 x 2 x x x
2
2
 x
2
2
標準偏差
 x
2
2
 x
2
 V
プログラムでは
まず
次いで
S  x1  x2  x3  ...  xN
T  x  x  x  ...  x
2
1
S
M
N
平均
2
2
2
3
2
N
T
V   M2
N
分散
を求め
 V
標準偏差
を求める