• Nenhum resultado encontrado

Dica de Produtividade 2

Sintaxe 2.7: Definição de Constante

const type_name constant_name = initial_value; Exemplo:

const double LITER_PER_OZ = 0.029586; Finalidade:

Define uma nova constante de um tipo particular e fornece seu valor.

Tabela 1

Conversão entre unidades métricas e não-métricas

Não-Métrica Métrica

1 onça líquida (fl. oz). 29,586 mililitro (ml) 1 galão 3,785 litro (l) 1 onça (oz) 28,3495 gramas (g)

1 libra (lb) 453,6 gramas 1 polegada 2,54 centímetros (cm)

1 pé 30,5 centímetros

Arquivo volume.cpp 1 #include <iostream> 2 3 using namespace std; 4 5 int main() 6 { 7 double bottles; 8

9 cout << "Quantas garrafas você tem? ";

10 cin >> bottles;

11

12 double cans;

13 cout << "Quantas latas você tem? ";

14 cin >> cans;

15

16 const double BOTTLE_VOLUME= 2.0;

17 const double CAN_VOLUME= 0.355;

18 double total = bottles * BOTTLE_VOLUME

19 + Cans * CAN_VOLUME;

20

21 cout << "O volume total é " << total << " litros.";

22

23 return 0;

24 }

Agora CAN_VOLUME é uma entidade com nome. Diferente de total, ela é constante. Após a inicialização com 0.355, ela nunca muda.

De fato, você pode fazer ainda melhor e explicar de onde provém o valor do volume da lata. const double LITRO_POR_ONCA = 0.029586;

const double VOLUME_LATA= 12 * LITRO_POR_ONCA; /* latas de 12 onças */

Certo, é mais trabalhoso dar tipo às definições de constantes e usar os nomes constantes nas fórmulas. Mas isto torna o código mais legível. Também torna o código mais fácil de alterar. Supo- nha que o programa faça computações envolvendo volumes em muitos lugares diferentes. E supo- nha que você precisa mudar de garrafas de 2 litros para garrafas de meio galão. Se você simples- mente multiplicou por 2 para obter o volume das garrafas, agora você deve substituir o 2 por 1.893... bem, nem todos os números 2. Pode haver outros usos de 2 no programa que nada tem a ver com garrafas. Você terá que examinar cada número 2 e ver se você precisa mudá-lo. Eu men- cionei aquela fórmula que multiplicava um contador de embalagens por 36 porque existiam 18 gar- rafas em cada embalagem? Este número agora precisa ser alterado para 18 ⋅ 1.893 – felizmente fo- mos sortudos de encontrá-la. Se, por outro lado, a constante BOTTLE_VOLUME for criteriosamen- te usada ao longo do programa, ela necessita ser atualizada em somente um lugar. Constantes iden- tificadas são muito importantes na manutenção de programas. Veja a Dica de Qualidade 2.3 para mais informações.

Constantes são comumente escritas em letras maiúsculas para distinguí-las visualmente de va- riáveis.

Dica de Qualidade

2.3

Não Use Números Mágicos

Um número mágico é uma constante numérica que aparece em seu código sem explicação. Por exemplo,

Por que 66? Talvez este programa imprima em uma fonte de 12 pontos em um papel de 8.5 × 11 polegadas com uma margem de 1 polegada em ambos os lados? Sendo assim, você pode colo- car 65 caracteres em uma linha. Assim que atingir a coluna 66, você ultrapassa a margem direita e deve fazer algo especial. Entretanto, estas são premissas bastante frágeis. Para fazer um programa funcionar com um tamanho diferente de papel, deve-se localizar todos os valores de 65 (e 66 e 64) e substituí-los, cuidando para não tocar aqueles 65s (e 66s e 64s) que nada têm a ver com o tama- nho do papel. Em um programa que possui mais do que poucas páginas de tamanho, isto é incri- velmente tedioso e sujeito a erros.

A solução é usar uma constante identificada const int MARGEM_DIREITA = 65;

if (col > MARGEM_DIREITA)...

Mesmo a mais razoável constante cósmica vai se alterar algum dia. Você pensa que existem 365 dias por ano? Seus clientes em Marte vão ficar bastante descontentes com a sua tola presunção. Crie uma constante

const int DIAS_POR_ANO = 365;

A propósito, a definição

const int TREZENTOS_E_SESSENTA_E_CINCO = 365;

é contraproducente e desaconselhada.

Você nunca deve usar números mágicos em seu código. Qualquer número, com as possíveis ex- ceções de 0, 1 e 2 devem ser declarados como constantes identificadas.

Tópico Avançado

2.5

Tipos Enumerados

Algumas vezes uma variável assume valores de um conjunto finito de possibilidades. Por exemplo, uma variável que descreve um dia da semana (segunda, terça, ... , domingo) pode ter apenas um dentre sete estados. Em C++, podemos definir tais tipos enumerados:

enum Dia_da_semana { SEGUNDA, TERCA, QUARTA, QUINTA, SEXTA, SABADO, DOMINGO };

Isso torna Dia_da_semana um tipo, similar a int. Assim como qualquer tipo, podemos de- clarar variáveis deste tipo.

Dia_da_semana dia_da_entrega = QUARTA; /* trabalho deve ser entregue na quarta */

Naturalmente, você poderia ter declarado dia_da_entrega como um inteiro. Então você precisaria codificar em números os dias da semana

int dia_da_entrega = 2;

Isto viola nossa regra contra “números mágicos”. Você pode ir em frente e definir constantes const int SEGUNDA = 0;

const int TERCA = 1; const int QUARTA = 2; const int QUINTA = 3; const int SEXTA = 4; const int SABADO = 5; const int DOMINGO = 6;

Entretanto, o tipo enumerado Dia_da_semana é mais claro, e é conveniente você não pre- cisar associar com valores inteiros. Ele também permite ao compilador detectar erros durante a compilação. Por exemplo, o seguinte provoca um erro de compilação:

Dia_da_semana dia_da_entrega = 10; /* erro de compilação */

Em contraste, o seguinte comando irá compilar sem reclamações e criar um problema lógico quando o programa for executado.

int dia_da_entrega = 10; /* erro lógico */

É uma boa idéia usar um tipo enumerado sempre que uma variável pode ter um conjunto finito de valores.

2.5

Aritmética

Você já viu como somar e multiplicar números e valores armazenados em variáveis: double t = p + d * 0.10 + q * 0.25;

Todas as quatro operações aritméticas básicas – adição, subtração, multiplicação e divisão – são suportadas. Você deve escrever a * b para indicar multiplicação, e não ab ou a ⋅ b.

A divisão é indicada por uma / e não um traço de fração. Por exemplo,

se torna

(a + b) / 2

Parênteses são usados tal como na álgebra: para indicar em que ordem as sub-expressões de- vem ser calculadas. Por exemplo, na expressão(a + b) / 2, a soma a + b é calculada pri- meiro e então a soma é dividida por 2. Em contraste, na expressão

a + b / 2

somente b édividido por 2 e após a soma de a e b / 2 é avaliada. Assim como na notação al- gébrica regular, a multiplicação e a divisão associam-se mais fortemente do que a adição e a sub- tração. Por exemplo, na expressão a + b / 2, a / é avaliada primeiro, mesmo que a operação + ocorra mais à esquerda.

A divisão funciona como você espera, desde que pelo menos um dos números envolvidos seja um número em ponto flutuante. Isto é,

7.0 / 4.0 7 / 4.0 7.0 / 4

todas resultam em 1,75. Entretanto, se ambos os números são inteiros, então o resultado da divisão é sempre um inteiro, com o resto descartado. Isto é,

7 / 4

resulta em 1 por que 7 dividido por 4 é 1 com um resto de 3 (o qual é descartado). Isso pode ser uma fonte de erros sutis de programação – veja o Erro Freqüente 2.2.

Se você está interessado somente no resto, use o operador %: 7 % 4

é 3, o resto da divisão inteira de 7 por 4. O operador %deve ser aplicado somente a inteiros e não a valores em ponto flutuante. Por exemplo, 7.0 % 4é um erro. O símbolo % não possui análogo em álgebra. Ele foi escolhido por que parece similar a / e a operação resto é relacionada à divisão.

a + b 2

Aqui está um uso típico para as operações inteiras /e %. Suponha que nós queremos saber o valor das moedas em uma carteira, em dólares e centavos. Podemos calcular o valor como um inteiro, in- dicando os centavos, e então calcular a quantidade em dólares e o troco restante:

Arquivo coins4.cpp 1 #include <iostream> 2 3 using namespace std; 4 5 int main() 6 {

7 cout << "Quantas moedas de 1 centavo (pennies) você tem? ";

8 int pennies;

9 cin >> pennies;

10

11 cout << "Quantas moedas de 5 centavos (nickels) você tem? ";

12 int nickels;

13 cin >> nickels;

14

15 cout << "Quantas moedas de 10 centavos (dimes) você tem? ";

16 int dimes;

17 cin >> dimes;

18

19 cout << "Quantas moedas de 25 centavos (quarters) você tem? ";

20 int quarters;

21 cin >> quarters;

22

23 int valor = pennies + 5 * nickels + 10 * dimes

24 + 25 * quarters;

25 int dollar = valor / 100;

26 int cents = valor % 100;

27

28 cout << "Valor total = " << dollar << " dólares e "

29 << cents << " centavos.";

30

31 return 0;

32 }

Por exemplo, se valoré 243, então o comando de saída irá exibir Valor total = 2 dólares e 43 centavos.

Para calcular a raiz quadrada de um número, você usa a função sqrt(ver Sintaxe 2.8). Por exemplo, é escrita como sqrt(x). Para calcular xn, você escreve pow(x, n). Entretanto, para calcular x2, é muito mais eficiente simplesmente escrever x * x. Para usar sqrte pow, vo- cê deve colocar a linha #include <cmath> no início de seu arquivo de programa. O arquivo de cabeçalho cmathé um cabeçalho padrão em C++ que está disponível em todos os sistemas C++, assim como iostream.

Como você pode ver, o efeito das operações /, sqrte pow é linearizar termos matemáticos. Em álgebra, você usa frações, expoentes e raízes para formar expressões em uma forma compacta bidimensional. Em C++, você tem que escrever todas as expressões em uma forma linear. Por exemplo, a sub-expressão

da fórmula de Báscara se torna

(-b + sqrt(b * b – 4 * a * c)) / (2 * a) − +b bac a 2 4 2 x

A Figura 7 mostra como analisar uma expressão assim. Com expressões complicadas como es- tas, nem sempre é fácil manter os parênteses balanceados – veja o Erro Freqüente 2.3.

A Tabela 2 mostra mais algumas funções que são declaradas no cabeçalho cmath. Entradas e saídas são números em ponto flutuante.

Erro Freqüente

2.2

Divisão Inteira

É lamentável que C++ use o mesmo símbolo, precisamente /, para a divisão inteira e em ponto flu- tuante. Estas são operações realmente distintas. É um erro comum usar a divisão inteira por aciden- te. Considere este segmento de programa que calcula a média de três inteiros.

cout << "Por favor digite suas últimas três notas de provas: "; int s1;

int s2; int s3;

cin >> s1 >> s2 >> s3;

double average = (s1 + s2 + s3) / 3; /* Erro */ cout << "Sua média é " << average << "\n";

O que poderia estar errado com isto? Naturalmente, a média de s1, s2e s3 é s1−s2−s3

3