Cプログラミング入門第1回三輪忍
ソフトウェア設計技術の基礎の習得
ソフトウェア設計の目的:◦ 人間が意図した作業を代わりにコンピュータに行わせること
なぜ?◦ 人間は面倒なことはやりたくない◦ コンピュータは疲れない
そのための方法論を学ぶ◦ C 言語を題材に
この授業のねらい
目的:ソフトウェア設計スキルの習得
普通は,◦ 講義でプログラミング理論を教える◦ 演習で実装して理解を深める
それぞれ半期ぐらい
授業の進め方(普通の情報科の場合)
『情報科学』(準必修,1年後期)◦ Ruby を用いたプログラミングの講義と演習
空白の1年
この授業◦ C を用いた3回の演習だけ...◦ スタート時点での理解度がばらばら
授業の進め方(うちの場合)
基本は演習◦ これから課題を提示◦ 出席とレポートで評価
課題の提示後に簡単な講義(1回だけ)◦ プログラミングをまったく理解していない人向け
『情報』『情報科学』を履修していない人 ほとんど忘れてしまった人
◦ 進められる人は講義中に課題をやってもよい
この演習の進め方
第1回(4 / 7)◦ 演習 or 講義(『コンピュータ概論と C 文法の基礎』)
第2回(4 / 14)◦ 演習
第3回(4 / 21)◦ 演習
レポート提出(4 / 28正午まで)
スケジュール
内容◦ 実装したプログラムをレポート形式で報告◦ 実装が十分理解できればソース・コードを提出する必要はない
提出方法: E-Mail◦ 宛先: [email protected]◦ Subject : 【プログラミング入門レポート】 学籍番号:氏名◦ PDF で
レポートに関して
巡回セールスマン問題の近似解を求めるプログラムを作成せよ.作成したプログラムを用いて、下記の都市データの最短経路を求めよ.
都市データのファイル http://www.hal.ipc.i.u-tokyo.ac.jp/~miwa/ja.txt
レポート課題
100
100
100
125
125 125
50
5075
75
データ・ファイルの見方◦ 1 行が 1 都市に相当◦ 各行の 3 つの数字の意味(例:” 1 288 149” )
都市の番号(” 1” ) (都市の位置を 2 次元平面上にプロットした場合の) x 座標
(” 288” ) y 座標(“ 149” )
レポートに書くべきこと◦ 実装したアルゴリズムの説明◦ 求めた解(ルート,総移動距離)
解の精度とアルゴリズムの面白さで評価
注意事項
288
149
都市 1
まだ訪問していない都市の中で最も近いものを選択
最近近傍法
100
100
100
125
125 125
50
5075
75
スタート
コンピュータ概論
生活を豊かにする便利なもの◦ インターネット端末◦ ワード・プロセッサ◦ 電子書籍リーダ◦ 携帯電話◦ etc
どんなシステム???
コンピュータに対する理解
融通のきかない人◦あらかじめ決められた手続きしかできない◦決まった言葉(言語・文法)しか理解できない
プログラム◦ コンピュータに行わせる一連の手続き◦命令の集合として記述
Ex.) C = A + B
システムとしてのコンピュータ
Memory◦命令やデータを格納する領域
CPU ( Central Processing Unit )◦メモリから命令やデータを取得◦ 演算を行う装置
詳しくは『計算システム論第2』で
コンピュータの構成
CPU
Memory
C = A + B A BC = A + B A B
CC
プログラム◦ コンピュータに行わせる手続き
命令の集合◦ 最終的には機械語(アセンブリ)
「 01001110 …」
人間が直接書くのはほぼ不可能◦昔は書いてた
『マイコンプログラミング演習』でもやる◦ちょっと複雑になると無理
プログラミング
高級言語Ex.) Fortran, C, Java, Ruby, … ◦ これなら何とかなる( for 人間)◦ 理解不能( for コンピュータ)
コンパイラ◦翻訳を行うプログラム◦高級言語で記述されたものを機械語へと変換
高級言語とコンパイラ
機械語高級言語コンパイル
web を参照◦ http://www.hal.ipc.i.u-tokyo.ac.jp/~miwa/exp-C.html
コンパイルの手順
C言語の文法の基礎
プログラムの基本構造 データと演算制御の流れ
内容
問題:◦ 進振り対象の学生の成績データ(平均点のデータ. 3,000 人
分)が手元にある.中央値を求めなさい. Ex.) 75 点, 95 点, 63 点, 70 点, 82 点,・・・
どうやって?◦ 人間が集計
データを昇順に並び替え(ソート) 1,500 人目を探す Ex.) 60 点, 60 点, 62 点, 63 点, 65 点,・・・, 77点,・・・
◦ コンピュータに集計させる
仕事の例
数日仕事
数分仕事
1,500 人目
バブル・ソート◦左端から右端に向かって以下の操作を行う
隣り合うデータの大小を比較 昇順になっていなかったら入れ替え
◦右端に到達したら左端に戻ってやり直し◦ 計算量:最悪 O (n^2)
ソーティング・アルゴリズム
75 点 95 点 63 点 70 点 82 点75 点 95 点 63 点 70 点95 点63 点 95 点63 点 70 点 95 点82 点70 点
1回目2回目
75 点 63 点63 点 75 点 75 点63 点 70 点
swap swap swap
C プログラムの構造#include <stdio.h>
main ( ) { int i, j, tmp; int data [3000];
for ( i = 0 ; i < 3000 – 1 ; i = i + 1) { for ( j = 0 ; j < 3000 – i + 1 ; j = j + 1) { if ( data [ j ] > data [ j + 1 ] ) { tmp = data [ j ]; data [ j ] = data [ j + 1]; data [ j + 1 ] = tmp; } } }
printf ( “median = %d\n”, data [1500] );}
関数文
ヘッダ
ファイル median.c の内容
処理のまとまり◦複数の文からなる
サブルーチンを実現(後述)
普通は繰り返し行われる処理を関数化◦同じことを何度も書くのは面倒◦バグのもと
関数
main 関数◦ プログラムの実行開始地点を表す◦ 普通は最初に 1 回呼ばれるだけ
特殊な関数
#include <stdio.h>
main ( ) { int i, j, tmp; int data [3000];
for ( i = 0 ; i < 3000 – 1 ; i = i + 1) { for ( j = 0 ; j < 3000 – i + 1 ; j = j + 1) { if ( data [ j ] > data [ j + 1 ] ) { tmp = data [ j ]; data [ j ] = data [ j + 1]; data [ j + 1 ] = tmp; } } }
printf ( “median = %d\n”, data [1500] );}
処理の最小単位◦「 A を B に代入する」◦「文字を出力する」
「 ; 」 の次の文字から 「 ; 」 まで 1文 / 行がマナー(例外アリ)
文
#include <stdio.h>
main ( ) { int i, j, tmp; int data [3000];
for ( i = 0 ; i < 3000 – 1 ; i = i + 1) { for ( j = 0 ; j < 3000 – i + 1 ; j = j + 1) { if ( data [ j ] > data [ j + 1 ] ) { tmp = data [ j ]; data [ j ] = data [ j + 1]; data [ j + 1 ] = tmp; } } }
printf ( “median = %d\n”, data [1500] );}
ヘッダ・ファイルの展開( include )
ヘッダ・ファイル◦複数のファイルで使用される関数などを宣言◦あらかじめ用意されていることもある
ヘッダ
#include <stdio.h>
main ( ) { int i, j, tmp; int data [3000];
for ( i = 0 ; i < 3000 – 1 ; i = i + 1) { for ( j = 0 ; j < 3000 – i + 1 ; j = j + 1) { if ( data [ j ] > data [ j + 1 ] ) { tmp = data [ j ]; data [ j ] = data [ j + 1]; data [ j + 1 ] = tmp; } } }
printf ( “median = %d\n”, data [1500] );}
C プログラムの構造#include <stdio.h>
main ( ) { int i, j, tmp; int data [3000];
for ( i = 0 ; i < 3000 – 1 ; i = i + 1) { for ( j = 0 ; j < 3000 – i + 1 ; j = j + 1) { if ( data [ j ] > data [ j + 1 ] ) { tmp = data [ j ]; data [ j ] = data [ j + 1]; data [ j + 1 ] = tmp; } } }
printf ( “median = %d\n”, data [1500] );}
関数文
ヘッダ
ファイル median.c の内容
文字列を出力する関数( printf )の宣言があるヘッダ・ファイル( stdio.h )を include
プログラムの開始地点
処理の方向
プログラムの終了
バブル・ソート
中央値を出力
プログラムの大部分はデータに対する演算◦「隣り合う2つの点数を比較する」◦「2つの点数を交換する」 など
データと演算
データ 演算
データ◦定数:変更不可 ( e.g. “1500”, “3000” )
◦変数:値の入れ物.中身を変更可能 ( e.g. “i”, “j”, “tmp” )
データ型◦ データを扱う形式◦ コンパイラが機械語を生成する際のヒント
“A + B” 整数の加算 or 浮動小数点の加算?
データの種類とデータ型
tmp
63
75
95
基本型◦ char : 1B の数値.文字の型としても使用◦ int :整数(通常 4B )◦ float :単精度浮動小数点(通常 4B )◦ double :倍精度浮動小数点(通常 8B )
修飾子◦長さ( short, long )◦符号( singed, unsigned )
データ型の種類
使い方(変数に限らない)◦ 最初に型を宣言◦ どこかで定義(宣言を兼ねることも)◦ 後は普通に使用
宣言 /定義の位置◦ グローバル
関数の外で宣言 /定義 そのファイル中のどこでも参照可能
◦ ローカル 関数の冒頭で宣言 /定義 その関数内でのみ参照可能
宣言 /定義と使用
#include <stdio.h>
main ( ) { int i, j, tmp; int data [3000];
for ( i = 0 ; i < 3000 – 1 ; i = i + 1) { for ( j = 0 ; j < 3000 – i + 1 ; j = j + 1) { if ( data [ j ] > data [ j + 1 ] ) { tmp = data [ j ]; data [ j ] = data [ j + 1]; data [ j + 1 ] = tmp; } } }
printf ( “median = %d\n”, data [1500] );}
#include <stdio.h>
main ( ) { int i, j, tmp; int data [3000];
for ( i = 0 ; i < 3000 – 1 ; i = i + 1) { for ( j = 0 ; j < 3000 – i + 1 ; j = j + 1) { if ( data [ j ] > data [ j + 1 ] ) { tmp = data [ j ]; data [ j ] = data [ j + 1]; data [ j + 1 ] = tmp; } } }
printf ( “median = %d\n”, data [1500] );}
関数の冒頭で宣言 /定義
宣言(定義は別のファイル)
使用
配列◦ベクタ,行列◦ インデクス付けされたデータの集合Ex.) 3,000 人分の平均点データ
int data0, data1, …, data2999; int data [3000];
“data [ i ]” で i 番目の要素にアクセス
ポインタ◦ データのアドレスを格納する変数
派生型
基本的には同じ型のデータ同士
種類◦算術演算( +, -, * , /, % )◦ 論理演算( &, |, ^, <<, >>, ~ )◦関係演算( <, >, >=, <=, == )
結果は真(1) or 偽(0)◦ 代入演算( = )
“A = B” は「 A に B を代入する」
演算
C プログラムの構造#include <stdio.h>
main ( ) { int i, j, tmp; int data [3000];
for ( i = 0 ; i < 3000 – 1 ; i = i + 1) { for ( j = 0 ; j < 3000 – i + 1 ; j = j + 1) { if ( data [ j ] > data [ j + 1 ] ) { tmp = data [ j ]; data [ j ] = data [ j + 1]; data [ j + 1 ] = tmp; } } }
printf ( “median = %d\n”, data [1500] );}
ファイル median.c の内容
#include <stdio.h>
main ( ) { int i, j, tmp; int data [3000];
for ( i = 0 ; i < 3000 – 1 ; i = i + 1) { for ( j = 0 ; j < 3000 – i + 1 ; j = j + 1) { if ( data [ j ] > data [ j + 1 ] ) { tmp = data [ j ]; data [ j ] = data [ j + 1]; data [ j + 1 ] = tmp; } } }
printf ( “median = %d\n”, data [1500] );}
j 番目のデータが j+1 番目のデータよりも大きいか比較j 番目のデータ
を tmp に退避
j+1 番目のデータをj 番目の位置に代入
tmp のデータを j+1 番目の位置に代入
データ交換
基本◦左から右へ◦ 上から下へ
流れを変えたいこともある◦条件付き実行
「左のデータの値が右のデータの値よりも大きい場合は交換する」
「 3000 回繰り返す(カウンタが 3000 を超えたら繰り返すのをやめる)」
◦関数呼び出し “ printf () ”
制御の流れソース・コード
分岐◦ if 文◦ switch 文
ループ◦ for 文◦ while 文
サブルーチン
流れを変えるもの
条件によって実行する部分を変更
◦ if 文: 条件の真偽により変更
分岐
◦ switch 文: 条件の値により変更
if ( A ) { B;} else { C;}
switch ( x ) { case 0: A; break; case 1: B; break;}
x が 0 の場合
x が 1 の場合
A が真の場合
A が偽の場合
C プログラムの構造#include <stdio.h>
main ( ) { int i, j, tmp; int data [3000];
for ( i = 0 ; i < 3000 – 1 ; i = i + 1) { for ( j = 0 ; j < 3000 – i + 1 ; j = j + 1) { if ( data [ j ] > data [ j + 1 ] ) { tmp = data [ j ]; data [ j ] = data [ j + 1]; data [ j + 1 ] = tmp; } } }
printf ( “median = %d\n”, data [1500] );}
ファイル median.c の内容
j 番目のデータが j+1 番目のデータよりも大きいか比較結果が真の場合
のみ交換を行う
条件が成立している限り繰り返す
書き方は2通り◦ for 文 / while 文◦ どちらでも同じことが実現可能◦慣例として,
for 文:制御変数が単調に変化する時 (配列アクセスなど) while 文:それ以外
ループ
for ( A ; B ; C ) { D;}
while ( B ) { D;}
制御変数の初期化
条件式制御変数の更新
条件式
B
D
B
D
A
B
D
C
B
D
C
C プログラムの構造#include <stdio.h>
main ( ) { int i, j, tmp; int data [3000];
for ( i = 0 ; i < 3000 – 1 ; i = i + 1) { for ( j = 0 ; j < 3000 – i + 1 ; j = j + 1) { if ( data [ j ] > data [ j + 1 ] ) { tmp = data [ j ]; data [ j ] = data [ j + 1]; data [ j + 1 ] = tmp; } } }
printf ( “median = %d\n”, data [1500] );}
ファイル median.c の内容
i を初期化
i が 2999 に達するまで繰り返す
i をインクリメント
サブルーチン◦別の処理を呼び出す◦終わったら元の位置に戻る◦関数呼び出し /復帰によって実現
関数◦引数:呼び出し時に関数に渡す データ◦返り値:復帰時に元のルーチン に返すデータ
サブルーチンと関数
printf ( “median = %d\n”, data [1500] );
void printf ( char* s, … ) {
}
第1引数返り値の型
プログラムの基本構造
データと演算◦ データには型が存在
制御の流れ◦ 基本は左から右へ.上から下へ◦流れを変えるもの
分岐,ループ,関数呼び出し
C文法のまとめ
カーニハン&リッチー: 「プログラミング言語 C 第2版」,共立出版
講義スライド◦ http://www.hal.ipc.i.u-tokyo.ac.jp/~miwa/C1_2013.pptx
参考書
おまけ
正直に言って,あまりよくない◦「どうしたらいいかわからない」◦「教え方が不親切.できる人にはこれでいいんだろうけ
ど...」 でも,こちらの立場としては,
◦ 理解度のばらつきが大きすぎて,演習や講義の最低ラインを決めるのが非常に難しい(あまりに易しくしすぎると,できる人には物足りない演習になる)
◦誰が何をわかってないのかこちらはわからないので,わからないことがあるなら質問してほしい(演習の間は講義室にいるのだから)
この演習の例年の評判
できない人をサポートしつつ,できる人も楽しめる演習にするに
はどうすればよいか?
サンプル・プログラムを配ります◦ データ・ファイルの読み込み,結果の出力部分など,アルゴリ
ズムとは直接関係ない部分を実装する手間を削減◦ アルゴリズムの考案・実装に注力できるようになる
サンプル・プログラムの URL◦ http://www.hal.ipc.i.u-tokyo.ac.jp/~miwa/tsp.c※ あくまでサンプルなので,ゼロから自分で書きたい人は自由に書いてください
対応策
1行が都市間の移動1回を表す
直前にいた都市の座標( X, Y )
訪問中の都市の座標( X, Y )
この都市に訪問するまでのトータルの移動距離
Top Related