C++ の制御フロー

C++C++Intermediate

💡 このチュートリアルは英語版からAIによって翻訳されています。原文を確認するには、 ここをクリックしてください

はじめに

この実験では、C++ の制御フロー文を学びます。if-else 文、switch 文、while ループ、do-while ループ、および for ループの使い方を学びます。

これは Guided Lab です。学習と実践を支援するためのステップバイステップの指示を提供します。各ステップを完了し、実践的な経験を積むために、指示に注意深く従ってください。過去のデータによると、この 中級 レベルの実験の完了率は 64%です。学習者から 100% の好評価を得ています。

コンテンツの概要

基本的なフロー制御構造には 3 つあります。直列的な条件付き(または判定)、およびループ(または反復)です。直列構造:実行プロセスは上から下に 1 行ずつです。条件付き構造は、if-else 文を使用して、特定の条件を満たすかどうかを検証し、その後選択を行います。ループ構造は、何度も同じ論理演算を実行するために使用されます。

画像の説明

直列的なフロー制御

プログラムは命令のシーケンスです。直列的なフローは最も一般的で単純で、プログラミングステートメントは書かれた順序で、つまり上から下に順次実行されます。

条件付きフロー制御

条件付き文にはいくつかの種類があります。if-thenif-then-elseネストされた ifif-elseif-elseif-...-else)、switch-case、および条件付き式です。

#include <iostream>
using namespace std;

int main(){

	int mark;

	cout<<"0 から 100 までの数値を入力してください:";
	cin>>mark;
    // if
    if (mark >= 50) {
       cout << "おめでとうございます!" << endl;
       cout << "この調子で頑張ってください!" << endl;
    }

    cout<<"0 から 100 までの数値を入力してください:";
	cin>>mark;
    // if-else
    if (mark >= 50) {
       cout << "おめでとうございます!" << endl;
       cout << "この調子で頑張ってください!" << endl;
    } else {
       cout << "もう少し頑張りましょう!" << endl;
    }

	cout<<"0 から 100 までの数値を入力してください:";
	cin>>mark;
    // ネストされた if
    if (mark >= 80) {
       cout << "A" << endl;
    } else if (mark >= 70) {
       cout << "B" << endl;
    } else if (mark >= 60) {
       cout << "C" << endl;
    } else if (mark >= 50) {
       cout << "D" << endl;
    } else {
       cout << "F" << endl;
    }

    // switch-case
    char oper;
    int num1 = 1, num2 = 2, result = 0;
    cout<<"[+ - / *] の文字を入力してください:";
    cin>> oper;
    switch (oper) {
       case '+':
          result = num1 + num2;
          break;
       case '-':
          result = num1 - num2;
          break;
       case '*':
          result = num1 * num2;
          break;
       case '/':
          result = num1 / num2;
          break;
       default:
          cout << "不明な演算子" << endl;
    }
    cout<<num1<<oper<<num2<<"="<<result;
    return 0;
}

出力:

0から100までの数値を入力してください: 50
おめでとうございます!
この調子で頑張ってください!
0から100までの数値を入力してください: 40
もう少し頑張りましょう!
0から100までの数値を入力してください: 85
A
[+ - / *]の文字を入力してください: +
1+2=3
画像の説明

条件付き演算子:条件付き演算子は 3 項演算子で、booleanExpr? trueExpr : falseExprの形式です。booleanExprに応じて、trueExprまたはfalseExprの値を評価して返します。

// "PASS" または "FAIL" を返し、cout に出力する
cout << (mark >= 50)? "PASS" : "FAIL" << endl;

max = (a > b)? a : b;   // 右辺は a または b を返す
abs = (a > 0)? a : -a;  // 右辺は a または-a を返す

ブレース:ブロック内に 1 つのステートメントだけがある場合、ブレース{ }を省略することができます。たとえば、

if (mark >= 50)
   cout << "PASS" << endl;   // 1 つのステートメントのみなので、{ }を省略できますが、推奨されません
else {                       // 複数のステートメントの場合は、{ }が必要です
   cout << "FAIL" << endl;
   cout << "もう少し頑張りましょう!" << endl;
}

ただし、ブロック内に 1 つのステートメントだけがある場合でも、プログラムの読みやすさを向上させるために、ブレースを使用することをお勧めします。

ループフロー制御

再び、いくつかの種類のループがあります。for ループwhile-do、およびdo-whileです。

// for ループ
int sum = 0;
for (int number = 1; number <= 100; ++number) {
   sum += number;
}

// while-do
int sum = 0, number = 1;
while (number <= 100) {
   sum += number;
   ++number;
}

// do-while
int sum = 0, number = 1;
do {
   sum += number;
   ++number;
} while (number <= 100);

上限値をユーザーに入力させます。1 から与えられた上限値までの整数の合計を求め、その平均を計算します。

/*
 * 1 から与えられた上限値までの合計を求め、その平均を計算します。
 */
#include <iostream>
using namespace std;

int main() {
   int sum = 0;     // 累積和を格納する
   int upperbound;
   cout << "上限値を入力してください:";
   cin >> upperbound;

   // 1 から上限値までの合計
   for (int number = 1; number <= upperbound; ++number) {
      sum += number;
   }
   cout << "合計は " << sum << endl;
   cout << "平均は " << (double)sum / upperbound << endl;

   // 奇数のみの合計
   int count = 0;     // 奇数の個数
   sum = 0;           // 合計をリセット
   for (int number=1; number <= upperbound; number=number+2) {
      ++count;
      sum += number;
   }
   cout << "奇数の合計は " << sum << endl;
   cout << "平均は " << (double)sum / count << endl;
}

出力:

上限値を入力してください: 15
合計は 120
平均は 8
奇数の合計は 64
平均は 8
画像の説明

ループフローの中断 - "break" と "continue"

break 文は、現在の(最内側の)ループを抜けて終了します。

continue 文は、現在の反復を中止し、現在の(最内側の)ループの次の反復に続きます。

breakcontinue は、読みにくく追跡しにくいため、構造が悪いです。絶対に必要な場合にのみ使用してください。常に breakcontinue を使用せずに同じプログラムを書くことができます。

次のプログラムは、2 から上限値までの非素数を表示します。

/*
 * 1 から上限値までの非素数を表示します。
 */
#include <iostream>
#include <cmath>
using namespace std;

int main() {
   int upperbound;
   cout << "上限値を入力してください:";
   cin >> upperbound;
   for (int number = 2; number <= upperbound; ++number) {
      // 2 から sqrt(number) までの因数がある場合、素数ではありません
      int maxFactor = (int)sqrt(number);
      for (int factor = 2; factor <= maxFactor; ++factor) {
         if (number % factor == 0) {   // 因数ですか?
            cout << number << " ";
            break;   // 因数が見つかりましたので、さらに因数を探す必要はありません
         }
      }
   }
   cout << endl;
   return 0;
}

出力:

上限値を入力してください: 20
4 6 8 9 10 12 14 15 16 18 20
画像の説明

代わりに、上記のプログラムを書き換えて、すべての素数を表示しましょう。isPrime と呼ばれる boolean フラグを使用して、現在の number が素数であるかどうかを示します。その後、これを使用して表示を制御します。

/*
 * 1 から上限値までの素数を表示します。
 */
#include <iostream>
#include <cmath>
using namespace std;

int main() {
   int upperbound;
   cout << "上限値を入力してください:";
   cin >> upperbound;
   for (int number = 2; number <= upperbound; ++number) {
      // 2 から sqrt(number) までの因数がある場合、素数ではありません
      int maxFactor = (int)sqrt(number);
      bool isPrime = true;  // number が素数であるかどうかを示す boolean フラグ
      for (int factor = 2; factor <= maxFactor; ++factor) {
         if (number % factor == 0) {   // 因数ですか?
            isPrime = false;   // number は素数ではありません
            break;   // 因数が見つかりましたので、さらに因数を探す必要はありません
         }
      }
      if (isPrime) cout << number << " ";
   }
   cout << endl;
   return 0;
}

出力:

上限値を入力してください: 100
2 3 5 7 11 13 17 19 23 29 31 37 41 43 47 53 59 61 67 71 73 79 83 89 97
画像の説明

次の breakcontinue を使用したプログラムを検討してください。

/* 謎のシリーズ */
#include <iostream>
using namespace std;

int main() {
   int number = 1;
   while (true) {
      ++number;
      if ((number % 3) == 0) continue;
      if (number == 53) break;
      if ((number % 2) == 0) {
         number += 3;
      } else {
         number -= 3;
      }
      cout << number << " ";
   }
   cout << endl;
   return 0;
}

出力:

5 4 2 7 11 10 8 13 17 16 14 19 23 22 20 25 29 28 26 31 35 34 32 37 41 40 38 43 47 46 44 49 53 52
画像の説明

プログラムの終了

プログラミングステートメントの終了前に、プログラムを終了する方法はいくつかあります。

exit(): プログラムを終了し、オペレーティングシステムに制御を戻すには、<cstdlib>(C の「stdlib.h」から移植)にある関数 exit(int exitCode) を呼び出すことができます。慣例として、戻り値がゼロは正常終了を示し、非ゼロの exitCode(-1)は異常終了を示します。たとえば、

abort(): ヘッダ <cstdlib> には、プログラムを異常に終了させるために使用できる abort() と呼ばれる関数もあります。

if (errorCount > 10) {
   cout << "エラーが多すぎます" << endl;
   exit(-1);  // プログラムを終了する
              // または abort();
}

ネストされたループ

次の図は、ネストされた for ループ、つまり外側の for ループの中に内側の for ループがあることを示しています。

画像の説明
/*
 * 三角形のパターンを表示します。
 */
#include <iostream>
using namespace std;

int main() {
   int size = 8;
   for (int row = 1; row <= size; ++row) {     // すべての行を表示するための外側のループ
      for (int col = 1; col <= size-row+1; ++col) {  // 各行のすべての列を表示するための内側のループ
         cout << "## ";
      }
      cout << endl;   // 1 行が終了したので、カーソルを次の行に移動させます
   }

   return 0;
}

出力:

## ## ## ## ## ## ## #
## ## ## ## ## ## #
## ## ## ## ## #
## ## ## ## #
## ## ## #
## ## #
## #
#
画像の説明

次の構文が一般的に使用されます。

while (true) { ...... }

これは無限ループのように見えますが、通常はループ本体の中で break または return 文によって終了します。この種のコードは読みにくいので、可能な限り条件を書き換えることで避けましょう。

まとめ

このセクションでは、3 つの制御構造を紹介しました。これらは非常に便利です。これらを組み合わせることができます。ループには注意してください。無限ループにならないように、終端条件を確認してください。