Você está na página 1de 52

2.

Dados: Representação e Utilização


• A solução de um problema pode envolver vários tipos de
dados. O caso mais comum são os dados numéricos:
• Números inteiros (2, 3, -7, por exemplo).
• Números com parte inteira e parte fracionária (1.234 e
-7.89, por exemplo).
• Nas linguagens de programação, dá-se o nome de número
de ponto flutuante aos números com parte inteira e parte
fracionária. Notar que o símbolo que separa a parte inteira
da parte fracionária é um ponto (.) e não uma vírgula (,).
• Da mesma forma que instruções, os dados de um
programa devem ser representados em notação binária.
• Cada tipo de dado é representado na memória do
computador de uma forma diferente.
© ELFS 37
Conversão de Números
1. De decimal para binário
• Seja, por exemplo, x = 23.625
• Passo 1 (Conversão da parte inteira): Divide-se
sucessivamente a parte inteira de x por 2, até que o
quociente seja igual a 1.

23 2
Pegar os bits (0 ou 1)
1 11 2 desde o último
1 5 2 quociente (1) até o
1 2 2 primeiro resto.
0 1

Portanto: (23)10 = (10111)2


© ELFS 38
• Passo 2 (Conversão da parte fracionária):
• Multiplica-se a parte fracionária de x por 2. Desse
resultado, toma-se a parte inteira (que, certamente, será
0 ou 1) como sendo o primeiro dígito na base binária.
• Repete-se este processo, considerando sempre a parte
fracionária resultante do passo anterior.
• Quando parar? Quando a parte fracionária for igual a zero
ou até que se observe o aparecimento de uma dízima
periódica.
0.625 0.250 0.500
Portanto:
x2 x2 x2
(0.625)10 = (0.101)2
1.250 0.500 1.000

Portanto: (23.625)10 = (10111.101)2


© ELFS 39
Atenção

• Um número decimal finito pode ter uma representação


binária infinita!
• Exemplo: x = 0.6

0.6 0.2 0.4 0.8 0.6


x2 x2 x2 x2 x2 ...
1.2 0.4 0.8 1.6 1.2

Portanto: (0.6)10 = (0.10011001...)2

• Como a memória do computador é finita, em algum


momento deve-se limitar essa representação. Isso leva a
um tipo de erro nos cálculos (erro de arredondamento).
© ELFS 40
Conversão de Números

2. De binário para decimal

• Basta expressar o número como uma soma de potências


de 2 e realizar as operações aritméticas da expressão.
• Exemplo: w = 1011.110
w = 1x23 + 0x22 + 1x21 + 1x20 + 1x2-1 + 1x2-2 + 0x2-3
Logo: w = 8 + 0 + 2 + 1 + 0.5 + 0.25 + 0 = (11.75)10

• Já sabemos que no computador tudo (instruções,


números, ...) deve ser representado em binário.
• Para escrever um número (mesmo binário) negativo, por
exemplo, usamos "-" e "." como em: -1011.110
• Mas, no computador, não existem esses símbolos "-" e "."
© ELFS 41
Representação de Números Inteiros
• Existem várias maneiras de representar números inteiros
no sistema binário.
• A forma mais simples é a sinal-magnitude: o bit mais
significativo corresponde ao sinal (0 é "+" e 1 é "-") e os
demais correspondem ao valor absoluto do número.
Exemplo: considere uma representação usando cinco bits.

Decimal Binário Desvantagens:


- Duas representações para o zero (+0 e -0).
+5 00101 - A representação dificulta os cálculos.

-3 10011 00101
10011
Soma 11000 Que número é esse?
5 – 3 = – 8 ???

© ELFS 42
Representação de Números Inteiros
• Outra representação, normalmente usada pelos
computadores, é a complemento-de-2. Para números
positivos, a representação é idêntica à da forma
sinal-magnitude. Para os números negativos, a
representação se dá em dois passos:
• Inverter os bits da representação do número positivo;
• Somar 1 ao resultado.
Exemplo:
Decimal Binário 00101 Notar que o último "vai
11101 um" não é usado, pois a
+5 00101 Soma 00010 representação usa apenas
+3 00011 5 bits.
−3 11100
1 Notar que esse número
11101 corresponde a +2!

© ELFS 43
Representação de Números Inteiros
• Na representação complemento-de-2, o que acontece com
o zero?
Decimal Binário
+0 00000 De novo, o último "vai um"
−0 11111 não é usado, pois a
1 representação usa apenas
00000 5 bits.

• Portanto, a representação complemento-de-2 resolve os


problemas de dupla representação para o zero e facilita os
cálculos!
• Na representação complemento-de-2, qual é o maior
número representável usando 5 bits?
E usando 10 bits?

© ELFS 44
• Observar que na representação complemento-de-2 existe
sempre um valor negativo a mais.
• Por exemplo, com n = 4 bits:
0000 0001 0010 0011 0100 0101 0110 0111
0 +1 +2 +3 +4 +5 +6 +7
1000 1001 1010 1011 1100 1101 1110 1111
-8 -7 -6 -5 -4 -3 -2 -1

• Portanto: o maior valor é 2n-1 - 1 e o menor valor é -2n-1.


• Na linguagem C, o tipo int usa 32 bits na representação.
O maior valor do tipo int será:
01111111111111111111111111111111 = 231 - 1 = 2147483647
e o menor será:
10000000000000000000000000000000 = -231 = -2147483648

• Logo: um valor int deve estar em [-2147483648, 2147483647]


© ELFS 45
• Exercício. Considere o seguinte programa:
#include <stdio.h>
#include <stdlib.h>
#include <math.h>
int main()
{
int x;

x = pow(2,31)-1;
printf("x = %d\n",x); Esse primeiro printf vai mostrar o que?
x = x + 1;
printf("x = %d\n",x); E esse outro printf vai mostrar o que?
return 0;
}

• A variável x armazena o maior valor possível. O que


acontece se o valor de x for incrementado de 1?
• Ocorre um overflow!
• Quando ocorre um overflow, o valor armazenado na
variável torna-se um "lixo".
© ELFS 46
• A linguagem C define modificadores para o tipo int.
Alguns deles são: short, long, unsigned.
• Um modificador de tipo altera o tamanho da
representação do número, ou seja, altera o intervalo de
valores que uma variável pode armazenar.
• Uma variável short int (16 bits) armazena valores de -215
a 215 - 1, ou seja de [-32768, 32767].
• Uma variável long int (64 bits) armazena valores de -263
a 263 - 1.
• O modificador de tipo unsigned instrui o compilador a
não considerar o primeiro bit como sinal, ou seja, todos
os bits são usados para a magnitude do valor (positivo).
• Uma variável unsigned int (32 bits) armazena valores de
0 a 232 - 1, ou seja de [0, 4294967297].

© ELFS 47
Representação de Números de Ponto Flutuante
• Números de ponto flutuante são os números reais que
podem ser representados no computador.
• Nem todos os números reais podem ser representados no
computador. Por que?
• A representação de números de ponto flutuante segue
padrões internacionais (IEEE-754 e IEC-559).
• A representação de ponto flutuante tem três partes: o
sinal, a mantissa e o expoente.
• Exemplo: x = 567.89 = 5.6789 x 102
• No caso de computadores (representação binária), a
mantissa é representada na forma normalizada, ou seja,
na forma 1.f, onde f corresponde aos demais bits.
• Ou seja, o primeiro bit da mantissa é sempre 1.

© ELFS 48
Representação de Números de Ponto Flutuante
• Exemplos:
Decimal Binário Binário normalizado
Expoente
+13.25 1101.01 1.10101 x 23
Mantissa

Decimal Binário Binário normalizado


Expoente
+0.25 0.01 1.0 x 2-2
Mantissa

• Portanto, a representação no computador utiliza: 1 bit


para o sinal, n bits para o expoente e m bits para a
mantissa (o primeiro bit não precisa ser representado).
© ELFS 49
Representação de Números de Ponto Flutuante
• Dois formatos para números de ponto flutuante:
• SP (precisão simples): n = 8, m = 23 (total: 32 bits)
• DP (precisão dupla): n = 11, m = 52 (total: 64 bits)
• Em precisão simples, o expoente é representado na
notação excesso-de-127: soma-se 127 ao valor do
expoente e transforma-se em binário. Por que?
• Porque é mais simples pensar apenas em valores
positivos. Como são 8 bits para o expoente, podem ser
representados 28 = 256 valores. Como existem expoentes
negativos e positivos, os valores a serem representados
vão de -127 a +128. Portanto, somando-se 127, os
valores representados vão de 0 a 255.
• Pela mesma razão, em precisão dupla o expoente é
representado na notação excesso-de-1023.
© ELFS 50
Representação de Números de Ponto Flutuante

• x = 1.10101 x 23
• mantissa = 10101
• expoente = 3 + 127 = (130)10 = (10000010)2

Ponto flutuante Representação SP

1.10101 x 23 0 10000010 10101000000000000000000


01000001010101000000000000000000

Ponto flutuante Representação SP

-1.0 x 2-2 1 01111101 00000000000000000000000

10111110100000000000000000000000

© ELFS 51
Uma questão importante:

• O computador só consegue realizar as operações


aritméticas entre operandos do mesmo tipo.
• Por que?
• Porque as representações de int e float na memória do
computador são diferentes.
• Exemplo: 01000010010100000000000000000000
• Que número é esse?
• Depende! É a representação de um int ou de um float?
• int: 230 + 225 + 222 + 220 = (1112539136)10
• float: 1.101 x 25 = (52.0)10

© ELFS 52
Representação de Dados Não-Numéricos

• Strings: sequências de caracteres delimitadas por aspas.


• Existem também padrões internacionais para a codificação
de caracteres (ASCII, ANSI, Unicode).
• A linguagem C adota o padrão ASCII (American Standard
Code for Information Interchange).
• Cada caractere é representado por 1 byte, ou seja,
uma sequência de 8 bits.

Caractere Decimal ASCII


'@' 64 01000000
'A' 65 01000001
'a' 97 01100001

• Quantos caracteres podem ser representados?


© ELFS 53
Variáveis
• Os dados que um programa utiliza precisam ser
armazenados na memória do computador. Cada posição
de memória do computador possui um endereço.
• Considere uma parte da memória de um computador
(cada célula cinza de memória corresponde a 1 byte = 8
bits) e os seguintes dados: x = 12.5 (ponto flutuante SP),
k = 81 (inteiro) e s = "FEG" (string).

FEG
0 1 2 3 4 5 6 7 8 9 10 11 12 13 14

12.5
15 16 17 18 19 20 21 22 23 24 25 26 27 28 29

81
30 31 32 33 34 35 36 37 38 39 40 41 42 43 44

• Uma variável corresponde ao nome simbólico de uma


posição de memória.
© ELFS 54
Variáveis

FEG
0 1 2 3 4 5 6 7 8 9 10 11 12 13 14

12.5
15 16 17 18 19 20 21 22 23 24 25 26 27 28 29

81
30 31 32 33 34 35 36 37 38 39 40 41 42 43 44

• Nesta representação, s representa um conjunto de 3


posições de memória (3 bytes) que começa no endereço 7,
ou seja, &s (endereço de s) = 7.
• Da mesma forma: &x = 16 e o valor de x ocupa 4 bytes a
partir do endereço 16; &k = 39 e o valor de k ocupa 4
bytes a partir do endereço 39.
• Assim, para saber qual é o valor armazenado na memória
do computador é preciso saber o endereço e o tamanho
(bytes). Variável significa esse par de informações.
© ELFS 55
Variáveis

• Com variáveis, podemos nos abstrair dos endereços físicos


onde estão armazenados os dados e imaginar a memória
apenas como um conjunto de posições (bytes).

FEG

12.5

81

float x = 12.5; int k = 81; char[] s = "FEG"

• O conteúdo das posições de memória ocupadas por uma


variável pode se alterar durante a execução do programa.
Por isso, usa-se o termo "variável".
© ELFS 56
Variáveis

• Resumindo:

• Cada variável está associado um tipo específico de


dado.

Tamanho
Tipo Valor
(bytes)
char 1 Um caractere.
int 4 Um número inteiro.
float 4 Um número de ponto flutuante (SP).
double 8 Um número de ponto flutuante (DP).

• Cada variável ocupa uma quantidade diferente de bytes,


uma vez que os tipos de dados são representados de
forma diferente na memória do computador.
© ELFS 57
Avaliação de Expressões Aritméticas
• Operadores aritméticos disponíveis na linguagem C:

Operador Operação
+ soma
- subtração
* multiplicação
/ divisão
% resto da divisão

• Na avaliação de expressões aritméticas, as operações


são realizadas sempre entre operandos de mesmo tipo.
• O resultado terá o mesmo tipo dos operandos.
• Caso haja valores inteiros e de ponto flutuante em uma
expressão, haverá uma conversão implícita de int para
float, sempre que necessário.
© ELFS 58
Prioridade de Execução das Operações:
1) expressões entre parênteses.
2) multiplicação, divisão e resto da divisão.
3) soma e subtração.
• As operações são realizadas da esquerda para a direita.
• Exemplo: v = (a*(c+d))/(b*(e+f));
• Seja: a = 1.5, b = 4, c = 2, d = 3, e = 1.2, f = 4.3
Ordem Operação Resultado Conversão de tipo
1a (c + d) (2 + 3) = 5 Não
2a (e + f) (1.2 + 4.3) = 5.5 Não
3a (a * 1a) (1.5 * 5) = 7.5 Sim (5 para 5.0)
4a (b * 2a) (4 * 5.5) = 22.0 Sim (4 para 4.0)
5a 3ª / 4ª 7.5 / 22.0 = 0.341 Não
6a v = 5ª v = 0.341 Não
© ELFS 59
Muito cuidado com a divisão inteira:
• É preciso ter muito cuidado com a divisão entre
operandos inteiros (divisão euclidiana).
• O resultado da divisão euclidiana é sempre um número
inteiro. Assim, se necessário, pode-se usar uma
conversão explícita de tipo (type casting).
• Exemplo:
int a = 10, b = 3;
int c;
float d;
c = a / b;
d = (float)a / b;

• Quais serão os valores de c e d?

© ELFS 60
Atenção!
int a = 10, b = 3;

• Observe que os resultados de:


(1) d = (float)a / b;

(2) d = (float)(a / b);

são totalmente diferentes!


• Em (1), realiza-se primeiro a conversão explícita de tipo
de a (a torna-se 10.0) e, em seguida, realiza-se a divisão
por b (b = 3).
Logo: d = 3.333333
• Em (2), primeiro divide-se a por b (10 / 3 = 3) e, em
seguida, faz-se a conversão explícita de tipo.
Logo: d = 3.0
© ELFS 61
Formatação de valores numéricos
• A formatação, por meio de tags (%d para valores inteiros
e %f para valores de ponto flutuante) pode ser usada
para exibir um valor numérico (em um printf).
• Um tag %d pode especificar o número total de
caracteres (incluindo o sinal).
• Um tag %f pode especificar o número total de caracteres
(incluindo o sinal e o ponto decimal) e o número de
casas decimais.
• Será acrescentado o caractere ' ' (espaço) à esquerda do
valor para completar o tamanho total, se necessário.
• Pode-se também completar o tamanho total com 0
(zero). %08.3f significa: exibir um valor de ponto
flutuante com oito caracteres no total e com três casas
decimais. Completar o tamanho com zeros à esquerda.
© ELFS 62
Formatação de valores numéricos

Valor Tag Valor exibido


%d 5 6 7
x = 567 %5d 5 6 7
%05d 0 0 5 6 7
%5.3f 3 . 1 4 2
pi = 3.14159 %8.3f 3 . 1 4 2
%08.3f 0 0 0 3 . 1 4 2
%5.3f 2 . 0 0 3
raio = 2.0031
%.6f 2 . 0 0 3 1 0 0
%5.3f 1 2 . 5 8 6
%6.3f 1 2 . 5 8 6
%7.3f 1 2 . 5 8 6
circ = 12.5858379
%e 1 . 2 5 8 5 8 3 7 9 e + 0 0 1
%E 1 . 2 5 8 5 8 3 7 9 E + 0 0 1
%12.3E 1 . 2 5 9 E + 0 0 1

© ELFS 63
Endereços de variáveis
• Uma variável representa um nome simbólico para uma
posição de memória.
• Cada posição de memória de um computador possui um
endereço. Logo, o endereço de uma variável é o
endereço da posição de memória representada pela
variável.
int x = 3;
printf("Valor = %d - Endereco = %p",x,&x);

Valor = 3 - Endereco = 0022FF74

Endereço no sistema hexadecimal.

(22FF74)16 = 2x165+2x164+Fx163+Fx162+7x161+4x160 = (2293620)10


© ELFS 64
Endereços de variáveis
• Note que o endereço de uma variável é um valor. Logo,
uma variável pode armazenar um endereço.
• Uma variável que armazena um endereço de memória é
conhecida como ponteiro (ou variável de referência).
• Daí porque o tag usado para exibir endereços de
memória ser %p.
• Exemplo: Suponha que y armazene o endereço
0022FF74 da posição de memória representada pela
variável x, que armazena o valor inteiro 3.

y 0022FF74 3 x
0022FF70 0022FF74
• Diz-se: y é um ponteiro para x ou y aponta para x.
© ELFS 65
Nível mais alto de abstração:

y 3 x

• Diz-se: y aponta para x (um valor int)


• Qual é o tipo da variável y?
• Para declarar um ponteiro é preciso saber para qual tipo
de valor este ponteiro irá apontar.
• Neste caso, o ponteiro aponta para um valor inteiro.
Então o tipo de y é int *.
• Portanto, a declaração da variável y será: int * y;
• Por que endereços são mostrados Indica que y é um ponteiro
como valores hexadecimais? (para int, no caso)

© ELFS 66
Sistema Hexadecimal
• O sistema hexadecimal (base 16) é o mais usado para
representar endereços de memória.
• Usado porque é compacto: consegue representar 1 byte
com apenas 2 dígitos! Ou seja, Hexa Decimal Binário
cada 4 bits são representados por 0 0 0000
1 1 0001
um único algarismo hexadecimal. 2 2 0010

• São utilizados 16 algarismos: 3


4
3
4
0011
0100
0,1,2,3,4,5,6,7,8,9,A,B,C,D,E,F. 5 5 0101
6 6 0110
• A tabela pode ser usada para 7 7 0111
conversões entre as bases 16 e 2: 8 8 1000
cada dígito hexa corresponde a 4 9 9 1001
A 10 1010
dígitos binários (e vice-versa). B 11 1011
(1267)16 = (0001 0010 0110 0111)2 C 12 1100
D 13 1101
(1010 0010)2 = (A2)16 E 14 1110

© ELFS
(1 0100)2 = (14)16 F 15 1111
67
Sistema Hexadecimal
• As conversões entre as bases 16 e 10 devem ser feitas
da forma padrão.
• Da base 16 para a base 10: soma de potências da base.
(ABAFA)16 = (703226)10
Ax164 + Bx163 + Ax162 + Fx161 + Ax160 = 703226

• Da base 10 para a base 16: os dígitos hexadecimais são


obtidos em divisões sucessivas da base.
703226 % 16 = 10 A 703226 / 16 = 43951
43951 % 16 = 15 F 43951 / 16 = 2746
2746 % 16 = 10 A 2746 / 16 = 171
171 % 16 = 11 B 171 / 16 = 10
10 A

© ELFS 68
Operadores de Incremento e Decremento
• Uma operação muito comum em programas de
computador é aumentar de 1 o valor de uma variável.
• Para fazer isso, devemos:
• Somar 1 ao valor atual da variável;
• Armazenar o resultado na própria variável.
• Exemplo: x = x + 1;
• Como a operação incremento de 1 é muito comum, na
linguagem C tem-se um operador especial: ++.
• Assim, em vez de: x = x + 1, podemos escrever: x++.
• Da mesma forma, para a operação decremento de 1, em
vez de: x = x - 1, podemos escrever: x--.
• Os operadores ++ e -- podem ser usados como prefixo
ou como sufixo do nome da variável.
© ELFS 69
Operadores de Incremento e Decremento
• Exemplos:

int a = 5, b = 3;
int c;
a++; a = 6
++b; b = 4
c = a++ + b; c = 6 + 4 = 10 a = 7
c = ++a + b; c = 8 + 4 = 12 a = 8

• As operações de incremento (++) e decremento (--) são


exemplos de operações combinadas com a atribuição.
• Lembrar que x++ significa: x = x + 1;
• Portanto, não tem sentido escrever: x = x++;
• Basta escrever: x++;

© ELFS 70
Operações combinadas com a atribuição
• Na linguagem C, uma operação de atribuição da forma:

variavel = variavel operador expressao;

pode ser escrita como:


variavel operador= expressao;

• Exemplos:
x = x + 1; x += 1;
x++; x += 1;
x = x + (a + b); x += (a + b);
x = x – (a + b); x -= (a + b);
x = x * (a – b); x *= (a – b);
x = x / (x + 1); x /= (x + 1);

• É bom escrever atribuições dessa forma?


© ELFS 71
• Atenção: O valor armazenado em uma variável por uma
operação de atribuição depende do tipo da variável.
• Se a variável for int, será armazenado um valor inteiro
(caso exista parte fracionária, ela será descartada).
• Se a variável for float ou double, será armazenado um
valor de ponto flutuante (caso não exista parte
fracionária, ela será zero).
• Exemplo:
int a;
float b;

Atribuição Valor Armazenado


a = (2 + 3) * 4 20
b = (1 – 4) / (2 – 5) 1.0
a = 2.75 + 1.12 3
b = a / 2.5 1.2
© ELFS 72
Processamento condicional
• Todo programa C inicia sua execução na primeira
instrução da função main().
• As instruções são executadas sequencialmente, na ordem
em que aparecem no programa.
• Muitas vezes, é necessário executar um conjunto de
instruções se uma condição for verdadeira e,
possivelmente, um outro conjunto de instruções se a
condição for falsa.
• Quando um programa executa ou deixa de executar
instruções com base no valor de uma condição, o
programa realiza um processamento condicional.
• Para executar um processamento condicional, um
programa C precisa utilizar o comando if.
© ELFS 73
Processamento condicional
• Raízes reais da equação ax2 + bx + c = 0
#include <stdio.h>
#include <stdlib.h>
#include <math.h>

int main()
{ Estas instruções serão
int a = 1; b = 2; c = 3;
float delta,x1,x2; executadas somente se
delta = b*b - 4*a*c; delta >= 0.
if (delta >= 0)
{
x1 = (-b + sqrt(delta))/(2*a);
x2 = (-b – sqrt(delta))/(2*a);
printf("Raizes reais: x1 = %f e x2 = %f\n",x1,x2);
}
return 0;
} Existe, portanto, uma condição para que
estas instruções sejam executadas. Se a
condição for falsa, as instruções não serão
executadas.
© ELFS 74
Processamento condicional
• Todo comando if requer uma condição. O valor de uma
condição pode ser verdadeiro (V) ou falso (F).
if (condição)
{
instruções a serem executadas se a condição for verdadeira;
}

• Na linguagem C, não existe um tipo de dados específico


para representar valores lógicos (V ou F).
• Em C, qualquer valor diferente de zero é interpretado
como V, enquanto zero é interpretado como falso.
if (a + b)
{
println("A mensagem será exibida somente se (a + b) != 0");
}

• Em geral, uma condição é uma relação entre valores.


© ELFS 75
Operadores relacionais
• Para escrever condições, são utilizados os operadores
relacionais e os operadores lógicos.
• Exemplos: int a = 3; float x = 1.5;

Condição Valor lógico


(a != x) Verdadeiro
(a/2.0 == x) Verdadeiro
(a/2 == x) Falso
(a/x <= 2) Falso
(a) Verdadeiro
(a – 2*x) Falso
(x >= a/2.0) Verdadeiro
((a/2 == x) && (a > 2)) Falso
((a – 2*x) || (x > a/2)) Verdadeiro
© ELFS 76
O comando if
• Sejam: int idade1, idade2;
as idades de duas pessoas. Quem é a pessoa mais nova?

maisnova = 1;
if (idade2 < idade1)
{
maisnova = 2;
}

if (idade1 < idade2)


{
maisnova = 1;
}
else
{
maisnova = 2;
}

• As duas soluções são equivalentes?


© ELFS 77
Cuidado com o teste de igualdade!
• Erro muito comum: em vez de usar o operador de
igualdade (==), usar o operador de atribuição (=).
int fator = 3;
if (fator == 1)
{
printf("Fator unitario\n"); Exibe:
}
printf("fator = %d\n", fator); fator = 3

int fator = 3;
if (fator = 1)
{ Exibe:
printf("Fator unitario\n"); Fator unitario
} fator = 1
printf("fator = %d\n", fator);

int fator = 3;
if (fator = 0)
{ E nesse caso?
printf("Fator nulo\n");
}
printf("fator = %d\n", fator);
© ELFS 78
Comando if-else
• Todo comando if requer uma condição, que pode ser
verdadeira ou falsa.
• Se a condição for verdadeira, um bloco de instruções
(delimitado por { }) será executado.
• Quando existe um bloco de instruções a ser executado, se
o valor da condição for falso, utiliza-se o comando if-else.
if (delta >=0) Se o bloco contém mais
{
x1 = (-b + sqrt(delta))/(2*a);
de 1 instrução as chaves
x2 = (-b – sqrt(delta))/(2*a); { } são obrigatórias.
printf("Raizes reais: %f e %f", x1,x2);
}
else
{
printf("Nao existem raizes reais.");
}
Se o bloco contém apenas 1 instrução as chaves { } são opcionais,
mas é uma boa prática de programação mante-las.
© ELFS 79
Comando if-else
• Um bloco de instruções pode conter qualquer instrução,
inclusive um comando if ou um comando if-else.
if (delta >=0)
{
x1 = (-b + sqrt(delta))/(2*a);
if (delta == 0) Observar que as
{ instruções que fazem
x2 = x1; parte de um bloco devem
} estar recuadas para a
else direita em relação às
{ chaves { }.
x2 = (-b – sqrt(delta))/(2*a);
}
printf("Raizes reais: %f e %f", x1,x2);
}
else
{
printf("Nao existem raizes reais.");
}

© ELFS 80
A importância dos recuos
if (delta >=0)
{
x1 = (-b + sqrt(delta))/(2*a); Que tal escrever o
if (delta == 0) programa dessa forma?
{
x2 = x1; Fica mais fácil ou mais
} difícil identificar qual é a
else abre-chaves que
{ corresponde a uma
x2 = (-b – sqrt(delta))/(2*a);
fecha-chaves?
}
printf("Raizes reais: %f e %f", x1,x2);
} Escrever o programa com
else recuos não custa nada e
{ o programa fica mais
printf("Nao existem raizes reais."); legível.
}

• Para o compilador, não faz diferença como o programa é


escrito. Os recuos são importantes para quem precisa ler
o programa (talvez você mesmo!).
© ELFS 81
Recuos não resolvem ambiguidades
if (nota >= 7)
if (nota_anterior < nota) O else se refere a
printf("Voce está melhorando!"); qual if?
else
printf("Sem estudo e' mais dificil ser aprovado.");

• O compilador sempre associa um else ao "if anterior mais


próximo que ainda não possui else".
• Logo: o else acima refere-se ao if (nota_anterior < nota)
• Como associar o else à instrução if (nota >= 7)?
if (nota >= 7)
{ Neste caso, as chaves, em
if (nota_anterior < nota) vez de opcionais, serão
printf("Voce está melhorando!"); obrigatórias, pois apenas
} os recuos não resolvem.
else
printf("Sem estudo e' mais dificil ser aprovado.");

© ELFS 82
O operador condicional
• O operador condicional da linguagem C tem a seguinte
sintaxe:
(condição)?
resultado-se-condição-verdadeira Tudo pode ser escrito
: numa única linha.
resultado-se-condição-falsa

• Os resultados podem ser de qualquer tipo: int, float,


char, double ou mesmo strings.
• O operador condicional representa um valor e, portanto,
pode ser usado em qualquer lugar em que se espera um
valor.
float x = (b != 0)? a/b : 0.0;
int k = (peso <= 75) ? 1 : 0;
printf("A equacao %s", (delta >= 0)? "possui raizes reais"
: "nao possui raizes reais");

© ELFS 83
Leitura de dados
• A leitura de dados é uma outra forma de atribuir valores
a variáveis. Na linguagem C, usa-se a função scanf() para
a leitura de dados.
• Assim como na função printf(), a função scanf() pode ter
vários parâmetros, sendo o primeiro um string.
• No caso da função scanf(), este string deve conter
apenas tags, separadas por espaços em branco.
• Os demais parâmetros da função scanf() devem ser
endereços de variáveis.
• O que acontece quando o computador executa uma
instrução de leitura de dados?
• Exemplo:
scanf("%f", &c);

© ELFS 84
Leitura de dados
scanf("%f", &c);

• A execução do programa é interrompida. O computador


espera que o usuário digite algum valor e pressione a
tecla Enter.
• Após pressionar Enter, o computador retoma a execução
do programa e armazena o valor digitado no endereço
fornecido na função scanf().
• Na leitura de dados, o valor digitado pelo usuário deve
respeitar o tipo da variável usada na função scanf().
• Para avisar o usuário que o computador espera a entrada
de algum valor, é comum usar a função printf() antes de
uma função scanf().
printf("Digite um valor: ");
scanf("%f", &c);
© ELFS 85
Leitura de dados
• Qual é a diferença entre a operação de atribuição e a
leitura de dados?
• Na operação de atribuição, o valor a ser atribuído é
definido antes da execução do programa, enquanto numa
operação de leitura de dados, o valor atribuído é definido
durante a execução.
• Em programação de computadores, uma coisa é estática
se ocorre antes da execução do programa e é dinâmica,
se ocorre durante a execução do programa.
• Com a leitura de dados, a execução do programa pode
ser realizada para diferentes valores da variável.
• Porém, se o valor da variável é estabelecido de forma
estática, para cada valor da variável, será necessário
compilar o programa novamente.
© ELFS 86
Escrevendo resultados

• A função printf é usada para exibir resultados produzidos


pelo programa e pode ter um ou mais parâmetros.
• O primeiro parâmetro da função printf é sempre um string,
e corresponde à sequência de caracteres que será exibida
pelo programa.
• Essa sequência de caracteres pode conter alguns tags que
representam valores (por exemplo: %d, para int e %f,
para float).
• Os demais parâmetros são valores a serem exibidos nos
tags.
• Exemplo: printf("Valor de y = %f, para n = %d",y,(a+b));
irá exibir:
[Valor de y =][um valor float][, para n =][um valor int]

© ELFS 87
Escrevendo resultados

• A linguagem C utiliza o símbolo \ (barra invertida) para


especificar alguns caracteres especiais:
Caractere Significado
\a Alarme sonoro (caractere invisível)
\n Nova linha (caractere invisível)
\t Tabulação (caractere invisível)
\’ Apóstrofo
\" Aspas

• Exemplo:
printf("Valor de y = %f,\npara n = %d",y,(a+b));

printf("Valor de y = %f,\n",y);
printf("para n = %d",(a+b));
© ELFS 88

Você também pode gostar