プログラミング制作 (金曜4限:担当 前田)


実行結果を確認してから、プログラムのソースファイルを
課題提出用アドレ ス lect@pc2617.heisei-u.ac.jp へメールで( 課題提出の注意事項 にしたがって)提出してください。その際、プログラムの最初にコメントと して授業名、日付、氏名、学籍番号を念のためにいれておいてください。不 備の場合は提出したものとみなせない場合があります。


10月5日の課題

以下のいずれか1つを解いてください。
  1. 初級
    テキストの6章、および
    配列 を参考にして、
    • 整数の配列 a[8] を用意して、
    • a に標準入力から8個の数字を読み込み、
    • それを大きい順に並び変え
    • それを出力する
    プログラムを作成してください。
    ちなみに個数のところは #define のマクロ 定義 を使っておくと、あとあと簡単に個数が変更できます。

  2. 中(〜上)級
    配列 の例題は並びかえ(ソート)の 1つのバブルソートでしたが、ソートには他にもよく知られたアルゴリズム が多数あります。ここではそのうちの1つで、バブルソートより効率が良い とされている、バケツソート (bucket sort、あるいはビンソート bin sort と呼ばれる)を紹介します。
    本当はさらに効率の良いクイックソートというのがあるのですが、これは (再帰)関数を修得していないと使えないので、またの機会とします。
    • まず、前提として、並びかえの対象となる要素の値が、1からn (例えば100) までの範囲に収まる整数で、かつ同じ値になることはないとします。
    • そして、1に対応する要素を納める場所、2に対応する要素を納める場所、… というふうに n 個の要素を納める場所(=配列)を用意します。
    • そして、各要素の値の対応するところに、要素を納めます。
    • その後、1に対応する要素を納める場所、2に対応する要素を納める場所、… というふうに順に取りだします。データが空の場合はその場所を抜かせばば よいだけです。

    これをプログラムにしてください。とりあえず、データは1から100まで の範囲で、標準入力から8つ読みこんで、小さいものから表示するようにし ておいてください。

    解答の1例 です。


10月12日の課題

以下のいずれか1つを解いてください。
  1. 初級
    テキストの7章、および
    ポインタと配列 を参考にして、
    • 整数の変数 a と ポインタ変数 p を用意し
    • p に a のアドレスを代入し
    • a に 3 を代入し *p を出力し
    • *p に 4 を代入し a を出力する
    プログラムを作成してください。

  2. 中級
    初級のプログラムを malloc() を使うように改造(かつ簡略化)してくださ い。すなわち;
    • 整数のポインタ変数 p を用意し
    • p に malloc() した結果のポインタを代入し
    • *p に 4 を代入し *p を出力する
    プログラムを作成してください。

10月19日の課題

以下のいずれか1つ(できればどちらも)を解いてください。
  1. 初級
    テキストの7・3、7・4、および
    文字列のポインタ操作 の例題を参考にして、文字列の長さを数えるプ ログラムを作成してください。すなわち、
    • ポインタ変数 cp と、カウンタ用の i を用意し
    • cp の値として "APROG" という文字列(のアドレス)をいれ
    • for ループで cp の指す文字列の長さをi でカウントして
    • i を出力する
    ものです。
    例題のループで、コピーをさぼって i だけ増加させれば文字の 長さを順におっていってることになります。

  2. 中級
    例題のプログラムをさらに拡張して、文字列を連結する プログラムを作成してください。すなわち、
    • 文字配列 str (長さは十分に、たとえば 20)と ポインタ変数 cp,cp2 と、カウンタ用の i を用意し
    • cp の値として "hannan-u." という文字列(のアドレス)をいれ
    • cp2 の値として "ac.jp" という文字列(のアドレス)をいれ
    • for ループで str に cp の実体をコピーして
    • その続きから for ループで str に cp2 の実体をコピーして
    • str を出力する
    ものです。

10月26日の課題

以下のいずれか1つを解いてください。
  1. 初級
    テキストの7・5、および
    ポインタの配列 の例題を参考にして以下のプ ログラムを作成してください。
    • 文字列のポインタの 3 要素の配列 strs[3] とカウンタ i を用意して、
    • strs[0] に "gi?????" の先頭アドレス(gi????? は 各自のユーザID)を代入し、
    • strs[1] に "@hannan-u" (の先頭アドレス)を代入し、
    • strs[2] に ".ac.jp" (の先頭アドレス)を代入し、
    • i を 0 から 3 未満までループさせ strs[i] を出力させ、
    • 最後に改行する。

  2. 中級
    初級のプログラムを改造して、文字列を標準入力から3つ読みこみ、それを 連結して出力するプログラムを作成してください。すなわち、
    • 文字配列 str (長さは十分に、たとえば 80)と ポインタ変数の 配列 atrs[3] と、カウンタ用の i を用意し
    • i を 0 から 3 未満までループさせ、「以下のルーチン」
      • まず str に入力し、
      • その長さをしらべ、
      • その長さ+1 (ヌル文字分)のメモリを確保しそのメモリのアドレスを strs[i] に代入し、
      • str の内容をその確保したメモリにコピーする
      を実行し、
    • i を 0 から 3 未満までループさせ strs[i] を出力させ、
    • 最後に改行する。
    ものです、ここで、「以下のルーチン」は以下のようになるはずです; scanf("%s",str); strs[i] = (char*) malloc(strlen(str)+1); strcpy(strs[i],str); ここでは詳細は略しますが、malloc はメモリ確保のライブラリ関数、 strcpy は文字列をコピーするライブラリ関数です。この場合、 #include <stdio.h> #include <stdlib.h> #include <string.h> のヘッダをインクルードする必要があるかもしれません。
    こうすることにより無駄なメモリの確保を防ぐ(必要十分な領域だけ使う) ことが可能になります。定石といってもよいでしょう。

  3. 上級
    中級の例題を (buffer overflow 対策ということで)scanf ではなく fgets() を使ったらどうなるかを考えてください。fgets の場合、最後の改 行まで文字列として保存されるので、その改行をとってやらないとうまくつ ながりません。

11月16日の課題

以下のいずれか1つを解いてください。
  1. 初級
    テキストの9・1〜3、および
    関数 の例題を参考にして以下のプログラムを作成してください。
    • 文字列をコピーする関数 stringcopy を宣言する。 宣言は以下の通り; void stringcopy(char* dest, char* src); 第2引数 src の内容を 第1引数 dest へコピーするものとし、dest には 十分な領域が確保されていると仮定してよい。
    • 文字列 char h1[] = "hannan-u" と char h2[10] を用意する。
    • stringcopy(h2,h1); という関数呼び出しにより h2 へ h1 の内容をコ ピーする。
    • h2 の内容を出力する。
    ようするに、 10月26日の課題 の中級編ででて きた strcpy を自作せよ、ということです。実はこれは、 文字列のポインタ操作 の例題を関数化する、 ということです。

  2. 中級
    文字列操作関数(string.h で定義されてるもの)には、strcpy のほかに strlen (文字数を数える)や strcat (文字列の連接)があります。 ここでは、strcat() をつくってみましょう。すなわち

    • 宣言は以下の通り; void strcat(char* dest, char* src);
    • 第2引数 src の内容(文字列)を 第1引数 dest の内容の後に くっつける。
    • dest には、繋げた文字列が格納できる十分な領域が確保されていると 仮定してよい。

    というものです、これをつかって、

    char s1[80]="hannan-u",s2[]=".ac.jp"; という文字列を用意して、 s1 に s2 の内容をくっつけて、その結果の s1 を 出力するプログラムを作成してください。
    まず s1 の文字列を最後まで読み飛ばして、その続きから初級と同様に文字 をコピーしていけばよいです。

11月30日の課題

以下のいずれか1つを解いてください。
  1. 初級
    再帰関数について をの例題を参考 にして冪乗を計算する (2引数 a,b で、ab を返す)関数 power を作成し、main で例題のように for 文を用いて 3の1乗から5乗 を出力するプログラムを作成してください。ただし、a,b ともに正の整数と 仮定してかまいません。
    abを求める冪乗の漸化式は、
    • b>=1 の時: ab = a * ab-1
    • b==0 の時: a0 = 1

  2. 中級
    並びかえ のところでもすこし話題にした、クイッ クソートを紹介します。ここでは、対象データは整数で、配列に格納されて るとし、それを data[] とします。とりあえずは 10 個のデータと して int data[10]={4,7,1,9,6,8,10,2,3,5}; で初期化されてるとしましょう。すると関数 quicksort(int data[],int start,int end) は以下のようになります。引数は、第1がデータのはいっている配列、第 2は並びかえ対象のデータがその配列の何番目からか、第2は並びかえ対象 のデータが何番目までか、を示しているものとします。
    • まず、その配列のデータ範囲のなかで、適当な中間値を選びます。上 の例では、最初はstart は 0, end は 9 でデータ数は10個なので半分の5 番目、すなわち data[4] (=6) を中間値とします。
    • そうしたら、配列全体を左右に(右が大きい)並べた時に、左は中間 値 (6) 未満、右はそれ以上になるように並びかえます。具体的には以下の ようなルーチンになります。 i = start,j = end; while (i<j) { /* 左右から挟みこむように見ていく */ while (data[i] < val) i++; /* 左から… */ while (data[j] > val) j--; /* 右から… */ if (i<=j) { /* このステップに来たということは、data[i] は中間値以上、 data[j] は中間値以下 */ int bf = data[i]; data[i] = data[j]; data[j] = bf; /* ↑3ステップで data[i] と data[j] を交換して */ i++;j--; /* 読み進む */ }
    • 左右にわけた結果、
      • もし左の要素がまだ2つ以上あるなら、その2以上の配列部に対して (newstart1 番目から newend1 番目が並びかえの対象として) quicksort(int data[],int newstart1,int newend1) を呼び出す。
      • もし右の要素がまだ2つ以上あるなら、その2以上の配列部に対して (newstart2 番目から newend2 番目が並びかえの対象として) quicksort(int data[],int newstart2,int newend2) を呼び出す
    上の繰り返し(再帰呼び出し)により、段々左右に振分けられていって、つ いには全体が順番にならぶ、というわけです。これを実装(プログラム作成) してみてください。

12月07日の課題

以下のいずれか1つを提出してください。
  1. 初級
    構造体について の例題を参考にして、構造体変数を利用して Class no.1: yamada-sensei, 30 nin Class no.2: sato-sensei, 35 nin Class no.3: suzuki-sensei, 32 nin と画面に表示させるプログラムを作成してください。
    配列要素が3つになっていることに注意してください。たとえば以下のよう な宣言をするといいでしょう。 struct kumi { int bangou; char sensei[10]; int ninzuu; };

  2. 中級
    初級の問題を改造して;
    構造体変数の値は初期化するのではなく、キーボー ド(標準入力)から入力させるように変更してください。そしてその入力結果を 画面に表示するプログラムを作成してください。
    入力するところも for でループさせます。メンバ各々のデータ型に注意!

12月21日の課題

以下のいずれか1つを提出してください。
  1. 初級
    構造体とポインタ の例題を参考にして、構造体変数を利用して、さらに その構造体のポインタを引数にとる関数を作成し、 Class no.1: yamada-sensei, 30 nin Class no.2: sato-sensei, 35 nin Class no.3: suzuki-sensei, 32 nin と画面に表示させるプログラムを作成してください。
    前回と同様、以下の構造体を使ってください。 struct kumi { int bangou; char sensei[10]; int ninzuu; }; また、例題の pout もすこし書き直す必要があります。というよりは、前回 の課題の出力部分を関数化するほうが楽かもしれません。

  2. 中(〜上)級
    構造体とポインタ の最後の例題についてさらに考察します。この例題の 場合は、リストが単方向(前から後にしか辿れない)のですが、 構造体を typedef struct _list_cell { int data; struct _list_cell *prev,*next; } list_cell; typedef list_cell list ; として、自分の手前のセルのポインタも持つようにすると、前後に辿れるの で非常に使い勝手がよくなります。これを実装してみてください。


課題提出用アドレス(件名に注意!)

一番最初へ戻る

トップ・ページへ戻る


前田としゆき / d-maeda@hannan-u.ac.jp / maechan@heisei-u.ac.jp