C言語で Java Silver レベルの問題を作ってみる No.18
プログラミング言語って、しばらく触れてないと細かな部分を忘れてしまいますよね。また、複数のプログラミング言語を習得している人は、頭がこんがりますね。
そんな方におススメしたいのが、資格試験の問題を1日5問程度解いていく方法です。毎日のスキマ時間を活用して短時間で知識レベルを維持することが出来ますよ。Javaならば、Silverの問題集が最適です。
Silverを既に取得している人も、これから取得を目指している人もぜひ試してみてください。
さて、この記事では、タイトルの通り、C言語をテーマにしています。
問題を毎日5問投稿していきますので、C言語を習得中の方、C言語の知識を維持されたい方は、ぜひご活用ください。
■ 関数とポインタ
□ 1. 次のプログラムをコンパイルし、実行したときの出力結果として、正しいものを選びなさい。(1つ選択)
#include <stdio.h>
float average(int count, int *numbers) {
int sum = 0;
int i;
for (i = 0; i < count; i++) {
sum += numbers[i];
}
return (float)sum / count;
}
int main(void) {
float (*pAvg)(int, int *);
int nums[4] = {15, 25, 35, 45};
pAvg = average;
float avgValue = pAvg(4, nums);
printf("平均値は %.2f です。\n", avgValue);
return 0;
}
A. 平均値は 20.00 です。
B. 平均値は 30.00 です。
C. 平均値は 35.00 です。
D. 平均値は 40.00 です。
□ 2. 次のプログラムをコンパイルし、実行したときの結果として、正しいものを選びなさい。(1つ選択)
#include <stdio.h>
void greet(void) {
printf("こんにちは!\n");
}
void farewell(void) {
printf("さようなら!\n");
}
int main(void) {
void (*pMessages[2])(void);
pMessages[0] = greet;
pMessages[1] = farewell;
int i;
for (i = 1; i < 2; i++) {
pMessages[i]();
}
return 0;
}
A. 「こんにちは!」と表示される
B. 「さようなら!」と表示される
C. コンパイルエラーが発生する
D. 実行時エラーが発生する
■ ポインタのポインタ
□ 3. 次のプログラムを実行したときに実行結果のように表示したい。空欄に入るコードとして、正しいものを選びなさい。(1つ選択)
#include <stdio.h>
void update_value(int **ppValue) {
static int value = 10;
_____空欄_____;
}
int main(void) {
int *pValue;
update_value(&pValue);
printf("値:%d\n", *pValue);
return 0;
}
[実行結果]
値:10
A. *ppValue = value
B. ppValue = &value
C. *ppValue = &value
D. ppValue = value
□ 4. 次のプログラムをコンパイルし、実行したときの結果として、正しいものを選びなさい。(1つ選択)
#include <stdio.h>
void set_array(int **ppArray) {
static int arr[3] = {1, 2, 3};
*ppArray = arr;
}
int main(void) {
int *pArray;
set_array(&pArray);
int i;
for(i = 0; i < 3; i++)
printf("%d ", pArray[i]);
printf("\n");
return 0;
}
A. 「1 2 3」と表示される
B. 何も表示されない
C. コンパイルエラーが発生する
D. 実行時エラーが発生する
□ 5. 次のプログラムをコンパイルし、実行したときの出力結果として、正しいものを選びなさい。(1つ選択)
#include <stdio.h>
#include <stdlib.h>
int compare(const void *a, const void *b) {
return -(*(int *)a - *(int *)b);
}
int main(void) {
int arr[5] = {5, 3, 2, 4, 1};
qsort(arr, 5, sizeof(int), compare);
int i;
for (i = 0; i < 5; i++) {
printf("%d ", arr[i]);
}
printf("\n");
return 0;
}
A. 1 2 3 4 5
B. 5 4 3 2 1
C. 1 3 2 4 5
D. 5 3 1 4 2
解答
1.B
このプログラムでは、以下の手順で動作します。
関数 average の定義:
引数 count は配列の要素数、numbers は整数型のポインタで、配列のアドレスを受け取ります。
変数 sum を初期化し、0から count までのループで各要素を sum に加算します。
平均値の計算:
ループが終了した後、合計 sum を count で割り、平均値を計算します。このとき、sum を float 型にキャストして割り算を行うことで、平均が小数点以下も考慮されます。
main 関数の動作:
nums という配列に {15, 25, 35, 45} の4つの整数を格納します。
関数ポインタ pAvg に average 関数のアドレスを代入します。
pAvg を用いて average 関数を呼び出し、配列の要素数(4)と配列 nums を引数として渡します。この呼び出しで平均値が計算され、avgValue に格納されます。
結果の出力:
計算された平均値は (15 + 25 + 35 + 45) / 4 = 30.00 となり、printf によって「平均値は 30.00 です。」と出力されます。
このプログラムの実行結果は「平均値は 30.00 です。」であり、選択肢の中で正しいのは2番となります。
2.B
このプログラムでは、関数ポインタの配列 pMessages に greet と farewell の関数を格納します。関数名はその関数のアドレスを示しますので、
pMessages[0] にはgreet関数のアドレス、
pMessages[1] にはfarewell関数のアドレスが格納されます。
続くfor文の繰り返しの中で、pMessages[1]()が実行されるとfarewell()関数が実行され、「さようなら!」と出力されます。
3.C
このプログラムでは、update_value 関数がポインタのポインタを使って value のアドレスを戻り値として返します。空欄には、ポインタのポインタである ppValue が指す先に value のアドレスを代入する必要があります。選択肢3の *ppValue = &value が正しく、value のアドレスを pValue に設定することができます。他の選択肢は正しい文法ではありません。
4.A
・関数 set_array:
引数 int **ppArray は「ポインタのポインタ」です。これは、ポインタが指すポインタのアドレスを受け取ります。
static int arr[3] = {1, 2, 3}; によって、配列 arr が定義され、静的にメモリに格納されます。静的配列は、プログラムの実行中ずっとメモリに存在し続けます。
*ppArray = arr; では、ppArray が指すポインタ(ここでは pArray)に arr のアドレスを代入します。これにより、pArray は arr を指すようになります。
・main 関数:
int *pArray; でポインタ pArray を宣言します。これは配列の最初の要素を指すポインタになります。
set_array(&pArray); で set_array を呼び出し、pArray のアドレスを渡します。これにより、set_array 内で pArray の値が更新され、配列 arr を指すようになります。
for ループでは pArray[i] を使って配列の要素を表示します。これにより、1 2 3 が出力されます。
5.B
このプログラムで使われているqsort 関数は、C言語の標準ライブラリに含まれる関数で、任意の型の配列をクイックソートアルゴリズムを使って並び替えます。
構文:
void qsort(void *base, size_t num, size_t size, int (*compare)(const void *, const void *));
引数の説明:
base:
ソート対象の配列の先頭アドレスを指すポインタ。
num:
配列内の要素の数。
size:
各要素のサイズ(バイト単位)。通常、sizeof(要素の型) で指定します。
compare:
要素を比較するための関数ポインタ。この関数は2つの const void* ポインタを引数に取り、比較結果に基づいて整数を返します。
戻り値:
負の値: 第一引数が第二引数より小さい。
0: 二つの引数が等しい。
正の値: 第一引数が第二引数より大きい。
上記の戻り値が返されるとき、ソート対象の配列は昇順にソートされます。
問題のプログラムでは、(int *)でキャストを書いてint型のポインタであるとコンパイラに教えた後、間接演算子「*」を付けることでポインタが指している値を参照します。
return -(*(int *)a - *(int *)b);
そして、a の値から b の値を引いた結果にマイナスを付けることで、昇順ではなく降順に並び替えるための結果を返します。
お疲れ様でした。
継続は力なりです。
明日も頑張りましょう!
この記事が気に入ったらサポートをしてみませんか?