C言語基礎|汎用的な関数

同じ“部品”でいろんな仕事をさせよう

前の記事では、決まった記号を並べるだけの関数を作って、三角形表示の見通しを良くしましたよね。
ここで一歩進めて、もっと使い回せる関数(汎用的な関数)にしてみましょう。

「同じ処理を、ちょっと条件を変えて何回も使いたい」
これ、プログラミングあるあるです。そこで登場するのが、引数で動作を切り替えられる関数です。

汎用的な関数って何?

ざっくり言うと、

  • 特定の用途だけに固定されていない。
  • 引数を変えるだけで別の用途にも使える。
  • いろんな場所で再利用できる。

そんな関数のことです。

専用関数と汎用関数の違い

種類できること便利さ
専用関数目的が固定星だけを並べる使う場面が限られる
汎用関数引数で用途を変えられる文字と回数を渡して並べるいろんな場面で使える

「星専用」から「好きな文字でOK」に変えるだけで、利用シーンが一気に広がります。

サンプルプログラム

ここでは タイトル付きの枠(フレーム)を描くプログラムを例にして、汎用関数の強みを体感します。

  • repeat_char:指定した文字を指定回数だけ表示する(汎用的)
  • draw_box:repeat_charを使って枠を描く(再利用の例)

プロジェクト名:chap6-8-1 ソースファイル名:chap6-8-1.c

Visual Studio でこのプログラムを実行するには、SDLチェック設定を変更しておく必要があります。
1.プロジェクト名を右クリックして、「プロパティ」をクリックします。
2.「C/C++」→「全般」→「SDLチェック」を「いいえ」に切り替えて「OK」をクリックします。

#include <stdio.h>

// 指定した文字chをn個連続して表示(値は返さない)
void repeat_char(int ch, int n)
{
    while (n-- > 0)
        putchar(ch);
}

// 幅widthのシンプルな枠を表示する
void draw_box(int width)
{
    // 上辺
    putchar('+');
    repeat_char('-', width);
    putchar('+');
    putchar('\n');

    // 中身(空行)
    putchar('|');
    repeat_char(' ', width);
    putchar('|');
    putchar('\n');

    // 下辺
    putchar('+');
    repeat_char('-', width);
    putchar('+');
    putchar('\n');
}

int main(void)
{
    int w;

    puts("タイトル枠を表示します。");
    printf("横幅を入力してください:");
    scanf("%d", &w);

    puts("----- 表示例 -----");
    draw_box(w);

    puts("同じ部品を使って、別の線も引けます。");
    repeat_char('=', w + 2);
    putchar('\n');

    return 0;
}

実行例

タイトル枠を表示します。
横幅を入力してください:10
----- 表示例 -----
+----------+
|          |
+----------+
同じ部品を使って、別の線も引けます。
============

repeat_char は枠の横線にも、空白にも、最後の強調線にも使えています。
これが「汎用性」の気持ちよさです。

汎用関数は“道具箱のドライバー”

引数で動作が変わる

入力(引数)repeat_charがすること出力
ch = '-' , n = 10- を10回表示----------
ch = ' ' , n = 10空白を10回表示(空白10個)
ch = '=' , n = 12= を12回表示============

同じ関数でも、引数が変わるだけで仕事が変わります。

表の説明(この記事で使ったものの補足)

  • 「専用関数と汎用関数の違い」表
    → 目的が固定されているか、引数で切り替えられるかを整理しました。汎用化すると、同じ関数を別の表示にも流用できるのがポイントです。
  • 「引数で動作が変わる」表
    → repeat_char が、文字chと回数nという2つの入力で動作を決めていることを示しました。ここが汎用化の核心です。

登場する命令の書式と役割

repeat_char の定義(書式)

  • void 関数名(引数...) { 文; }

  • void repeat_char(int ch, int n) { ... }

これは「値を返さず、表示処理だけをする関数」です。

while の書式

  • while(条件) 文

  • while (n-- > 0) putchar(ch);

意味:n が 0 より大きい間、putchar(ch) を繰り返す

putchar の書式

  • putchar(文字)

文字を1つ表示します。repeat_char がこれを何度も呼んで「連続表示」を作っています。

puts の書式

  • puts(文字列)

文字列を表示して改行します。見出し表示に便利です。

scanf の書式

  • scanf(書式, 変数のアドレス)

キーボード入力を読み込みます。今回だと width を読むために使っています。

よくある注意点(汎用関数でハマりやすいところ)

ありがちな落とし穴

注意点何が起きる?対策
回数nが負になる繰り返しが1回も動かない、または意図不明になる入力チェックを入れる
幅が小さすぎる枠が崩れる最低値を決める(例:1以上)
chをcharにしてもOK?putcharはintを受ける設計引数はintにしておくと安心

演習問題

演習6-6:合図をn回表示する関数を作ろう

指定した文字を n 回表示して改行する関数を作成せよ。

  • 関数名:signal_n
  • 返却値型:void
  • 引数:int ch, int n

プロジェクト名:chap6-8-2 ソースファイル名:chap6-8-2.c

Visual Studio でこのプログラムを実行するには、SDLチェック設定を変更しておく必要があります。
1.プロジェクト名を右クリックして、「プロパティ」をクリックします。
2.「C/C++」→「全般」→「SDLチェック」を「いいえ」に切り替えて「OK」をクリックします。

#include <stdio.h>

void signal_n(int ch, int n)
{
    while (n-- > 0)
        putchar(ch);
    putchar('\n');
}

int main(void)
{
    puts("合図を表示します。");
    signal_n('!', 5);
    signal_n('#', 8);
    return 0;
}

解説
repeat_char と同じ発想で、文字と回数を引数にすると、!でも#でも同じ関数で表示できます。これが汎用関数の基本形です。

まとめ:汎用性を上げるコツ

  • 固定値をやめて、引数で渡す(文字、回数、幅など)
  • 小さな処理を部品化して、他の関数から呼び出す。
  • 同じ処理が2回出たら、汎用関数のチャンス