【6日でできるC言語入門】ポインタの演習プログラム

 C言語の「ポインタ」は配列や文字列処理、関数との連携などさまざまな場面で登場します。ポインタの仕組みや使い方を身につけることで、より柔軟なプログラムが作成できます。ここでは、ポインタの活用を段階的に学ぶための演習プログラムを、すべて新しいバリエーションで解説します。

1.ポインタを使った配列操作の演習

1.1. 配列の中から3の倍数だけを抽出して表示する

課題
 長さ10の配列に1から15までの乱数を格納し、その配列から3の倍数だけを表示するプログラムを作成しましょう。3の倍数の表示にはポインタを使った関数print_multiple_of_threeを利用します。

関数仕様(表)

関数名引数戻り値処理内容
print_multiple_of_threeint* arr(配列)なし配列内の3の倍数を順に表示する

サンプルプログラム1

プロジェクト/ファイル名: Lesson57_1/main.c

#include <stdio.h>
#include <stdlib.h>
#include <time.h>

void print_multiple_of_three(int* arr);

int main(void) {
    int numbers[10];
    srand((unsigned)time(NULL));
    printf("生成された値: ");
    for (int i = 0; i < 10; i++) {
        numbers[i] = rand() % 15 + 1;
        printf("%d ", numbers[i]);
    }
    printf("\n");
    print_multiple_of_three(numbers);
    return 0;
}

void print_multiple_of_three(int* arr) {
    printf("3の倍数: ");
    for (int i = 0; i < 10; i++) {
        if (*(arr + i) % 3 == 0) {
            printf("%d ", *(arr + i));
        }
    }
    printf("\n");
}

実行結果

生成された値: 9 7 3 14 3 9 5 10 13 7
3の倍数: 9 3 3 9

1.2. 文字列の最初の母音の位置を探す

課題
 キーボードから英単語を入力し、その単語中で最初に現れる母音(a, e, i, o, u)の位置(インデックス)を表示するプログラムを作成します。ポインタを使った関数find_first_vowelを用います。

関数仕様

関数名引数戻り値処理内容
find_first_vowelchar* strint(位置)母音が最初に現れる位置を返す

サンプルプログラム2

プロジェクト/ファイル名: Lesson57_2/main.c

#include <stdio.h>

int find_first_vowel(char* str);

int main(void) {
    char word[100];
    printf("英単語を入力してください:");
    scanf("%s", word);
    int pos = find_first_vowel(word);
    if (pos >= 0) {
        printf("最初の母音は%d文字目です。\n", pos + 1);
    } else {
        printf("母音は含まれていません。\n");
    }
    return 0;
}

int find_first_vowel(char* str) {
    int index = 0;
    while (*str != '\0') {
        if (*str == 'a' || *str == 'e' || *str == 'i' || *str == 'o' || *str == 'u') {
            return index;
        }
        index++;
        str++;
    }
    return -1;
}

実行結果

英単語を入力してください:school
最初の母音は4文字目です。

2.ポインタを使った文字列処理の演習

2.1. 英単語中の小文字を「*」に置き換えて別の文字列に格納する

課題
 英単語を入力し、小文字のアルファベットを「*」に置き換えた新しい文字列を別の配列に作成して表示するプログラムです。変換にはポインタを使ったreplace_lowercase_with_asterisk関数を使用します。

関数仕様(表)

関数名引数戻り値処理内容
replace_lowercase_with_asteriskchar* src, char* destなしsrcの小文字を'*'に変換しdestへコピー

サンプルプログラム3

プロジェクト/ファイル名: Lesson57_3/main.c

#include <stdio.h>

void replace_lowercase_with_asterisk(char* src, char* dest);

int main(void) {
    char input[100], result[100];
    printf("英単語を入力してください:");
    scanf("%s", input);
    replace_lowercase_with_asterisk(input, result);
    printf("変換後の文字列:%s\n", result);
    return 0;
}

void replace_lowercase_with_asterisk(char* src, char* dest) {
    while (*src != '\0') {
        if (*src >= 'a' && *src <= 'z') {
            *dest = '*';
        } else {
            *dest = *src;
        }
        src++;
        dest++;
    }
    *dest = '\0';
}

実行結果

英単語を入力してください:HelloWorld
変換後の文字列:H****W****

2.2. 2つの文字列の先頭N文字を比較し、同じなら「先頭N文字は一致しています」と表示

課題
 2つの文字列と比較する文字数Nを入力し、先頭N文字が一致していればメッセージを表示するプログラムです。

サンプルプログラム4

プロジェクト/ファイル名: Lesson57_4/main.c

#include <stdio.h>
#include <string.h>

int main(void) {
    char str1[100], str2[100];
    int n;
    printf("1つ目の文字列を入力してください:");
    scanf("%s", str1);
    printf("2つ目の文字列を入力してください:");
    scanf("%s", str2);
    printf("比較する文字数を入力してください:");
    scanf("%d", &n);

    if (strncmp(str1, str2, n) == 0) {
        printf("先頭%d文字は一致しています。\n", n);
    } else {
        printf("先頭%d文字は一致していません。\n", n);
    }
    return 0;
}

実行結果

「SDLチェック」を「いいえ」にして、プログラムを実行します。

1つ目の文字列を入力してください:programming
2つ目の文字列を入力してください:program
比較する文字数を入力してください:7
先頭7文字は一致しています。

3.ポインタ演習の応用問題

3.1. 2つの文字列の共通文字をすべて表示する(重複は1回だけ)

課題
2つの文字列に共通して含まれる文字を重複なしで表示するプログラムです。

サンプルプログラム5

プロジェクト/ファイル名: Lesson57_5/main.c

#include <stdio.h>
#include <string.h>
#include <stdbool.h>

int main(void) {
    char str1[100], str2[100];
    bool printed[256] = {0};
    printf("1つ目の文字列:");
    scanf("%s", str1);
    printf("2つ目の文字列:");
    scanf("%s", str2);

    printf("共通して含まれる文字:");
    for (int i = 0; str1[i] != '\0'; i++) {
        for (int j = 0; str2[j] != '\0'; j++) {
            if (str1[i] == str2[j] && !printed[(unsigned char)str1[i]]) {
                printf("%c ", str1[i]);
                printed[(unsigned char)str1[i]] = true;
                break;
            }
        }
    }
    printf("\n");
    return 0;
}

実行結果

「SDLチェック」を「いいえ」にして、プログラムを実行します。

1つ目の文字列:computer
2つ目の文字列:output
共通して含まれる文字:o u t

解説

1. 意味・役割
  • bool printed[256]は、配列です。
    配列のサイズは256です。
  • 配列の各要素はbool型(真偽値、true または false)です。
  • = {0} で、すべての要素をfalseで初期化しています。
    = {0} は、配列のすべての要素を 0(ゼロ)で初期化する、という意味です。
    ・C言語では、配列の初期化で {0} と書くと、最初の要素が 0 で初期化され、残りも自動的に 0 になります
2. なぜ256?
  • char型(1文字)は、0~255の256種類の値を持つことができます。
    つまり、すべてのASCII文字やバイナリ値をカバーできるようにしています。
  • 例えば、文字'A'のASCIIコードは65なので、printed[65]'A'に対応します。
    「(unsigned char)」とキャストすることで、0~255の正の値に強制変換しています。
3. どう使っているか?
  • プログラムは「2つの文字列の中で、両方に共通して含まれる文字」を1度だけ表示するために動作します。
  • もし同じ文字が何度も共通していても、1回だけ出力したいときに、この配列を使います。
使い方の流れ
  1. まだその文字が出力されていない場合:printed[文字コード] == false
  2. 出力したら:printed[文字コード] = true にする
  3. 以降その文字にまた遭遇しても、!printed[文字コード]falseになるので、再出力されない
4.

たとえば

  • str1 = "apple"
  • str2 = "grape"
    の場合
  • 共通文字は a, p, e ですが、pstr1に2回出てきます。
  • この配列によってpは1回だけ出力されます。

3.2. 文字列中の数字('0'~'9')の個数を数えて表示する

サンプルプログラム6

プロジェクト/ファイル名: Lesson57_6/main.c

#include <stdio.h>

int main(void) {
    char text[100];
    printf("文字列を入力してください:");
    scanf("%s", text);
    int count = 0;
    for (int i = 0; text[i] != '\0'; i++) {
        if (text[i] >= '0' && text[i] <= '9') {
            count++;
        }
    }
    printf("数字の個数:%d\n", count);
    return 0;
}

実行結果

「SDLチェック」を「いいえ」にして、プログラムを実行します。

文字列を入力してください:abc12345xyz
数字の個数:5

まとめ

 ポインタは配列や文字列の操作、関数の引数、文字データの加工などC言語のあらゆる場面で登場します。
 この演習プログラムを通して、ポインタの使い方と基本動作を理解し、標準関数や自作関数を組み合わせて柔軟に問題を解決できるようになりましょう。
安全性や配列サイズのチェックも意識しつつ、さらなる応用問題にもチャレンジしてください。