2017年11月19日
《その141》 ポインタのポインタを渡す & p.97演習3-3
「@ 関数にポインタを渡す(オブジェクトのアドレスを渡す)」ことと
「A 関数にポインタのポインタを渡す(ポインタ自身のアドレスを渡す)」こと
の違いを考えてみます。
「@ 関数にポインタ p を渡す」
関数にポインタ p(の保持するアドレス)を渡すと、それを受け取った関数は、そのアドレスに書かれている内容、すなわちそのポインタ p が指すオブジェクト *p の値を変更できるようになります。
「A 関数にポインタ p のアドレス &p を渡す」
関数にポインタ自身のアドレス &p を渡すと、それを受け取った関数は、そのアドレスに書かれている内容、すなわちポインタ p が保持しているアドレス(ポインタ p が指す先)を変更できるようになります。
例えば、関数内で動的に配列 set[] を生成したような場合、ポインタ p が指す先を、配列の先頭アドレスに変更できるわけです。
つまり、関数が生成した配列を関数から main関数に渡すようなことが可能ということになります。
新版明解C++中級編 p.97 演習3-3
指定された条件を満たす全要素を配列から探索する関数 search_if_all を作成せよ。
int search_if_all(const int a[], int n, bool cond(int), int** idx);
先頭側の三つの引数は、前回《140》の演習3-2 と同様である。
指定された条件を満たす全要素の添字を格納するための配列を生成し、その配列の先頭要素へのポインタを、第4引数 idx の指すポインタに格納すること。なお、関数が返却するのは、格納した要素数(条件を満たした要素数)である(たとえば、配列 {1, 3, 6, 7, 8} から偶数である要素を探索した場合は、6 と 8 の添字である {2, 4} を格納する配列を生成して 2 を返却する)。なお、条件を満たす要素が存在しない場合は、idx の指すポインタに NULL を代入するとともに、0 を返却すること。
// p97_演習3-3
#include <iomanip>
#include <ctime>
#include <cstdlib>
#include <iostream>
using namespace std;
bool mlt_of_17(int x) { // 17の倍数
return x % 17 == 0;
}
bool mlt_of_23(int x) { // 23の倍数
return x % 23 == 0;
}
bool _80_to_90(int x) { // 80〜90の数
return x >= 80 && x <= 90;
}
bool prime_num(int x) { // 素数
bool b = true;
for (int i = 2; i <= x / i; i++) {
if (!(x % i)) {
b = false; break;
}
}
return b;
}
// main関数が用意したポインタ p 自身のアドレス &p を、
// ポインタのポインタ idx に受け取ります。
int search_if_all(
const int a[],
int n,
bool cond(int),
int** idx
) {
int num = 0;
for (int i = 0; i < n; i++)
if (cond(a[i])) num++;
if (num) {
int* vec = new int[num];
int index = 0;
for (int i = 0; i < n; i++)
if (cond(a[i])) vec[index++] = i;
*idx = vec;
// 新たに作成した配列の先頭要素アドレス vec
// を、*idx すなわちポインタp に書き込
// みます。
}
else {
*idx = NULL;
}
return num;
}
int main() {
srand((unsigned int)time(NULL));
int a[20];
int n = sizeof(a) / sizeof(a[0]);
for (int i = 0; i < n; i++) {
a[i] = rand() % 90 + 10;
cout << "a[" << setw(2) << i << "] = "
<< a[i] << '\n';
}
int* p;
int num = search_if_all(a, n, mlt_of_17, &p);
// ポインタ p は、関数 search_if_all が作る配列の
// 先頭要素のアドレスを格納してもらうための
// ものです。
// 引数として関数に渡すのは
// ポインタp の値(この時点では不定値)ではな
// く、ポインタp 自身のアドレス &p です。
cout << "\n☆\"17の倍数 \"の個数 : " << num;
cout << '\n';
for (int i = 0; i < num; i++)
cout << " 添字 : " << setw(2) << p[i]
<< ", 値 : " << a[p[i]] << '\n';
if (num) delete[] p;
int* q;
num = search_if_all(a, n, mlt_of_23, &q);
cout << "\n☆\"23の倍数 \"の個数 : " << num;
cout << '\n';
for (int i = 0; i < num; i++)
cout << " 添字 : " << setw(2) << q[i]
<< ", 値 : " << a[q[i]] << '\n';
if (num) delete[] q;
int* r;
num = search_if_all(a, n, _80_to_90, &r);
cout << "\n☆\"80〜90の数\"の個数 : " << num;
cout << '\n';
for (int i = 0; i < num; i++)
cout << " 添字 : " << setw(2) << r[i]
<< ", 値 : " << a[r[i]] << '\n';
if (num) delete[] r;
int* s;
num = search_if_all(a, n, prime_num, &s);
cout << "\n☆\"素数 \"の個数 : " << num;
cout << '\n';
for (int i = 0; i < num; i++)
cout << " 添字 : " << setw(2) << s[i]
<< ", 値 : " << a[s[i]] << '\n';
if (num) delete[] s;
}
この記事へのコメント
コメントを書く
この記事へのトラックバックURL
https://fanblogs.jp/tb/6986209
※ブログオーナーが承認したトラックバックのみ表示されます。
この記事へのトラックバック