Vous êtes sur la page 1sur 22

INFORMTICA APLICADA LINGUAGEM C

1 INTRODUO
MINISTRIO DA EDUCAO UNIVERSIDADE TECNOLGICA FEDERAL DO PARAN CAMPUS PATO BRANCO CURSO SUPERIOR DE TECNOLOGIA EM MANUTENO INDUSTRIAL

Neste material so passados os conceitos bsicos da linguagem de programao C, que tem se tornado cada dia mais popular, devido sua versatilidade e ao seu poder. Uma das grandes vantagens do C que ele possui tanto caractersticas de "alto nvel" quanto de "baixo nvel". O C uma linguagem de programao genrica que utilizada para a criao de programas diversos como processadores de texto, planilhas eletrnicas, sistemas operacionais, programas de comunicao, programas para a automao industrial, gerenciadores de bancos de dados, programas de projeto assistido por computador, programas para a soluo de problemas da Engenharia, Fsica, Qumica e outras Cincias, etc. Estudaremos a estrutura do ANSI C, o C padronizado pela ANSI. Sugere-se que o aluno realmente use o mximo possvel dos exemplos, problemas e exerccios apresentados, gerando os programas executveis com o seu compilador. Quando utilizamos o compilador aprendemos a lidar com mensagens de aviso, mensagens de erro, bugs, etc. Apenas ler os exemplos no basta. O conhecimento de uma linguagem de programao transcende o conhecimento de estruturas e funes. O C exige, alm do domnio da linguagem em si, uma familiaridade com o compilador e experincia em achar bugs nos programas. importante ento que o aluno digite, compile e execute os exemplos apresentados.

2 LINGUAGEM C PRIMEIROS PASSOS


2.1 O C "Case Sensitive" Vamos comear ressaltando um ponto de suma importncia: o C "Case Sensitive", isto , maisculas e minsculas fazem diferena. Se uma varivel for declarada com o nome var, ela ser diferente de Var, VAR, VaR ou vAr. Da mesma maneira, os comandos do C devem ser escritos da forma correta para o compilador interpret-los como comandos. 2.2 O Primeiro Programa Vejamos um primeiro programa em C:
#include <stdio.h> int main () /* Um Primeiro Programa */ { printf ("Informtica Aplicada Primeiro Programa\n"); return(0); }

IA34M - INFORMTICA APLICADA - LINGUAGEM C -

Compilando e executando este programa voc ver que ele coloca a mensagem Informtica Aplicada Primeiro Programa na tela. Como compilar programas usando o DevC++? Uma vez instalado o compilador, voc pode criar um novo programa atravs da opo: Arquivo / Novo / Arquivo Fonte, ou utilizando as teclas de atalho Ctrl+N, ou ainda, utilizando o boto correspondente na barra de ferramentas. Na janela que aparece, voc digita o seu programa. Veja que o DevC++ oferece para voc um programa inicial que voc pode apagar, se quiser. Uma vez digitado o seu programa, voc pode compil-lo e executlo atravs da opo: Executar / Compilar & Executar, ou pressionando diretamente F9, ou utilizando o boto Compilar & Executar na barra de ferramentas. Note que se voc fizer isto para um programa que no espera nenhuma entrada do usurio, como o exemplo anterior, o programa ser executado, terminar sua execuo, e a janela onde ele est executando ser automaticamente fechada. Com isto, voc no conseguir ver a sada do programa. Para evitar que isto acontea, voc pode modificar seus programas incluindo as linhas:
#include <stdlib.h> no incio do programa system("pause"); antes do final do programa

PROF. CARLOS MARCELO DE OLIVEIRA STEIN FEVEREIRO, 2006

Fazendo-se estas alteraes no primeiro programa, tem-se:

V 06 0306

INFORMTICA APLICADA LINGUAGEM C #include <stdio.h> #include <stdlib.h> int main () /* Um Primeiro Programa */ { printf ("Informtica Aplicada Primeiro Programa\n"); system("pause"); return(0); }

INFORMTICA APLICADA LINGUAGEM C

2.2.1

Analisando o programa por partes

recomendvel de se fazer, pois pode gerar confuso. Apresentamos a seguir as palavras reservadas do ANSI C. volatile struct register float default auto while switch return for do break typedef short goto double case union signed if else char unsigned sizeof int enum const void static long extern continue 2.6 Os Tipos do C

A linha #include <stdio.h> diz ao compilador que ele deve incluir o arquivo de biblioteca de comandos stdio.h. Neste arquivo existem declaraes de funes teis para entrada e sada de dados (std = standard, padro em ingls; io = Input/Output, entrada e sada ==> stdio = Entrada e sada padronizadas). Toda vez que voc quiser usar uma destas funes deve-se incluir este comando. O C possui diversas bibliotecas de comandos. Quando fazemos um programa, uma boa idia usar comentrios que ajudem a elucidar o funcionamento do mesmo. No caso acima temos um comentrio: /* Um Primeiro Programa */. O compilador C desconsidera qualquer coisa que esteja comeando com /* e terminando com */. A linha int main() define uma funo de nome main. Todos os programas em C tm que ter uma funo main, pois esta funo que ser chamada quando o programa for executado. O contedo da funo delimitado por chaves { }. O cdigo que estiver dentro das chaves ser executado sequencialmente quando a funo for chamada. A palavra int indica que esta funo retorna um nmero inteiro. A nica coisa que este programa realmente faz chamar a funo printf(), passando o texto "Informtica Aplicada Primeiro Programa\n" como argumento. por causa do uso da funo printf() que a biblioteca stdio.h foi includa. A funo printf() neste caso ir apenas colocar o texto na tela do computador. A \n uma constante chamada de constante barra invertida de nova linha que interpretado como um comando de mudana de linha, isto , aps imprimir Informtica Aplicada Primeiro Programa o cursor passar para a prxima linha. importante observar tambm que os comandos do C terminam com ;. 2.3 Comentrios

O C tem tipos bsicos: char (um caracter), int (um nmero inteiro), float (um nmero com ponto flutuante) e double (ponto flutuante de preciso dupla). Para cada um dos tipos de variveis existem os modificadores de tipo. Os modificadores de tipo do C so quatro: signed, unsigned, long e short. Ao float no se pode aplicar nenhum e ao double pode-se aplicar apenas o long. Os quatro podem ser aplicados a inteiros. A inteno que short e long devam prover tamanhos diferentes de inteiros onde isto for prtico. int normalmente ter o tamanho natural para uma determinada mquina. Assim, em uma mquina de 16 bits, int provavelmente ter 16 bits e em uma mquina de 32, 32 bits. Na verdade, cada compilador livre para escolher tamanhos adequados para o seu prprio hardware, com a nica restrio de que short e int devem ocupar pelo menos 16 bits, long pelo menos 32 bits, e short no pode ser maior que int, que no pode ser maior que long. A seguir esto listados os tipos de dados permitidos e seus valores mximos e mnimos em um compilador tpico para um hardware de 16 bits:
Tipo char unsigned char signed char int unsigned int signed int short int unsigned short int signed short int long int signed long int unsigned long int float double long double Nmero de bits 8 8 8 16 16 16 16 16 16 32 32 32 32 64 80 Intervalo Inicio Fim -128 127 0 255 -128 127 -32.768 32.767 0 65.535 -32.768 32.767 -32.768 32.767 0 65.535 -32.768 32.767 -2.147.483.648 2.147.483.647 -2.147.483.648 2.147.483.647 0 4.294.967.295 3,4E-38 3.4E+38 1,7E-308 1,7E+308 3,4E-4932 3,4E+4932

O compilador ignora os comentrios existentes no cdigo fonte, ou seja, eles no interferem no programa executvel. O uso de comentrios torna o cdigo do programa mais fcil de se entender. Existem basicamente duas formas de inserir comentrios: com o comando // e com o comando /* */. O primeiro utilizado para comentar o restante da linha (aps //), e o segundo para comentar tudo entre /* e */. Um comentrio pode, desta forma, ter mais de uma linha. 2.4 Nomes de Variveis

As variveis no C podem ter qualquer nome se algumas condies forem satisfeitas: o nome deve comear com uma letra ou sublinhado (_) e os caracteres subsequentes podem ser letras, nmeros ou sublinhado. Alm disso, o nome de uma varivel no pode ser igual a uma palavra reservada, nem igual ao nome de uma funo declarada pelo programador, ou pelas bibliotecas do C. Variveis de at 32 caracteres so aceitas. Mais uma coisa: bom sempre lembrar que o C "case sensitive" e, portanto deve-se prestar ateno s maisculas e minsculas. 2.5 Palavras Reservadas do C

O tipo long double o tipo de ponto flutuante com maior preciso. importante observar que os intervalos de ponto flutuante, na tabela acima, esto indicados em faixa de expoente, mas os nmeros podem assumir valores tanto positivos quanto negativos. 2.7 Declarao e Inicializao de Variveis

As variveis no C devem ser declaradas antes de serem usadas. A forma geral da declarao de variveis :
tipo_da_varivel lista_de_variveis;

Todas as linguagens de programao tm palavras reservadas. As palavras reservadas no podem ser usadas a no ser para seus propsitos originais. Como o C "case sensitive" podemos declarar uma varivel For, apesar de haver uma palavra reservada for, mas isto no uma coisa

As variveis da lista de variveis tero todas o mesmo tipo e devero ser separadas por vrgula. Como o tipo default (padro) do C o int, quando vamos declarar variveis int com algum dos modificadores de tipo, basta colocar o nome do modificador de tipo. Assim um long basta para declarar um long int. Por exemplo, as declaraes
char ch, letra; long cont;

V 06 0306

V 06 0306

INFORMTICA APLICADA LINGUAGEM C float pi;

INFORMTICA APLICADA LINGUAGEM C

2.9

A Funo scanf O formato geral da funo scanf() :


scanf (string_de_controle, lista_de_argumentos);

declaram duas variveis do tipo char (ch e letra), uma varivel long int (cont) e um float (pi). Podemos inicializar variveis no momento de sua declarao. Isto importante, pois quando o C cria uma varivel ele no a inicializa. Isto significa que at que um primeiro valor seja atribudo nova varivel ela tem um valor indefinido e que no pode ser utilizado para nada. Nunca presuma que uma varivel declarada vale zero ou qualquer outro valor. Exemplos de inicializao so dados abaixo:
char ch='D'; int cont=0; float pi=3.141;

Usando a funo scanf() podemos pedir dados ao usurio. Mais uma vez, devemos ficar atentos a fim de colocar o mesmo nmero de argumentos que o de cdigos de controle na string de controle. Outra coisa importante lembrarmos de colocar o & antes das variveis da lista de argumentos. 2.10 O Segundo Programa Podemos agora tentar um programa mais complicado:
#include <stdlib.h> #include <stdio.h> int main () { int Minutos; // Declarao de Varivel float Horas; printf("Entre com os minutos: "); // Entrada de Dados scanf("%d",&Minutos); Horas=Minutos/60.0; // Converso Minutos->Horas printf("\n %d minutos equivalem a %f horas.\n",Minutos,Horas); system("pause"); return(0); }

2.8

A Funo printf A funo printf() tem a seguinte forma geral:


printf (string_de_controle, lista_de_argumentos);

Teremos, na string de controle, uma descrio de tudo que a funo vai colocar na tela. A string de controle mostra no apenas os caracteres que devem ser colocados na tela, mas tambm quais as variveis e suas respectivas posies. Isto feito usando-se os cdigos de controle, que usam a notao %. Na string de controle indicamos quais, de qual tipo e em que posies esto as variveis a serem apresentadas. muito importante que, para cada cdigo de controle, tenhamos um argumento na lista de argumentos. Apresentamos agora alguns dos cdigos %:
Cdigo %d %f %c %s %% Significado Inteiro Float Caractere String Coloca na tela um %

Vamos entender como este programa funciona. Inicialmente so declaradas duas variveis: uma inteira (Minutos) e uma ponto flutuante (Horas). feita ento uma chamada funo printf(), que coloca uma mensagem na tela. Queremos agora ler um dado que ser fornecido pelo usurio e coloc-lo na varivel Minutos. Para isso usamos a funo scanf(). A string "%d" diz funo que iremos ler um inteiro. O segundo parmetro passado funo diz em que varivel dever ser armazenado o dado lido. importante ressaltar a necessidade de se colocar um & antes do nome da varivel a ser lida quando se usa a funo scanf(). Observe que, no C, quando temos mais de um parmetro para uma funo, eles sero separados por vrgula. Temos ento uma expresso matemtica simples que atribui a Horas o valor de Minutos dividido por 60.0. Como Horas uma varivel float, o compilador far uma converso entre os tipos das variveis (o nmero 60.0 est com este formato para forar esta converso). A segunda chamada funo printf() tem trs argumentos. A string "\n %d minutos equivalem a %f horas.\n" diz funo para dar uma nova linha (passar para a prxima linha), colocar um inteiro (Minutos) na tela, colocar a mensagem " minutos equivalem a ", colocar um ponto flutuante (Horas) na tela, colocar a mensagem " horas." e dar mais uma nova linha. Os outros parmetros so as variveis das quais devem ser lidos os valores. 2.10.1 Exerccio: O que faz o seguinte programa?
#include <stdlib.h> #include <stdio.h> main() { int x; scanf("%d",&x); printf("%d",x); system("pause"); }

Vamos ver alguns exemplos de printf() e o que eles exibem:


printf printf printf printf printf ("Teste %% %%") -> "Teste % %" ("%f",40.345) -> "40.345" ("%c = %d",'D',120) -> "D = 120" ("Veja %s exemplo","este") -> "Veja este exemplo" ("%s%d%%","Juros de ",10) -> "Juros de 10%"

2.8.1

Exerccio:

Escreva um programa que declare seis variveis inteiras e atribua os valores 10, 20, 30, ..., 60 a elas. Declare 6 variveis caracteres e atribua a elas as letras c, o, e, l, h, o. Finalmente, o programa dever imprimir, usando todas as variveis declaradas: As variveis inteiras contm os nmeros: 10,20,30,40,50,60 O animal contido nas variveis caracteres o coelho 2.8.2 Constantes de barra invertida

Para nos facilitar a tarefa de programar, o C utiliza vrios cdigos chamados cdigos de barra invertida. A lista completa dos cdigos de barra invertida dada a seguir:
Cdigo Significado \" Aspas \' Apstrofo \\ Barra invertida \0 Nulo (0 em decimal) \a Sinal sonoro ("beep") \b Retrocesso ("back") Cdigo Significado \f Alimentao de formulrio ("form feed") \n Nova linha ("new line") \t Tabulao horizontal ("tab") \v Tabulao vertical \N Constante octal (N o valor da constante) \xN Constante hexadecimal (N o valor da constante)

V 06 0306

V 06 0306

INFORMTICA APLICADA LINGUAGEM C

INFORMTICA APLICADA LINGUAGEM C #include <stdlib.h> int main () { char Ch; scanf("%c", &Ch); printf ("Voce pressionou a tecla %c\n",Ch); system("pause"); return(0); }

2.11 Caracteres Os caracteres so um tipo de dado: o char. O C trata os caracteres como sendo variveis de um byte (8 bits). Um bit a menor unidade de armazenamento de informaes em um computador. Na linguagem C, tambm podemos usar um char para armazenar valores numricos inteiros, alm de us-lo para armazenar caracteres de texto. Para indicar um caractere de texto usamos apstrofos. Veja um exemplo de programa que usa caracteres:
#include <stdio.h> #include <stdlib.h> int main () { char Ch; Ch='D'; printf ("%c",Ch); system("pause"); return(0); }

A principal diferena da verso que utiliza getch() para a verso que no utiliza getch() que no primeiro caso o usurio simplesmente aperta a tecla e o sistema l diretamente a tecla pressionada. No segundo caso, necessrio apertar tambm a tecla <ENTER>. Lembre-se que, se voc quiser manter a portabilidade de seus programas, no deve utilizar as funes getch e getche, pois estas no fazem parte do padro ANSI C. 2.13 Strings No C uma string um vetor de caracteres terminado com um caractere nulo. O caracter nulo um caractere com valor inteiro igual a zero (cdigo ASCII igual a 0). O caractere nulo tambm pode ser escrito usando a conveno de barra invertida do C como sendo \0. Para declarar uma string podemos usar o seguinte formato geral:
char nome_da_string[tamanho];

No programa acima, %c indica que printf() deve colocar um caractere na tela. Como dito anteriormente, um char tambm usado para armazenar um nmero inteiro. Este nmero conhecido como o cdigo ASCII correspondente ao caractere. Veja o programa abaixo:
#include <stdio.h> #include <stdlib.h> int main () { char Ch; Ch='D'; printf ("%d",Ch); /* Imprime o caracter como inteiro */ system("pause"); return(0); }

Isto declara um vetor de caracteres (uma string) com nmero de posies igual a tamanho. Note que, como temos que reservar um espao para o caractere nulo, temos que declarar o comprimento da string como sendo, no mnimo, um caractere maior que a maior string que pretendemos armazenar. Vamos supor que declaremos uma string de 8 posies e coloquemos a palavra Texto nela. Teremos: T e x t o \0 ... ...

Este programa vai imprimir o nmero 68 na tela, que o cdigo ASCII correspondente ao caractere 'D' (d maisculo). 2.11.1 Exerccio: Escreva um programa que leia um caractere digitado pelo usurio, imprima o caractere digitado e o cdigo ASCII correspondente a este caractere. 2.12 As Funes getch e getche Muitas vezes queremos ler um caractere fornecido pelo usurio. Para isto pode-se utilizar as funes getch() ou getche(). Ambas retornam o caractere pressionado, sendo que getche() imprime o caractere na tela antes de retorn-lo e getch() apenas retorna o caractere pressionado sem imprimilo na tela. Ambas as funes podem ser encontradas na biblioteca conio.h. Eis um exemplo que usa a funo getch():
#include <stdio.h> #include <stdlib.h> #include <conio.h> int main () { char Ch; Ch=getch(); printf ("Voce pressionou a tecla %c\n",Ch); system("pause"); return(0); }

No caso acima, as duas clulas no usadas tm valores indeterminados. Isto acontece porque o C no inicializa variveis, cabendo ao programador esta tarefa. Se quisermos ler uma string fornecida pelo usurio podemos usar a funo gets(). Um exemplo do uso desta funo apresentado abaixo. A funo gets() coloca o terminador nulo na string, quando voc aperta a tecla "Enter".
#include <stdio.h> #include <stdlib.h> int main () { char string[100]; printf ("Digite uma string: "); gets (string); printf ("\n\nVoce digitou %s.\n",string); system("pause"); return(0); }

Neste programa, o tamanho mximo da string que voc pode entrar de 99 caracteres. Se voc entrar com uma string de comprimento maior, o programa ir aceitar, mas os resultados podem ser desastrosos. Como as strings so vetores de caracteres, para se acessar um determinado caracter de uma string, basta usar um ndice para acessar o caracter desejado. Suponha uma string chamada str. Podemos acessar a segunda letra de str da seguinte forma:
str[1] = 'a';

Equivalente para o programa acima, sem usar getch():


#include <stdio.h>

Observe que na linguagem C o ndice comea em zero. Assim, a primeira letra da string sempre estar na posio 0. A segunda letra sempre estar na posio 1 e assim sucessivamente.
V 06 0306 V 06 0306

INFORMTICA APLICADA LINGUAGEM C

INFORMTICA APLICADA LINGUAGEM C

10

Segue um exemplo que imprimir a terceira letra da string "Texto", apresentada acima. Em seguida, ele mudar esta letra e apresentar a nova string no final.
#include <stdio.h> #include <stdlib.h> int main() { char str[10] = "Texto"; printf("\n\nString: %s", str); printf("\nTerceira letra: %c", str[2]); str[2] = 'n'; printf("\nAgora a terceira letra eh: %c", str[2]); printf("\n\nString resultante: %s\n", str); system("pause"); return(0); }

2.14.1 Argumentos Argumentos so as entradas que a funo recebe. atravs dos argumentos que passamos parmetros para a funo. J vimos funes com argumentos. As funes printf() e scanf() so funes que recebem argumentos. Vamos ver um exemplo simples de funo com argumentos:
#include <stdio.h> #include <stdlib.h> void quad(int x) // Calcula o quadrado de x { printf ("O quadrado e %d",(x*x)); } main () { int num; printf ("Entre com um numero: "); scanf ("%d",&num); printf ("\n\n"); quad(num); system("pause"); }

Nesta string, o terminador nulo est na posio 5. Das posies 0 a 5, sabemos que temos caracteres vlidos, e portanto podemos escrev-los. Note a forma como inicializamos a string str com os caracteres 'T' 'e' 'x' 't' 'o' e '\0' simplesmente declarando char str[10] = "Texto". Veremos, posteriormente que "Texto" (uma cadeia de caracteres entre aspas) o que chamamos de string constante, isto , uma cadeia de caracteres que est pr-carregada com valores que no podem ser modificados. J a string str uma string varivel, pois podemos modificar o que nela est armazenado, como de fato fizemos. 2.13.1 Exerccio: Escreva um programa que leia duas strings e as coloque na tela. Imprima tambm a segunda letra de cada string. 2.14 Funes Uma funo um bloco de cdigo que pode ser usado diversas vezes na execuo de um programa. O uso de funes permite que o programa fique mais legvel, e melhor estruturado. Na verdade, um programa em C consiste de vrias funes colocadas juntas. A forma geral de uma funo :
tipo_de_retorno nome_da_funo (lista_de_argumentos) { cdigo_da_funo }

Na definio de quad() dizemos que a funo receber um argumento inteiro x. Quando fazemos a chamada funo, o inteiro num passado como argumento. H alguns pontos a observar. Em primeiro lugar temos de satisfazer aos requisitos da funo quanto ao tipo e a quantidade de argumentos quando a chamamos. Apesar de existirem algumas converses de tipo que o C faz automaticamente, importante ficar atento. Em segundo lugar, no importante o nome da varivel que se passa como argumento, ou seja, a varivel num, ao ser passada como argumento para quad() copiada para a varivel x. Dentro de quad() trabalha-se apenas com x. Se mudarmos o valor de x dentro de quad() o valor de num na funo main() permanece inalterado. Vamos ver um exemplo de funo com mais de uma varivel. Repare que, neste caso, os argumentos so separados por vrgula e que deve ser explicitado o tipo de cada um dos argumentos, um a um. Note tambm que no necessrio que todos os argumentos passados para a funo sejam variveis, porque sero copiados para a varivel de entrada da funo.
#include <stdio.h> #include <stdlib.h> void mult (float a, float b, float c) { printf ("%f",a*b*c); } main () { float x,y; x=23.5; y=12.9; mult (x,y,3.87); system("pause"); } // Multiplica 3 nmeros

Abaixo o tipo mais simples de funo:


#include <stdio.h> #include <stdlib.h> void mensagem () // Funo simples: s imprime o texto { printf ("Informtica "); } main () { mensagem(); printf ("Aplicada\n"); system("pause"); }

2.14.2 Retornando valores Muitas vezes necessrio fazer com que uma funo retorne um valor. As funes que vimos at aqui no retornam nada, pois especificamos um retorno void. Podemos especificar um tipo de retorno indicando-o antes do nome da funo. Mas para dizer ao C o que vamos retornar precisamos da palavra reservada return. Assim fica fcil fazer uma funo para multiplicar dois inteiros e que retorna o resultado da multiplicao. Veja:
#include <stdio.h>

Este programa ter o mesmo resultado que o primeiro exemplo visto. O que ele faz definir uma funo mensagem() que coloca uma string na tela e no retorna nada (void). Depois esta funo chamada a partir de main() (que tambm uma funo).

V 06 0306

V 06 0306

INFORMTICA APLICADA LINGUAGEM C #include <stdlib.h> int prod (int x,int y) { return (x*y); } main () { int saida; saida=prod (12,7); printf ("A saida e: %d\n",saida); system("pause"); }

11

INFORMTICA APLICADA LINGUAGEM C

12

comando. interessante notar que, no caso da declarao ser um bloco de cdigo, no necessrio (e nem permitido) o uso do ; no final do bloco. Isto uma regra geral para blocos de cdigo. Abaixo apresentamos um exemplo:
#include <stdio.h> #include <stdlib.h> int main () { int num; printf ("Digite um numero: "); scanf ("%d",&num); if (num>10) printf ("\n\nO numero e maior que 10"); if (num==10) { printf ("\n\nVoce acertou!\n"); printf ("O numero e igual a 10."); } if (num<10) printf ("\n\nO numero e menor que 10"); system("pause"); return (0); }

Veja que, como prod retorna o valor de 12 multiplicado por 7, este valor pode ser usado em uma expresso qualquer. No programa fizemos a atribuio deste resultado varivel saida, que posteriormente foi impressa usando printf. Uma observao adicional: se no especificarmos o tipo de retorno de uma funo, o compilador C automaticamente supor que este tipo inteiro. Porm, no uma boa prtica no se especificar o valor de retorno. Mais um exemplo de funo, que agora recebe dois floats e tambm retorna um float. Repare que neste exemplo especificamos um valor de retorno para a funo main (int) e retornamos zero. Normalmente isto que fazemos com a funo main, que retorna zero quando ela executada sem qualquer tipo de erro:
#include <stdio.h> #include <stdlib.h> float prod (float x, float y) { return (x*y); } int main () { float saida; saida=prod (45.2,0.0067); printf ("A saida e: %f\n",saida); system("pause"); return(0); }

No programa acima a expresso num>10 avaliada e retorna um valor diferente de zero, se verdadeira, e zero, se falsa. Repare que quando queremos testar igualdades usamos o operador == e no =. Isto porque o operador = representa apenas uma atribuio. Isto pode parecer estranho primeira vista, mas se escrevssemos
if (num=10) ... /* Isto est errado */

o compilador iria atribuir o valor 10 varivel num e a expresso num=10 iria retornar 10, fazendo com que o nosso valor de num fosse adulterado e fazendo com que a declarao fosse executada sempre. Este problema gera erros freqentes entre iniciantes e, portanto, muita ateno deve ser tomada. Os operadores de comparao so:
Operador == != > < >= <= Significado igual diferente maior que menor que maior ou igual menor ou igual

2.14.3 Exerccio: a) Escreva uma funo que some dois inteiros e retorne o valor da soma. 3.1.1 O else

3 ESTRUTURAS DE CONTROLE DE FLUXO


As estruturas de controle de fluxo so fundamentais para qualquer linguagem de programao. Sem elas s haveria uma maneira do programa ser executado: de cima para baixo, comando por comando. No haveria condies, repeties ou saltos. A linguagem C possui diversos comandos de controle de fluxo. possvel resolver todos os problemas sem utilizar todas elas, mas devemos nos lembrar que a elegncia e facilidade de entendimento de um programa dependem do uso correto das estruturas no local certo. 3.1 O Comando if

Podemos pensar no comando else como sendo um complemento do comando if. O comando if completo tem a seguinte forma geral:
if (condio) declarao_1; else declarao_2;

A expresso da condio ser avaliada. Se ela for satisfeita, a declarao_1 ser executada, caso contrrio, a declarao_2 ser executada. importante nunca esquecer que, quando usamos a estrutura if-else, estamos garantindo que uma das duas declaraes ser executada. Nunca sero executadas as duas ou nenhuma delas. Abaixo est um exemplo do uso do if-else que deve funcionar como o programa da seo anterior.
#include <stdio.h> #include <stdlib.h> int main () { int num; printf ("Digite um numero: "); scanf ("%d",&num);

O comando if representa uma tomada de deciso do tipo "SE isto ENTO aquilo". A sua forma geral :
if (condio) declarao;

O comando if avalia a expresso da condio. A declarao ser executada somente se a condio for satisfeita (for verdadeira). A declarao pode ser um bloco de cdigo ou apenas um
V 06 0306

V 06 0306

INFORMTICA APLICADA LINGUAGEM C if (num==10) { printf ("\n\nVoce printf ("O numero } else { printf ("\n\nVoce printf ("O numero } system("pause"); return(0); }

13

INFORMTICA APLICADA LINGUAGEM C if (!num) ....

14

acertou!\n"); e igual a 10.\n");

3.1.4

ifs aninhados

errou!\n"); e diferente de 10.\n");

O if aninhado simplesmente um if dentro da declarao de um outro if externo. O nico cuidado que devemos ter o de saber exatamente a qual if um determinado else est ligado. Vejamos um exemplo:
#include <stdio.h> #include <stdlib.h> int main () { int num; printf ("Digite um numero: "); scanf ("%d",&num); if (num==10) { printf ("\n\nVoce acertou!\n"); printf ("O numero e igual a 10.\n"); } else { if (num>10) { printf ("O numero e maior que 10."); } else { printf ("O numero e menor que 10."); } } system("pause"); return(0); }

3.1.2

O if-else-if

A estrutura if-else-if apenas uma extenso da estrutura if-else. Sua forma geral pode ser escrita como sendo:
if (condio_1) declarao_1; else if (condio_2) declarao_2; else if (condio_3) declarao_3; . . . else if (condio_n) declarao_n; else declarao_default;

Esta estrutura funciona da seguinte maneira: o programa testa as condies at encontrar uma expresso que seja satisfeita. Neste caso ele executa a declarao correspondente. S uma declarao ser executada, ou seja, s ser executada a declarao equivalente primeira condio que for satisfeita. A ltima declarao (default) ser executada no caso de nenhuma condio ser satisfeita, e opcional. Um exemplo desta estrutura:
#include <stdio.h> #include <stdlib.h> int main () { int num; printf ("Digite um numero: "); scanf ("%d",&num); if (num>10) printf ("\n\nO numero e maior que 10"); else if (num==10) { printf ("\n\nVoce acertou!\n"); printf ("O numero e igual a 10."); } else if (num<10) printf ("\n\nO numero e menor que 10"); system("pause"); return(0); }

3.1.5

O Operador ? De uma maneira geral, expresses do tipo:


if (condio) expresso_1; else expresso_2;

podem ser simplificada usando-se o operador ? da seguinte maneira:


condio?expresso_1:expresso_2;

Assim, uma expresso como:


if (a>0) b=-150; else b=150;

3.1.3

A expresso condicional

Quando o compilador avalia uma condio, ele quer um valor de retorno para poder tomar a deciso. Mas esta expresso no necessita ser uma expresso no sentido convencional. Uma varivel sozinha pode ser uma expresso e esta retorna o seu prprio valor. Assim, as seguintes expresses:
int num; if (num!=0) .... if (num==0) ....

pode ser simplificada por:


b=a>0?-150:150;

O operador ? limitado (no atende a uma gama muito grande de casos) mas pode ser usado para simplificar expresses complicadas. Uma aplicao interessante a do contador circular. Veja o exemplo:
#include <stdio.h> #include <stdlib.h> int main() { int index = 0, contador;

equivalem a
int num; if (num) ....

V 06 0306

V 06 0306

INFORMTICA APLICADA LINGUAGEM C char letras[6] = "Texto"; for (contador=0; contador < 1000; contador=contador+1) { printf("\n%c",letras[index]); index=(index==5)? index=0: index=index+1; } system("pause"); }

15

INFORMTICA APLICADA LINGUAGEM C break; case 11: printf ("\n\nO numero e igual a 11.\n"); break; default: printf ("\n\nNao e 9 nem 10 nem 11.\n"); } system("pause"); return(0); }

16

A palavra Texto escrita verticalmente na tela at a varivel contador determinar o trmino do programa. Enquanto isto a varivel index assume os valores 0, 1, 2, 3, 4, 0, 1, ... progressivamente. 3.1.6 Exerccios:

3.3

O Comando for

a) Altere o ltimo exemplo para que ele escreva cada letra 5 vezes seguidas. Para isto, use um if para testar se o contador divisvel por cinco (utilize o operador %) e s ento realizar a atualizao em index. 3.2 O Comando switch

O for a primeira de uma srie de trs estruturas para se trabalhar com loops (laos) de repetio. As outras so while e do. As trs compem a segunda famlia de comandos de controle de fluxo. Podemos pensar nesta famlia como sendo a das estruturas de repetio controlada. O comando for usado para repetir um comando (ou bloco de comandos) diversas vezes, de maneira que se possa ter um bom controle sobre o lao. Sua forma geral :
for (inicializao;condio;incremento) declarao;

O comando if-else e o comando switch so os dois comandos de tomada de deciso. Sem dvida alguma o mais importante dos dois o if, mas o comando switch tem aplicaes valiosas. O comando switch prprio para se testar uma varivel em relao a diversos valores prestabelecidos. Sua forma geral :
switch (varivel) { case constante_1: declarao_1; break; case constante_2: declarao_2; break; . . . case constante_n: declarao_n; break; default declarao_default; }

A declarao no comando for tambm pode ser um bloco ({ }) e neste caso o ; omitido. O melhor modo de se entender o for ver de que maneira ele funciona. O for equivalente a se fazer o seguinte:
inicializao; if (condio) { declarao; incremento; "Volte para o comando if" }

Podemos ver, ento, que o for executa a inicializao e testa a condio. Se a condio for falsa ele no faz mais nada. Se a condio for verdadeira ele executa a declarao, faz o incremento e volta a testar a condio. Ele fica repetindo estas operaes at que a condio seja falsa. Abaixo vemos um programa que coloca os primeiros 100 nmeros inteiros na tela:
#include <stdio.h> #include <stdlib.h> int main () { int cont; for (cont=1;cont<=100;cont=cont+1) printf ("%d ",cont); system("pause"); return(0); }

Podemos fazer uma analogia entre o switch e a estrutura if-else-if apresentada anteriormente. A diferena fundamental que a estrutura switch no aceita expresses, aceita apenas constantes. O switch testa a varivel e executa a declarao cujo case corresponda ao valor atual da varivel. A declarao default opcional e ser executada apenas se a varivel que est sendo testada no for igual a nenhuma das constantes. O comando break faz com que o switch seja interrompido assim que uma das declaraes seja executada. Mas ele no essencial ao comando switch. Se aps a execuo da declarao no houver um break, o programa continuar executando. Isto pode ser til em algumas situaes, mas recomenda-se cuidado. Veremos agora um exemplo do comando switch:
#include <stdio.h> #include <stdlib.h> int main () { int num; printf ("Digite um numero: "); scanf ("%d",&num); switch (num) { case 9: printf ("\n\nO numero e igual a 9.\n"); break; case 10: printf ("\n\nO numero e igual a 10.\n");

Outro exemplo interessante mostrado a seguir: o programa l uma string e conta quantos dos caracteres desta string so iguais letra 'c'
#include <stdio.h> #include <stdlib.h> int main () { char string[100]; /* String, ate' 99 caracteres */ int i, cont; printf("\n\nDigite uma frase: "); gets(string); /* Le a string */ printf("\n\nFrase digitada:\n%s", string); cont = 0; for (i=0; string[i] != '\0'; i=i+1) { if ( string[i] == 'c' ) /* Se for a letra 'c' */ cont = cont +1; /* Incrementa o contador */ } printf("\nNumero de caracteres c = %d", cont); system("pause");

V 06 0306

V 06 0306

INFORMTICA APLICADA LINGUAGEM C return(0); }

17

INFORMTICA APLICADA LINGUAGEM C { long int i; printf("\a"); // Imprime o caracter de alerta (um beep) for (i=0; i<1000000000; i=i+1);// Espera 1000000000 iteracoes printf("\a"); // Novo beep system("pause"); return(0); }

18

Note o teste que est sendo feito no for: o caractere armazenado em string[i] comparado com '\0' (caractere final da string). Caso o caractere seja diferente de '\0', a condio verdadeira e o bloco do for executado. Dentro do bloco existe um if que testa se o caractere igual a 'c'. Caso seja, o contador de caracteres c incrementado. 3.3.1 Exerccios

a) Escreva um programa que coloque os nmeros de 1 a 100 na tela na ordem inversa (comeando em 100 e terminando em 1). b) Escreva um programa que leia uma string, conte quantos caracteres desta string so iguais a 'a' e substitua os que forem iguais a 'a' por 'b'. O programa deve imprimir o nmero de caracteres modificados e a string modificada. O for na linguagem C bastante flexvel. Temos acesso inicializao, condio e ao incremento. Um ponto importante que podemos omitir qualquer um dos elementos do for, isto , se no quisermos uma inicializao poderemos omiti-la. Isto nos permite fazer o que quisermos com o comando, conforme veremos a seguir. 3.3.2 O lao infinito O lao infinito tem a forma
for (inicializao; ;incremento) declarao;

Um problema do cdigo anterior, a dependncia do tempo de espera com a velocidade de processamento do computador. Para gerar um tempo de espera em milisegundos, pode-se utilizar o comando Sleep, da seguinte forma:
Sleep(tempo);

Para utilizar este comando, deve-se incluir a biblioteca windows. Observe que a primeira letra do comando maiscula, e que o tempo deve estar em milisegundos. Por exemplo, para que o programa espere 5 segundos:
#include <stdio.h> #include <stdlib.h> #include <windows.h> // biblioteca onde est o comando Sleep int main () { long int i; printf("\a"); // Imprime o caracter de alerta (um beep) Sleep(5000);// Espera 5 segundos printf("\a"); // Novo beep system("pause"); return(0); }

Este bloco de programa um lao infinito porque ser executado para sempre (no existindo a condio, ela ser sempre considerada verdadeira), a no ser que ele seja interrompido. Para interromper um lao como este usamos o comando break. O comando break vai quebrar o lao infinito e o programa continuar sua execuo normalmente. Como exemplo vamos ver um programa que faz a leitura de uma tecla e sua impresso na tela, at que o usurio aperte uma tecla sinalizadora de final (um FLAG). O nosso FLAG ser a letra 'X'.
#include <stdio.h> #include <stdlib.h> #include <conio.h> int main () { int cont; char ch; for (cont=1; ;cont=cont+1) { ch = getch(); if (ch == 'X') break; printf("\nLetra: %c",ch); } system("pause"); return(0); }

3.3.4

Exerccios

a) Faa um programa que inverta uma string: leia a string com gets e armazene-a invertida em outra string. Use o comando for para varrer a string at o seu final. b) Escreva um programa, utilizando os comandos for e switch, que leia uma string (use gets) e substitua todos os espaos e tabulaes (\t) por caracteres de nova linha (\n). O for deve ser encerrado quando o caracter de final da string (\0) for encontrado. 3.4 O Comando while O comando while tem a seguinte forma geral:
while (condio) declarao;

Assim como fizemos para o comando for, vamos tentar mostrar como o while funciona fazendo uma analogia. Ento o while seria equivalente a:
if (condio) { declarao; "Volte para o comando if" }

3.3.3

O lao sem contedo

Lao sem contedo aquele no qual se omite a declarao. Sua forma geral (ateno ao ponto e vrgula!):
for (inicializao;condio;incremento);

Uma das aplicaes desta estrutura gerar tempos de espera. O programa a seguir faz isto.
#include <stdio.h> #include <stdlib.h> int main ()

Podemos ver que a estrutura while testa uma condio. Se esta for verdadeira, a declarao executada e faz-se o teste novamente, e assim por diante. Assim como no caso do for, podemos fazer um lao infinito. Para tanto basta colocar uma expresso eternamente verdadeira na condio. Pode-se tambm omitir a declarao e fazer um lao sem contedo. No exemplo abaixo, o programa s ir finalizar quuando o usurio digitar a tecla 'q':
#include #include #include int main <stdio.h> <stdlib.h> <conio.h> ()

V 06 0306

V 06 0306

INFORMTICA APLICADA LINGUAGEM C { char Ch; Ch='\0'; while (Ch!='q') { Ch = getch(); } system("pause"); return(0); }

19

INFORMTICA APLICADA LINGUAGEM C

20

3.6

O Comando break

Ns j vimos dois usos para o comando break: interrompendo os comandos switch e for. Na verdade, estes so os dois usos do comando break: ele pode quebrar a execuo de um comando (como no caso do switch) ou interromper a execuo de qualquer lao (for, while ou do while). O break faz com que a execuo do programa continue na primeira linha seguinte ao lao ou bloco que est sendo interrompido. Observe que um break causar uma sada somente do lao mais interno. Por exemplo:
for(t=0; t<100; ++t) { cont=1; for(;;) { printf("%d", cont); cont = cont + 1; if(cont==10) break; } }

3.4.1

Exerccios Refaa o programa anterior. Use o comando while para fechar o loop.

3.5

O Comando do-while A terceira estrutura de repetio que veremos o do-while. De forma geral:
do { declarao; } while (condio);

Mesmo que a declarao seja apenas um comando uma boa prtica deixar as chaves. O ponto-e-vrgula final obrigatrio. Vamos, como anteriormente, ver o funcionamento da estrutura do-while:
declarao; if (condio) "Volta para a declarao"

O cdigo acima imprimir os nmeros de 1 a 10 cem vezes na tela. Toda vez que o break encontrado, o controle devolvido para o lao for externo. Outra observao o fato que um break usado dentro de uma declarao switch afetar somente os dados relacionados com o switch e no qualquer outro lao em que o switch estiver. 3.7 O Comando continue

Vemos pela anlise do bloco acima que a estrutura do-while executa a declarao, testa a condio e, se esta for verdadeira, volta para a declarao. A grande novidade no comando do-while que ele, ao contrrio do for e do while, garante que a declarao ser executada pelo menos uma vez. Um dos usos da estrutura do-while em menus, nos quais voc quer garantir que o valor digitado pelo usurio seja vlido, conforme apresentado abaixo:
#include <stdio.h> #include <stdlib.h> int main () { int i; do { printf ("\n\nEscolha a fruta pelo numero:\n\n"); printf ("\t(1)...Mamao\n"); printf ("\t(2)...Abacaxi\n"); printf ("\t(3)...Laranja\n\n"); scanf("%d", &i); } while ((i<1)||(i>3)); switch (i) { case 1: printf ("\t\tVoce escolheu Mamao.\n"); break; case 2: printf ("\t\tVoce escolheu Abacaxi.\n"); break; case 3: printf ("\t\tVoce escolheu Laranja.\n"); break; } system("pause"); return(0); }

O comando continue pode ser visto como sendo o oposto do break. Ele s funciona dentro de um lao. Quando o comando continue encontrado, o lao pula para a prxima iterao, sem o abandono do lao. O programa abaixo exemplifica o uso do continue:
#include <stdio.h> #include <stdlib.h> int main() { int opcao; while (opcao != 5) { printf("\n\n Escolha uma opcao entre 1 e 5: "); scanf("%d", &opcao); if ((opcao > 5)||(opcao <1)) continue; /* Opcao invalida: volta ao inicio do loop */ switch (opcao) { case 1: printf("\n --> Primeira opcao.."); break; case 2: printf("\n --> Segunda opcao.."); break; case 3: printf("\n --> Terceira opcao.."); break; case 4: printf("\n --> Quarta opcao.."); break; case 5: printf("\n --> Abandonando.."); break; } } system("pause"); return(0); }

O programa acima ilustra uma aplicao simples para o continue. Ele recebe uma opo do usurio. Se esta opo for invlida, o continue faz com que o fluxo seja desviado de volta ao incio do lao. Caso a opo escolhida seja vlida o programa segue normalmente.

V 06 0306

V 06 0306

INFORMTICA APLICADA LINGUAGEM C

21

INFORMTICA APLICADA LINGUAGEM C

22

3.8

O Comando goto

3.8.1

Exerccio

Vamos mencionar o goto apenas para que voc saiba que ele existe. Ele pertence a uma classe parte: a dos comandos de salto incondicional. O goto realiza um salto para um local especificado. Este local determinado por um rtulo. Um rtulo, na linguagem C, uma marca no programa. Voc d o nome que quiser a esta marca. Podemos tentar escrever uma forma geral:
nome_do_rtulo: .... goto nome_do_rtulo; ....

Escreva um programa que pea trs inteiros, correspondentes a dia, ms e ano. Pea os nmeros at conseguir valores que estejam na faixa correta (dia entre 1 e 31, ms entre 1 e 12 e ano entre 1900 e 2100). Verifique se o ms e o nmero de dias esto coerentes (incluindo verificao de anos bissextos). Se estiver tudo certo, imprima o nmero que aquele dia corresponde no ano. Comente seu programa. PS: Um ano bissexto se for divisvel por 4 e no for divisvel por 100, exceto para os anos divisveis por 400, que tambm so bissextos.

Devemos declarar o nome do rtulo, seguido de :, na posio para a qual vamos dar o salto. O goto pode saltar para um rtulo que esteja para frente ou para trs no programa. Uma observao importante que o rtulo e o goto devem estar dentro da mesma funo. Como exemplo do uso do goto vamos reescrever o equivalente ao comando for:
inicializao; inicio: if (condio) { declarao; incremento; goto inicio; }

O comando goto deve ser utilizado com conteno, pois o abuso no seu uso tende a tornar o cdigo confuso. O goto no um comando necessrio, podendo sempre ser substitudo por outras estruturas de controle. Um caso em que ele pode ser til quando temos vrios laos e ifs aninhados e se queira, por algum motivo, sair dos laos e ifs de uma vez. Neste caso, um goto resolve o problema mais elegantemente que vrios breaks, sem contar que os breaks exigiriam muito mais testes. Ou seja, neste caso o goto mais elegante e mais rpido. O exemplo anterior pode ser reescrito usando-se o goto:
#include <stdio.h> #include <stdlib.h> int main() { int opcao; while (opcao != 5) { REFAZ: printf("\n\n Escolha uma opcao entre 1 e 5: "); scanf("%d", &opcao); if ((opcao > 5)||(opcao <1)) goto REFAZ; /* Opcao invalida: volta ao rotulo REFAZ */ switch (opcao) { case 1: printf("\n --> Primeira opcao.."); break; case 2: printf("\n --> Segunda opcao.."); break; case 3: printf("\n --> Terceira opcao.."); break; case 4: printf("\n --> Quarta opcao.."); break; case 5: printf("\n --> Abandonando.."); break; } } system("pause"); return(0); }

V 06 0306

V 06 0306

INFORMTICA APLICADA LINGUAGEM C

23

INFORMTICA APLICADA LINGUAGEM C short int unsigned int float double 100 -30 50000 35678 0.0 23.7 -12.3e-10 12546354334.0 -0.0000034236556

24

4 VARIVEIS, CONSTANTES, OPERADORES E EXPRESSES


H trs lugares nos quais podemos declarar variveis. O primeiro fora de todas as funes do programa. Estas variveis so chamadas variveis globais e podem ser usadas a partir de qualquer lugar no programa. Pode-se dizer que, como elas esto fora de todas as funes, todas as funes as vem. O segundo lugar no qual se pode declarar variveis no incio de um bloco de cdigo. Estas variveis so chamadas locais e s tm validade dentro do bloco no qual so declaradas, isto , s a funo qual ela pertence sabe da existncia desta varivel, dentro do bloco no qual foram declaradas. O terceiro lugar onde se pode declarar variveis na lista de parmetros de uma funo. Mais uma vez, apesar de estas variveis receberem valores externos, estas variveis so conhecidas apenas pela funo onde so declaradas. Veja o programa abaixo:
#include <stdio.h> #include <stdlib.h> int contador; int func1(int j) { ... } int main() { char condicao; int i; for (i=0; ...) { /* Bloco do for */ float f2; ... func1(i); } ... return(0); }

4.1.2

Constantes hexadecimais e octais

Muitas vezes precisamos inserir constantes hexadecimais (base dezesseis) ou octais (base oito) em um programa. O C permite que se faa isto. As constantes hexadecimais comeam com 0x. As constantes octais comeam em 0. Alguns exemplos:
Constante Tipo 0xEF Constante Hexadecimal (8 bits) 0x12A4 Constante Hexadecimal (16 bits) 03212 Constante Octal (12 bits) 034215432 Constante Octal (24 bits)

Portanto nunca escreva 013 achando que o C vai compilar isto como se fosse 13. Na linguagem C 013 diferente de 13! 4.1.3 Constantes strings

J mostramos como o C trata strings. Vamos agora alertar para o fato de que uma string "Joao" na realidade uma constante string. Isto implica, por exemplo, no fato de que 't' diferente de "t", pois 't' um char enquanto que "t" uma constante string com dois chars onde o primeiro 't' e o segundo '\0'. 4.1.4 Operadores Aritmticos e de Atribuio

Os operadores aritmticos so usados para desenvolver operaes matemticas. A seguir apresentamos a lista dos operadores aritmticos do C:
Operador + * / % ++ -Ao Soma (inteira e ponto flutuante) Subtrao ou Troca de sinal (inteira e ponto flutuante) Multiplicao (inteira e ponto flutuante) Diviso (inteira e ponto flutuante) Resto de diviso (de inteiros) Incremento (inteiro e ponto flutuante) Decremento (inteiro e ponto flutuante)

A varivel contador e uma varivel global, e acessvel de qualquer parte do programa. As variveis condio e i, s existem dentro de main(), isto so variveis locais de main. A varivel float f2 um exemplo de uma varivel de bloco, isto , ela somente conhecida dentro do bloco do for, pertencente funo main. A varivel inteira j um exemplo de declarao na lista de parmetros de uma funo (a funo func1). As regras que regem onde uma varivel vlida chamam-se regras de escopo da varivel. H mais dois detalhes que devem ser ressaltados. Duas variveis globais no podem ter o mesmo nome. O mesmo vale para duas variveis locais de uma mesma funo. J duas variveis locais, de funes diferentes, podem ter o mesmo nome sem perigo algum de conflito. 4.1 Constantes

O C possui operadores unrios e binrios. Os unrios agem sobre uma varivel apenas, modificando ou no o seu valor, e retornam o valor final da varivel. Os binrios usam duas variveis e retornam um terceiro valor, sem alterar as variveis originais. A soma um operador binrio, pois pega duas variveis, soma seus valores, sem alterar as variveis, e retorna esta soma. Outros operadores binrios so os operadores - (subtrao), *, / e %. O operador - como troca de sinal um operador unrio que no altera a varivel sobre a qual aplicado, pois ele retorna o valor da varivel multiplicado por -1. O operador / (diviso) quando aplicado a variveis inteiras, nos fornece o resultado da diviso inteira; quando aplicado a variveis em ponto flutuante nos fornece o resultado da diviso "real". Assim seja o seguinte trecho de cdigo:
int a = 17, b = 3; int x, y; float z = 17. , z1, z2; x = a / b; y = a % b; z1 = z / b; z2 = a/b;

Constantes so valores que so mantidos fixos pelo compilador. J usamos constantes neste curso. So consideradas constantes, por exemplo, os nmeros e caracteres como 45.65 ou 'n', etc... 4.1.1 Constantes dos tipos bsicos Abaixo vemos as constantes relativas aos tipos bsicos do C:
Tipo de Dado char int long int Exemplos de Constantes 'b' '\n' '\0' 2 32000 -130 100000 -467

V 06 0306

V 06 0306

INFORMTICA APLICADA LINGUAGEM C

25

INFORMTICA APLICADA LINGUAGEM C != Diferente de

26

ao final da execuo destas linhas, os valores calculados seriam: x = 5, y = 2, z1 = 5.666666 e z2 = 5.0 . Note que na linha correspondente a z2, primeiramente feita uma diviso inteira (pois os dois operandos so inteiros). Somente depois de efetuada a diviso que o resultado atribudo a uma varivel float. Os operadores de incremento e decremento so unrios que alteram a varivel sobre a qual esto aplicados. O que eles fazem incrementar ou decrementar, a varivel sobre a qual esto aplicados, de 1. Ento
x++; x--;

Os operadores relacionais retornam verdadeiro (1) ou falso (0). Para verificar o funcionamento dos operadores relacionais, execute o programa abaixo:
/* Este programa ilustra o funcionamento dos operadores relacionais. */ #include <stdio.h> #include <stdlib.h> int main() { int i, j; printf("\nEntre com dois nmeros inteiros: "); scanf("%d%d", &i, &j); printf("\n%d == %d %d\n", i, j, i==j); printf("\n%d != %d %d\n", i, j, i!=j); printf("\n%d <= %d %d\n", i, j, i<=j); printf("\n%d >= %d %d\n", i, j, i>=j); printf("\n%d < %d %d\n", i, j, i<j); printf("\n%d > %d %d\n", i, j, i>j); system("pause"); return(0); }

so equivalentes a
x=x+1; x=x-1;

Estes operadores podem ser pr-fixados ou ps- fixados. A diferena que quando so prfixados eles incrementam e retornam o valor da varivel j incrementada. Quando so ps-fixados eles retornam o valor da varivel sem o incremento e depois incrementam a varivel. Ento, em
x=23; y=x++;

teremos, no final, y=23 e x=24. Em


x=23; y=++x;

Voc pode notar que o resultado dos operadores relacionais sempre igual a 0 (falso) ou 1 (verdadeiro). Para fazer operaes com valores lgicos (verdadeiro e falso) temos os operadores lgicos:
Operador Ao && AND (E) || OR (OU) ! NOT (NO)

teremos, no final, y=24 e x=24. Uma curiosidade: a linguagem de programao C++ tem este nome pois ela seria um "incremento" da linguagem C padro. A linguagem C++ igual a linguagem C s que com extenses que permitem a programao orientada a objeto, o que um recurso extra. O operador de atribuio do C o =. O que ele faz pegar o valor direita e atribuir varivel da esquerda. Alm disto ele retorna o valor que ele atribuiu. Isto faz com que as seguintes expresses sejam vlidas:
x=y=z=1.5; /* Expressao 1 */ if (k=w) ... /* Expressao 2 */

Usando os operadores relacionais e lgicos podemos realizar uma grande gama de testes. A tabela-verdade destes operadores dada a seguir:
p falso falso verdadeiro verdadeiro q falso verdadeiro falso verdadeiro p AND q falso falso falso verdadeiro p OR q falso verdadeiro verdadeiro verdadeiro

A expresso 1 vlida, pois quando fazemos z=1.5 ela retorna 1.5, que passado adiante. A expresso dois ser verdadeira se w for diferente de zero, pois este ser o valor retornado por k=w. Pense bem antes de usar a expresso dois, pois ela pode gerar erros de interpretao. Voc no est comparando k e w. Voc est atribuindo o valor de w a k e usando este valor para tomar a deciso. 4.1.5 Exerccios a) Diga o resultado das variveis x, y e z depois da seguinte seqncia de operaes:
int x,y,z; x=y=10; z=++x; x=-x; y++; x=x+y-(z--);

O programa a seguir ilustra o funcionamento dos operadores lgicos. Compile-o e faa testes com vrios valores para i e j:
#include <stdio.h> #include <stdlib.h> int main() { int i, j; printf("informe dois nmeros(cada um sendo 0 ou 1): "); scanf("%d%d", &i, &j); printf("%d AND %d %d\n", i, j, i && j); printf("%d OR %d %d\n", i, j, i || j); printf("NOT %d %d\n", i, !i); system("pause"); }

4.2

Operadores Relacionais e Lgicos Os operadores relacionais do C realizam comparaes entre variveis. So eles:
Operador > >= < <= == Ao Maior do que Maior ou igual a Menor do que Menor ou igual a Igual a

Exemplo: No trecho de programa abaixo a operao j++ ser executada, pois o resultado da expresso lgica verdadeiro:
int i = 5, j =7; if ( (i > 3) && ( j <= 7) && ( i != j) ) j++; V AND V AND V = V

V 06 0306

V 06 0306

INFORMTICA APLICADA LINGUAGEM C

27

INFORMTICA APLICADA LINGUAGEM C c= a*b + d/e; c= a*(b+d)/e;

28

Mais um exemplo. O programa abaixo, imprime na tela somente os nmeros pares entre 1 e 100, apesar da variao de i ocorrer de 1 em 1:
/* Imprime os nmeros pares entre 1 e 100. */ #include <stdio.h> #include <stdlib.h> int main() { int i; for(i=1; i<=100; i++) if(!(i%2)) printf("%d ",i); /* o operador de resto */ system("pause"); /* dar falso (zero) quando */ /* usada com nmero par. */ } /* Esse resultado invertido pelo ! */

4.3.1

Converso de tipos em expresses

Quando o C avalia expresses onde temos variveis de tipos diferentes o compilador verifica se as converses so possveis. Se no so, ele no compilar o programa, dando uma mensagem de erro. Se as converses forem possveis ele as faz, seguindo as regras abaixo: Todos os chars e short ints so convertidos para ints. Todos os floats so convertidos para doubles. Para pares de operandos de tipos diferentes: se um deles long double o outro convertido para long double; se um deles double o outro convertido para double; se um long o outro convertido para long; se um unsigned o outro convertido para unsigned. 4.3.2 - Expresses que Podem ser Abreviadas

4.2.1

Operadores Lgicos Bit a Bit

O C permite que se faa operaes lgicas "bit-a-bit" em nmeros. Ou seja, neste caso, o nmero representado por sua forma binria e as operaes so feitas em cada bit dele. Imagine um nmero inteiro de 16 bits, a varivel i, armazenando o valor 2. A representao binria de i, ser: 0000000000000010 (quinze zeros e um nico 1 na segunda posio da direita para a esquerda). Poderemos fazer operaes em cada um dos bits deste nmero. Por exemplo, se fizermos a negao do nmero (operao binria NOT, ou operador binrio ~ em C), isto , ~i, o nmero se transformar em 1111111111111101. As operaes binrias ajudam programadores que queiram trabalhar com o computador em "baixo nvel". As operaes lgicas bit a bit s podem ser usadas nos tipos char, int e long int. Os operadores so:
Operador & | ^ ~ >> << Ao AND OR XOR (OR exclusivo) NOT Deslocamento de bits direita Deslocamento de bits esquerda

O C admite as seguintes equivalncias, que podem ser usadas para simplificar expresses ou para facilitar o entendimento de um programa:
Expresso Original x=x+k; x=x-k; x=x*k; x=x/k; x=x>>k; x=x<<k; x=x&k; etc... Expresso Equivalente x+=k; x-=k; x*=k; x/=k; x>>=k; x<<=k; x&=k;

4.3.3

Encadeando expresses: o operador ,

Os operadores &, |, ^ e ~ so as operaes lgicas bit a bit. A forma geral dos operadores de deslocamento :
valor>>nmero_de_deslocamentos valor<<nmero_de_deslocamentos

O operador , determina uma lista de expresses que devem ser executadas seqencialmente. Em sntese, a vrgula diz ao compilador: execute as duas expresses separadas pela vrgula, em seqncia. O valor retornado por uma expresso com o operador , sempre dado pela expresso mais direita. No exemplo abaixo:
x=(y=2,y+3);

O nmero_de_deslocamentos indica o quanto cada bit ir ser deslocado. Por exemplo, para a varivel i anterior, armazenando o nmero 2:
i << 3;

o valor 2 vai ser atribudo a y, se somar 3 a y e o retorno (5) ser atribudo varivel x. Pode-se encadear quantos operadores , forem necessrios. O exemplo a seguir mostra um outro uso para o operador , dentro de um for:
#include<stdio.h> #include <stdlib.h> int main() { int x, y; for(x=0 , y=0 ; x+y < 100 ; ++x , y++) /* Duas variveis de controle: x e y . Foi atribudo o valor zero a cada uma delas na inicializao do for e ambas so incrementadas na parte de incremento do for */ printf("\n%d ", x+y); /* o programa imprimir os nmeros pares de 2 a 98 */ system("pause"); }

far com que i agora tenha a representao binria: 0000000000010000, isto , o valor armazenado em i passa a ser igual a 16. 4.2.2 Exerccios Diga se as seguintes expresses sero verdadeiras ou falsas:
((10>5)||(5>10)) (!(5==6)&&(5!=6)&&((2>1)||(5<=4)))

4.3

Expresses

Expresses so combinaes de variveis, constantes e operadores. Quando montamos expresses temos que levar em considerao a ordem com que os operadores so executados. Exemplos de expresses:
Anos=Dias/365.25; i = i+3;

4.3.4

Tabela de Precedncias do C

Esta a tabela de precedncia dos operadores em C. Alguns (poucos) operadores ainda no foram estudados, e sero apresentados em aulas posteriores.

V 06 0306

V 06 0306

INFORMTICA APLICADA LINGUAGEM C Maior precedncia () [] ->


! ~ ++ -- . -(unrio) (cast) *(unrio) &(unrio) sizeof */% +<< >> <<= >>= == != & ^ | && || ? = += -= *= /=

29

INFORMTICA APLICADA LINGUAGEM C

30

Quando o C v uma declarao como esta ele reserva um espao na memria suficientemente grande para armazenar o nmero de clulas especificadas em tamanho. Por exemplo, se declararmos:
float exemplo [20];

o C ir reservar 4x20=80 bytes. Estes bytes so reservados de maneira adjacente. Na linguagem C a numerao comea sempre em zero. Isto significa que, no exemplo acima, os dados sero indexados de 0 a 19. Para acess-los vamos escrever:
exemplo[0] exemplo[1] ... exemplo[19]

Menor precedncia

Uma dica aos iniciantes: Voc no precisa saber toda a tabela de precedncias de cor. til que voc conhea as principais relaes, mas aconselhvel que ao escrever o seu cdigo, voc tente isolar as expresses com parnteses, para tornar o seu programa mais legvel. 4.4 Modeladores (Casts)

Mas ningum o impede de escrever:


exemplo[30] exemplo[103]

Um modelador aplicado a uma expresso. Ele fora a mesma a ser de um tipo especificado. Sua forma geral :
(tipo)expresso

Por qu? Porque o C no verifica se o ndice que voc usou est dentro dos limites vlidos. Este um cuidado que voc deve tomar. Se o programador no tiver ateno com os limites de validade para os ndices ele corre o risco de ter variveis sobrescritas ou de ver o computador travar. Bugs terrveis podem surgir. Vamos ver agora um exemplo de utilizao de vetores:
#include <stdio.h> #include <stdlib.h> int main () { int num[100]; /* Declara um vetor de inteiros de 100 posicoes */ int count=0; int totalnums; do { printf ("\nEntre com um numero (-999 p/ terminar): "); scanf ("%d",&num[count]); count++; } while (num[count-1]!=-999); totalnums=count-1; printf ("\n\n\n\t Os nmeros que voc digitou foram:\n\n"); for (count=0;count<totalnums;count++) printf (" %d",num[count]); system("pause"); return(0); }

Um exemplo:
#include <stdio.h> #include <stdlib.h> int main () { int num; float f; num=10; f=(float)num/7; /* Uso do modelador. Fora a transformao de num em um float */ printf ("%f",f); system("pause"); return(0); }

Se no tivssemos usado o modelador no exemplo acima o C faria uma diviso inteira entre 10 e 7. O resultado seria 1 (um) e este seria depois convertido para float mas continuaria a ser 1.0. Com o modelador temos o resultado correto. 4.4.1 Exerccios

Compile o exemplo acima sem usar o modelador, e verifique os resultados. Compile-o novamente usando o modelador e compare a sada com os resultados anteriores.

5 MATRIZES E STRINGS
5.1 Vetores Vetores nada mais so que matrizes unidimensionais. Vetores so uma estrutura de dados muito utilizada. importante notar que vetores, matrizes bidimensionais e matrizes de qualquer dimenso so caracterizadas por terem todos os elementos pertencentes ao mesmo tipo de dado. Para se declarar um vetor podemos utilizar a seguinte forma geral:
tipo_da_varivel nome_da_varivel [tamanho];

No exemplo acima, o inteiro count inicializado em 0. O programa pede pela entrada de nmeros at que o usurio entre com o Flag -999. Os nmeros so armazenados no vetor num. A cada nmero armazenado, o contador do vetor incrementado para na prxima iterao escrever na prxima posio do vetor. Quando o usurio digita o flag, o programa abandona o primeiro loop e armazena o total de nmeros gravados. Por fim, todos os nmeros so impressos. bom lembrar aqui que nenhuma restrio feita quanto quantidade de nmeros digitados. Se o usurio digitar mais de 100 nmeros, o programa tentar ler normalmente, mas o programa os escrever em uma parte no alocada de memria, pois o espao alocado foi para somente 100 inteiros. Isto pode resultar nos mais variados erros no instante da execuo do programa. 5.1.1 Exerccios

Reescreva o exemplo acima, realizando a cada leitura um teste para ver se a dimenso do vetor no foi ultrapassada. Caso o usurio entre com 100 nmeros, o programa dever abortar o loop de leitura automaticamente. O uso do Flag (-999) no deve ser retirado.

V 06 0306

V 06 0306

INFORMTICA APLICADA LINGUAGEM C

31

INFORMTICA APLICADA LINGUAGEM C printf (string);

32

5.2

Strings

Strings so vetores de chars. Nada mais e nada menos. As strings so o uso mais comum para os vetores. Devemos apenas ficar atentos para o fato de que as strings tm o seu ltimo elemento como um \0. A declarao geral para uma string :
char nome_da_string [tamanho];

isto simplesmente imprimir a string. 5.2.2 strcpy Sua forma geral :


strcpy (string_destino,string_origem);

Devemos lembrar que o tamanho da string deve incluir o \0 final. A biblioteca padro do C possui diversas funes que manipulam strings. Estas funes so teis, pois no se pode, por exemplo, igualar duas strings:
string1=string2; /* NAO faca isto */

A funo strcpy() copia a string-origem para a string-destino. Seu funcionamento semelhante ao da rotina apresentada na seo anterior. As funes apresentadas nestas sees esto no arquivo cabealho string.h. A seguir apresentamos um exemplo de uso da funo strcpy():
#include <stdio.h> #include <string.h> #include <stdlib.h> int main () { char str1[100],str2[100],str3[100]; printf ("Entre com uma string: "); gets (str1); strcpy (str2,str1); /* Copia str1 em str2 */ strcpy (str3,"Voce digitou a string "); /* Copia "Voce digitou a string" em str3 */ printf ("\n\n%s%s",str3,str2); system("pause"); return(0); }

Fazer isto um desastre. Quando voc terminar de ler a seo que trata de ponteiros voc entender porqu. As strings devem ser igualadas elemento a elemento. Quando vamos fazer programas que tratam de string muitas vezes podemos fazer bom proveito do fato de que uma string termina com \0 (isto , o nmero inteiro 0). Veja, por exemplo, o programa abaixo que serve para igualar duas strings (isto , copia os caracteres de uma string para o vetor da outra):
#include <stdio.h> #include <stdlib.h> int main () { int count; char str1[100],str2[100]; ..../* Aqui o programa le str1 que sera copiada para str2 */ for (count=0;str1[count];count++) str2[count]=str1[count]; str2[count]='\0'; .... /* Aqui o programa continua */ }

5.2.3

strcat A funo strcat() tem a seguinte forma geral:


strcat (string_destino,string_origem);

A condio no loop for acima baseada no fato de que a string que est sendo copiada termina com \0. Quando o elemento encontrado em str1[count] o \0, o valor retornado para o teste condicional falso (nulo). Desta forma a expresso que vinha sendo verdadeira (no zero) continuamente, torna-se falsa. Vamos ver agora algumas funes bsicas para manipulao de strings. 5.2.1 gets A funo gets() l uma string do teclado. Sua forma geral :
gets (nome_da_string);

A string de origem permanecer inalterada e ser anexada ao fim da string de destino. Um exemplo:
#include <stdio.h> #include <string.h> #include <stdlib.h> int main () { char str1[100],str2[100]; printf ("Entre com uma string: "); gets (str1); strcpy (str2,"Voce digitou a string "); strcat (str2,str1); /* str2 armazenara' Voce digitou a string + o conteudo de str1 */ printf ("\n\n%s",str2); system("pause"); return(0); }

O programa abaixo demonstra o funcionamento da funo gets():


#include <stdio.h> #include <stdlib.h> int main () { char string[100]; printf ("Digite o seu nome: "); gets (string); printf ("\n\n Ola %s",string); system("pause"); return(0); }

5.2.4

strlen Sua forma geral :


strlen (string);

Repare que vlido passar para a funo printf() o nome da string. Voc ver mais adiante porque isto vlido. Como o primeiro argumento da funo printf() uma string tambm vlido fazer:

A funo strlen() retorna o comprimento da string fornecida. O terminador nulo no contado. Isto quer dizer que, de fato, o comprimento do vetor da string deve ser um a mais que o inteiro retornado por strlen(). Um exemplo do seu uso:
#include <stdio.h> #include <string.h> #include <stdlib.h>

V 06 0306

V 06 0306

INFORMTICA APLICADA LINGUAGEM C int main () { int size; char str[100]; printf ("Entre com uma string: "); gets (str); size=strlen (str); printf ("\n\nA string que voce digitou tem tamanho %d",size); return(0); }

33

INFORMTICA APLICADA LINGUAGEM C int i,j,count; count=1; for (i=0;i<20;i++) for (j=0;j<10;j++) { mtrx[i][j]=count; count++; } system("pause"); return(0); }

34

5.2.5

strcmp Sua forma geral :


strcmp (string1,string2);

No exemplo acima, a matriz mtrx preenchida, sequencialmente por linhas, com os nmeros de 1 a 200. Voc deve entender o funcionamento do programa acima antes de prosseguir. 5.3.2 Matrizes de strings

A funo strcmp() compara a string 1 com a string 2. Se as duas forem idnticas a funo retorna zero. Se elas forem diferentes a funo retorna no-zero. Um exemplo da sua utilizao:
#include <stdio.h> #include <string.h> #include <stdlib.h> int main () { char str1[100],str2[100]; printf ("Entre com uma string: "); gets (str1); printf ("\n\nEntre com outra string: "); gets (str2); if (strcmp(str1,str2)) printf ("\n\nAs duas strings so diferentes."); else printf ("\n\nAs duas strings so iguais."); system("pause"); return(0); }

Matrizes de strings so matrizes bidimensionais. Imagine uma string. Ela um vetor. Se fizermos um vetor de strings estaremos fazendo uma lista de vetores. Esta estrutura uma matriz bidimensional de chars. Podemos ver a forma geral de uma matriz de strings como sendo:
char nome_da_varivel [num_de_strings][compr_das_strings];

A surge a pergunta: como acessar uma string individual? Fcil. s usar apenas o primeiro ndice. Ento, para acessar uma determinada string faa:
nome_da_varivel [ndice]

Aqui est um exemplo de um programa que l 5 strings e as exibe na tela:


#include <stdio.h> #include <stdlib.h> int main () { char strings [5][100]; int count; for (count=0;count<5;count++) { printf ("\n\nDigite uma string: "); gets (strings[count]); } printf ("\n\n\nAs strings que voce digitou foram:\n\n"); for (count=0;count<5;count++) printf ("%s\n",strings[count]); system("pause"); return(0); }

5.2.6

Exerccios

Faa um programa que leia quatro palavras pelo teclado, e armazene cada palavra em uma string. Depois, concatene todas as strings lidas numa nica string. Por fim apresente esta como resultado ao final do programa. 5.3 5.3.1 Matrizes Matrizes bidimensionais 5.3.3

J vimos como declarar matrizes unidimensionais (vetores). Vamos tratar agora de matrizes bidimensionais. A forma geral da declarao de uma matriz bidimensional muito parecida com a declarao de um vetor:
tipo_da_varivel nome_da_varivel [altura][largura];

Matrizes multidimensionais O uso de matrizes multidimensionais na linguagem C simples. Sua forma geral :
tipo_da_varivel nome_da_varivel [tam1][tam2] ... [tamN];

muito importante ressaltar que, nesta estrutura, o ndice da esquerda indexa as linhas e o da direita indexa as colunas. Quando vamos preencher ou ler uma matriz no C o ndice mais direita varia mais rapidamente que o ndice esquerda. Mais uma vez bom lembrar que, na linguagem C, os ndices variam de zero ao valor declarado, menos um; mas o C no vai verificar isto para o usurio. Manter os ndices na faixa permitida tarefa do programador. Abaixo damos um exemplo do uso de uma matriz:
#include #include int main { int mtrx <stdio.h> <stdlib.h> () [20][10];

Uma matriz N-dimensional funciona basicamente como outros tipos de matrizes. Basta lembrar que o ndice que varia mais rapidamente o ndice mais direita. 5.3.4 Inicializao

Podemos inicializar matrizes, assim como podemos inicializar variveis. A forma geral de uma matriz com inicializao :
tipo_da_varivel nome_da_varivel {lista_de_valores}; [tam1][tam2] ... [tamN] =

V 06 0306

V 06 0306

INFORMTICA APLICADA LINGUAGEM C

35

INFORMTICA APLICADA LINGUAGEM C

36

A lista de valores composta por valores (do mesmo tipo da varivel) separados por vrgula. Os valores devem ser dados na ordem em que sero colocados na matriz. Abaixo vemos alguns exemplos de inicializaes de matrizes:
float vect [6] = { 1.3, 4.5, 2.7, 4.1, 0.0, 100.1 }; int matrx [3][4] = { 1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11, 12 }; char str [10] = { 'J', 'o', 'a', 'o', '\0' }; char str [10] = "Joao"; char str_vect [3][10] = { "Joao", "Maria", "Jose" };

Mas, lembre-se: o uso descuidado de ponteiros pode levar a srios bugs e a dores de cabea

terrveis.
6.1 Como Funcionam os Ponteiros

O primeiro demonstra inicializao de vetores. O segundo exemplo demonstra a inicializao de matrizes multidimensionais, onde matrx est sendo inicializada com 1, 2, 3 e 4 em sua primeira linha, 5, 6, 7 e 8 na segunda linha e 9, 10, 11 e 12 na ltima linha. No terceiro exemplo vemos como inicializar uma string e, no quarto exemplo, um modo mais compacto de inicializar uma string. O quinto exemplo combina as duas tcnicas para inicializar um vetor de strings. Repare que devemos incluir o ; no final da inicializao. 5.3.5 Inicializao sem especificao de tamanho

Os ints guardam inteiros. Os floats guardam nmeros de ponto flutuante. Os chars guardam caracteres. Ponteiros guardam endereos de memria. Quando voc anota o endereo de um colega voc est criando um ponteiro. O ponteiro este seu pedao de papel. Ele tem anotado um endereo. Qual o sentido disto? Simples. Quando voc anota o endereo de um colega, depois voc vai usar este endereo para ach-lo. O C funciona assim. Voc anota o endereo de algo numa varivel ponteiro para depois usar. Da mesma maneira, uma agenda, onde so guardados endereos de vrios amigos, poderia ser vista como sendo uma matriz de ponteiros no C. Um ponteiro tambm tem tipo. Veja: quando voc anota um endereo de um amigo voc o trata diferente de quando voc anota o endereo de uma firma. Apesar de o endereo dos dois locais ter o mesmo formato (rua, nmero, bairro, cidade, etc.) eles indicam locais cujos contedos so diferentes. Ento os dois endereos so ponteiros de tipos diferentes. No C quando declaramos ponteiros ns informamos ao compilador para que tipo de varivel vamos apont-lo. Um ponteiro int aponta para um inteiro, isto , guarda o endereo de um inteiro. 6.2 Declarando e Utilizando Ponteiros Para declarar um ponteiro temos a seguinte forma geral:
tipo_do_ponteiro *nome_da_varivel;

Podemos, em alguns casos, inicializar matrizes das quais no sabemos o tamanho a priori. O compilador C vai, neste caso verificar o tamanho do que voc declarou e considerar como sendo o tamanho da matriz. Isto ocorre na hora da compilao e no poder mais ser mudado durante o programa, sendo muito til, por exemplo, quando vamos inicializar uma string e no queremos contar quantos caracteres sero necessrios. Alguns exemplos:
char mess [] = "Linguagem C: flexibilidade e poder."; int matrx [][2] = { 1,2,2,4,3,6,4,8,5,10 };

No primeiro exemplo, a string mess ter tamanho 36. Repare que o artifcio para realizar a inicializao sem especificao de tamanho no especificar o tamanho! No segundo exemplo o valor no especificado ser 5. 5.3.6 Exerccios

o asterisco (*) que faz o compilador saber que aquela varivel no vai guardar um valor mas sim um endereo para aquele tipo especificado. Vamos ver exemplos de declaraes:
int *pt; char *temp,*pt2;

a) O que imprime o programa a seguir? Tente entend-lo e responder. A seguir, execute-o e comprove o resultado.
# include <stdio.h> #include <stdlib.h> int main() { int t, i, M[3][4]; for (t=0; t<3; ++t) for (i=0; i<4; ++i) M[t][i] = (t*4)+i+1; for (t=0; t<3; ++t) { for (i=0; i<4; ++i) printf ("%3d ", M[t][i]); printf ("\n"); } system("pause"); return(0); }

O primeiro exemplo declara um ponteiro para um inteiro. O segundo declara dois ponteiros para caracteres. Eles ainda no foram inicializados (como toda varivel do C que apenas declarada). Isto significa que eles apontam para um lugar indefinido. Este lugar pode estar, por exemplo, na poro da memria reservada ao sistema operacional do computador. Usar o ponteiro nestas circunstncias pode levar a um travamento do micro, ou a algo pior. O ponteiro deve ser inicializado (apontado para algum lugar conhecido) antes de ser usado! Isto de suma importncia! Para atribuir um valor a um ponteiro recm-criado poderamos igual-lo a um valor de memria. Mas, como saber a posio na memria de uma varivel do nosso programa? Seria muito difcil saber o endereo de cada varivel que usamos, mesmo porque estes endereos so determinados pelo compilador na hora da compilao e realocados na execuo. Podemos ento deixar que o compilador faa este trabalho por ns. Para saber o endereo de uma varivel basta usar o operador &. Veja o exemplo:
int count=10; int *pt; pt=&count;

6 PONTEIROS
O C altamente dependente dos ponteiros. Para ser um bom programador em C fundamental que se tenha um bom domnio deles. Por isto, recomendvel o aluno ter um carinho especial com esta parte do curso que trata deles. Ponteiros so to importantes na linguagem C que voc j os viu e nem percebeu, pois mesmo para se fazer uma introduo bsica linguagem C precisa-se deles.

Criamos um inteiro count com o valor 10 e um apontador para um inteiro pt. A expresso &count nos d o endereo de count, o qual armazenamos em pt. Simples, no ? Repare que no alteramos o valor de count, que continua valendo 10. Como ns colocamos um endereo em pt, ele est agora liberado para ser usado. Podemos, por exemplo, alterar o valor de count usando pt. Para tanto vamos usar o operador inverso do

V 06 0306

V 06 0306

INFORMTICA APLICADA LINGUAGEM C

37

INFORMTICA APLICADA LINGUAGEM C

38

operador &, que o operador *. No exemplo acima, uma vez que fizemos pt=&count a expresso *pt equivalente ao prprio count. Isto significa que, se quisermos mudar o valor de count para 12, basta fazer *pt=12. Vamos fazer uma pausa e voltar nossa analogia para ver o que est acontecendo. Digamos que exista uma firma. Ela como uma varivel que j foi declarada. Voc tem um papel em branco onde vai anotar o endereo da firma. O papel um ponteiro do tipo firma. Voc ento liga para a firma e pede o seu endereo, o qual voc vai anotar no papel. Isto equivalente, no C, a associar o papel firma com o operador &. Ou seja, o operador & aplicado firma equivalente a voc ligar para a mesma e pedir o endereo. Uma vez de posse do endereo no papel voc poderia, por exemplo, fazer uma visita firma. No C voc faz uma visita firma aplicando o operador * ao papel. Uma vez dentro da firma voc pode copiar seu contedo ou modific-lo. Uma observao importante: apesar do smbolo ser o mesmo, o operador * (multiplicao) no o mesmo operador que o * (referncia de ponteiros). Para comear, o primeiro binrio, e o segundo unrio pr-fixado. Aqui vo dois exemplos de usos simples de ponteiros:
#include <stdio.h> #include <stdlib.h> int main () { int num,valor; int *p; num=55; p=&num; /* Pega o endereco de num */ valor=*p;// Valor e igualado a num de uma maneira indireta printf ("\n\n%d\n",valor); printf ("Endereco para onde o ponteiro aponta: %p\n",p); printf ("Valor da variavel apontada: %d\n",*p); system("pause"); return(0); } #include <stdio.h> #include <stdlib.h> int main () { int num,*p; num=55; p=&num; /* Pega o endereco de num */ printf ("\nValor inicial: %d\n",num); *p=100; /* Muda o valor de num de uma maneira indireta */ printf ("\nValor final: %d\n",num); system("pause"); return(0); }

ponteiro aponta. Isto , se temos um ponteiro para um inteiro e o incrementamos ele passa a apontar para o prximo inteiro. Esta mais uma razo pela qual o compilador precisa saber o tipo de um ponteiro: se voc incrementa um ponteiro char* ele anda 1 byte na memria e se voc incrementa um ponteiro double* ele anda 8 bytes na memria. O decremento funciona semelhantemente. Supondo que p um ponteiro, as operaes so escritas como:
p++; p--;

Mais uma vez insiste-se. Estamos falando de operaes com ponteiros e no de operaes com o contedo das variveis para as quais eles apontam. Por exemplo, para incrementar o contedo da varivel apontada pelo ponteiro p, faz-se:
(*p)++;

Outras operaes aritmticas teis so a soma e subtrao de inteiros com ponteiros. Vamos supor que voc queira incrementar um ponteiro de 15. Basta fazer:
p=p+15; ou p+=15;

E se voc quiser usar o contedo do ponteiro 15 posies adiante:


*(p+15);

A subtrao funciona da mesma maneira. Uma outra operao, s vezes til, a comparao entre dois ponteiros. Mas que informao recebemos quando comparamos dois ponteiros? Bem, em primeiro lugar, podemos saber se dois ponteiros so iguais ou diferentes (== e !=). No caso de operaes do tipo >, <, >= e <= estamos comparando qual ponteiro aponta para uma posio mais alta na memria. Ento uma comparao entre ponteiros pode nos dizer qual dos dois est "mais adiante" na memria. A comparao entre dois ponteiros se escreve como a comparao entre outras duas variveis quaisquer:
p1>p2

Entretanto h operaes que voc no pode efetuar num ponteiro. Voc no pode dividir ou multiplicar ponteiros, adicionar dois ponteiros, adicionar ou subtrair floats ou doubles de ponteiros. 6.2.1 Exerccios a) Explique a diferena entre
p++; (*p)++; *(p++);

O que quer dizer *(p+10);? Explique o que voc entendeu da comparao entre ponteiros b) Qual o valor de y no final do programa? Tente primeiro descobrir e depois verifique no computador o resultado. A seguir, escreva um /* comentrio */ em cada comando de atribuio explicando o que ele faz e o valor da varivel esquerda do '=' aps sua execuo.
#include <stdlib.h> int main() { int y, *p, x; y = 0; p = &y; x = *p; x = 4; (*p)++; x--; (*p) += x; printf ("y = %d\n", y); system("pause"); return(0); }

Nos exemplos acima vemos um primeiro exemplo do funcionamento dos ponteiros. No primeiro exemplo, o cdigo %p usado na funo printf() indica funo que ela deve imprimir um endereo. Podemos fazer algumas operaes aritmticas com ponteiros. A primeira, e mais simples, igualar dois ponteiros. Se tivermos dois ponteiros p1 e p2 podemos igual-los fazendo p1=p2. Repare que estamos fazendo com que p1 aponte para o mesmo lugar que p2. Se quisermos que a varivel apontada por p1 tenha o mesmo contedo da varivel apontada por p2 devemos fazer *p1=*p2. Basicamente, depois que se aprende a usar os dois operadores (& e *) fica fcil entender operaes com ponteiros. As prximas operaes, tambm muito usadas, so o incremento e o decremento. Quando incrementamos um ponteiro ele passa a apontar para o prximo valor do mesmo tipo para o qual o

V 06 0306

V 06 0306

INFORMTICA APLICADA LINGUAGEM C

39

INFORMTICA APLICADA LINGUAGEM C int count; p=matrx[0]; for (count=0;count<2500;count++) { *p=0.0; p++; } system("pause"); return(0); }

40

6.3

Ponteiros e Vetores Veremos nestas sees que ponteiros e vetores tm uma ligao muito forte.

6.3.1

Vetores como ponteiros

Vamos dar agora uma idia de como o C trata vetores. Quando voc declara uma matriz da seguinte forma:
tipo_da_varivel nome_da_varivel [tam1][tam2] ... [tamN];

o compilador C calcula o tamanho, em bytes, necessrio para armazenar esta matriz. Este tamanho :
tam1 x tam2 x tam3 x ... x tamN x tamanho_do_tipo

No primeiro programa, cada vez que se faz matrx[i][j] o programa tem que calcular o deslocamento para dar ao ponteiro. Ou seja, o programa tem que calcular 2500 deslocamentos. No segundo programa o nico clculo que deve ser feito o de um incremento de ponteiro. Fazer 2500 incrementos em um ponteiro muito mais rpido que calcular 2500 deslocamentos completos. H uma diferena entre o nome de um vetor e um ponteiro que deve ser frisada: um ponteiro uma varivel, mas o nome de um vetor no uma varivel. Isto significa, que no se consegue alterar o endereo que apontado pelo "nome do vetor". Seja:
int vetor[10]; int *ponteiro, i; ponteiro = &i; /* as operacoes a seguir sao invalidas */ vetor = vetor + 2; /* ERRADO: vetor nao e' variavel */ vetor++; /* ERRADO: vetor nao e' variavel */ vetor = ponteiro; /* ERRADO: vetor nao e' variavel */

O compilador ento aloca este nmero de bytes em um espao livre de memria. O nome da varivel que voc declarou na verdade um ponteiro para o tipo da varivel da matriz. Este conceito fundamental. Eis porque: Tendo alocado na memria o espao para a matriz, ele toma o nome da varivel (que um ponteiro) e aponta para o primeiro elemento da matriz. Mas a surge a pergunta: ento como que podemos usar a seguinte notao?
nome_da_varivel[ndice]

Isto pode ser facilmente explicado desde que voc entenda que a notao acima absolutamente equivalente a se fazer:
*(nome_da_varivel+ndice)

Agora podemos entender como que funciona um vetor! Vamos ver o que podemos tirar de informao deste fato. Fica claro, por exemplo, porque que, no C, a indexao comea com zero. porque, ao pegarmos o valor do primeiro elemento de um vetor, queremos, de fato, *nome_da_varivel e ento devemos ter um ndice igual a zero. Ento sabemos que:
*nome_da_varivel equivalente a nome_da_varivel[0]

Teste as operaes acima no seu compilador. Ele dar uma mensagem de erro. Alguns compiladores diro que vetor no um Lvalue. Lvalue, significa "Left value", um smbolo que pode ser colocado do lado esquerdo de uma expresso de atribuio, isto , uma varivel. Outros compiladores diro que se tem "incompatible types in assignment", tipos incompatveis em uma atribuio.
/* as operacoes abaixo sao validas */ ponteiro = vetor; /* CERTO: ponteiro e' variavel */ ponteiro = vetor+2; /* CERTO: ponteiro e' variavel */

Outra coisa: apesar de, na maioria dos casos, no fazer muito sentido, poderamos ter ndices negativos. Estaramos pegando posies de memria antes do vetor. Isto explica tambm porque o C no verifica a validade dos ndices. Ele no sabe o tamanho do vetor. Ele apenas aloca a memria, ajusta o ponteiro do nome do vetor para o incio do mesmo e, quando voc usa os ndices, encontra os elementos requisitados. Vamos ver agora um dos usos mais importantes dos ponteiros: a varredura seqencial de uma matriz. Quando temos que varrer todos os elementos de uma matriz de uma forma seqencial, podemos usar um ponteiro, o qual vamos incrementando. Qual a vantagem? Considere o seguinte programa para zerar uma matriz:
#include <stdlib.h> int main () { float matrx [50][50]; int i,j; for (i=0;i<50;i++) for (j=0;j<50;j++) matrx[i][j]=0.0; system("pause"); return(0); }

O que voc aprendeu nesta seo de suma importncia. No siga adiante antes de entend-la bem. 6.3.2 Ponteiros como vetores

Sabemos agora que, na verdade, o nome de um vetor um ponteiro constante. Sabemos tambm que podemos indexar o nome de um vetor. Como conseqncia podemos tambm indexar um ponteiro qualquer. O programa mostrado a seguir funciona perfeitamente:
#include <stdio.h> #include <stdlib.h> int main () { int matrx [10] = { 1, 2, 3, 4, 5, 6, 7, 8, 9, 10 }; int *p; p=matrx; printf ("O terceiro elemento do vetor e: %d",p[2]); system("pause"); return(0); }

Podemos reescrev-lo usando ponteiros:


#include <stdlib.h> int main () { float matrx [50][50]; float *p;

Podemos ver que p[2] equivale a *(p+2). 6.3.3 Strings

Seguindo o raciocnio acima, nomes de strings, so do tipo char*. Isto nos permite escrever a nossa funo StrCpy(), que funcionar de forma semelhante funo strcpy() da biblioteca:
V 06 0306 V 06 0306

INFORMTICA APLICADA LINGUAGEM C #include <stdio.h> #include <stdlib.h> void StrCpy (char *destino,char *origem) { while (*origem) { *destino=*origem; origem++; destino++; } *destino='\0'; } int main () { char str1[100],str2[100],str3[100]; printf ("Entre com uma string: "); gets (str1); StrCpy (str2,str1); StrCpy (str3,"Voce digitou a string "); printf ("\n\n%s%s",str3,str2); system("pause"); return(0); }

41

INFORMTICA APLICADA LINGUAGEM C

42

6.4

Inicializando Ponteiros

Podemos inicializar ponteiros. Vamos ver um caso interessante dessa inicializao de ponteiros com strings. Precisamos, para isto, entender como o C trata as strings constantes. Toda string que o programador insere no programa colocada num banco de strings que o compilador cria. No local onde est uma string no programa, o compilador coloca o endereo do incio daquela string (que est no banco de strings). por isto que podemos usar strcpy() do seguinte modo:
strcpy (string,"String constante.");

strcpy() pede dois parmetros do tipo char*. Como o compilador substitui a string "String constante." pelo seu endereo no banco de strings, tudo est bem para a funo strcpy(). O que isto tem a ver com a inicializao de ponteiros? que, para uma string que vamos usar vrias vezes, podemos fazer:
char *str1="String constante.";

H vrios pontos a destacar no programa acima. Observe que podemos passar ponteiros como argumentos de funes. Na verdade assim que funes como gets() e strcpy() funcionam. Passando o ponteiro voc possibilita funo alterar o contedo das strings. Voc j estava passando os ponteiros e no sabia. No comando while (*origem) estamos usando o fato de que a string termina com \0 como critrio de parada. Quando fazemos origem++ e destino++ o aluno poderia argumentar que estamos alterando o valor do ponteiro-base da string, contradizendo o que recomendei que se deveria fazer, no final de uma seo anterior. O que o aluno talvez no saiba ainda (e que ser estudado em detalhe mais adiante) que, no C, so passados para as funes cpias dos argumentos. Desta maneira, quando alteramos o ponteiro origem na funo StrCpy() o ponteiro str2 permanece inalterado na funo main(). 6.3.4 Endereos de elementos de vetores Nesta seo vamos apenas ressaltar que a notao
&nome_da_varivel[ndice]

A poderamos, em todo lugar que precisarmos da string, usar a varivel str1. Devemos apenas tomar cuidado ao usar este ponteiro. Se o alterarmos, vamos perder a string. Se o usarmos para alterar a string, podemos facilmente corromper o banco de strings que o compilador criou. Mais uma vez fica o aviso: ponteiros so poderosos, mas se usados com descuido, podem ser uma tima fonte de dores de cabea. 6.4.1 Exercicios Escreva a funo
int strend(char *s, char *t)

que retorna 1 (um) se a cadeia de caracteres t ocorrer no final da cadeia s, e 0 (zero) caso contrrio. 6.5 Ponteiros para Ponteiros

Um ponteiro para um ponteiro como se voc anotasse o endereo de um papel que tem o endereo da casa do seu amigo. Podemos declarar um ponteiro para um ponteiro com a seguinte notao:
tipo_da_varivel **nome_da_varivel;

vlida e retorna o endereo do ponto do vetor indexado por ndice. Isto seria equivalente a nome_da_varivel + ndice. interessante notar que, como conseqncia, o ponteiro nome_da_varivel tem o endereo &nome_da_varivel[0], que indica onde na memria est guardado o valor do primeiro elemento do vetor. 6.3.5 Vetores de ponteiros

Algumas consideraes: **nome_da_varivel o contedo final da varivel apontada; *nome_da_varivel o contedo do ponteiro intermedirio. No C podemos declarar ponteiros para ponteiros para ponteiros, ou ento, ponteiros para ponteiros para ponteiros para ponteiros (UFA!) e assim por diante. Para fazer isto (no me pergunte qual a utilidade disto!) basta aumentar o nmero de asteriscos na declaraco. A lgica a mesma. Para acessar o valor desejado apontado por um ponteiro para ponteiro, o operador asterisco deve ser aplicado duas vezes, como mostrado no exemplo abaixo:
#include <stdio.h> #include <stdlib.h> int main() { float fpi = 3.1415, *pf, **ppf; pf = &fpi; /* pf armazena o endereco de fpi */ ppf = &pf; /* ppf armazena o endereco de pf */ printf("%f", **ppf); /* Imprime o valor de fpi */ printf("%f", *pf); /* Tambem imprime o valor de fpi */ system("pause"); return(0); }

Podemos construir vetores de ponteiros como declaramos vetores de qualquer outro tipo. Uma declarao de um vetor de ponteiros inteiros poderia ser:
int *pmatrx [10];

No caso acima, pmatrx um vetor que armazena 10 ponteiros para inteiros. 6.3.6 Exercicios

Fizemos a funo StrCpy(). Faa uma funo StrLen() e StrCat() que funcionem como as funes strlen() e strcat() de string.h respectivamente

V 06 0306

V 06 0306

INFORMTICA APLICADA LINGUAGEM C

43

6.5.1 tela.

Exerccios Verifique o programa abaixo. Encontre o seu erro e corrija-o para que escreva o nmero 10 na
#include <stdio.h> #include <stdlib.h> int main() { int x, *p, **q; p = &x; q = &p; x = 10; printf("\n%d\n", &q); system("pause"); return(0); }

6.6

Cuidados a Serem Tomados ao se Usar Ponteiros

O principal cuidado ao se usar um ponteiro deve ser: saiba sempre para onde o ponteiro est apontando. Isto inclui: nunca use um ponteiro que no foi inicializado. Um pequeno programa que demonstra como no usar um ponteiro:
int main () /* Errado - Nao Execute */ { int x,*p; x=13; *p=x; return(0); }

Este programa compilar e rodar. O que acontecer? Ningum sabe. O ponteiro p pode estar apontando para qualquer lugar. Voc estar gravando o nmero 13 em um lugar desconhecido. Com um nmero apenas, voc provavelmente no vai ver nenhum defeito. Agora, se voc comear a gravar nmeros em posies aleatrias no seu computador, no vai demorar muito para travar o micro (se no acontecer coisa pior). 6.6.1 Exerccios

Escreva um programa que declare uma matriz 100x100 de inteiros. Voc deve inicializar a matriz com zeros usando ponteiros para enderear seus elementos. Preencha depois a matriz com os nmeros de 1 a 10000, tambm usando ponteiros.

V 06 0306

Vous aimerez peut-être aussi