CプログラミングI

Similar documents
C プログラミング演習 1( 再 ) 2 講義では C プログラミングの基本を学び 演習では やや実践的なプログラミングを通して学ぶ

Microsoft PowerPoint - 11.pptx

今回のプログラミングの課題 ( 前回の課題で取り上げた )data.txt の要素をソートして sorted.txt というファイルに書出す ソート (sort) とは : 数の場合 小さいものから大きなもの ( 昇順 ) もしくは 大きなものから小さなもの ( 降順 ) になるよう 並び替えること

プログラミング実習I

関数の呼び出し ( 選択ソート ) 選択ソートのプログラム (findminvalue, findandreplace ができているとする ) #include <stdiu.h> #define InFile "data.txt" #define OutFile "surted.txt" #def

gengo1-11

Microsoft PowerPoint - 計算機言語 第7回.ppt

バイオプログラミング第 1 榊原康文 佐藤健吾 慶應義塾大学理工学部生命情報学科

関数の呼び出し ( 選択ソート ) 選択ソートのプログラム (findminvalue, findandreplace ができているとする ) #include <stdio.h> #define InFile "data.txt" #define OutFile "sorted.txt" #def

Microsoft PowerPoint ppt

<4D F736F F D20438CBE8CEA8D758DC03389F0939A82C282AB2E646F63>

02: 変数と標準入出力

第2回

C言語7

7 ポインタ (P.61) ポインタを使うと, メモリ上のデータを直接操作することができる. 例えばデータの変更 やコピーなどが簡単にできる. また処理が高速になる. 7.1 ポインタの概念 変数を次のように宣言すると, int num; メモリにその領域が確保される. 仮にその開始のアドレスを 1

02: 変数と標準入出力

Microsoft PowerPoint - lec10.ppt

Microsoft PowerPoint - 06.pptx

Microsoft Word - no11.docx

情報処理Ⅰ演習

第1回 プログラミング演習3 センサーアプリケーション

Microsoft Word - no202.docx

PowerPoint プレゼンテーション

C プログラミング 1( 再 ) 第 4 回 講義では C プログラミングの基本を学び 演習では やや実践的なプログラミングを通して学ぶ 1

PowerPoint プレゼンテーション

Microsoft Word - no12.doc

コマンドラインから受け取った文字列の大文字と小文字を変換するプログラムを作成せよ 入力は 1 バイトの表示文字とし アルファベット文字以外は変換しない 1. #include <stdio.h> 2. #include <ctype.h> /*troupper,islower,isupper,tol

Microsoft Word - no02.doc

Microsoft PowerPoint - prog07.ppt

Microsoft PowerPoint - 09.pptx

02: 変数と標準入出力

PowerPoint プレゼンテーション

FORTRAN( と C) によるプログラミング 5 ファイル入出力 ここではファイルからデータを読みこんだり ファイルにデータを書き出したりするプログラムを作成してみます はじめに テキスト形式で書かれたデータファイルに書かれているデータを読みこんで配列に代入し 標準出力に書き出すプログラムを作り

Cプログラミング1(再) 第2回

Microsoft PowerPoint - 6.pptx

memo

プログラミング及び演習 第1回 講義概容・実行制御

memo

PowerPoint プレゼンテーション - 物理学情報処理演習

02: 変数と標準入出力

/* do-while */ #include <stdio.h> #include <math.h> int main(void) double val1, val2, arith_mean, geo_mean; printf( \n ); do printf( ); scanf( %lf, &v

PowerPoint Presentation

/*Source.cpp*/ #include<stdio.h> //printf はここでインクルードして初めて使えるようになる // ここで関数 average を定義 3 つの整数の平均値を返す double 型の関数です double average(int a,int b,int c){

02: 変数と標準入出力

次に示す数値の並びを昇順にソートするものとする このソートでは配列の末尾側から操作を行っていく まず 末尾の数値 9 と 8 に着目する 昇順にソートするので この値を交換すると以下の数値の並びになる 次に末尾側から 2 番目と 3 番目の 1

Microsoft PowerPoint - lec06 [互換モード]

講習No.12

PowerPoint プレゼンテーション

Microsoft PowerPoint - 13th.ppt [互換モード]

02: 変数と標準入出力

Microsoft Word - 3new.doc

情報処理 Ⅱ 2007 年 11 月 26 日 ( 月 )

02: 変数と標準入出力

PowerPoint プレゼンテーション

目次

情報工学実験 C コンパイラ第 2 回説明資料 (2017 年度 ) 担当 : 笹倉 佐藤

kiso2-09.key

Microsoft PowerPoint - C4(反復for).ppt

第2回講義:まとめ

Microsoft PowerPoint - prog06.ppt

PowerPoint プレゼンテーション

PowerPoint プレゼンテーション

Taro-再帰関数Ⅲ(公開版).jtd

Microsoft PowerPoint pptx[読み取り専用]

< F2D837C E95CF CF68A4A94C5816A2E6A>

今までの復習 プログラムで最低限必要なもの 入力 ( キーボードから ファイルから ) 出力 ( 画面へ ファイルへ ) 条件分岐 : 条件の成立 不成立により 異なる動作をする 繰り返し : 一定の回数の繰返し 条件成立の間の繰返し 関数の定義 関数の呼び出し C ではそれ以外に ポインタ データ

Taro-スタック(公開版).jtd

Microsoft PowerPoint - 第3回目.ppt [互換モード]

プログラム言語及び演習Ⅲ

Microsoft PowerPoint - exp2-02_intro.ppt [互換モード]

Microsoft PowerPoint - ruby_instruction.ppt

C言語講座

cp-7. 配列

memo

Microsoft PowerPoint - kougi2.ppt

講習No.9

プログラミング基礎I(再)

Prog1_10th

Microsoft Word - Training10_プリプロセッサ.docx

PowerPoint プレゼンテーション

PowerPoint プレゼンテーション - 物理学情報処理演習

プログラミング実習I

Microsoft PowerPoint - C_Programming(3).pptx

Microsoft Word - no15.docx

PowerPoint プレゼンテーション

関数の中で宣言された変数の有効範囲はその関数の中だけです さっきの rectangle _s で宣言されている変数 s は他の関数では使用できません ( 別の関数で同じ名前の変数を宣言することはできますが 全く別の変数として扱われます このように ある関数の中で宣言されている変数のことをその関数の

02: 変数と標準入出力

PowerPoint プレゼンテーション

Microsoft Word - no13.docx

02: 変数と標準入出力

char int float double の変数型はそれぞれ 文字あるいは小さな整数 整数 実数 より精度の高い ( 数値のより大きい より小さい ) 実数 を扱う時に用いる 備考 : 基本型の説明に示した 浮動小数点 とは数値を指数表現で表す方法である 例えば は指数表現で 3 書く

Microsoft Word - Cプログラミング演習(12)

Prog1_12th

02: 変数と標準入出力

Microsoft PowerPoint - kougi7.ppt

02: 変数と標準入出力

System.out.print 先段まで使用してきた上記 System/Math/String クラスは基本パッケージと呼ばれ,import 文の記述なしに提供されるクラス 2.2 BufferedReader クラスと例外処理 端末から文字列をプログラムに入力したい場合,java.io.Buff

プログラミング方法論 II 第 14,15 回 ( 担当 : 鈴木伸夫 ) 問題 17. x 座標と y 座標をメンバに持つ構造体 Point を作成せよ 但し座標 は double 型とする typedef struct{ (a) x; (b) y; } Point; 問題 18. 問題 17 の

18/12/06 情報工学実験 C コンパイラ (2018 年度 ) 担当 : 笹倉 佐藤 その 3 yacc の構造 定義部 %% 定義部の終了 規則部 %% 規則部の終了 ユーザ定義サブルーチン部 :C のプログラムを書く 形は lex と同じ 1

Transcription:

C プログラミング I Swap 関数を作る Stack データ構造のための準備

整数変数 x と y の値を取り替える関数 swap を作る 最初の試み : swap-01.c #include <stdio.h> void swap(int a, int b) { int tmp; tmp = a; a = b; b = tmp; int main(void) { int x=10, y=30; printf("before: x = %d, y = %d n", x, y); // 10, 30 と表示される swap(x, y); printf("after: x = %d, y = %d n", x, y); // 30, 10 と表示される? return 0;

これではうまくいかない 30 10 定義 : 呼出 : void swap(int a, int b) { int tmp; tmp = a; a = b; b = tmp; swap(x, y); 原因は (swap) 関数に渡される値にある a, bそれぞれに xとyの値が渡される swap 関数の中では確かに変数 aとbの値はswapされるが swap 関数を呼び出した (main) 関数内の変数 xとyの値が入れ替わるわけではない

そこで x と y のアドレスを渡す xとyのアドレス値を記憶する変数を px, py とすれば px = xのアドレスなので *px は xの値となる pyとyについても同様 そう考えると, 次のように関数を定義することが考えられる : void swap(int *a, int *b) { int tmp; tmp = *a; // *a(=x) の値を tmp で記憶 *a = *b; // *a (=x) の値を *b(=y) で書き換える *b = tmp; // *b (=y) の値を tmp の値で書き換える

試してみよう swap-01.c の swap 関数を書き換える : swap-02.c #include <stdio.h> 定義 : 呼出 : void swap(int *a, int *b) { int tmp; tmp = *a; // *a(=x) の値を tmp で記憶 *a = *b; // *a (=x) の値を *b(=y) で書き換える *b = tmp; // *b (=y) の値を tmp の値で書き換える int main(void) { int x=10, y=30; printf("before: x = %d, y = %d n", x, y); // 10, 30 と表示される swap(x,y); printf("after: x = %d, y = %d n", x, y); // 30, 10 と表示される? return 0;

その結果は コンパイルすると 次のようなエラーがでる ( はず ): エラー E2342 swaptemplate2.c 13: パラメータ 'a' は int * 型として定義されているので int は渡せない ( 関数 main ) エラー E2342 swaptemplate2.c 13: パラメータ 'b' は int * 型として定義されているので int は渡せない ( 関数 main ) *** 2 errors in Compile *** これは swap 関数が間違っているからではない

実は swap 関数の呼び出し エラーが起こるのは swap 関数の呼び出し swap(x,y); が間違いなのである このままだと何回やっても x と y の値が swap 関数に渡される しかし swap 関数に渡してほしいのは x と y のアドレス ( ポインタ ) である そこで swap(&x, &y); と直す必要がある ( 理由は分かるだろうか?) さあ書きなおして再度試してみよう

再チャレンジ #include <stdio.h> 定義 : 呼出 : void swap(int *a, int *b) { int tmp; tmp = *a; // *a(=x) の値を tmp で記憶 *a = *b; // *a (=x) の値を *b(=y) で書き換える *b = tmp; // *b (=y) の値を tmp の値で書き換える int main(void) { int x=10, y=30; printf("before: x = %d, y = %d n", x, y); // 10, 30 と表示される swap(&x, &y); printf("after: x = %d, y = %d n", x, y); // 30, 10 と表示される? return 0; 結果 : Before: x = 10, y = 30 After: x = 30, y = 10

参考 : 配列に対しても 定義は同じ : #include <stdio.h> void swap(int *a, int *b) { int tmp; tmp = *a; // *a(=x) の値を tmp で記憶 *a = *b; // *a (=x) の値を *b(=y) で書き換える *b = tmp; // *b (=y) の値を tmp の値で書き換える 注意 1: 浮動小数点数を swap するには int をすべて float とする注意 2: 文字列 ( 文字列の配列 ) にはこのままでは使えない 呼出 : int main(void) { int ar[ ] = {10, 30 ; // 配列 printf("before: ar[0] = %d, ar[1] = %d n", ar[0], ar[1]); // 10, 30 と表示される swap(&ar[0], &ar[1]); printf("after: ar[0] = %d, ar[1] = %d n", ar[0], ar[1]); // 30, 10 と表示される? return 0;

配列に似たデータ構造 : スタックとキュー スタック (stack) とはスタックは データの挿入 およびデータの取り出しが制限された配列 とみなせる 比較 : 配列 array を例にすれば array[10] とすると添字番号 10 番目の要素が取り出せ array[13]=100; とすれば添字番号 113 番目の要素を書き換えられる ( データの記憶が可能 ) このように 配列では 任意の場所のデータを取り出せ 任意の場所にデータを記憶できる それに対しスタックは 特定の位置 ( 多くは 最後 ) にしかデータを追加 もしくは取り出せないようになっている

スタックの操作 データの追加のための関数を push 最後の要素として追加される データの取り出しのための関数を pop 最後の要素が取り出され スタックから取り除かれる 見方を変えると 一番最後に入ってきたものが最初に取り出されるため Last In First Out (LIFO) ともいう

配列を使ったスタックの実現 必要な物は : (1) データ記憶用の配列 (2) スタックに記憶されている要素数 (= 最後の要素が入っている場所 ) (3) そのスタックに要素を付け加える関数 push (4) そのスタックから要素を取り出す関数 pop

スタックの実現 (1) データ記憶用の配列 (2) スタックに記憶されている要素数 (3) そのスタックに要素を付け加える関数 push (4) そのスタックから要素を取り出す関数 pop (1) は ( 大域変数として ) int stack[num]; // NUM は #define NUM 1000 というように宣言しておく (2) はこのための ( 大域 ) 変数 stack_top を宣言しておく int stack_top=0; // 初めは空っぽなので 0 を初期値としておく (3) の関数 push はスタックと その要素数を記憶している変数 そのスタックにいれる数を引数とする. 値は返さないので型は void である void push(int st[ ], int *top, int item); // top の値を書き換えないといけないので ポインタでないといけない * 要解説 * 4) の関数 pop はスタックと その要素数を記憶している変数とを引数とし そのスタックの最後の要素を返す そして 要素数が1 減り 元のスタックにおいて最後に記憶された要素を返す void pop(int st[ ], int *top);

課題 課題 1. push 関数の定義は以下 : 関数本体は 1 行で書ける チャレンジしよう void push(int st[ ], int *top, int item) { int x = *top; st[x] = item; *top = x+1; 課題 2. pop 関数の定義は以下 : 関数本体は 1 行で書ける チャレンジしよう int pop(int st[ ], int *top) { *top = *top - 1; return st[ *top ];

課題 3. 次のプログラムを完成させ 走らせて期待したような値が表示されるか確かめよう #include <stdio.h> #define NUM 100 int stack[num]; int stack_top = 0; void push(int st[ ], int *top, int item) { // ここに push の定義を書く int pop(int st[ ], int *top) { // ここに pop の定義を書く void printstack(int st[], int top) { printf("current state of the stack :"); for(top-- ; top >= 0; top--) printf("%3d", st[top]);printf(" n"); int main(void) { push(stack, &stack_top, 10); push(stack, &stack_top, 20); push(stack, &stack_top, 30); printstack(stack, stack_top); printf("popped --- %d n", pop(stack, &stack_top)); push(stack, &stack_top, 40); push(stack, &stack_top, 50); printstack(stack, stack_top); while (stack_top > 0) { printf("popped --- %d n", pop(stack, &stack_top)); return 0;

期待した実行結果 : Current state of the stack : 30 20 10 popped --- 30 Current state of the stack : 50 40 20 10 popped --- 50 popped --- 40 popped --- 20 popped --- 10 なぜこうなるはずなのか 説明せよ

課題 4. スタックの応用として 逆ポーランド記法がある 逆ポーランド記法とは 普通の数式が 1 + 2 * 3-4 というように 演算子 (+ - * /) を 演算される要素の間に書く ( これを中置記法という ) のに対し 1 2 3 * + 4 - というように 演算子を演算される要素の後ろに置く ( 後置記法 ) 一見難しそうに見えるかもしれないが (1) 日本語として読みやすい ( ただし 適当に助詞を入れる必要がある ) (2) カッコが不要になるという特徴がある たとえば 1 2 3 * + 4 - は 1 に 2 と 3 を * した ( 掛けた ) ものを + して ( 足して ) 4 を - する ( 引く ) と読める ちなみに 前置記法であるポーランド記法では 演算子が先頭に書かれる : - + 1 * 2 3 4 なお その計算機では = を入力したら そこれを基礎知識として 数値や演算子を一つ一つ読み込み それらが逆ポーランド記法として書かれたものとして計算する 電卓 を作れ なお = が入力されたら そこまでの結果を表示するものとする (porlandtemplate.c 参照 ) 課題 5. キューについて調べ 配列を用いてキューを実現するためには どのようにすればよいか スタックの分析を参考に考えてみよう