# ch06 — 標準入力をループで処理

Source: https://php-school.pages.dev/topics/loop/ch06-loop-with-input/
Site: AIと学ぶPHPの学校 (https://php-school.pages.dev)
Lesson: 繰り返し
Level: L2

Reference (official): https://www.php.net/manual/ja/control-structures.for.php

## 本文

# ch06 — 標準入力をループで処理

## 概要

ループの基本構文を覚えたら、次は **実用パターン** に進む。プログラミング演習でも実務でも頻出するのが「**最初に件数 N が与えられ、続く N 行に実データが並ぶ**」という入力形式だ。たとえば「テストの人数 → 各人の点数」「商品数 → 各商品の価格」のように、件数を先に教えてもらえば、こちらは N 回の `for` ループでデータを順に読めば良い、という構造になる。

具体的な書き方は、まず `trim(fgets(STDIN))` で 1 行目から N を受け取り、続けて `for ($i = 0; $i < $N; $i++)` の中でもう一度 `fgets(STDIN)` を呼ぶ、というパターンになる。読んだ値は文字列なので、数値計算したいときは `(int)` でキャストするのを忘れないこと。読み込んだ値はその場で集計してもいいし、いったん配列に貯めて後でまとめて処理する形でもいい — 後者なら配列章で学ぶ `array_sum()` / `max()` / `min()` のような **組み込み関数** をそのまま使えて、ループの中で `if` の山を書かずに済む。

このパターンを押さえると、「**入力フォーマットを読む** → **ループで処理** → **集計値を出力**」という、プログラミング演習で出題される問題の **半分以上** が同じ骨格で解けることに気づくはずだ。逆に言うと、ここで「件数 N → N 行データ → 集計」の型が体に染みていないと、後の配列・関数の章で「何でこんな構造になってるんだろう」と毎回混乱することになる。シンプルだが土台になるパターンなので、ドリルで手を動かして体得しておきたい。

## 学習目標

- 「件数 N の後に N 行のデータ」というよくある入力形式を処理できる
- ループの中で `fgets(STDIN)` を呼び、複数行入力を読める
- ループの結果を集計 (合計・最大値) できる

## 所要時間

スライド 5 分 + ドリル 3 問 = **20 分**

## ドリル

| no | 内容 |
|---|---|
| 01 | 1 行目に N、2 行目以降に N 行のテキスト → そのまま出力 |
| 02 | 1 行目に N、2 行目以降に N 個の整数 → 合計を出力 |
| 03 | 1 行目に N、2 行目以降に N 個の整数 → 最大値を出力 |

## 採点

```bash
php scripts/grade.php topics/loop/ch06-loop-with-input/drill/01-echo-n-lines/
```

## 関連チャプター

- [`ch01-for`](../ch01-for/) — N 回ループの基本形 (このチャプターの前提)
- [`ch02-while`](../ch02-while/) — 件数不明の入力を `while` で読むパターン
- [`ch05-nested`](../ch05-nested/) — 入れ子ループで 2 次元データを読む発展形

## スライド

---
marp: true
theme: dojo
paginate: true
size: 16:9
---

<!--
LLM_CONTEXT:
  Lesson 3 / Chapter 6
  目的: 「1 行目に件数 N、2 行目以降に N 行のデータ」という入力形式をループで処理できる
  扱わない: 関数定義 (L7) / 配列の詳細 (後続章) — 配列への push と array_sum / max は使う
  読み上げ時間目安: 4 分半〜5 分
-->

# 標準入力をループで処理

Lesson 3 / Chapter 6

---

## よくある入力形式

```
3
りんご
みかん
ぶどう
```

- 1 行目に **件数 N**
- 2 行目以降に **N 行のデータ**

この形式は競技プログラミングや paizaLMS でも頻出。

---

## 件数 N を読んで N 回ループ

```php
<?php
$n = (int) trim(fgets(STDIN));
for ($i = 0; $i < $n; $i++) {
    $line = trim(fgets(STDIN));
    echo $line . "\n";
}
```

- まず 1 行目で N を読む
- `for` で N 回ループ
- 各回で `fgets(STDIN)` を 1 回呼ぶ
- 読んだ値を使う / 配列に貯める

---

## 配列に貯める

```php
<?php
$n = (int) trim(fgets(STDIN));
$lines = [];
for ($i = 0; $i < $n; $i++) {
    $lines[] = trim(fgets(STDIN));
}
```

- `$lines = [];` で空の配列を用意
- `$lines[] = ...;` で末尾に追加
- N 回ループしたら N 個の要素が入っている

---

## 合計を計算する

```php
<?php
$n = (int) trim(fgets(STDIN));
$sum = 0;
for ($i = 0; $i < $n; $i++) {
    $sum += (int) trim(fgets(STDIN));
}
echo $sum . "\n";
```

- `$sum = 0;` で 0 から始める
- ループの中で `$sum += ...;` で足していく
- 最後に `$sum` を出力

`array_sum($arr)` で配列の合計を一発で計算する書き方もある。

---

## 最大値を計算する

```php
<?php
$n = (int) trim(fgets(STDIN));
$values = [];
for ($i = 0; $i < $n; $i++) {
    $values[] = (int) trim(fgets(STDIN));
}
echo max($values) . "\n";
```

- 一旦配列に貯める
- `max($values)` で配列の最大値を取得

ループの中で「これまでの最大」を更新していく書き方もある:

```php
$best = PHP_INT_MIN;
for (...) {
    $v = (int) trim(fgets(STDIN));
    if ($v > $best) $best = $v;
}
```

---

## このチャプターでできるようになること

✅ 「N 行のデータ」を for ループで読める
✅ 読んだ値を配列に貯められる
✅ 合計を計算できる
✅ 最大値を `max()` で取得できる

→ ドリルへ
