授業概要:プログラミング演習は,「プログラミング言語」で解説する Cプログラミング技法を用いてプログラミングを行い, 一層習熟することを目的とします.
実際の授業は次のように進めていくものとします.()内はそれぞれ,該当する授業を表します.
以上のように,授業はトライ&エラーで進めていきます.したがって,演習の課題は行わなくても授業の内容を聞けば,
プログラミング技法についての理解を得ることはできますが,
このようなスタンスで「プログラミング演習」と「プログラミング言語」の授業を進めていきますので, 演習をおこなう時には,次のようなプロセスを踏んで下さい.
授業に参加する前にできることがたくさんあることに気づくはずです.プログラミング技法とは直接関係はありませんが, 自分の知りたい情報を自分で取得する力を身につけることも,授業を通して身につけて欲しい能力です.
以下の各章の課題は,次のようなテーブル形式で記述されています.プログラムのインデントが正しく見えるように できるだけ画面はフルサイズにして見て下さい.
|
例題のタイトルを示します. printf関数の使い方 |
プログラムの概要を示します. printf関数を使って,画面出力を行います. |
|---|---|
|
プログラムコードを示します. #include<stdio.h> void main( void ) { printf( "My name is Tadahiko Murata\n" ); } |
プログラム記述の際の注意事項を示します. 必ずプログラムの最初に書くこと! printf関数による出力 行末にセミコロン( ; )を忘れないように! |
| 実行結果 | 疑問に思って欲しい点 |
|
実行結果と実行結果に対する注釈を示します. My name is Tadahiko Murata! 名前がモニターに出ます. |
考察できる点を示します. ・ ダブルクォーテーション( " " )の中の \n がなくなるとどうなるか? |
| Next!(さらに高度なことをやってみよう!) | |
|
他にどんな使い方ができるか示します. ・ プログラム中の変数の値を出力する(変数の型と出力形式の関係). ・ 数字以外に任意の文字列を出力するにはどうすればいいか?(文字列の出力) |
|
表の内容にしたがって,次のような順番で演習を行っていってください.
※注意事項
このページに記載されているプログラムは,ウェブページ用に書かれたものです.
実際の挙動については責任を持てませんので,各自の責任のもとにプログラムを組み,
実行して下さい.間違っているところを見つけたら,
村田(←クリックすれば,メーラーが
立ち上がります)まで連絡して下さい.
参考図書
・ 「Turbo C 初級プログラミング」 河西 朝雄 著 技術評論社 (1989) \2,200
・ 「Cプログラミング診断室」 藤原 博文 著 技術評論社 (1993) \2,427+Tax
・ 「新ANSI C言語辞典」 平林 雅英 著 技術評論社 (1995) \2,300+TAX
参考になるページ
・ C++入門のページ
・ Cプログラミング診断室 目次にたどり着くまでの前置きが長いですが・・
・ プログラミング超入門
・ 猫でもわかるプログラミング
まず,プログラミングを行い,挙動を確かめ,納得できたら,次の課題に進んでいきましょう. この課題では,printf関数(画面表示)とscanf関数(キーボード入力)についての理解を深めます.
| printf関数とscanf関数 |
実数型の変数を入力し,加減乗除の結果を表示する. |
|---|---|
|
#include<stdio.h> void main( void ) { double x, y; printf( "入力した2つの数の加減乗除を行います." ); printf( "割る数には0を入力しないでください.\n" ); printf( "一つ目の変数−double(実数)型:x="); scanf( "%lf", &x ); printf( "\n2つ目の変数−double(実数)型:y="); scanf( "%lf", &y ); printf("\nx + y = %f + %f = %f\n" , x, y, x + y ); printf("x - y = %f - %f = %f\n" , x, y, x - y ); printf("x * y = %f * %f = %f\n" , x, y, x*y ); printf("x / y = %f / %f = %f\n" , x, y, x/y ); } |
必ずプログラムの最初につけること. 変数の定義 入力に関する画面表示 変数入力を促す表示 1つ目の変数の入力 変数入力を促す表示 2つ目の変数の入力 足し算 引き算 かけ算 わり算 |
| 実行結果 | 疑問に思って欲しい点 |
|
x + y = 2.0000 + 4.0000 = 6.0000 x - y = 2.0000 - 4.0000 = -2.0000 x * y = 2.0000 * 4.0000 = 8.0000 x / y = 2.0000 / 4.0000 = 0.5000 |
|
| Next!(さらに高度なことをやってみよう!) | |
|
|
まず,プログラミングを行い,挙動を確かめ,納得できたら,次の課題に進んでいきましょう. この課題では,if else文(条件分岐)とfor文(繰り返し)についての理解を深めます. 他にも,条件分岐についてはswitch case文が,繰り返しについてはwhile文などがありますが, これらは,if else文やfor文によっても表現可能ですので省略し,自学自習の範囲とします.
| if else文とfor文 |
if文を用いた条件分岐とfor文を用いた繰り返しにより, *で直角三角形を画面に描きます. |
|---|---|
|
#include<stdio.h> void main( void ) { int a; int cnt, cnt1; printf( "5以下の正の整数を入力" ); printf( "してください.\n" ); scanf( "%d", &a ); if( a>0 && a<=5 ){ for( cnt=0;cnt<a;cnt++ ){ for( cnt1=0;cnt1<cnt;cnt1++ ){ printf( "*" ); } printf( "\n" ); } }else{ printf( "5以下の正の整数を入力してくだ" ); printf( "さい.プログラムを終了します.\n" ); exit(1); } } |
必ずプログラムの最初につけること. 変数の定義 条件の設定 (プログラムの仕様にかなう場合の動作) 条件の設定(プログラムの仕様に 合わない入力を拒否し,終了する) プログラムの強制終了 |
| 実行結果 | 疑問に思って欲しい点 |
|
* ** *** **** 5段にならないことに注意しよう! |
|
| Next!(さらに高度なことをやってみよう!) | |
|
|
まず,プログラミングを行い,挙動を確かめ,納得できたら,次の課題に進んでいきましょう. この課題では,配列についての理解を深めます.
| 配列 |
配列を用いて,入力されたデータの出現頻度を ヒストグラムにより表します. |
|---|---|
|
#include<stdio.h> void main( void ) { int histogram[11]; int cnt, cnt1, dat; for( cnt=0;cnt<11;cnt++ ){ histogram[cnt]=0; } printf( "0〜100の整数を入力" ); printf( "してください.\n" ); printf( "データの入力の終わりには,"); printf( "Ctrl+zを入力してください.\n" ); while( scanf("%d", &dat)!= EOF ){ if( 0<=dat && dat<=100 ){ histogram[dat/10]++; } } printf("\n----- Histogram -----\n" ); for( cnt=10;cnt>=0;cnt-- ){ printf( "%3d - ", cnt*10 ); for( cnt1=0;cnt1<histogram[cnt];cnt1++ ){ printf( "*" ); } printf( "\n" ); } } |
必ずプログラムの最初につけること. 配列の定義(histogramと言う名前で, [0]から[10]までの箱をつくる) 配列の要素を初期化する(0を代入しておく). 入力データに関する指示を画面に出す. Ctrl+zが入力されるまでデータの入力を行う. データが0から100までの間に入っているとき, 対応する配列要素を一つ増やす. 配列要素のヒストグラム表示 |
| 実行結果 | 疑問に思って欲しい点 |
|
100 - * 90 - ** 80 - *** 70 - **** 60 - ** 50 - *** 40 - **** 30 - ** 20 - *** 10 - **** 0 - ** |
|
| Next!(さらに高度なことをやってみよう!) | |
|
|
まず,プログラミングを行い,挙動を確かめ,納得できたら,次の課題に進んでいきましょう. この課題では,ポインタについての理解を深めます.
| ポインタと配列 |
任意の長さの文字列を入力して,一文字ずつ出力する. |
|---|---|
|
#include<stdio.h> void main( void ) { char str[30]; char *pstr; printf( "入力した文字を配列strに格納します." ); printf( "30文字以内の英数字を入力してください.\n" ); scanf( "%s", str ); printf( "\n入力された文字は「%s」です.\n", str); printf("縦に書くと次のようになります.\n" ); pstr = &str[0]; while( *pstr != '\0' ){ printf( "%c\n", *pstr ); pstr++; } } |
必ずプログラムの最初につけること. 文字型配列の定義.30個の箱が用意される. ポインタ変数の定義. 入力に関する画面表示 アルファベットの入力 入力された文字の一括出力. ポインタ変数の初期化.配列の先頭アドレスを格納する. 入力された文字の一文字ずつの出力. アドレスを一つ増やす. |
| 実行結果 | 疑問に思って欲しい点 |
|
入力された文字は「Nandemo_OK!」です. 縦に書くと次のようになります. N a n d e m o _ O K ! |
|
| Next!(さらに高度なことをやってみよう!) | |
|
|
まず,プログラミングを行い,挙動を確かめ,納得できたら,次の課題に進んでいきましょう. この課題では,関数の作り方と関数間のデータの授受についての理解を深めます.この課題では 2つの課題があるので,まず,基本となる課題を2つ仕上げてから,Next!の課題に進んでください. 変数,値,ポインタ,アドレスの関係についてよく理解するようにしてください.
| 関数(その1) |
多入力一出力の関数を作る.変数の値を関数に渡す方法. |
|---|---|
|
#include<stdio.h> int plus( int x, int y ); void main( void ) { int a, b, c, d; int ans; a = -10; b = 20; ans = plus( a, b ); printf( "a + b = %d + %d = %d\n", a, b, ans ); c = 30; d = -40; ans = plus( c, d ); printf( "c + d = %d + %d = %d\n", c, d, ans ); } int plus( int x, int y ) { int z; z = x + y; return( z ); } |
必ずプログラムの最初につけること. main関数の中で用いる関数の定義. 変数の定義. 答えを代入する変数の定義. 変数に値を代入する. plus関数を使って足し算を行う.aとbの値を関数に対する入力値とする. 計算結果の出力. 変数に値を代入する. plus関数を使って足し算を行う.cとdの値を関数に対する入力値とする. 計算結果の出力. plus関数の記述. 出力の型 関数名( 入力の型 変数名, 入力の型 変数名 ) plus関数の中だけで使うことのできる変数の定義. 足し算の実行. 足し算の結果を関数の出力とする. |
| 実行結果 | 疑問に思って欲しい点 |
|
a + b = -10 + 20 = 10 c + d = 30 + -40 = -10 |
|
| Next!(さらに高度なことをやってみよう!) | |
|
|
| 関数(その2) |
多入力多出力(?)の関数を作る.変数のアドレスを関数に渡す方法. |
|
#include<stdio.h> int plus( int *x, int *y ); void main( void ) { int a, b, c, d; int ans; a = -10; b = 20; ans = plus( &a, &b ); printf( "a + b = %d + %d = %d\n", a, b, ans ); c = 30; d = -40; ans = plus( &c, &d ); printf( "c + d = %d + %d = %d\n", c, d, ans ); } int plus( int *x, int *y ) { int z; if( *x < 0 ) *x = -1*(*x); if( *y < 0 ) *y = -1*(*y); z = *x + *y; return( z ); } |
必ずプログラムの最初につけること. main関数の中で用いる関数の定義. 変数の定義. 答えを代入する変数の定義. 変数に値を代入する. plus関数を使って足し算を行う.aとbのアドレスを関数に対する入力値とする. 計算結果の出力. 変数に値を代入する. plus関数を使って足し算を行う.cとdのアドレスを関数に対する入力値とする. 計算結果の出力. plus関数の記述. 出力の型 関数名( 入力の型 変数名, 入力の型 変数名 ) plus関数の中だけで使うことのできる変数の定義. 変数が負の場合は正の数にする. 足し算の実行. 足し算の結果を関数の出力とする. |
| 実行結果 | 疑問に思って欲しい点 |
|
a + b = 10 + 20 = 30 c + d = 30 + 40 = 70 |
|
| Next!(さらに高度なことをやってみよう!) | |
|
|
まず,プログラミングを行い,挙動を確かめ,納得できたら,次の課題に進んでいきましょう. この課題では,ファイル入出力についての理解を深めます.
| ファイル入出力 |
ファイル入出力 |
|---|---|
|
#include<stdio.h> #include<process.h> void main( void ) { FILE *fp; int year; char name[20]; if( (fp=fopen( "file.txt", "w" ) ) == NULL ){ printf( "Can not open the file.txt.\n" ); exit( 1 ); } printf( "名前 年齢 を入力してください.\n" ); printf( "入力の終わりはCTRL+zを入力してください.\n" ); fprintf( fp, "名前 年齢\n" ); while( scanf( "%s %d", name, &year ) != EOF ){ fprintf( fp, "%s %d\n", name, year); } fclose( fp ); } |
必ずプログラムの最初につけること. exit関数を使うために必要なヘッダファイル. ファイルポインタの定義. 変数の定義. 文字列配列の定義. ファイルのオープン,書き込み型で定義する. 書き込めない場合に,エラー文を画面表示して, 終了する. 入力を促すメッセージ文の画面表示. 入力終了条件の指示. ファイルの項目のファイルへの書き込み. キーボードからの入力 ファイルのクローズ |
| 実行結果 | 疑問に思って欲しい点 |
|
名前 年齢 福田 20 田中 19 中村 19 立花 21 重田 20 -----ここまで----- 実行ファイルと同じフォルダでfile.txt というファイルをみつけ,内容を確認する. ファイル-開く-ファイルの種類(テキストファイル) でファイルを見つける. |
|
| Next!(さらに高度なことをやってみよう!) | |
|
|
まず,プログラミングを行い,挙動を確かめ,納得できたら,次の課題に進んでいきましょう. この課題では,構造体についての理解を深めます.
| 構造体 |
構造体 |
|---|---|
|
#include<stdio.h> #include<process.h> struct meibo{ char name[20]; char tel[20]; char address[20]; }; void message( void ); void input( FILE *fp, int cnt , struct meibo *a, int *end ); void main( void ) { struct meibo a[20]; FILE *fp; int cnt, end; if( (fp=fopen( "meibo.dat", "w" ) ) == NULL ){ printf( "Can not open the meibo.dat.\n" ); exit( 1 ); } message(); fprintf( fp, "番号, 名前, TEL, 住所\n" ); fflush( fp ); cnt = 0; end = 0; while( end == 0 ){ input( fp, cnt, &a[cnt], &end ); cnt++; fflush( fp ); if( cnt == 20 ){ printf( "人数が一杯です.終了します.\n" ); end = 1; } } fclose( fp ); } void message( void ) { printf( "名前, TEL, 住所, endを入力してください.\n" ); printf( "継続の時はend=0," ); printf( "中止の時は,end=1と入力してください.\n" ); } void input( FILE *fp, int cnt, struct meibo *a, int *end ) { printf( "名前-->" ); scanf( "%s", a->name ); printf( "TEL -->" ); scanf( "%s", a->tel ); printf( "住所-->" ); scanf( "%s", a->address ); printf( "Exit? Continue:0 Exit:1 -->" ); scanf( "%d", end ); printf( "\n" ); fprintf( fp, "%2d, %s, %s, %s\n", cnt+1, a->name, a->tel, a->address ); } |
必ずプログラムの最初につけること. exit関数を使うために必要なヘッダファイル. 構造体meiboの宣言. 構造体の内容の定義. }の後のコンマを忘れないように! 入力を促す画面表示関数. 入力関数 構造体配列の定義. ファイルポインタの定義. カウンタ変数の定義. ファイルのオープン,書き込み型で定義する. 書き込めない場合に,エラー文を画面表示して, 終了する. 入力を促すメッセージ文を画面表示するための関数. ファイルの項目のファイルへの書き込み. ファイルポインタバッファの解放. カウンタ変数の初期化. 終了判定変数の初期化. 終了判定(0の場合にwhile文を実行する). 入力のための関数. カウンタの増分. ファイルポインタバッファの解放. カウンタが一杯の時の対応. ファイルポインタのクローズ. message関数の内容. 画面表示. input関数の内容. 入力を促す画面表示. scanf関数による変数への入力 終了判定変数への値の入力. 入力された値のファイルへの書き込み. |
| 実行結果 | 疑問に思って欲しい点 |
|
番号, 名前, TEL, 住所 1, 福田, 56-3478, 足利市 2, 田中, 65-9947, 足利市 3, 中村, 37-6587, 佐野市 4, 立花, 42-3456, 佐野市 5, 重田, 88-9987, 宇都宮市 -----ここまで----- 実行ファイルと同じフォルダでmeibo.dat というファイルをみつけ,内容を確認する. ファイル-開く-ファイルの種類(テキストファイル) でファイルを見つける. |
|
| Next!(さらに高度なことをやってみよう!) | |
|
|