Escolar Documentos
Profissional Documentos
Cultura Documentos
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.
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.
Funes de teste e tratamento de caracteres Funes de uso genrico Funes para controle da tela
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.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; }
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; }
P F F V V
Q F V F V
P AND Q F F F V
P OR Q F V V V
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.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; }
/* 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; }
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.
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; }
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.
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; }
/* 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; }
{ 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; }
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.
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.
30
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
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
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