• 検索結果がありません。

C言語入門

N/A
N/A
Protected

Academic year: 2021

シェア "C言語入門"

Copied!
45
0
0

読み込み中.... (全文を見る)

全文

(1)

C言語入門

第7週

プログラミング言語Ⅰ(実習を含む。),

計算機言語Ⅰ・計算機言語演習Ⅰ,

(2)

前回の復習

(3)

連立一次方程式を行列で計算する

• 吐き出し法(ガウスの消去法)

• ステップ1: 前進消去(上三角行列の作成)

gaussian_elimination1.c // step1 for (k = 0; k < M - 1; k++) { for (i = k + 1; i < M; i++) { x = a[i][k] / a[k][k]; for (j = 0; j < N; j++) {

a[i][j] = a[i][j] - a[k][j] * x; } b[i] = b[i] - b[k] * x; } } まずどこで ピボッティング処理するのが 良いのか考える 少なくとも、a[k][k]で割る 前でないと意味がないので 候補はこの3か所

(4)

連立一次方程式を行列で計算する

• 吐き出し法(ガウスの消去法)

• ステップ1: 前進消去(上三角行列の作成)

gaussian_elimination1.c // step1 for (k = 0; k < M - 1; k++) { for (i = k + 1; i < M; i++) { x = a[i][k] / a[k][k]; for (j = 0; j < N; j++) {

a[i][j] = a[i][j] - a[k][j] * x; } b[i] = b[i] - b[k] * x; } } k毎に処理しないと いけないので一番上は除外 k毎に処理しておけば i毎に処理する必要はない 従って一番下も除外 結果、真ん中が最適 と言うことになる

(5)

ピボッティング

• a[k][k] が 0 か調べる

gaussian_elimination1.c // step1 for (k = 0; k < M - 1; k++) { if (a[k][k] == 0) { // この場合にピボッティングする必要がある } for (i = k + 1; i < M; i++) { x = a[i][k] / a[k][k]; for (j = 0; j < N; j++) {

a[i][j] = a[i][j] - a[k][j] * x; }

b[i] = b[i] - b[k] * x; }

(6)

ピボッティング

• k+1行目以降でk列目が 0 でない行を探す

gaussian_elimination1.c // step1 for (k = 0; k < M - 1; k++) { if (a[k][k] == 0) { for (i = k + 1; i < M; i++) { // ここでa[i][k]が0でない行を探す } } // ... }

(7)

ピボッティング

• 目的の行を見つけた際の処理を書く

gaussian_elimination1.c // step1 for (k = 0; k < M - 1; k++) { if (a[k][k] == 0) { for (i = k + 1; i < M; i++) { if (a[i][k] != 0) { // 目的の行を見つけた際の処理を書く } } } // ... } 授業では最初ここを a[i][k] == 0 としていたので、 上手く動いていませんでした。

(8)

ピボッティング

• k行とi行の各列で値を交換する

gaussian_elimination1.c // step1 for (k = 0; k < M - 1; k++) { if (a[k][k] == 0) { for (i = k + 1; i < M; i++) { if (a[i][k] != 0) { for (j = 0; j < N; j++) { // k行とi行の各列でaの値を交換する処理 } // k行とi行でbの値を交換する処理 } } } // ... }

(9)

ピボッティング

• 暫定的に完成したピボッティング

gaussian_elimination1.c if (a[k][k] == 0) { for (i = k + 1; i < M; i++) { if (a[i][k] != 0) { float tmp; for (j = 0; j < N; j++) { tmp = a[k][j]; a[k][j] = a[i][j]; a[i][j] = tmp; } tmp = b[k]; b[k] = b[i]; b[i] = tmp; } } } なぜ暫定的かと言うと このままだと、 二重にピボッティングする事もある。 実害はないが無駄な処理なので ピボッティングに成功したら そこでピボッティングの処理を 打ち切るほうが効率的。

(10)

繰り返し(ループ)の復習

(11)

ループの再開と脱出

• continue 文

• while, do while, for 文内で使用可能

• 以降の処理を中断してループを再開する

• for文では後処理(第3パラメータ)も実行する

• break 文

• while, do while, for, switch 文内で使用可能

• 以降の処理を中断してループを脱出する

• switch文の場合はswitch文から脱出する

continue 文の

2つ目の説明が微妙に間違ってました

正しくはループ末尾から再開

8週資料参照

(12)

後判定ループ (do while 文)

• 真偽値による繰り返し

do {

// 条件式 が真の場合の処理

} while (条件式);

条件式 処理 真 偽 do while 文は、ループ内の処理を 最低1回は実行する。 教科書 p.123. continue break

do while 文内の

continue 文で

飛ぶ先が間違ってました

正しくは次項または

8週資料参照

(13)

後判定ループ (do while 文)

• 真偽値による繰り返し

do {

// 条件式 が真の場合の処理

} while (条件式);

条件式 処理 真 偽 do while 文は、ループ内の処理を 最低1回は実行する。 教科書 p.123. continue break

(14)

初期化・更新処理付きループ (for 文)

• 真偽値による繰り返し

for (式1; 式2; 式3) {

// 式2が真の場合の処理

};

式2 式1 真 偽 前判定ループだが 式1による初期化と 式3による更新処理を ひとまとめにして書ける。 処理 式3 教科書 pp.124-129. continue break

(15)

for文とwhile文 (前判定ループ)

• 以下のループは等価

• continue時の式3の扱いに注意

for (式1; 式2; 式3) {

// 式2が真の場合の処理

};

式2 式1 真 偽 処理 式3 教科書 pp.123-129. for文の continue break

式1;

while (式2) {

// 式2が真の場合の処理

式3;

};

while文の continue

(16)

for文とwhile文 (前判定ループ)

• 以下のループは等価

• continue時の式3の扱いに注意

for (i = 0; i < 10; i++) {

// ループ内の処理

};

i < 10 i = 0 真 偽 処理 i++ 教科書 pp.123-129. for文の continue break

i = 0;

while (i < 10) {

//ループ内の処理

i++;

};

while文の continue

(17)

後判定ループ (do while 文)

• continue, break 後の処理(iの値)に注目

looptest_dowhile.c int i = 0, j = 0, n; fprintf(stderr, "n = "); scanf("%d", &n); do { j++; printf("%d, %d: 1st", i, j);

if (j == 2) {printf(" continue¥n"); continue;} printf(" 2nd");

if (j == 4) {printf(" break¥n"); break;} printf(" 3rd¥n"); i++; } while (i < n); 教科書 pp.119-122. mintty + bash $ ./looptest_dowhile n = 10 0, 1: 1st 2nd 3rd 1, 2: 1st continue 1, 3: 1st 2nd 3rd 2, 4: 1st 2nd break mintty + bash $ ./looptest_dowhile n = 0 0, 1: 1st 2nd 3rd do while 文は、 ループ内の処理を 最低1回は実行する。

(18)

前判定ループ (while 文)

• continue, break 後の処理(iの値)に注目

looptest_while.c int i = 0, j = 0, n; fprintf(stderr, "n = "); scanf("%d", &n); while (i < n) { j++; printf("%d, %d: 1st", i, j);

if (j == 2) {printf(" continue¥n"); continue;} printf(" 2nd");

if (j == 4) {printf(" break¥n"); break;} printf(" 3rd¥n"); i++; } 教科書 p.123. mintty + bash $ ./looptest_while n = 10 0, 1: 1st 2nd 3rd 1, 2: 1st continue 1, 3: 1st 2nd 3rd 2, 4: 1st 2nd break mintty + bash $ ./looptest_while n = 0

(19)

初期化・更新処理付きループ (for 文)

• continue, break 後の処理(iの値)に注目

looptest_for.c int i = 0, j = 0, n; fprintf(stderr, "n = "); scanf("%d", &n); for (i = 0; i < n; i++) { j++; printf("%d, %d: 1st", i, j);

if (j == 2) {printf(" continue¥n"); continue;} printf(" 2nd");

if (j == 4) {printf(" break¥n"); break;} printf(" 3rd¥n"); } 教科書 pp.124-129. mintty + bash $ ./looptest_for n = 10 0, 1: 1st 2nd 3rd 1, 2: 1st continue 2, 3: 1st 2nd 3rd 3, 4: 1st 2nd break mintty + bash $ ./looptest_for n = 0

(20)
(21)

コマンドライン引数

• main 関数の引数として取得出来る。

argtest.c

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

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

int i;

printf("argc = %d¥n", argc); for (i = 0; i < argc; i++) {

printf("argv[%d] = ¥"%s¥"¥n", i, argv[i]); } return EXIT_SUCCESS; } main の引数名は 自由につけて良いが 以下の名前を使うのが 慣例になっている

argc: ARGument Count argv: ARGument Vector 教科書 pp.265-272.

[1] pp.139-144.

argument は英語で 引数を意味する

(22)

コマンドライン引数

• main 関数の引数として取得出来る。

コマンドプロンプト >argtest a b "c d" "e¥"f" argc = 5 argv[0] = "C:¥Users¥kou¥Desktop¥CLangI2014S1¥argtest.exe" argv[1] = "a" argv[2] = "b" argv[3] = "c d" argv[4] = "e"f" mintty + bash $ ./argtest a b "c d" "e¥"f" argc = 5 argv[0] = "./argtest" argv[1] = "a" argv[2] = "b" argv[3] = "c d" argv[4] = "e"f" 教科書 pp.265-272. [1] pp.139-144. コマンドライン空白で分割されて argvに格納される。 argvに空白を含めたい場合は 「"」(ダブルクォーテーション)で囲む 「"」を含めたい場合は「¥」でエスケープする argv[0]は実行中のコマンド名

(23)

標準入出力と標準エラー出力

• 以下の入出力が利用できる

• stdin: STanDard INput:

標準入力

• stdout: STanDard OUTput:

標準出力

• stderr: STanDard ERRor output: 標準エラー出力

• scanf や getchar 等は stdin から入力している

• printf や putchar 等は stdout へ出力している

• stdin, stdout はパイプやリダイレクトの対象だ

が stderr は標準では対象外

(24)

標準入出力と標準エラー出力

• パイプやリダイレクトで処理されたくない内容

は stderr へ出力する

• fscanf や fprintf を使うと、入出力先を自由に

選択出来る

[1] pp.196, 199, 218. stdiotest.c

printf("output to stdout with printf¥n");

fprintf(stdout, "output to stdout with fprintf¥n"); fprintf(stderr, "output to stderr with fprintf¥n"); mintty + bash

$ ./stdiotest > redirect.txt output to stderr with fprintf $ cat redirect.txt

output to stdout with printf output to stdout with fprintf

(25)

標準入出力と標準エラー出力

• stdin,stdout,stderrはstdio.hで定義されている

• stdio.h は standard input / output header

(26)

fprintf 関数

• int fprintf(FILE *fp,

const char *FORMAT, ...);

• printfの結果をfpへ書き出す

• 引数:

• fp:

FILE 構造体へのポインタ

• FORMAT:

書式

• ...:

任意の数の引数

• 戻り値:

• 書き出された文字数

• エラーの場合負の数

教科書 pp.61, 64-66, 98, 300. 参考: [1] pp.305-306.

(27)

fscanf 関数

• int fscanf(FILE *fp,

const char *FORMAT, ...);

• fpからデータを読み込む

• 引数:

• fp:

FILE 構造体へのポインタ

• FORMAT:

書式

• ...:

任意の数の引数

値を格納する変数へのポインタ

• 戻り値:

• 変換され代入された入力項目の数

• ファイル終端またはエラーの場合EOF

教科書 pp.80-83, 254. 参考: [1] pp.307-309.

(28)

fopen 関数

• FILE *fopen(const char *filename,

const char *mode);

• ファイルを開き、FILE構造体へのポインタを得る

• 引数:

• filename: ファイル名(パス)の文字列

• mode:

ファイルを開くモード

• 戻り値:

• FILE 構造体へのポインタ

• エラーの場合 NULL

教科書 pp.298-305. 参考: [1] pp.194-198.

(29)

fopen 関数の mode

mode 読み込み 書き込み 動作 "r" 任意の位置 × ファイルを開く、存在しない場合エラー "w" × 任意の位置 ファイルを作成し、前の内容は消去する "a" × ファイル末尾 ファイルを開く、または作成 "r+" 任意の位置 任意の位置 ファイルを開く、存在しない場合エラー "w+" 任意の位置 任意の位置 ファイルを作成し、前の内容は消去する "a+" 任意の位置 ファイル末尾 ファイルを開く、または作成 教科書 pp.298-305. 参考: [1] pp.194-198. "r", "w", "a", "r+", "w+", "a+" はテキストモードで読み書きする テキストモードでは改行コード(¥n)の扱いが環境によって異なる • Windows: CR LF (0xd 0xa) • Mac: CR (0xd) • UNIX: LF (0xa) バイナリモードにするには、"rb", "wb", "ab", "r+b", "w+b", "a+b" のように "b" を追加する

(30)

fclose 関数

• int fclose(FILE *fp);

• ファイルを閉じます

• 引数:

• fp:

FILE構造体へのポインタ

• 戻り値:

• 0 を返す

• エラーの場合 EOF を返す

教科書 pp.298-305. 参考: [1] pp.194-198.

(31)
(32)

演習: print_0.c

• 0を表示せよ

• 数値の直後で改行すること

コマンドプロンプト

>print0

0

>

(33)

演習: print_dec.c

• scanf関数を用いてキーボードから入力され

た整数をint型の変数iに読み込み10進数と

して表示せよ

• i を入力する前に「i = 」と

標準エラー出力に表示する事

第3週資料 pp.23-33, 34-42. mintty + bash $ ./print_dec i = 123 123

(34)

演習: print_octdechex.c

• scanf関数を用いてキーボードから入力された

8,10,16進数の整数をint型の変数iに読み込

み8,10,16進数の3種類の表示せよ

• i を入力する前に「i = 」と

標準エラー出力に表示する事

• 8進数表示の前には0を表示せよ

• 16進数表示の前には0xを表示せよ

• 各数値は幅6桁で右寄せで表示し

末尾は改行すること

8,16進数頭の0,0xは6桁に含める

第3週資料 pp.23-33, 34-42. mintty + bash $ ./print_octdechex i = 0123 0123 83 0x53 $ ./print_octdechex i = 123 0173 123 0x7b $ ./print_octdechex i = 0x123 0443 291 0x123

(35)

演習: print_evenodd.c

• iが偶数か奇数か調べ以下の文字列を

printf関数に与えて表示せよ

• 偶数の場合: "even number¥n"

• 奇数の場合: "odd number¥n"

• print_evenodd_tmp.c を

print_evenodd.c にコピーし

指定の場所に作成する事

mintty + bash $ ./print_evenodd i = 1 odd number mintty + bash $ ./print_evenodd i = 2 even number

(36)

演習: print_natural_lt.c

• n未満の非負整数(0を含む自然数)を小さい

順に全て表示せよ

• 各数値の直後で改行すること

• 変数はi,nのみを使うこと

• print_natural_lt_tmp.c を

元に、指定の場所に作成する事

mintty + bash $ ./print_natual_lt n = 10 0 1 2 3 4 5 6 7 8 9

(37)

演習: print_even_lt.c

• 0以上n未満の偶数を小さい順に全て表示せ

• 各数値の直後で改行すること

• 変数はi,nのみを使うこと

• print_even_lt_tmp.c を

元に、指定の場所に作成する事

mintty + bash $ ./print_even_lt n = 20 0 2 4 6 8 10 12 14 16 18

(38)

素数

• 1と自分以外に正の約数を持たない自然数

(正整数)で1でない数

• 調べたい数をiとすると、2以上i/2以下の整

数jの全てについてiが割り切れないことを確

認すれば良い。

(39)

演習: print_isprime.c

• iが素数かどうか調べ以下の文字列をprintf関数に

与えて表示せよ

• 非素数: "not prime number¥n"

• 素数: "prime number¥n"

• 変数はi,j,primeのみを使う事

• 変数は以下の目的で使う事

• i: 素数かどうか調べたい数

• j: 2以上i/2以下の正数

• prime: 素数判定用のフラグ

0=非素数,1=素数

• print_isprime_tmp.c を元に

指定の位置に作成せよ

mintty + bash $ ./print_prime_lt n = 2 $ ./print_isprime i = 2 prime number $ ./print_isprime i = 3 prime number $ ./print_isprime i = 5 prime number $ ./print_isprime i = 7 prime number $ ./print_isprime i = 11 prime number

(40)

演習: print_isprime.c

• 非素数の場合も確認

mintty + bash

$ ./print_isprime i = 4

not prime number $ ./print_isprime i = 6

not prime number $ ./print_isprime i = 8

not prime number $ ./print_isprime i = 9

not prime number $ ./print_isprime i = 10

not prime number

mintty + bash

$ ./print_isprime i = -1

not prime number $ ./print_isprime i = 0

not prime number $ ./print_isprime i = 1

not prime number

負の場合、 0及び1の場合 合成数の場合

(41)

演習: print_prime_lt.c

• n未満の素数を小さい順に全て表示せよ

• 各数値の直後で改行すること

• 変数はi,j,n,primeのみを使う事

• 変数は以下の目的で使う事

• i: 素数かどうか調べたい数

• j: 2以上i/2以下の数

• prime: 素数判定用のフラグ

• print_prime_lt_tmp.cを元に

指定の位置に作成せよ

mintty + bash $ ./print_prime_lt n = 30 2 3 5 7 11 13 17 19 23 29

(42)

フィボナッチ数列

• いわゆる黄金比の数列

𝐹

0

= 0

𝐹

1

= 1

(43)

演習:

print_fibonacci_n.c

フィボナッチ数列

のうち最小のn個を小さい順に

表示せよ

• 各数値の直後で改行すること

• 変数は f0, f1, f2, i, n のみを使うこと

• 各変数は以下の用途で用いる事

• f0 = 𝐹

𝑖

• f1 = 𝐹

𝑖+1

• f2 = 𝐹

𝑖+2

• iは上記𝐹

𝑖

の添え字の意味で0~n-1

までの整数

mintty + bash $ ./print_fibonacci_n n = 10 0 1 1 2 3 5 8 13 21 34

(44)

演習:

print_fibonacci_lt.c

• n未満の

フィボナッチ数列

を小さい順に全て表示

せよ

• 各数値の直後で改行すること

• 変数は f0, f1, f2, n のみを使うこと

• 各変数は以下の用途で用いる事

• f0 = 𝐹

𝑖

• f1 = 𝐹

𝑖+1

• f2 = 𝐹

𝑖+2

mintty + bash $ ./print_fibonacci_lt n = 40 0 1 1 2 3 5 8 13 21 34

(45)

参考文献

• [1] B.W.カーニハン/D.M.リッチー著 石田晴久

訳、プログラミング言語C 第2版 ANSI 規格準

拠、共立出版(1989)

参照

関連したドキュメント

左側の例では、 MSFC またはルータは VLAN 201 、 301 、 302 、および 303 の間をルーティングしま

one-way ticket 片道チケット return ticket 帰りのチケット round trip ticket 往復チケット immigration 入国審査 boarding pass 搭乗券 boarding time

「橋中心髄鞘崩壊症」は、学術的に汎用されている用語である「浸透圧性脱髄症候群」に変更し、11.1.4 を参照先 に追記しました。また、 8.22 及び 9.1.3 も同様に変更しました。その他、

○ 4番 垰田英伸議員 分かりました。.

②立正大学所蔵本のうち、現状で未比定のパーリ語(?)文献については先述の『請来資料目録』に 掲載されているが

参加者は自分が HLAB で感じたことをアラムナイに ぶつけたり、アラムナイは自分の体験を参加者に語っ たりと、両者にとって自分の

自然言語というのは、生得 な文法 があるということです。 生まれつき に、人 に わっている 力を って乳幼児が獲得できる言語だという え です。 語の それ自 も、 から

下山にはいり、ABさんの名案でロープでつ ながれた子供たちには笑ってしまいました。つ