C言語版 APG4b 中編

# 本記事について

この記事は [前編](https://qiita.com/cnng0712/items/50840498105228780f71) の続きとなります。前編を読んだことを前提として進めていくので、読んでからこの記事を読むことを推奨します。
前回 1.00 から 1.05 までを扱ったため、今回の内容は 1.06 から 1.10 までとなっています。

後編は[こちら](https://qiita.com/cnng0712/items/709292655d77ee335199)

前回書いたように、問題があれば本記事は削除します。

# 目次
- 1.00.はじめに
- 1.01.出力とコメント | EX1
- 1.02.プログラムの書き方とエラー | EX2
- 1.03.四則演算と優先順位 | EX3
- 1.04.変数と型 | EX4
- 1.05.プログラムの実行順序と入力 | EX5

↓ここから

- 1.06.if文・比較演算子・論理演算子 | EX6
- 1.07.条件式の結果とbool型 | EX7
- 1.08.変数のスコープ | EX8
- 1.09.複合代入演算子 | EX9
- 1.10.while文 | EX10

↑ここまで

- 1.11.for文・break・continue | EX11
- 1.12.文字列と文字 | EX12
- 1.13.配列 | EX13
- 1.14.STLの関数 | EX14
- 1.15.関数 | EX15



# [G - 1.06.if文・比較演算子・論理演算子](https://atcoder.jp/contests/apg4b/tasks/APG4b_g)

## キーポイント

- __if文__を使うと「ある条件が正しい時だけ処理をする」というプログラムが書ける
- __else句__を使うと「条件式が正しくなかった時」の処理を書ける

```c
if (条件式1) {
  処理1
}
else if (条件式2) {
  処理2
}
else {
  処理3
}
```

- 比較演算子

|演算子|意味|
|:---:|:---:|
|`x == y`|xとyは等しい|
|`x != y`|xとyは等しくない|
|`x > y`|xはyより大きい|
|`x < y`|xはyより小さい|
|`x >= y`|xはy以上|
|`x <= y`|xはy以下|

- 論理演算子

|演算子|意味|真になる時|
|:---:|:---:|:---:|
|`!(条件式)`|条件式の結果の反転|条件式が偽|
|`条件式1 && 条件式2`|条件式1が真 かつ 条件式2が真|条件式1と条件式2のどちらも真|
|`条件式1 `&#124;&#124;` 条件式2`|条件式1が真 または 条件式2が真|条件式1と条件式2の少なくとも片方が真|

## if文

__if文__を使うと、__ある条件が正しい時だけ処理をする__というプログラムが書けるようになります。

書き方は次のようになります。

```c
if (条件式) {
  処理
}
```

__条件式__が正しい時、`{` から `}` の間の処理が実行され、条件式が正しくないとき、処理は飛ばされます。

次の例では、入力の値が10より小さければ「xは10より小さい」と出力した後「終了」と出力します。また、入力の値が10より小さくなければ「終了」とだけ出力します。

```c
#include <stdio.h>

int main(void){
  int x;
  scanf("%d", &x);
  
  if(x < 10){
    printf("xは10より小さい\n");
  }

  printf("終了\n");
}
```

```:入力1
5
```

```:実行結果1
xは10より小さい
終了
```

```:入力2
15
```

```:実行結果2
終了
```

この例では、まず変数xに整数のデータを入力しています。

```c
int x;
scanf("%d", &x);
```

重要なのはその後です。

```c
if(x < 10){
  printf("xは10より小さい\n");
}
```

この部分は、「もし`x < 10`（xが10より小さい）なら、`xは10より小さい`と出力する」という意味になります。

最後に`printf("終了\n");`を実行して`終了`と出力し、プログラムは終了します。

xが10より小さく無い場合、次の処理は飛ばされます。

```c
{
  printf("xは10より小さい\n");
}
```

そのため、2つ目の実行例では`終了`とだけ出力されています。

if文のように、何かの条件で処理が別れることを__条件分岐__といいます。
また、「条件式が正しい」ことを__条件式が真__、「条件式が正しくない」ことを__条件式が偽__といいます。以降からこの表現を使います。

## 比較演算子

条件式のところには、多くの場合、__比較演算子__を使って条件を書きます。
比較演算子は以下の6つです。

|演算子|意味|
|:---:|:---:|
|`x == y`|xとyは等しい|
|`x != y`|xとyは等しくない|
|`x > y`|xはyより大きい|
|`x < y`|xはyより小さい|
|`x >= y`|xはy以上|
|`x <= y`|xはy以下|

「より大きい」「より小さい」を表す記号は数学と同じです。
「等しい」は`=`を2つ繋げたものになり、「等しくない」は`!`が`=`の前につきます。
「以上」「以下」は、数学では「≧」「≦」のように`=`を下につけますが、C言語では`>=`,`<=`のように__右に__`=`をつけます。

次のプログラムは、入力された整数値がどんな条件を満たしているかを出力するプログラムです。

```c
#include <stdio.h>

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

  if(x < 10){
    printf("xは10より小さい\n");
  }

  if(x >= 20){
    printf("xは20以上\n");
  }

  if(x == 5){
    printf("xは5\n");
  }

  if(x != 100){
    printf("xは100ではない\n");
  }

  printf("終了\n");
}
```
```:入力1
5
```

```:実行結果1
xは10より小さい
xは5
xは100ではない
終了
```

```:入力2
100
```

```:実行結果2
xは20以上
終了
```

## 論理演算子

条件式の中にはもっと複雑な条件を書くこともできます。そのためには__論理演算子__を使います。

|演算子|意味|真になる時|
|:---:|:---:|:---:|
|`!(条件式)`|条件式の結果の反転|条件式が偽|
|`条件式1 && 条件式2`|条件式1が真 かつ 条件式2が真|条件式1と条件式2のどちらも真|
|`条件式1 `&#124;&#124;` 条件式2`|条件式1が真 または 条件式2が真|条件式1と条件式2の少なくとも片方が真|

```c
#include <stdio.h>

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

  if(!(x == y)){
    printf("xとyは等しくない\n");
  }

  if(x == 10 && y == 10){
    printf("xとyは10\n");
  }

  if(x == 0 || y == 0){
    printf("xかyは0\n");
  }

  printf("終了\n");
}
```

```:入力1
2 3
```

```:実行結果1
xとyは等しくない
終了
```

```:入力2
10 10
```

```:実行結果2
xとyは10
終了
```

```:入力3
0 8
```

```:実行結果3
xとyは等しくない
xかyは0
終了
```

## 「前の条件が真でないとき」の処理

### else句

__else句__は、if文の後に書くことで「if文の条件が偽の時」に処理を行えるようになります。
書き方は次のようになります。

```c
if (条件式1) {
  処理1
}
else {
  処理2
}
```

次のプログラムは入力の値が10より小さければ「xは10より小さい」と出力し、そうでなければ「xは10より小さくない」と出力します。

```c
#include <stdio.h>

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

  if(x < 10){
    printf("xは10より小さい\n");
  }
  else {
    printf("xは10より小さくない\n");
  }
}
```

```:入力1
5
```

```:実行結果1
xは10より小さい
```

```:入力2
15
```

```:実行結果2
xは10より小さくない
```

### else if

__else if__は「『前のif文の条件が偽』かつ『else ifの条件が真』」の時に処理が行われます。

書き方は次のようになります。

```c
if (条件式1) {
  処理1
}
else if (条件式2) {
  処理2
}
```

処理2が実行されるのは「条件式1が偽 かつ 条件式2が真」のときになります。

else ifの後に続けてelse ifやelseを書くこともできます。次のプログラムはその例です。

```c
#include <stdio.h>

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

  if(x < 10){
    printf("xは10より小さい\n");
  }
  else if(x > 20){
    printf("xは10より小さくなくて、20より大きい\n");
  }
  else if(x == 15){
    printf("xは10より小さくなくて、20より大きくなくて、15である\n");
  }
  else{
    printf("xは10より小さくなくて、20より大きくもなくて、15でもない\n");
  }
}
```

```:入力1
5
```

```:実行結果1
xは10より小さい
```

```:入力2
30
```

```:実行結果2
xは10より小さくなくて、20より大きい
```

```:入力3
15
```

```:実行結果3
xは10より小さくなくて、20より大きくなくて、15である
```

```:入力4
13
```

```:実行結果4
xは10より小さくなくて、20より大きくもなくて、15でもない
```

## 注意点

### よくあるミス

`==`のつもりで`=`とだけ書いてしまわないように注意しましょう。

次のプログラムは「xが10と等しいか」を判定するプログラムの典型的なミスです。

```c
#include <stdio.h>

int main(void){
  int x = 5;

  if(x = 10){
    printf("xは10\n");
  }
}
```

```:実行結果
xは10
```

`if (x = 10)`のif文はxがどんな数値でも真だと判定されます。ハマりどころなので覚えておきましょう。なぜそうなるかは次の節で説明します。

## 細かい話

細かい話なので、飛ばして問題を解いても良いです。

### `{ }` の省略

処理の部分が1文しか無い場合は、`{ }`を省略することができます。

```c
if(x < 10)
  printf("xは10より小さい\n");
```

「1文」とは、「セミコロンが1つだけで十分な処理」だと思えば良いです。
つまり、以下のような書き方は思った通りには動きません。

```c
if(x < 10)
  printf("xは10より小さい\n"); printf("Hello!\n");
```

これは次のように書いたのと同じ意味になります。

```c
if(x < 10){
  printf("xは10より小さい\n");
}
printf("Hello!\n");
```

### if文のネスト

if文の中にif文を入れることをif文の__ネスト__と言います。

```c
#include <stdio.h>

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

  if(x == 10){
    printf("xは10\n");
    if(y == 10){
      printf("yも10\n");
    }
  }

  printf("終了\n");
}
```

```:入力1
10 10
```

```:実行結果1
xは10
yも10
終了
```

```:入力2
5 10
```

```:実行結果2
終了
```

## 問題

以下のリンク先に問題文が載っています。

[EX6 - 電卓をつくろう](https://atcoder.jp/contests/apg4b/tasks/APG4b_cq)

```c:サンプルプログラム
#include <stdio.h>

int main(void){
  int A, B;
  char op;
  scanf("%d %c %d", &A, &op, &B);

  if (op == '+') {
    printf("%d\n", A + B);
  }
  // ここにプログラムを追記
}
```

### 解答例

__必ず自分で問題に挑戦してみてから見てください。__

<details><summary>解答例</summary>
<div>

```c
#include <stdio.h>

int main(void){
  int A, B;
  char op;
  scanf("%d %c %d", &A, &op, &B);

  if (op == '+') {
    printf("%d\n", A + B);
  }
  else if (op == '-') {
   printf("%d\n", A - B);
  }
  else if (op == '*') {
    printf("%d\n", A * B);
  }
  else if (op == '/' && B != 0) {
    printf("%d\n", A / B);
  }
  else {
    printf("error\n");
  }
}
```

</div>
</details>

# [H - 1.07.条件式の結果とbool型](https://atcoder.jp/contests/apg4b/tasks/APG4b_h)

## キーポイント

- 条件式の結果は真のとき`1`に、偽のとき`0`になる
- `1`を`true`で、`0`を`false`で表す
- __bool型__は`true`と`false`だけが入る型

||int型の表現|bool型の表現|
|---|---|---|
|真|1|true|
|偽|0|false|

## 条件式の結果

C言語では、真のことを数値の`1`で表現し、偽のことを数値の`0`で表現します。
条件式の「計算結果」も真のときは`1`、偽のときは`0`になります。

次のプログラムは条件式の結果をそのまま出力し、真のときと偽のときでどのような値を取るかを確認しています。

```c
#include <stdio.h>

int main(void){
  printf("%d\n", (5 < 10)); //真
  printf("%d\n", (5 > 10)); //偽
}
```

```:実行結果
1
0
```

出力を見てみると、条件が真のときは`1`、偽のときは`0`になっていることがわかります。

`1 + 1`の計算結果が`2`という数値になること同じように、条件式`5 < 10`の計算結果は1という数値になるということです。

## trueとfalse

条件式の部分に直接`1`や`0`を書くこともできます。次のプログラムはその例です

```c
#include <stdio.h>

int main(void){
  
  // 1は真を表すのでhelloと出力される
  if(1){
    printf("hello\n");
  }
  
  // 0は偽を表すのでこのifの中は実行されない
  if (0) {
    printf("world\n");
  }
  
}
```

```:実行結果
hello
```

先述したとおり、C言語では「1と真」「0と偽」はほとんど同じ意味になります。
しかし、「数値としての1と0」なのか、「真偽を表すための1と0」なのかが分かりにくいことがあります。
そのため、真のことを `true` 、偽のことを `false` で表すことができるようになっています。その場合、stdbool.h をインクルードする必要があります。

次のプログラムは上のプログラムと同じ動作をします。

```c
#include <stdio.h>
#include <stdbool.h>

int main(void){
  
  // 1と書くよりも真だということがわかりやすい
  if(true){
    printf("hello\n");
  }
  
  // 0と書くよりも偽だということがわかりやすい
  if (false) {
    printf("world\n");
  }
  
}
```

## bool型

__bool型__というデータ型があります。stdbool.h をインクルードすると使うことができます。この型の変数には__true__またはfalseだけが入ります。

```c
#include <stdio.h>
#include <stdbool.h>

int main(void){
  int x;
  scanf("%d", &x);
  
  bool a = true;
  bool b = x < 10; // xが10未満のときtrue そうでないときfalseになる
  bool c = false;
  
  if (a && b) {
    printf("hello\n");
  }
  if (c) {
    printf("world\n");
  }
}
```

```:入力
3
```

```:実行結果
hello
```

このように、条件式の結果など、真偽のデータを変数で扱いたい場合はbool型を使います。

いままで`if (条件式)`と書いていましたが、基本的には`if (bool型の値)`ということになります。

ここまでの話をまとめたのが次の表です。

||int型の表現|bool型の表現|
|---|---|---|
|真|1|true|
|偽|0|false|

### bool型を使う場面

今まで学んできたものと違い、「bool型がないと書けないプログラム（計算）」はありません。
bool型は基本的に「条件式の結果」や「状態が2つしか無いもの」を扱っていることを明示するために使います。

これができることによる恩恵は今はわかりにくいかもしれませんが、bool型を使うことでプログラムがわかりやすくなることがあります。
なお、今後は「真」や「偽」という言葉の代わりに__true__や__false__という言葉を使って説明することがあるので、これらの意味はしっかりと覚えておいてください。

## 細かい話

細かい話なので、飛ばして問題を解いても良いです。

### bool型と数値

実は、`0`と`1`以外の数値もbool型の値のように扱うことができます。
その場合、`0`のときだけ`false`、それ以外の数値はすべて`true`になります。

```c
#include <stdio.h>
#include <stdbool.h>

int main(void){
  bool a = 10; // 10はtrue
  bool b = 0; // 0はfalse
  
  //変換指定子は int と同じ
  printf("%d\n", a); // 1
  printf("%d\n", b); // 0
  
  // 100はtrue
  if (100) {
    printf("hello\n");
  }
}
```

```:実行結果
1
0
hello
```

if文の節で紹介した`==`と`=`を書き間違える典型的なミスは、この「trueとfalse以外の値もbool型のように受け入れてしまう」という性質によって引き起こされています。
`a = b`という式の「計算結果」は`b`になります。そのため、`if (a = b)`は`if (b != 0)`とほとんど同じ意味になってしまいます。

## 問題

以下のリンク先に問題文が載っています。

[EX7.bool値パズル](https://atcoder.jp/contests/apg4b/tasks/APG4b_cp)

```c:サンプルプログラム
#include <stdio.h>
#include <stdbool.h>

int main(void) {
  // 変数a,b,cにtrueまたはfalseを代入してAtCoderと出力されるようにする。
  bool a = // true または false
  bool b = // true または false
  bool c = // true または false
 
  // ここから先は変更しないこと
 
  if (a) {
    printf("At");
  }
  else {
    printf("Yo");
  }
 
  if (!a && b) {
    printf("Bo");
  }
  else if (!b || c) {
    printf("Co");
  }
 
  if (a && b && c) {
    printf("foo!");
  }
  else if (true && false) {
    printf("yeah!");
  }
  else if (!a || c) {
    printf("der");
  }
 
  printf("\n");
}
```

### 解答例

__必ず自分で問題に挑戦してみてから見てください。__

<details><summary>解答例</summary>
<div>

```c
#include <stdio.h>
#include <stdbool.h>

int main(void) {
  // 変数a,b,cにtrueまたはfalseを代入してAtCoderと出力されるようにする。
  bool a = true; // true または false
  bool b = false; // true または false
  bool c = true; // true または false
 
  // ここから先は変更しないこと
 
  if (a) {
    printf("At");
  }
  else {
    printf("Yo");
  }
 
  if (!a && b) {
    printf("Bo");
  }
  else if (!b || c) {
    printf("Co");
  }
 
  if (a && b && c) {
    printf("foo!");
  }
  else if (true && false) {
    printf("yeah!");
  }
  else if (!a || c) {
    printf("der");
  }
 
  printf("\n");
}
```

</div>
</details>

# [I - 1.08.変数のスコープ](https://atcoder.jp/contests/apg4b/tasks/APG4b_i)

## キーポイント

- `{ }`で囲われた部分のところを__ブロック__という
- 変数が使える範囲のことを__スコープ__という
- 変数のスコープは「変数が宣言されてからそのブロックが終わるまで」
- スコープが重なっている場合は最も内側のブロックで宣言された変数が選ばれる

## 変数のスコープ

今までmain関数やif文の後には`{ }`を書いてきました。この`{ }`で囲った部分のところを__ブロック__といいます。

あるブロックの中で宣言した変数は、それより内側のブロックでしか使えないというルールがあります。そして、その変数が使える範囲のことを__スコープ__といいます。
具体例を見てみましょう。

```c
#include <stdio.h>

int main(void) {
  int x = 5; // xのスコープはこの行からmain関数のブロックの終わりまで
 
  if (x == 5) {
    int y = 10; // yのスコープはこの行からif文のブロックの終わりまで
    printf("%d\n", x + y);
  }
 
  printf("%d\n", x);
  printf("%d\n", y);
}
```

```:コンパイルエラー
./Main.c: In function ‘main’:
./Main.c:12:18: error: ‘y’ undeclared (first use in this function)
   12 |   printf("%d\n", y);
      |                  ^
./Main.c:12:18: note: each undeclared identifier is reported only once for each function it appears in
```

変数`y`は6行目からはじめるif文のブロックで宣言されています。

```c
if (x == 5) {
  int y = 10; // yのスコープはこの行からif文のブロックの終わりまで
  printf("%d\n", x + y);
}
```

しかし、12行目の

```c
printf("%d\n", y);
```

は`y`を宣言したブロックよりも外側にあるので、`y`を使うことができません。

なお、変数`y`のスコープ、つまり変数`y`が使える場所は、「変数が宣言されてからそのブロックが終わるまで」なので、7行目から9行目の間ということになります。

```c
int y = 10; // yのスコープはこの行からif文のブロックの終わりまで
  printf("%d\n", x + y);
}
```

### 同じ名前の変数

変数を宣言するブロックが異なれば、同じ名前の変数を宣言することができます。

```c
#include <stdio.h>

int main(void) {
  int x = 10;
  if (x == 5) {
    int y = 10;
    printf("%d\n", x + y);
    
    // char y = 'a'; 同じブロックに変数yがあるので宣言できない
  }
 
  if(x == 10){
    char y = 'a'; // ブロックが違うので変数yを宣言できる
    printf("%d%c\n", x, y);
  }
}
```

```:実行結果
10a
```

### スコープがある理由

スコープがある理由はいくつかありますが、その中から一つ説明します。

スコープがない場合、一度宣言した変数等の名前は別の場所で使えなくなってしまいます。
プログラムの規模が大きくなってくると、その分多くの変数が用いられます。そのため、新しく変数を宣言しようとしたとき、まだ使われていない名前を考えることに手間がかかってしまいます。

スコープがあることで、プログラムの別の部分でどのような名前が使われているかをあまり考えること無く、変数等の名前を決められるようになります。

## 問題

解説していない文字列が出てきてしまっているので、軽く説明しておきます。
文字列は

```c
char s[100];
```

のように宣言します。`[]`の中身は文字数になりますが、必ず多めに取っておくようにしてください。文字列の変換指定子は`%s`です。

```c
char s[100]

scanf("%s", s);
printf("%s\n", s);
```

のように書きます。文字列の入力を受け取る時には`&`を付けないということに注意してください。

以下のリンク先に問題文が載っています。

[EX8.たこ焼きセット](https://atcoder.jp/contests/apg4b/tasks/APG4b_co)

```c:A君が書いたプログラム
#include <stdio.h>

int main(void) {
  int p;
  scanf("%d", &p);
 
  // パターン1
  if (p == 1) {
    int price;
    scanf("%d", &price);
  }
 
  // パターン2
  if (p == 2) {
    char text[50];
    int price;
    scanf("%s", text);
    scanf("%d", &price);
  }
 
  int N;
  scanf("%d", &N);
 
  printf("%s!\n", text);
  printf("%d\n", price * N);
}
```

### 解答例

__必ず自分で問題に挑戦してみてから見てください。__

<details><summary>解答例</summary>
<div>

```c
#include <stdio.h>

int main(void) {
  int p;
  scanf("%d", &p);
 
  // パターン2
  if (p == 2) {
    char text[50];
    scanf("%s", text);
    printf("%s!\n", text);
  }
  
  int price;
  scanf("%d", &price);
  int N;
  scanf("%d", &N);
 
  printf("%d\n", price * N);
}
```

</div>
</details>

# [J - 1.09.複合代入演算子](https://atcoder.jp/contests/apg4b/tasks/APG4b_j)

## キーポイント

- `x = x + y`は`x += y`のように短く書ける
- `x += 1`は`x++`と書ける（__インクリメント__）
- `x -= 1`は`x--`と書ける（__デクリメント__）

## 複合代入演算子

`x = x + 1` のように、同じ変数名が2回現れる代入文では、__複合代入演算子__を使うとより短く書くことができます。

次のプログラムは、変数`x`に`(1 + 2)`を足して出力するだけのプログラムです。

```c
#include <stdio.h>

int main(void) {
  int x = 5;
  x += 1 + 2;
  printf("%d\n", x); // 8
}
```

```:実行結果
8
```

```c
x += 1 + 2;
```
は

```c
x = x + (1 + 2);
```

と同じ意味になります。

### +=以外の複合代入演算子

他の算術演算子についても同様のことができます。

```c
#include <stdio.h>

int main(void) {
  int a = 5;
  a -= 2;
  printf("%d\n", a); // 3
 
  int b = 3;
  b *= 1 + 2;
  printf("%d\n", b);// 9
 
  int c = 4;
  c /= 2;
  printf("%d\n", c); // 2
 
  int d = 5;
  d %= 2;
  printf("%d\n", d); // 1
}
```

```:実行結果
3
9
2
1
```

### インクリメントとデクリメント

`x = x + 1`は`x++`または`++x`と書くことができます。このような「1増やす操作」を__インクリメント__と言います。

`x = x - 1`は`x--`または`--x`と書くことができます。このような「1減らす操作」を__デクリメント__と言います。

```c
#include <stdio.h>

int main(void) {
  int x = 5;
  x++;
  printf("%d\n", x); // 6
 
  int y = 5;
  y--;
  printf("%d\n", y); // 4
}
```

```:実行結果
6
4
```

このように、プログラムを短く書くための記法のことを__シンタックスシュガー__と言います。

## 問題

以下のリンク先に問題文が載っています。

[EX9.複合代入演算子を使おう](https://atcoder.jp/contests/apg4b/tasks/APG4b_cn)

```c:サンプルプログラム
#include <stdio.h>

int main(void) {
  int x, a, b;
  scanf("%d%d%d", &x, &a, &b);
 
  // 1.の出力
  x++;
  printf("%d\n", x);
 
  // ここにプログラムを追記
}
```

### 解答例

__必ず自分で問題に挑戦してみてから見てください。__

<details><summary>解答例</summary>
<div>

```c
#include <stdio.h>

int main(void) {
  int x, a, b;
  scanf("%d%d%d", &x, &a, &b);
 
  // 1.の出力
  x++;
  printf("%d\n", x);
 
  // ここにプログラムを追記
  x *= a + b;
  printf("%d\n", x);
  
  x *= x;
  printf("%d\n", x);
  
  x--;
  printf("%d\n", x);
}
```

</div>
</details>

# [K - 1.10.while文 ](https://atcoder.jp/contests/apg4b/tasks/APG4b_k)

## キーポイント

- while文を使うと繰り返し処理ができる
- 条件式が真のとき処理を繰り返す

```c
while (条件式) {
  処理
}
```

- 「N回処理する」というプログラムを書く場合、「カウンタ変数を0からはじめ、カウンタ変数がNより小さいときにループ」という形式で書く

```c
int i = 0; // カウンタ変数
while (i < N) {
  処理
  i++;
}
```

## while文

__while文__を使うと、プログラムの機能の中でも非常に重要な「繰り返し処理」（ループ処理）を行うことができます。

### 無限ループ

次のプログラムは、「`"Hello"`と出力して改行した後、`"AtCoder"`と出力する処理」を無限に繰り返すプログラムです。

```c
#include <stdio.h>
#include <stdbool.h>

int main(void) {
  
  while (true) {
    printf("Hello\n");
    printf("AtCoder\n");
  }
  
}
```

```:実行結果
Hello
AtCoder
Hello
AtCoder
Hello
AtCoder
Hello
AtCoder
Hello
AtCoder
...(無限に続く)
```

while文は次のように書き、条件式が真のとき処理を繰り返し続けます。

```c
while (条件式) {
  処理
}
```

先のプログラムでは条件式の部分に`true`と書いているため、無限に処理を繰り返し続けます。
このように、無限に繰り返し続けることを__無限ループ__と言います。

### 1ずつカウントする

次プログラムは、1から順に整数を出力し続けます。

```c
#include <stdio.h>
#include <stdbool.h>

int main(void) {
  
  int i = 1;
  
  while (true) {
    printf("%d\n", i);
    i++; //ループのたびに1増やす
  }
  
}
```

```:実行結果
1
2
3
4
5
6
7
8
...(無限に1ずつ増えていく)
```

ずっと出力を追っていると途中で負の値になったかもしれません。なぜそうなるかは本家APG4bでは「3.01.数値型」で説明されています。[^4]
[^4]: そこまで書く予定はないので、興味がある人は各自調べてください。

### ループ回数の指定

1ずつカウントするプログラムを「1から5までの数を出力するプログラム」に変える場合、次のようにします。

```c
#include <stdio.h>

int main(void) {
  
  int i = 1;
  
  // iが5以下の間だけループ
  while (i <= 5) {
    printf("%d\n", i);
    i++;
  }
  
}
```

```:実行結果
1
2
3
4
5
```

### カウンタ変数は0からN未満まで

5回`Hello`と出力するプログラムを考えます。
まず一般的でない書き方（やめておいた方が良い書き方）を紹介し、次に一般的な書き方（推奨される書き方）を紹介します。

```c:一般的でない書き方
#include <stdio.h>

int main(void) {
  
  // iを1からはじめる
  int i = 1;
  
  // iが5以下の間だけループ
  while (i <= 5) {
    printf("Hello\n");
    i++;
  }
  
}
```

```:実行結果
Hello
Hello
Hello
Hello
Hello
```

「N回処理をする」というプログラムをwhile文で書く場合、今までは「iを1からはじめ、N以下の間ループする」という形式で書いてきました。

```c
int i = 1;
while (i <= N) {
  処理
  i++;
}
```

この形式は一見わかりやすいと感じるかもしれません。
しかし、この書き方はあまり一般的ではなく、次のように書いたほうが良いです


```c:一般的な書き方
#include <stdio.h>

int main(void) {
  
  // iを0からはじめる
  int i = 0;
  
  // iが5未満の間だけループ
  while (i < 5) {
    printf("Hello\n");
    i++;
  }
  
}
```

```:実行結果
Hello
Hello
Hello
Hello
Hello
```

「N回処理する」というプログラムを書く場合、次のように__「iを0からはじめ、iがNより小さいときにループする」という形式で書くのが一般的__です。

```c
int i = 0;
while (i < N) {
  処理
  i++;
}
```

最初は分かりづらく感じるかもしれませんが、こう書いた方がプログラムをシンプルに書けることが後々増えてくるので、慣れるようにしましょう。

なお、このプログラムの変数`i`のように、「何度目のループか」を管理する変数のことを__カウンタ変数__と呼ぶことがあります。 カウンタ変数は基本的に`i`を使い、`i`が使えない場合は`j`, `k`, `l`...と名前をつけていくのが一般的です。

### 応用例

N人の合計点を求めるプログラムを作ってみましょう。
次のプログラムは「入力の個数N」と「点数を表すN個の整数」を入力で受け取り、点数の合計を出力します。

```c
#include <stdio.h>

int main(void) {
  int N;
  scanf("%d", &N);
 
  int sum = 0; // 合計点を表す変数
  int x;       // 入力を受け取る変数
  int i = 0;   // カウンタ変数
 
  while (i < N) {
    scanf("%d", &x);
    sum += x;
    i++;
  }
 
  printf("%d\n", sum);
}
```

```:入力
3
1 10 100
```

```:実行結果
111
```

合計点を表す変数`sum`を作っておき、ループするたびに入力を変数`x`に入れ、`sum`に足しています。
このように、繰り返し処理を使えば様々な処理が行えるようになります。

## 細かい話

細かい話なので、飛ばして問題を解いても良いです。

### 2ずつ増やす

今までは`i`を1ずつだけ増やしてきましたが、2ずつ増やすこともできます。

```c
#include <stdio.h>

int main(void) {
  
  int i = 0;
 
  while (i < 10) {
    printf("%d\n", i);
    i += 2;
  }
  
}
```

```:実行結果
0
2
4
6
8
```

次のように書くことで2ずつ増やしています。

```c
i += 2;
```

同様にして、より多く飛ばしてループすることもできます。

### 逆順ループ

5から0までの数を出力したい場合は以下のようにします。

```c
#include <stdio.h>

int main(void) {
  
  int i = 5;
 
  while (i >= 0) {
    printf("%d\n", i);
    i--;
  }
  
}
```

```:実行結果
5
4
3
2
1
0
```

こちらはデクリメントを使うことで1ずつ減らしています。

```c
i--;
```

### 無限ループをコードテストで実行した場合

AtCoderのコードテストでは実行時間が長すぎるとプログラムが中断されます。また、出力が長すぎる場合も途中から省略されます。
そのため、はじめに紹介した「`"Hello"`と出力して改行した後、`"AtCoder"`と出力する処理」を無限に繰り返すプログラムをコードテストで実行しても無限には出力されず、次のように表示されます。

```:標準出力
Hello
AtCoder
（中略）
Hello
AtCoder
He...
```

```:終了コード
9
```

無限ループが発生した場合、終了コードは実行時間が長すぎることを表す9となります。

## 問題

以下のリンク先に問題文が載っています。

[EX10.棒グラフの出力](https://atcoder.jp/contests/apg4b/tasks/APG4b_cm)

```c:サンプルプログラム
#include <stdio.h>

int main(void) {
  int A, B;
  scanf("%d%d", &A, &B);
 
  // ここにプログラムを追記
  
}
```

### 解答例

__必ず自分で問題に挑戦してみてから見てください。__

<details><summary>解答例</summary>
<div>

```c
#include <stdio.h>

int main(void) {
  int A, B;
  scanf("%d%d", &A, &B);
 
  int i = 0;
  printf("A:");
  while (i < A) {
    printf("]");
    i++;
  }
  printf("\n");
 
  i = 0;
  printf("B:");
  while (i < B) {
    printf("]");
    i++;
  }
  printf("\n");
  
}
```

</div>
</details>

# おわりに

ということで今回は、1.10まで書いてみました。後半どうするか悩んでいるので、その辺が解決すれば続編が出るかもしれません。気長にお待ちください。

はじめに書いたように、問題があれば本記事は削除します。その点はよろしくお願いいたします。

[next](https://qiita.com/cnng0712/items/709292655d77ee335199)