0
0

Delete article

Deleted articles cannot be recovered.

Draft of this article would be also deleted.

Are you sure you want to delete this article?

More than 3 years have passed since last update.

C言語版 APG4b 中編

Last updated at Posted at 2020-09-05

本記事について

この記事は 前編 の続きとなります。前編を読んだことを前提として進めていくので、読んでからこの記事を読むことを推奨します。
前回 1.00 から 1.05 までを扱ったため、今回の内容は 1.06 から 1.10 までとなっています。

後編はこちら

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

目次

  • 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文・比較演算子・論理演算子

キーポイント

  • __if文__を使うと「ある条件が正しい時だけ処理をする」というプログラムが書ける
  • __else句__を使うと「条件式が正しくなかった時」の処理を書ける
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 || 条件式2 条件式1が真 または 条件式2が真 条件式1と条件式2の少なくとも片方が真

if文

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

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

if (条件式) {
  処理
}

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

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

#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に整数のデータを入力しています。

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

重要なのはその後です。

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

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

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

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

{
  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言語では>=,<=のように__右に__=をつけます。

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

#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 || 条件式2 条件式1が真 または 条件式2が真 条件式1と条件式2の少なくとも片方が真
#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文の条件が偽の時」に処理を行えるようになります。
書き方は次のようになります。

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

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

#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の条件が真』」の時に処理が行われます。

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

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

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

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

#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と等しいか」を判定するプログラムの典型的なミスです。

#include <stdio.h>

int main(void){
  int x = 5;

  if(x = 10){
    printf("xは10\n");
  }
}
実行結果
xは10

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

細かい話

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

{ } の省略

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

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

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

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

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

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

if文のネスト

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

#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 - 電卓をつくろう

サンプルプログラム
#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);
  }
  // ここにプログラムを追記
}

解答例

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

解答例
#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");
  }
}

H - 1.07.条件式の結果とbool型

キーポイント

  • 条件式の結果は真のとき1に、偽のとき0になる
  • 1trueで、0falseで表す
  • __bool型__はtruefalseだけが入る型
int型の表現 bool型の表現
1 true
0 false

条件式の結果

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

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

#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

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

#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 をインクルードする必要があります。

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

#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だけが入ります。

#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型と数値

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

#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値パズル

サンプルプログラム
#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");
}

解答例

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

解答例
#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");
}

I - 1.08.変数のスコープ

キーポイント

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

変数のスコープ

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

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

#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文のブロックで宣言されています。

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

しかし、12行目の

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

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

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

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

同じ名前の変数

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

#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

スコープがある理由

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

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

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

問題

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

char s[100];

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

char s[100]

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

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

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

EX8.たこ焼きセット

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);
}

解答例

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

解答例
#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);
}

J - 1.09.複合代入演算子

キーポイント

  • x = x + yx += yのように短く書ける
  • x += 1x++と書ける(インクリメント
  • x -= 1x--と書ける(デクリメント

複合代入演算子

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

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

#include <stdio.h>

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

x = x + (1 + 2);

と同じ意味になります。

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

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

#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 + 1x++または++xと書くことができます。このような「1増やす操作」を__インクリメント__と言います。

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

#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.複合代入演算子を使おう

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

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

解答例

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

解答例
#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);
}

K - 1.10.while文

キーポイント

  • while文を使うと繰り返し処理ができる
  • 条件式が真のとき処理を繰り返す
while (条件式) {
  処理
}
  • 「N回処理する」というプログラムを書く場合、「カウンタ変数を0からはじめ、カウンタ変数がNより小さいときにループ」という形式で書く
int i = 0; // カウンタ変数
while (i < N) {
  処理
  i++;
}

while文

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

無限ループ

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

#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文は次のように書き、条件式が真のとき処理を繰り返し続けます。

while (条件式) {
  処理
}

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

1ずつカウントする

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

#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.数値型」で説明されています。1

ループ回数の指定

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

#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と出力するプログラムを考えます。
まず一般的でない書き方(やめておいた方が良い書き方)を紹介し、次に一般的な書き方(推奨される書き方)を紹介します。

一般的でない書き方
#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以下の間ループする」という形式で書いてきました。

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

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

一般的な書き方
#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より小さいときにループする」という形式で書くのが一般的__です。

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

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

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

応用例

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

#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ずつ増やすこともできます。

#include <stdio.h>

int main(void) {
  
  int i = 0;
 
  while (i < 10) {
    printf("%d\n", i);
    i += 2;
  }
  
}
実行結果
0
2
4
6
8

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

i += 2;

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

逆順ループ

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

#include <stdio.h>

int main(void) {
  
  int i = 5;
 
  while (i >= 0) {
    printf("%d\n", i);
    i--;
  }
  
}
実行結果
5
4
3
2
1
0

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

i--;

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

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

標準出力
Hello
AtCoder
(中略)
Hello
AtCoder
He...
終了コード
9

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

問題

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

EX10.棒グラフの出力

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

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

解答例

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

解答例
#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");
  
}

おわりに

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

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

next

  1. そこまで書く予定はないので、興味がある人は各自調べてください。

0
0
0

Register as a new user and use Qiita more conveniently

  1. You get articles that match your needs
  2. You can efficiently read back useful information
  3. You can use dark theme
What you can do with signing up
0
0

Delete article

Deleted articles cannot be recovered.

Draft of this article would be also deleted.

Are you sure you want to delete this article?