Você está na página 1de 40

UNIVERSIDADE DO OESTE DE SANTA CATARINA UNOESC Campus Chapec

CURSO DE SISTEMAS DE INFORMAO


LINGUAGEM C
SUMRIO
1 A LINGUAGEM C 2 SINTAXE 2.1 O C "CASE SENSITIVE" 2.2 DIRETIVAS DE COMPILAO #INCLUDE 2.3 PALAVRAS RESERVADAS DO C 2.4 PRIMEIRO PROGRAMA 3 PORTUGOL X LINGUAGEM C 4 INSTRUES DE ENTRADA E SADA 4.1 SCANF() 4.2 PRINTF() 4.3 O TAMANHO E PRECISO DO CAMPO 5 OPERADORES 5.1 OPERADORES ARITMTICOS 5.2 OPERADORES COMBINADOS 5.3 OPERADORES RELACIONAIS 5.4 OPERADORES LGICOS 5.5 OPERADOR TERNRIO 5.6 OPERADOR SIZEOF 5.7 OPERADOR DE MOLDAGEM OU CAST 4 5 5 5 6 6 7 10 10 11 12 13 13 14 14 14 15 15 15

5.8 EXPRESSES 6 ESTRUTURAS DE CONTROLE DE FLUXO 6.1 O COMANDO IF 6.1.1 O COMANDO ELSE 6.1.2 O IF-ELSE-IF 6.1.3 A EXPRESSO CONDICIONAL 6.1.4 IFS ANINHADOS 6.1.5 O OPERADOR ? 6.2 O COMANDO SWITCH 6.3 O COMANDO FOR 6.3.1 O LOOP INFINITO 6.3.2 O LOOP SEM CONTEDO 6.4 O COMANDO WHILE 6.5 O COMANDO DO-WHILE 6.6 O COMANDO BREAK 6.7 O COMANDO CONTINUE 7 VETORES E MATRIZES 7.1 VETORES 7.2 MATRIZES 7.2.1 MATRIZES BIDIMENSIONAIS 7.2.2 INICIALIZAO 8 ALOCAO DINMICA DE MEMRIA 8.1 MALLOC 8.2 CALLOC 8.3 REALLOC 8.4 FREE 8.5 ALOCAO DINMICA DE VETORES E MATRIZES

16 17 17 17 18 19 19 20 21 22 23 23 24 25 26 26 28 28 29 29 30 31 31 31 32 33 34

8.5.1 ALOCAO DINMICA DE VETORES 8.6 ALOCAO DINMICA DE MATRIZES 9 FUNES DIVERSAS 9.1 STDLIB.H 9.2 CTYPE.H 9.3 STRING.H 9.4 MATH.H REFERNCIAS

34 34 36 36 38 39 39 40

1 A LINGUAGEM C
O C nasceu na dcada de 70. Seu inventor, Dennis Ritchie, implementou-o pela primeira vez usando um DEC PDP-11 rodando o sistema operacional UNIX. O C derivado de uma outra linguagem: o B, criado por Ken Thompson. O B, por sua vez, veio da linguagem BCPL, inventada por Martin Richards. 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... bem provvel que o Navegador que voc utiliza tenha sido escrito em C ou C++. Dados histricos:

1969 - Desenvolvimento do UNIX (num PDP 7 em linguagem Assembly); 1969 - Desenvolvimento da linguagem BCPL, prxima do Assembly; 1970 - Desenvolvimento da linguagem B, sucessora da anterior (o B a 1 letra de BCPL); 1971 - Primeiro desenvolvimento da linguagem C, sucessora da anterior (o C a 2 letra de BCPL); 1973 - O sistema operativo UNIX reescrito em linguagem C; 1978 - Primeira edio do livro The C Programming Language, Kernighan & Ritchie; 1983-1988 - Definio do ANSI C;

A linguagem C pode ser considerada como uma linguagem de mdio nvel, pois possui instrues que a tornam ora uma linguagem de alto nvel e estruturada como o Pascal, se assim se fizer necessrio, ora uma linguagem de baixo nvel, pois possui instrues to prximas da mquina, que s o Assembler possui. De fato com a linguagem C podemos construir programas organizados e concisos (como o Pascal), ocupando pouco espao de memria com alta velocidade de execuo (como o Assembler). Infelizmente, dada toda a flexibilidade da linguagem, tambm poderemos escrever programas desorganizados e difceis de serem compreendidos. Devemos lembrar que a linguagem C foi desenvolvida a partir da necessidade de se escrever programas que utilizassem recursos prprios da linguagem de mquina de uma forma mais simples e portvel que o assembler. A inmeras razes para a escolha da linguagem C como a predileta para os desenvolvedores profissionais. As caractersticas abaixo serviro para mostrar o porqu de sua ampla utilizao. Caractersticas da Linguagem C:

Portabilidade entre mquinas e sistemas operacionais. Dados compostos em forma estruturada. Programas Estruturados. Total interao com o Sistema Operacional. Cdigo compacto e rpido, quando comparado ao cdigo de outras linguagens de complexidade anloga.

Pergunta: 1. Se voc fosse desenvolver um vrus qual linguagem seria utilizada?

2 SINTAXE
A sintaxe so regras detalhadas para cada construo vlida na linguagem C. Estas regras esto relacionadas com os tipos, as declaraes, as funes e as expresses. Os tipos definem as propriedades dos dados manipulados em um programa. A linguagem C disponibiliza quatro tipos bsicos que podem ser utilizados para a declarao de variveis: Tipo Descrio Bytes Intervalo de valores char Um nico caracter 1 0 a 255 int Nmeros inteiros (sem casas decimais) 4 -2147483648 a +2147483647 float Nmeros em ponto flutuantes com preciso simples 4 3,4.10-38 a 3,4.1038 (7 casas decimais) double Nmeros em ponto flutuante com preciso dupla (15 8 3,4.10-4932 a 1,1.10-4932 casas decimais) As declaraes expressam as partes do programa, podendo dar significado a um identificador, alocar memria, definir contedo inicial, definir funes. As funes especificam as aes que um programa executa quando roda. A determinao e alterao de valores definidas nas expresses, que so combinaes de variveis, constantes e operadores. As funes so as entidades operacionais bsicas dos programas em C, que por sua vez so a unio de uma ou mais funes executando cada qual o seu trabalho. H funes bsicas que esto definidas na biblioteca C. As funes printf() e scanf() por exemplo, permitem respectivamente escrever na tela e ler os dados a partir do teclado. O programador tambm pode definir novas funes em seus programas, como rotinas para clculos, impresso, etc. Todo programa C inicia sua execuo chamando a funo main(), sendo obrigatria a sua declarao no programa principal. Comentrios no programa so colocados entre /* e */ no sendo considerados na compilao. Cada instruo encerra com ; (ponto e vrgula) que faz parte do comando.

2.1 O C "CASE SENSITIVE"


importante ressaltar um ponto de suma importncia: o C "Case Sensitive", isto , maisculas e minsculas fazem diferena. Se declarar uma varivel com o nome soma ela ser diferente de Soma, SOMA, SoMa ou sOmA. Da mesma maneira, os comandos do C if e for, por exemplo, s podem ser escritos em minsculas, pois seno o compilador no ir interpret-los como sendo comandos, mas sim como variveis.

2.2 DIRETIVAS DE COMPILAO #INCLUDE


As diretivas dizem ao compilador para incluir na compilao do programa outros arquivos, geralmente estes arquivos contem bibliotecas de funes ou rotinas do prprio C ou do usurio. Sua sintaxe geral : #include "nome_do_arquivo" ou #include <nome_do_arquivo> Arquivo Descrio: Nome do arquivo stdio.h string.h math.h Descries das funes Funes de entrada e sada (I/O) Funes de tratamento de strings Funes matemticas

ctype.h stdlib.h conio.h

Funes de teste e tratamento de caracteres Funes de uso genrico Funes para controle da tela

2.3 PALAVRAS RESERVADAS DO C


Todas as linguagens de programao tm palavras reservadas. As palavras reservadas no podem ser usadas a no ser nos seus propsitos originais, isto , no podemos declarar funes ou variveis com os mesmos nomes. Como o C "case sensitive" podemos declarar uma varivel For, apesar de haver uma palavra reservada for, mas isto no uma coisa recomendvel de se fazer, pois pode gerar confuso. Apresentamos a seguir as palavras reservadas do ANSI C. Veremos o significado destas palavras chave medida que o curso for progredindo: auto break case char const continue default do double else enum extern float for goto if int long register return short signed sizeof static struct switch typedef union unsigned void volatile while

2.4 PRIMEIRO PROGRAMA


Vejamos um primeiro programa em C: /*Um Primeiro Programa */ #include <stdio.h> int main () { printf ("Ola! Eu estou vivo!\n"); return 0; }

3 PORTUGOL X LINGUAGEM C
Portugol Programa Inicio Fim Var Escreva Leia Para Enquanto Inteiro Real Caracter Literal E Ou Negar menor Maior Maior igual menor igual Igual Incremento Decremento Atribuio Caso Comentrio se condio entao para i de 1 ate 10 faca enquanto condicao faca Pascal Program Begin End Var Write Read For While Integer Real Char String And Or Not < > >= <= = inc ou (valor := (valor + 1)) dec ou (valor := (valor - 1)) := Case {} ou // if condicao then for i:=0 to 10 do while (condicao) do Units (Delphi) CORPO GERAL DO PROGRAMA PORTUGOL Algoritmo NOME // Funo : // Autor : // Data : // Seo de Declaraes var inicio // Seo de Comandos fimalgoritmo LINGUAGEM C #include <stdio.h> // Funo : // Autor : /* Data : */ // Seo de Declaraes globais int main() { // Seo de Declaraes locais // Seo de Comandos } C main { } printf scanf for while int float char char[] && || ! < > >= <= == ++ -= ou -> switch /* *\ if (condicao) for(i=1;i <= 10;i = i + 1) while (condicao) #include

OBS: Vejam acima que em C podemos ter duas sesses de declaraes e no necessria a utilizao da palavra var. DECLARAO DAS VARIVEIS PORTUGOL var A : inteiro B: real C: literal LINGUAGEM C int A; float B; double B; char C; char C[10]; COMANDO CONDICIONAL SE PORTUGOL se condicao entao // Seo de Comandos //Escopo dos Comando fimse } COMANDO CONDICIONAL SE SENAO PORTUGOL se condicao entao // Seo de Comandos VERDADEIROS //Escopo dos Comando VERDADEIROS senao // Seo de Comandos FALSOS //Escopo dos Comando FALSOS fimse } else { // Seo de Comandos FALSOS //Escopo dos Comando FALSOS } LINGUAGEM C if (condicao) { // Seo de Comandos VERDADEIROS //Escopo dos Comando VERDADEIROS LINGUAGEM C if (condicao) { // Seo de Comandos //Escopo dos Comando

COMANDO CONDICIONAL ESCOLHA PORTUGOL escolha VARIAVEL caso 1 // Seo de Comandos caso 1 //Escopo dos Comando caso 1 caso 2 // Seo de Comandos caso 2 //Escopo dos Comando caso 2 outrocaso // Seo de Comandos caso outrocaso //Escopo dos Comando caso outrocaso fimescolha LINGUAGEM C switch (VARIAVEL) { case 1: // Seo de Comandos caso 1 //Escopo dos Comando caso 1 break; case 2: // Seo de Comandos caso 2 //Escopo dos Comando caso 2 break; default: // Seo de Comandos caso default //Escopo dos Comando caso default }

COMANDO REPETICAO PARA FACA PORTUGOL para i de 1 ate 10 faca // Seo de Comandos //Escopo dos Comandos fimpara } COMANDO REPETICAO ENQUANTO FACA PORTUGOL enquanto condicao faca // Seo de Comandos //Escopo dos Comandos fimenquanto } COMANDO REPETICAO REPITA ATE PORTUGOL repita // Seo de Comandos //Escopo dos Comandos ate condicao }while(condicao) LINGUAGEM C do { // Seo de Comandos //Escopo dos Comandos LINGUAGEM C while (codicao) { // Seo de Comandos //Escopo dos Comandos LINGUAGEM C for (i = 0; i < 10; i ++) { // Seo de Comandos //Escopo dos Comandos

4 INSTRUES DE ENTRADA E SADA


O objetivo de escrevermos programas em ltima anlise, a obteno de resultados (Sadas) depois da elaborao de clculos ou pesquisas (Processamento) atravs do fornecimento de um conjunto de dados ou informaes conhecidas (Entradas). Para que nosso programa possa receber dados e aloc-los em variveis, que sero responsveis por armazenar as informaes iniciais, nossa linguagem dever conter um conjunto de instrues que permitam ao operador interagir com o programa fornecendo os dados quando estes forem necessrios.

4.1 SCANF()
Uma das mais importantes e poderosas instrues servir basicamente para promover leitura de dados (tipados) via teclado. Sua forma geral ser: scanf(string de controle, lista de argumentos); A string de controle assumir os valores bsicos listados a seguir: %c - leitura de caracter %d - leitura de nmeros inteiros %f - leitura de nmeros reais %s - leitura de caracteres, ou seja, string A lista de argumentos deve conter exatamente o mesmo nmero de argumentos quantos forem os cdigos de formatao na <string de controle>. Se este no for o caso, diversos problemas podero ocorrer - incluindo at mesmo a queda do sistema - quando estivermos utilizando programas compilados escritos em C. Felizmente ao utilizarmos o C, apenas uma mensagem de erro ser apresentada, para que possamos corrigir o programa sem outros inconvenientes. Cada varivel a ser lida, dever ser precedida pelo caracter &. Para seqncia de caracteres (%s), o caracter & no dever ser usado. 10

A tabela abaixo exibe outras funes que podem ser utilizadas para entrada de dados, ou seja funes de leitura: Funo Operao getchar ( ) l um caractere; getche ( ) l um caractere; getch ( ) l um caractere; putchar ( ) Imprime um caractere na tela; gets ( ) l uma string via teclado; puts ( ) Imprime uma string na tela;

! Devido forma como a funo scanf trata o buffer (rea de armazenamento temporria) de entrada, quando
ela for utilizada em conjunto com as demais funes de leitura aconselhvel sempre limpar este buffer com fflush(stdin);

4.2 PRINTF()
O Comando printf, segue o mesmo padro de scanf(), porm destinado a apresentao dos dados, enquanto aquele destina-se a leitura dos dados. outro dos mais poderosos recursos da linguagem C, printf() servir basicamente para a apresentao de dados no monitor. Sua forma geral ser: printf(string de controle, lista de argumentos); Necessariamente voc precisar ter tantos argumentos quantos forem os comandos de formatao na string de controle. Se isto no ocorrer, a tela exibir sujeira ou no exibir qualquer dado. Os caracteres a serem utilizados pelo printf() em sua <string de controle>, no momento sero os mesmos de scanf(). Tabela contendo cdigos de formatao para printf e scanf: Cdigo printf scanf %d imprime um inteiro decimal l um inteiro decimal %f ponto decimal flutuante l um numero com ponto flutuante %lf ponto flutuante l um nmero com ponto flutuante %s string de caracteres l uma string de caracteres %c um nico caractere l um nico caractere %i decimal l um inteiro decimal %p imprime um ponteiro l um ponteiro %e notao cientifica l um numero com ponto flutuante %% imprime % na tela Observemos o quadro de operadores especiais suportados por printf() Cdigo Significado \b Retrocesso (BackSpace) \f Salto de Pgina (Form Feed) \n Linha Nova (Line Feed) \r Retorno de carro (cr) \a Caracter de alerta (beep)

11

/* Exemplo de programa em C*/ #include <stdio.h> int main() { printf("Programa C muito simples\n"); return 0; } /* Exemplo l e Mostra Idade */ #include <sdtio.h> int main() { int idade; char nome[30]; printf(Digite sua Idade: ); scanf(%d,&idade); printf(Seu Nome: ); scanf(%s,nome); /* Strings no utilizar & na leitura */ printf(%s sua idade e %d anos. \n, nome, idade); return 0; }

4.3 O TAMANHO E PRECISO DO CAMPO


O tamanho do campo indica quantas posies da sada sero utilizados para exibir o valor correspondente um especificador de formato. O tamanho do campo determinado colocando-se um nmero entre o % e o caracter indicador do formato. Por exemplo, %5d indica que o valor a ser impresso vai ocupa 5 posies na tela. Por padro, as posies em excesso so preenchidas com brancos e o valor alinhado direita do campo. Se o tamanho do campo for precedido por um smbolo - (menos), ento o valor ser alinhado esquerda do campo. Se o tamanho do campo for precedido com o smbolo 0 (zero), ento as posies excedentes so preenchidas com zeros. Sempre que o tamanho do campo for insuficiente para exibir o valor solicitado, este tamanho ignorado. Desta forma um valor nunca truncado. Para valores em ponto-flutuante, pode-se definir o nmero de casas decimais a serem impressas, colocandose o um ponto (.) e outro nmero depois do tamanho do campo. Por exemplo, o formato %10.2f, exibe o valor em ponto-flutuante com duas casas decimais, dentro de um campo de tamanho 10. Se esta mesma lgica for utilizada com strings (formato %s), o valor antes do ponto continua indicando a tamanho do campo, porm a segunda parte limitar o nmero mximo de caracteres da string a serem impressos.

12

5 OPERADORES
5.1 OPERADORES ARITMTICOS
So utilizados para efetuar as operaes aritmticas com os seus operandos. Estes operandos podem ser utilizados com qualquer tipo de dados, exceto o resto da diviso, o qual no pode ter operandos em ponto flutuante. Operador Descrio = Atribuio + Soma Subtrao * Multiplicao / Diviso (se os dois valores forem int, o resultado no ter casas decimais) % Resto da diviso inteira ++ Incremento pr ou ps-fixado -Decremento pr ou ps-fixado /* Exemplo utilizando diversos operadores aritmticos */ #include <stdio.h> int main() { int a,b,c; a=b=c=2; b= ++a; c= b++; printf("a:%d\nb:%d\nc:%d\n", a, b, --c); retrun 0; } /* Exemplo: Dado um nmero, calcule seu quadrado. */ #include <sdtio.h> int main() { int numero; printf(Digite um Numero: ); scanf(%d,&numero); printf(O %d elevado ao quadrado resulta em %d. \n,numero,numero*numero); return 0; } Ateno especial deve ser dada operao de diviso. Numa operao onde tanto o dividendo como o divisor forem valores inteiros o resultado perder as casas decimais, independente do tipo da varivel ao qual estar sendo atribudo.

13

/* Exemplo destacando os cuidados com as operaes e variveis relacionadas diviso */ #include <stdio.h> int main(void) { int dividendo=10, divisor=3; float quociente=0.0; quociente = dividendo / divisor; printf("%d/%d = %.2f\n", dividendo, divisor, quociente); return 0; }

5.2 OPERADORES COMBINADOS


Sempre que em um programa C aparece uma expresso onde o resultado da operao est sendo atribuda para o seu primeiro operando (da esquerda), conforme o formato x = x op y; esta expresso pode ser reduzida para o formato x op= y; Expresso Normal Expresso Simplificada a = a + b; a+=b; a = a - b; a-=b; a = a * b; a*=b; a = a / b; a/=b; a = a % b; a%=b;

5.3 OPERADORES RELACIONAIS


Os operadores expresses. Operador > >= < <= == != relacionais so utilizados em expresses condicionais para a comparao do valor de duas Descrio Maior que Maior ou igual Menor que Menor ou igual Igual Diferente de

5.4 OPERADORES LGICOS


Os operadores lgicos so utilizados para conectar expresses lgicas sendo geralmente utilizados em expresses condicionais. Operador Descrio && AND lgico || OR lgico ! NOT lgico Usando os operadores lgicos podemos realizar uma grande gama de testes. A tabela-verdade destes operadores dada a seguir: 14

P F F V V

Q F V F V

P AND Q F F F V

P OR Q F V V V

5.5 OPERADOR TERNRIO


O nome deste operador deve-se ao fato que ele possui 3 (trs) operandos. O primeiro uma expresso condicional que ser avaliada (testada). Se esta condio for verdadeira, o segundo operando utilizado (o valor que est aps o ponto de interrogao). Se a condio for falsa, ser utilizado o terceiro operando (o ltimo valor, aps o dois-pontos ) Sintaxe: (condio)?valor1:valor2 /* Exemplo demonstrando a utilizao do operador ternrio */ #include <stdio.h> int main() { int n1, n2, maior; printf("Digite dois valores:\n"); scanf("%d\n%d", &n1, &n2); maior = (n1>n2)?n1:n2; printf("O maior e' %d\n", maior); fflush(stdin); return 0; }

5.6 OPERADOR SIZEOF


Este operador retorna o tamanho em bytes ocupado na memria pela expresso ou pelo tipo indicado. O tamanho de uma varivel nunca depende do seu contedo armazenado, mas apenas do tipo com o qual ela foi declarada. O tamanho de um arranjo igual a soma do tamanho de seus elementos. Sintaxe: sizeof(expresso) ou sizeof(tipo) Exemplo: int r, x=100, vet[3]; r = sizeof(x); /* r recebe 4 (int -> 4 bytes) */ r = sizeof(double); /* r recebe 8 (double -> 8 bytes) */ r = sizeof(vet); /* r recebe 12 (3*4 -> 12) */

5.7 OPERADOR DE MOLDAGEM OU CAST


Colocando-se o nome de um tipo de dados entre parnteses esquerda de uma expresso, fora-se aquela expresso a assumir o tipo indicado, isto , converte-se o valor naquele ponto do programa. Quando utilizado com varivel, o tipo dela no modificado, apenas o seu valor temporariamente convertido. 15

Sintaxe: (tipo) expresso /* Exemplo utilizando moldagem (cast) */ #include <stdio.h> int main() { int dividendo=10, divisor=3; float quociente=0.0; quociente = (float)dividendo / divisor; printf("%d/%d = %.2f\n", dividendo, divisor, quociente); return 0; }

5.8 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, conforme a tabela de precedncia vista abaixo: Maior precedncia () [] -> ! ~ ++ -- . -(unrio) (cast) *(unrio) &(unrio) sizeof */% +<< >> <<= >>= == != & ^ | && || ? = += -= *= /= , Menor precedncia Exemplos de expresses: Anos=Dias/365.25; i = i+3; c= a*b + d/e; c= a*(b+d)/e;

16

6 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.

6.1 O COMANDO IF
J introduzimos o comando if. Sua forma geral : if (condio) declarao; A expresso, na condio, ser avaliada. Se ela for zero, a declarao no ser executada. Se a condio for diferente de zero a declarao ser executada. /* Exemplo do uso do comando if */ #include <stdio.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"); return 0; }

6.1.1 O comando else


Podemos pensar no comando else como sendo um complemento do comando if: if (condio) declarao_1; else declarao_2; A expresso da condio ser avaliada. Se ela for diferente de zero a declarao 1 ser executada. Se for zero 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. 17

/* Exemplo anterior utilizando else */ #include <stdio.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 { printf ("\n\nVoce errou!\n"); printf ("O numero e diferente de 10.\n"); } return 0; }

6.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; A estrutura acima funciona da seguinte maneira: o programa comea a testar as condies comeando pela 1 e continua a testar at que ele ache uma expresso cujo resultado d diferente de zero. Neste caso ele executa a declarao correspondente. S uma declarao ser executada, ou seja, s ser executada a declarao equivalente primeira condio que der diferente de zero. A ltima declarao (default) a que ser executada no caso de todas as condies darem zero e opcional. /* Um exemplo da estrutura acima */ #include <stdio.h> int main () { 18

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"); return 0; }

6.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. Isto quer dizer que teremos as seguintes expresses: int num; if (num!=0) .... if (num==0) .... for (i = 0; string[i] != '\0'; i++) equivalem a int num; if (num) .... if (!num) .... for (i = 0; string[i]; i++) Isto quer dizer que podemos simplificar algumas expresses simples.

6.1.4 ifs aninhados


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. /* Exemplo utilizando ifs aninhados */ #include <stdio.h> int main () { int num; printf ("Digite um numero: "); scanf ("%d",&num); if (num==10) { 19

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."); } } return 0; }

6.1.5 O Operador ?
Uma expresso como: if (a>0) b=-150; else b=150; pode ser simplificada usando-se o operador ? da seguinte maneira: b=a>0?-150:150; De uma maneira geral expresses do tipo: if (condio) expresso_1; else expresso_2; podem ser substitudas por: condio?expresso_1:expresso_2; 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. /* Exemplo do comando ? */ #include <stdio.h> int main() { int index = 0, contador; char letras[5] = "Joao"; for (contador=0; contador < 1000; contador++) { 20

printf("\n%c",letras[index]); (index==3) ? index=0: ++index; } Return 0; } O nome Joao escrito na tela verticalmente at a varivel contador determinar o trmino do programa. Enquanto isto a varivel index assume os valores 0, 1, 2, 3, , 0, 1, ... progressivamente.

6.2 O COMANDO SWITCH


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. Mais uma vez vale lembrar que devemos usar o comando certo no local certo. Isto assegura um cdigo limpo e de fcil entendimento. O comando switch prprio para se testar uma varivel em relao a diversos valores pr-estabelecidos. 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; } Podemos fazer uma analogia entre o switch e a estrutura if-else-if j visto acima. 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 eu recomendo cuidado. /* Exemplo do comando switch */ #include <stdio.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"); 21

break; case 10: printf ("\n\nO numero e igual a 10.\n"); break; case 11: printf ("\n\nO numero e igual a 11.\n"); break; default: printf ("\n\nO numero nao e nem 9 nem 10 nem 11.\n"); } return 0; }

6.3 O COMANDO FOR


for a primeira de uma srie de trs estruturas para se trabalhar com loops 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. Como j foi dito, o loop for usado para repetir um comando, ou bloco de comandos, diversas vezes, de maneira que se possa ter um bom controle sobre o loop. Sua forma geral : for (inicializao;condio;incremento) declarao; O melhor modo de se entender o loop for ver como ele funciona "por dentro". O loop 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 incondicionalmente 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. Um ponto importante que podemos omitir qualquer um dos elementos do for, isto , se no quisermos uma inicializao poderemos omiti-la. Abaixo vemos um programa que coloca os primeiros 100 nmeros inteiros na tela: /* Exemplo que coloca os primeiros 100 nmeros inteiros na tela */ #include <stdio.h> int main () { int count; for (count=1; count<=100; count++) printf ("%d ",count); return 0; } 22

Note que, no exemplo acima, h uma diferena em relao ao exemplo anterior. O incremento da varivel count feito usando o operador de incremento que ns agora j conhecemos. Esta a forma usual de se fazer o incremento (ou decremento) em um loop for. O for na linguagem C bastante flexvel. Temos acesso inicializao, condio e ao incremento. Qualquer uma destas partes do for pode ser uma expresso qualquer do C, desde que ela seja vlida. Isto nos permite fazer o que quisermos com o comando. As trs formas do for abaixo so vlidas: for ( count = 1; count < 100 ; count++) { ... } for (count = 1; count < NUMERO_DE_ELEMENTOS ; count++) { ... } for (count = 1; count < BusqueNumeroDeElementos() ; count+=2) { ... } Preste ateno ao ltimo exemplo: o incremento est sendo feito de dois em dois. Alm disto, no teste est sendo utilizada uma funo (BusqueNumeroDeElementos() ) que retorna um valor que est sendo comparado com count.

6.3.1 O loop infinito


O loop infinito tem a forma: for (inicializao; ;incremento) declarao; Este loop chama-se loop 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 loop como este usamos o comando break. O comando break vai quebrar o loop 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 usuario aperte uma tecla sinalizadora de final (um FLAG). O nosso FLAG ser a letra 'X'. Repare que tivemos que usar dois scanf() dentro do for. Um busca o caractere que foi digitado e o outro busca o outro caracter digitado na seqncia, que o caractere correspondente ao <ENTER> */ #include <stdio.h> int main () { int Count; char ch; printf(" Digite uma letra - <X para sair> "); for (Count=1;;Count++) { scanf("%c", &ch); if (ch == 'X') break; printf("\nLetra: %c \n",ch); scanf("%c", &ch); } return 0; }

6.3.2 O loop sem contedo


Loop sem contedo aquele no qual se omite a declarao. Sua forma geral (ateno ao ponto e vrgula!): 23

for (inicializao;condio;incremento); Uma das aplicaes desta estrutura gerar tempos de espera. /* Exemplo de gerao de tempo de espera */ #include <stdio.h> int main () { long int i; printf("\a"); /* Imprime o caracter de alerta (um beep) */ for (i=0; i<10000000; i++); /* Espera 10.000.000 de iteracoes */ printf("\a"); /* Imprime outro caracter de alerta */ return 0; }

6.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" } Podemos ver que a estrutura while testa uma condio. Se esta for verdadeira a declarao executada e fazse o teste novamente, e assim por diante. Assim como no caso do for, podemos fazer um loop infinito. Para tanto basta colocar uma expresso eternamente verdadeira na condio. Pode-se tambm omitir a declarao e fazer um loop sem contedo. Vamos ver um exemplo do uso do while. /* Exemplo executa enquanto i for menor que 100. */ #include <stdio.h> int main () { int i = 0; while ( i < 100) { printf(" %d", i); i++; } return 0; } 24

/* Exemplo espera o usurio digitar a tecla 'q' e s depois finaliza */ #include <stdio.h> int main () { char Ch; Ch='\0'; while (Ch!='q') { scanf("%c", &Ch); } return 0; }

6.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 "por dentro": declarao; if (condio) "Volta para a declarao" 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 extrutura do-while em menus, nos quais voc quer garantir que o valor digitado pelo usurio seja vlido, conforme exemplo */ #include <stdio.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) 25

{ 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; } return 0; }

6.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 loop (como no caso do for, do while ou do do while). O break faz com que a execuo do programa continue na primeira linha seguinte ao loop 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) { count=1; for(;;) { printf("%d", count); count++; if(count==10) break; } } 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.

6.7 O COMANDO CONTINUE


O comando continue pode ser visto como sendo o oposto do break. Ele s funciona dentro de um loop. Quando o comando continue encontrado, o loop pula para a prxima iterao, sem o abandono do loop, ao contrrio do que acontecia no comando break. /* Exemplo usando do continue */ #include <stdio.h> int main() { 26

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; } } return 0; } O programa acima ilustra uma aplicao simples para o continue. Ele recebe uma opo do usuario. Se esta opo for invlida, o continue faz com que o fluxo seja desviado de volta ao incio do loop. Caso a opo escolhida seja vlida o programa segue normalmente.

27

7 VETORES E MATRIZES
7.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]; 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 contgua. 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] Mas ningum o impede de escrever: exemplo[30] exemplo[103] 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 sobreescritas ou de ver o computador travar. Bugs terrveis podem surgir. Vamos ver agora um exemplo de utilizao de vetores: /*Exemplo do uso de vetor na linguagem C */ #include <stdio.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++) 28

printf (" %d",num[count]); return(0); } 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 a 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.

7.2 MATRIZES 7.2.1 Matrizes bidimensionais


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]; 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. /*Exemplo do uso de uma matriz*/ #include <stdio.h> int main () { int mtrx [20][10]; int i,j,count; count=1; for (i=0;i<20;i++) for (j=0;j<10;j++) { mtrx[i][j]=count; count++; printf("\nLinha:%d Col:%d INT:%d",i,j,mtrx[i][j]); } return(0); } No exemplo acima, a matriz mtrx preenchida, seqencialmente por linhas, com os nmeros de 1 a 200. Voc deve entender o funcionamento do programa acima antes de prosseguir.

29

7.2.2 Inicializao
Podemos inicializar matrizes, assim como podemos inicializar variveis. A forma geral de uma matriz como inicializao : tipo_da_varivel nome_da_varivel [tam1][tam2] ... [tamN] = {lista_de_valores}; 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" }; 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.

7.2.2.1 Inicializao sem especificao de tamanho


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.

30

ALOCAO DINMICA DE MEMRIA

A alocao dinmica permite ao programador alocar memria para variveis quando o programa est sendo executado. Assim, poderemos definir, por exemplo, um vetor ou uma matriz cujo tamanho descobriremos em tempo de execuo. O padro C ANSI define apenas 4 funes para o sistema de alocao dinmica, disponveis na biblioteca stdlib.h: No entanto, existem diversas outras funes que so amplamente utilizadas, mas dependentes do ambiente e compilador. Aqui sero abordadas somente estas funes padronizadas.

8.1 MALLOC
A funo malloc() serve para alocar memria e tem o seguinte prottipo: void *malloc (unsigned int num); A funao toma o nmero de bytes que queremos alocar ( num), aloca na memria e retorna um ponteiro void * para o primeiro byte alocado. O ponteiro void * pode ser atribudo a qualquer tipo de ponteiro. Se no houver memria suficiente para alocar a memria requisitada a funo malloc() retorna um ponteiro nulo. Veja um exemplo de alocao dinmica com malloc(): #include <stdio.h> #include <stdlib.h> /* Para usar malloc() */

int main (void) { int *p; int a; int i; /* Determina o valor de a em algum lugar */ p=(int *)malloc(a*sizeof(int)); /* Aloca a nmeros inteiros p pode agora ser tratado como um vetor com a posies */ if (!p) { printf ("** Erro: Memoria Insuficiente **"); exit; } for (i=0; i<a ; i++) /* p pode ser tratado como um vetor com a posicoes */ p[i] = i*i; return 0; } No exemplo acima, alocada memria suficiente para se armazenar a nmeros inteiros. O operador sizeof() retorna o nmero de bytes de um inteiro. Ele util para se saber o tamanho de tipos. O ponteiro void* que malloc() retorna convertido para um int* pelo cast e atribudo a p. A declarao seguinte testa se a operao foi bem sucedida. Se no tiver sido, p ter um valor nulo, o que far com que !p retorne verdadeiro. Se a operao tiver sido bem sucedida, podemos usar o vetor de inteiros alocados normalmente, por exemplo, indexando-o de p[0] a p[(a-1)].

8.2 CALLOC
31

A funo calloc() tambm serve para alocar memria, mas possui um prottipo um pouco diferente: void *calloc (unsigned int num, unsigned int size); A funao aloca uma quantidade de memria igual a num * size, isto , aloca memria suficiente para um vetor de num objetos de tamanho size. Retorna um ponteiro void * para o primeiro byte alocado. O ponteiro void * pode ser atribudo a qualquer tipo de ponteiro. Se no houver memria suficiente para alocar a memria requisitada a funo calloc() retorna um ponteiro nulo. Veja um exemplo de alocao dinmica com calloc(): #include <stdio.h> #include <stdlib.h> /* Para usar calloc() */

int main () { int *p; int a; int i; /* Determina o valor de a em algum lugar */ p=(int *)calloc(a,sizeof(int)); /* Aloca a nmeros inteiros p pode agora ser tratado como um vetor com as posicoes*/ if (!p) { printf ("** Erro: Memoria Insuficiente **"); exit; } for (i=0; i<a ; i++)/* p pode ser tratado como um vetor com a posicoes */ p[i] = i*i; return 0; } No exemplo acima, alocada memria suficiente para se colocar a nmeros inteiros. O operador sizeof() retorna o nmero de bytes de um inteiro. Ele util para se saber o tamanho de tipos. O ponteiro void * que calloc() retorna convertido para um int * pelo cast e atribudo a p. A declarao seguinte testa se a operao foi bem sucedida. Se no tiver sido, p ter um valor nulo, o que far com que !p retorne verdadeiro. Se a operao tiver sido bem sucedida, podemos usar o vetor de inteiros alocados normalmente, por exemplo, indexando-o de p[0] a p[(a-1)].

8.3 REALLOC
A funo realloc() serve para realocar memria e tem o seguinte prottipo: void *realloc (void *ptr, unsigned int num); A funao modifica o tamanho da memria previamente alocada apontada por *ptr para aquele especificado por num. O valor de num pode ser maior ou menor que o original. Um ponteiro para o bloco devolvido porque realloc() pode precisar mover o bloco para aumentar seu tamanho. Se isso ocorrer, o contedo do bloco antigo copiado no novo bloco, e nenhuma informao perdida. Se ptr for nulo, aloca size bytes e devolve um ponteiro; se size zero, a memria apontada por ptr liberada. Se no houver memria suficiente para a alocao, um ponteiro nulo devolvido e o bloco original deixado inalterado. 32

#include <stdio.h> #include <stdlib.h>

/* Para usar malloc() e realloc*/

int main () { int *p; int a; int i; /* Determina o valor de a em algum lugar */ a = 30; p=(int *)malloc(a*sizeof(int)); /* Aloca a nmeros inteiros p pode agora ser tratado como um vetor com a posicoes*/ if (!p) { printf ("** Erro: Memoria Insuficiente **"); exit; } for (i=0; i<a ; i++) /* p pode ser tratado como um vetor com a posicoes */ p[i] = i*i; /* O tamanho de p deve ser modificado, por algum motivo ... */ a = 100; p = realloc (p, a*sizeof(int)); for (i=0; i<a ; i++)/* p pode ser tratado como um vetor com a posicoes */ p[i] = a*i*(i-6); return 0; }

8.4 FREE
Quando alocamos memria dinamicamente necessrio que ns a liberemos quando ela no for mais necessria. Para isto existe a funo free() cujo prottipo : void free (void *p); Basta ento passar para free() o ponteiro que aponta para o incio da memria alocada. Mas voc pode se perguntar: como que o programa vai saber quantos bytes devem ser liberados? Ele sabe pois quando voc alocou a memria, ele guardou o nmero de bytes alocados numa "tabela de alocao" interna. Vamos reescrever o exemplo usado para a funo malloc() usando o free() tambm agora: #include <stdio.h> #include <stdlib.h> /* Para usar malloc e free */

int main () { int *p; int a; p=(int *)malloc(a*sizeof(int)); if (!p) { printf ("** Erro: Memoria Insuficiente **"); 33

exit; } free(p); return 0; }

8.5 ALOCAO DINMICA DE VETORES E MATRIZES 8.5.1 Alocao Dinmica de Vetores


Um exemplo de implementao para vetor real fornecido a seguir: #include <stdlib.h> #include <stdio.h> int main() { int *vet; int i,tam; printf("Entre com o tamanho do vetor: "); scanf("%d",&tam); //Aloca memoria conforme o tamanho desejado vet = (int*) malloc(tam * sizeof(int)); //Se vet ficar null no foi possvel alocar a memria desejada if (vet == 0) { printf("No foi possvel alocar a memria desejada.\n"); exit(1); } //Entrada do vetor for(i = 0;i < tam;i++) { printf("Entre com vetor[%d]: ",i); scanf("%d",&vet[i]); fflush(stdin); } //Exibe o vetor for(i = 0;i < tam;i++) printf("Vetor[%d] = %d\n",i,vet[i]); free(vet); return 0; }

8.6 ALOCAO DINMICA DE MATRIZES


A alocao dinmica de memria para matrizes realizada da mesma forma que para vetores, com a diferena que teremos um ponteiro apontando para outro ponteiro que aponta para o valor final, ou seja um ponteiro para ponteiro, o que denominado indireo mltipla. A indireo mltipla pode ser levada a qualquer dimenso desejada, mas raramente necessrio mais de um ponteiro para um ponteiro. Um exemplo de implementao para matriz real bidimensional fornecido a seguir. A estrutura de dados utilizada neste exemplo composta por um vetor de ponteiros (correspondendo ao primeiro ndice da 34

matriz), sendo que cada ponteiro aponta para o incio de uma linha da matriz. Em cada linha existe um vetor alocado dinamicamente, como descrito anteriormente (compondo o segundo ndice da matriz). void main (void) { float **mat; //matriz a ser alocada int l, c; //Numero de linhas e colunas da matriz int i, j; mat = (float **) calloc (m, sizeof(float *)); //Um vetor de m ponteiros para float if (mat == 0) { printf("No foi possvel alocar a memria desejada.\n"); exit(1); } //Aloca as colunas da matriz for ( i = 0; i < m; i++ ) { mat[i] = (float*) calloc (n, sizeof(float)); //m vetores de n floats if (mat[i] == 0) { printf("No foi possvel alocar a memria desejada.\n"); exit(1); } } for (i = 0; i < l; i++) for ( j = 0; j < c; j++) mat[i][j] = i+j; for (i=0; i<m; i++) free (v[i]); //libera as linhas da matriz free (v); //libera a matriz (vetor de ponteiros) }

35

9 FUNES DIVERSAS
Como visto nos capitulos iniciais a linguagem C oferece diversas bibliotecas de funes j implementadas, ou seja, prontas para serem usadas. As bibliotecas em C funcionam quase da mesma forma que as units do Delphi, ou seja, para utilizar as funes deve-se declarar elas no cabealho do programa.

9.1 STDLIB.H
Funo exit: void exit(int codigo_retorno); Esta funo provoca a concluso imediata e anormal do programa. Retorno igual a 0 ira informar ao sistema operacional um trmino de programa normal. Qualquer outro resultado ir indicar trmino com erro. Funo abs: int abs(int num); Esta funo converte os nmeros digitados pelo usurio em seus valores absolutos. Funo div: div_t div(int numerador,int denominador); A funo div() retorna o resto da diviso. Esta funo pode ser utilizada para determinar se um numero par ou no. Utilize no numerador o nmero que se deseja verificar e no denominador utiliza 2. /*Exemplo utilizando div*/ #include <stdio.h> #include <stdlib.h> main() { int a; div_t num; printf("Entre com o numerador: "); scanf("%d",&a); num = div(a,2); if (num.rem == 0) printf("Numero par"); else printf("Numero impar"); } Funo atof: double atof (const char *str); Esta funo converte a string apontada por str em um valor double e retorna o resultado. A string deve conter um nmero em ponto flutuante vlido. Funo atoi: int atoi (const char *str); Esta funo converte a string apontada por str em um valor int e retorna o resultado. A string deve conter um nmero inteiro vlido. Funo atol: int atol (const char *str); Esta funo converte a string apontada por str em um valor long int e retorna o resultado. A string deve conter um inteiro longo vlido. Funo qsort: void qsort (void *buf, size_t num, size_t size, int(*compare)(const void *, const void *)); 36

Esta funo ordena a matriz apontada por buf, usando quicksort. A funo apontada por compare usada para comparar um elemento da matriz com a chave. A forma compare deve ser: int compare (const void *arg1, const void arge)); A funo pode ter o nome que vc quiser. No entanto ela deve devolver os seguintes valores: Se arg1 menor que arg2, devolve menor que zero. Se arg1 igual a arg2, devolve zero. Se arg1 maior que arg2 maior que zero. /*Exemplo utilizando qsort*/ #include <stdlib.h> #include <stdio.h> int num[10] = { 1, 3, 6, 5, 8, 7, 9, 6, 2, 0 }; int comp(const void *, const void *); void main(void) { int i; printf("Matriz original: "); for(i=0; i<10; i++) printf("%d ", num[i]); qsort(num, 10, sizeof(int), comp); printf("\nMatriz ordenada: "); for(i=0; i<10; i++) printf("%d ", num[i]); } /* compara os inteiro */ comp(const void *i, const void *j) { return *(int *)i - *(int *)j; } Funo rand: int rand(void); Esta funo gera uma seqncia de nmeros randmicos. /*Exemplo utilizando rand*/ #include <stdlib.h> #include <stdio.h> void main(void) { int i; for(i=0; i<10; i++) 37

printf("%d ", rand()); } Funo srand: int srand(unsigned seed); Esta funo estabelece um ponto de partida para seqncia randmica gerada por rand(). Esta funo geralmente usada para permitir que os programas usem seqncias diferentes a cada chamada de rand. Funo system: int system(const char *str); Esta funo passa a string apontada p str como um comando para o processador de comandos do sistema operacional. /*Exemplo utilizando system*/ #include <stdlib.h> void main(void) { system("dir"); }

9.2 CTYPE.H
Funo isalnum: int isalnum (int ch); Esta funo devolve um valor diferente de zero se o argumento for uma letra ou um dgito. Funo isalpha: int isalpha (int ch); Esta funo devolve um valor diferente de zero se ch for uma letra do alfabeto, caso contrrio, devolver zero. Funo ispunct: int ispunct (int ch); Esta funo devolve um valor diferente de zero se ch um caracter de pontuao, caso contrrio, devolver zero. Funo isspace: int isspace (int ch); Esta funo devolve um valor diferente de zero se ch for um espao, caso contrrio, devolver zero. Funo islower: int islower (int ch); Esta funo devolve um valor diferente de zero se ch uma letra minscula, caso contrrio, devolve zero. Funo isupper: int isupper (int ch); Esta funo devolve um valor diferente de zero se ch uma letra maiscula, caso contrrio, devolve zero. Funo tolower: int tolower (int ch); Esta funo devolve o equivalente minsculo de ch se ch uma letra caso contrrio, ch devolvido sem alterao. Funo toupper: int toupper (int ch); Esta funo devolve o equivalente maisculo de ch se ch uma letra caso contrrio, ch devolvido sem alterao. Funo isupper: int isupper (int ch); 38

Esta funo devolve um valor diferente de zero se ch uma letra maiscula, caso contrrio, devolve zero.

9.3 STRING.H
Funo strcat: char *strcat(char *str1, const char *str2); Esta funo concatena uma cpia de str2 em str1 com um nulo. /*Este exemplo concatena as strings s1 e s2. Suponha que seja digitado alo e aqui o resultado ser aquialo*/ #include <stdio.h> #include <string.h> void main(void) { char s1[80], s2[80]; gets(s1); gets(s2); strcat(s2, s1); printf(s2); } Funo strcmp: int *strcmp(char *str1, const char *str2); Esta funo compara duas strings e devolve um inteiro baseado no resultado. Menor que zero: str1 menor que str2. Zero: str1 igual a str2. Maior que zero: str1 maior que str2. Funo strcpy: int *strcpy(char *str1, const char *str2); Esta funo copia o contedo de str2 em str1. str2 deve ser um ponteiro para uma string terminada com um nulo.

9.4 MATH.H
Funo cos: double cos(double arg); Esta funo devolve o co-seno de arg. O valor de arg deve estar em radianos. Funo sin: double sin(double arg); Esta funo devolve o seno de arg. O valor de arg deve estar em radianos. Funo tan: double tant(double num); Esta funo devolve a tangente de arg. Funo pow: double pow(double base, doubl exp); Esta funo devolve base elevada a potncia exp. Funo sqrt: double sqrt(double num); Esta funo devolve a raiz quadrada de num.

39

Referncias
HTTP.Apostila Linguagem C. Disponvel em http://vitoria.upf.br/~brusso/progc. Acesso em 10 de Junho de 2003.

40

Você também pode gostar