Baixe o app para aproveitar ainda mais
Prévia do material em texto
CAPITULO 2 – OPERADORES C é uma linguagem rica em operadores, em torno de 50. OPERADOR DE ATRIBUIÇÃO: = Representa a atribuição da expressão à sua direita à variável à sua esquerda. Exemplo: x = 2000; Atribui o valor 2000 à variável de nome x. Podemos escrever y = x = 3; Lembrando que atribuições são executadas da direita para a esquerda , a expressão anterior pode ser escrita y = (x = 3) e y terá valor 3. Expressões desse tipo são chamadas de atribuições múltiplas. OPERADORES ARITMÉTICOS: + — * / % C oferece 5 operadores aritméticos binários (que operam sobre dois operandos, + — * /) e um operador aritmético unário (que opera sobre um operando %). São eles: ■ Operadores Aritméticos Binários + Soma — Subtração * Multiplicação / Divisão % Módulo ■ Operador Aritmético Unitário O operador módulo opera somente com operandos inteiros e dá como resultado o resto da divisão do inteiro à sua esquerda pelo inteiro à sua direita. Exemplo: 17 % 5 /*Resulta em 2 */ Pois, quando dividimos 17 por 5, restam 2. ■ Precedência A precedência de operadores indica qual operador deverá ser executado primeiro. A multiplicação e a divisão têm precedência sobre a soma e a subtração. Podemos usar parênteses para mudar a ordem de avaliação. As expressões entre parênteses são as primeiras a serem avaliadas. Os operadores + e — têm a mesma precedência, e a regra de associatividade é da “esquerda para a direita”. ✓ Os operadores *, / e % têm a mesma precedência e associatividade da “esquerda para a direita”. ✓ Os operadores *, / e % tem precedência sobre os operadores + e – ■ O operador menos unário: — O operador menos unário é usado somente para indicar a troca do sinal algébrico do valor associado. Exemplo: x = —8; X = —X; X = 8 OPERADOR DE ENDEREÇOS: & A linguagem C oferece um operador que opera sobre o nome de uma variável e retorna o seu endereço. A memória de seu computador é dividida em bytes, que são numerados de 0 até o limite de memória de sua máquina. Estes números são chamados de “endereços” de bytes. Um endereço é a referência que o computador usa para localizar variáveis. Toda variável ocupa uma certa localização na memória, e o seu endereço é o do PRIMEIRO BYTE (byte menos significativo) ocupado por ela. Se você declarou uma variável inteira, nomeou-a n e atribuiu a ela o valor 2, quando n for referida obteremos 2. Entretanto, se você usar &n, o resultado será o endereço do primeiro byte (byte menos significativo) ocupado por n. O programa seguinte imprime o valor e o endereço de n: { int n = 2; printf("Valor de n = %d\nEndereco de n = %p\n", n, &n); } Valor de n = 2 Endereco de n = 0029FF2C /* Endereço do primeiro byte ocupado por n Endereços de memória são impressos em hexadecimal (base 16) e o formato usado é %p. A FUNÇÃO scanf() A função scanf() é outra função de I/O (entrada e saída) presente na biblioteca-padrão, fornecida com os compiladores C <stdio.h>. Ela é o complemento de printf() e nos permite ler dados formatados da entrada padrão (teclado). As definições necessárias ao uso de scanf() estão no arquivo stdio.h. Sua sintaxe é similar à de printf(): isto é, uma expressão de controle seguida por uma lista de argumentos separados por virgulas. Os argumentos de scanf() devem ser endereços de variáveis. ■ Sintaxe scanf(“%expressão de controle”, &lista_de_argumentos); A expressão de controle pode conter códigos de formatação precedidos por um sinal de %, ou ainda pelo caractere * colocado após a % e antes do código de formatação. O caractere * avisa à função que deve ser lido um valor do tipo indicado pela especificação, mas não deve ser atribuído a nenhuma variável, ou seja, deve ser descartado. A lista de argumentos deve consistir dos endereços das variáveis. ■ Códigos de formatação da função scanf() Os códigos de formatação para impressão formatada da função scanf() são semelhantes aos código de formatação da função printf(): Códigos de formatação para scanf() Significado %c Caractere simples %d Inteiro decimal com sinal %i Inteiro decimal, hexadecimal ou octal %e Notação científica %f Ponto flutuante em decimal %g Usa %e ou %f, o que for menor %o Inteiro octal %s String de caracteres %u Inteiro decimal sem sinal %x Inteiro hexadecimal %ld Inteiro decimal longo %lf Ponto flutuante longo (double) %Lf Double longo Exemplo: { float idade, dias; printf("Qual sua idade em anos? "); scanf("%f", &idade); dias = idade * 365; printf("Sua idade em dias eh de : %.0f\n", dias); } Saída: Qual sua idade em anos? 35.3 Sua idade em dias eh de : 12885 ■ Múltiplas entradas com scanf() Podemos ler vários valores com uma única chamada à scanf(). Exemplo: { float p1, p2, p3, p4, media; printf("Digite as notas das provas: "); scanf("%f%f%f%f", &p1, &p2, &p3, &p4); media = (p1 + p2 + p3 + p4) / 4; printf("Media = %.1f\n", media); } Saída: Digite as notas das provas: 9 8 7 5 Media = 7.3 A função scanf() entende um espaço em branco como o término de uma entrada. Múltiplas entradas são digitadas separadas por um espaço em branco. Digitamos [ENTER] como finalizador geral. ■ Incluindo expressões com operadores aritméticos (e outros operadores) diretamente em printf() Um programa que usa vários operadores aritméticos e converte temperaturas de graus Celsius para graus Fahrenheit Exemplo: { float ctemp; printf("Digite a temperatura em graus Celsius: "); scanf("%f", &ctemp); printf("Temperatura em graus Fahrenheit = %.1f\n", ctemp*9/5+32); } Saída: Digite a temperatura em graus Celsius: 28 Temperatura em graus Fahrenheit = 82.40 ■ Impressão formatada com printf() (decimal, hexadecimal, octal) Exemplo: { char caracter; printf("Digite um caractere e veja-o como DECIMAL, OCTAL e HEXADECIMAL: "); scanf("%c", &caracter); printf("Caracter = %c\n", caracter); printf("Dec\t = %d\n", caracter); printf("Oct\t = %o\n", caracter); printf("Hex\t = %x\n", caracter); } Saída: Digite um caractere e veja-o como DECIMAL, OCTAL e HEXADECIMAL: A Caracter = A Dec = 65 Oct = 101 Hex = 41 ■ Entrada formatada usando %* com scanf() O que o comando %*c faz é ler um caractere e descartá-lo, ou seja, ele limpa a sujeira do buffer. Por exemplo, se você fizer isso: printf("Digite um caractere: "); scanf("%c", &caractere); O que vai acontecer é que o caractere que o usuário digitar vai ser lido pelo scanf e armazenado na variável caractere. Porém, se você fizer isso: printf("Digite um caractere: "); scanf("%*c", &caractere); O que vai acontecer é que o scanf vai ler o caractere digitado pelo usuário e vai descartá-lo. Exemplo: { int dia, mes, ano; printf("Digite uma data no formato dd/mm/aaaa\n"); scanf("%d %*c %d %*c %d", &dia, &mes, &ano); printf("A data que voce digitou foi : %d/%0.2d/%d\n", dia, mes, ano); } Saída: Digite uma data no formato dd/mm/aaaa 29/12/1986 A data que voce digitou foi : 29/12/1986 Faz-se uso de uma função para limpar a sujeira no buffer, que seria essa: void limpa_linha() { scanf("%*[^\n]"); // aqui vai ser lido qualquer lixo do buffer que houver exceto o '\n' scanf("%*c"); // aqui vai ser lido o '\n' que é gerado ao se dar um ENTER e vai descartá-lo } O QUALIFICADOR const A palavra-chave const assegura que a variável associada não será alterada em todo o programa. Esse qualificador é indicado para declarar valores constantes. Exemplo: { const char Bip = '\a'; const double Pi = 3.141592; double raio, area; printf("Digite o raio da esfera: "); scanf("%lf", &raio); area = 4 * Pi * raio * raio; printf("%c",Bip); printf("A area da esfera = %.2lf\n",area); } Saída: Digite o raio da esfera: 10 /* Alerta de aviso sonoro */ A area da esfera = 1256.64 CONVERSORES DE TIPOS E O OPERADOR DE MOLDE OU cast C tem um operador para alterar o tipo de um valor explicitamente. Este operador é chamado de cast. Executando um cast de tipos, o valor da expressão é forçado a ser de um tipo particular, não importando a regra de conversão de tipos. Repare no problema: Exemplo: { int num1 = 9; int num2 = 2; float div = num1 / num2; printf("%f\n", div); } Saída: 4.000000 Percebe-se que por mais que a variável div seja do tipo float o resultado não dá 4.5, pois para o compilador C a divisão de dois números inteiros resultará em um número inteiro. Podemos resolver esse problema de duas formas: Resolução 1: multiplicando uma das variáveis por um número float { int num1 = 9; int num2 = 2; float div = num1 * 1.0 / num2; printf("%f\n", div); } Saída: 4.500000 Resolução 2: moldando uma das variáveis para o tipo float { int num1 = 9; int num2 = 2; float div = (float) num1 / num2; printf("%f\n", div); } Saída: 4.500000 Muitas vezes, uma expressão lógica ou aritmética envolve variáveis e constantes de tipos distintos, como char, int, float e double. Algumas conversões são efetuadas implicitamente pelo compilador, sem riscos para a integridade dos dados manipulados. Todavia, algumas conversões podem levar à perda de informação e precisam ser forçadas pelo programador, através de conversões explícitas. ■ Conversão implícita Quando uma expressão envolve operandos de diversos tipos, o compilador primeiro os converte para um único tipo, antes de avaliar a expressão. Nos casos de tipos numéricos os tipos de menor tamanho (com menos bytes) são automaticamente convertidos para os tipos de maior tamanho (com mais bytes). A hierarquia para a promoção automática é a seguinte: char < short < int < long < long long < float < double < long double A Conversão Implícita é realizada para as expressões aritméticas (+ - * / %), relacionais (< <= > >= == !=), com bits (& | ^) e para o operador condicional (? :). Por exemplo, na expressão a seguir, as variáveis à direita da atribuição (sinal =) são convertidas para um tipo único, antes da expressão ser avaliada. Exemplo 1: char c = 'A'; int i = 3, j = 54; short k = 31; float x = 31.8; double y; j = c + 30 ; // o valor de c (65) é convertido para int y = i * x + k ; // os valores de i e k são convertidos para float Em alguns casos, a Conversão Implícita na atribuição pode levar à perda de informação. Vejamos alguns exemplos. char c = 'A'; int i, j = 34; long long k = 12345677890; float x, y = 451.28; double pi = 3.141592653589793264; i = c; // ok, pois int > char x = i; // ok, pois float > int i = y; // problema, parte fracionária é truncada x = pi; // problema, perda de precisão i = k; // problema, perde os bits mais significativos ■ Conversão explícita Em alguns casos, é necessário forçar a conversão de tipos de dados, para que uma expressão seja avaliada da forma desejada pelo programador. Exemplo: int soma = 100; int num = 40; float media = soma / num; // media = 2.0 (por que?) No caso acima, a expressão soma/num será avaliada como int/int, resultando em uma divisão inteira e consequente perda de precisão. Para gerar o resultado correto, a expressão deve ser avaliada como float. Isso pode ser obtido de duas formas: 1. Adicionando um elemento neutro de tipo float à expressão; 2. Forçando a avaliação de soma ou num como float. int soma, num; float media; soma = 10; num = 4; media = soma / num; // errado, perda de precisão media = 1.0 * soma / num; // soma é "promovida" a float media = (float)soma / num; // soma é avaliada como float (casting) media = soma / (float) num; // num é avaliado como float (casting) AS FUNÇÕES DE BIBLIOTECA <conio.h>: getche() e getch() Em algumas situações, a função scanf() não atende perfeitamente, pois é preciso pressionar a tecla [ENTER] toda vez que desejar terminar a leitura. A biblioteca <conio.h> de funções C oferece duas funções que leem um caractere no instante em que é digitado, sem esperar pela tecla [ENTER]. <conio.h> A princípio, tem função de capturar um caractere da entrada e retorná-lo. Porém, ela é mais usada mesmo para pausar o terminal, visto que a instrução system (“PAUSE”) seu argumento (nesse caso (“PAUSE”) depende diretamente do sistema operacional. getche() retorna o caractere lido do teclado. O valor retomado de uma função pode ser chamado de valor da função ou resultado da função. ch = getche() // atribui o valor da função getche() à variável ch A função getch() é similar a getche(), exceto pelo fato de o caractere digitado não ser impresso no vídeo. Dizemos que a função getch() não ecoa no vídeo. As duas necessitam da biblioteca <conio.h> Exemplo de getche(): { char ch; printf("digite uma letra: "); ch = getche(); printf("\na letra digitada foi <%c>\n", ch); } Saída: digite uma letra: K < - - - a letra digitada foi <K> Exemplo de getch(): int main() { char ch; printf("digite uma letra: "); ch = getch(); printf("\na letra digitada foi <%c>\n", ch); } Saída: digite uma letra: < - - - ausência de eco a letra digitada foi <K> AS FUNÇÕES DE BIBLIOTECA-PADRÃO <stdio.h> : getchar() e putchar() A função getchar() tem protótipo definido no arquivo <stdio.h> que acompanha seu compilador. Aguarda o próximo caractere da entrada padrão (teclado) e retorna o caractere lido. Essa função só termina a leitura quando a tecla [ENTER] é pressionada. getchar() e putchar() são mais utilizados para capturar caracteres de forma isolada, sem utilizar necessariamente o scanf(); para fazer uma leitura formatada, ou o prinf(); para fazer uma impressão formatada. Muito utilizado para fazer pausas no programa ao finalizar, visto que ele só finaliza a instrução quando ele recebe um [ENTER]. Exemplo: { char ch; printf("Digite uma letra: "); ch = getchar(); printf("A letra digitada foi: "); putchar(ch); printf("\n"); } Saída: Digite uma letra: k A letra digitada foi: k Podemos aproveitar a mesma sintaxe e usar getch() e getche() da biblioteca <conio.h> mas usando a saída putch(). Exemplo: { char ch; printf("Digite uma letra para ser lida: "); ch = getche(); //Podemos usar também getch() printf("\nA letra lida foi: "); putch(ch); printf("\n"); } Saida: Digite uma letra para ser lida: A A letra lida foi: A OPERADORES DE INCREMENTO + + e DECREMENTO – – O operador de incremento (++) e decremento (––) operam sobre o nome de uma variável e adiciona ou subtrai 1 ao valor da variável operando. O operador de incremento pode ser usado de duas maneiras: Pré-incremento: quando aparece antes do nome da variável ++variavel b = ++a // Primeiro incrementa ‘a’, depois atribui ‘a’ para ‘b’ Pós-incremento: quando aparece em seguida ao nome da variável. variável++ b = a++ // Primeiro atribui ‘a’ para ‘b’, depois incrementa ‘a’ ■ Pós-incremento Exemplo: { int a, b; //Pós incremento a = 0, b = 0; printf("Pos incremento:\n"); while (a<5) { b = a++; // Primeiro atribui 'a' para 'b', depois incrementa 'a' printf("a = %d \t b = %d\n", a, b); } } Saída: Pos incremento: a = 1 b = 0 a = 2 b = 1 a = 3 b = 2 a = 4 b = 3 a = 5 b = 4 ■ Pré-incremento Exemplo: { int a, b; //Pré incremento a = 0, b = 0; printf("Pre incremento:\n"); while (a<5) { b = ++a; // Primeiro incrementa ‘a’, depois atribui ‘a’ para ‘b’printf("a = %d \t b = %d\n", a, b); } } Saída: Pré incremento: a = 1 b = 1 a = 2 b = 2 a = 3 b = 3 a = 4 b = 4 a = 5 b = 5 ■ Precedência Exemplo: x = a * b++ É equivalente a: x = a * (b++) Na instrução anterior, o resultado da operação de multiplicação de ‘a’ por ‘b’ será atribuído a ‘x’, depois, ‘b’ será incrementada. Já na expressão: x = a * ++b: A variável ‘b’ é incrementada e depois multiplicada por ‘a’: por fim, o resultado é atribuído a x. Exemplo 1: x = a * b++ { int x, a, b; a = 1, b = 1; x = a * b++; printf("x = %d", x); } Saída: x = 1 Exemplo 2: x = a * ++b { int x, a, b; a = 1, b = 1; x = a * ++b; printf("x = %d\n", x); } Saída: x = 2 OPERADORES ARITIMÉTICOS DE ATRIBUIÇÃO: += –= *= /= %= Esses operadores combinam as operações aritméticas com a operação de atribuição, oferecendo uma maneira curta e clara de escrita de certas expressões de atribuição. O operando da esquerda é sempre o nome de uma variável, e o da direita, uma expressão qualquer. Exemplo: i += 2 Equivale a: i = i + 2 x *= y + 1 Equivale a: x = x * (y + 1) t /= 2.5 Equivale a: t = t / 2.5 p %= 5 Equivale a: p = p % 5 d -= 3 Equivale a: d = d -3 Exemplo: void main() { float nota, media; media = 0; printf("Primeira nota: "); scanf("%f", ¬a); media += nota; printf("Segunda nota: "); scanf("%f", ¬a); media += nota; printf("Terceira nota: "); scanf("%f", ¬a); media += nota; printf("Quarta nota: "); scanf("%f", ¬a); media += nota; media /= 4; printf("MEDIA = %.2f\n", media); } Saida: Primeira nota: 7 Segunda nota: 9 Terceira nota: 7 Quarta nota: 9 MEDIA = 8.00 OPERADORES RELACIONAIS: > >= < <= == != Os operadores relacionais fazem comparações. São eles: > Maior >= Maior ou igual < Menor <= Menor ou igual == Igual != Diferente Em C, não existe um tipo de variável chamada de “booleana”, isto é, que assuma um valor verdadeiro ou falso. Quando o computador deve responder se uma expressão é verdadeira ou falsa, responderá com o valor um (1) para verdadeiro e com o valor zero (0) para falso. Exemplo: { int Verdadeiro, Falso; Verdadeiro = (15 < 20); Falso = (15 == 20); printf("Verdadeiro \t %d\n", Verdadeiro); printf("Falso \t %d\n", Falso); } Saída: Verdadeiro 1 Falso 0 Operadores relacionais avaliam seus operandos como quantidades numéricas, e o resultado da operação é o valor lógico 1 para verdadeiro e 0 para falso. ■ Precedência Os operadores relacionais têm precedência menor que a dos operadores aritméticos. Isso significa que os operadores aritméticos são resolvidos antes dos relacionais. Exemplo: { printf("O valor da expressao 4 + 1 < 3 eh: %d\n", 4+1<3); printf("O valor da expressao 2 < 1 + 3 eh: %d\n", 2<1+3); } Saída: O valor da expressao 4 + 1 < 3 eh: 0 O valor da expressao 2 < 1 + 3 eh: 1 OPERADORES LÓGICOS: && || ! Operadores Lógicos também fazem comparações. A diferença entre Comparações Lógicas e Relacionais está na forma como os operadores avaliam seus operandos. Operandos de operadores lógicos são avaliados como lógicos (0 ou 1), e não como quantidades numéricas. C oferece três operadores lógicos. São eles: && Lógico E || Lógico OU ! Lógico NÃO Desses operadores, ! é unário e os outros dois são binários. Os operadores lógicos são geralmente aplicados a expressões relacionais. Exemplo: (dia == 7 && mes == 6) // Verdadeiro (1) se dia for 7 E mes for 6 (op == 's' || op == 'S') // Verdadeiro (1) se op for 's' OU 'S' (!Masculino) // Verdadiro se masculino for 0 OPERADORE CONDICIONAL TERNÁRIO: ?: É o único operador C que opera sobre três expressões. Sua sintaxe geral possui a seguinte construção: exp1 ? exp2 : exp3 A exp1 é avaliada primeiro. Se o seu valor for verdadeiro, a exp2 será avaliada e o seu resultado será o valor da expressão condicional como um todo. Se a exp1 for falsa, a exp3 será avaliada e será o valor da expressão condicional como um todo. Exemplo: A variável que contém o maior valor numérico entre a e b será atribuída a max. max = (a > b) ? a : b; Exemplo: O valor absoluto de x: abs = (x > 0) ? x : -x; Exemplo: Saber se um número é par ou impar: printf("%s", x%2? "Impar" : "Par"); TABELA DE PRECEDÊNCIA DOS OPERADORES BÁSICOS A tabela seguinte apresenta as precedências dos operadores. Os que estão no mesmo bloco têm a mesma precedência e são executados primeiro os que aparecem antes na expressão. Símbolo Operador - Menos unário ++ Incremento prefixado ou pós-fixado -- Decremento prefixado ou pós-fixado ! Lógico NÃO * Multiplicação aritmética / Divisão aritmética % Módulo aritmético + Mais aritmético - Menos aritmético < Menor relacional <= Menor ou igual relacional > Maior relacional >= Maior ou igual relacional == Igual relacional != Diferente relacional && E lógico || OU lógico ?: Condicional = Atribuição *= Aritmético de atribuição (vezes) /= Aritmético de atribuição (divide) %= Aritmético de atribuição (módulo) += Aritmético de atribuição (soma) -= Aritmético de atribuição (menos)
Compartilhar