変数・算術演算・printf / scanf を使う問題を、初級から上級まで13問そろえました。ブラウザでコードを書いて「採点する」を押すと、本物の gcc でいくつかの入力を試し、出力が正しいかを判定します。
※ 実行と採点では、コードを外部の無料コンパイルサービス Wandbox に送信して gcc で動かします。
/ と % の結果をそのまま表示する。「実行」で入力を与えて動かす/「採点する」で 5 個のテストを自動で試します
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; }
a == (a / b) * b + a % b を満たすように決まるので −1 になります(余りの符号は a と同じ)。scanf では &a のように & を付け忘れないことにも注意しましょう。「実行」で入力を与えて動かす/「採点する」で 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; }
scanf("%f", &r) と書くのは誤りです(%f は float 用)。scanf は %lf、printf は %f と覚えましょう。%.2f は小数第3位以下を丸めて小数第2位まで表示します(変数の値そのものは変わりません)。ただし double は2進数で近似されているため、2.675 が 2.67 になるように、ちょうど「5」の位置でも切り上がらないことがあります。「実行」で入力を与えて動かす/「採点する」で 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 にしてから割りましょう。「実行」で入力を与えて動かす/「採点する」で 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 になりません。「実行」で入力を与えて動かす/「採点する」で 5 個のテストを自動で試します
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) とカッコでくくると、切り捨ての後に変換するので意味がありません。「実行」で入力を与えて動かす/「採点する」で 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 です。「実行」で入力を与えて動かす/「採点する」で 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 枚のようにおかしな結果になります。A〜Z)を入力し、その文字コード(ASCII コード)、対応する小文字、アルファベットで何番目か(A を 1 番目とする)を例の形式で表示せよ。「実行」で入力を与えて動かす/「採点する」で 4 個のテストを自動で試します
%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' と書く方が意図が伝わります。「実行」で入力を与えて動かす/「採点する」で 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; }
(int)x + 0.5 と書くと、先に切り捨ててから 0.5 を足すことになり四捨五入になりません(カッコの位置に注意)。なお 0.5 を足す方法は x が 0 以上のときの書き方で、負の数では −2.7 が −2 になってしまいます。「実行」で入力を与えて動かす/「採点する」で 5 個のテストを自動で試します
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 に戻ってしまうので、カッコが必要です。printf("%5d x %2d = %6d\n", 単価, 個数, 金額) の書式で表示する。続けて 小計、消費税(小計の 10%、1円未満切り捨て)、合計 を、それぞれ "小計: %d\n" の形で表示する。「実行」で入力を与えて動かす/「採点する」で 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; }
sub * 0.1 のように小数で計算すると、表示のときに %d と型が合わなくなります。お金は int のまま、掛けてから割るのが確実です(sub / 100 * 10 の順だと 1343 円で 130 円になります)。a / b と a % b の値、検算として (a / b) * b + a % b の値、そして数学の余り(0 以上 b 未満になる余り)を表示せよ。「実行」で入力を与えて動かす/「採点する」で 5 個のテストを自動で試します
% は 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; }
(a / b) * b + a % b == a が成り立つように決まるので −1 です。曜日や時計の計算で負の値を扱うときは、r + b だけでは r = 0 のとき b になってしまうので、最後にもう一度 % b を取ります。HH:MM(どちらも2桁0埋め、24時間表記)で表示せよ。次の行に、日付が何日先に進んだかを表示する。「実行」で入力を与えて動かす/「採点する」で 5 個のテストを自動で試します
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; }
/ と % で分解するのが、時刻や単位換算の定石です(1日 = 24 × 60 = 1440 分)。