はじめに
本記事では、C言語でAtCoderに臨む場合の入出力処理の方法についてまとめます。
「C言語やったことないよ〜ぴえん」という方にもわかるように説明している(つもりな)ので、
ご安心ください。
目次
入力編
整数 1 個の入力
入力
整数 $n$
#include <stdio.h>
int main(void) {
int n;
scanf("%d", &n);
printf("%d\n", n + 5);
// このコードは入力された整数に5を足して出力するコードです。
// 標準入力から2,147,483,647を入力してコードを実行し、出力を予想してみましょう。
return 0;
}
-
{変数の型} {変数名}
の形で宣言します。 - int型は $-2,147,483,648 \le n \le 2,147,483,647$ を満たす整数です。
- int型を代入する時は
scanf("%d", &{変数名})
と書き、この%d
をフォーマット演算子と呼びます。 -
&
には変数の場所を示す意味があり、これがないと正しく動作しません(私もしばしば書き忘れていました)。 -
"\n"
というのは改行の指示です。
整数 2 個の入力
入力
整数 $ a b$
#include <stdio.h>
int main(void) {
int a, b;
scanf("%d%d", &a, &b);
printf("%d%d%d\n", a, b, a * b);
// フォーマット演算子の間に何かを入力して、どんな出力をするか調べてみましょう。
}
-
{変数の型} {変数名1}, {変数名2}
の形で宣言します。 - 2つの変数に代入する時には、
scanf("%d%d", &{変数名1}, &{変数名2})
と書きます。 -
&
がないと動きません。私のことは忘れても、&
だけは忘れないでください。
整数 n 個の入力
入力例
配列の長さ ${n}$
配列の要素 ${A_0} {A_1} {…} {A_{n-1}}$
#include <stdio.h>
int main(void) {
int n;
scanf("%d", &n);
int A[n];
for (int i = 0; i < n; i++) {
scanf("%d", &A[i]);
// A[i]にひとつずつ代入する, 配列の要素でも&は変わらず
}
printf("%d %d\n", A[1], A[0]);
return 0;
}
- 同じ型の値を複数扱う時に使うのが、配列と呼ばれるデータ構造です。
- 宣言時は
{変数の型名} {配列名}[{配列の長さ}]
と書きます。 - 「配列の何番目か」 は
[0]
から始まり、[{配列の長さ} - 1]
までを指定することができます。 -
A[0]
からA[n - 1]
まで任意の値を代入できるように for 文を使って代入します。
文字 の入力
入力例
文字 $c$
$c$ は文字('a'
や'9'
)
#include <stdio.h>
int main(void) {
char c;
scanf("%c", &c);
printf("%c\n", c);
return 0;
}
- C言語では、文字の型名として
char
を用います。 - 整数の時と同様に、
{変数の型} {変数名}
の形で宣言します。 -
char
型を代入する時はscanf("%c", &{変数名})
と書きます。 - またも
&
がないと正しく動作しません。
文字列 の入力
入力例
文字列 $s$
文字列の長さは4("They"
、"l0ve"
、"d0lp"
、"2023"
など)
#include <stdio.h>
int main(void) {
char s[5];
// 文字列の長さ 4 + ヌル文字'\0'のぶん 1
scanf("%s", s);
printf("%s\n", s);
return 0;
}
- 文字列は、文字の配列として読み込むので、変数型として
char
を用います。 -
char {変数名}[{文字列の長さ + 1}]
の形で宣言します(文字列の末尾には、文字列の終端を示すヌル文字'\0'
が自動的に付加されるため)。 - 文字列を読み込むときのフォーマット演算子は
%s
です。 -
scanf("%s", s)
と書き、&
を使いません。 -
&
を使わない理由については、C言語のポインタが深く関わってきます。解説記事を書く予定なのでご期待ください。待ちきれない方は「C言語 ポインタ」でググるとよい結果を得られると思います。
演習編
出典:
第 1 問: Welcome to AtCoder (100点)
【問題概要】
整数 $a, b, c$ と文字列 $s$ が与えられます。$ a + b + c $ と $ s $ を並べて出力してください。
【入力】
$a$
$b c$
$s$
【制約】
$ 1 \le a, b, c \le 1,000 $
$ 1 \le |\ s \ | \le 100 $
【キーワード】
- 四則演算
- 出力
【解法】
入力を受け取って、 $ a + b + c $ を計算し、 $ s $ と並べて出力します。
【実装例】
#include <stdio.h>
int main(void) {
int a;
scanf("%d", &a);
int b, c;
scanf("%d%d", &b, &c);
char s[101];
scanf("%s", s);
printf("%d %s\n", a + b + c, s);
return 0;
}
【コメント】
入力を受け取り、問題文通りに実装しましょう。
第 2 問: Shift only (200点)
【問題概要】
整数 $ N $ と 整数列 $ A $ が与えられます。 $ A $ の項がすべて偶数であるとき、全ての項を、2で割ったものに置き換える操作を行うことができます。操作は最大で何回行えますか。
【入力】
$N$
${A_0} {A_1} {…} {A_{N-1}}$
【制約】
$ 1 \le N \le 200 $
$ 1 \le A_i \le10^9 $
【実装例】
#include <stdio.h>
int main(void) {
int N, A[200], cnt, flag;
scanf("%d", &N);
for (int i = 0; i < N; i++) {
scanf("%d", &A[i]);
}
cnt = 0;
flag = 0;
for (int i = 0; i < 30; i++) {
for (int j = 0; j < N; j++) {
if (A[j] % 2 == 0) {
A[j] /= 2;
} else {
flag = 1;
}
}
if (flag) break;
cnt++;
}
printf("%d\n", cnt);
return 0;
}
【コメント】
操作を行った回数 cnt
と、$ A $に含まれる数字が奇数かどうか確かめるフラグflag
を $ 0 $ で初期化します。制約より、$ A_i\le 10^9< 2^{30} $ であることは自明なので、forループは $ 30 $ 回にします($ 2 $ で高々 $ 30 $ 回も割れば操作を行えなくなるため)。ループの中で、flag
が真(= 1)になったらループを終了します。
まとめ
本記事が「AtCoder を始めてみよう」という方の役に立つことができれば、とても嬉しい気持ちです。
読んでいただきありがとうございました。
質問・指摘・修正等ありましたら @_dolp_ までよろしくお願いいたします。