リスト処理の基本
来週からのテストということもあり、前半に簡単なリスト処理の基本を説明したあと、 後半はテスト勉強時間とした。
最初に復習のおまけとして、typedef や C++でのリストの宣言の違いを説明。
// 授業でのスタイル struct List { int data ; struct List* next ; } ; // C言語でtypedefを使うスタイル typedef struct LIST { int data ; struct LIST* next ; } List ; List* top = .... ; // C++では、構造体名がそのまま使える struct List { int data ; List* next ; } ; List* top = .... ;
簡単な補助関数を示して、基礎的なプログラム例を演習として行う。
struct List* cons( int x , struct List* n ) { struct List* ans ; if ( (ans=(struct List*)malloc(sizeof(struct List)))!=NULL ) { ans->data = x ; ans->next = n ; } return ans ; } void print( struct List* p ) { for( ; p != NULL ; p = p->next ) { printf( "%d" , p->data ) ; } } int sum( struct List* p ) { int ans ; for( ans = 0 ; p != NULL ; p = p->next ) { ans += p->data ; } return ans ; } void main() { struct List* top = cons( 1 , cons( 2 , cons( 3 , NULL ) ) ) ; print( top ) ; printf( "%d" , sum( top ) ) ; }
FD講演会で認証評価に関する講演
今年度は、福井高専では学位授与機構にによる認証評価とJABEE審査が行われる。 講演では、認証評価に備えた説明があった。
この中で、特徴的と思われる点は、第2サイクルの評価に当たり、 「学生による事前学習」が重要とのことであった。 このため、シラバスには事前学習の内容を明記などが、必要となりそう。 特に各週毎に明記が理想とのことであった。
うーむ、シラバスの管理システムに、記述欄そんなに増やせるのかな…
グラフィックスと純粋仮想クラス
先週の純粋仮想基底クラスの事例を、具体的なプログラムでの演習とすべく、 下記資料を配布し、演習を行う。
最初に、他学科の学生であればGrWinを知らない可能性もあり、 本科3年向けの資料を配布し、説明を行う。 ただし、電気電子OB学生が中心であるため、GrWinは授業で経験済みであった。
Figure というdraw()という仮想関数を持つ純粋仮想基底クラスを宣言し、 FigureBox , FigureCircle という、具体的な図形のクラスを派生させ、 各描画関数 draw を示す。演習では、別の図形を派生させたり、 色つきクラスに拡張してもらうなどして、次のクラス設計の元ネタとすべく演習を予定。
高専プロコン(第23回)の学内審査
高専プロコンへの参加者を決めるための学内審査を行った。
4EI前期授業の「創造工学演習」の中からの応募と、 他のグループからの応募希望者で選考を行なっているが、 今年は4EI以外からの希望者がなく、創造工学演習からの参加者でのみ選考を 行った。
- (競技部門)
-
競技部門への参加希望は、この1チームだけであり、 プログラム作成時の問題点をあげ、それに対応できる方法を検討中であった。 現在、各種プログラムをつくり、基本的な動作のテスト中ということで、 競技部門へ応募。
- (課題部門): お年寄りと子供の交流の場を提供するシステム
-
課題部門の「少子高齢化」という趣旨に沿っている点で、 アイデアは良く、熱心さも伝わる資料であった。 しかし、ゲーム要素等の具体性がなく説明があいまいで不十分。 より具体的な概念図が必要と思われる。 説明の中で、独自用語の説明が不十分で、作成予定の独自デバイスについても 機能などが不明瞭なので、説明などを修正して課題部門に応募。
- (自由部門): 子供がつえをもってお遊び
-
ディスプレイの前で杖を持ち、各種ゲームをする点で子供たちが喜びそう。 教育要素も取り入れているのが良いが、類似ソフトとの違いの説明が必要であろう。 説明や内容を練り直し、自由部門での応募を目指す。
- (自由部門): ネットワーク対応LEGOブロックシミュレータ
-
既存のシミュレータと違い、ネットワーク対応・複数人で遊べる点が良いと思われる。 ブロックの新しい遊び方を提案できる可能性を評価。 具体的な画面・説明・機能の説明が必要で、加筆の上自由部門での応募を目指す。
- ×電子ブロックシミュレータ
-
既存のソフトとの違いが不明瞭で、論理回路も利用可能にするなどのアイデアを 評価したいが、実装方法も不明瞭で完成が難しそうであった。
- ×どこでも掲示板 ネットワーク対応の電子掲示板
-
基本的な部分は、実現しやすいと思われるが、既存の電子掲示板の機能を超えていない。 フォントの取扱いやマトリックスLEDの複数行への対応の説明が不明瞭で、 完成が難しそう。
- ×稲作シミュレーション
-
稲作をとりあげるなど面白いと思えるが、実現性は高いが面白さのためのアイデア不足 している。 食文化をどのように、外国人に伝えることを目的としているけど、その方法が不明瞭であった。
2011年度授業アンケート
授業アンケート(2011年度)のデータが送付されてきた。 ということで、例年通りそのまま記載。
データベース
75.9→77.8でポイントは微増。 黒板やOHP資料のポイントが低い。 担任クラスでもあり、甘めの評価の懸念あり。
情報構造論
81.3→82.3でポイントは微増。 黒板やOHP資料のポイントが低い。 意見欄では、良かったや分かりやすかったの意見があり、 総じて良い評価であったと思われる。
創造工学演習
時間不足を指摘する意見が多い。 前年度の授業段階から事前準備などの提案もあり、 目的意識を持って取り組んだという意味では、良い傾向と思われる。
プログラミング応用
77.3→81.0でポイントも上がっている。 この科目では、黒板OHPのポイントが特に悪いという程ではない。 意見欄でも、プリントが分かりやすいとか理解が深まったとの 好印象な意見が得られた。 一方、授業中の演習が座学と区別しているため、実際にどんな動きをするのか見てみたかったとの意見もあった。
計算機システム
N進数変換とbit演算の応用
前回の授業で、#defineマクロやbit演算の説明をしたけど、 まだ詰めが甘かったので、開いたサブルーチン・閉じたサブルーチンなどの 説明を行い、標準関数などの説明も行う。
開いたサブルーチンと閉じたサブルーチン
#define マクロと、関数の違いを理解してもらうために、 プリプロセッサ・コンパイル・リンクといった機械語生成までの流れを説明し、 #define マクロを多用すると、同じ機械語が何度も生成され、機械語が肥大する 可能性を説明する。逆に関数を何度も利用しても、一箇所の機械語が使われるため 機械語の肥大は無いことを説明する。一方、関数では実引数・仮引数の 値渡しなどが発生するので、わずかとはいえ余計な処理時間を要することを説明。 この結果、#define マクロは、小さな関数向きであることを述べる。 また、関数は入口・出口が明確に作られることから、閉じたサブルーチンと呼ばれる。 逆に #define マクロは入口・出口が明確でなく、開いたサブルーチンと呼ばれることを 説明する。
N進数変換や文字列処理で使う標準関数
N進数変換や文字列処理で、ctype.h の isdigit() 関数や、stdlib.h の strtol() などの 標準関数を説明する。
型の問題と実行時のトラブル
1桁の数値と+,-記号で式の値を求めるeval() という関数を示し、 文字列処理のサンプルを説明する。このあと、以下の様な呼び出しの問題点を考えてもらう。
int eval( char s[] ) { // 一桁の数値と"+","-"の計算式 // 例 printf( "%d" , eval( "1+2+3" ) ) ; // 6 } void main() { printf( "%d" , eval( 1+2+3 ) ) ; // 引数型の不一致 printf( "%d" , eval( '1+2+3' ) ) ; // 文字定数エラー printf( "%d" , eval( "1+2+3" ) ) ; // OK // よくありそうな書き間違い char s[ 100 ] ; scanf( "%s" , s ) ; printf( "%d" , eval( s[100] ) ) ; // 引数型不一致 // 文字列ポインタの間違い char* s ; scanf( "%s" , s ) ; // 変な場所に文字列格納でメモリエラー printf( "%d" , eval( s ) ) ; // char s[ 5 ] ; scanf( "%s" , s ) ; // 1+2+3+4+5+6 を入力したら!? printf( "%d" , eval( s ) ) ; }
2012年5月27日(第270回)
ゲスト:福井高専1期生 藤本様、釧路高専1期生 新庄様、福井高専43期生 五十嵐様
- 卒業生の方とのお話
担当:田中(5E)、前田(3EI)、松島(1C)、西(教員)
リスト構造
配列の利点・欠点を踏まえ、リスト構造の説明を行う。
配列は、N番目のデータ抽出が簡単であり、2分探索法では中央の値を 簡単に取り出せることから、O(log N)の処理が可能となる。 この一方で、C言語では配列サイズは固定であり、 最初の段階で適切なサイズが解らない場合は、メモリの使用効率を 低下させる。
これに加え、配列の欠点としてあげられるのが、途中データの削除・挿入となる。 配列の指定位置にデータを追加しようと思うと、 入れるべき場所に"空き"を作るために、以降のデータを1つ後ろにずらす必要がある。 削除でも同様に、1つ前にずらす処理が必要となる。 これにかかる処理時間は、最悪N件、最低で0件となることから、平均N/2回の ループを要し、O(N)の処理が必要となる。
これらの欠点の対応方法として、配列であれば、次のデータの入っている 場所を使えば良い。
((リストを配列で)) top: 3 data,next 0: 41 1 int data[..] ; 1: 60 -1 int next[..] ; 2: 10 4 for( p = top ; p >= 0 ; p = next[ p ] ) 3: 6 2 printf( "%d" , data[ p ] ) ; 4: 22 5 5: 34 0
この方法は、アパートの回覧板で、部屋の住人は「次の部屋の人の番号を知っていれば十分」という状況と同じである。 この方式であれば、たとえデータを追加したい場合でも、 例えば30を追加するのであれば、data[4]の後ろに追加したいのであり、 data[6] = 30 を保存し、next[4] = 6、next[6] = 5 とすれば、途中にデータを混ぜることができる。
この方法によって、データを途中に追加する場合でも、O(1)で挿入が可能となる。 (ただし挿入すべき場所を探すにはO(N)の時間を要する)
リスト構造
一方でこのままでは、data[],next[]の最初の配列サイズ以上のデータを保存することは できない。そこで必要に応じてメモリを確保する方法をとる。
// 基本となるリスト構造の宣言 struct List { int data ; struct List* next ; } ; // 手作業で地道にリストを生成 struct List* top ; top = (struct List*)malloc( sizeof(struct List) ) ; top->data = 1 ; top->next = (struct List*)malloc( sizeof(struct List) ) ; top->next->data = 2 ; top->next->next = (struct List*)malloc( sizeof(struct List) ) ; top->next->next->data = 3 ; top->next->next->next = NULL ; // リストデータを表示 struct List* p ; for( p = top ; p != NULL ; p = p->next ) printf( "%d" , p->data ) ;
このような方法であれば、必要に応じてメモリを確保するため、 配列サイズが途中で不足するといった事態を考える必要がない。 (mallocがNULLを返すことは考える必要があるけど…) 一方、欠点としては、データを参照する場合には、 先頭から1つづつアクセスする必要があり、 中央データを参照して2分探索といったテクニックは使えない。
いいねぇ〜 “素人でも使…(05/21)
- 05/21 いいねぇ〜 "素人でも使いやすい回路図エディタBSch3V" http://tinyurl.com/6wdovm #fnct
- 05/21 いいねぇ〜… RT @jun1s: 先日も、市内の某IT会社の役員達と飲んでいたわけだが、曰く、「いい人材の雇用はとかく難しい。面接やテストだけではなかなか測れない。奥が深い。しかし、高専卒は別。彼らは安心して採用できる。5年間彼らを見てきた先生達から意見を… #fnct
この記事は、 の @TohruSaitohに掲載した #fnct タグ付き記事を、まとめたものです。
浮動小数点データ・bit演算・#defineマクロ
演習も終わった所で、同じプログラムを効率良く記述できることを知ることを 目標に、bit演算や#defineマクロを説明する。
浮動小数点データ
浮動小数点形式のデータは、float,double の2通りがあるが、最近はほとんど double 型で 計算をすれば十分。単精度実数(float)と、その倍の倍精度実数(double)
((float)) S:符号(1bit) E:指数部(8bit) F:仮数部(23bit) SEEE,EEEE,EFFF,FFFF,FFFF,FFFF,FFFF,FFFF 指数部 - 127 float = 1.仮数部 * 2 ((double)) S:符号(1bit) E:指数部(11bit) F:仮数部(52bit) SEEE,EEEE...EEEE,FFFF,FFFF,.....,FFFF,FFFF 指数部 - 1023 double = 1.仮数部 * 2
bit演算子
2進数,8進数,16進数の変換プログラムでは、 2,8,16といった数値で割った余りや、商を求めることが多い。 コンピュータ内は2進数で扱っているため、16での余りを求める計算は、 下4bitを取り出したり、16で割るという計算は4ビットシフトに置き換えられる。 そこで、AND(&),OR(|),XOR(^),NOT(~)などのbit演算を説明。
printf( "%d" , 5 & 3 ) ; // 0101 & 0011 = 0001 = 1)10 printf( "%d" , 5 | 3 ) ; // 0101 | 0011 = 0111 = 7)10 printf( "%d" , 5 ^ 3 ) ; // 0101 ^ 0011 = 0110 = 6)10 printf( "%d" , 5 << 2 ) ; // 0101 左2bitシフト = 010100 = 20)10 printf( "%d" , ~10 + 1 ) ; // 反転+1は2の補数 = -10
#defineマクロ
N進数変換のプログラムの中には、下記のような部分があるけど、これを シンプルに書くためには、#defineマクロがよく利用される。
char s[...] ; if ( '0' <= s[i] && s[i] <= '9' ) .... #define isdigit(C) ('0' <= (C) && (C) <= '9') if ( isdigit( s[i] ) ) ...
C言語のプログラムは、最初にプリプロセッサと呼ばれる文字列置換プログラムによって、 #include や、#define の処理が行われる。 #define は、指定された文字を、指定された文字に置換する。 #define マクロは、それを関数的に記載できるようにしたもの。 閉じたサブルーチンと開いたサブルーチンの説明は次回に行う予定。