C言語 変数・演算・入出力(printf・scanf)の練習問題

変数・算術演算・printf / scanf を使う問題を、初級から上級まで13問そろえました。ブラウザでコードを書いて「採点する」を押すと、本物の gcc でいくつかの入力を試し、出力が正しいかを判定します。

この練習問題の使い方
  1. 問題文と実行例を読み、下の欄にコードを書く
  2. 「▶ 実行」で自分で入力を与えて動かしてみる
  3. 「✔ 採点する」で、用意したいくつかの入力に対して出力が正しいかを判定
  4. 行き詰まったら「ヒント」、解けたら「模範解答と解説」で確認
採点のルール
  • 出力は実行例と同じ形で表示する。「数を入力してください」のような入力を促すメッセージは表示しない
  • 行末の空白と、最後の空行の有無は区別しない
  • 書いたコードはこのブラウザに自動保存されます

※ 実行と採点では、コードを外部の無料コンパイルサービス Wandbox に送信して gcc で動かします。

全13問(初級 4・中級 5・上級 4)

変数・演算・入出力の練習問題(13問)

B01 初級

問1. 2つの整数の四則演算

整数 a, b(−10000 ≤ a, b ≤ 10000、b ≠ 0)を空白区切りで入力し、和・差(a−b)・積・商・余りを、例のように1行に1つずつ表示せよ。商と余りは C の / と % の結果をそのまま表示する。
実行例(下線が入力)
17 5 和: 22 差: 12 積: 85 商: 3 余り: 2
コードを書く
「実行」で入力を与えて動かす/「採点する」で 5 個のテストを自動で試します
int どうしの a / b は整数の割り算(小数部分は切り捨て)、a % b は余りです。結果は printf("商: %d\n", a / b); のようにそのまま表示できます。
#include <stdio.h>

int main(void) {
    int a, b;
    scanf("%d %d", &a, &b);

    printf("和: %d\n", a + b);
    printf("差: %d\n", a - b);
    printf("積: %d\n", a * b);
    printf("商: %d\n", a / b);
    printf("余り: %d\n", a % b);
    return 0;
}
解説:C の整数の割り算は0 の方向へ切り捨てです。そのため −7 / 2 は −4 ではなく −3、余りは a == (a / b) * b + a % b を満たすように決まるので −1 になります(余りの符号は a と同じ)。scanf では &a のように & を付け忘れないことにも注意しましょう。
B02 初級

問2. 円の面積と円周

円の半径 r(0 < r ≤ 1000、小数可)を入力し、面積と円周の長さを小数第2位まで表示せよ。円周率は 3.14159 とする。
実行例(下線が入力)
2.5 面積: 19.63 円周: 15.71
コードを書く
「実行」で入力を与えて動かす/「採点する」で 5 個のテストを自動で試します
小数を扱うので double 型を使います。scanf では %lf、printf で小数第2位までなら %.2f です。面積は PI * r * r、円周は 2 * PI * r。
#include <stdio.h>

int main(void) {
    const double PI = 3.14159;
    double r;
    scanf("%lf", &r);

    printf("面積: %.2f\n", PI * r * r);
    printf("円周: %.2f\n", 2 * PI * r);
    return 0;
}
解説:double を読み込むとき scanf("%f", &r) と書くのは誤りです(%f は float 用)。scanf は %lf、printf は %f と覚えましょう。%.2f は小数第3位以下を丸めて小数第2位まで表示します(変数の値そのものは変わりません)。ただし double は2進数で近似されているため、2.675 が 2.67 になるように、ちょうど「5」の位置でも切り上がらないことがあります。
B03 初級

問3. 摂氏から華氏へ

摂氏の温度 C(−100 ≤ C ≤ 1000、小数可)を入力し、華氏の温度 F = C × 9 / 5 + 32 を小数第1位まで表示せよ。
実行例(下線が入力)
36.6 華氏: 97.9
コードを書く
「実行」で入力を与えて動かす/「採点する」で 5 個のテストを自動で試します
式をそのまま c * 9 / 5 + 32 と書けば、c が double なので計算も double で行われます。9 / 5 を先に計算する書き方には注意が必要です。
#include <stdio.h>

int main(void) {
    double c;
    scanf("%lf", &c);

    double f = c * 9 / 5 + 32;
    printf("華氏: %.1f\n", f);
    return 0;
}
解説:c * (9 / 5) + 32 と書くと、9 / 5 が整数どうしの割り算で 1 になり、F = C + 32 という誤った式になります。9.0 / 5 のようにどちらかを小数で書くか、左から順に c と掛けて double にしてから割りましょう。
B04 初級

問4. 3桁の数の各位と逆順

3桁の整数 N(100 ≤ N ≤ 999)を入力し、百の位・十の位・一の位を表示せよ。続けて、各位を逆に並べた数を整数として表示せよ(例: 120 なら 21)。ループは使わなくてよい。
実行例(下線が入力)
123 百の位: 1 十の位: 2 一の位: 3 逆順: 321
コードを書く
「実行」で入力を与えて動かす/「採点する」で 4 個のテストを自動で試します
百の位は n / 100、十の位は n / 10 % 10、一の位は n % 10 です。逆順の数は 一の位 * 100 + 十の位 * 10 + 百の位 で作れます。
#include <stdio.h>

int main(void) {
    int n;
    scanf("%d", &n);

    int h = n / 100;
    int t = n / 10 % 10;
    int o = n % 10;

    printf("百の位: %d\n", h);
    printf("十の位: %d\n", t);
    printf("一の位: %d\n", o);
    printf("逆順: %d\n", o * 100 + t * 10 + h);
    return 0;
}
解説:/ で「下の桁を捨てる」、% で「下の桁だけ残す」と考えると、どの位でも取り出せます。逆順を printf("%d%d%d", o, t, h) と3つ並べて表示すると、120 のとき 021 となり整数の 21 になりません。
B05 中級

問5. 3科目の合計と平均

3科目の点数(0 以上 100 以下の整数)を空白区切りで入力し、合計点と平均点を表示せよ。平均点は小数第2位まで表示する。
実行例(下線が入力)
80 75 91 合計: 246 平均: 82.00
コードを書く
「実行」で入力を与えて動かす/「採点する」で 5 個のテストを自動で試します
合計は int で求めます。平均は sum / 3 ではなく (double)sum / 3 または sum / 3.0 として、小数のまま割り算します。
#include <stdio.h>

int main(void) {
    int a, b, c;
    scanf("%d %d %d", &a, &b, &c);

    int sum = a + b + c;
    double avg = (double)sum / 3;

    printf("合計: %d\n", sum);
    printf("平均: %.2f\n", avg);
    return 0;
}
解説:double avg = sum / 3; と書いても、右辺はint どうしの割り算なので先に小数が切り捨てられ、299 / 3 は 99 → 99.00 になってしまいます。割る前に (double) で型を変換(キャスト)するのがポイントです。(double)(sum / 3) とカッコでくくると、切り捨ての後に変換するので意味がありません。
B06 中級

問6. 秒を時:分:秒に変換

秒数 N(0 ≤ N ≤ 360000)を入力し、「時:分:秒」の形で表示せよ。分と秒は2桁(1桁のときは先頭を 0 で埋める)、時は桁数をそろえずそのまま表示する。
実行例(下線が入力)
3725 1:02:05
コードを書く
「実行」で入力を与えて動かす/「採点する」で 5 個のテストを自動で試します
時間は n / 3600、分は n % 3600 / 60、秒は n % 60 です。0 埋め2桁の表示は %02d を使います。
#include <stdio.h>

int main(void) {
    int n;
    scanf("%d", &n);

    int h = n / 3600;
    int m = n % 3600 / 60;
    int s = n % 60;

    printf("%d:%02d:%02d\n", h, m, s);
    return 0;
}
解説:分を n / 60 とすると、3725 秒で 62 分のように時間に繰り上がった分まで含めてしまいます。先に % 3600 で「1時間未満の残り」にしてから 60 で割ります。%2d だと空白で埋まり 1: 2: 5 になるので、0 で埋めるには %02d です。
B07 中級

問7. お金を紙幣と硬貨に分ける

金額 N 円(0 ≤ N ≤ 100000)を入力し、1000円札・500円玉・100円玉・50円玉・10円玉・5円玉・1円玉を使って、枚数の合計が最も少なくなるように支払うときのそれぞれの枚数を、例の形式で大きい順に表示せよ。
実行例(下線が入力)
1888 1000円: 1枚 500円: 1枚 100円: 3枚 50円: 1枚 10円: 3枚 5円: 1枚 1円: 3枚
コードを書く
「実行」で入力を与えて動かす/「採点する」で 4 個のテストを自動で試します
大きいお金から順に、n / 1000 で枚数を求め、n %= 1000; で残りの金額にします。これを 500, 100, … と続けます。
#include <stdio.h>

int main(void) {
    int n;
    scanf("%d", &n);

    printf("1000円: %d枚\n", n / 1000);
    n %= 1000;
    printf("500円: %d枚\n", n / 500);
    n %= 500;
    printf("100円: %d枚\n", n / 100);
    n %= 100;
    printf("50円: %d枚\n", n / 50);
    n %= 50;
    printf("10円: %d枚\n", n / 10);
    n %= 10;
    printf("5円: %d枚\n", n / 5);
    n %= 5;
    printf("1円: %d枚\n", n);
    return 0;
}
解説:「割り算の商が枚数、余りが次に回す金額」という / と % の組み合わせの定番です。n %= 1000; は n = n % 1000; の省略形(複合代入)です。残りを更新し忘れると、1888 円で 100 円玉が 18 枚のようにおかしな結果になります。
B08 中級

問8. 文字コードと大文字・小文字

英大文字1文字(A〜Z)を入力し、その文字コード(ASCII コード)、対応する小文字、アルファベットで何番目か(A を 1 番目とする)を例の形式で表示せよ。
実行例(下線が入力)
C 文字コード: 67 小文字: c 番目: 3
コードを書く
「実行」で入力を与えて動かす/「採点する」で 4 個のテストを自動で試します
char は小さな整数なので、%d で表示すると文字コード、%c で表示すると文字になります。小文字は c - 'A' + 'a'、何番目かは c - 'A' + 1 で計算できます。
#include <stdio.h>

int main(void) {
    char c;
    scanf(" %c", &c);

    printf("文字コード: %d\n", c);
    printf("小文字: %c\n", c - 'A' + 'a');
    printf("番目: %d\n", c - 'A' + 1);
    return 0;
}
解説:'A' は文字コードの値(ASCII では 65)を表す整数です。ASCII では A〜Z、a〜z がそれぞれ連続して並んでいるので、「A からいくつ離れているか」を足し引きすれば変換できます。32 のような数を直接書くより、'a' - 'A' と書く方が意図が伝わります。
B09 中級

問9. 整数部分・小数部分・四捨五入

0 以上の小数 x(0 ≤ x < 100000、小数第2位まで)を入力し、整数部分、小数部分(小数第2位まで)、小数第1位を四捨五入した整数を表示せよ。キャスト(型変換)を使い、math.h の関数は使わないこと。
実行例(下線が入力)
3.7 整数部分: 3 小数部分: 0.70 四捨五入: 4
コードを書く
「実行」で入力を与えて動かす/「採点する」で 5 個のテストを自動で試します
(int)x で小数部分が切り捨てられて整数部分が得られます。小数部分は x - (int)x。四捨五入は「0.5 を足してから切り捨てる」、つまり (int)(x + 0.5) です。
#include <stdio.h>

int main(void) {
    double x;
    scanf("%lf", &x);

    int ip = (int)x;
    double fp = x - ip;
    int rounded = (int)(x + 0.5);

    printf("整数部分: %d\n", ip);
    printf("小数部分: %.2f\n", fp);
    printf("四捨五入: %d\n", rounded);
    return 0;
}
解説:double から int への変換は0 の方向への切り捨てです。(int)x + 0.5 と書くと、先に切り捨ててから 0.5 を足すことになり四捨五入になりません(カッコの位置に注意)。なお 0.5 を足す方法は x が 0 以上のときの書き方で、負の数では −2.7 が −2 になってしまいます。
B10 上級

問10. BMIと標準体重

体重 w [kg](小数可)と身長 h [cm](整数)を空白区切りで入力し、BMI = 体重 ÷ (身長[m])² と、標準体重 = 22 × (身長[m])² を小数第1位まで表示せよ(30 ≤ w ≤ 200、100 ≤ h ≤ 250)。
実行例(下線が入力)
60 170 BMI: 20.8 標準体重: 63.6kg
コードを書く
「実行」で入力を与えて動かす/「採点する」で 5 個のテストを自動で試します
まず身長をメートルに直します。h は int なので h / 100 では整数の割り算になってしまいます。h / 100.0 として double で受け取りましょう。
#include <stdio.h>

int main(void) {
    double w;
    int h;
    scanf("%lf %d", &w, &h);

    double m = h / 100.0;
    double bmi = w / (m * m);
    double std = 22 * m * m;

    printf("BMI: %.1f\n", bmi);
    printf("標準体重: %.1fkg\n", std);
    return 0;
}
解説:double m = h / 100; は、170 / 100 が整数の割り算で 1 になってから double に代入されるので m = 1.0 になります。代入先が double でも、右辺の計算は右辺の型で行われる点が落とし穴です。また w / m * m は (w / m) * m の意味になりほぼ w に戻ってしまうので、カッコが必要です。
B11 上級

問11. レシートを作る

3行にわたって「単価 個数」(単価は 1〜99999、個数は 1〜99 の整数)を入力し、例のようなレシートを表示せよ。各商品の行は printf("%5d x %2d = %6d\n", 単価, 個数, 金額) の書式で表示する。続けて 小計、消費税(小計の 10%、1円未満切り捨て)、合計 を、それぞれ "小計: %d\n" の形で表示する。
実行例(下線が入力)
120 3 1980 1 85 12 120 x 3 = 360 1980 x 1 = 1980 85 x 12 = 1020 小計: 3360 消費税: 336 合計: 3696
コードを書く
「実行」で入力を与えて動かす/「採点する」で 4 個のテストを自動で試します
%5d は「最低5文字の幅で右寄せ」です。消費税は int のまま sub * 10 / 100 と計算すれば、整数の割り算で1円未満が切り捨てられます。
#include <stdio.h>

int main(void) {
    int p1, q1, p2, q2, p3, q3;
    scanf("%d %d", &p1, &q1);
    scanf("%d %d", &p2, &q2);
    scanf("%d %d", &p3, &q3);

    int s1 = p1 * q1;
    int s2 = p2 * q2;
    int s3 = p3 * q3;
    printf("%5d x %2d = %6d\n", p1, q1, s1);
    printf("%5d x %2d = %6d\n", p2, q2, s2);
    printf("%5d x %2d = %6d\n", p3, q3, s3);

    int sub = s1 + s2 + s3;
    int tax = sub * 10 / 100;
    printf("小計: %d\n", sub);
    printf("消費税: %d\n", tax);
    printf("合計: %d\n", sub + tax);
    return 0;
}
解説:幅指定は最低の幅なので、9899901 のように 6 桁を超える値は切られずにそのまま全部表示されます(3つ目のテスト)。sub * 0.1 のように小数で計算すると、表示のときに %d と型が合わなくなります。お金は int のまま、掛けてから割るのが確実です(sub / 100 * 10 の順だと 1343 円で 130 円になります)。
B12 上級

問12. 負の数の割り算と余り

整数 a(−10000 ≤ a ≤ 10000)と正の整数 b(1 ≤ b ≤ 10000)を入力し、C の a / b と a % b の値、検算として (a / b) * b + a % b の値、そして数学の余り(0 以上 b 未満になる余り)を表示せよ。
実行例(下線が入力)
-7 3 商: -2 余り: -1 検算: -7 数学の余り: 2
コードを書く
「実行」で入力を与えて動かす/「採点する」で 5 個のテストを自動で試します
C の % は a が負のとき負の余りを返します。そこに b を足してもう一度 b で割った余りを取る、(a % b + b) % b で 0 以上の余りにそろえられます。
#include <stdio.h>

int main(void) {
    int a, b;
    scanf("%d %d", &a, &b);

    int q = a / b;
    int r = a % b;
    int m = (r + b) % b;

    printf("商: %d\n", q);
    printf("余り: %d\n", r);
    printf("検算: %d\n", q * b + r);
    printf("数学の余り: %d\n", m);
    return 0;
}
解説:C99 以降、整数の割り算は0 の方向へ切り捨てと決まっています(−7 / 3 は −2.33… → −2)。余りは (a / b) * b + a % b == a が成り立つように決まるので −1 です。曜日や時計の計算で負の値を扱うときは、r + b だけでは r = 0 のとき b になってしまうので、最後にもう一度 % b を取ります。
B13 上級

問13. 時刻の足し算

開始時刻の時 h(0〜23)と分 m(0〜59)、経過時間 t 分(0 ≤ t ≤ 100000)を空白区切りで入力し、t 分後の時刻を HH:MM(どちらも2桁0埋め、24時間表記)で表示せよ。次の行に、日付が何日先に進んだかを表示する。
実行例(下線が入力)
23 30 90 01:00 +1日
コードを書く
「実行」で入力を与えて動かす/「採点する」で 5 個のテストを自動で試します
時と分をばらばらに扱わず、まず「0時0分からの通算の分」h * 60 + m + t に直します。そこから日数は / 1440、その日の中の分は % 1440 で求まります。
#include <stdio.h>

int main(void) {
    int h, m, t;
    scanf("%d %d %d", &h, &m, &t);

    int total = h * 60 + m + t;
    int days = total / 1440;
    int rest = total % 1440;

    printf("%02d:%02d\n", rest / 60, rest % 60);
    printf("+%d日\n", days);
    return 0;
}
解説:分に 45 を足して 60 を超えたら時を 1 増やす…と個別に繰り上げると、条件分岐が増えて間違えやすくなります。いったん一番小さい単位(分)にそろえてから / と % で分解するのが、時刻や単位換算の定石です(1日 = 24 × 60 = 1440 分)。

復習する講座

← 練習問題の一覧へ