ACM-ICPC

データの入力


ここでは、全ての問題において必要な、データの入力と回答の出力について説明します。

入出力の概要

基本的に、どの問題も与えられたデータから得られる答えを出力しなさいというもので、プログラムは大きく分けて
の3つのパートになるでしょう。
ここでは、そのうち入力について説明します。

データセット

入力データは、いくつかの値(数値や文字列)のカタマリとして大量に与えられます。

例えば、
10 ←データセット1
23 ←データセット2
9 ←データセット3
...
のように数値が一つだけのものや、

abc 10 20 ←データセット1
a 100 50 ←データセット2
xyz 25 35 ←データセット3
...
のように複数の値のセットとして与えれらるものや、

2 ←データセット1
150
200
3 ←データセット2
380
120
250
...
のように、値の個数で始まってその個数分続くもの、などがあります。

入力データの形式

入力データとして与えられる入力の書式は、大きく分けて2つあります。もちろん例外もありますが・・・。

それぞれの形式は、次のようになります。
個数あり 個数なし
個数(=n)
データセット1
データセット2
...
データセットn
データセット1
データセット2
...
データセットn
終了記号
終了記号というのは、データセットはもう無いよというのを示すもので、たいていはいくつかのゼロが並んでいたりします。


さて、それぞれのデータの入力のしかたを、擬似言語を使って示してみましょう。

まず、個数ありの場合。
nに個数を読み込む。
for( i = 0 〜 n-1) {
 データセットを読み込む。
 ここで計算をする。
 答えを出力する。
}
特に問題はないと思います。最初に個数を読み込み、その回数分だけ入力・計算・出力を繰り返します。

次に、個数なしの場合。
データセットを読み込む。
while( 読み込んだのが終了記号でない ) {
 ここで計算する。
 答えを出力する。
 データセットを読み込む。
}
または、
while( true ) {
 データセットを読み込む。
 if( 読み込んだのが終了記号だった )
   break;
 ここで計算する。
 答えを出力する。
}
どっちを選ぶかは、好みの問題だと思うので、お任せします。
前者の場合、次のデータセットを読み込むのを忘れないように注意してください。


それぞれの言語における記述

ここでは、簡単な例として、
入力された整数の2乗を出力しなさい。ただし整数は1以上10000以下と仮定する。
という問題をそれぞれの言語で記述してみましょう。

入力データは、
個数あり 個数なし
5
10
2
8
15
6
10
2
8
15
6
0
のように、データセットが整数1つで示されるものとします。
個数なしの方の終了記号は1つのゼロで表されるものとします。

この場合
25
100
4
64
225
36
と出力されれば正解です。

プログラム中、個数を受ける変数はn、データを受ける変数はxとしてあります。

C言語の場合
#include <stdio.h>

int main(void)
{
 int n, i, x, y;
 scanf("%d", &n);
 for( i = 0; i < n; i++ ) {
   scanf("%d", &x);
   y = x * x;
   printf("%d\n", y);
 }
 return 0;
}
#include <stdio.h>

int main(void)
{
 int x;
 scanf("%d", &x);
 while( x != 0) {
   y = x * x;
   printf("%d\n", y);
   scanf("%d", &x);
 }
 return 0;
}

大丈夫ですよね。入力にはscanf、出力にはprintfを使います。
忘れちゃった人はしっかり復習しておいてください。


C++の場合
#include <iostream>
using namespase std;

int main(void)
{
 int n, i, x;
 cin >> n;
 for( i = 0; i < n; i++ ) {
   cin >> x;
   y = x * x;
   cout << y << endl;
 }
 return 0;
}
#include <iostream>
using namespase std;

int main(void)
{
 int x;
 cin >> n;
 while( x != 0) {
   y = x * x;
   cout << y << endl;
   cin >> x;
 }
 return 0;
}

入力は「cin >> 変数名」、出力は「cout << 式 << endl」と記述します。
endlは\nのようなものだと思えば大丈夫です。(若干違うらしいですが。)
また機会があれば、C++についての説明も書こうかなぁと思います。


Javaの場合
import java.util.*;

class A{
 public static void main(String[] args) {
   Scanner sc = new Scanner(System.in);
   int n = sc.nextInt();
   for( int i = 0; i < n; i++ ) {
     int x = sc.nextInt();
     int y = x * x;
     System.out.println(y);
   }
 }
}
個数なしの方は、めんど… ほとんど同じなので省略します。

データを読み込むのに、scannerクラスを使うのが一般的のようです。
ただ、私自身あまりJavaに詳しくないので(ぉぃ)、これ以上詳しい説明はできません。
(値読み込み専用のクラスとか作った方がいいのかなぁ?)