
C言語入門|8章の練習問題
8章では 「関数」 をテーマに、プログラムを部品化して扱いやすくする方法を学びました。
関数は C 言語の学習の中でも、特に「可読性」「再利用性」を大きく高めてくれる頼もしい存在です。
ただ、「関数は難しそう…」という声もよく聞きます。
そこでこの序章では、関数の役割や呼び出しの仕組みを 図解や表を使って直感的に理解できるように 解説していきます。

関数とは?
関数は「何か1つの仕事をまとめた小さなプログラム」のことです。
たとえば、
- 画面にメッセージを表示する。
- 数値を受け取って計算する。
- 判定を行って結果を返す。
など、「1つの役割」を持つものを関数として切り出します。
■ 関数のイメージ(表で理解)
| 要素 | 役割 |
|---|---|
| 関数名 | 部品の名前。呼び出すときに使う |
| 引数 | 関数に渡すデータ |
| 戻り値 | 関数が返す結果 |
| 本体 | 実際の処理({} の中) |
以下のような箱イメージで考えると、とても理解しやすくなります。
| 関数名:calcPrice |
|---|
| 引数:数量、単価 |
| 処理:数量 × 単価 |
| 戻り値:合計金額 |
「calcPrice(quantity, unitPrice)」のように箱に値を渡すと、
処理が行われて、戻り値が“ポンッ”と返ってきます。
関数定義の書式(表でまとめ)
8章で登場する命令(関数定義)の基本形は次の通りです。
| 書式 | 説明 |
|---|---|
| 戻り値の型 関数名(引数リスト) { 処理 } | 関数を定義する基本形 |
例
void hello(void)
{
printf("こんにちは!プログラムからのメッセージです。\n");
}- 戻り値がないときは void
- 引数がないときも void
- 処理内容は {} の中に書く
関数呼び出しの書式
呼び出すときは、たったこれだけです。
| 書式 | 説明 |
|---|---|
| 関数名(引数); | 関数を実行(呼び出す) |
例
hello();これだけで定義済みの関数が動きます。
関数が呼び出される流れ
| 手順 | 内容 |
|---|---|
| ① main から関数を呼ぶ | calcArea(10.0) |
| ② 値が引数に入る | radius = 10.0 |
| ③ 関数内の処理を実行 | 面積を計算 |
| ④ 結果が戻り値として返る | return area; |
| ⑤ main で受け取る | double a = calcArea(10.0); |
関数を使うメリット
| メリット | 説明 |
|---|---|
| コードが読みやすくなる。 | main がスッキリする。 |
| 再利用できる。 | 同じ処理を何度も書かずに済む。 |
| 修正が楽になる。 | 関数だけ直せば全部に反映される。 |
| 役割が明確になる。 | 「何をするコードか」が名前でわかる。 |
8章の練習問題
ここからは「8章で学んだ関数の基礎〜応用」を実践的に身につけるための練習問題です。
引数・戻り値・条件分岐・関数分割・関数修正ポイント・再帰の理解などをバランスよく扱っています。
【練習8-1】(関数定義:基本)
次の仕様を満たす関数を定義してください。
処理内容は書かなくてよいものとします。
(1) 「こんにちは」「こんばんは」など、時間帯に応じた挨拶を表示する greet 関数
- 引数:なし
- 戻り値:なし
(2) 三角形の底辺と高さを受け取り、面積を返す calcTriangleArea 関数
- 引数:double 型を2つ
- 戻り値:double 型
(3) 現在のCPU時間(clock() 関数の戻り値)を long 型で返す getCpuTime 関数
- 引数:なし
- 戻り値:long 型
(4) 引数として int 型の点数を受け取ると、合否判定(60点以上で合格)を返す isPass 関数
- 引数:int 型
- 戻り値:bool 型
【解答例】
(1)
void greet(void);
(2)
double calcTriangleArea(double base, double height);
(3)
long getCpuTime(void);
(4)
bool isPass(int score);【解説】
- 戻り値・引数の型が正しく書けているかがポイント
- 処理内容(本体)は不要なので 書式の理解 が重要
- 関数名は “何をするか” が分かるように命名している。
【練習8-2】(条件判定関数の完成)
次の仕様に従って、練習8-1 (4) の isPass 関数を完成させ、
この関数を呼び出す main 関数を作成してください。
【合否判定ルール】
- 60 点以上 → 合格
- 60 点未満 → 不合格
【表示例】
- 合格だった場合:
「75 点は合格です。」 - 不合格だった場合:
「42 点は不合格です。」
【解答例】
#include <stdio.h>
#include <stdbool.h>
bool isPass(int score)
{
return score >= 60;
}
int main(void)
{
int score = 75;
if (isPass(score)) {
printf("%d 点は合格です。\n", score);
} else {
printf("%d 点は不合格です。\n", score);
}
return 0;
}【解説】
- isPass は「真偽を返す」ため return score >= 60; という書き方が最もスマート
- 三項演算子でも書けるが、今回は if の方が読みやすい
- main で関数を呼んで表示する流れが 8章の基本の形
【練習8-3】(関数修正ポイントを探す問題)
次のプログラムは「歩く → 電車に乗る → 走る → 走る」の順に出力します。
#include <stdio.h>
void train(void)
{
printf("電車に乗ります。\n");
}
void jog(void)
{
printf("走ります!\n");
}
void walk(void)
{
printf("歩きます。\n");
}
int main(void)
{
printf("出発!\n");
walk(); train(); jog(); jog();
printf("帰宅。\n");
return 0;
}このプログラムを 「走った後には必ず歩く」 ようにするために修正すべき点を 2つ 挙げてください。
ただし main の変更とプロトタイプ宣言は禁止とします。
【解答例】
修正すべき点はこれ
1.jog 関数の中で walk を呼び出すよう変更する。
void jog(void)
{
printf("走ります!\n");
walk(); // 走ったあとは歩く
}2.walk 関数を jop より下に移動(または jog を walk より上に移動)する。
→ なぜなら、プロトタイプ宣言を使えないため 定義順に依存するから
【解説】
- main は変更不可なので、呼び出しの順番を変えることはできない。
- jog() の中に walk() を組み込むことで「走ったら歩く」を実現する。
- プロトタイプなし → 呼び出す関数は 先に定義する必要がある。
→ これに気づくことがポイント
【練習8-4】(類似問題:ポイント分配プログラム)
次の仕様を満たす 「ポイント分配プログラム」 を作成しなさい。
元の割り勘プログラムと同様に、処理を 3 つの関数に切り出し、main から呼び出す形に変更すること。
【条件】
- 総ポイント(例:1260ポイント)をメンバー人数で割り、
1人あたりの配布ポイントを整数単位で切り上げ て求める。
→ 小数点以下が発生したら必ず 1 ポイント上乗せする。 - 配布後に端数が余った場合、
余ったポイントはリーダーが受け取る。 - 入力は文字列で受け取り、整数に変換する。
【作成する関数】(3 つ)
(1)iget 関数:入力 → int 変換
| 項目 | 内容 |
|---|---|
| 戻り値 | 入力された値(int 型) |
| 引数 | なし |
| 機能 | scanf で文字列入力し、atoi で整数に変換して返す |
(2)calcPoint 関数:分配ポイントの計算
| 項目 | 内容 |
|---|---|
| 戻り値 | 1人あたりの配布ポイント(切り上げ後の int 型) |
| 引数 | 総ポイント、人数 |
| 機能 | 小数点があれば切り上げて整数にする |
| 例 | 1260 ÷ 11 → 114.545… → 115 |
(3)showResult 関数:結果表示
| 項目 | 内容 |
|---|---|
| 戻り値 | なし |
| 引数 | 1人あたりポイント、余りポイント、総人数 |
| 機能 | 結果を読みやすく表示する |
【解答例】
#include <stdio.h>
#include <stdlib.h>
int iget(void)
{
char buf[1024];
scanf("%s", buf);
return atoi(buf);
}
int calcPoint(int total, int members)
{
double tmp = (double)total / members;
int point = (int)tmp; // 切り捨て
if ((double)point < tmp) {
point += 1; // 小数点以下があれば切り上げ
}
return point;
}
void showResult(int point, int extra, int members)
{
printf("*** ポイント配布結果 ***\n");
printf("1人あたり %dpt(%d人)、リーダーは %dpt を受け取ります。\n",
point, members - 1, extra);
}
int main(void)
{
int total, members;
int point, leader;
printf("総ポイントを入力してください:");
total = iget();
printf("参加メンバー数を入力してください:");
members = iget();
point = calcPoint(total, members);
leader = total - point * (members - 1);
showResult(point, leader, members);
return 0;
}【解説】
iget 関数
- 文字列として入力したものを atoi で整数化
- 入力まわりを関数化すると main がスッキリする
calcPoint 関数
- 割り算 → double
- 切り捨て値よりも元の値が大きければ「小数点以下がある」
- そのとき +1 して切り上げ
- 100 円単位→ポイント単位に変わっただけでロジックは同じ
showResult 関数
- 表示専用の関数にすることで
「ロジックと表示の分離」 が学べる - 人数から 1 を引くのは、リーダー以外の人数のため
【練習8-5】(再帰関数の理解)
次の仕様を満たす 再帰関数 sumToN を定義してください。
【sumToN の仕様】
- 引数 n を受け取り、
1 〜 n までの合計を返す - 再帰を使って実装すること
例
sumToN(5) → 1+2+3+4+5 = 15【解答例】
int sumToN(int n)
{
if (n <= 1) return n;
return n + sumToN(n - 1);
}【解説】
- 再帰は「自分自身を呼び出す関数」
- 終端条件(停止条件) が必要
- sumToN(n) = n + sumToN(n-1) という数学的定義そのまま
- 再帰の“美しさ”を感じられる基本問題
【練習8-6】(実用ミニプログラム:温度変換関数)
次の仕様を満たす温度変換プログラムを作成してください。
【仕様】
- double toFahrenheit(double c)
→ 摂氏 c を華氏に変換して返す
(式:F = C × 9/5 + 32) - double toCelsius(double f)
→ 華氏 f を摂氏に変換して返す
(式:C = (F - 32) × 5/9) - main で以下を実行・表示
・摂氏 30℃ を華氏へ
・華氏 98.6°F を摂氏へ
【解答例】
#include <stdio.h>
double toFahrenheit(double c)
{
return c * 9.0 / 5.0 + 32.0;
}
double toCelsius(double f)
{
return (f - 32.0) * 5.0 / 9.0;
}
int main(void)
{
double f = toFahrenheit(30.0);
double c = toCelsius(98.6);
printf("30℃ = %.2f°F\n", f);
printf("98.6°F = %.2f℃\n", c);
return 0;
}【解説】
- 「入力 → 処理 → 戻り値」という関数の基本形が明確
- 数学式をそのままコードにできる良い練習
- 単体テストがしやすく、関数の役割がはっきりしている。
