31章 ポインタの配列
http://www.geocities.jp/ky_webid/c/031.html
char str[] = "abcde"; char *str = "abcde";
これらの違いについて詳しく説明されてるのでこれはきっちり覚えないといけないですね。
ポインタの配列
と、言ってますが読み進めてたところ、そこまで難しく考える必要はないみたいです。
結局のところ二次元配列のようなノリですね。ただし上記でも触れたように扱い方に少し違いがあるのでそこは注意が必要です。
問題1
次の2つのポインタ変数が、同じ文字列定数のアドレスを保持していることを確認する方法を考えて、プログラムを作って下さい。
char *p1 = "abcde"; char *p2 = p1;
これは簡単ですね。
int main () { char *p1 = "abcde"; char *p2 = p1; *p1 = '0'; printf("%s\n",p1); printf("%s\n",p2); return 0; }
$ main 0bcde 0bcde
p1経由で値を書き換えればp2も変わります。指してるアドレスが同じだから当然ですね。
答え合わせ
int main(void){ char *p1 = "abcde"; char *p2 = p1; if( p1 == p2 ) /* 保持するアドレスが等しいか */ { printf( "同じアドレスです\n" ); } else { printf( "異なるアドレスです\n" ); } return 0; }
そーゆー意味でしたか・・・。
わざわざ書き換えて確かめなくてもポインタ同士を比較すれば同じアドレスかどうかのチェックができるみたいです。
ラーニングしました。
問題2
5つの独立したint型変数に格納された正数を、それぞれ「1乗」「2乗」「3乗」「4乗」「5乗」して表示したいと思います。この作業を1つのfor文で行えるようにポインタ配列を使ってプログラムを書いて下さい。
とりあえずやってみましょう。
#define MAX 5 float power(float num,int pow){ int tmp = num; if ( pow == 0 ) { return 1; } if ( pow > 0 ) { while(--pow){ num *= tmp; } } else { num /= tmp; while(pow++){ num /= tmp; } } return num; } int main () { int i; int num1 = 1; int num2 = 2; int num3 = 3; int num4 = 4; int num5 = 5; int *num[] = { &num1, &num2, &num3, &num4, &num5 }; for(i=0;i<MAX;++i){ printf("%.f\n",power(*num[i],i+1)); } return 0; }
少しの問題の意味がわかりにくい感じもしましたが、多分これであってると思います。
累乗の処理は前に実装したのがあるのでそれを使いました。
答え合わせ
おお、完璧に近いくらいあってましたw
というか累乗の関数を分けるところまで一致してるとは・・・。
そして新情報。累乗をしてくれる関数が標準ライブラリに存在するみたいです。
ライブラリ関数にはpow関数という累乗を行う関数が用意されており、それは math.hという標準ヘッダをインクルードして使います。ちなみに、pow関数は次のように宣言されています。
このあたりのライブラリ関数も調べないといけないですね。
問題3
char*型の配列の先頭アドレスと、2つの添字を受け取り、添字が示す2つの要素のポインタを交換する関数を作って下さい。その関数を使って、この章の「要素の交換」で示したプログラム例を書き換えて下さい。
とりあえず交換する関数を実装してみます。
void swap(char *message[], int index1, int index2) { char *tmp; tmp = message[index1]; message[index1] = message[index2]; message[index2] = tmp; }
できました。簡単ですね。
あとはコレを使うだけです。実際に書き換えて動かしてみましたが、ちゃんと動いてました。
完璧っすね。