プログラミング入門 第1 4 回講義

24
rog-0 2013 Lec14-1 Copyright (C) 1999 – 2013 by Programming-0 Group プププププププププ 4 プププ ププププププププププププププププ /home/course/prog0/public_html/2013/lec/source/ プププププププププププ ププププププププププププ プププププ ププププププ ププププププププププ 、・ ププ プププ プ (2) プププププ (2) ププププ ププププププ (4) ププププ ププ (11) ププププ プププププ (14) ププププププププププププ (17) ププププ プ→ プププ 10 (20)

description

プログラミング入門 第1 4 回講義. 関数(その2) 関数の復習 (2) 関数の例1 ニュートン法 (4) 関数の例2 桁数 (11) 関数の例3 ある桁の数 (14) エラーチェックと強制終了 (17) 関数の例4 2進→10進変換 (20).   マークのあるサンプルプログラムは /home/course/prog0/public_html/2013/lec/source/ 下に置いてありますから、各自自分のディレクトリに コピーして、コンパイル・実行してみてください. #include double nijou(double); - PowerPoint PPT Presentation

Transcript of プログラミング入門 第1 4 回講義

Page 1: プログラミング入門 第1 4 回講義

Prog-0 2013 Lec14-1Copyright (C) 1999 – 2013 by Programming-0 Group

プログラミング入門第1 4 回講義

プログラミング入門第1 4 回講義

  マークのあるサンプルプログラムは/home/course/prog0/public_html/2013/lec/source/

下に置いてありますから、各自自分のディレクトリにコピーして、コンパイル・実行してみてください

  マークのあるサンプルプログラムは/home/course/prog0/public_html/2013/lec/source/

下に置いてありますから、各自自分のディレクトリにコピーして、コンパイル・実行してみてください

関数(その2)関数の復習 (2)関数の例1 ニュートン法 (4)関数の例2 桁数 (11)関数の例3 ある桁の数 (14)エラーチェックと強制終了 (17)関数の例4 2進→10進変換(20)

Page 2: プログラミング入門 第1 4 回講義

Prog-0 2013 Lec14-2Copyright (C) 1999 – 2013 by Programming-0 Group

#include <stdio.h>

double nijou(double);

main(){ double a = 1.73 , b , c ; b = nijou(a); c = nijou(1.41); ... (以下略)}

double nijou( double x ){ double y; y = x * x; return y ;}

#include <stdio.h>

double nijou(double);

main(){ double a = 1.73 , b , c ; b = nijou(a); c = nijou(1.41); ... (以下略)}

double nijou( double x ){ double y; y = x * x; return y ;}

引数が仮引数にコピーされる関数内で仮引数の値に従って 計算(処理)戻り値が関数の値となるmain の前にプロトタイプ宣言main の後ろに関数本体の宣言

関数の復習関数の復習

Page 3: プログラミング入門 第1 4 回講義

Prog-0 2013 Lec14-3Copyright (C) 1999 – 2013 by Programming-0 Group

#include <stdio.h>

double nijou(double);

main(){ double x = 2.0, a1, a2, a3; a1 = nijou(3.0); /* 値 */ a2 = nijou(x); /* 変数 */ a3 = nijou(x * 2.0); /* 式 */ printf("a1:%f a2:%f a3:%f \

n", a1, a2, a3);}

double nijou(double x){ double y; y = x * x; return y ;}

#include <stdio.h>

double nijou(double);

main(){ double x = 2.0, a1, a2, a3; a1 = nijou(3.0); /* 値 */ a2 = nijou(x); /* 変数 */ a3 = nijou(x * 2.0); /* 式 */ printf("a1:%f a2:%f a3:%f \

n", a1, a2, a3);}

double nijou(double x){ double y; y = x * x; return y ;}

1. main の最初の実行文から開始2. nijou(3.0) が評価される3. 3.0 が関数の仮引数 x にコピーされ、関

数 nijou に実行が移る4. 計算の結果、 y に 9.0 が入り、「 return

y 」で 9.0 が nijou 関数の結果となる5. nijou 関数の結果が a1 に代入される。6. 次に nijou(x) が評価される7. x(2.0) が関数の x にコピーされ、関数

nijou に実行が移る8. 計算の結果 y に 4.0 が入り、「 return

y 」で 4.0 が nijou 関数の結果となる9. nijou 関数の結果が a2 に代入される10. a3 も同様に計算される11. printf で a1,a2,a3 が表示される12. 終了(教科書 P165 参照)

1. main の最初の実行文から開始2. nijou(3.0) が評価される3. 3.0 が関数の仮引数 x にコピーされ、関

数 nijou に実行が移る4. 計算の結果、 y に 9.0 が入り、「 return

y 」で 9.0 が nijou 関数の結果となる5. nijou 関数の結果が a1 に代入される。6. 次に nijou(x) が評価される7. x(2.0) が関数の x にコピーされ、関数

nijou に実行が移る8. 計算の結果 y に 4.0 が入り、「 return

y 」で 4.0 が nijou 関数の結果となる9. nijou 関数の結果が a2 に代入される10. a3 も同様に計算される11. printf で a1,a2,a3 が表示される12. 終了(教科書 P165 参照)

関数の動作おさらい

関数の動作おさらい

Page 4: プログラミング入門 第1 4 回講義

Prog-0 2013 Lec14-4Copyright (C) 1999 – 2013 by Programming-0 Group

非線型方程式 f(x)=0 の解を求める方法例題として、ニュートン法で

                             の解 を求める  ( ただし、  は与えられた定数、例えば 1,2 など )

関数の例 1― ニュートン法(p.178)

関数の例 1― ニュートン法(p.178)

x2 a 0

x

a

Page 5: プログラミング入門 第1 4 回講義

Prog-0 2013 Lec14-5Copyright (C) 1999 – 2013 by Programming-0 Group

以後 xn につきステップ①②を繰り返す

x0x1

f(x)

傾き f'(x0)

x0

y

求める x

x2

傾き f'(x1)

傾き f'(x2)

x3

ニュートン法の原理ニュートン法の原理

y y0 f (x0)

       と x 軸との交点を反復法によって求めるステップ① : 初期値 x0 を与え、点 (x0,y0) における y=f(x) の接線

y f (x)

(x x0)

ステップ② : 点 (x1,y1) における y=f(x) の接線

と x 軸との交点を求める

y y1 f (x1)

(x x1)

ただし y0=f(x0)

ただし y1=f(x1)

と x 軸の交点 x1 を求める

x0, x1, x2 , x3 … と だんだん f(x) の零点 ( 根になる点 )に近づいていく

Page 6: プログラミング入門 第1 4 回講義

Prog-0 2013 Lec14-6Copyright (C) 1999 – 2013 by Programming-0 Group

ニュートン法の原理まとめニュートン法の原理まとめ

xk xk 1 f (xk 1)f (xk 1)

xk xk 1 f (xk 1)f (xk 1)

x

xfxf

d

)(d)('

初期値 x0 とし、そこでの接線と x 軸との交点を順次求めて行く

ここで、

とする。

(k 0,1,2)

x0x1

f(x)

傾き f'(x0)

x0

y

求める x

x2

傾き f'(x1)

傾き f'(x2)

x3

求めた f(xk) の値が一定の値(精度)より小さければ終了

f(x0)

f(x1)

f(x2)

f(xk)<( 精度 )

Page 7: プログラミング入門 第1 4 回講義

Prog-0 2013 Lec14-7Copyright (C) 1999 – 2013 by Programming-0 Group

フローチャートフローチャート

x←x-f(x,a)/df(x)

f(x,a)> 精度

はじめ

x← 初期値

終り

関数f(x,a)

fx← x*x-a

return fx

関数df(x)

dfx←2*x

return dfx

初期値は一般的に解より少し大きい値 a とする。精度はマクロ EPS で与え、値は10 -6 とするまた、一般的には「 f(x,a)< 精度」に関して、本当は f(x,a) の絶対値を取る必要があるが、初期値を解より大きい a としたので、負になることは考えない

初期値は一般的に解より少し大きい値 a とする。精度はマクロ EPS で与え、値は10 -6 とするまた、一般的には「 f(x,a)< 精度」に関して、本当は f(x,a) の絶対値を取る必要があるが、初期値を解より大きい a としたので、負になることは考えない

dfx は、 fx つまり x2

の 1 階微分だから2x

x 出力

読みこみa← 定数

Page 8: プログラミング入門 第1 4 回講義

Prog-0 2013 Lec14-8Copyright (C) 1999 – 2013 by Programming-0 Group

  プログラム  プログラム#include <stdio.h>#define EPS 1.0e-6

double f(double, double);double df(double);

main(){ double a, x, fx, dfx; printf("input a number : "); scanf("%lf",&a); x = a; printf("x(k-1) \ t \ tfx \ t \ tdfx \ t \

tx(k) \ t \ tf(x,%f)", a); while((fx = f(x,a)) > EPS ){

dfx = df(x); printf("%f \ t%f \ t%f",x,fx,dfx);

x = x - fx/dfx; printf(" \ t%f \ t%12.10f \ n",x,f(x,a)); } printf("sqrt(%f) : %12.10f \ n",a,x);}

#include <stdio.h>#define EPS 1.0e-6

double f(double, double);double df(double);

main(){ double a, x, fx, dfx; printf("input a number : "); scanf("%lf",&a); x = a; printf("x(k-1) \ t \ tfx \ t \ tdfx \ t \

tx(k) \ t \ tf(x,%f)", a); while((fx = f(x,a)) > EPS ){

dfx = df(x); printf("%f \ t%f \ t%f",x,fx,dfx);

x = x - fx/dfx; printf(" \ t%f \ t%12.10f \ n",x,f(x,a)); } printf("sqrt(%f) : %12.10f \ n",a,x);}

double f(double x, double a){ double fx; fx = x*x - a; return fx;}

double df(double x){ double dfx; dfx = 2.0*x; return dfx;}

double f(double x, double a){ double fx; fx = x*x - a; return fx;}

double df(double x){ double dfx; dfx = 2.0*x; return dfx;}

タブ

代入してから比較

マクロで精度を定

/home/course/prog0/public_html/2013/lec/source/lec14-1.c/home/course/prog0/public_html/2013/lec/source/lec14-1.c

初期値

Page 9: プログラミング入門 第1 4 回講義

Prog-0 2013 Lec14-9Copyright (C) 1999 – 2013 by Programming-0 Group

実行結果実行結果

std0dc0{s1000000}1: ./a.out

input a number : 2

x(k-1) fx dfx x(k) f(x,2.000000)

2.000000 2.000000 4.000000 1.500000 0.2500000000

1.500000 0.250000 3.000000 1.416667 0.0069444444

1.416667 0.006944 2.833333 1.414216 0.0000060073

1.414216 0.000006 2.828431 1.414214 0.0000000000

sqrt(2.000000) : 1.4142135624

std0dc0{s1000000}2:

std0dc0{s1000000}1: ./a.out

input a number : 2

x(k-1) fx dfx x(k) f(x,2.000000)

2.000000 2.000000 4.000000 1.500000 0.2500000000

1.500000 0.250000 3.000000 1.416667 0.0069444444

1.416667 0.006944 2.833333 1.414216 0.0000060073

1.414216 0.000006 2.828431 1.414214 0.0000000000

sqrt(2.000000) : 1.4142135624

std0dc0{s1000000}2:

値が EPS (精度)以下になった時点でループを終了する

xk での関数 f(xk) の値。この値が0になった時の xk

が求める値であるが、 f(xk) は完全に0にはならないので、非常に小さい値 EPS 以下になった時の xk を解とする

xk つまりxk-1 - fx/dfxxk-1

Page 10: プログラミング入門 第1 4 回講義

Prog-0 2013 Lec14-10Copyright (C) 1999 – 2013 by Programming-0 Group

  他の方程式 ( ) を解く場合

  他の方程式 ( ) を解く場合

double f(double x, double a){ double fx; fx = x*x*x – a ; return fx;}

double df(double x){ double dfx; dfx = 3.0*x*x; return dfx;}

double f(double x, double a){ double fx; fx = x*x*x – a ; return fx;}

double df(double x){ double dfx; dfx = 3.0*x*x; return dfx;}

main関数での変更は最小限で済む簡単な変更で、もっと複雑な方程式の解を求めることも 可能

/home/course/prog0/public_html/2013/lec/source/lec14-2.c/home/course/prog0/public_html/2013/lec/source/lec14-2.c

2

x 3 a 0

dfx は、 fx つまり x3

の 1 階微分だから 3x2

Page 11: プログラミング入門 第1 4 回講義

Prog-0 2013 Lec14-11Copyright (C) 1999 – 2013 by Programming-0 Group

関数の例 2 :桁数を知る (1)関数の例 2 :桁数を知る (1)

入力された数の桁数を返す関数を作る(例えば、「 12345678 」は8桁)受け渡しの要件:1入力・1出力

入力:数 ⇨ int型出力:桁数 ⇨ int型

関数名は桁数( digits )から digitsとする。digitsのプロトタイプ宣言は以下のようになる。

int digits(int);

Page 12: プログラミング入門 第1 4 回講義

Prog-0 2013 Lec14-12Copyright (C) 1999 – 2013 by Programming-0 Group

桁数を知る (2)桁数を知る (2)

10 で割った答えが 0 でなければ、 2 桁以上の数 100(=1010) で割った答えが 0 でなければ、 3 桁以上の数1000(=10010) で割った答えが 0 でなければ、 4 桁以上の数…と割る数を順次 10 倍し、答えが 0 でない限り計算を続ける。答えが初めて 0 になったときを見つける。

10 で割った答えが 0 でなければ、 2 桁以上の数 100(=1010) で割った答えが 0 でなければ、 3 桁以上の数1000(=10010) で割った答えが 0 でなければ、 4 桁以上の数…と割る数を順次 10 倍し、答えが 0 でない限り計算を続ける。答えが初めて 0 になったときを見つける。

ループ回数 y x/y keta

1 10 1234567 1

2 100 123456 2

3 1000 12345 3

4 10000 1234 4

5 100000 123 5

6 1000000 12 6

7 10000000 1 7

8 100000000 0 8

引数に 12345678 が渡された時のループの様子整数どうしの割り算は小数点以下は切り捨てられる

int digits(int x){ int keta = 1 , y = 10;

while((x / y) > 0){ y *= 10; keta++; } return keta;}

int digits(int x){ int keta = 1 , y = 10;

while((x / y) > 0){ y *= 10; keta++; } return keta;}

xをyで割った答えが0以外の間以下の処理 yを10倍する ( つまり今度は一桁上を見る) 桁数に1加える

xをyで割った答えが0以外の間以下の処理 yを10倍する ( つまり今度は一桁上を見る) 桁数に1加える

右表はこの時点の値

初期値として 桁数=1,y=10とする

初期値として 桁数=1,y=10とする

ループここまで関数の値として桁数をリターン

ループここまで関数の値として桁数をリターン

数が一桁の場合は一度もループに入らな

kohei
100->1000に修正
Page 13: プログラミング入門 第1 4 回講義

Prog-0 2013 Lec14-13Copyright (C) 1999 – 2013 by Programming-0 Group

#include<stdio.h>

int digits(int);

main(){ int i, j; scanf("%d",&i); j = digits(i); printf("%d の桁数は %d です\ n",i,j); }

int digits(int x){ int keta = 1 , y = 10 ;

while((x / y) > 0){ y *= 10; keta++; } return keta;}

#include<stdio.h>

int digits(int);

main(){ int i, j; scanf("%d",&i); j = digits(i); printf("%d の桁数は %d です\ n",i,j); }

int digits(int x){ int keta = 1 , y = 10 ;

while((x / y) > 0){ y *= 10; keta++; } return keta;}

実行結果std1dc1{s1000000}1: ./a.out1234567812345678 の桁数は 8 ですstd1dc1{s1000000}2:

実行結果std1dc1{s1000000}1: ./a.out1234567812345678 の桁数は 8 ですstd1dc1{s1000000}2:

  プログラムと実行結果  プログラムと実行結果

/home/course/prog0/public_html/2013/lec/source/lec14-3.c/home/course/prog0/public_html/2013/lec/source/lec14-3.c

43

Page 14: プログラミング入門 第1 4 回講義

Prog-0 2013 Lec14-14Copyright (C) 1999 – 2013 by Programming-0 Group

関数の例 3 :ある桁の数を知る (1)

関数の例 3 :ある桁の数を知る (1)

入力された数字の指定された桁の数を返す関数を作る  (例えば、 654321 の下から2桁目は2)受け渡しの要件:2入力・1出力二つの入力:

データ ⇨ int 型桁数  ⇨ int 型

結果(その桁の数) ⇨ int 型関数名は get_1_digit とした。この関数のプロトタイプ宣言は以下のようになる。

int get_1_digit(int,int);

データ 桁数

Page 15: プログラミング入門 第1 4 回講義

Prog-0 2013 Lec14-15Copyright (C) 1999 – 2013 by Programming-0 Group

ある桁の数を知る (2)ある桁の数を知る (2)

例えば 654321 の(下から)2桁目は2   654321 % 100 = 21

   21 / 10 = 2

つまり 求める数 =  ( データ % 10桁数 ) / 10 ( 桁数ー1 )

10 ( 桁数ー1 ) をどう作るか?  ⇨ 10を(桁数ー1)回掛け合わせる(ループにて)

5

剰余算

Page 16: プログラミング入門 第1 4 回講義

Prog-0 2013 Lec14-16Copyright (C) 1999 – 2013 by Programming-0 Group

#include<stdio.h>

int get_1_digit(int, int);

main(){ int i, j = 2, result; scanf("%d",&i); result = get_1_digit(i, j); printf("%d の %d 桁目は %d です\n",i,j,result);}

int get_1_digit(int x, int pos){ int i, j, k = 1;

for(i = 1 ; i < pos ; i++){ k *= 10; } j = x % (k * 10) / k; return j;}

#include<stdio.h>

int get_1_digit(int, int);

main(){ int i, j = 2, result; scanf("%d",&i); result = get_1_digit(i, j); printf("%d の %d 桁目は %d です\n",i,j,result);}

int get_1_digit(int x, int pos){ int i, j, k = 1;

for(i = 1 ; i < pos ; i++){ k *= 10; } j = x % (k * 10) / k; return j;}

実行結果std1dc1{s1000000}1: ./a.out654321654321 の 2 桁目は 2 ですstd1dc1{s1000000}2:

実行結果std1dc1{s1000000}1: ./a.out654321654321 の 2 桁目は 2 ですstd1dc1{s1000000}2:

  プログラムと実行結果  プログラムと実行結果

10(桁数ー1)のためのループ10(桁数ー1)のためのループ

(データ%10桁数) / 10(桁数ー1)の計算

(データ%10桁数) / 10(桁数ー1)の計算

/home/course/prog0/public_html/2013/lec/source/lec14-4.c/home/course/prog0/public_html/2013/lec/source/lec14-4.c

Page 17: プログラミング入門 第1 4 回講義

Prog-0 2013 Lec14-17Copyright (C) 1999 – 2013 by Programming-0 Group

10進数 : 10本指の人間が理解しやすい 14(10) = 1×101+ 4×100

2進数  : コンピュータが理解出来る(スイッチの on/offとして) 1110(2) = 1×23+ 1×22 + 1×21+ 0×20 = 14(10)

X進数の「X]のことを基数と呼ぶ。0からカウントアップし、基数になると桁上げが起こる。2進数は0、1と来て、2になると桁上げが起こり10になる。

コンピュータの内部では、命令もデータも全て 0/1 の列( 2進数)で表現される→詳細は後期、「コンピュータシステム概論」で学ぶ32ビット( 32個の 0/1 の系列)で表現できる最大の数232=4294967296=約 43億→ 138年(一秒ごとにひとつカウントした場合)

例4の前に: 2 進数と 10 進数例4の前に: 2 進数と 10 進数

Page 18: プログラミング入門 第1 4 回講義

Prog-0 2013 Lec14-18Copyright (C) 1999 – 2013 by Programming-0 Group

関数の例4:2進数から10進数への変換 (1)

関数の例4:2進数から10進数への変換 (1)

入力された数字を2進数とみなして10進数に変換するプログラム(これまで作った関数を使う)構成

main

digits  (桁数を求める)get_1_digit  (数のうち一桁だけを取り出す)

main() で行うこと:0が入力されるまで無限ループで数を読み込む2進数から10進数への変換(次ページ)

Page 19: プログラミング入門 第1 4 回講義

Prog-0 2013 Lec14-19Copyright (C) 1999 – 2013 by Programming-0 Group

2進数から10進数への変換 (2)2進数から10進数への変換 (2)各桁の重みと各桁の数をかけた物を加え合わす 例: 101011 (2進数) ⇨ 43 25*1+24*0+23*1+22*0+21*1+20*1 = 43

処理:

keta = digits(data)total = 0;exp = 1;for(i = 1 ; i <= keta ; i++){ n = get_1_digit(data, i); total += n * exp; exp *= 2;}

keta = digits(data)total = 0;exp = 1;for(i = 1 ; i <= keta ; i++){ n = get_1_digit(data, i); total += n * exp; exp *= 2;}

桁数を求める (digits を使用 )合計を0にする。桁の重みの初期値を20(=1)にする桁数回ループして各桁について計算する

その桁の数を求める (get_1_digit を使用 )桁の重みと桁の数(0または1)を掛けて合計に足し込む次のループに備えて次の桁の重みを計算する(重みを2倍する)

ループここまで

桁数を求める (digits を使用 )合計を0にする。桁の重みの初期値を20(=1)にする桁数回ループして各桁について計算する

その桁の数を求める (get_1_digit を使用 )桁の重みと桁の数(0または1)を掛けて合計に足し込む次のループに備えて次の桁の重みを計算する(重みを2倍する)

ループここまで

n exp total

1 1 1

1 2 3

0 4 3

1 8 11

0 16 11

1 32 43この場所での値

ループの様子

計算順序

Page 20: プログラミング入門 第1 4 回講義

Prog-0 2013 Lec14-20Copyright (C) 1999 – 2013 by Programming-0 Group

#include<stdio.h>#include<stdlib.h>int digits(int);int get_1_digit(int, int);main(){ int data, keta, i, n, exp, total; while(1){ /* データ読み込みとチェック */ printf(" 8桁以下の2進数を入力 ==> "); scanf("%d",&data); if (data == 0) exit(0); if (data > 11111111 || data < 0){ printf(" 変換出来る範囲を越えています\ n"); continue; } /* 桁数計算 */ keta = digits(data); /* 10進数に変換 */ total = 0; exp = 1; for(i = 1 ; i <= keta ; i++){ n = get_1_digit(data, i); if((n != 0) && (n != 1)){ /* データチェック */ printf(" データが0か1ではありません\ n"); exit(8); } total += n * exp; exp *= 2; } printf(" 2進 : %d -> 10進 : %d \ n",data,total); }}

#include<stdio.h>#include<stdlib.h>int digits(int);int get_1_digit(int, int);main(){ int data, keta, i, n, exp, total; while(1){ /* データ読み込みとチェック */ printf(" 8桁以下の2進数を入力 ==> "); scanf("%d",&data); if (data == 0) exit(0); if (data > 11111111 || data < 0){ printf(" 変換出来る範囲を越えています\ n"); continue; } /* 桁数計算 */ keta = digits(data); /* 10進数に変換 */ total = 0; exp = 1; for(i = 1 ; i <= keta ; i++){ n = get_1_digit(data, i); if((n != 0) && (n != 1)){ /* データチェック */ printf(" データが0か1ではありません\ n"); exit(8); } total += n * exp; exp *= 2; } printf(" 2進 : %d -> 10進 : %d \ n",data,total); }}

int digits(int x){ int keta = 1 , k = 10;

while((x / k) > 0){ k *= 10; keta++; } return keta;}

int get_1_digit(int x, int pos){ int i, j, k = 1;

for(i = 1 ; i < pos ; i++){ k *= 10; } j = x % (k * 10) / k; return j;}

int digits(int x){ int keta = 1 , k = 10;

while((x / k) > 0){ k *= 10; keta++; } return keta;}

int get_1_digit(int x, int pos){ int i, j, k = 1;

for(i = 1 ; i < pos ; i++){ k *= 10; } j = x % (k * 10) / k; return j;}

右に続く⇨

⇨左から続く

   2進数→ 10 進数変換プログラム

   2進数→ 10 進数変換プログラム

/home/course/prog0/public_html/2013/lec/source/lec14-6{a,b,c,d}.c/home/course/prog0/public_html/2013/lec/source/lec14-6{a,b,c,d}.c

8

lec14-6a.c が記載されたプログラム。後は様々なバリエーション

Page 21: プログラミング入門 第1 4 回講義

Prog-0 2013 Lec14-21Copyright (C) 1999 – 2013 by Programming-0 Group

std1dc1{s1000000}1: ./a.out8桁以下の2進数を入力 ==> 1010112進 : 101011 -> 10進 : 438桁以下の2進数を入力 ==> 101010101変換出来る範囲を越えています8桁以下の2進数を入力 ==> -101変換出来る範囲を越えています8桁以下の2進数を入力 ==> 10123データが0か1ではありませんstd1dc1{s1000000}2: echo $status8std1dc1{s1000000}3:

std1dc1{s1000000}1: ./a.out8桁以下の2進数を入力 ==> 1010112進 : 101011 -> 10進 : 438桁以下の2進数を入力 ==> 101010101変換出来る範囲を越えています8桁以下の2進数を入力 ==> -101変換出来る範囲を越えています8桁以下の2進数を入力 ==> 10123データが0か1ではありませんstd1dc1{s1000000}2: echo $status8std1dc1{s1000000}3:

実行例実行例

9

cshの場合

Page 22: プログラミング入門 第1 4 回講義

Prog-0 2013 Lec14-22Copyright (C) 1999 – 2013 by Programming-0 Group

エラーチェックエラーチェック

エラーチェックとは 予想される間違いを検出 すること前述の例4のプログラムの場合、以下のような入力誤りが予想される

負の数が入力される(例:-101)1 桁の数が入力される(例:8)

エラーを検出した場合はエラーに応じた処理を行う(「エラー処理」と言う)エラーの重大さによって、処理が異なることがある(例えば軽度なエラーは処理を続行させ、重度なエラーは処理を中止するなど)例4のプログラムの場合

負の数だった場合:「変換出来る範囲を越えています」と表示して再度データ入力からやり直す1桁の数だった場合、「データが適切ではありません」と表示してプログラムを強制終了させる。(強制終了は次ページ参照)

エラーチェックをしっかりしておくとプログラムの誤動作を未然に防ぐことが出来る 7

6

Page 23: プログラミング入門 第1 4 回講義

Prog-0 2013 Lec14-23Copyright (C) 1999 – 2013 by Programming-0 Group

  プログラムの強制終了  プログラムの強制終了プログラムの強制終了の方法

<stdlib.h> をインクルードする。exit( 整数 );  で どこからでもプログラムを強制終了させることが出来る。プログラム実行後、この引数はシェル変数に渡される(例えば tcsh だと「 $?」、 csh だと 「 $status」 というシェル変数に格納される)シェル変数の制約により渡せる引数は 0~ 255 までの整数のみに限られる。このようにプログラムからシェル変数に値が渡る事で、

値によってエラーの理由を知ることが出来るシェルスクリプトを使用して値によって動作を変える事が可能

例えば以下のような非常に簡単なプログラム (exit(8);で強制終了)の実行終了後 $statusを見ると8という数字が入っていることが分かる。

#include <stdio.h>#include <stdlib.h>

main(){ exit(8);}

#include <stdio.h>#include <stdlib.h>

main(){ exit(8);}

実行結果 (csh の場合)std1dc1{s1000000}1: ./a.outstd1dc1{s1000000}2: echo $status8std1dc1{s1000000}3:

実行結果 (csh の場合)std1dc1{s1000000}1: ./a.outstd1dc1{s1000000}2: echo $status8std1dc1{s1000000}3:

/home/course/prog0/public_html/2013/lec/source/lec14-5.c/home/course/prog0/public_html/2013/lec/source/lec14-5.c

Page 24: プログラミング入門 第1 4 回講義

Prog-0 2013 Lec14-24Copyright (C) 1999 – 2013 by Programming-0 Group

  補足:10進数から2進数への変換  補足:10進数から2進数への変換

なお、10進数から2進数への変換は以下のようなプログラムによって行う事が出来る。

#include<stdio.h>main(){ unsigned int data; int bin[32], i; printf(" 10進数を入力 ==> "); scanf("%u",&data); for(i = 0; i < 32; i++){ bin[31 - i] = data % 2; data /= 2; } for(i = 0; i < 32; i++){ printf("%1d",bin[i]); } printf(" \ n");}

#include<stdio.h>main(){ unsigned int data; int bin[32], i; printf(" 10進数を入力 ==> "); scanf("%u",&data); for(i = 0; i < 32; i++){ bin[31 - i] = data % 2; data /= 2; } for(i = 0; i < 32; i++){ printf("%1d",bin[i]); } printf(" \ n");}

#include<stdio.h>

main(){ unsigned int data; int i; printf(" 10進数を入力 ==> "); scanf("%u",&data);

for(i = 0; i < 32; i++){ printf("%1d",(data >> (31 - i)) & 1); } printf(" \ n");}

#include<stdio.h>

main(){ unsigned int data; int i; printf(" 10進数を入力 ==> "); scanf("%u",&data);

for(i = 0; i < 32; i++){ printf("%1d",(data >> (31 - i)) & 1); } printf(" \ n");}

配列を使用 シフト演算子を使用

/home/course/prog0/public_html/2013/lec/source/lec14-7{a,b,c}.c/home/course/prog0/public_html/2013/lec/source/lec14-7{a,b,c}.c