プログラミング論 II 電卓,逆ポーランド記法電卓

Slides:



Advertisements
Similar presentations
第 2 章 数値の入力と変数 scanf と変数をやります 第 2 章 数値の入力と変数 1. 以下のプログラムを実行してみよう  C 言語では文の最後に「 ; 」(セミコロン)が付きます 第 2 章 数値の入力と変数 2 #include int main() { int x; x = 3; printf("x.
Advertisements

オブジェクト指向言語・ オブジェクト指向言語演習 中間試験回答例. Jan. 12, 2005 情報処理技術基礎演習 II 2 オブジェクト指向言語 中間試験解説 1  (1) 円柱の体積(円柱の体積 = 底面の円の面積 x 高さ) を求めるプログラムを作成しなさい。ただし、出力結果は、入 力した底面の円の半径.
プログラミング演習II 2004年11月 30日(第6回) 理学部数学科・木村巌.
情報処理演習C2 ファイル操作について (2).
情報基礎演習B 後半第5回 担当 岩村 TA 谷本君.
第2章 数値の入力と変数 scanfと変数をやります.
基礎プログラミングおよび演習 第9回
基本情報技術概論(第4回) 埼玉大学 理工学研究科 堀山 貴史
Ibaraki Univ. Dept of Electrical & Electronic Eng.
コンパイラ 第9回 コード生成 ― スタックマシン ―
プログラミング言語論 第6回 型 情報工学科 篠埜 功.
情報工学概論 (アルゴリズムとデータ構造)
プログラミング演習II 2004年10月19日(第1回) 理学部数学科・木村巌.
第6章 2重ループ&配列 2重ループと配列をやります.
データ構造とアルゴリズム 第13回 スタックとキュー
データ構造とアルゴリズム 第5回 スタック ~ データ構造(2)~.
Stack & Queue & List 3.
アルゴリズムと データ構造 第4回 スタック・キュー.
プログラミング演習Ⅰ 課題2 10進数と2進数 2回目.
精密工学科プログラミング基礎 第9回資料 (12/11 実施)
関数 関数とスタック.
二分探索木によるサーチ.
第10章 char 文字列; 文字列を入力させるよ!.
プログラミング論 関数ポインタ と 応用(qsort)
プログラミング2 関数
プログラミング論 ファイル入出力
東京工科大学 コンピュータサイエンス学部 担当 亀田弘之
データ構造とアルゴリズム 第5回 スタック ~ データ構造(2)~.
プログラミング論 II 2008年10月30日 文字列
プログラミング入門 電卓を作ろう・パートIV!!.
アルゴリズムとプログラミング (Algorithms and Programming)
データ構造と アルゴリズム第4回 知能情報学メジャー 和田俊和.
前回の練習問題.
アルゴリズムとデータ構造1 2005年6月28日
プログラミング論 ファイル入出力
Cの実行モデル.
プログラミング基礎B 文字列の扱い.
精密工学科プログラミング基礎Ⅱ 第4回資料 今回の授業で習得してほしいこと: 文字列の扱い ファイル入出力の方法 コマンドライン引数の使い方
明星大学 情報学科 2012年度 後期   情報技術Ⅱ   第8回
東京工科大学 コンピュータサイエンス学部 担当 亀田弘之
オブジェクト指向言語論 第六回 知能情報学部 新田直也.
スタックとキュー データ構造とプログラミング (第5回).
C言語 はじめに 2016年 吉田研究室.
統計ソフトウエアRの基礎.
東京工科大学 コンピュータサイエンス学部 担当 亀田弘之
IF文 START もしも宝くじが当たったら 就職活動する 就職活動しない YES END NO.
データ構造とアルゴリズム (第3回) 静岡大学工学部 安藤和敏
プログラミング入門 電卓を作ろう・パートI!!.
プログラミング論 ポインタ
バブルソート,バケツソート,クイックソート
第8回 データを収納する (スタックとキュー)
C言語復習 来週もこの資料を持参してください.
オブジェクト指向言語論 第五回 知能情報学部 新田直也.
pf-6. スタック (Python プログラミング基礎を演習で学ぶシリーズ)
プログラミング論 構造体
東京工科大学 コンピュータサイエンス学部 担当 亀田弘之
標準入出力、変数、演算子、エスケープシーケンス
プログラミング論 文字列
コンパイラ 2012年10月11日
プログラミング 4 文字列.
Inline 展開のアルゴリズム 長谷川啓
プログラミング演習I 2003年6月11日(第9回) 木村巌.
2005年度 データ構造とアルゴリズム 第2回 「C言語の復習:配列」
printf・scanf・変数・四則演算
第2章 数値の入力と変数 scanfと変数をやります.
分岐(If-Else, Else if, Switch) ループ(While, For, Do-while)
プログラミング演習I 補講用課題
第1章 文字の表示と計算 printfと演算子をやります 第1章 文字の表示と計算.
第1章 文字の表示と計算 printfと演算子をやります.
プログラミング論 バイナリーサーチ 1.
Presentation transcript:

プログラミング論 II 電卓,逆ポーランド記法電卓 http://www.ns.kogakuin.ac.jp/~ct13140/Prog.2010/

電卓

文字列の長さを調べるプログラム void main(){ int i=0; char txt[100]="hello"; while( txt[i]!='\0' ){ i++; } printf("%sの長さは%d\です\n",txt,i);

文字列を数字に変換(自作) char txt[10] = "123"; int i, n=0; for(i=0; i<10; i++){ if(txt[i] != '\0' ){ n = n*10 + txt[i]-'0'; } else { break; } printf("%d\n", n);

文字列を数字に変換(自作) txt[10] は '1','2','3'. 最初のtxt[0]を読むと'1'. (これは49) '1'-'0'で,int型の1が得られる. txt[1]を読むと'2'. 1*10 + 2  12. txt[2]を読むと'3'. 12*10 + 3  123.

文字列を数字に変換(自作) txt[]="123456"として,前から読んでいく. "1234"まで既に読んでおり,次に'5'を読むと… 1234 → 12345 1234*10 + 5 という処理を行う.

超単純な電卓プログラム "1+2" を読み込んだら,"3"を出力. 式を読み込み,計算結果を表示するプログラム. 式の中には,演算子が1個だけだとする. 登場する数字は,1桁の自然数のみとする. つまり,文字は3個あり, 順に,「数字」,「演算子」,「数字」が格納されている.

超単純な電卓プログラム void main(){ char txt[4] = "7*4"; char a; int x; /* 0文字目を 解析する. */ a = txt[0]; printf("0文字目は,文字コード %d の\n", a); printf("[%c] という文字です.\n", a); x = a - '0'; printf("数字に変換すると %d です.\n", x); :

超単純な電卓プログラム void main(){ char txt[4] = "7*4"; char a, o; int x; /* 0文字目を 解析する. */ 略 /* 1文字目を 解析する. */ o = txt[1]; printf("1文字目は,文字コード %d の\n", o); printf("[%c] という文字です.\n", o); :

超単純な電卓プログラム void main(){ char txt[4] = "7*4"; char a, b, o; int x, y; 略 /* 2文字目を 解析する. */ b = txt[2]; printf("2文字目は,文字コード %d の\n", b); printf("[%c] という文字です.\n", b); y = b - '0'; printf("数字に変換すると %d です.\n", y); :

超単純な電卓プログラム void main(){ char txt[4]="7*4"; char a, b, o; int x, y, result; 略 if( o == '+' ){ result = x + y; } else if( o == '-' ){ result = x - y; } else if( o == '*' ){ result = x * y; } else if( o == '/' ){ result = x / y; } printf("計算結果は %d です\n", result);

実行結果 0文字目は,文字コード 55 の [7] という文字です. 数字に変換すると 7 です. 1文字目は,文字コード 42 の void main(){ char txt[10] = "7*4"; char a, b, o; int x, y, result; /* 0文字目を 解析する. */ a = txt[0]; printf("0文字目は,文字コード %d の\n", a); printf("[%c] という文字です.\n", a); x = a - '0'; printf("数字に変換すると %d です.\n", x); /* 1文字目を 解析する. */ o = txt[1]; printf("1文字目は,文字コード %d の\n", o); printf("[%c] という文字です.\n", o); /* 2文字目を 解析する. */ b = txt[2]; printf("2文字目は,文字コード %d の\n", b); printf("[%c] という文字です.\n", b); y = b - '0'; printf("数字に変換すると %d です.\n", y); if( o == '+' ){ result = x + y; } else if( o == '-' ){ result = x - y; } else if( o == '*' ){ result = x * y; } else if( o == '/' ){ result = x / y; } printf("計算結果は %d です\n", result); 実行結果 0文字目は,文字コード 55 の [7] という文字です. 数字に変換すると 7 です. 1文字目は,文字コード 42 の [*] という文字です. 2文字目は,文字コード 52 の [4] という文字です. 数字に変換すると 4 です. 計算結果は 28 です

練習 0 以下の,txtを反転するには? char txt[]="Hello"; ??? printf("%s\n", txt); 実行結果 olleH

解答 0 void main(){ char txt[]="Hello"; int len, i; char tmp; len = strlen(txt); for(i=0; i<len/2; i++){ tmp = txt[i]; txt[i] = txt[len-1-i]; txt[len-1-i] = tmp; } printf("%s\n", txt);

Stack

Stack スタック stack:積み重ね 箱を積む C D B B B B B A A A A A A 新しいものは,一番上に積み, 一番上から取る. 一番上に積む↑ 一番上に積む↑ 一番上を取る↑ 一番上に積む↑ 一番上を取る↑ C D B B B B B A A A A A A

Stack スタック データ管理手法としてのstack 感覚としては, 一番上に積み, 一番上に積んである ものが取り出せる. 3をpushする 3 メモリ 7をpushする 3 7 6をpushする 3 7 6 popする.6が取り出せる 3 7 2をpushする 3 7 2 popする.2が取り出せる 3 7

Stack スタック データ管理手法としてのstack 後入れ先出し 最後に入れたものが最初に取り出せる. LIFO (Last In First Out) PUSH: スタックにデータを入れる操作を"PUSH"という.当然,Stackの一番上に入る. POP: スタックからデータを取り出す操作を"POP"という.当然,Stackの一番上のデータが取り出せる. Stack Pointer: スタックの一番上がどこにあるを示す情報.Stackに何個積んであるかと似ている.

練習 1 以下の様にpush,popをしたらどうなるか? 8をpushする 3をpushする popする. ?が取り出せる 7をpushする

解答 1 8をpushする 8 3をpushする 8 3 popする. 3が取り出せる 8 7をpushする 8 7

余談:FIFO FIFO (Fist In First Out) Queue, 待ち行列.先に入れたものが先に出てくる. 感覚としては, 先に列んだ客が 先にサービスを 受ける. 3をenqueueする. 3 7をenqueueする. 3 7 6をenqueueする. 3 7 6 denqueueする.3が取り出せる. 7 6 denqueueする.7が取り出せる. 6

オブジェクト指向言語(C++など)では, Stack機能のプログラミング グローバル変数. 本当は好ましくない. オブジェクト指向言語(C++など)では, もっと綺麗に記述できる. #define ST_SIZE 100 char data[ST_SIZE]; int stack_pointer = 0; void push(char ch){ if( stack_pointer < ST_SIZE ){ data[stack_pointer] = ch; stack_pointer ++; printf("(%cをpushしました.)\n", ch); } else { printf("(Stackがいっぱいでpushできません.)\n"); } char pop(){ if( 0 < stack_pointer ){ stack_pointer --; printf("(popして,%cが得られました.)\n", data[stack_pointer]); return data[stack_pointer]; printf("(Stackが空です.popできません.)\n"); return 0;

Stack機能のプログラミング int stack_length(){ return stack_pointer; } void print_stack(){ int i; for(i=0; i<stack_pointer; i++){ printf(" (print_stack : %d個目は %d)\n", i, data[i]); void main(){ char ch; push('H'); push('e'); print_stack(); push('r'); ch = pop(); printf("ch = %c\n", ch);

逆ポーランド記法電卓

逆ポーランド記法 数式の記述の仕方の1種. 括弧が不要.演算順序が一意に定まる. 演算対象の後に,演算子を記述する. 演算順序は,左から順にやっていけば良い. ただし,数字同士の区切りが必要になる. 演算対象の後に,演算子を記述する. 例:「3と5の和」は 通常の記法: 3 + 5 逆ポーランド記法: 3 5 + 処理系(文字列処理プログラム)の作成がとても容易.

逆ポーランド記法 1 2 + 2 * → ((1 2 +) 2 *) → ( 3 2 *) → 6 → ((1 2 +) 2 *) → ( 3 2 *) → 6 上記逆ポーランド記法を,通常の記法に直すと ((1+2) * 2) 通常記法では,1+(2*2) と (1+2)*2 は 意味が異なる. 逆ポーランド記法ではこの問題がない

逆ポーランド記法 1 2 + 3 4 + * → ((1 2 +) (3 4 +) *) → ( 3 (3 4 +) *) → ((1 2 +) (3 4 +) *) → ( 3 (3 4 +) *) → ( 3 7 *) → 21 上記逆ポーランド記法を通常の記法に直すと ((1+2) * (3+4)) 演算の順番は,(1+2)→3, (3+4)→7, 3*7→21 これは「左から順」でなく,分かりづらい(とも言える?)

逆ポーランド記法 1 2 + 3 4 + * → ((1 2 +) (3 4 +) *) → ( 3 (3 4 +) *) → ((1 2 +) (3 4 +) *) → ( 3 (3 4 +) *) → ( 3 7 *) → 21 左から,+ + * の順に処理をしていけば良い

逆ポーランド記法数式の計算 1 2 + 3 4 + * の場合. 左から順に処理をしていけば良い 1 2 + 3 4 + * ↓1 2 + を処理し,3に置き換える. 3 3 4 + * ↓3 4 + を処理し,7に置き換える. 3 7 * ↓3 7 * を処理し,21に置き換える. 21

通常の記法→逆ポーランド記法 (8-2)/(1+2)を逆ポーランド記法にすると… 上記はまず 8-2 が行われるので 8 2 – 次に, 1+2 が行われるので 8 2 – 1 2 + 最後の,6/3 が行われるので 8 2 – 1 2 + / ↑は,→の意味 ((8 2 -) (1 2 +) /)

逆ポーランド記法電卓の実装 以下の手順で実装可能 [1] stackを用意する. [2] 左から順に読んでいく. もし,数字だったら,stackにpush もし,演算子だったら,数字を2個popして 演算結果をpush. [2]を,式の終わりまで繰り返す.

逆ポーランド記法電卓の実装 1 2 + 3 4 + * stackを用意する. 左から順に読んでいく. 1を読んだ.数字をpush. +を読んだ.2個popし, 演算をし,結果をpush. 3を読んだ.数字をpush. 1 1 2 3 3 3

逆ポーランド記法電卓の実装 4 + * 4を読んだ.数字をpush. +を読んだ.2個popし, 演算をし,結果をpush. 最後に,stack上にある数字をpopし,終了. 答えは "21" 3 3 3 3 4 3 3 7 21 21

逆ポーランド記法電卓の実装 続きは,プログラミング演習IIで.