講義では、Cプログラミングの基本を学び 演習では、やや実践的なプログラミングを通して学ぶ

Slides:



Advertisements
Similar presentations
C 言語講座 第 7 回 ポインター. メモリとアドレス(ポインターの前 に) コンピュータのメモリには 1 バイトずつ 0 番地、 1 番地、 2 番地・・・というように 住所が割り当てられている この住所をアドレスという。 メモリはデータをしまうもので それを引き出すためには メモリに番号(アドレス)を振っておけばよいな.
Advertisements

プログラミング演習II 2004年11月 30日(第6回) 理学部数学科・木村巌.
7/10 if 文課題 力作が多くて感心! 演習1:キーボードから2つの整数を入力し、小さい方の数字を 表示せよ。
プログラムのパタン演習 解説.
15.1 文字列処理の基本 15.2 文字列処理用ライブラリ関数
ヒープソートの演習 第13回.
関数(1) 第11回 [6月29日、H.16(‘04)] 今日のメニュー 1 前回の課題 2 前回の宿題 3 いろいろな関数の演習 4 課題
プログラミング基礎I(再) 山元進.
第11回 整列 ~ シェルソート,クイックソート ~
情報基礎演習B 後半第5回 担当 岩村 TA 谷本君.
数理情報工学演習第一C プログラミング演習 (第3回 ) 2014/04/21
第11回 整列 ~ バケットソート,基数ソート,ヒープソート~
配列(2) 第10回[平成15年6月26日(木)]:PN03-10.ppt 今日の内容 1 素数を求める(教科書の例):復習
データ構造とアルゴリズム 第10回 mallocとfree
システムプログラミング 第5回 情報工学科 篠埜 功 ヒアドキュメント レポート課題 main関数の引数 usageメッセージ
基礎プログラミングおよび演習 第9回
プログラミング演習Ⅱ 第12回 文字列とポインタ(1)
プログラミング基礎I(再) 山元進.
文字配列の課題1 解説 /* a */ #include <stdio.h> main( ) { int i;
プログラミング演習(2組) 第12回
第10回 ソート(1):単純なソートアルゴリズム
C言語 配列 2016年 吉田研究室.
情報処理Ⅱ 2005年12月9日(金).
理由:文字数より要素数の多い配列を用いた時に,文字列の最後を示すため
理由:文字数より要素数の多い配列を用いた時に,文字列の最後を示すため
情報理論2 第6回 小林 学 湘南工科大学 2011年11月15日 〒 神奈川県藤沢市辻堂西海岸1-1-25
配列の扱い、探索 有効範囲と記憶域期間 第12回 [7月10日、H.15(‘03)] 今日のメニュー 1 前回の課題の復習
配列の扱い、探索 有効範囲と記憶域期間 第12回 [7月6日、H.16(‘04)] 今日のメニュー 1 前回の課題の復習
精密工学科プログラミング基礎 第9回資料 (12/11 実施)
第11回 整列 ~ シェルソート,クイックソート ~
精密工学科プログラミング基礎Ⅱ 第3回資料 今回の授業で習得してほしいこと: 2次元配列の使い方 (前回の1次元配列の復習もします.)
情報工学科 3年生対象 専門科目 システムプログラミング 第5回、第6回 ヒアドキュメント レポート課題 情報工学科 篠埜 功.
ちょっとした練習問題① 配列iroを['R', 'W', 'R', 'R', 'W' , 'W' , 'W']を宣言して、「W」のときの配列の番号をprintfで表示するようなプログラムを記述しなさい。
プログラミング 4 記憶の割り付け.
前回の練習問題.
情報とコンピュータ 静岡大学工学部 安藤和敏
アルゴリズムとデータ構造 第3章 ヒープ 6月10日分
P n ポインタの基礎 5 q m 5 7 int* p; int 型の変数を指すポインタ int* q; int 型の変数を指すポインタ int n=5, m=7; int 型の変数 int array[3]; int* pArray[3]; p = &n; ポインタにアドレスを代入しているのでOK.
関数の再帰呼び出しとは ハノイの塔 リダイレクト レポート課題
関数への道.
プログラミング基礎B 文字列の扱い.
プログラミング 4 整列アルゴリズム.
2009/10/23 整列アルゴリズム (1) 第4講: 平成21年10月23日 (金) 4限 E252教室 コンピュータアルゴリズム.
精密工学科プログラミング基礎Ⅱ 第4回資料 今回の授業で習得してほしいこと: 文字列の扱い ファイル入出力の方法 コマンドライン引数の使い方
プログラミング 4 探索と計算量.
第2回課題 配布した通り.氏名・学生番号を忘れないこと.
Cプログラミング演習資料.
15.1 文字列処理の基本 15.2 文字列処理用ライブラリ関数
アルゴリズムとプログラミング (Algorithms and Programming)
プログラミング 3 2 次元配列.
アルゴリズムとプログラミング (Algorithms and Programming)
ソートのプログラムの流れ 配列の中身を小さい順に並び替える a[1],a[2],…a[n]の値を順に出力する
第5回 プログラミングⅡ 第5回
精密工学科プログラミング基礎 第7回資料 (11/27実施)
ヒープソート.
情報工学科 3年生対象 専門科目 システムプログラミング 第3回 makeコマンド 動的リンクライブラリ 情報工学科 篠埜 功.
プログラミング 4 文字列.
情報工学科 3年生対象 専門科目 システムプログラミング 第3回 makeコマンド 動的リンクライブラリ 情報工学科 篠埜 功.
参考:大きい要素の処理.
精密工学科プログラミング基礎Ⅱ 第2回資料 今回の授業で習得してほしいこと: 配列の使い方 (今回は1次元,次回は2次元をやります.)
高度プログラミング演習 (07).
プログラミング演習I 2003年6月11日(第9回) 木村巌.
Cプログラミング演習資料.
15.1 文字列処理の基本 15.2 文字列処理用ライブラリ関数
湘南工科大学 2013年10月22日 情報理論2 湘南工科大学情報工学科 准教授 小林 学.
プログラミング入門2 第5回 配列 変数宣言、初期化について
プログラミング入門2 第3回 条件分岐(2) 繰り返し文 篠埜 功.
計算技術研究会 第5回 C言語勉強会 関数(function)を使う
計算機プログラミングI 第5回 2002年11月7日(木) 配列: 沢山のデータをまとめたデータ どんなものか どうやって使うのか
プログラミング 2 静的変数.
Presentation transcript:

講義では、Cプログラミングの基本を学び 演習では、やや実践的なプログラミングを通して学ぶ

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

プログラムが作れたら… data.txtの中身 ソートの結果: 2 3 -5 9 12 -10 8 -3 -10 -3 -5 2 3 8 9 9 12 -10 8 -3 -10 -3 -5 2 3 8 9 12

プログラムの手順 入力: data.txt 処理: ソート(いろいろな方法がある) 出力: ソートした結果を画面表示する(ファイルに書出す)

プログラムの手順 入力: data.txt 処理: ソート(いろいろな方法がある) 出力: ソートした結果を画面表示する(ファイルに書出す) 処理: ソート(いろいろな方法がある) 出力: ソートした結果を画面表示する(ファイルに書出す) ファイルから要素を読み込み、配列に記憶する

プログラムの手順 入力: data.txt 処理: ソート(いろいろな方法がある) 出力: ソートした結果を画面表示する(ファイルに書出す) 処理: ソート(いろいろな方法がある) 出力: ソートした結果を画面表示する(ファイルに書出す) 適当な大きさの配列を用意する ファイルの読み込み準備(ファイル変数) ファイルから要素を一個ずつ読み込んで、  配列に記憶する ファイルから要素を読み込み、配列に記憶する

プログラムの手順 入力: data.txt 処理: ソート(いろいろな方法がある) 処理: ソート(いろいろな方法がある)  ここでは、昇順の選択ソート(selection sort)を考えよう  「配列の1番目以降の要素で最小の要素を探し、1番目の要素と 交換する 。(これにより1番目の要素が「最小」となる)  次に配列の2番目以降の要素で最小の要素を探し、2番目の要素 と交換する。(これにより2番目の要素が「2番目に最小」となる) … この操作を配列の最後の要素まで繰り返す」 (3) 出力: ソートした結果を画面表示する(ファイルに書出す) 注意:配列で1番目の要素の インデックスは 0 同様に 2番目の要素のインデックスは 1 ファイルから要素を読み込み、配列に記憶する

昇順の選択ソートプログラム 「配列の1番目以降の要素で最小の要素を探し、1番目の要素と交換する 。 次に配列の2番目以降の要素で最小の要素を探し、2番目の要素と交換する。 … この操作を配列の最後の要素まで繰り返す」 注意:配列で1番目の要素の インデックスは 0 同様に 2番目の要素のインデックスは 1 ちょっと難しそう。。。なにをどうしたらよいのか? 考え方:「何かを繰り返す」と書いてあるのだから、 繰り返される処理を「関数」として捉える

昇順の選択ソートプログラム 青字:入力 茶色:処理 注意:配列で1番目の要素の インデックスは 0 配列の1番目以降の要素で最小の要素を探し、1番目の要素と交換 次に配列の2番目以降の要素で最小の要素を探し、2番目の要素 と交換… この操作を配列の最後の要素まで繰り返す これに注目 繰り返される処理を「関数」として捉える 青字:入力 茶色:処理 配列のi番目以降の要素で最小の要素を探し、 i 番目の要素と 交換する 最終的に得られるのは… 要素が交換された配列 確認:この部分でも当てはまる?

昇順の選択ソート 「配列の1番目以降の要素で最小の要素を探し、1番目の要素と交換。 次に配列の2番目以降の要素で最小の要素を探し、2番目の要素と 交換… この操作を配列の最後の要素まで繰り返す」 という方法が実際にうまくいくのか、自分の手で確かめてみる: 注意:配列で1番目の要素の インデックスは 0 2番目の要素のインデックスは 1 ... 2 3 -5 9 12 -10 8 -3 -10 3 -5 9 12 2 8 -3 -10 -5 3 9 12 2 8 -3 -10 -5 -3 9 12 2 8 3 最小 最小 最小 うまくいきそう。。。

昇順の選択ソートプログラム作成 「配列の1番目以降の要素で最小の要素を探し、1番目の要素と交換。  次に配列の2番目以降の要素で最小の要素を探し、2番目の要素と 交換… この操作を配列の最後の要素まで繰り返す」 まず、繰り返される処理を行う関数の名前、入力、処理、出力を定める 配列 arr の要素数を nとする 関数名を、(仮に)findAndReplace とする 処理: i番目以降の要素のうちの 最小値を見つけて i番目の要素と取り替える 入力: 整数の配列 int arr[ ] 整数  int i, int n 出力: 書き換えられた整数の配列 int arr[ ] あとで修正

昇順の選択ソートプログラム作成 「配列の1番目以降の要素で最小の要素を探し、1番目の要素と交換。  次に配列の2番目以降の要素で最小の要素を探し、2番目の要素と 交換… この操作を配列の最後の要素まで繰り返す」 注意:配列で1番目の要素の インデックスは 0 2番目の要素のインデックスは 1 ... 処理: i番目以降の要素のうちの 最小値を見つけて i番目の要素と取り替える やるべき仕事は2つ (1) 配列のi番目以降の要素から最小値を見つける (2) その要素とi番目の要素を入れ替える

「配列から最小値を求めるプログラム」の改訂 配列の1番目の要素(インデックス0)から最後の要素(インデッ クスn-1)までの要素のうちの最小値を求めるプログラム … は前に作った 今回はこれを元に 配列に対し、インデックスiからn-1までの要素のうちの最小値と 最小値の要素の番号(インデックス)を求める」関数 を作る 注意:配列で1番目の要素の インデックスは 0 そして、最小値とインデックスi番目の要素を入れ替える…   そのために、最小値の要素のインデックスも記憶する!

「配列から最小値を求めるプログラム」の改訂 第2回目演習で「配列の要素の最小値を求める」関数を作った: これを元に「インデックスiからn-1までの要素のうちの最小値と その番号(インデックス)を求める」関数にするには、以下をどの ように変更するかを考えれば良い: 入力 処理 出力 注意:2つのもの(ここでは最小値とそのインデックス)を返す方法はまだ学んでいない…  しかし! インデックスさえわかれば最小値がなんであるかは分かる!  そこで、「最小値のインデックス」を求める関数を考えてみよう

関数 minInArray 出力=記憶した最小要素 は int 型 入力=整数を要素とする配列 int ar[] と 要素数 int n int minInArray (int ar[] , int n) { int min=ar[0]; 今まで見た要素の中で最小のものを記憶する」変数を宣言、その変数に初期値を与える int i; for (i=1; i< n; i++) { if (min > ar[i]) // 一個ずつmin値と比較 min = ar[i]; // minxよりも大きければ更新 } 要素を比較して最小値を求める return min; } 出力=最小要素

「配列から最小値を求めるプログラム」の改訂 配列に対し、インデックスiからn-1までの要素のうちの最小値と そのインデックスとを求める」関数に作り変えてみよう 整数型の配列 → 変更なし 配列の要素数 → 最小値を求める先頭のインデックス iと 最後の要素のインデックス n とする つまり, int arr[ ], int i, int n 入力 (2)処理 (3)出力 処理 → 最小要素の値に加えて その要素のインデックス を記録 最小要素の値 → その要素のインデックス を返す  これにより、最小要素の値を「先頭の要素と取り換え」も容易

前回の課題(1) 配列の最小の要素のインデックスを返す関数 IndexOfMin 整数型の配列 ar とその要素数nを引数とし、最小要素のインデッ クスを返す関数 例えば int array[] = { 5,4,3,2,1,6,7}; と宣言されているとき、この要素数は7であり、最小要素は1でそ のインデックスは 4 (つまり array[4] = 1)であるから、 IndexOfMin(array, 7) は 4 を返す。

関数 IndexOfMin 出力=記憶した最小要素 は int 型 入力=整数を要素とする配列 int ar[] と 要素数 int n int indexOfMin (int ar[] , int n) { int min=ar[ans] , i; int ans=0; // 答えの候補、初期値は配列の先頭 要素を比較して最小値を求める for (i=1; i< n; i++) { if (min > ar[i]) // 一個ずつmin値と比較 min = ar[ans]; // minxよりも大きければ更新 } ans = i; return ans; } 返却値:最小要素のインデックス

昇順の選択ソートプログラム作成 「配列の1番目以降の要素で最小の要素を探し、1番目の要素と交換。  次に配列の2番目以降の要素で最小の要素を探し、2番目の要素と 交換… この操作を配列の最後の要素まで繰り返す」 処理: インデックス i 以降の要素から (1) 最小値の要素のインデックスを見つけて (2)インデックス i の要素と取り替える (1) 関数の名前を findMinValueとする。 findMinValue(arr, i n)によりインデックスi番目からn-1番目までの要素のうち、最小値要素のインデックスを返す (2) findMinValue(arr, i, n)の値を k とすると、 arr[i]とarr[k]の値を取り替える(swap)

findMinValue(arr, i n)によりインデックスi番目からn-1番目までの要素のうち、最小値要素のインデックスを返す findMinValue関数は IndexOfMin関数とは違う IndexOfMin 関数は引数の配列の全体で最小値を探し、そのイ ンデックスを返す findMinValue関数は引数の「ある特定の範囲」から最小値を探 し、そのインデックスを返す しかしfindMinValueは IndexOfMinをもとに作れる!

配列において指定された範囲における最小の要素を返す関数 MinInRange MinInArray関数をもとにIndexOfMin関数を作ったように、 findMinValue関数をいきなり作らずに、次のようなMinInRange関数を 作ってから考えよう。 整数型の配列 ar 、最小要素を探すインデックスの値k、arの要素数nを 引数とし、最小要素を返す関数 例えば int array[] = { 1,2,3,5,7,9,4,6,8}; とmain関数で宣言されているとき、この配列の要素数は9 MinInRange(array,0,9) は 1を返す⇒全範囲でarray[0](=1)最小値 MinInRange (array, 3,9) は 4を返す⇒範囲内でarray[6](=4)が最小値 インデックス 0 1 2 3 4 5 6 7 8

関数 minInArray 出力=記憶した最小要素 は int 型 入力=整数を要素とする配列 int ar[] と 要素数 int n int minInArray (int ar[] , int n) { int min=ar[0]; 今まで見た要素の中で最小のものを記憶する」変数を宣言、その変数に初期値を与える int i; for (i=1; i< n; i++) { if (min > ar[i]) // 一個ずつmin値と比較 min = ar[i]; // minxよりも大きければ更新 } 要素を比較して最小値を求める return min; } 出力=最小要素

関数 MinInRange 出力=記憶した最小要素 は int 型 int MinInRange (int ar[] , int s, int n) // sからn-1までの範囲での最小値 { int min=ar[s]; 今まで見た要素の中で最小のものを記憶する」変数を宣言、その変数に初期値を与える int i; for (i=s+1; i< n; i++) { if (min > ar[i]) // 一個ずつmin値と比較 min = ar[i]; // minxよりも大きければ更新 } 要素を比較して最小値を求める return min; } 出力=最小要素

配列において指定された範囲における最小の要素のインデックスを返す関数 findMinValue 整数型の配列 ar 、最小要素を探すインデックスの値k、arの要素 数nを引数とし、最小要素を返す関数 例えば int array[] = { 1,2,3,5,7,9,4,6,8}; と宣言されているとき、この要素数は9 findMinValue(array,0,9) は 0を返す⇒全範囲でarray[0](=1)最小値 findMinValue(array, 1,9) は 1を返す⇒範囲内でarray[1](=2)が最小値 findMinValue(array, 2,9) は 2を返す⇒範囲内でarray[2](=3)が最小値 findMinValue(array, 3,9) は 6を返す⇒範囲内でarray[6](=4)が最小値 0 1 2 3 4 5 6 7 8 インデックス

関数 MinInRange 出力=記憶した最小要素 は int 型 int MinInRange (int ar[] , int s, int n) // sからn-1までの範囲での最小値 { int min=ar[s]; 今まで見た要素の中で最小のものを記憶する」変数を宣言、その変数に初期値を与える int i; for (i=s+1; i< n; i++) { if (min > ar[i]) // 一個ずつmin値と比較 min = ar[i]; // minxよりも大きければ更新 } 要素を比較して最小値を求める return min; } 出力=最小要素

関数 findMinValue 出力=記憶した最小要素 は int 型 int findMinValue (int ar[] , int s, int n) // sからn-1までの範囲での最小値 { int i; int ans=s, min=ar[ans]; for (i=s+1; i< n; i++) { if (min > ar[i]) // 一個ずつmin値と比較 ans = i; min = ar[ans]; // minxよりも大きければ更新 } 要素を比較して最小値を求める return ans; } 出力=最小要素

昇順の選択ソートプログラム作成 findAndReplace関数 「配列の1番目以降の要素で最小の要素を探し、1番目の要素と交換。  次に配列の2番目以降の要素で最小の要素を探し、2番目の要素と 交換… この操作を配列の最後の要素まで繰り返す」 findAndReplace関数 処理: インデックス i 以降の要素から (1) 最小値の要素のインデックスを見つけて (2)インデックス i の要素と取り替える (1) 関数の名前を findMinValueとする。 findMinValue(arr, i n)によりインデックスi番目からn-1番目までの要素のうち、最小値要素のインデックスを返す (2) findMinValue(arr, i, n)の値を k とすると、 arr[i]とarr[k]の値を取り替える(swap)

配列の要素の値の取替え(ちょっと落とし穴) 「arr[i]とarr[k]の値を取り替える(swap) 」についての注意 これは以下のようにすればできる、と勘違いする人が時々いる… arr[i] = arr[k] arr[k] = arr[i] これではできない! 例: arr[i]=10, arr[k]=3とおくと、最初の実行で arr[i]=arr[k]=3 とな り、 arr[i]が持っていた値 10が消えてしまうからである! 解決策: 変数をもう一つ用意する(tempとする) そして、 temp = arr[i] ; arr[i]=ar[k]; arr[k]=temp とする(これが動くことを確かめよ) コツ:変数をケチらないこと

関数 findAndReplace の完成  void となっているのは、 「書き換えられた配列」を 内部で作っているから、 配列を出力しなくてよいため 関数 findMinValue を用いて作る void findAndReplace(int arr[ ], int i, int n) { int k, temp; k = findMinValue(arr, i, n); temp = arr[i]; arr[i] = arr[k]; arr[k] = temp; } 配列arrのi番目から最後の要素までで 「最小の要素」を探し、そのインデックスが kの値になっている arr[i]とarr[k]の値の交換: arr[i]にはi番目から最後の要素までの最小値が入る arr[k]にはもとのarr[i]の要素がはいる

昇順の選択ソートプログラムの作成 整数を要素とする配列 arr 、そのインデックス0からn-1まで(配列 の要素数はn)の要素をソートする: // arrには要素が既に入っているとする for (i=0; i < n; i++) { findAndReplace(arr, i, n); } // この結果 arr の中身はどうなっているだろうか?

選択ソート・アルゴリズムの記述 名称: Selection Sort 入力: 整数(もしくは浮動小数点数)型の配列 array, 要素数 n 出力: arrayの要素を昇順に並び替えたもの(関数の返却値はなし) 手順: for i ← 0 until n -1 do (i =0からn-1まで以下を行う) ind ← findMinValue(array, i, n) (arrayのiからn-1までの要素の 中で最小の要素の「インデックス」を求める) swap(array[i], array[index]) (array[i]とarray[index]の値を入れ替 える) findAndReplaace(array,i,n)

全体のプログラムの完成 data.txt の要素をソートして、sorted.txt というファイルに書出す #include <stdio.h> // 関数 findMinValue を定義 // 関数 findAndReplaceを定義 int main(void) { // 必要な変数の定義 // ファイルdata.txtから要素を読み込み 配列 arr に記憶 // そのとき、読み込んだ要素数も記憶 (変数nの値とする) // 選択ソートにより、配列 arr の中身を昇順ソート // arr の中身を sotred.txt に書出す return 0; }

課題の提出 プログラムを完成させ、 適当なファイル(例えばdata.txt)を与えて その要素をソートし その結果がsorted.txtファイルに書き込まれる ことを確認しよう できたらプログラム(説明付き)と実行結果を提出する。 プログラムは適切にインデントすることをお忘れなく