C言語の問題でソースコードが思いつかないときの考え方|問題文からアルゴリズムを組み立てる手順を解説

C言語関連

C言語の課題で「ソースコードを書いてください」と言われても、いきなりコードを書き始めると手が止まりやすいものです。大切なのは、C言語の文法を片っ端から思い出すことではなく、問題文を「入力・処理・出力」に分解し、その処理を小さな手順へ変換することです。

また、「C言語の問題なのですがソースコードを教えてください」という情報だけでは、具体的なプログラムを一つに決めることはできません。問題文に「何を入力するのか」「何を計算するのか」「何を表示するのか」「繰り返しや条件があるのか」といった条件が必要だからです。

そこでこの記事では、特定の一問だけに答えるのではなく、C言語の問題を見たときにどのように考えればソースコードへ落とし込めるのかを、具体例とともに順番に解説します。

まず問題文を「入力・処理・出力」に分ける

C言語の課題を解くとき、最初に確認したいのが「入力」「処理」「出力」の3つです。ほとんどの初級プログラムは、この3要素に分けて考えられます。

確認すること 意味
入力 プログラムが受け取る値 整数を2個入力する
処理 入力値を使って何をするか 2個の整数を足す
出力 最終的に何を表示するか 合計を表示する

例えば「整数を2つ入力し、その合計を表示する」という問題なら、入力は整数2個、処理は加算、出力は合計値です。この段階まで整理できれば、必要なC言語の要素も自然に見えてきます。

いきなりC言語で書かず、日本語で処理手順を書く

初心者ほど、問題を読んだ直後に int main(void) から書き始めがちです。しかし、まず日本語で処理手順を書いたほうが間違いを減らせます。

例えば「整数を2つ入力して大きいほうを表示する」という問題なら、次のように考えます。

  1. 整数aを入力する
  2. 整数bを入力する
  3. aとbを比較する
  4. aのほうが大きければaを表示する
  5. そうでなければbを表示する

この日本語をC言語へ置き換えると、「入力には scanf」「比較には if」「表示には printf」が必要だと分かります。プログラミングは、いきなりコードを発明する作業ではなく、考えた手順を文法へ翻訳する作業と考えると分かりやすくなります。

例1|2つの整数を足す問題はどう考える?

「2つの整数を入力して合計を表示する」という問題を例にします。必要なのは、2個の整数を保存する変数と、合計を保存する変数です。

処理の流れは「aとbを入力→a+bを計算→結果を表示」です。C言語では次のように書けます。

#include <stdio.h>

int main(void)
{
    int a, b, sum;

    scanf("%d %d", &a, &b);
    sum = a + b;
    printf("%d\n", sum);

    return 0;
}

int a, b, sum; で整数を保存する場所を用意し、scanf で入力し、sum = a + b; で計算しています。このように、問題文の一文ずつをコードへ対応させるのが基本です。

例2|条件によって処理が変わるならif文を使う

「入力した整数が正なら『正の数』、負なら『負の数』、0なら『0』と表示する」という問題では、入力値によって出力が変化します。このような問題では条件分岐が必要です。

日本語にすると「nが0より大きいか調べる→違えば0より小さいか調べる→どちらでもなければ0」となります。

#include <stdio.h>

int main(void)
{
    int n;

    scanf("%d", &n);

    if (n > 0) {
        printf("正の数\n");
    } else if (n < 0) {
        printf("負の数\n");
    } else {
        printf("0\n");
    }

    return 0;
}

問題文に「~なら」「~の場合」「それ以外」といった表現があるときは、ifelse が必要になる可能性が高いと考えられます。

例3|同じ処理を何度も行うならfor文やwhile文を使う

「1から10まで表示する」「入力された回数だけ処理する」「100個の数値を順番に調べる」といった問題では、同じ処理を繰り返します。この場合は forwhile を検討します。

例えば1から10まで表示するなら、1、2、3……と10回 printf を書く必要はありません。

#include <stdio.h>

int main(void)
{
    int i;

    for (i = 1; i <= 10; i++) {
        printf("%d\n", i);
    }

    return 0;
}

「同じ形の処理が何度も出てくる」と気づいたら、繰り返し構文へ置き換えられないか考えるのがポイントです。

問題文の言葉から必要な構文を予想する

C言語の基礎問題では、問題文に使われている言葉から必要な構文をある程度予想できます。

問題文によく出る表現 考えられる機能
入力する scanf、fgetsなど
表示する printf、putsなど
もし~なら if
それ以外 else
~回繰り返す for
~まで繰り返す while
複数の値を保存する 配列
最大値・最小値を求める 比較+繰り返し
処理をまとめる 関数

ただし、これは絶対的なルールではありません。同じ問題でも複数の書き方が可能です。まず「どんな処理が必要か」を考え、その後で適切なC言語の構文を選びます。

変数は「途中の値を覚えておく箱」と考える

C言語の問題では、どの変数を用意すればよいか分からなくなることがあります。そのときは、「途中で覚えておく必要がある値は何か」を考えます。

例えば「5教科の合計点と平均点を求める」なら、各点数を保存する値、合計、平均が必要になります。個別の点数を全部後で使うなら配列を使う方法もあります。

変数名も ab だけで済ませず、scoretotalaverage のように役割が分かる名前にすると、複雑な問題でも読みやすくなります。

整数と小数では型に注意する

C言語では、データの種類によって変数の型を選びます。整数を扱うなら int、小数を扱うなら double などが代表的です。

例えば合計点が250点で科目数が3なら、整数同士で 250 / 3 と計算すると小数部分が切り捨てられます。平均を83.333…として求めたい場合は、小数として計算する必要があります。

double average;
average = (double)total / count;

「計算式は合っているのに答えがおかしい」という場合は、演算子だけでなく変数の型も確認します。

最大値を求める問題では「暫定1位」を更新していく

アルゴリズムの考え方が分かりやすい例として、「配列の中から最大値を求める」問題があります。重要なのは、一度に最大値を見つけようとしないことです。

まず最初の値を「今のところ最大」として覚えておき、次の値と比較します。次の値のほうが大きければ最大値を更新し、それを最後まで繰り返します。

int max = data[0];

for (int i = 1; i < n; i++) {
    if (data[i] > max) {
        max = data[i];
    }
}

これは「暫定1位を決めて、新しい候補が来るたびに入れ替える」と考えると理解しやすくなります。プログラミングでは、このように人間が自然に行っている判断を細かな手順へ分解します。

合計を求める問題では「0から少しずつ足す」

複数の値の合計を求める場合も、一度に答えを出そうとする必要はありません。合計を保存する変数を0で初期化し、値を一つずつ足していきます。

int total = 0;

for (int i = 0; i < n; i++) {
    total += data[i];
}

例えば10、20、30という値なら、最初はtotal=0、次に10、次に30、最後に60となります。

この「途中結果を保存して少しずつ更新する」という考え方は、合計、件数、最大値、最小値など多くの問題で使います。

「何個あるか数える」問題ではカウンタを使う

「10個の整数の中に偶数が何個あるか求める」という問題なら、偶数を見つけるたびにカウントを1増やします。

int count = 0;

for (int i = 0; i < 10; i++) {
    if (data[i] % 2 == 0) {
        count++;
    }
}

% は余りを求める演算子です。2で割った余りが0なら偶数なので、data[i] % 2 == 0 と判断できます。

「条件に当てはまった回数を求める」という問題では、0から始めるカウンタ変数を用意するのが定番です。

配列を使うかどうかは「複数の同種類データ」がポイント

同じ種類のデータを大量に扱う場合は、変数を一つずつ用意するより配列を使うと便利です。

例えば5人分の点数を扱うのに score1score2score3score4score5 と作ることもできますが、人数が100人になれば現実的ではありません。

int score[5];

配列にしておけば、for 文と組み合わせて入力、合計、検索などを繰り返し処理できます。「同じ種類の値が何個も並ぶ問題」では配列を検討しましょう。

関数を使う問題では「一つの仕事を切り出す」

関数を作る課題では、プログラム全体を一つの main 関数へ詰め込むのではなく、まとまった役割を別の関数として切り出します。

例えば「2つの整数のうち大きい値を返す関数」を作るなら、次のように書けます。

int max_value(int a, int b)
{
    if (a > b) {
        return a;
    }
    return b;
}

関数を考えるときは、「何を受け取るか」「何を処理するか」「何を返すか」の3点を整理すると分かりやすくなります。

コードを書く前に具体的な数字で手作業してみる

アルゴリズムが思いつかないときに非常に有効なのが、具体的な数字を入れて自分の手で答えを求めてみる方法です。

例えば「3個の整数の最大値を求める」という問題なら、12、7、25という具体例で考えます。「まず12を仮の最大値にする→7と比較する→12のまま→25と比較する→25へ更新」となります。

自分が紙の上で行った手順を、そのままコンピュータに一つずつ命令すればプログラムになります。コードが思いつかないときほど、まず具体例を手計算してみることが重要です。

エラーが出たら「文法エラー」と「答えが違う」を分ける

C言語でプログラムを書いた後、問題が起きたときにはエラーの種類を分けて考えます。コンパイルできない場合は文法や型などの問題、実行できるのに答えが違う場合は処理手順の問題である可能性が高くなります。

例えばセミコロンを忘れた、変数名を間違えた、scanf の変数に & を付け忘れた、といった問題はコンパイルエラーになることがあります。

一方、「最大値を求めたつもりなのに間違った値が出る」といった場合は、比較条件や初期値、繰り返し回数などアルゴリズムを確認します。

入力例と出力例を自分で追跡する

問題文に入力例と出力例がある場合は、完成したコードへその値を入れたとき、変数がどのように変化するか順番に追ってみます。

例えば total が0から10、30、60と変化することを紙に書くだけでも、どこで計算が間違っているか発見しやすくなります。

この作業は「トレース」と呼ばれます。プログラミング初心者ほど、頭の中だけで実行結果を予想するより、変数の値を紙へ書いて追跡する方法が効果的です。

問題文がないと具体的なソースコードは決められない

C言語の質問で最も重要なのは、実際の問題文です。「C言語の問題です。コードを教えてください」だけでは、何を入力し、何を計算し、何を出力するのか判断できません。

具体的な回答を得るには、少なくとも問題文全文、入力条件、出力条件、入力例・出力例、自分で書いたコード、分からない部分を示す必要があります。

例えば「1から100までの整数のうち3の倍数の合計を求める」という情報があれば、for文とif文を組み合わせる問題だと判断できます。しかし「C言語の問題」とだけ書かれていても、配列問題なのか関数問題なのかすら分かりません。

質問するときは自分のコードも載せると解決しやすい

プログラミングについて質問するときは、「完成コードをください」だけより、自分がどこまで考えたのかを示すほうが具体的な助言を得やすくなります。

例えば「for文を使うと思い、ここまで書きましたが合計の変数をどこで初期化すればよいか分かりません」と説明すれば、問題点を絞り込めます。

コンパイルエラーがある場合は、エラーメッセージも省略せず掲載すると原因を特定しやすくなります。学校課題の場合は、提出条件として使用禁止の構文や指定された書き方がないかも重要です。

完成コードを丸暗記するより「なぜそう書くか」を理解する

課題の完成ソースコードをそのままコピーすれば、一時的には答えを出せるかもしれません。しかし次に数字や条件を少し変更した問題が出ると、再び解けなくなる可能性があります。

例えばfor文について、形だけ for (i = 0; i < n; i++) と暗記するより、「iを0から始め、n未満の間、1ずつ増やす」と理解するほうが応用できます。

C言語では、変数、if文、for文、配列、関数といった少数の基本要素を組み合わせて多くの問題を解きます。完成コードよりも、「なぜこの変数が必要か」「なぜこの条件になるか」を説明できる状態を目指すと上達しやすくなります。

C言語の問題を解く基本手順

どのような問題でも、次の順番で考えると整理しやすくなります。

  1. 問題文を最後まで読む
  2. 入力されるデータを確認する
  3. 最終的に何を出力するか確認する
  4. 入力から出力までの手順を日本語で書く
  5. 必要な変数を決める
  6. 条件分岐が必要か考える
  7. 繰り返しが必要か考える
  8. 複数データなら配列が必要か考える
  9. 日本語の手順をC言語へ置き換える
  10. 入力例で実行結果を確認する

この方法を習慣にすると、問題文を見てすぐコードが出てこなくても、「次に何を考えればよいか」が分かるようになります。

まとめ|C言語は問題文を小さな手順へ分解してからコードにする

C言語の問題を解くときは、最初からソースコードを書こうとするのではなく、まず問題文を「入力・処理・出力」に分けます。その後、処理を日本語の手順へ分解し、必要に応じて iffor、配列、関数などへ置き換えていくのが基本です。

「~なら」と条件が変化するならif文、「何回も繰り返す」ならfor文やwhile文、「同じ種類のデータが多数ある」なら配列、といったように問題文から必要な道具を判断できます。

コードが思いつかない場合は、具体的な数字を一つ決め、自分なら手作業でどう答えを求めるかを書き出してみるのが特に効果的です。その手順こそがアルゴリズムの土台になります。

なお、具体的なC言語のソースコードを決めるには実際の問題文が必要です。問題文、入力条件、出力条件、自分で書いたコード、エラー内容までそろっていれば、どの構文を使うべきか、どのように考えればよいかを正確に整理できます。

コメント

タイトルとURLをコピーしました