080303

「080303」の編集履歴(バックアップ)一覧に戻る
080303」を以下のとおり復元します。
*080303
前回はちょっと難しかったので今回は簡単…とは限らない。
ポインタの中でも一番厄介な関数ポインタを使ってみましょう。
まともにゲームプログラミングするなら知っておいて損はない、というかタスクシステムとかで普通に使います。

**関数ポインタをとる関数
int を取り int を返す関数のポインタを取り、その関数に0〜9までの整数を適用した結果を出力する関数を書いてください。
よくわからなかったら使用例と出力例を見てください。

**使用例
int add(int i){ return i + 1; }
int square(int i){ return i * i; }
apply_0to9(&add);
apply_0to9(&square);

**出力例
1 2 3 4 5 6 7 8 9 10
0 1 4 9 16 25 36 49 64 81

**解答例
 #include <stdio.h>
 int add(int i){ return i+1; }
 int square(int i){ return i*i; }
 void apply_0to9(int (*fp)(int)){
  int n;
  for(n=0; n<10; n++){
   printf("%d", fp(n));
   printf((n==9) ? "\n" : " ");
  }
 }
 int main(){
  apply_0to9(&add);
  apply_0to9(&square);
  return 0;
 }

**解説
与未さんから完璧な解答が何故かきたので一部いじって解答例に載せました。前から思ってましたが普通にC言語結構理解してますよね与未さん…
さて今回は、関数ポインタを引数にとる関数を書く、ということを兎に角やってもらいたかったため、内容は非常にシンプルです。
つまり「int (*fp)(int)」が全てです。
関数ポインタというものを理解していれば、すぐに書けたと思います。
関数というのは、実のところ「実行コードのアドレスを指すポインタ」に過ぎません(ほんとか?)そのためポインタ値としてそのまま取り扱う事ができるわけですね。

**関数ポインタの利点
関数ポインタを使うことで、「処理」を変数として扱う事ができます。
これの利点は、標準のqsortなどを見てもらえば分かると思います。値の比較の方法を渡してもらうことで、どんな値でもソーティングすることができるわけです。
他にも利点はあります。ゲームプログラミングでは、例えばアクションゲームを作っているとしましょう。プレイ中は↑の入力があったらキャラクタをジャンプさせ、ポーズ中はメニューの移動をさせたい。すると、入力がある度にポーズ中かどうかをチェックしないといけない。これは非常に面倒ですし無駄です。勿論入力を処理する部分をプレイ中とポーズ中とで分ける、という解決もありますし、プレイ中とポーズ中では処理が全く違うので普通はそうすべきだと思ったりもしますが…
関数ポインタを使うと以下のように書くことができます。
 void jump(); /* ジャンプする */
 void select_up(); /* 一つ上を選択 */
 void (*keydown_up)(); /* 矢印上が押されたときに実行されるべき関数へのポインタ */
 void main_frame(){
   ...
   switch(keydown){
     ...
     case KEY_UP:
       keydown_up();
       break;
     ...
   }
   ...
 }
このようにしておけば、プレイ中にポーズされた時、逆にポーズが解除された時にkeydown_up変数を書き換えるだけですみます。
ゲームプログラミングでは、他にもタスクシステムという重要な仕組みの実装に関数ポインタを使います。興味のある人は適当にぐぐったりしてみてください。タスクシステムの解説はまたそのうち。

**めんどくさいのでここで返事するぜー
ぐだぐだと。
 #include<stdio.h>
 int number(int num1,int num2);
 int main()
 {
  int (*gate)(int num1,int num2);
  int i,j;
  gate = number;
  printf("これはそれっぽいリストを書くプログラムです\n");
  for(i=0;i<10;i++)
  {
   for(j=0;j<10;j++)
   {
    printf("%2d ",(*gate)(i,j));
   }
   printf("\n");
  }
  return 0;
 }
 int number(int num1,int num2)
 {
  int answer;
  answer = num1 * num2;
  return answer;
 }
 よくはわかりませんがこんな感じでよろしかったのでしょうか?
 後、今回変になった所がありまして
 上記の”リスト”を”表”にすると
  
 warrning : unkonwn escape sequense: '\202'
  
 というのが出まして、このまま実行しますと
  
 ”これはそれっぽい浮 曹ュプログラムです”
  
 となってしまったのですが、そういう仕様なのでしょうか?
そういう仕様です。
まずソースコードに日本語を使うべきではありません。何故かというと、処理系は文字列を1byteずつ見ているからです。そのためにエスケープシーケンスなどが文字に含まれていた場合に問題が起こります。
どういうことかというと、日本語などのいわゆる2byte文字は、その名のとおり2byte以上の値を使って表現されています。それをプログラム側がちゃんとルールに従って理解し、表示した結果日本語などが一文字表示されるわけです。
詳しくは適当にぐぐるとこういうページが出るのでこちらに。
http://www.asahi-net.or.jp/~uc3k-ymd/Lesson/Section01/gcc_sjis.html

復元してよろしいですか?