Controle de Fluxo em C++

C++Beginner
Pratique Agora

Introdução

Neste laboratório, você aprenderá as instruções de controle de fluxo em C++. Você aprenderá como usar as instruções if-else, switch, loops while, loops do-while e loops for.

Pré-visualização do Conteúdo

Existem três construções básicas de controle de fluxo - sequencial, condicional (ou decisão) e loop (ou iteração). A estrutura sequencial: o processo de execução é de cima para baixo, linha por linha. A estrutura condicional usa a instrução if-else para verificar se uma instrução satisfaz alguma condição específica e, em seguida, faz uma escolha. A estrutura de loop é usada para executar alguma operação lógica repetidamente.

image desc

Controle de Fluxo Sequencial

Um programa é uma sequência de instruções. O fluxo sequencial é o mais comum e direto, onde as instruções de programação são executadas na ordem em que são escritas - de cima para baixo, de forma sequencial.

Controle de Fluxo Condicional

Existem alguns tipos de condicionais, if-then, if-then-else, nested-if (if-elseif-elseif-...-else), switch-case e expressão condicional.

#include <iostream>
using namespace std;

int main(){

 int mark;

 cout<<"Input a number [0-100]: ";
 cin>>mark;
    // if
    if (mark >= 50) {
       cout << "Congratulation!" << endl;
       cout << "Keep it up!" << endl;
    }

    cout<<"Input a number [0-100]: ";
 cin>>mark;
    // if-else
    if (mark >= 50) {
       cout << "Congratulation!" << endl;
       cout << "Keep it up!" << endl;
    } else {
       cout << "Try Harder!" << endl;
    }

 cout<<"Input a number [0-100]: ";
 cin>>mark;
    // nested-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<<"Input a char [+ - / *]: ";
    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 << "Unknown operator" << endl;
    }
    cout<<num1<<oper<<num2<<"="<<result;
    return 0;
}

Saída:

Input a number [0-100]: 50
Congratulation!
Keep it up!
Input a number [0-100]: 40
Try Harder!
Input a number [0-100]: 85
A
Input a char [+ - / *]: +
1+2=3
image desc

Operador Condicional: Um operador condicional é um operador ternário (3 operandos), na forma de booleanExpr ? trueExpr : falseExpr. Dependendo da booleanExpr, ele avalia e retorna o valor de trueExpr ou falseExpr.

// return either "PASS" or "FAIL", and put to cout
cout << (mark >= 50) ? "PASS" : "FAIL" << endl;

max = (a > b) ? a : b;   // RHS returns a or b
abs = (a > 0) ? a : -a;  // RHS returns a or -a

Chaves: Você pode omitir as chaves { }, se houver apenas uma instrução dentro do bloco. Por exemplo,

if (mark >= 50)
   cout << "PASS" << endl;   // Only one statement, can omit { } but not recommended
else {                       // more than one statements, need { }
   cout << "FAIL" << endl;
   cout << "Try Harder!" << endl;
}

No entanto, recomendamos que você mantenha as chaves, mesmo que haja apenas uma instrução no bloco, para melhorar a legibilidade do seu programa.

Controle de Fluxo de Loop

Novamente, existem alguns tipos de loops: for-loop, while-do e do-while.

// for-loop
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);

Solicite ao usuário um limite superior. Some os inteiros de 1 até um limite superior fornecido e calcule sua média.

/*
 * Sum from 1 to a given upperbound and compute their average.
 */
#include <iostream>
using namespace std;

int main() {
   int sum = 0;     // Store the accumulated sum
   int upperbound;
   cout << "Enter the upperbound: ";
   cin >> upperbound;

   // Sum from 1 to the upperbound
   for (int number = 1; number <= upperbound; ++number) {
      sum += number;
   }
   cout << "Sum is " << sum << endl;
   cout << "Average is " << (double)sum / upperbound << endl;

   // Sum only the odd numbers
   int count = 0;     // counts of odd numbers
   sum = 0;           // reset sum
   for (int number=1; number <= upperbound; number=number+2) {
      ++count;
      sum += number;
   }
   cout << "Sum of odd numbers is " << sum << endl;
   cout << "Average is " << (double)sum / count << endl;
}

Saída:

Enter the upperbound: 15
Sum is 120
Average is 8
Sum of odd numbers is 64
Average is 8
image desc

Interrompendo o Fluxo do Loop - 'break' e 'continue'

A instrução break interrompe e sai do loop atual (mais interno).

A instrução continue aborta a iteração atual e continua para a próxima iteração do loop atual (mais interno).

break e continue são estruturas ruins, pois são difíceis de ler e difíceis de seguir. Use-as apenas se absolutamente necessário. Você sempre pode escrever o mesmo programa sem usar break e continue.

O programa a seguir lista os números não primos entre 2 e um limite superior.

/*
 *  List non-prime from 1 to an upperbound.
 */
#include <iostream>
#include <cmath>
using namespace std;

int main() {
   int upperbound;
   cout << "Enter the upperbound: ";
   cin >> upperbound;
   for (int number = 2; number <= upperbound; ++number) {
      // Not a prime, if there is a factor between 2 and sqrt(number)
      int maxFactor = (int)sqrt(number);
      for (int factor = 2; factor <= maxFactor; ++factor) {
         if (number % factor == 0) {   // Factor?
            cout << number << " ";
            break;   // A factor found, no need to search for more factors
         }
      }
   }
   cout << endl;
   return 0;
}

Saída:

Enter the upperbound: 20
4 6 8 9 10 12 14 15 16 18 20
image desc

Vamos reescrever o programa acima para listar todos os primos em vez disso. Uma flag boolean chamada isPrime é usada para indicar se o number atual é um primo. Ele é então usado para controlar a impressão.

/*
 *  List primes from 1 to an upperbound.
 */
#include <iostream>
#include <cmath>
using namespace std;

int main() {
   int upperbound;
   cout << "Enter the upperbound: ";
   cin >> upperbound;
   for (int number = 2; number <= upperbound; ++number) {
      // Not a prime, if there is a factor between 2 and sqrt(number)
      int maxFactor = (int)sqrt(number);
      bool isPrime = true;  // boolean flag to indicate whether number is a prime
      for (int factor = 2; factor <= maxFactor; ++factor) {
         if (number % factor == 0) {   // Factor?
            isPrime = false;   // number is not a prime
            break;   // A factor found, no need to search for more factors
         }
      }
      if (isPrime) cout << number << " ";
   }
   cout << endl;
   return 0;
}

Saída:

Enter the upperbound: 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
image desc

Estude o seguinte programa usando break e continue.

/* A mystery series */
#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;
}

Saída:

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
image desc

Encerrando o Programa

Existem algumas maneiras de terminar seu programa, antes de chegar ao final das instruções de programação.

exit(): Você pode invocar a função exit(int exitCode), em <cstdlib> (portada do "stdlib.h" de C), para terminar o programa e retornar o controle ao Sistema Operacional. Por convenção, o código de retorno zero indica terminação normal; enquanto um exitCode diferente de zero (-1) indica terminação anormal. Por exemplo,

abort(): O cabeçalho <cstdlib> também fornece uma função chamada abort(), que pode ser usada para terminar o programa anormalmente.

if (errorCount > 10) {
   cout << "too many errors" << endl;
   exit(-1);  // Terminate the program
              // OR abort();
}

Loops Aninhados

O diagrama a seguir ilustra um loop for aninhado, ou seja, um loop for interno dentro de um loop for externo.

image desc
/*
 *  Print triangle pattern.
 */
#include <iostream>
using namespace std;

int main() {
   int size = 8;
   for (int row = 1; row <= size; ++row) {     // Outer loop to print all the rows
      for (int col = 1; col <= size-row+1; ++col) {  // Inner loop to print all the columns of each row
         cout << "## ";
      }
      cout << endl;   // A row ended, bring the cursor to the next line
   }

   return 0;
}

Saída:

## ## ## ## ## ## ## #
## ## ## ## ## ## #
## ## ## ## ## #
## ## ## ## #
## ## ## #
## ## #
## #
#
image desc

A seguinte construção é comumente usada:

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

Parece ser um loop sem fim (ou loop infinito), mas geralmente é terminado por meio de uma instrução break ou return dentro do corpo do loop. Esse tipo de código é difícil de ler - evite-o, se possível, reescrevendo a condição.

Resumo

Nesta seção, introduzimos três estruturas de controle. Elas são muito úteis. Você pode combiná-las. Tenha cuidado com o loop, verifique a condição de término, em caso de loop infinito.