Sunteți pe pagina 1din 105

Linguagem de Programao

Fonte: http://www.apostilando.com Adaptado por Prof. Marcelo Assis

LINGUAGEM C

LINGUAGEM C

2/105

LINGUAGEM C

Sumrio
1. INTRODUO....................................................................................................................................9 1.1 VISO GERAL DE UM PROGRAMA C......................................................................................................9 2. ESTRUTURA BSICA DE UM PROGRAMA EM C..................................................................10 2.1 BIBLIOTECAS.................................................................................................................................10 3. TIPOS DE DADOS............................................................................................................................11 3.1 ENUMERAO................................................................................................................................12 3.2 MODIFICADORES DE TIPO DE ACESSO.................................................................................................13 3.2.1 Const...........................................................................................................................................13 3.2.2 Volatile.......................................................................................................................................13 3.3 CONSTANTES.................................................................................................................................13 3.4 CONSTANTES PR-DEFINIDAS.............................................................................................................14 3.5 AS BIBLIOTECAS DISPONVEIS E ALGUMAS FUNES INTERESSANTES...........................................................14 4. COMANDO DE ESCRITA..............................................................................................................17 4.1 MODIFICADORES DE SADA...............................................................................................................18 4.2 EXERCCIOS ..................................................................................................................................19 5. VARIVEIS.......................................................................................................................................20 5.1 NOME DE VARIVEIS......................................................................................................................20 5.2 DECLARAO DE VARIVEIS.............................................................................................................20 5.2.1 Tipos de Declaraes de Variveis...........................................................................................20
5.2.1.1 Variveis locais..................................................................................................................................21 5.2.1.2 Parmetros Formais...........................................................................................................................21 5.2.1.3 Variveis Globais...............................................................................................................................21

5.3 PALAVRAS RESERVADAS...................................................................................................................22 6. OPERADORES..................................................................................................................................23 6.1 ATRIBUIO..................................................................................................................................23 6.1.1 Converso de Tipos em Atribuies..........................................................................................23 6.2 OPERADORES ARITMTICOS..............................................................................................................24 6.2.1 Incremento e Decremento..........................................................................................................24 6.2.2 Operadores Aritmticos de Atribuio......................................................................................25 6.3 OPERADORES RELACIONAIS E LGICOS...............................................................................................25 6.4 OPERADORES BIT A BIT..................................................................................................................25 6.5 OPERADOR ?.................................................................................................................................26 6.6 OPERADORES DE PONTEIROS & E *....................................................................................................26 6.7 OPERADOR VRGULA.......................................................................................................................27 6.8 EXPRESSES ..................................................................................................................................27 6.8.1 Converso de Tipos em Expresses...........................................................................................27 6.8.2 Casts...........................................................................................................................................28 6.8.3 Espacejamento e Parnteses......................................................................................................28 7. ALGUMAS FUNES DE E/S ......................................................................................................30 7.1 FUNO SCANF()............................................................................................................................30 7.2 FUNO GETCHE() E GETCH()............................................................................................................31 7.3 LENDO E ESCREVENDO CARACTERES...................................................................................................31 7.4 EXERCCIOS...................................................................................................................................32 8. COMANDOS CONDICIONAIS......................................................................................................33

3/105

LINGUAGEM C 8.1 COMANDO IF..................................................................................................................................33 8.2 COMANDO SWITCH..........................................................................................................................33 8.3 EXERCCIOS...................................................................................................................................34 9. COMANDOS REPITITIVOS OU LAOS....................................................................................36 9.1 LAO FOR.....................................................................................................................................36 9.2 LAO WHILE..................................................................................................................................36 9.3 LAO DO-WHILE.............................................................................................................................37 9.4 COMANDOS BREAK, CONTINUE E EXIT()...............................................................................................37 9.5 EXERCCIOS...................................................................................................................................38 10. FUNES........................................................................................................................................40 10.1 LOCALIZAO DAS FUNES...........................................................................................................41 10.1.1 Corpo da funo antes do programa principal (no mesmo arquivo).....................................41 10.1.2 Corpo da funo depois do programa principal (no mesmo arquivo)...................................41 10.1.3 Corpo da funo escrito em arquivo separado.......................................................................42 10.2 ARGUMENTOS PARA FUNO MAIN().................................................................................................43 10.3 PROTTIPO DE FUNES.................................................................................................................43 10.4 RETORNO DE PONTEIROS................................................................................................................43 10.5 NMEROS DE PARMETROS VARIVEL...............................................................................................44 10.5.1 Funes para nmero varivel de argumentos.......................................................................44 10.6 CLASSES DE ARMAZENAMENTO.......................................................................................................45 10.6.1 Classe de Armazenamento - auto............................................................................................45 10.6.2 Classe de Armazenamento - extern.........................................................................................45 10.6.3 Classe de Armazenamento - static...........................................................................................46
10.6.3.1 Variveis Locais static.....................................................................................................................46 10.6.3.2 Variveis Globais static...................................................................................................................46

10.6.4 Classe de Armazenamento - register.......................................................................................46 10.7 DIRETIVA #DEFINE........................................................................................................................46 10.8 FUNES RECURSIVAS...................................................................................................................47 10.9 EXERCCIOS.................................................................................................................................47 11. VETORES E MATRIZES..............................................................................................................48 11.1 INICIALIZAO DE VETORES E MATRIZES..........................................................................................48 11.2 MATRIZES E VETORES COMO ARGUMENTO DE FUNES........................................................................49 11.3 LIMITES .....................................................................................................................................49 11.4 STRINGS......................................................................................................................................50 11.4.1 Leitura de Strings.....................................................................................................................50
11.4.1.1 Funo scanf().................................................................................................................................50 11.4.1.2 Funo gets()...................................................................................................................................51

11.4.2 Escrita de Strings.....................................................................................................................51 11.4.3 Funes de Manipulao de Strings.......................................................................................52


11.4.3.1 11.4.3.2 11.4.3.3 11.4.3.4 11.4.3.5 11.4.3.6 Funo Funo Funo Funo Funo Funo 11.4.2.1 Funo printf().................................................................................................................................51 11.4.2.2 Funo puts()...................................................................................................................................51 strlen().................................................................................................................................52 strcat().................................................................................................................................52 strcmp()...............................................................................................................................53 strcpy()................................................................................................................................53 strchr().................................................................................................................................53 strstr()..................................................................................................................................53

11.4.4 Exemplo Geral.........................................................................................................................53 11.5 EXERCCIOS.................................................................................................................................54 12. PONTEIROS....................................................................................................................................56 12.1 EXPRESSES COM PONTEIROS..........................................................................................................56 12.1.1 Atribuio de Ponteiros...........................................................................................................56

4/105

LINGUAGEM C 12.1.2 Aritmtica de Ponteiros...........................................................................................................57 12.2 INICIALIZAO DE PONTEIROS..........................................................................................................57 12.2.1 Comparao de Ponteiros.......................................................................................................58 12.3 PONTEIROS E MATRIZES.................................................................................................................58 12.3.1 Matrizes de Ponteiros..............................................................................................................59 12.3.2 Acessando partes de Matrizes como vetores...........................................................................60 12.4 INDIREO MLTIPLA....................................................................................................................60 12.5 PONTEIROS PARA FUNES.............................................................................................................61 12.6 MAIS SOBRE DECLARAES DE PONTEIROS........................................................................................62 12.7 EXERCCIOS.................................................................................................................................64 13. ESTRUTURAS E UNIES............................................................................................................65 13.1 ESTRUTURAS................................................................................................................................65 13.1.1 Inicializando Estruturas...........................................................................................................66 13.1.2 Estruturas Aninhadas...............................................................................................................66 13.1.3 Estruturas e funes.................................................................................................................67 13.1.4 Vetor de Estruturas..................................................................................................................68 13.1.5 Ponteiros para Estruturas........................................................................................................68 13.2 CAMPOS DE BITS..........................................................................................................................69 13.3 UNIES.......................................................................................................................................70 13.4 SIZEOF().....................................................................................................................................72 13.5 TYPEDEF.....................................................................................................................................72 13.6 EXERCCIOS.................................................................................................................................73 14. ALOCAO DINMICA..............................................................................................................75 14.1 FUNES DE ALOCAO DINMICA EM C..........................................................................................75 14.1.1 Funo malloc().......................................................................................................................75 14.1.2 Funo calloc()........................................................................................................................76 14.1.3 Funo free()............................................................................................................................77 14.1.4 Funo realloc()......................................................................................................................78 14.2 MATRIZES DINAMICAMENTE ALOCADAS............................................................................................78 14.3 LISTAS ENCADEADAS....................................................................................................................80 14.3.1 Listas Singularmente Encadeadas...........................................................................................80 14.3.2 Listas Duplamente Encadeadas...............................................................................................81 14.4 RVORES BINRIAS......................................................................................................................83 14.5 EXERCCIOS.................................................................................................................................86 15. E/S COM ARQUIVO......................................................................................................................87 15.1 E/S ANSI X E/S UNIX..............................................................................................................87 15.2 STREAMS....................................................................................................................................87 15.3 ARQUIVOS...................................................................................................................................87 15.4 SISTEMA DE ARQUIVOS.................................................................................................................87 15.5 ESTRUTURA FILE........................................................................................................................88 15.6 ABERTURA DE ARQUIVOS...............................................................................................................88 15.7 FECHAMENTO DE ARQUIVO.............................................................................................................89 15.8 LEITURA E GRAVAO DE CARACTERES............................................................................................89 15.8.1 Gravao..................................................................................................................................89 15.8.2 Leitura......................................................................................................................................90 15.9 VERIFICANDO FIM DE ARQUIVO........................................................................................................90 15.10 TRABALHANDO COM ARQUIVOS......................................................................................................90 15.11 TRABALHANDO COM STRINGS : FPUTS () E FGETS ()..............................................................................91 15.12 FUNES DE TRATAMENTO DE ARQUIVOS.........................................................................................92 15.12.1 rewind()..................................................................................................................................92

5/105

LINGUAGEM C 15.12.2 ferror()....................................................................................................................................93 15.12.3 remove().................................................................................................................................93 15.12.4 fflush()....................................................................................................................................94 15.12.5 Funo ftell().........................................................................................................................94 15.13 LENDO E GRAVANDO REGISTROS.....................................................................................................94 15.13.1 Escrita de um bloco de dados................................................................................................94 15.13.2 Leitura de um bloco de dados................................................................................................95 15.13.3 Utilizando os comandos de leitura e gravao de registros.................................................95 15.14 ACESSO ALEATRIO.....................................................................................................................96 15.15 COMANDO DE GRAVAO EM MODO TEXTO FORMATADO......................................................................97 15.16 CONDIES DE ERRO...................................................................................................................98 15.17 STREAMS PADRO......................................................................................................................98 15.18 EXERCCIO:...............................................................................................................................99 15.19 SISTEMA DE ARQUIVO TIPO UNIX................................................................................................99 15.19.1 open()...................................................................................................................................100 15.19.2 creat()...................................................................................................................................101 15.19.3 close()...................................................................................................................................101 15.19.4 read() e write().....................................................................................................................101 15.19.5 unlink().................................................................................................................................103 15.19.6 lseek() e tell().......................................................................................................................103 15.19.7 Funes para manipulao de buffers................................................................................103 16. BIBLIOGRAFIA...........................................................................................................................105

6/105

LINGUAGEM C

Lista de Figuras
FIGURA 1.1 - CODIFICAO DE UM PROGRAMA C.................................................................9 FIGURA 12.2 INDIREO SIMPLES E MLTIPLA....................................................................61 FIGURA 14.3 EXEMPLO DE UMA RVORE BINRIA..............................................................84

7/105

LINGUAGEM C

Lista de Tabelas

8/105

1.

Introduo

A linguagem C foi criada por Dennis M. Ritchie e Ken Thompson no Laboratrio Bell em 1972, baseada na linguagem B de Thompson que era uma evoluo da antiga BCPL. A linguagem C tornou-se muito popular devido a caractersticas como: O C uma linguagem de alto nvel com uma sintaxe bastante estruturada e flexvel tornando sua programao bastante simplificada. Programas em C so compilados, gerando programas executveis. O C compartilha recursos tanto de alto quanto de baixo nvel, pois permite acesso e programao direta do microprocessador. Com isto, rotinas cuja dependncia do tempo crtica, podem ser facilmente implementadas usando instrues em Assembly. Por esta razo o C a linguagem preferida dos programadores de aplicativos. O C uma linguagem estruturalmente simples e de grande portabilidade. O compilador C gera cdigos mais enxutos e velozes do que muitas outras linguagens. Embora estruturalmente simples (poucas funes intrnsecas) o C no perde funcionalidade pois permite a incluso de uma farta quantidade de rotinas do usurio. Os fabricantes de compiladores fornecem uma ampla variedade de rotinas pr-compiladas em biblioteca Como uma ferramenta poderosa a linguagem C usada na construo de vrios aplicativos como sistemas operacionais, planilhas eletrnicas, processadores de texto, sistemas de transmisso de dados, entre outros. Um exemplo clssico o sistema operacional UNIX, o qual foi implementado em C. No incio da dcada de 80 a linguagem C padronizada pelo American National Standard Institute: surge o ANSI C. Atualmente, a linguagem C vem sendo usada para desenvolver novas linguagens, entre elas a linguagem C+ + e Java.

1.1

Viso geral de um programa C

A gerao do programa executvel a partir do programa fonte obedece a uma seqncia de operaes ante de tornar-se um executvel. Depois de escrever o mdulo fonte em um editor de textos, o programador aciona o compilador. Essa ao desencadeia uma seqncia de etapas, cada qual traduzindo a codificao do usurio para uma forma de linguagem de nvel inferior, que termina com o executvel criado pelo linkador. FIGURA 1.1 - Codificao de um programa C Editor (mdulo fonte em C) Pr-processador (novo fonte expandido)

Compilador (arquivo objeto)

Linkador (executvel)

LINGUAGEM C

2.

Estrutura Bsica de um Programa em C

Um programa C consiste em uma ou vrias funes. Baseado nesta afirmao, deve existir um mecanismo que garanta que todos os programas inicializem da mesma forma. Este mecanismo pode ser entendido como a padronizao da funo que ser chamada primeiramente. Tal funo chama-se main(). Sintaxe: main() { } primeira funo a ser executada inicia o corpo da funo termina a funo

Abaixo relacionam-se algumas regras para a programao em C: Toda funo C deve ser iniciada e encerrada por um abre chaves e um fecha chaves respectivamente; O nome da funo, os parnteses e as chaves so os nicos elementos obrigatrios de uma funo; Todas as instrues devem estar dentro das chaves; As instrues C so sempre encerradas por um ponto-e-vrgula;

2.1

Bibliotecas

Para no ter que criar programas grandes devido a linkedio de um arquivo objeto a linguagem inclui as bibliotecas para que no momento da compilao seja gerado um programa com as funes utilizadas. Para fazer isto, usa-se uma diretiva de compilao a qual colocada fora de qualquer funo do programa. A diretiva #include instrui o compilador a ler outro arquivo-fonte. Sintaxe: #include nome_arq onde: nome_arq tem que estar entre aspas ou smbolos de maior ou menor

Em algumas plataformas existe somente uma das duas formas. No caso da plataforma DOS/Windows 95, aspas significa para o compilador que a biblioteca em questo deve ser buscada primeiramente no diretrio atual e depois no diretrio padro do turbo ou pelas variveis de ambiente. Tambm, os caracteres <> significam ao compilador que deve procurar somente no diretrio padro ou nos diretrios definidos pelas variveis de ambiente. Exemplo 2.1 #include <stdio.h> No se usa o ponto-e-vrgula aps diretivas de compilao. Este tipo de declarao muito usado nos programas profissionais. Cada comando pr-definido em C est prototipado em alguma biblioteca (isto informado conjuntamente ao comando).

10/105

LINGUAGEM C

3.

Tipos de Dados

Em C existem 5 tipos de variveis bsicas. Nos computadores da linha IBM-PC (sistema operacional 16 bits) a tabela 3.1 vlida. Tabela 3.1 - Tipos de dados bsicos TIPO char int float double void BIT 8 16 32 64 0 FAIXA MNIMA -128 a 127 - 32768 a 32767 3.4E-38 a 3.4E+38 1.7E-308 a 1.7E+308 sem valor

Com exceo de void, os tipos de dados bsicos podem estar acompanhados por modificadores na declarao de variveis. Os modificadores de tipos da linguagem C so: long; short. Os modificadores signed, short, long e unsigned podem ser aplicados aos tipos bsicos caractere e inteiro. Contudo, long tambm pode ser aplicado a double. A tabela 3.2 mostra todas a combinaes de tipos de dados Tabela 3.2 - Utilizao dos modificadores de tipos de dados TIPO unsigned char signed char unsigned int signed int short int unsigned short int signed short int long int signed long int unsigned long int long double BIT 8 8 16 16 16 16 16 32 32 32 128 FAIXA MNIMA 0 a 255 -128 a 127 0 a 65535 O mesmo que int O mesmo que int 0 a 65535 O mesmo que short int -2.147.483.647 a 2.147.483.647 -2.147.483.647 a 2.147.483.647 0 a 4.294.967.925 Dez dgitos de preciso signed; unsigned;

O uso de signed com inteiros redundante. No entanto, ele permitido porque a declarao default de inteiros assume um nmero com sinal. O uso mais importante de signed modificar char em implementaes em que esse tipo, por padro, no tem sinal. Algumas implementaes podem permitir que unsigned seja aplicado aos tipos de ponto flutuante (como em unsigned double). Porm, isso reduz a portabilidade de seu cdigo e geralmente no recomendado. O modificador unsigned altera o valor da faixa mnima do tipo atravs do uso do bit mais significativo (indicador de sinal). No caso do sistema operacional ser 32 bits o tipo int ser o nico a ser alterado, pois ele passa de 2 bytes para 4 bytes de armazenamento. Isto tambm faz com que o intervalo de valores seja aumentado. Exemplo 3.2 main() { int qtde; char tam; float total; qtde = 2; tam = G; total = 20.70; printf(Comprei %d camisas de tamanho %c., qtde, tam); printf(\nNo total, paguei R$ %f., custo);

11/105

LINGUAGEM C

} Execuo: Comprei 2 camisas de tamanho G. No total, paguei R$ 20.70. As variveis podem ser inicializadas no momento em que se faz a declarao das mesmas. Pode-se ver isto usando o programa anterior, que a execuo ser a mesma da verso anterior. main() { int qtde=2; char tam=G; float total=20.70; printf(Comprei %d camisas de tamanho %c., qtde, tam); printf(\nNo total, paguei R$ %f., custo); }

3.1

Enumerao

Enumerao um conjunto de constantes inteiras que especifica todos os valores legais de uma varivel desse tipo pode ser. A forma geral para enumerao : Sintaxe: enum nome { lista_de_enumerao } lista_de_variveis; Aqui, tanto o nome da enumerao quanto a lista de variveis so opcionais. O nome da enumerao usado para declarar variveis daquele tipo. Com isso pode-se declarar as cores Exemplo 3.2 enum cores {amarelo, verde, vermelho}; enum cores semaforo; Dada essa definio e declarao, os tipos de comandos seguintes so perfeitamente vlidos: semaforo = verde; if (semaforo==verde) printf(Passagem permitida \n); Para melhor compreenso da enumerao entende-se que cada smbolo representa um valor inteiro. O valor do primeiro smbolo da enumerao 0. Assim, printf (%d %d, verde, vermelho); mostra 1 2 na tela. Como extenso, pode-se inicializar os smbolos de forma alternada para algum problema especfico. Exemplo 3.3 enum cores { amarelo, verde=10, vermelho }; Agora os valores destes smbolos so amarelo verde vermelho 0 10 11

12/105

LINGUAGEM C

3.2

Modificadores de Tipo de Acesso

O padro ANSI introduziu dois novos modificadores de tipo que controlam a maneira como a variveis podem ser acessadas ou modificadas. Esses modificadores so const e volatile. Devem preceder os modificadores de tipo e os nomes que eles modificam.

3.2.1 Const
Variveis do tipo const no podem ser modificadas por seu programa (por isso ela recebe um valor inicial). Exemplo 3.4 const int a=10; O exemplo 5.4 cria uma varivel inteira chamada a, com um valor inicial 10, que seu programa no pode modificar. Um exemplo do uso do const para verificar se uma varivel em particular modificada pelo seu programa.

3.2.2 Volatile
O modificador volatile usado para informar ao compilador que o valor de uma varivel pode ser alterado de maneira no explicitamente especificada pelo programa. Por exemplo, um endereo de uma varivel global pode ser passado para a rotina de relgio do sistema operacional e usado para guardar o tempo real do sistema. Nessa situao, o contedo de uma varivel alterado sem nenhum comando de atribuio explicito no programa. Isso ajuda o programa no sentido de avisar ao compilador que o contedo de uma varivel mutvel, mesmo que sua referncia no aparecer no lado esquerdo da expresso. possvel usar const e volatile juntos. Por exemplo, se 0x30 assumido como sendo o valor de uma porta que mudado por condies externas. Para evitar efeitos colaterais deve-se declarar da seguinte forma: const volatile unsigned char *port = 0x30;

3.3

Constantes

Uma constante tem valor fixo e inaltervel durante a execuo do programa. Isto pode ser exemplificado pelos exemplos 3.1 e 3.2 da funo printf(). Em uma constante caractere escrita entre aspas simples (), uma constante cadeia de caracteres entre aspas duplas () e constantes numricas como o nmero propriamente dito. Exemplo 3.5 C programa 8 465.67 Constantes em C podem ser de qualquer um dos cinco tipos de dados bsicos. A maneira como cada constante representada depende do seu tipo. Pode-se especificar precisamente o tipo da constante numrica atravs da utilizao de um sufixo. Para tipos em ponto flutuante coloca-se um F aps o nmero, ele ser tratado como float. Se for colocado um L, ele tornar-se- um long double. Para tipos

13/105

LINGUAGEM C inteiros, o sufixo U representa unsigned e o L representa long. A tabela 5.3 mostra alguns exemplos de constantes. Tabela 3.3 - Exemplo de constantes Tipo de Dado int long int short int unsigned int float Double long double Exemplo de Constantes 1 123 21000 -234 35000L -34L 10 -12 90 10000U 987U 40000 123.23F 2.34e-3F 123.23 12312333 -0.9876324 1001.2L

Alm deste tem-se as constantes Hexadecimais e Octais. Usam-se tais sistemas numricos para facilitar a programao. Uma constante hexadecimal deve consistir em um 0x seguido por uma constante na forma hexadecimal. Uma constante octal comea com 0. Exemplo 3.6 int hex = 0x80; int oct = 012; /* 128 em decimal */ /* 10 em decimal */

3.4

Constantes pr-definidas

Em alguns compiladores C, algumas constantes simblicas j esto pr-definidas. Estas constantes em geral definam alguns valores matemticos (, /2, e, etc.), limites de tipos etc. A seguir segue uma tabela contendo algumas (existem muitas outras) constantes simblicas pr-definidas no compilador Turbo C++ da Borland. Biblioteca math.h math.h math.h math.h math.h conio.h conio.h conio.h conio.h conio.h conio.h limits.h limits.h Constante M_PI M_PI_2 M_PI_4 M_1_PI M_SQRT2 BLACK BLUE GREEN CYAN RED MAGENTA INT_MAX INT_MIN Valor 3.14159... 1.57079... 0,78539... 0,31830... 1,41421... 0 1 2 3 4 5 32767 -32768 Significado /2 /4 1/ 2 valor da cor (preto) valor da cor (azul) valor da cor (verde) valor da cor (cyan) valor da cor (vermelho) valor da cor (magenta) limite superior do tipo int limite inferior do tipo int

3.5

As bibliotecas disponveis e algumas funes interessantes

A seguir segue uma lista de algumas as bibliotecas disponveis no compilador Turbo C++ Borland: Ao longo do texto veremos o uso de muitas funes cobrindo uma boa parte destas

14/105

LINGUAGEM C bibliotecas, porm o leitor que desejar tornar-se "fluente" na linguagem C pode (e deve) estud-las com profundidade. alloc.h conio.h errno.h graphics.h locale.h setjmp.h stdio.h strstrea.h values.h assert.h ctype.h fcntl.h io.h malloc.h share.h stdiostr.h sys\stat.h bcd.h dir.h float.h iomanip.h math.h signal.h stdlib.h sys\timeb.h bios.h dirent.h fstream.h iostream.h mem.h stdarg.h stream.h sys\types.h complex.h dos.h generic.h limits.h process.h stddef.h string.h time.h

Vejamos algumas funes disponveis nas bibliotecas C. Biblioteca math.h int abs(int i); double fabs(double d); Calcula o valor absoluto do inteiro i e do real d, respectivamente. double sin(double arco); double cos(double arco); double tan(double arco); double asin(double arco); double acos(double arco); double atan(double arco); Funes trigonomtricas do ngulo arco, em radianos. double ceil(double num); double floor(double num); Funes de arredondamento para inteiro. ceil() arredonda para cima. Ex. ceil(3.2) == 4.0; floor() arredonda para baixo. Ex. floor(3.2) == 3.0; double log(double num); double log10(double num);

15/105

LINGUAGEM C

Funes logartmicas: log() logaritmo natural (base e), log10() logaritmo decimal (base 10). double pow(double base, double exp); Potenciao: pow(3.2,5.6) = 3.25.6. double sqrt(double num); Raiz quadrada: sqrt(9.0) = 3.0. Biblioteca stdlib.h int random(int num); Gera um nmero inteiro aleatrio entre 0 e num - 1.

16/105

LINGUAGEM C

4.

Comando de Escrita

A funo printf() uma das funes de E/S (entrada e sada) que mostra na tela os parmetros que so passados como argumento. Seu prottipo est na biblioteca stdio.h. Sintaxe: onde: printf(<expressao_de_controle>, lista_de_argumentos) expresso_de_controle = contm caracteres que sero exibidos na tela e cdigos de formatao que indicam o formato em que os argumentos (da lista_de_argumentos) devem ser impressos. lista_de_argumentos = lista de argumentos que sero apresentadas na expresso_de_controle. Tal lista no tem tamanho mximo e cada argumento deve ser separado por uma vrgula. A tabela 4.1 mostra os cdigos na linguagem para caracteres que no podem ser inseridos diretamente do teclado. Tabela 4.3 - Cdigo para os caracteres especiais CDIGOS ESPECIAIS \n \t \b \ \\ \f \r \ \v \a \N \xN \0 SIGNIFICADO Nova Linha (LF) Tab (HT) Retrocesso (BS) Barra invertida Salta Pgina de Formulrio (FF) Retorno de Carro (CR) Tabulao Vertical Alerta (beep) Constante octal (onde N uma constante octal) Constante Hexadecimal (onde N uma constante hexadecimal) Nulo

Alm destes, existem os cdigos para formatao de impresso dos argumentos passados para a funo, os quais est relacionados na tabela 4.2. Tabela 4.4 - Cdigos para formatao de impresso CDIGO printf() %c %d ou %i %e ou %E (minsculo ou maisculo) %f %g ou %G (minsculo ou maisculo) %o %s %u %x ou %X (minsculo ou maisculo) %% Exemplo 4.3 main() FORMATO Caractere Simples Decimal Notao Cientfica Ponto Flutuante %e ou %f (o mais curto) Octal Cadeia de Caracteres Decimal sem Sinal Hexadecimal Escreve o smbolo %

17/105

LINGUAGEM C

{ printf(A %s C foi criada em %d \nOk?, Linguagem, 1972); } Execuo:: A Linguagem C foi criada em 1972 Ok? No exemplo 3.1 percebe-se o uso de dois tipos de cdigos: primeiro de formatao com %s (para strings) representando a constante string Linguagem e %d (decimais) representando a constante ano 1972; segundo um cdigo especial para representar caracter de nova linha \n. Exemplo 4.4 main() { printf(A %s %c foi , Linguagem, C); printf( criada em %d , 1972); } Execuo: A Linguagem C foi criada em 1972 No exemplo 3.2, nota-se que C delimitado por aspas simples enquanto que Linguagem delimitado por aspas duplas. Isto indica ao compilador como diferenciar um caractere de uma cadeia de caracteres.

4.1

Modificadores de Sada

Para complementar os cdigos de formatao a linguagem C oferece alguns cdigos especiais para melhorar a apresentao dos dados. Para isto relacionam-se: - : alinhamento pela esquerda. +: coloca o sinal de menos ou mais se o valor for numrico. n (nmero) : indica o tamanho mnimo do campo. O preenchimento feito com espaos em branco. Se o tamanho iniciar com 0 (ex. 05), o preenchimento passa a ser feito com zeros. .m : tamanho mximo do campo, menos para os reais onde usado para indicar o nmero de casas decimais. * : substitui um dos n, mas o seu valor o prximo parmetro. l : indica que segue um dado longo. Exemplo 4.3 COMANDO printf(%s %d, Numero,10); printf(%8s %4d, Numero,10); printf(%-8s %4d, Numero,10); printf(%-3.5s %2.2f,Numero,10.99); printf(Long %ld, 57485784); onde: # - representa 1 espao em branco. TELA Numero 10 ##Numero ##10 Numero## ##10 Numer 10.99 Long 57485784

18/105

LINGUAGEM C

4.2

Exerccios

1. Escreva os comandos de sada formatada que gerem as seguintes sadas: 01234567890123456789012 a) Camisa estampada 40,00 Camisa lisa 35,00 b) Camisa estampada Camisa lisa c) Camisa estampada Camisa lisa d) Camisa e Camisa l 40 35 40,00 35,00 00040,00 00035,00

19/105

LINGUAGEM C

5.

Variveis

Varivel em C um espao de memria reservado para armazenar um certo tipo de dado e tendo um nome para referenciar o seu contedo. O contedo da mesma pode variar segundo os comandos de alterao do programa. Exemplo 5.5 main() { int ano; ano = 1972; printf(A Linguagem C foi criada em %d , ano); } A primeira instruo, int ano; um exemplo de declarao de varivel, isto , apresenta um tipo, int, e um nome, ano. A segunda instruo, ano = 1972; atribui um valor varivel e este valor ser acessado atravs de seu nome. Para realizar isto foi usado o operador de atribuio (=).

5.1
Regras:

Nome de Variveis

Uma varivel no pode ter o mesmo nome de uma palavra-chave de C. Em C, letras maisculas diferem das letras minsculas. O nmero de caracteres vlidos definido de ambiente para ambiente.

5.2

Declarao de Variveis

A declarao de variveis serve para reservar uma quantidade de memria apropriada para armazenar o tipo especificado. Tal declarao consiste no nome de um tipo, seguido do nome da varivel. Em C todas as variveis devem ser declaradas. Se existir mais de uma varivel do mesmo tipo, pode-se declar-la de uma vez separando seus nomes por vrgulas. int ano, mes, dia;

5.2.1 Tipos de Declaraes de Variveis


O tipo de declarao de varivel definido pela localizao onde a mesma declarada. Existem trs lugares bsicos: dentro de funes, na definio dos parmetros das funes e fora de todas as funes. Estas so variveis locais, parmetros formais e variveis globais, respectivamente.

20/105

LINGUAGEM C

5.2.1.1 Variveis locais


Variveis que so declaradas dentro de uma funo. Tais variveis s podem ser referenciadas por comandos que esto dentro do bloco no qual as variveis foram declaradas, isto , no so reconhecidas fora de seu prprio bloco de cdigo. Exemplo 5.2 void main() { int num; num = 10; }

5.2.1.2 Parmetros Formais


Variveis que so declaradas para passagem de parmetros em funes. Exemplo 5.3 int soma(int x, int y) { return (x+y); }

5.2.1.3 Variveis Globais


Variveis que so declaradas fora de qualquer funo. Tais variveis so reconhecidas pelo programa inteiro e podem ser usadas por qualquer pedao de cdigo. Exemplo 5.4 int num=10; void main() { printf(%d, num * num); } Exemplo 5.5 int num=2; int media(int y, int x) { return ((x+z)/num); } void main() { int x1 = 15; int x2 = 4; printf(%d } %d , num * num, media(x1,x2));

21/105

LINGUAGEM C

5.3

Palavras reservadas

Existem certos nomes que no podem ser usados como identificadores. So chamadas as palavras reservadas e so de uso restrito da linguagem C (comandos, estruturas, declaraes, etc.). O conjunto de palavras reservadas usadas em C o seguinte: asm class do extern friend interrupt pascal _saveregs static union auto const double _export goto _loadds private _seg struct unsigned break continue _ds far huge long protected short switch virtual case _cs else _fastcall if near public signed template void cdecl default enum float inline new register sizeof this volatile char delete _es for int operator return _ss typedef while

22/105

LINGUAGEM C

6.

Operadores

A linguagem C muito rica em operadores internos. C define quatro classes de operadores: aritmticos, relacionais, lgicos e bit a bit. Alm disso, C tem alguns operadores especiais para tarefas particulares.

6.1

Atribuio

Para o operador de atribuio utilizado o smbolo =. Alm disto, a linguagem oferece um tipo de atribuio mltipla, isto , em um comando s pode-se atribuir o mesmo valor a muitas variveis. Exemplo 6.6 x = 10; a = b = c = 10;

6.1.1 Converso de Tipos em Atribuies


A linguagem C permite a converso automtica de tipos, o que no acontece em Pascal, por exemplo. Converso de tipos refere-se situao em que variveis de um tipo so misturadas com varveis de outro tipo. Em um comando de atribuio, a regra de converso de tipos muito simples: o valor do lado direito (lado da expresso) de uma atribuio convertido no tipo do lado esquerdo (varivel destino), como no exemplo 6.2: Exemplo 6.2 void main() { int x; char ch; float f; ch = x; x = f; f = ch; f = x; } // // // // Linha Linha Linha Linha 1 2 3 4

Na linha 1, os bits mais significativos da varivel inteira x so ignorados, deixando ch com os 8 bits menos significativos. Se x est entre 255 e 0, ento ch e x tm valores idnticos. De outra forma, o valor de ch reflete apenas os bits menos significativos de x. Na linha 2, x recebe a parte inteira de f. Na linha 3, f converte o valor inteiro de 8 bits armazenado em ch no mesmo valor em formato de ponto flutuante. Isso tambm acontece na linha 4, exceto por f converter um valor inteiro de 16 bits no formato de ponto flutuante. Na tabela 6.1 mostra-se algumas converses de tipos e seus efeitos. Para essas converses foi assumido uma palavra de 16 bits. Tabela 6.5 - Converses de tipos e seus efeitos Tipo Destino signed char char char char int int float double Tipo da Expresso char short int int long int long int float double long double Possvel Informao Perdida Se valor > 127, o destino negativo Os 8 bits mais significativos Os 8 bits mais significativos Os 24 bits mais significativos Os 16 bits mais significativos A parte fracionria e possivelmente mais Preciso, o resultado arredondado Preciso, o resultado arredondado

23/105

LINGUAGEM C Para utilizar a tabela acima a fim de fazer uma converso no mostrada, simplesmente converta um tipo por vez at acabar. por exemplo, para converter double em int, primeiro converta double em float e, ento, float em int.

6.2

Operadores Aritmticos
A tabela 6.2 mostra os operadores aritmticos suportados pela linguagem. Tabela 6.2 - Operadores aritmticos

Operador + * / % -++ um sinal

Ao Subtrao, tambm menos unrio Adio Multiplicao Diviso Mdulo da Diviso (resto) Decremento Incremento

O menos unrio multiplica seu nico operando por -1. Isso , qualquer nmero precedido por Quando / aplicado a um inteiro ou caractere, qualquer resto truncado.

O operador mdulo % tambm, trabalha em C da mesma forma que em outras linguagens, devolvendo o resto de uma diviso inteira. Contudo, % no pode ser usado nos tipos em ponto flutuante.

6.2.1 Incremento e Decremento


A linguagem C inclui dois operadores que geralmente no encontramos em outras linguagens. So os operadores de incremento (++) e decremento (--), os quais somam 1 ao seu operando, e subtraem 1 de seu operando, respectivamente. x++; ou ++x; x--; ou --x; ou ou x = x + 1; x = x - 1;

Quando usados em uma expresso tem seus efeitos alterados pela posio do sinal de decremento e incremento. Se o operador de incremento ou decremento preceder seu operando, C executa a operao de incremento ou decremento antes de usar o valor do operando. Se o operador estiver aps seu operando, C usa o valor do operando antes de increment-lo ou decrement-lo. Exemplo 6.3 x = 10; y = ++x; /*y recebe 11*/ x = 10; y = x++; /* y recebe 10 */

A precedncia dos operadores aritmticos a seguinte: ++ * + a direita. -/ % Mais alta Mais baixa

Os operadores do mesmo nvel de precedncia so avaliados pelo compilador da esquerda para

24/105

LINGUAGEM C

6.2.2 Operadores Aritmticos de Atribuio


A tabela 6.3 mostra os operadores aritmticos de atribuio suportados pela linguagem. Tabela 6.3 - Operadores aritmticos de atribuio Operador x -= y x += y x *= y x /= y x %= y Ao x=x-y x=x+y x=x*y x=x/y x=x%y

As expresses com este operadores so mais compactas e normalmente produzem um cdigo de mquina mais eficiente.

6.3

Operadores Relacionais e Lgicos


A tabela 6.4 mostra os operadores relacionais e lgicos suportados pela linguagem C. Tabela 6.4 - Operadores relacionais e lgicos

Operador > >= < <= == !=

Ao Maior que Maior ou igual que Menor que Menor ou igual que Igual Diferente

Operador && || !

Ao AND OR NOT

Em C, verdadeiro qualquer valor diferente de zero, e falso zero. As expresses que usam operadores relacionais ou lgicos devolvem zero para falso e 1 para verdadeiro. Lembre-se de que toda expresso relacional e lgica produz como resiltado 0 ou 1. A precedncia dos operadores relacionais e lgicos a seguinte: ! > == && || Mais alta >= != < <= Mais baixa

6.4

Operadores Bit a Bit


A tabela 6.5 mostra os operadores bit a bit suportados pela linguagem. Tabela 6.5 - Operadores bit-a-bit

Operador & | ^ ~ >> <<

Ao AND OR OR exclusivo (XOR) Complemento de um Deslocamento direita Deslocamento esquerda

A tabela 6.6 mostra o resultado de operaes com deslocamento.

25/105

LINGUAGEM C Tabela 6.6 - Exemplo de operaes de deslocamento bit-a-bit char x; x =7 x << 1 x << 3 x << 2 x >> 1 x >> 2 x a cada execuo da sentena 00000111 00001110 01110000 11000000 01100000 00011000 Valor de x 7 14 112 192 96 24

Os operadores bit a bit s podem ser utilizados sobre um byte ou uma palavra, isto , aos tipos de dados char e int e variantes do padro C. Operaes bit no podem ser usadas em float, double, long double, void ou outros tipos mais complexos.

6.5

Operador ?
O operador ? substitui sentenas da forma Se-ento-seno.

Sintaxe: Exp1 ? Exp2 : Exp3; Onde Exp1, Exp2 e Exp3 so expresses. Onde Exp1 avaliada e se a mesma for verdadeira, ento Exp2 avaliada e se torna o valor da expresso. Se Exp1 falso, ento Exp3 avaliada e se torna o valor da expresso. Exemplo 6.4 x = 10; y = x > 9 ? 100 : 200; No exemplo 6.4, y recebe o valor 100, porque x (valor 10) maior que 9. Uma expresso equivalente seria x = 10; if (x > 9) y = 100; else y = 200;

6.6

Operadores de Ponteiros & e *

Um ponteiro um endereo na memria de uma varivel. Uma varivel de ponteiro uma varivel especialmente declarada para guardar um ponteiro para seu tipo especificado. O primeiro operador de ponteiro &. Ele um operador unrio que devolve o endereo na memria de seu operando. Por exemplo, m = &cont; atribui o endereo de memria da varivel cont em m. Este tipo de operando no pode ser utilizado em trs casos: 1. &(cont + 4) - sempre associa-se a uma varivel e no expresso; 2. &3 - constantes no so vlidas; 3. variveis declaradas com classe de armazenamento register (no existe endereo para registrador).

26/105

LINGUAGEM C O segundo operador *. Ele um operador unrio que devolve o valor da varivel localizada no endereo que o segue. Por exemplo, se m contm o endereo da varivel cont, q = *m; coloca o valor de cont em q. Os seguintes operadores * e & colocam o valor 10 na varivel chamada target. O resultado (o valor 10) deste programa mostrado na tela. Exemplo 6.5 #include stdio.h void main() { int target, source; int *m; source = 10; m = &source; target = *m; printf(%d,target); }

6.7

Operador Vrgula

O operador vrgula usado para encadear diversas expresses. O lado esquerdo de um operador vrgula sempre avaliado como void. Isso significa que a expresso do lado direito se torna o valor de toda a expresso separada por vrgulas. Exemplo 6.6 x = (y = 3, y + 1); No exemplo 6.5, primeiro y recebe 3 e, em seguida, atribui o valor 4 a x.

6.8

Expresses

Operadores, constantes e variveis so os elementos que constituem as expresses. Uma expresso qualquer combinao vlida desses elementos.

6.8.1 Converso de Tipos em Expresses


Quando constantes e variveis de tipos diferentes so misturadas em uma expresso, elas so convertidas a um mesmo tipo. O compilador C converte todos os operandos no tipo do maior operando, o que denominado promoo de tipo. Isso feito operao por operao, como descrito nas regras de converso de tipos abaixo. SE um operando long double ENTO o segundo convertido para long double. SENO, SE um operando double ENTO o segundo convertido para double. SENO, SE um operando float ENTO o segundo convertido para float. SENO, SE um operando unsigned long ENTO o segundo convertido para unsigned long. SENO, SE um operando long

27/105

LINGUAGEM C ENTO o segundo convertido para long. SENO, SE um operando unsigned ENTO o segundo convertido para unsigned. H ainda um caso adicional especial: se um operando long e o outro unsigned, e se o valor do unsigned no pode ser representado por um long, os dois operandos so convertidos para unsigned long. Considere as converses de tipo que ocorrem no exemplo 6.6. Primeiro, o caractere ch convertido para um inteiro e float f convertido para double. Em seguida, o resultado de ch/i convertido para double porque f*d double. O resultado final double porque, nesse momento, os dois operandos so double. Exemplo 6.7 char ch; int i; float f; double d; result= ( ch / i )

( f * d )

( f + i );

int

double

float

double

double

6.8.2 Casts
A linguagem permite que uma expresso pode ser forada a ser de um tipo especificado usando uma construo chamada cast. A forma geral de um cast (tipo) expresso onde um tipo um tipo de dado padro de C. Por exemplo, para ter certeza de que a expresso x /2 ser do tipo float, escreve-se (float) x/2; Neste caso se a varivel x fosse um inteiro mpar sem o cast seu valor reria um inteiro (o que no seria verdadeiro). Entretanto, com o uso do Cast oa varivel x definida como um float o que tornar o seu resultado um float. Como um operador, um cast unrio e tem a mesma precedncia de qualquer outro operador unrio.

6.8.3 Espacejamento e Parnteses


A linguagem C no limita o espaamento ou tabulaes em uma expresso. Ajudam a aumentar a legibilidade do programa.

28/105

LINGUAGEM C O excesso de parnteses no causa erros, isto , colocar parnteses onde no necessita, no provoca erros, mas dificulta a leitura do programa.

29/105

LINGUAGEM C

7.

Algumas funes de E/S

Neste captulo ser visto algumas funes como scanf(), getche(), getch(), getchar() e putchar(). Tais funes encontram-se no arquivo stdio.h, exceto getch() e getche() que encontram-se seus prottipos em conio.h.

7.1

Funo scanf()

Esta funo serve para ler dados formatados da entrada padro (teclado). Sua sintaxe similar de printf(), isto , uma expresso de controles seguida por uma lista de argumentos separados por vrgulas. A principal diferena que os argumentos de scanf() devem ser endereos de variveis. Para enviar o endereo de cada argumento utiliza-se o operador &. Sintaxe: scanf(expresso_de_controle,lista_de_argumentos) A expresso de controle pode conter cdigos de formatao, precedidos por um sinal %. Alm disso, o caractere * colocado aps o % que avisa funo que deve ser lido um valor do tipo indicado pela especificao, mas no deve ser atribudo a nenhuma varivel (no deve ter parmetros na lista de argumentos para estas especificaes). Tabela 7.6 - Cdigos de formatao do comando scanf() CDIGO printf() %c %d ou %i %e %f %g %o %s %u %x %l %% Exemplo 7.7 main() { char a; printf(Digite um caractere e veja-o em decimal, ); printf ( octal e hexadecimal. \n); scanf(%c,&a); printf(\n%c=%d dec., %o oct. e %x hex. \n,a,a,a,a); } Execuo (faa voc mesmo): FORMATO L um nico caractere simples L um inteiro decimal L um nmero em notao cientfica L um nmero em ponto flutuante L um nmero em ponto flutuante L um nmero em octal L um nmero em cadeia de Caracteres L um decimal sem sinal L um hexadecimal L um inteiro longo Busca por um conjunto de caracteres

30/105

LINGUAGEM C

7.2

Funo getche() e getch()

A funo getche() l um caractere do teclado sem pressionar <ENTER> e mostra o que foi digitado. Esta funo no aceita argumentos e devolve o caracter lido para a funo que a chamou. Exemplo 7.2 main() { char ch; printf(Digite algum caractere:); ch=getche(); printf(\n A tecla pressionada eh %c., ch); } Execuo: Digite algum caractere: a A tecla pressionada eh a. A funo getch() l um caractere do teclado sem pressionar <ENTER> e no mostra o que foi digitado. Esta funo no aceita argumentos e devolve o caracter lido para a funo que a chamou. Exemplo 7.3 main() { char ch; printf(Digite algum caractere:); ch=getch(); printf(\n A tecla pressionada eh %c., ch); } Execuo: Digite algum caractere: A tecla pressionada eh a.

7.3

Lendo e escrevendo caracteres

A funo getchar() l um caractere do teclado (este comando necessita o pressionamento da tecla <ENTER> aps o caractere), e putchar() escreve um caracter na tela. A funo getchar() espera at que uma tecla seja pressionada (a qual mostrada na tela) e devolve o seu valor. A funo putchar() escreve seu argumento caractere na tela a partir da posio atual do cursor. Os prottipos para getchar() e putchar() so mostrados aqui: int getchar(void); int putchar(int c); A funo getchar() devolve um inteiro, mas o byte de baixa ordem contm o caractere. Alm disso, pode-se chamar putchar() com um argumento caractere. A funo putchar() devolve o caractere escrito, ou EOF (definida em stdio.h e geralmente igual a -1), se ocorreu algum erro. A funo putchar() no acrescenta um \n a sada. Exemplo 7.4 main() { char ch; printf(Digite algum caractere:); ch=getchar(); printf(\n A tecla pressionada eh ); putchar(ch); }

31/105

LINGUAGEM C

7.4

Exerccios

1. Escreva um programa que leia 3 nmeros e mostre a sua mdia. 2. Escreva um programa que leia 2 nmeros e mostre qual o maior. 3. Faa um programa que leia dois nmeros e em seguida mostre ,o produto a soma e a subtrao entre eles. 4. Faa um programa que leia 3 variveis a, b e c, coeficientes de uma equao do 2 grau e escreva as duas razes da equao.

b , onde = b 2 4ac 2a 5. Escreva um programa onde o usurio entra com um nmero qualquer e o programa responda se o nmero e par ou impar . Se for par emite a mensagem O nmero par ou caso contrrio O nmero impar . x=

32/105

LINGUAGEM C

8.

Comandos Condicionais
Neste captulo sero vistos os comandos condicionais da linguagem C.

8.1
Sintaxe:

Comando if
if (<expresso>) <comando>; else <comando>;

Onde comando pode ser um nico comando, um bloco de comandos ou nada (no caso de comandos vazios). A clusula else opcional. Exemplo 8.8 if (x != 0) x = 0; Obs.: Caso haja um else ele pertence ao if mais prximo. Exemplo 8.9 if (a > 5) { if (a < 10) b = 3; } else b = 7; No exemplo 8.2, se o comando if mais interno no fosse separado por chaves, o else pertenceria ao mesmo e no ao mais externo. Exemplo 8.10 /* Programa para adivinhar um numero */ #include stdio.h #include stdlib.h void main() { int num, tentativa; num = rand(); /*gera numero aleatorio entre 0 e 32767*/ scanf(%d, &tentativa); if (tentativa == num) printf(* * * CERTO * * *); } Lembre-se que para montar um bloco de comando somente necessrio usar o abre e fecha chaves para marcar incio e fim de bloco de comandos respectivamente.

8.2

Comando switch

C tem um comando interno de seleo mltipla, switch, que testa sucessivamente o valor de uma expresso contra uma lista de constantes inteiras ou de caractere. Sintaxe:

33/105

LINGUAGEM C switch (<expresso>) { case <valor1> : <seqncia de comandos> break; case <valor2> : <seqncia de comandos> break; default: <seqncia de comandos> } O valor da expresso testado, na ordem, contra os valores das constantes especificadas nos comandos case. Quando uma coincidncia for encontrada, a seqncia de comandos associada quele case ser executada at que o comando break ou o fim do comando switch seja alcanado. O comando default (opcional) executado no momento em que no coincidir nenhum valor. Exemplo 8.4 #include <stdio.h> void main() { char opcao; printf(1. Opcao 1 \n); printf(2. Opcao 2 \n); printf(3. Opcao 3 \n); printf(Opcao:); opcao=getchar(); switch(opcao) { case 1: printf (\nVoc escolheu a opcao 1); break; case 2: printf (\n Voc escolheu a opcao 2); break; case 3: printf (\n Voc escolheu a opcao 3); break; default: printf (\n Nenhuma opcao selecionada); break; } }

8.3

Exerccios

1. Escrever um programa que leia 3 pares de cordenadas (x,y), que definam 3 pontos e: Verificar se eles formam um tringulo : no podem estar alinhados e no podem haver pontos sobrepostos. calcular os lados do tringulo. classificar o tipo do tringulo: eqiltero, issceles ou escaleno. acutngulo, obtusngulo ou retngulo 2. Escreva um programa que leia 3 nmeros e os escreve em ordem crescente. 3. Faa um programa que leia um nmero inteiro, verifique se positivo ou negativo e escreva uma mensagem apropriada. 4. Faa um programa contendo um menu com as seguintes opes : S - soma P - produto U - subtrao D - diviso Q - sair

34/105

LINGUAGEM C O programa deve conter uma funo para executar cada tarefa pedida: soma , subtrao etc . Quando o usurio teclar ESC o programa deve terminar.

35/105

LINGUAGEM C

9.
9.1

Comandos Repititivos ou Laos


Lao for
Comando de repetio condicional com inicializao e incremento.

Sintaxe: for(inicializao; condio;incremento) comando; Onde comando um comando vazio, um comando simples, ou um bloco de comandos. Primeiro executado a inicializao que consiste em atribuies iniciais. Depois testada a condio (expresso relacional) de controle do lao. O incremento executado aps a execuo do comando ou bloco de comandos. O fim do lao determinado pelo valor falso que a condio se apresenta. Exemplo 9.11 #include stdio.h main() { int x; for(x=1; x<=100; x++) printf(%d,x); } No programa acima x inicializado com 1. Uma vez que x menor que 100, printf() executado e x incrementado em 1 e testado para ver se ainda menor ou igual a 100. Esse processo se repete at que x fique maior que 100; nesse ponto, o lao termina. Ento este programa imprime na tela os nmeros de 1 a 100.

9.2

Lao while
Comando de repetio condicional.

Sintaxe:

while(condio) comando;

Onde comando um comando vazio, uma comando simples, ou um bloco de comandos. Primeiro testada a condio (expresso relacional) de controle do lao. E a cada execuo de comando repetido o teste de condio. O fim do lao determinado pelo valor falso que a condio se apresenta. Exemplo 9.12 #include stdio.h main() { int cont=0; char ch; while((c=getchar()) != 0) cont++; printf(Foram lidos %d caracteres,cont); }

36/105

LINGUAGEM C

9.3

Lao do-while

Ao contrrio dos comandos for e while, que testam a condio do lao no comeo, o lao dowhile verifica a condio ao final do lao. Sintaxe: do <comando> while(condio); Exemplo 9.2 #include <stdio.h> void main() { char opcao; printf(1. Opcao 1 \n); printf(2. Opcao 2 \n); printf(3. Opcao 3 \n); printf(Opcao:); do { opcao=getchar(); switch(opcao) { case 1: printf (\nVoc escolheu a opcao 1); break; case 2: printf (\n Voc escolheu a opcao 2); break; case 3: printf (\n Voc escolheu a opcao 3); break; printf (\n Nenhuma opcao selecionada); break; }} while (opcao != 1 && opcao != 2 && opcao != 3); } default:

9.4

Comandos break, continue e exit()

O comando break pode ser usado no corpo de qualquer estrutura de lao C. Causa a sada imediata do lao e o controle passa para o prximo comando do programa. Sintaxe: break;

O comando continue fora a prxima iterao do lao e pula o cdigo que estivar abaixo. Nos laos while e do-while um comando continue faz com que o controle do programa v diretamente para o teste condicional e depois continue o processo do lao. Sintaxe: continue; Da mesma forma que pode-se sair de um lao, pode-se sair de um programa usando a funo exit() da biblioteca padro. Essa funo provoca uma terminao imediata do programa inteiro, forando um retorno ao sistema operacional. Sintaxe: void exit(int cdigo_de_retorno);

37/105

LINGUAGEM C O valor de cdigo_de_retorno retornado ao processo chamador (sistema operacional). O zero geralmente usado como um cdigo de retorno que indica uma terminao normal do programa. Exemplo 9.3 #include <stdio.h> void main() { char opcao; printf(1. Opcao 1 \n); printf(2. Opcao 2 \n); printf(3. Opcao 3 \n); printf(4. Abandonar \n); printf(Opcao:); do { opcao=getchar(); switch(opcao) { case 1: printf (\nVoc escolheu a opcao 1); break; case 2: printf (\n Voc escolheu a opcao 2); break; case 3: printf (\n Voc escolheu a opcao 3); break; case 4: exit(0); /* retorna ao SO */ }} while (opcao != 1 && opcao != 2 && opcao != 3); }

9.5

Exerccios

1. Escreva um programa para calcular o fatorial de um nmero lido. 2. Escreva um programa para ler um caracter de comparao e vrios caracteres de entrada finalizados por 0 e contar o nmero de vezes que o caracter de comparao apareceu. 3. Escrever um programa que mostre os nmeros primos entre 1 e 100. 4. Escreva um programa que leia um nmero no determinado de valores positivos, e mostre a soma e mdia dos respectivos nmeros ao ser lido um valor negativo. 5. Faa um programa que leia um nmero (inteiro) e escreva todos os seus divisores. 6. Faa um programa que leia um nmero de no mximo 3 dgitos e escreva-o na tela. 7. Faa um programa que receba como entrada uma quantia em dinheiro e mostre na tela a quantidade de notas de 5, 10, 50 e 100 so necessrias para representar o valor. O programa deve contabilizar a partir das notas de 100. 8. Suponha um nmero N qualquer: se N par ento N agora N / 2; se N mpar N agora 3*N + 1. Assim para N = 3 calculamos a seguinte tabela : 3 10 42 10 5 21 5 16 14 16 8 42 8 4 21 Observe que a partir de sete iteraes a seqncia 4 2 1 comea a se repetir . Faa um programa que calcule para um dado N o nmero de iteraes at se chegar ao primeiro 1 .

38/105

LINGUAGEM C 9. Faa um programa que imprima os elementos de uma PA e o somatrio da mesma dados : primeiro termo , numero de termos e razo 10. Faa um programa que imprima um elemento da seqncia de Fibonacci , dado o numero do elemento. 11. Faa um programa onde o usurio entra com um nmero decimal e o mesmo calcula e imprime o nmero no sistema binrio . 12. Faa um programa onde o usurio entra com dois nmeros A e B o programa devolve como resultado A elevado a B . 13. Escreva um programa que solicite ao usurio trs nmeros inteiros a,b,c onde a maior que 1 . Seu programa deve somar todos os inteiros entre b e c divisveis por a .

39/105

LINGUAGEM C

10.

Funes
A forma geral de uma funo :

Sintaxe:

tipo_funo nome_funo (lista_de_parmetros) declarao_parmetros { corpo_funo; }

Exemplo 10.13 int soma(int x, int y) { ... }

ou int soma(x, y) int x,y; { ... } As funes retornam um valor (do tipo indicado em tipo_funo). O valor retornado pela funo dado pelo comando return (o valor retornado pode ou no ser utilizado). Existem dois tipos de passagem de argumentos: por valor e por referncia. A segunda realizada atravs de apontadores. Exemplo 10.14 int pot(x,n) int x,n; { int p; for(p=1;n>0;n--) p *= x; return p; } /* x elevado na n potncia */

No exemplo 11.2, os argumentos foram passados por valor e a funo retorna um valor do tipo inteiro. A chamada seria: a = pot(10,2); No exemplo 11.3, nenhum valor retornado (por isso usa-se o tipo void) mas realizado uma troca dos valores das variveis, necessitando de uma passagem de parmetros por referncia. Exemplo 10.15 void troca(a,b) int *a, *b; { int aux; aux = *a; *a = *b; /* troca os valores das variveis */ /* usa-se ponteiros para referenciar */ /* o contedo do endereo da varivel */

40/105

LINGUAGEM C

*b = aux; } A chamada para esta funo seria: int x=1,y=2; troca(&x,&y); Na passagem de parmetros por referncia passado explicitamente o endereo da varivel com o uso do operador &. Quando o argumento for uma matriz automaticamente ser passado o endereo da matriz para a funo. A linguagem C aceita chamadas recursivas de funes.

10.1

Localizao das funes

Existem basicamente duas posies possveis para escrevermos o corpo de uma funo: ou antes ou depois do programa principal. Podemos ainda escrever uma funo no mesmo arquivo do programa principal ou em arquivo separado.

10.1.1 Corpo da funo antes do programa principal (no mesmo arquivo)


Quando escrevemos a definio de uma funo antes do programa principal e no mesmo arquivo deste, nenhuma outra instruo necessria. Exemplo 10.4 float media2(float a, float b){ float med; med = (a + b) / 2.0; return(med); } // funo

void main(){ // programa principal float num_1, num_2, med; puts(Digite dois nmeros:); scanf(%f %f, &num_1, &num_2); med = media2(num_1, num_2); // chamada da funo printf(\nA media destes nmeros e %f, med); }

10.1.2 Corpo da funo depois do programa principal (no mesmo arquivo)


Quando escrevemos a definio de uma funo depois do programa principal e no mesmo arquivo deste, devemos incluir um prottipo da funo chamada. Um prottipo uma instruo que define o nome da funo, seu tipo de retorno e a quantidade e o tipo dos argumentos da funo. O prottipo de uma funo indica ao compilador quais so as funes usadas no programa principal os tipo. A sintaxe geral para isto a seguinte: Sintaxe: void main(){ tipo nomef(...); ... // programa principal // prottipo da funo

41/105

LINGUAGEM C var = nomef(...) ... } tipo nomef(...){ [corpo de funo] } Exemplo 10.5 void main(){ // programa principal float media2(float,float); // prottipo de media2() float num_1, num_2, med; puts(Digite dois nmeros:); scanf(%f %f, &num_1, &num_2); med = media2(num_1, num_2); // chamada a funo printf(\nA media destes nmeros e %f, med); } float media2(float a, float b){ // funo media2() float med; med = (a + b) / 2.0; return(med); } Observe que o prottipo de uma funo nada mais que a declarao da funo sem o seu corpo. Observe ainda que na lista de argumentos do prottipo podem ser escritos apenas os tipos dos argumentos. // definio da funo // chamada a funo

10.1.3 Corpo da funo escrito em arquivo separado


Em C, como em muitas outras linguagens, permitido que o usurio crie uma funo em um arquivo e um programa que a chame em outro arquivo distinto. Esta facilidade permite a criao de bibliotecas de usurio: um conjunto de arquivos contendo funes escritas pelo usurio. Esta possibilidade uma grande vantagem utilizada em larga escala por programadores profissionais. Quando escrevemos a definio de uma funo em arquivo separado do programa principal devemos incluir este arquivo no conjunto de arquivos de compilao do programa principal. Esta incluso feita com a diretiva #include. Esta diretiva, vista nas sees 2.4.2 e 3.7.1, instrui o compilador para incluir na compilao do programa outros arquivos que contem a definio das funes de usurio e de biblioteca. Sintaxe: #include path void main(){ ... var = nomef(...) ... } // incluso da funo // programa principal // chamada a funo

Na diretiva #include, indicamos entre aspas duplas o caminho de localizao do arquivo onde est definida a funo chamada. Exemplo 10.6 #include c:\tc\userbib\stat.h void main(){ // incluso da funo // programa principal

42/105

LINGUAGEM C float num_1, num_2, med; puts(Digite dois nmeros:); scanf(%f %f, &num_1, &num_2); med = media2(num_1, num_2); // chamada a funo printf(\nA media destes nmeros e %f, med); }

10.2

Argumentos para funo main()

A funo main() aceita argumentos para a passagem de parmetros realizada atravs da chamada do programa. Os dois argumentos so: argc: contador de argumentos; argv: vetor de argumentos (vetor de apontadores para strings). Sintaxe: main(int argc, char *argv[]) importante lembrar que Exemplo 10.7 #include stdio.h void main(int argc, char *argv[]) { int cont; printf(Foram encontrados %d argumentos \n,argc -1); for (cont=1;cont < argc;cont++) printf(Argumento %d: %s \n, cont, argv[cont]); } O primeiro argumento (argv[0]) o nome do programa.

10.3

Prottipo de funes

O padro ANSI C expandiu a declarao tradicional de funo, permitindo que a quantidade e os tipos dos argumentos das funes sejam declarados. A definio expandida chamada prottipo de funo. Prottipos de funes no faziam parte da linguagem C original. Prottipos permitem que C fornea uma verificao mais forte dos tipos. Prottipos de funes ajudam a detectar erros antes que eles ocorram. verificado nmero de parmetros, compatibilidade de tipos, entre outras. Existem trs tipos de declarao de prottipos: Sintaxe tipo_funo nome_funo(); tipo_funo nome_funo(lista_tipo_argumentos); tipo_funo nome_funo(lista_tipo_nome_argumentos); Exemplo int pot(); int pot(int,int); int pot(int x, int y);

10.4

Retorno de Ponteiros

Ponteiros para variveis no so variveis e tampouco inteiros sem sinal. So endereo na memria de um certo tipo de dado. A forma geral : Sintaxe:

43/105

LINGUAGEM C tipo_funo *nome_funo(lista_de_argumentos);

10.5

Nmeros de parmetros varivel

Em C, pode-se especificar uma funo que possui a quantidade e os tipos de parmetros variveis. O exemplo mais comum printf(). Para informar ao compilador que um nmero desconhecido de parmetros ser passado para uma funo, deve-se terminar a declarao dos seus parmetros usando trs pontos. Por exemplo, essa declarao especifica que func() ter ao menos dois parmetros inteiros e um nmero desconhecido (incluindo 0) de parmetros aps eles. func(int a, int b, ...); Essa forma de declarao tambm usada por um prottipo de funo. Qualquer funo que usa um nmero varivel de argumentos deve ter pelo menos um argumento verdadeiro. Por exemplo, isso est incorreto: func(...); Para poder utilizar esta caracterstica tem-se que utilizar as funes descritas na prxima seo.

10.5.1 Funes para nmero varivel de argumentos


Para este tipo de aplicao necessrio o uso de trs macros definidas em STDARG.H: va_arq(), va_start() e va_end(). Sintaxe: void va_arg(va_list argptr, type); type va_start(va_list argptr, last_parm); void va_end(va_list argptr); O tipo va_list definido em STDARG.H. O procedimento geral para criar uma funo que pode receber um nmero varivel de argumentos o seguinte: a funo deve ter pelo menos um parmetro conhecido, podendo, porm, ter mais anterior lista varivel de parmetros. O parmetro conhecido, mais direita, last_parm. Antes que qualquer dos parmetros de comprimento varivel possa ser acessado, o argumento ponteiro argptr deve ser inicializado atravs de uma chamada va_start(). Em seguida, parmetros so devolvidos via chamadas va_arg(), com type sendo o tipo do prximo parmetro. Finalmente, aps todos os parmetros terem sido lidos e antes de retornar a funo, deve ser feita uma chamada va_end() para garantir que a pilha seja corretamente restaurada. Se va_end() no for chamada, muito provvel que ocorra um crash do programa. No exemplo abaixo, utiliza-se sum_series() para devolver a soma de uma srie de nmeros. O primeiro argumento contm o nmero de argumentos que se sucedem. #include stdio.h #include stdarg.h double sum_series(int num, ...); void main() { double d, sum_series(); d = sum_series(5, 0.5, 0.25, 0.125, 0.0625, 0.03125); printf(soma da serie: %f \n,d); }

44/105

LINGUAGEM C

double sum_series(int num, ...) { double sum=0.0, t; va_list argptr; va_start(argptr,num); /* inicializa argptr */ for (;num;num--) /* soma a serie */ { t = va_arg(argptr,double); sum += t; } va_end(argptr); /* finaliza a lista de argumentos */ return sum; }

10.6

Classes de Armazenamento
So quatro as classes de armazenamento de variveis C: auto extern static register (automticas) (externas) (estticas) (em registradores)

10.6.1 Classe de Armazenamento - auto


As variveis declaradas nos exemplos anteriores s podem ser acessadas somente s funes onde esto declaradas. Tais variveis so chamadas locais ou automticas, so criadas quando a funo chamada e destrudas quando a funo ou o bloco de cdigo termina a sua execuo. As variveis declaradas dentro de uma funo so automticas por padro. A classe de variveis automticas pode ser explicitada usando-se a palavra auto. O cdigo main() { auto int x; ... } main() { int x; ... }

equivalente a

10.6.2 Classe de Armazenamento - extern


Toda varivel declarada fora de qualquer funo tm a classe de armazenamento extern. Como pode-se somente uma nica vez declarar uma varivel global, ao usar diversos arquivos para um mesmo programa (por ser grande, por exemplo) deve-se utilizar a declarao extern nos outros arquivos onde a varivel utilizada. Se no proceder assim, o compilador acusar um erro de duplicidade de varivel. Exemplo 10.8 Arquivo 1 int x,y; char ch; main() { ... } func1() { x = 123;

45/105

LINGUAGEM C

} } Arquivo 2

x = y / 10;

extern int x,y; extern char ch; func22() { No arquivo 2, a lista de variveis globais foi copiada do arquivo 1 e o especificador extern foi adicionado s declaraes. O especificador extern diz ao compilador que os tipos de varivel e nomes que o seguem foram declarados em outro lugar. Isto , o compilador no reserva um espao de memria para essas variveis declaradas com o especificador extern na certeza de estarem declaradas em outro mdulo.

func23() { y = 10; }

10.6.3 Classe de Armazenamento - static


Dentro de sua prpria funo ou arquivo, variveis static so variveis permanentes. Ao contrrio das variveis globais, elas no so reconhecidas fora de sua funo ou arquivo, mas mantm seus valores entre chamadas. O especificador static tem efeitos diferentes em variveis locais e em variveis globais.

10.6.3.1

Variveis Locais static

Quando o modificador static aplicado a uma varivel local, o compilador cria armazenamento permanente para ela quase da mesma forma como cria armazenamento para uma varivel global. Em termos simples, uma varivel local static uma varivel local que retm seu valor entre chamadas. Mas ela s reconhecida apenas no bloco em que est declarada.

10.6.3.2

Variveis Globais static

Quando o modificador static aplicado a uma varivel global, o compilador cria uma varivel que reconhecida apenas no arquivo na qual a mesma foi declarada.

10.6.4 Classe de Armazenamento - register


A classe de armazenamento register indica que a varivel associada deve ser guardada fisicamente numa memria de acesso muito mais rpido, chamada registrador. No caso do IBM-PC pode ser colocado o tipo int e char associado a register pois o registrador tem apenas 16 bits. Basicamente, variveis register so usadas para aumentar a velocidade de processamento. Por exemplo, variveis de uso freqente como variveis de laos e argumentos de funes.

10.7

Diretiva #define

A diretiva #define pode ser usada para definir constantes simblicas com nomes apropriados. Por exemplo, a constante PI pode ser definida com o valor 3.14159. #define PI 3.14159 S pode ser escrito um comando destes por linha, e no h ponto-e-vrgula aps qualquer diretiva do pr-processador.

46/105

LINGUAGEM C Esta diretiva usada para definir macros com argumentos. #define AREA(x) (4*PI*x*x) A declarao acima define a funo AREA() a qual calcula a rea de uma esfera. A vantagem desta declarao no tipagem do argumento x. No deve haver espaos entre o nome da macro e seus identificadores.

10.8

Funes Recursivas

Uma funo dita recursiva quando se definida dentro dela mesma. Isto , uma funo e recursiva quando dentro dela est presente uma instruo de chamada a ela prpria. Exemplo 10.9 // imprime uma frase invertida . Usa recursao #include <stdio.h> #include <conio.h> void inverte( ) void main( ) { clrscr( ); inverte( ); getch(); } void inverte ( ) { char ch ; if ((ch=getche( )) != \r ) inverte( ); scanf(%c,ch) }

10.9

Exerccios

1. Escreva um programa que receba como parmetro um ndice (float). Aps, ler uma sequncia de nmeros (a qual termina por 0) e exibir o seu valor multiplicado pelo ndice. A funo que transforma uma string em um float atof(char *x). 2. Escreva uma funo que receba um caracter como argumento e que retorne a letra maiscula se a mesma for minscula. funes: islower(int ch), toupper(int ch). 3. Escreva uma funo que calcule o fatorial de forma recursiva. 4. Implementar as seguintes funes: strlen() strcat() strcpy()

47/105

LINGUAGEM C

11.

Vetores e Matrizes

Vetores e matrizes so estruturas de dados usada para representar uma certa quantidade de variveis de valores homogneos. Em C, estas estruturas precisam ser declaradas, como quaisquer outras variveis, para que o compilador conhea o tipo do vetor ou da matriz e reserve espao de memria suficiente para armazen-lo. O que diferencia a declarao de uma matriz ou vetor da declarao de qualquer varivel a parte que segue o nome, isto , os pares de colchetes ([ e ]) que envolvam um nmero inteiro, que indica ao compilador o tamanho da matriz. int notas[5]; A declarao acima aloca um intervalo de memria com nome notas para armazenar 5 elementos do tipo int. Por definio um vetor ou matriz composto por elementos de um nico tipo. Para a declarao de mais de uma dimenso em C necessrio o nmero de par de colchetes ser igual ao nmero de dimenses. Isto , se a matriz for de duas dimenses teremos uma declarao assim: int notas[5][5]; que declara uma matriz bi-dimensional; para trs dimenses assim int notas[5][5][5]; que declara uma matriz tridimensional e assim por diante. O limite de ndices definido pelo compilador ou pela memria. Os elementos do vetor ou da matriz so sempre enumerados por ndices iniciados por 0 (zero). Exemplo 11.16 for (i=0;i<5;i++) { printf(Digite a nota do aluno %d:,i); scanf(%d, &notas[i]); } Obs.: A linguagem C no realiza verificao de limites em matrizes!!!

11.1

Inicializao de Vetores e Matrizes

Como o C permite a inicializao de variveis bsicas, tambm permitido a inicializao de vetores e matrizes. Exemplo 11.2 int TAB[5]={1,5,10,15,20} int MAT[5][6]={ { 1, 0, 1, { 0, 1, 0, { 1, 0, 1, { 0, 1, 0, { 1, 0, 1, 0, 1, 0, 1, 0, 1, 0, 1, 0, 1, 0 1 0 1 0 }, }, }, }, } };

Obs.: Quando houver uma inicializao de um vetor ou uma matriz na declarao, pode-se suprimir sempre o valor do primeiro colchete, isto , pelo nmero de argumentos ele assume o nmero do primeiro colchete.

48/105

LINGUAGEM C

Exemplo 11.3 int TAB[]={1,5,10,15,20} int MAT[][6]={ { { { { { 1, 0, 1, 0, 1, 0, 1, 0, 1, 0, 1, 0, 1, 0, 1, 0, 1, 0, 1, 0, 1, 0, 1, 0, 1, 0 1 0 1 0 }, }, }, }, } };

11.2

Matrizes e Vetores como argumento de Funes

O C permite que passe matrizes ou vetores como argumento de uma funo. Mas h uma peculiaridade na passagem de parmetros: a forma como ela passada. O nome de uma matriz ou vetor desacompanhado de colchetes equivalente ao endereo da matriz ou do vetor, isto , passagem por referncia. Quando o nome estiver acompanhado de um indexador passado como argumento o contedo daquela posio da matriz ou do vetor, isto , passagem por valor.

11.3

Limites

Na linguagem C, devemos ter cuidado com os limites de um vetor. Embora na sua declarao, tenhamos definido o tamanho de um vetor, o C no faz nenhum teste de verificao de acesso a um elemento dentro do vetor ou no. Por exemplo se declaramos um vetor como int valor[5], teoricamente s tem sentido usarmos os elementos valor[0], ..., valor[4]. Porm, o C no acusa erro se usarmos valor[12] em algum lugar do programa. Estes testes de limite devem ser feitos logicamente dentro do programa. Este fato se deve a maneira como o C trata vetores. A memria do microcomputador um espao (fsico) particionado em pores de 1 byte. Se declaramos um vetor como int vet[3], estamos reservando 6 bytes (3 segmentos de 2 bytes) de memria para armazenar os seus elementos. O primeiro segmento ser reservado para vet[0], o segundo segmento para vet[1] e o terceiro segmento para vet[2]. O segmento inicial chamado de segmento base, de modo que vet[0] ser localizado no segmento base. Quando acessamos o elemento vet[i], o processador acessa o segmento localizado em base+i. Se i for igual a 2, estamos acessando o segmento base+2 ou vet[2](o ultimo segmento reservado para o vetor). Porm, se i for igual a 7, estamos a acessando segmento base+7 que no foi reservado para os elementos do vetor e que provavelmente est sendo usado por uma outra varivel ou contm informao espria (lixo). Observe que acessar um segmento fora do espao destinado a um vetor pode destruir informaes reservadas de outras variveis. Estes erros so difceis de detectar pois o compilador no gera nenhuma mensagem de erro... A soluo mais adequada sempre avaliar os limites de um vetor antes de manipul-lo. A princpio este fato poderia parecer um defeito da linguagem, mas na verdade trata-se de um recurso muito poderoso do C. Poder manipular sem restries todos os segmentos de memria uma flexibilidade apreciada pelos programadores.

49/105

LINGUAGEM C

11.4

Strings

Em C no existe um tipo de dados string como na linguagem "Pascal". Ao contrrio, as string so implementadas como cadeia de caracteres, terminados pelo caracter null (\0). O caracter null serve como uma marca de fim de string para as funes que lidam com strings. Como em qualquer vetor, os caracteres da string podem ser individualmente acessados. A declarao: char nome[15]; reserva um espao de memria para uma string de tamanho 14, pois o dcimo-quinto byte para o caracter null. A manipulao de strings pode ser feita atravs de funes ou elemento a elemento como se fosse um vetor. Exemplo 11.4 char str[2]; str[0] = U; str[1] = /0;

/* Caracter NULL para finalizar string */

Como todo vetor as strings podem ser inicializadas, como mostram o exemplo 10.5: Exemplo 11.5 char nome[]={C,a,r,l,o,s,\0}; char nome[]=Carlos; char nomes[][8]={Eduardo, Andre, Adriana, Carla, Jose};

11.4.1 Leitura de Strings


Para ler uma string pode-se utilizar a funo scanf() ou a funo gets() da biblioteca C para receber a string.

11.4.1.1

Funo scanf()

A funo scanf() bastante limitada para a leitura de strings. Pois no pode haver espaos em branco na string lida. O que vier aps o espao em branco eliminado. Exemplo 11.6 #include <stdio.h> main() { char nome[15]; printf(Digite seu nome:); scanf(%s,&nome); printf(Saudacoes %s,nome); } Execuo

50/105

LINGUAGEM C

Digite seu nome: Carlos Alberto Saudacoes, Carlos

11.4.1.2

Funo gets()

A funo gets() bastante conveniente para a leitura de strings. O seu propsito unicamente ler uma string da sua entrada padro que por default o teclado. Visto que uma string no tem um tamanho pr-determinado, gets() l caracteres at encontrar o de nova linha (\n) que gerado ao pressionar a tecla [Enter]. Todos os caracteres anteriores ao \n so armazenados na string e ento includo o caractere \0. Caracteres brancos como espaos e tabulaes so aceitveis como parte da string. Exemplo 11.7 #include <stdio.h> main() { char nome[15]; printf(Digite seu nome:); gets(nome); printf(Saudacoes %s,nome); } Execuo Digite seu nome: Carlos Alberto Saudacoes, Carlos Alberto

11.4.2 Escrita de Strings


Para escrever uma string pode-se utilizar a funo printf() ou a funo puts() da biblioteca C.

11.4.2.1

Funo printf()

A funo printf() ao imprimir a string no realiza uma nova linha, como definido na sua implementao. Em compensao uma funo que pode ser usada para impresso de mais que uma string por linha.

11.4.2.2

Funo puts()

A funo puts() o complementa de gets(). O seu propsito unicamente imprimir a string apontada pelo seu argumento. O endereo desta string deve ser mandado para puts() como argumento. O prximo exemplo ilustra algumas das muitas possibilidades de seu uso. /* mostra o uso de putc() */ #include <stdio.h> main() { char nome[81]; puts(Digite seu nome:); gets(nome); puts(Saudacoes, );

51/105

LINGUAGEM C

puts(nome); puts(puts() pula de linha sozinha); puts(&nome[4]); } Execuo Digite seu nome: Carlos Alberto Saudacoes, Carlos Alberto puts() pula de linha sozinha los Alberto A funo puts() reconhece /0como fim de string. Cada impresso de puts(), ele acaba com um caracter de nova linha. Utilizando a funo printf() o mesmo efeito seria: printf(%s\n,nome); puts(nome);

11.4.3 Funes de Manipulao de Strings


Como strings so implementadas como vetores, os operadores usuais no podem ser aplicados sobre este tipo de dado. Por exemplo: comparao atribuio no so suportados por este tipo de dado. As funes descritas nas prximas sees utilizam o cabealho padro STRING.H.

11.4.3.1
contado. Sintaxe:

Funo strlen()

Devolve o comprimento da string terminada por um nulo apontada por str. O nulo no

size_t strlen(char *str); Exemplo 11.8 printf(%d,strlen(ola)); /* O resultado 3 */

11.4.3.2

Funo strcat()

Concatena uma cpia de str2 em str1 e termina str1 com um nulo. Como no existe verificao de limites, de inteira responsabilidade do usurio que o tamanho de str1 seja suficientemente grande para armazenar seu contedo original e o de str2. Sintaxe: char *strcat(char *str1, const char *str2); Exemplo 11.9 printf(%s,strcat(ola, mundo)); /* O resultado ola mundo */

52/105

LINGUAGEM C

11.4.3.3

Funo strcmp()

Compara lexicograficamente duas strings e devolve um inteiro baseado no resultado como mostrado aqui: Valor Menor que zero Zero Maior que zero Sintaxe: Significado str1 menor que str2 str1 igual a str2 str1 maior que str2

int strcmp(const char *str1, const char *str2);

11.4.3.4

Funo strcpy()

Copia o contedo de str2 em str1. str2 deve ser um ponteiro para uma string terminada com um nulo. A funo strcpy() devolve um ponteiro para str1. Sintaxe: char *strcpy(char *str1, const char *str2); Exemplo 11.10 char str[80]; strcpy(str, mundo); /* copia mundo na string str */

11.4.3.5

Funo strchr()

Devolve um ponteiro primeira ocorrncia do byte menos significativo de ch na string apontada por str. Se no for encontrada nenhuma coincidncia, ser devolvido um ponteiro nulo. Sintaxe: char *strchr(const char *str, int ch);

11.4.3.6

Funo strstr()

Devolve um ponteiro primeira ocorrncia da string apontada por str2 na string apontada por str1. Se no for encontrada nenhuma coincidncia, ser devolvido um ponteiro nulo. Sintaxe: char *strstr(const char *str1, const char *str2);

11.4.4 Exemplo Geral


O programa abaixo exemplifica o uso das funes descritas anteriormente. Exemplo 11.11 #include stdio.h #include string.h void main()

53/105

LINGUAGEM C

{ char s1[80], s2[80]; gets(s1); gets(s2); printf(comprimento: %d %d \n, strlen(s1), strlen(s2)); if (!strcmp(s1,s2)) printf(As strings sao iguais\n); strcat(s1,s2); printf(%s\n,s1); strcpy(s1, Isso e um teste \n); printf(s1); if (strchr(alo,o)) printf(o esta em alo \n); if (strstr(ola aqui, ola)) printf(ola encontrado); } Ao rodar este programa e entrar com as strings ola e ola, a sada ser comprimentos: 3 3 As strings so iguais aloalo Isso e um teste o esta em alo ola encontrado

11.5
1. 2. 3.

Exerccios
Faa um programa que leia 10 valores inteiros e escreva-os na ordem inversa a que foram lidos.

Faa um programa que leia 10 valores inteiros, calcule sua mdia e escreva todos os valores que esto abaixo da mdia. Calcular os nmeros primos entre 0 e 100 (inclusive) utilizando o crivo de Eritstenes: Usar um vetor de 101 inteiros; zerar o vetor; repetir de 2 a 100 para cada nmero: somar 1 a todos os contadores dos seus mltiplos. ao final os nmeros que possuem 0 no vetor so primos. Escreva um programa que leia um vetor de 100 posies e mostre-o em ordem crescente e decrescente. Faa um programa que leia uma matriz M[10][10] e some todos os elementos abaixo da diagonal principal. Faa um programa que leia 3 nomes (at 30 letras) e os escreva em ordem alfabtica. Escreva um programa que leia um nmero indeterminado de caracteres e conta o nmero de vezes que cada letra (A-Z) aparece: Desconsiderar se a letra maiscula ou minscula; Termina com o caracter 0.

4. 5. 6. 7.

8. 9.

Faa um programa que leia uma matriz M[4][4] e mostra a sua transposta. Escreva um programa cuja execuo se segue abaixo :

54/105

LINGUAGEM C digite uma frase : carlos <enter> digite uma letra dessa frase : r <enter> rlos 10. Escreva uma funo que realize a multiplicao de matrizes. 11. Escrever a funo atoi() (recebe uma string como parmetro e transforma em um inteiro). 12. Faa um programa que use a funo (definida por voc) : char *concat( char *s1 , char * s2) . A funo retorna um ponteiro que a concatenao de s2 com s1 . Exemplo de chamada : char mat1[80]=casa ; char mat2[80]=grande; char *p; p = concat(mat1,mat2); printf( %s,p); 13. Escreva uma funo que receba um vetor e o tamanho do mesmo e troque os elementos (1 com o ltimo, o 2 com o penltimo e assim por diante).

55/105

LINGUAGEM C

12. Ponteiros
Para uma boa utilizao dos ponteiros deve-se compreender corretamente o seu uso. Existem trs razes para isso: primeiro, ponteiros fornecem os meios pelos quais as funes podem modificar seus argumentos; segundo, eles so usados para suportar as rotinas de alocao dinmica de C, e terceiro, o uso de ponteiros para aumentar a eficincia de certas rotinas. Por ser um dos aspectos mais poderosos da linguagem tambm so os mais perigosos. Por erros no uso de ponteiros (como a no inicializao de ponteiros - ponteiros selvagens) podem provocar quebra do sistema. Por definio, um ponteiro uma varivel que contm um endereo de memria. Esse endereo normalmente uma posio de uma outra varivel na memria. Uma declarao de ponteiros consiste no tipo base, um "*" e o nome da varivel. A forma geral : tipo *nome; onde tipo qualquer tipo vlido em C e nome o nome da varivel ponteiro. O tipo base do ponteiro define que tipo de variveis o ponteiro pode apontar. Basicamente, qualquer tipo ponteiro pode apontar para qualquer lugar, na memria. Mas, para a aritmtica de ponteiros feita atravs do tipo base. Os operadores utilizados so * e &, como j foi explicado na seo 6.6.

12.1

Expresses com Ponteiros


Nesta seo sero analisados alguns aspectos especiais de expresses com ponteiros.

12.1.1 Atribuio de Ponteiros


Como o caso com qualquer varivel, um ponteiro pode ser usado no lado direito de um comando de atribuio para passar seu valor para um outro ponteiro. Exemplo 12.17 #include stdio.h void main() { int x; int *p1,*p2; tipo base int. */ p1 = &x; p2 = p1; printf(%p,p2); valor */ }

/* declarao do ponteiro p1 e p2 com o

/* escreve o endereo de x, no seu

Agora, tanto p1 quanto p2 apontam para x. O endereo de x mostrado usando o modificador de formato de printf() %p, que faz com que printf() apresente um endereo no formato usado pelo computador hospedeiro.

56/105

LINGUAGEM C

12.1.2 Aritmtica de Ponteiros


Existem apenas duas operaes aritmticas que podem ser usadas com ponteiros: adio e subtrao. Os operadores permitidos no caso seriam: +, -, ++, --. O incremento sempre realizado do tamanho bsico de armazenamento do tipo base. Isto , se o tipo base for um inteiro e incrementarmos em uma unidade, o apontador apontar para o prximo inteiro (no caso do inteiro ocupar 2 bytes o incremento ser de dois bytes), no caso de um caracter (char) ser de um byte. Exemplo 12.18 int *ptri=3000; char *ptrc=4000; float *ptrf=4000; ptri++; ptrc++; ptrf++; ptri = ptri - 10; ptrc = ptrc - 10; ptrf = ptrf - 10;

/* /* /* /* /* /*

ptri ptrc ptrf ptri ptrc ptrf

apontar apontar apontar apontar apontar apontar

para para para para para para

o o o o o o

endereo endereo endereo endereo endereo endereo

3002 4001 5004 2982 3991 4964

*/ */ */ */ */ */

Alm de adio e subtrao entre um ponteiro e um inteiro, nenhuma outra operao aritmtica pode ser efetuada com ponteiros. Isto , no pode multiplicar ou dividir ponteiros; no pode aplicar os operadores de deslocamento e de mascaramento bit a bit com ponteiros e no pode adicionar ou subtrair o tipo float ou o tipo double a ponteiros. Lembre-se! No altera-se o valor de um ponteiro constante (ponteiro para um tipo bsico - int, float double, entre outros), somente de um ponteiro varivel (ponteiro de estruturas complexas vetores, matrizes, strings, entre outros).

12.2

Inicializao de Ponteiros

Aps um ponteiro ser declarado, mas antes que lhe seja atribudo um valor, ele contm um valor desconhecido. Ao usar este ponteiro antes de inicializar, provavelmente provocar uma falha do programa ou at do sistema operacional. Como um ponteiro nulo assumido como sendo no usado, pode-se utilizar o ponteiro nulo para fazer rotinas fceis de codificar e mais eficientes. Por exemplo, pode-se utilizar um ponteiro nulo para marcar o fim de uma matriz de ponteiros. Uma rotina que acessa essa matriz sabe que chegar ao final ao encontrar o valor nulo. A funo search(), mostrada no exemplo 13.11, ilustra esse tipo de abordagem. Exemplo 12.19 /* procura um nome */ search(char *p[], char *name) { register int t; for (t=0;p[t];++t) if(!strcmp(p[t],name)) return t; retrun -1; /* no encontrado */ } O lao for dentro de search() executado at que seja encontrada uma coincidncia ou um ponteiro nulo. Como o final da matriz marcado com um ponteiro nulo, a condio de controle do lao falha quando ele atingido.

57/105

LINGUAGEM C Uma outra utilizao de inicializao de ponteiros a inicializao de strings. Isto pode ser levado como uma variao no tema de inicializao usado na varivel argv. Exemplo 12.20 char *p= alo mundo \n; O ponteiro p (exemplo 13.12) no uma matriz, mas como o compilador C cria uma tabela de strings, a constante string colocada em tal tabela sendo que a mesma pode ser utilizada em todo o programa como se fosse uma string comum (exemplo 13.13). Por isso, inicializar uma matriz de strings usando ponteiros aloca menos memria que a inicializao atravs de matriz. Exemplo 12.21 #include stdio.h #include string.h char *p=alo mundo; void main() { register int t; printf(p); for (t=strlen(p) - 1; t > -1; t--) printf(%c,p[t]); }

12.2.1 Comparao de Ponteiros


possvel comparar dois ponteiros em uma expresso relacional. Exemplo 12.2 if (p<q) printf(p aponta para uma memria mais baixa que q /n); Geralmente, a utilizao de comparao entre ponteiros quando os mesmos apontam para um objeto comum. Exemplo disto a pilha, onde verificado se o ponteiro de incio e fim da pilha esto apontando para a mesma posio de memria, significando pilha vazia.

12.3

Ponteiros e Matrizes

Existe uma estreita relao entre matrizes e ponteiros. Pois C fornece dois mtodos para acessar elementos de matrizes: aritmtica de ponteiros e indexao de matrizes. Aritmtica de ponteiros pode ser mais rpida que indexao de matrizes. Normalmente utiliza-se ponteiros para acessar elementos de matrizes devido a velocidade de acesso. Exemplo 12.3 char str[80], *p1; p1 = str; Para acessar a string str pode-se utilizar estes dois mecanismos str[4] ou *(p1 + 4) /* aritmtica de ponteiros */ /* indexao de matrizes */

Os dois comandos devolvem o quinto elemento.

58/105

LINGUAGEM C *(matriz + ndice) o mesmo que matriz[ndice]. Para uma melhor compreenso ou facilidade de programao as funes de indexao trabalham com ponteiros (como mostra o exemplo 13.5 a implementao da funo puts()). Exemplo 12.4 /* Indexa s como uma matriz */ void put(char *s) { register int t; for (t=0;s[t]; ++t) putchar(s[t]); } /* Acessa s como um ponteiro */ void put(char *s) { while (*s) putchar(*s++); } No caso da passagem de parmetros possvel tratar uma matriz como se fosse um ponteiro. Exemplo 12.5 #include stdlib.h #include stdio.h #include string.h void le_tab(int *p) { register int i; for(i=0; i<20; i++) scanf(%d,(p+i)); } void mostra_tab(int *p) { register int i; for(i=0; i<20; i++) printf(%d,*(p+i)); } void main(void) { int mat[20]; le_tab(mat); mostra_tab(mat); }

12.3.1 Matrizes de Ponteiros


Ponteiros podem ser organizados em matrizes como qualquer outro tipo de dado. A declarao de uma matriz de ponteiros int, de tamanho 10, int *x[10]; Para atribuir o endereo de uma varivel inteira, chamada var, ao terceiro elemento da matriz de ponteiros, deve-se escrever x[2] = &var;

59/105

LINGUAGEM C para encontrar o valor de var, escreve-se *x[2]; Se for necessrio passar uma matriz de ponteiros para uma funo, pode ser usado o mesmo mtodo que utilizado para passar outras matrizes - simplesmente chama-se a funo com o nome da matriz sem qualquer ndice (como mostra o exemplo 13.7). Exemplo 12.6 void display_array(int *q[]) { register int t; for (t=0; t<10; t++) printf(%d,*q[t]); } Lembre-se de que q no um ponteiro para inteiros; q um ponteiro para uma matriz de ponteiros para inteiros. Portanto, necessrio declarar o parmetro q como uma matriz de ponteiros para inteiros, como mostrado no exemplo 13.7. Isto , no uma passagem de parmetros por referncia por dois motivos: primeiro, matriz como argumento de funo automaticamente passada por referncia por questo da implementao da linguagem, e segundo, uma matriz de ponteiros e consequentemente sua declarao caracterizada pelo asterisco na frente do nome da varivel. Matrizes de ponteiros so usadas normalmente como ponteiros de strings como, por exemplo, o argumento da linha de comandos argv.

12.3.2 Acessando partes de Matrizes como vetores


A linguagem C trata partes de matrizes como matrizes. Mais especificamente, cada linha de uma matriz de duas dimenses pode ser considerada como uma matriz de uma dimenso. Isto pode ser muito til no tratamento de matrizes. O exemplo 13.8 mostra a atribuio de uma linha da matriz nome para um ponteiro. Exemplo 12.7 main() { static char nome[10][10]; char *p[10]; for (i = 0;i<10;i++) p[i] = nome[i]; ordena(p); }

12.4

Indireo Mltipla

Indireo mltipla uma situao onde o ponteiro aponta para um outro ponteiro e que o mesmo aponta para um valor final. A figura 12.1 mostra o conceito de indireo mltipla. Ponteiro endereo Indireo Simples Ponteiro Ponteiro Varivel Varivel valor

60/105

LINGUAGEM C endereo endereo Indireo Mltipla Figura 12.2 Indireo simples e mltipla A indireo mltipla pode ser levada a qualquer dimenso desejada, mas raramente necessrio mais de um ponteiro para um ponteiro. Obs.: No confunda indireo mltipla com listas encadeadas. A declarao deste tipo de varivel feita colocando-se um * adicional em frente ao nome da varivel, como mostra o exemplo 13.9. Tal exemplo mostra a declarao da varivel ptrptrint como um ponteiro para um ponteiro do tipo int. Exemplo 12.22 int **ptrptrint; Para acessar o valor final apontado indiretamente por um ponteiro a um ponteiro, voc deve utilizar o operador asterisco duas vezes, como no exemplo 13.10: Exemplo 12.23 #include stdio.h void main() { int x, *p, **q; x = 10; p = &x; q = &p; printf(%d, **q); } valor

/* imprime o valor de x */

12.5

Ponteiros para Funes

A linguagem C permite apontadores para funes. Isto permitido pois toda funo tem uma posio fsica na memria que pode ser atribuda a um ponteiro. Portanto, um ponteiro de funo pode ser usado para chamar uma funo. O endereo de uma funo obtido usando o nome da funo sem parnteses ou argumentos. Mas para declarar este tipo de apontador tem que se seguir uma sintaxe especial como mostra o exemplo 13.14. Exemplo 12.24 #include stdio.h #include string.h void check(char *a, char *b, int (*cmp)()); void main() { char s1[80], s2[80]; int (*p)(); p = strcmp; gets(s1); gets(s2); check(s1,s2,p); } void check(char *a, char *b, int (*cmp)());

61/105

LINGUAGEM C

{ if (!(*cmp) (a, b)) printf(igual); else printf(diferente); } Quando a funo check() chamada, dois ponteiros para caracter e um ponteiro para uma funo so passados como parmetros. Dentro da funo check(), note como o ponteiro para funo declarado, pois esta a forma correta de se declarar este tipo de ponteiro. Os parnteses ao redor de *cmp so necessrios para que o compilador interprete o comando corretamente. Uma outra forma de fazer a chamada mostrada no exemplo 13.14 o qual dispensa o uso de um ponteiro adicional. check(s1, s2, strcmp); Uma das grandes utilidades o uso de drivers de dispositivos (placas de som, placas de vdeo, modems, entre outros) que fornecem rotinas de tratamento para aquele hardware especfico. Onde o programador l o arquivo do driver para a memria e o executa de acordo com as especificaes do fabricante. Outra utilidade o programador poder enviar a funo que se apropria para a comparao por exemplo. Isto , no caso de strings pode-se pensar em um comparador de strings genrico onde como terceiro parmetro enviado a funo que vai realizar a comparao. Antes da chamada da funo genrica pode verificar se a string composta por caracteres alfanumricos (atravs da funo isalpha()) e enviar a funo strcmp(), caso contrrio uma funo que realize uma comparao de nmeros inteiros (nesta funo conter a converso das strings em um inteiro (funo atoi()).

12.6

Mais Sobre declaraes de Ponteiros

As declaraes de ponteiros podem ser complicadas e necessrio algum cuidado na sua interpretao. principalmente em declaraes que envolvem funes e matrizes. Assim, a declarao int *p(int a); indica uma funo que aceita um argumento inteiro e retorna um ponteiro para um inteiro. Por outro lado, a declarao int (*p)(int a); indica um ponteiro para uma funo que aceita um argumento inteiro e retorna um inteiro. Nessa ltima declarao, o primeiro par de parnteses usado para o aninhamento e o segundo par, para indicar uma funo. A interpretao de declaraes mais complexas pode ser extremamente mais trabalhosa. Por exemplo, considere a declarao int *(*p)(int (*a)[]); Nessa declarao, (*p)(..) indica um ponteiro para uma funo. Por isso, int *(*p)(...) indica um ponteiro para uma funo que retorna um ponteiro para um inteiro. Dentro do ltimo par de parnteses (a especificao dos argumentos da funo), (*a)[] indica um ponteiro para um vetor. Assim int (*a)[] representa um ponteiro para um vetor de inteiros. Juntando todas as peas, (*p)(int (*a)[]) representa um ponteiro para uma funo cujo argumento um ponteiro para um vetor de inteiros. E, finalmente, a declarao original representa um ponteiro para uma funo que aceita um ponteiro para um vetor de inteiros como argumento e devolve um ponteiro para um inteiro. Lembre-se que se logo aps um identificador existir um abre parnteses indica que o identificador representa uma funo e os colchetes representam uma matriz. Os parnteses e colchetes tm maior precedncia do que qualquer operador.

62/105

LINGUAGEM C A seguir ser mostrado vrias declaraes envolvendo ponteiros e seu significado. int *p; int *p[10]; p um ponteiro para um valor inteiro p uma matriz de ponteiros com 10 elementos para valores inteiros p um ponteiro para uma matriz de inteiros com 10 elementos p uma funo que retorna um ponteiro para um valor inteiro p uma funo que aceita um argumento que um ponteiro para um caracter e retorna um ponteiro para um valor inteiro p m ponteiro para uma funo que aceita um argumento que um ponteiro para um caracter e retorna um valor inteiro p uma funo que aceita um argumento que um ponteiro para um caracter e retorna um ponteiro para uma matriz inteira de 10 elementos p uma funo que aceita um argumento que um ponteiro para uma matriz de caracter e retorna um valor inteiro p uma funo que aceita um argumento que uma matriz de ponteiros para caracter e retorna um valor inteiro p uma funo que aceita um argumento que uma matriz de caracter e retorna um ponteiro para um valor inteiro p uma funo que aceita um argumento que um ponteiro para uma matriz de caracter e retorna um ponteiro para um valor inteiro p uma funo que aceita um argumento que uma matriz de ponteiros para caracteres e retorna um ponteiro para um valor inteiro p um ponteiro para uma funo que aceita um argumento que um ponteiro para uma matriz de caracter e retorna um valor inteiro p um ponteiro para uma funo que aceita um argumento que um ponteiro para uma matriz de caracter e retorna um ponteiro para um valor inteiro p um ponteiro para uma funo que aceita um argumento que uma matriz de ponteiros para caracteres e retorna um ponteiro para um valor inteiro p uma matriz de ponteiros com 10 elementos para funes; cada funo aceita um argumento que um caracter e retorna um valor inteiro

int (*p)[10];

int *p(void);

int *p(char *a);

int (*p)(char *a);

int (*p(char *a))[10];

int p(char (*a)[]);

int p(char *a[]);

int *p(char a[]);

int *p(char (*a)[]);

int *p(char *a[]);

int (*p)(char (*a)[]);

int *(*p)(char (*a)[]);

int *(*p)(char *a[]);

int (*p[10])(char a);

63/105

LINGUAGEM C

int *(*p[10])(char a);

p uma matriz de ponteiros com 10 elementos para funes; cada funo aceita um argumento que um caracter e retorna um ponteiro para um valor inteiro p uma matriz de ponteiros com 10 elementos para funes; cada funo aceita um argumento que um ponteiro para um caracter e retorna um ponteiro para um valor inteiro

int *(*p[10])(char *a);

12.7

Exerccios

1. Como referenciar mat[x][y] em notao de ponteiros. 2. Qual ser a sada deste programa? main() { int i=5; int *p; p = &i; printf(%u %d %d %d %d \n, p, *p+2,**&p,3**p,**&p+4); } 3. Escreva uma funo que inverta a ordem dos caracteres de uma string. 4. Crie uma funo que receba como parmetro uma matriz de ponteiros para strings e devolve a matriz ordenada. 5. Faa uma funo que receba um ponteiro para uma matriz e que realize a ordenao da mesma. 6. Faa a declarao de uma funo (nome: teste) que receba um ponteiro para uma funo que possui dois argumentos (int e char) e retorne um ponteiro para um float. 7. Faa a declarao e inicializao de uma matriz de ponteiros para os dias da semana. 8. Faa uma funo que receba uma matriz de ponteiros para caracteres e realize a ordenao alfabtica da mesma.

64/105

LINGUAGEM C

13. Estruturas e Unies


A linguagem C permite criar tipos de dados definveis pelo usurio de cinco formas diferentes. A primeira estrutura, que um agrupamento de variveis sobre um nome e, algumas vezes, chamada de tipo de dado conglomerado. O segundo tipo definido pelo usurio o campo de bit, que uma variao da estrutura que permite o fcil acesso aos bits dentro de uma palavra. O terceiro a unio, a qual permite que a mesma poro da memria seja definida por dois ou mais tipos diferentes de variveis. Um quarto tipo de dado a enumerao, que uma lista de smbolos, como foi visto na seo 1.5. O ltimo tipo definido pelo usurio criado atravs do uso de typedef e define um novo nome para um tipo existente.

13.1

Estruturas

O tipo estruturado struct possibilita a criao de estruturas de dados complexas, isto , pode-se obter estruturas que contenham mais de um tipo de dado. Tal estrutura conhecida em outras linguagens como registros. Cada elemento que compe a estrutura (chamado campo) pode ser acessado individualmente, assim como a estrutura pode ser acessada como um todo. Em C, a declarao de uma estrutura feita da seguinte forma: struct [nome_struct] { tipo var1; tipo var2; tipo varN;} [nome_var]; Deve-se encerrar com um ponto-e-vrgula a declarao porque a definio de estrutura na realidade uma instruo C. A declarao de estruturas pode se apresentar de diversas formas. Tais como: struct { char nome[30]; int idade; int codigo; float saldo; } conta1, conta2; Na declarao acima, o nome_struct no utilizado pois esta estrutura ser utilizada pelas variveis de estrutura conta1 e conta2. Para utilizar esta estrutura na definio de outras variveis temse que declar-las juntas com a definio da estrutura. No caso de um programa que utilize esta estrutura para passar parmetros, declarar variveis locais, entre outros, a linguagem permite a criao de rtulos de estruturas (nome_struct). struct cad_conta { char nome[30]; int idade; int codigo; float saldo; } conta1, conta2; Como mostra o exemplo acima, foram declaradas as variveis conta1 e conta2 como sendo uma estrutura do tipo cad_conta. Quando rotula-se a estrutura pode-se omitir a declarao das variveis, como mostrado no exemplo abaixo: struct cad_conta { char nome[30]; int idade;

65/105

LINGUAGEM C

int codigo; float saldo; }; Para usar esta estrutura em outras declaraes deve-se especificar desta forma: struct cad_conta conta1, conta2; As estruturas seguem o padro do escopo de variveis, isto , se a declarao estiver contida numa funo, a estrutura tem escopo local para aquela funo; se a declarao estiver fora de todas as funes, ela ter um escopo global. Para acessar um campo especfico de uma struct utiliza-se o operador . (ponto). Exemplo 13.25 conta1.saldo = 0; conta1.codigo = 0; strcpy(conta1.nome,Joao); conta1.idade = 21; permitida a atribuio entre struct. Neste caso todos os campos so copiados. Exemplo 13.26 conta2 = conta1;

13.1.1 Inicializando Estruturas


Uma estrutura s pode ser inicializada se pertencer s classes static ou extern. Observe que a classe de uma estrutura dada pelo ponto em que as variveis foram declaradas e no pelo ponto onde a estrutura foi definida. Da mesma forma que os vetores, as estruturas so inicializadas com uma lista de valores (cada um correspondente a um campo de estrutura) entre chaves e separados por vrgulas. struct cad_conta { char nome[30]; int idade; int codigo; float saldo; }; main() { static struct cad_conta conta1 = {Andre, 23, 9507, 1567.89}, conta2 = {Carlos, 33, 9678, 1000.59}; }

13.1.2 Estruturas Aninhadas


Como os campos da estrutura podem ser de qualquer tipo, tambm permitido o uso de estruturas na declarao. struct data { int dia; char mes[10]; int ano; };

66/105

LINGUAGEM C

struct func { char nome[20]; int codigo; float salario; struct data nascimento; }; main() { static struct func funcionario = {Marcio, 1234, 3743.44, {10, Janeiro, 1967}}, gerente = {Jose, 456, 5634.28, {18, Marco, 1950}}; } Observe a inicializao das variveis. A estrutura inicializada tambm com uma lista de valores entre chaves e separados por vrgulas. O acesso a um campo de uma estrutura aninhada feito na forma: funcionrio.nascimento.dia = 10; strcpy(gerente.nascimento.mes,Abril);

13.1.3 Estruturas e funes


Em verses mais antigas de compiladores C, as estruturas no podiam ser usadas em passagem de parmetros por valor para funes. Isto se devia a razes de eficincia, uma vez que uma estrutura pode ser muito grande e a cpia de todos os seus campos para a pilha poderia consumir um tempo exagerado. Desta forma, as estruturas eram obrigatoriamente passadas por referncia, usando-se o operador de endereo (&). No Turbo C e outros compiladores mais recentes, a responsabilidade da deciso fica a cargo do programador. Assim, uma funo pode passar ou retornar uma estrutura. struct cad_conta { char nome[30]; int idade; int codigo; float saldo; };

main() { static struct cad_conta conta1; conta1 = ins_conta(); lista(conta1); } struct cad_conta ins_conta() { struct cad_conta aux; gets(aux.nome); scanf(%d, &aux.idade); scanf(%d, &aux.codigo); scanf(%f, &aux.saldo); return(aux); } void lista(aux)

67/105

LINGUAGEM C

struct cad_conta aux; { printf(Nome : %s\n,aux.nome); printf(Idade : %d\n, aux.idade); printf(Codigo : %d\n, aux.codigo); printf(Saldo : %.2f\n, aux.saldo); }

13.1.4 Vetor de Estruturas


A criao de tabela de estruturas mantm a sintaxe normal de definio de matrizes, como mostrada abaixo: struct cad_conta { char nome[30]; int idade; int codigo; float saldo; }; main() { int i static struct cad_conta conta[10]= { {Andre, 23, 9507, 1567.89}, {Carlos, 33, 9678, 1000.59}, ... }; for (i=0;i<10;i++) { printf(Nome : %s\n,conta[i].nome); printf(Idade : %d\n, conta[i].idade); printf(Codigo : %d\n, conta[i].codigo); printf(Saldo : %.2f\n, conta[i].saldo); } }

13.1.5 Ponteiros para Estruturas


C permite ponteiros para estruturas exatamente como permite ponteiros para outros tipos de variveis. No entanto, h alguns aspectos especiais de ponteiros de estruturas. Como outros ponteiros, declara-se colocando um * na frente do nome da estrutura. No exemplo 12.3 declara-se ptr_cta como um apontador da estrutura previamente definida cad_conta. Exemplo 13.3 struct cad_conta *ptr_cta; H dois usos primrios para ponteiros de estrutura: gerar uma chamada por referncia para uma funo e criar estruturas de dados dinmicas (listas, pilhas, filas, entre outras) utilizando-se do sistema de alocao de C. Na forma de acessar os elementos ou campos de uma estrutura usando um ponteiro para a estrutura, deve-se utilizar o operador -> (seta). A seta usada sempre no caso de apontador de estruturas. No exemplo abaixo mostrada a declarao, atribuio e utilizao de ponteiros de estruturas. Exemplo 13.4

68/105

LINGUAGEM C

struct cad_conta { char nome[30]; int idade; int codigo; float saldo; } conta; main() { struct cad_conta *ptr; ptr = &conta; /* o estrutura a ser apontada */ ptr->idade = 23; ptr->codigo = 1000; }

ponteiro

recebe

endereco

da

13.2

Campos de Bits

Ao contrrio das linguagens de computador, C tem um mtodo intrnseco para acessar um nico bit dentro de um byte. Isso pode ser til por um certo nmero de razes: Se o armazenamento limitado, voc pode armazenar diversas variveis Booleanas (verdadeiro/falso) em um byte. Certos dispositivos transmitem informaes codificadas nos bits dentro de um byte. Certas rotinas de criptografia precisam acessar os bits dentro de um byte.

Para acessar os bits, C usa um mtodo baseado na estrutura. Um campo de bits , na verdade, apenas um tipo de elemento de estrutura que define o comprimento, em bits, do campo. A forma geral de uma definio de campo de bit : struct nome { tipo var1 : comprimento; tipo var2 : comprimento; tipo varN : comprimento;} [lista_de_variaveis]; Um campo de bit deve ser declarado como int, unsigned ou signed. Campos de bit de comprimento 1 devem ser declarados como unsigned, porque um nico bit no pode ter sinal. (Alguns compiladores s permitem campos do tipo unsigned). Um exemplo de campos de bits a comunicao via serial que devolve um byte de estado organizado desta forma: Bit 0 1 2 3 4 5 6 7 Significado quando ligado alterao na linha clear-to-send alterao em data-set-ready borda de subida da portadora detectada alterao na linha de recepo clear-to-send data-set-ready chamada do telefone sinal recebido Pode-se representar a informao em um byte de estado utilizando o seguinte campo de bits: struct status_type {

69/105

LINGUAGEM C

unsigned unsigned unsigned unsigned unsigned unsigned unsigned unsigned } status;

delta_cts delta_dsr tr_edge delta_rec cts dsr ring rec_line

: : : : : : : :

1; 1; 1; 1; 1; 1; 1; 1;

Para atribuir um valor a um campo de bit, simplesmente utiliza-se a forma para atribuio de outro tipo de elemento de estrutura. status.ring = 0; No necessrio dar um nome a todo campo de bit. Isto torna fcil alcanar o bit que se deseja acessar, contornando os no usados. Por exemplo, se apenas cts e dtr importam, pode-se declarar a estrutura status_type desta forma: struct status_type { unsigned unsigned cts unsigned dsr } status; : 4; : 1; : 1;

Alm disso, nota-se que os bits aps dsr no precisam ser especificados se no so usados. Variveis de campo de bit tm certas restries: No pode obter o endereo de uma varivel de campo de bit. Variveis de campo de bit no podem ser organizadas em matrizes. No pode ultrapassar os limites de um inteiro. No pode saber, de mquina para mquina, se os campos estaro dispostos da esquerda para a direita ou da direita para a esquerda. Em outras palavras, qualquer cdigo que use campos de bits pode ter algumas dependncias da mquina. Finalmente, vlido misturar elementos normais de estrutura com elementos de campos de bit. Por exemplo, struct emp { struct addr address; float pay; unsigned lau_off : 1; /* ocioso ou ativo */ unsigned hourly : 1; /* pagamento por horas */ unsigned deduction : 3; /* dedues de imposto */ }; define um registro de um empregado que usa apenas um byte para conter trs informaes: o estado do empregado, se o empregado assalariado e o nmero de dedues. Sem o campo de bits, essa varivel ocuparia trs bytes.

13.3

Unies

Uma unio um tipo de dado que pode ser usado de muitas maneiras diferentes. Por exemplo, uma unio pode ser interpretada como sendo um inteiro numa operao e um float ou double em outra. Embora, as unies possam tomar a aparncia de uma estrutura, elas so muito diferentes.

70/105

LINGUAGEM C Uma unio pode conter um grupo de muitos tipos de dados, todos eles compartilhando a mesma localizao na memria. No entanto, uma unio s pode conter informaes de um tipo de dados de cada vez. Para criar uma unio utiliza-se a seguinte sintaxe: union [nome_union] { tipo var1; tipo var2; tipo varN;} [nome_var]; Deve-se encerrar com um ponto-e-vrgula a declarao porque a definio de unio na realidade uma instruo C. A declarao de unies pode se apresentar de diversas formas. Tais como: union { char c; int i; double d; float f; } data; Na declarao acima, o nome_union no utilizado pois esta unio ser utilizada pela varivel data. Para utilizar esta unio na definio de outras variveis tem-se que declar-las juntas com a definio da unio. No caso de um programa que utilize esta unio em vrias partes do programa a linguagem C permite a criao de rtulos de estruturas (nome_union). union tipos { char c; int i; double d; float f; } data; Como mostra o exemplo acima, foi declarada a varivel data como sendo uma unio do tipo tipos. Quando rotula-se a unio pode-se omitir a declarao das variveis, como mostrado no exemplo abaixo: union tipos { char c; int i; double d; float f; }; Para usar esta unio em outras declaraes deve-se especificar desta forma: union tipos data1, data2; As estruturas seguem o padro do escopo de variveis, isto , se a declarao estiver contida numa funo, a estrutura tem escopo local para aquela funo; se a declarao estiver fora de todas as funes, ela ter um escopo global. Para acessar um campo especfico de uma union utiliza-se o operador . (ponto). Pode-se declarar estruturas dentro de unies. struct so_int { int i1,i2; }; struct so_float { float f1,f2; };

71/105

LINGUAGEM C

union { struct so_int i; struct so_float f; } teste; main() { teste.i.i1 teste.i.i2 printf(i1 teste.f.f1 teste.f.f2 printf(f1

= = = = = =

2; 3; %-3d i2 = %-3d\n,teste.i.i1,teste.i.i2); 2.5; 3.5; %.1f f2 = %.1f\n,teste.f.f1,teste.f.f2);

13.4

Sizeof()

Com uso de estruturas, unies e enumeraes pode-se utiliz-las para a criao de variveis de diferentes tamanhos e que o tamanho real dessas variveis pode mudar de mquina para mquina. O operador unrio sizeof() calcula o tamanho de qualquer varivel ou tipo e pode ajudar a eliminar cdigos dependentes da mquina de seus programas. Exemplo 13.5 union tipos { char c; int i; double d; float f; } data; O sizeof(data) 8. No tempo de execuo, no importa o que a unio data est realmente guardando. Tudo o que importa o tamanho da maior varivel que pode ser armazenada porque a unio tem de ser do tamanho do seu maior elemento.

13.5

Typedef

C permite que defina-se explicitamente novos nomes aos tipos de dados, utilizando a palavrachave typedef. No h criao de uma nova varivel, mas sim, definindo-se um novo nome para um tipo j existente. Serve para uma boa documentao ou at tornar os programas dependentes de mquina um pouco mais portteis. A forma geral de um comando typedef typedef tipo nome; Por exemplo, poderia ser criado um novo nome para char utilizando typedef char boolean; Esse comando diz ao compilador para reconhecer boolean como outro nome para char. Assim, para se criar uma varivel char, usando boolean boolean ok; Tambm vlida a redefinio, isto , utilizar um novo nome para um nome atribudo a um dado previamente estabelecido. #include <stdio.h> typedef char boolean; typedef boolean bool;

72/105

LINGUAGEM C

void main() { boolean a; bool b; a = 1; b = 2; printf("%d %d",a,b); } A declarao typedef usado tambm para definir tipos estruturados (struct e union) para facilitar a nomenclatura dos tipos na declarao de variveis (exemplo 12.6) Exemplo 13.6 typedef struct conta { char nome[30]; int idade; int codigo; float saldo; } cad_conta;

main() { cad_conta *ptr; ptr = &conta; ptr->idade = 23; ptr->codigo = 1000; } ou struct conta { char nome[30]; int idade; int codigo; float saldo; }; typedef struct conta cad_conta; main() { cad_conta *ptr; ptr = &conta; ptr->idade = 23; ptr->codigo = 1000; }

13.6

Exerccios

1. Faa um programa que leia os dados de 10 clientes de um banco e aps leia 100 conjuntos de 3 valores: cdigo de operao - 0 depsito, 1 - retirada, valor da operao cdigo do cliente.

73/105

LINGUAGEM C Realize as movimentaes nas contas correspondentes e ao final escreva o nome e saldo de cada cliente. 2. Faa um programa de cadastro de clientes que contenham as seguintes opes: incluir, alterao, excluir e consultar por cdigo ou por nome. O cadastro deve ser da seguinte forma: nome (30 caracteres); cdigo (0 a 255); idade(char);

74/105

LINGUAGEM C

14. Alocao Dinmica


Programas consistem em duas coisas: algoritmos e estruturas de dados. Um bom programa uma combinao de ambos. A escolha e a implementao de uma estrutura de dados so to importantes quanto as rotinas que manipulam os dados. Para a manipulao de dados utilizado mecanismos que auxiliam tanto na forma de como armazenado ou recuperado. Existem vrios mecanismos que realizam este tipo de processamento. Abaixo esto listados alguns mecanismos bsicos: Listas Pilhas Filas rvores

Cada um destes mecanismos pode ter variaes de acordo com a poltica de processamento (armazenamento/recuperao). Neste captulo ser abordado com mais nfase as listas encadeadas, porque sero como base para a construo dos demais.

14.1

Funes de Alocao dinmica em C

A memria alocada pelas funes de alocao dinmica de C obtida do heap - a regio de memria livre que est o programa, a rea permanente e a pilha. As funes so utilizadas para alocar e desalocar esta memria, o que estiver livre. O padro C ANSI define apenas quatro funes para o sistema de alocao dinmica: calloc(), malloc(), free(), realloc(). No entanto, sero estudadas, alm das funes descritas, algumas funes que esto sendo largamente utilizadas. O padro C ANSI especifica que os prottipos para as funes de alocao dinmica definidas pelo padro esto em STDLIB.H. Entretanto, tais funes esto especificadas na biblioteca ALLOC.H, onde encontram-se mais funes de alocao dinmica. O padro C ANSI especifica que o sistema de alocao dinmica devolve ponteiros void, que so ponteiros genricos, podendo apontar para qualquer objeto. Porm, alguns compiladores mais antigos devolvem ponteiros para char. Nesse caso, deve-se usar um cast quando atribuir a ponteiros de tipos diferentes.

14.1.1 Funo malloc()


Esta funo devolve um ponteiro para o primeiro byte de uma regio de memria de tamanho size que foi alocada do heap. No caso em que no houver memria suficiente, a funo devolve um ponteiro nulo.

Cuidado! Ao usar um ponteiro nulo, pode ocorrer uma quebra do sistema.


Sintaxe.: void *malloc(size_t size); Onde size_t pode ser considerado um inteiro sem sinal e size o nmero de bytes de memria que se quer alocar. Essa funo devolve um ponteiro void, como mostra a sintaxe, portanto pode-se atribuir a qualquer tipo de ponteiro.

75/105

LINGUAGEM C Para assegurar a portabilidade de um programa que utilize a alocao dinmica, faz-se necessrio a utilizao da funo sizeof(). Exemplo 14.27 Esta funo aloca memria suficiente para conter uma estrutura do tipo addr: struct addr { char nome[40]; char rua[40]; char cidade[40]; char estado[3]; char cep[10];}; struct addr *get_struct(void) { struct addr *p; if ((p=(struct addr*)malloc(sizeof(addr)))==NULL) { printf( erro de alocao - abortando); exit(1); } return p; } O fragmento do cdigo mostra a alocao de 1000 bytes de memria. char *p; p = (char*)malloc(1000); No fragmento abaixo alocado memria suficiente para 50 inteiros. int *p; p = (int*)malloc(50 * sizeof(int)); O compilador deve conhecer duas informaes sobre qualquer ponteiro: o endereo da varivel apontada e seu tipo. Por isso, precisa-se fazer uma converso de tipo (cast) do valor retornado por malloc(), j que o mesmo retorna um void. Portanto, no exemplo 13.15 deve-se indicar ao compilador que o valor retornado por malloc() do tipo ponteiro para struct addr. p=(struct addr*) malloc(sizeof(addr)) Este tipo de converso deve ser realizado em todas as funes de alocao como calloc(), realloc() e malloc().

14.1.2 Funo calloc()


Esta funo devolve um ponteiro para o primeiro byte de uma regio de memria de tamanho size * num que foi alocada do heap. No caso em que no houver memria suficiente, a funo devolve um ponteiro nulo. Sintaxe.: void *calloc(size_t num, size_t size); Onde size_t pode ser considerado um inteiro sem sinal e size o nmero de bytes de memria que se quer alocar. Essa funo devolve um ponteiro void, como mostra a sintaxe, portanto pode-se atribuir a qualquer tipo de ponteiro.

76/105

LINGUAGEM C Para assegurar a portabilidade de um programa que utilize a alocao dinmica, faz-se necessrio a utilizao da funo sizeof(). A diferena entre calloc() e malloc() que a primeira aloca a memria e inicializa-a com zeros. Exemplo 14.2 Esta funo aloca memria suficiente para conter umvetor de 100 elementos: #include stdlib.h #include stdio.h float *get_mem(void) { float *p; p=(float*)calloc(100, sizeof(float)); if (!p) { printf( erro de alocao - abortando); exit(1); } return p; } No fragmento abaixo alocado memria suficiente para 50 inteiros. int *p; p = (int*)calloc(50,sizeof(int));

14.1.3 Funo free()


Esta funo devolve ao heap a memria apontada por ptr, tornando a memria disponvel para alocao futura. free() deve ser chamada somente com um ponteiro que foi previamente alocado com uma das funes do sistema de alocao dinmica. A utilizao de um ponteiro invlido na chamada provavelmente destruir o mecanismo de gerenciamento de memria e provocar uma quebra do sistema. Exemplo 14.3 #include <string.h> #include <stdio.h> #include <alloc.h> int main(void) { char *str; /* aloca memoria para uma string */ str = (char*)malloc(10); /* copia "Hello" para a string */ strcpy(str, "Hello"); /* mostra a string */ printf("String: %s\n", str); /* libera a memoria */

77/105

LINGUAGEM C

free(str); return 0; }

14.1.4 Funo realloc()


Esta funo modifica o tamanho da memria previamente alocada apontada por ptr para aquele especificado por size. O valor de size pode ser maior ou menor que o original. Um ponteiro para o bloco de memria devolvido porque realloc() pode precisar mover o bloco para aumentar seu tamanho. Se isso ocorre, o contedo do bloco antigo copiado no novo bloco; nenhuma informao perdida. Sintaxe.: void *realloc(void *ptr, size_t size); Se ptr um nulo, realloc() simplesmente aloca size bytes de memria e devolve um ponteiro para a memria alocada. Se size zero, a memria apontada por ptr liberada. Se no h memria livre suficiente no heap para alocar size bytes, devolvido um ponteiro nulo e o bloco original deixado inalterado. Exemplo 14.4 Esta programa primeiro aloca 23 caracteres, copia a string isso so 22 caracteres neles e, em seguida, usa realloc() para aumentar o tamanho para 24 e, assim, pr um ponto no final. #include stdlib.h #include stdio.h #include string.h void main(void) { char *p; p=(char*)malloc(23); if (!p) { printf( erro de alocao - abortando); exit(1); } strcpy(p,isso so 22 caracteres); p = (char*)realloc(p,24); if (!p) { printf( erro de alocao - abortando); exit(1); } strcat(p,.); printf(p); free(p); }

14.2

Matrizes Dinamicamente Alocadas

Qualquer ponteiro pode ser indexado como se fosse uma matriz unidimensional, portanto no haver nenhum problema para utilizar (exemplo 13.19).

78/105

LINGUAGEM C Exemplo 14.6 /* Aloca memria para uma string dinamicamente, solicita */ /* a entrada do usurio e, em seguida, imprime a string */ /* de trs para frente. */ #include stdlib.h #include stdio.h #include string.h void main(void) { char *s; register int t; s=(char*)malloc(80); if (!s) { printf( erro de alocao - abortando); exit(1); } gets(s); for (t=strlen(s)-1; t>=0; t--) putchar(s[t]); free(s); } Para acessar uma matriz unidimensional simples, mas para mais de uma dimenso levam alguns problemas com a indexao. Para conseguir uma matriz alocada dinamicamente, deve-se utilizar um truque: passar um ponteiro como um parmetro a uma funo. Dessa forma, a funo pode definir as dimenses do parmetro que recebe o ponteiro, permitindo, assim, a indexao normal da matriz. Isto mostrado no exemplo 13.20. Exemplo 14.7 #include stdlib.h #include stdio.h #include string.h void le_tab(int mat[20][5]) { register int i,j; for(i=0; i<20; i++) for(j=0; j<5; j++) scanf(%d,&mat[i][j]); } void mostra_tab(int mat[20][5]) { register int i,j; for(i=0; i<20; i++) for(j=0; j<5; j++) printf(%d,mat[i][j]); } void main(void) { char *p; register int t; s=(int*)calloc(100, sizeof(int)); if (!p) {

79/105

LINGUAGEM C

printf( erro de alocao - abortando); exit(1); } le_tab(p); mostra_tab(p); }

14.3

Listas Encadeadas

Listas encadeadas so usadas para dois propsitos fundamentais. O primeiro criar matrizes de tamanho desconhecido na memria. Listas encadeadas tambm so usadas em armazenamento de banco de dados em arquivos em disco. Listas encadeadas podem ser singularmente (simplesmente) - um elo para o prximo item - ou duplamente - elos para o anterior e prximo elemento da lista - encadeadas.

14.3.1 Listas Singularmente Encadeadas


Uma lista singularmente encadeada requer que cada item de informao contenha um elo como o prximo da lista. Cada item de dado geralmente consiste em uma estrutura que inclui campos de informao e ponteiro de enlace (ou de ligao). Antes, precisa-se definir a estrutura de dados que contenha a informao e os elos. Considere um exemplo de armazenamento de coordenadas cartesianas (x,y,z) para representao de uma figura geomtrica. A estrutura de dados para cada elemento definido aqui: struct ponto { int x,y,z; struct ponto *prox; } figura1; typedef struct ponto figura; Na estrutura acima, declarado um apontador para a prxima estrutura, por isso declara-se um apontador para a prpria estrutura (auto-referncia). Aps a declarao, foi definido que figura um tipo, que representa uma struct ponto, o qual pode ser utilizado em todo o programa. A funo inclui() constri uma lista singularmente encadeada colocando cada novo item no final da lista. Deve ser passado um ponteiro para uma estrutura do tipo ponto, ponteiro para o primeiro elemento e ponteiro para o ltimo elemento. void inclui(figura *i, figura **inicio, figura **fim) { if (!*fim) /* Primeiro elemento da lista */ { *fim = i; *inicio = i; } else { (*fim)->prox = i; *fim = i; } } Os parmetros incio e fim da funo tm dois asteriscos porque representam uma indireo mltipla. Isto , so apontadores para apontadores da estrutura figura. Isto necessrio para poder implementar a passagem de parmetros por referncia.

80/105

LINGUAGEM C Apagar um item de uma lista singularmente encadeada pode ocorrer em trs situaes: apagar o primeiro item, apagar um item intermedirio e apagar o ltimo item. A funo a seguir excluir um item de uma lista de estruturas do tipo ponto: void exclui( figura *p, figura *i, figura **inicio, figura **ultimo) { if (p) p->next = i->next; else *start = i->next; if (i==*last && p) *last = p; } /* /* /* /* item anterior */ item a apagar */ incio da lista */ final da lista */

Listas singularmente encadeadas tm uma desvantagem que a lista no pode ser lida em ordem inversa.

14.3.2 Listas Duplamente Encadeadas


Consistem em dados e elos para o prximo item e para o item precedente. Um novo elemento pode ser inserido em uma lista duplamente encadeada de trs maneiras: inserir um novo primeiro elemento, inserir um elemento intermedirio ou inserir um novo ltimo elemento. A construo de uma lista duplamente encadeada semelhante de uma lista singularmente encadeada, exceto pelo fato de que dois elos devem ser mantidos. Utilizando a estrutura ponto, ser mostrado a declarao de um nodo de lista duplamente encadeada. struct ponto { int x,y,; struct ponto *prox; struct ponto *ant; }; typedef struct ponto figura; Usando figura como o item de dado bsico, a funo seguinte constri uma lista duplamente encadeada. Esta funo inclui um novo dado no fim da lista: void incfim(figura *i, figura **fim) { if (!*fim) *fim = i; /* o primeiro item da lista */ else (*fim)->prox = i; i->prox = NULL; i->ant = *fim; *fim = i; } Para armazenagem de um dados em uma posio especfica a funo abaixo realiza a incluso em ordem crescente pelo eixo x de uma lista duplamente encadeada. void incord(figura *i, figura **inicio, figura **fim) /* novo elemento */ /* primeiro elemento da lista */ /* ultimo elemento da lista */

81/105

LINGUAGEM C

{ if (!*fim) /* o primeiro item da lista */ { i->prox = NULL; i->ant = NULL; *inicio = i; *fim = i; } else { figura *old, *p; p = *inicio; old = NULL; while (p && (p->x < i->x)) { old = p; p = p->prox; } if (!old) { i->prox = p; /* inserir no inicio da lista */ i->ant = NULL; p->ant = i; *inicio = i; } else { if (p->ant) { /* inserir em uma posio */ p->ant->prox = i; /* intermediria da lista */ i->prox = p; i->ant = p->ant; p->ant = i; } else { old->prox = i; /* inserir no fim da lista */ i->prox = NULL; i->ant = old; *fim = i; } } } Como o ponteiro de incio e fim de lista podem ser alterados, a funo incord() atualiza automaticamente estes ponteiros atravs das variveis inicio e fim. H trs casos a considerar ao excluir um elemento de uma lista duplamente encadeada: excluir o primeiro item, excluir um item intermedirio ou excluir o ltimo item. void delord(figura *i, /* item a apagar */ figura **inicio, /* primeiro elemento da lista */ figura **fim) /* ultimo elemento da lista */ { figura *old, *p; p = *inicio; old = NULL; while (p && (p->x != i->x) &&(p->y != i->y)) { old = p; p = p->prox;

82/105

LINGUAGEM C

} if ((p->x = i->x) &&(p->y = i->y)) { if (!old) /* exclusao unico elemento da lista */ *inicio=*fim=NULL; else { if (!p->prox) * exclusao do ultimo elemento da lista */ { old->prox = NULL; *fim = old; } else { /* excluir item de uma posio */ old->prox = p->prox; /* intermediria da lista */ p->prox->ant = old; } } free(p); } }

14.4

rvores Binrias

A estrutura utilizada para a cosntruo de rvores binrias semelhante a listas duplamente encadeadas. A diferena est na poltica de organizao das mesmas. A funo abaixo constri uma rvore binria ordenada recursivamente: struct tree { char info; struct tree *esq; struct tree *dir; }; typedef struct tree arvore; arvore *stree ( arvore *raiz; arvore *r; char info); { if (!r) { r = (arvore *) malloc(sizeof(arvore)); if (!r) { printf(Sem memria \n); exit(0); } r->esq = NULL; r->dir = NULL; r->info = info; if (!raiz) return r; /* primeira entrada */ if (info < raiz->info) raiz->esq = r; else raiz->dir = r;

83/105

LINGUAGEM C

return r; } if (info < r->info) stree(r,r->esq, info); else stree(r,r->dir, info); A chamada desta funo realizada desta forma: if (!rt) rt = stree(rt, rt, info); else stree (rt, rt, info); Dessa forma, tanto o primeiro quanto os elementos subsequentes podem ser inseridos corretamente. A funo stree() um algoritmo recursivo. Existem trs formas de acessar os dados de uma rvore: ordenada, preordenada e psordenada. Onde a ordenada, visitado a subrvore da esquerda, a raiz e em seguida a subrvore da direita. Na preordenada, visita-se a raiz, subrvore da esquerda e, em seguida, a subrvore da direita. Na ps-ordenada, visita-se a subrvore da esquerda, subrvore da direita e, depois, a raiz.
d b a c e f g

Figura 14.3 Exemplo de uma rvore binria Utilizando a figura 14.1, a ordem de acesso rvore usando cada mtodo ordenada preordenada ps-ordenada a d a b b c c a b d c e e f g f e f g g d

Para o acesso de forma ordenada, pelas formas descritas anteriormente, pode-se utilizar as funes descritas abaixo: void inorder(arvore *raiz) { if(!raiz) return; inorder(raiz->esq); printf(%c, raiz->info); inorder(raiz->dir); } void preorder(arvore *raiz) { if(!raiz) return; printf(%c, raiz->info); preorder(raiz->esq); preorder(raiz->dir);

84/105

LINGUAGEM C

} void postorder(arvore *raiz) { if(!raiz) return; postorder(raiz->esq); postorder(raiz->dir); printf(%c, raiz->info); } Para excluso de um n de uma rvore tem que ser verificado se o n a raiz, um nodo esquerdo ou direito e que os mesmos podem ter subrvores ligadas a ele. Na funo a seguir realizada uma excluso recursiva observando as restries delineadas anteriormente. arvore *dtree(arvore *raiz, char key) { arvore *p, *p2; if (raiz->info==key) /* apagar a raiz */ { if (raiz->esq== raiz->dir) /*no tem filhos */ { free(raiz); return NULL; } else if (raiz->esq == NULL) { p = raiz->dir; free(raiz); return p; } else if (raiz->dir == NULL) { p = raiz->esq; free(raiz); return p; } else { p2 = raiz->dir; p = raiz->dir; while (p->esq) p = p->esq; p->esq = raiz->esq; free(raiz); return p2; } } if (raiz->info < key) raiz->dir = dtree(raiz->dir, key); else raiz->esq = dtree(raiz->esq, key); return raiz; } rvores binrias oferecem grande poder, flexibilidade e eficincia quando usadas em programas de gerenciamento de banco de dados. Principalmente pela sua poltica de organizao e a no limitao do tamanho (exceto aquela imposta pela memria).

85/105

LINGUAGEM C

14.5

Exerccios

1. Escreva um programa que leia vrios nomes e endereos, rearranje os nomes em ordem alfabtica e, depois, imprima a lista em ordem alfabtica. Utilize vrias estruturas. 2. Escreva um programa que gerencie uma pilha. O mesmo deve conter a funo de empilhar e desempilhar para o usurio os quatro tipos de dados bsicos da linguagem C (char, float, int, double). 3. Escreva um programa que gerencie uma fila circular do tipo FIFO (Primeiro que entra o primeiro que sai). 9. Faa um programa que leia o nmero de alunos; construa uma matriz dinamicamente alocada de tamanho N X 4, onde N o nmero de alunos e 4 as respectivas notas de cada aluno. Calcule a mdia e mostre na tela conforme descrio a seguir: ALUNO N1 N2 N3 N4 MEDIA 1 8.5 7.0 9.5 7.0 8.0 2 7.5 7.0 6.5 7.0 7.0

86/105

LINGUAGEM C

15. E/S com Arquivo


So grupos de dados armazenados em meio no voltil (disco, fita, entre outros). So utilizados para armazenar dados de forma permanente. A linguagem C no contm nenhum comando de E/S. Ao contrrio, todas as operaes de E/S ocorrem atravs de chamadas a funes da biblioteca C padro. Essa abordagem faz o sistema de arquivos de C extremamente poderoso e flexvel. O sistema de E/S de C nico, porque dados podem ser transferidos na sua representao binria interna ou em um formato de texto.

15.1

E/S ANSI x E/S UNIX

O padro ANSI define um conjunto completo de funes de E/S que pode ser utilizado para ler e escrever qualquer tipo de dado. Em contraste, o antigo padro C UNIX contm dois sistemas distintos de rotinas que realizam operaes de E/S. O primeiro mtodo denominado de sistema de arquivo com buffer (algumas vezes os termos formatado ou alto nvel so utilizados para referenci-lo). O segundo o sistema de arquivo tipo UNIX (algumas vezes chamado de no formatado ou sem buffer) definido apenas sob o antigo padro UNIX.

15.2

Streams

A linguagem C oferece uma abstrao da interface para controle de E/S, independente do dispositivo real (terminais, acionadores de disco, acionadores de fita, entre outros) que acessado. Sendo que o dispositivo real chamado de arquivo. Existem dois tipos de streams: texto e binria. A primeira uma seqncia de caracteres organizados em linhas e terminadas por um caractere de nova linha (depende da implementao). A segunda uma seqncia de bytes com uma correspondncia de um para um com aqueles encontrados no dispositivo externo - isto , no ocorre nenhuma traduo de caracteres.

15.3

Arquivos

Um arquivo pode ser qualquer coisa, desde um arquivo em disco at um terminal ou uma impressora. Associa-se uma stream com um arquivo especfico realizando uma operao de abertura. Todos as streams so iguais, mas no todos os arquivos. Isto , um arquivo disco pode suportar acesso aleatrio enquanto um teclado no pode. Cada stream associada a um arquivo tem uma estrutura de controle de arquivo do tipo FILE. Essa estrutura definida no cabealho STDIO.H. Todos os arquivos so fechados automaticamente quando o programa termina, normalmente com main() retornando ao sistema operacional ou uma chamada exit(). Os arquivos no so fechados quando um programa quebra (crash).

15.4

Sistema de Arquivos

O sistema de arquivos ANSI composto de diversas funes inter-relacionadas. As mais comuns so mostradas na tabela 15.1. Essas funes exigem que o cabealho STDIO.H seja includo em qualquer programa em que so utilizadas.

87/105

LINGUAGEM C Tabela 15.7 - Funes mais comuns do sistema de arquivo com buffer Nome fopen() fclose() putc() fputc() getc() fgetc() fseek() fprintf() fscanf() feof() ferror() rewind() remove() fflush() Funo Abre um arquivo Fecha um arquivo Escreve um caractere em um arquivo O mesmo que putc() L um caractere de um arquivo O mesmo que getc() Posiciona o arquivo em um byte especfico para um arquivo o que printf() para o console para um arquivo o que scanf() para o console Devolve verdadeiro se o fim de arquivo for atingido Devolve verdadeiro se ocorreu um erro Repe o indicador de posio de arquivo no incio do arquivo Apaga um arquivo Descarrega um arquivo

O arquivo cabealho STDIO.H fornece os prottipos para as funes de E/S e define estes trs tipos: size_t, fpos_t e FILE. O tipo size_t essencialmente o mesmo que um unsigned, assim como o fpos_t. O tipo FILE discutido na prxima seo. STDIO.H define vrias macros como: EOF, SEEK_SET, SEEK_CUR e SEEK_END. A macro EOF geralmente definida como -1 e o valor quando uma funo de entrada tenta ler alm do final do arquivo. As outras macros so usadas com fseek(), que uma funo que executa acesso aleatrio em um arquivo.

15.5

Estrutura FILE

Para a manipulao de arquivos utilizado a declarao de ponteiro (ponteiro de arquivo). Isto , um ponteiro para informaes que definem vrios dados sobre o arquivo, como o seu nome, status, e a posio atual do arquivo. Um ponteiro de arquivo uma varivel ponteiro do tipo FILE . Todas as funes so realizadas utilizando o ponteiro. Para a declarao de um ponteiro de arquivo utiliza-se a seguinte sintaxe:

Sintaxe:
FILE *<var> Exemplo 15.28 FILE *fp;

15.6

Abertura de Arquivos

A funo fopen() abre uma stream para uso e associa um arquivo a ela. Retorna o ponteiro de arquivo associado a esse arquivo. Sintaxe: FILE *fopen(const char * <nome_ arquivo>, const char *<modo_abertura>);

O modo de abertura define a forma como feito o acesso aos dados (somente leitura, leitura e escrita, etc). As forma principais so apresentadas na tabela 15.2. Tabela 15.2 - Os modos de abertura vlidos Modo r w Significado Abre um arquivo texto para leitura Cria um arquivo texto para escrita

88/105

LINGUAGEM C a rb wb ab r+ w+ a+ r+b ou rb+ w+b ou wb+ a+b ou ab+ Exemplo 15.2 FILE *arq; /* ponteiro de arquivo */ arq = fopen(dados.dat,wb); Se ao abrir um arquivo para leitura o mesmo no existir a funo fopen retorna um ponteiro nulo (NULL). arq = fopen(dados.dat,rb); if (arq= =NULL) arq=fopen(dados.dat,wb); Anexa a um arquivo texto Abre um arquivo binrio para leitura Cria um arquivo binrio para escrita Anexa a um arquivo binrio Abre um arquivo texto para leitura/escrita Cria um arquivo texto para leitura/escrita Anexa ou cria um arquivo texto para leitura/escrita Abre um arquivo binrio para leitura/escrita Cria um arquivo binrio para leitura/escrita Anexa a um arquivo binrio para leitura/escrita

15.7

Fechamento de Arquivo

A funo fclose() fecha uma stream que foi aberta atravs de uma chamada fopen(). Esta funo tem a seguinte sintaxe: Sintaxe: int fclose(FILE *fp); onde fp o ponteiro de arquivo devolvido pela chamada fopen(). O valor de retorno 0 significa uma operao de fechamento bem-sucedida. Qualquer outro valor indica erro, que pode ser diagnosticada pela funo ferror() (discutida mais adiante).

15.8

Leitura e Gravao de caracteres

Para as operaes de leitura e gravao so utilizadas duas funes padres: getc() e putc() (consideradas tecnicamente macros) . Para cada uma destas funes existem duas equivalentes: fgetc() e fputc(). Nas sees a seguir sero estudadas as funes declaradas padro ANSI (as duas primeiras). As outras funes tm a mesma sintaxe que suas equivalentes.

15.8.1 Gravao
Para escrita de caracteres em um arquivo utilizam-se as funes putc() e fputc(), as quais so equivalentes (putc() uma macro). O prottipo para essa funo Sintaxe: int putc(int ch, FILE *fp);

89/105

LINGUAGEM C onde fp um ponteiro de arquivo devolvido por fopen() e ch o caractere a ser escrito. Se a operao putc() foi bem-sucedida, ela devolve o caractere escrito. Caso contrrio, ela devolve EOF.

15.8.2 Leitura
Para leitura de caracteres em um arquivo utilizam-se as funes getc() e fgetc(), as quais so equivalentes (getc() uma macro). O prottipo para essa funo Sintaxe: int getc(FILE *fp); onde fp um ponteiro de arquivo devolvido por fopen(). Se a operao getc() foi bem-sucedida, ela devolve o caractere lido. Caso contrrio, ela devolve EOF. O exemplo 15.3 mostra um lao que realiza uma leitura de um arquivo texto at que a marca de final de arquivo seja lida. Exemplo 15.3 do { ch = getc(fp); } while (ch!=EOF);

15.9

Verificando fim de arquivo

Alm de realizar um teste para fim de arquivo como no exemplo 15.3 pode-se utilizar uma funo como feof() que devolve verdadeiro quando for encontrado o fim de arquivo. O prottipo desta funo est declarado abaixo: Sintaxe: int feof(FILE *fp); Esta funo pode ser aplicada tanto para arquivo texto como para arquivos binrios. A rotina do exemplo 15.4 l um arquivo binrio at que o final do arquivo seja encontrado. Exemplo 15.4 while (!feof(fp)) ch = getc(fp);

15.10 Trabalhando com arquivos


As funes fopen(), getc(), putc() e fclose() constituem o conjunto mnimo de rotinas de arquivos. O programa a seguir l caracteres do teclado e os escreve em um arquivo em disco at que o usurio digite um cifro ($). O nome do arquivo passado pela linha de comando. #include stdio.h #include stdlib.h void main(int argc, char *argv[]) { FILE *fp;

90/105

LINGUAGEM C

char ch; if(argc !=2) { printf(Voce esqueceu de entrar o nome do arquivo \n); exit(1); } if((fp=fopen(argv[1],w))==NULL) { printf(Arquivo nao pode ser aberto\n); exit(1); } do { ch = getchar(); putc(ch,fp); } while(ch!=$); fclose(fp); } tela. O programa complementar descrito a seguir l qualquer arquivo ASCII e mostra o contedo na #include stdio.h #include stdlib.h void main(int argc, char *argv[]) { FILE *fp; char ch; if(argc !=2) { printf(Voce esqueceu de entrar o nome do arquivo \n); exit(1); } if((fp=fopen(argv[1],r))==NULL) { printf(Arquivo nao pode ser aberto\n); exit(1); } ch = getc(fp); while (ch!=EOF) { putchar(ch); ch = getc(fp); } fclose(fp); }

15.11 Trabalhando com Strings: fputs() e fgets()


Para a gravao e leitura de strings de caractere para e de um arquivo em disco so utilizadas as funes fgets() e fputs(), respectivamente. So os seguintes os seus prottipos: Sintaxe: int fputs(const char *str, FILE *fp); char *fgets(char *str, int length, FILE *fp);

91/105

LINGUAGEM C A funo fputs() opera como puts(), mas escreve a string na stream especificada. EOF devolvido se ocorre um erro. A funo fgets() l uma string da stream especificada at que um caractere de nova linha seja lido ou que length-1 caracteres tenham sido lidos. Se uma nova linha lida, ela ser parte da string (diferente de gets()). A string resultante ser terminada por um nulo. A funo devolve um ponteiro para str se bem-sucedida ou um ponteiro nulo se ocorre um erro. O programa a seguir l strings do teclado e escreve-as no arquivo chamado frase.dat. A condio de sada uma linha em branco. Como gets() no armazena o caractere de nova linha, adicionado um antes que a string seja escrita no arquivo para que o arquivo possa ser lido mais facilmente. #include stdio.h #include stdlib.h #include string.h void main(void) { char str[80]; FILE *fp; if((fp=fopen(frase.dat,w))==NULL) { printf(Arquivo nao pode ser aberto\n); exit(1); } do { printf(entre uma string (CR para sair): \n); gets(str); strcat(str,\n); fputs(str,fp); } while (*str != \n); fclose(fp); }

15.12 Funes de tratamento de arquivos


Nas prximas sees sero vistas algumas funes utilizadas em operaes com arquivos com buffer.

15.12.1

rewind()

Esta funo reposiciona o indicador de posio de arquivo no incio do arquivo especificado como seu argumento. Seu prottipo : Sintaxe: void rewind(FILE *fp); O exemplo 15.5 rebobina o arquivo do programa anterior e mostrar o contedo do mesmo. Exemplo 15.5 #include stdio.h #include stdlib.h #include string.h

92/105

LINGUAGEM C

void main(void) { char str[80]; FILE *fp; if((fp=fopen(frase.dat,w))==NULL) { printf(Arquivo nao pode ser aberto\n); exit(1); } do { printf(entre uma string (CR para sair): \n); gets(str); strcat(str,\n); fputs(str,fp); } while (*str != \n); rewind(fp); /* reinicializa o file pointer */ while(!feof(fp)) { fgets(str, 79, fp); printf(str); } fclose(fp); }

15.12.2

ferror()

A funo ferror() determina se uma operao com arquivo produziu um erro. A funo ferror() tem esse prottipo: Sintaxe: int ferror(FILE *fp); Ela retorna verdadeiro se ocorreu um erro durante a ltima operao no arquivo; caso contrrio, retorna falso.

15.12.3

remove()

A funo remove() apaga o arquivo especificado. Seu prottipo : Sintaxe: int remove(char *nome_arq) Ela devolve zero caso seja bem-sucedido e um valor diferente de zero caso contrrio. O exemplo 15.6 apresenta um trecho de programa que apaga o arquivo dados.dat. Exemplo 15.6 if (remove(dados.dat)) { printf(Arquivo nao pode ser apagado\n); exit(1); }

93/105

LINGUAGEM C

15.12.4

fflush()

Para se esvaziar o contedo de uma stream de sada, deve-se utilizar a funo fflush(), cujo prottipo mostrado a seguir: Sintaxe: int fflush(FILE *fp); Essa funo escreve o contedo de qualquer dado existente no buffer arquivo associado a fp. Se fflush() devolve 0 para indicar sucesso; caso contrrio, devolve EOF.

15.12.5

Funo ftell()

Esta funo retorna a posio do ponteiro de um arquivo binrio em relao ao seu comeo. Esta funo aceita um nico argumento, que o ponteiro para a estrutura FILE do arquivio. Seu prottipo mostrado aqui: Sintaxe: long ftell (FILE *fp); Retorna um valor do tipo long, que representa o nmero de bytes do comeo do arquivo at a posio atual. A funo ftell() pode no retornar o nmero exato de bytes se for usada com arquivos em modo texto, devido combinao CR/LF que representada por um nico caractere em C.

15.13 Lendo e gravando registros


As funes fread() e fwrite() possibilitam uma maneira de transferir blocos de dados do disco para a memria do computador e vice-versa. A grande vantagem destes comandos poder ler e gravar dados maiores que um byte e que formem estruturas complexas (vetor, matriz, ou um registro, ou at um vetor de registros).

15.13.1

Escrita de um bloco de dados

Para se gravar um bloco de dados maiores que um byte o sistema de arquivo ANSI C fornece a funo fwrite(). Seu prottipo est definido a seguir: Sintaxe: size_t fwrite(void *buffer, size_t num_bytes, size_t count, FILE *fp); onde buffer um ponteiro para uma regio de memria que contm as informaes que sero escritas no arquivo. O nmero de bytes para gravar especificado por num_bytes. O argumento count determina quantos itens sero gravados. E, finalmente, fp um ponteiro de arquivo para uma stream aberta anteriormente. Esta funo devolve o nmero de itens escritos. O nmero retornado pode ser menor que count quando o final de arquivo for atingido ou ocorrer um erro de gravao. Exemplo 15.7

94/105

LINGUAGEM C

int var_int; FILE *arq; arq = fopen(dados.dat,wb); var_int = 5; fwrite(&var_int,sizeof(var_int),10,arq);

15.13.2

Leitura de um bloco de dados

Para se ler um bloco de dados maiores que um byte o sistema de arquivo ANSI C fornece a funo fread(). Seu prottipo est definido a seguir: Sintaxe: size_t fread(void *buffer, size_t num_bytes, size_t count, FILE *fp); onde buffer um ponteiro para uma regio de memria que receber os dados do arquivo. O nmero de bytes para ler especificado por num_bytes. O argumento count determina quantos itens sero lidos. E, finalmente, fp um ponteiro de arquivo para uma stream aberta anteriormente. Esta funo devolve o nmero de itens lidos. O nmero retornado pode ser menor que count quando o final de arquivo for atingido ou ocorrer um erro de leitura. Exemplo 15.8 int var_int; FILE *arq; arq = fopen(dados.dat,rb); fread(&var_int,sizeof(var_int),1,arq);

15.13.3

Utilizando os comandos de leitura e gravao de registros

Uma das mais teis aplicaes de fread() e fwrite() envolve ler e escrever tipos de dados definidos pelo usurio, especialmente estruturas. #include stdio.h struct pto { int x,y; }; typedef struct pto ponto; void main() { FILE *fp; int i; ponto coord[10]; for (i=0; i < 10; i++) { printf(Coordenada x:); scanf(%d \n,&coord[i].x); printf(Coordenada y:); scanf(%d \n,&coord[i].y); } if((fp=fopen(figura.dat,w))==NULL) {

95/105

LINGUAGEM C

printf(Arquivo nao pode ser aberto\n); exit(1); } for (i=0; i < 10; i++) fwrite(&coord[i], sizeof(ponto),1, fp); rewind(fp); i = 0; while(!feof(fp)) { fread(&coord[i], sizeof(ponto), 1, fp); printf(Coordenadas (x,y) = (%d,%d),coord[i].x,coord[i].y); } fclose(fp); }

15.14 Acesso aleatrio


Operaes de leitura e escrita aleatrias podem ser executadas utilizando o sistema de E/S bufferizado com a ajuda de fseek(), que modifica o indicador de posio de arquivo. Seu prottipo mostrado aqui: Sintaxe: int fseek (FILE *fp, long numbytes, int origem); Onde, numbytes, um inteiro longo, o nmero de bytes a partir de oriem, que se tornar a nova posio corrente, e origem uma das seguintes macros definidas em STDIO.H. Tabela 15.3 Macros definidas em STDIO.H para as posies permitidas na funo fseek(). Origem Incio do arquivo Posio atual Final do arquivo Nome da Macro SEEK_SET SEEK_CUR SEEK_END

A funo fseek() devolve 0 se a operao for bem-sucedida e um valor diferente de zero se ocorre um erro. O exemplo 15.9 mostra a utilizao da funo fseek(). Este exemplo recebe pela linha de comando o deslocamento a ser realizado sempre a partir do incio do arquivo (SEEK_SET). Exemplo 15.9 #include stdio.h #include stdlib.h void main(int argc, char *argv[]) { FILE *fp; char ch; if(argc !=3) { printf(Uso: SEEK nomearq byte \n); exit(1);

96/105

LINGUAGEM C

} if((fp=fopen(argv[1],r))==NULL) { printf(Arquivo nao pode ser aberto\n); exit(1); } if(fseek(fp, atol(argv[2]), SEEK_SET)) { printf(erro na busca\n); exit(1); } printf(O byte em %ld %c\n, atol(argv[2]), getc(fp)); fclose(fp); } No exemplo 15.9 verifica-se a utilizo da funo atol(), que tem por funo converter uma string em um inteiro longo. No printf() utiliza-se o modo de formatao %ld que para apresentao de um decimal longo ou um inteiro longo.

15.15 Comando de gravao em modo texto formatado


Como extenso das funes bsicas de E/S j discutidas, o sistema de E/S com buffer inclui fprintf() e fscanf(). Essas funes se comportam exatamente como printf() e scanf() exceto por operarem em arquivos. Os prottipos de fprintf() e fscanf() so Sintaxe: int fprintf(FILE *fp, const char *control_string, ...); int fscanf(FILE *fp, const char *control_string, ...); onde fp um ponteiro de arquivo devolvido por uma chamada fopen(). fprintf() e fscanf() direcionam suas operaes de E/S para o arquivo apontado por fp. A fscanf() devolve o nmero de elementos lidos, convertidos e armazenados. No caso de fim de arquivo o fscanf() devolve o valor EOF. O exemplo 15.10 mostra um programa que l uma string e um inteiro do teclado, escreve-os em um arquivo em disco e em seguida l e mostra a informao na tela. Exemplo 15.290 #include stdio.h #include stdlib.h #include io.h void main(void) { FILE *fp; char s[80]; int t; if((fp=fopen(teste,w))==NULL) { printf(Arquivo nao pode ser aberto\n); exit(1); } printf(entre com uma string e um nmero: ); fscanf(stdin, %s%d, s, &t); /* le do teclado */

97/105

LINGUAGEM C

fprintf(fp, %s %d, s, t); /* escreve no arquivo */ fclose(fp); if((fp=fopen(teste,w))==NULL) { printf(Arquivo nao pode ser aberto\n); exit(1); } fscanf(fp, %s%d, s, &t); /* le do arquivo */ fprintf(stdout, %s %d, s, t); /* imprime na tela */ } A formatao realizada para leitura e escrita de dados pode comprometer a velocidade de processamento do programa.

15.16 Condies de erro


Para determinar se um erro ocorreu utiliza-se a funo ferror(), mas esta informao no basta para a soluo por parte do usurio. Para isso utiliza-se a funo perror() em conjunto com a funo ferror(). O argumento de perror() uma string fornecida pelo programa que normalmente uma mensagem de erro que indica em que parte do programa ocorreu erro. Sintaxe: void perror (const char *str); Se for detectado um erro de disco, ferror() retornar um valor verdadeiro (no zero) e perror() imprimir a seguinte mensagem Erro de Busca: Bad data A primeira parte da mensagem fornecida pelo programa, e a segunda parte, pelo sistema operacional.

15.17 Streams Padro


Sempre que um programa iniciado trs streams padres so abertas automaticamente: stdin stdout stderr stdaux stdprn (entrada padro - teclado); (sada padro - tela); (sada de erro padro - tela); (sada auxiliar padro - porta serial); (impressora padro - impressora paralela).

Essas streams podem ser utilizadas normalmente para executar operaes de E/S bufferizada, como mostra o exemplo 15.10 na leitura de variveis pelo teclado. Para redirecionar as streams padro utiliza-se a funo freopen(). Sintaxe: FILE *freopen(const char *nomearq, const char *modo, FILE *stream); onde nomearq um ponteiro para o nome do arquivo que se deseja associar stream apontada por stream. O programa do exemplo 15.2 redireciona a stdout para o arquivo chamado OUTPUT. Exemplo 15.11

98/105

LINGUAGEM C

#include stdio.h void main(void) { char str[80]; freopen(OUTPUT, w, stdout); printf(entre com uma string: ); gets(str); printf(str); }

15.18 Exerccio:
1. 2. 3. 4. Faa um programa que escreva os nmeros de 0 a 10 em um arquivo. Faa um programa que leia 11 nmeros de um arquivo. Faa um programa que verifique se o nmero de abre-chaves corresponde ao nmero de fechachaves de um arquivo de programa fonte C, o qual lido pelo teclado. Faa um programa que gere um novo arquivo com registros ordenados (crescente) pelo cdigo de um arquivo, cujo nome fornecido pelo usurio. A estrutura do arquivo : struct reg { int cod; char nome[30]; char idade; };

15.19 Sistema de Arquivo tipo UNIX


Como C foi originalmente desenvolvida sobre o sistema operacional UNIX, ela inclui um segundo sistema de E/S com arquivos em disco que reflete as operaes em disco de baixo nvel do UNIX. A diferena est no fato que tanto a leitura como a gravao so realizadas sem buffer. Isto , o programador fica com o trabalho de criar e manter o buffer de dados. Para as operaes em disco utilizam-se algumas funes especiais, as quais esto descritas na tabela 15.3 Tabela 15.3 - Funes de E/S tipo UNIX sem buffer Nome open() close() read() write() lseek() tell() unlink() Funo Abre um arquivo em disco Fecha um arquivo em disco L um buffer de dados Escreve um buffer de dados Move ao byte especificado em um arquivo Devolve o valor atual do indicador de posio de arquivo Apaga um arquivo do diretrio

O arquivo-cabealho usado pelo sistema de arquivo tipo UNIX chamado IO.H em muitas implementaes. Em algumas funes necessrio a incluso do cabealho FNCTL.H (definio de algumas macros).

99/105

LINGUAGEM C

15.19.1

open()

Ao contrrio do sistema de arquivos com buffer, o sistema de baixo nvel (sem buffer) no utiliza ponteiros de arquivo do tipo FILE, mas descritores de arquivo do tipo int. O prottipo para open() : Sintaxe: int open(const char *nomearq, int modo); onde nomearq qualquer nome de arquivo vlido e modo uma das seguintes macros que so definidas no arquivo-cabealho FNCTL.H. Tabela 15.4 Modos de abertura de arquivos em baixo nvel Modo O_RDONLY O_WRONLY O_RDWR O_APPEND O_CREAT O_TRUNC O_BINARY O_TEXT Efeito Abre um arquivo somente para leitura Abre um arquivo somente para escrita Abre um arquivo para leitura/gravao coloca o ponteiro de arquivo no fim dele cria um novo arquivo para gravao (no faz efeito se o arquivo j existe) Abre e trunca umarquivo existente para tamanho 0 Abre um arquivo em modo binrio Abre um arquivo em modo texto

Os modos de abertura de arquivo em baixo nvel so mostrados na tabela 16.5. A existncia destas macros dependem do compilador, isto , nem todas podem existir. Algumas das macros listadas so mutuamente exclusivas, por exemplo, no pode abrir o arquivo para somente leitura e somente gravao ao mesmo tempo. Quando dois ou mais macros so utilizadas ao mesmo tempo, devem ser combinadas usando-se o operador bit-a-bit OR (|). Exemplo 15.12 #include <io.h> #include <fnctl.h> main() { int i; char buff[512];

/* identificador do arquivo /* definio do buffer */

*/

if((i=open(teste.txt,O_RDONLY | O_BINARY)) < 0) perror(No posso abrir arquivo:); ... } No exemplo 16.12, mostrado a abertura de um arquivo somente para leitura (O_RDONLY) e binrio (O_BINARY). O comando open() devolve um inteiro para i como descritor do arquivo para futuras operaes no mesmo.

100/105

LINGUAGEM C

15.19.2

creat()

Se o compilador no permitir criar um arquivo novo com a funo open() ou se quer garantir a portabilidade, deve-se utilizar a funo creat() para criar um arquivo novo para operaes de escrita. A sintaxe para creat() : Sintaxe: int creat(const char *nomearq, int modo); Os argumentos desta funo seguem a mesma sintaxe da funo open().

15.19.3

close()

A funo close() libera o identificador ou descritor do arquivo para que ele possa ser reutilizado por outro arquivo. Sintaxe: int close(int descritor_de_arquivo); O descritor_de_arquivos deve ser um descritor de arquivos vlido, previamente obtido atravs de uma chamada open() ou creat(). A funo close() devolve -1 se for incapaz de fechar o arquivo, e 0 caso contrrio.

15.19.4

read() e write()

Uma vez o arquivo aberto pela funo open(), para escrever alguma informao utiliza-se a funo write(). O prottipo para a funo write() Sintaxe: int write (int fd, const void *buf, unsigned size); Ao chamar a funo write() so escritos size caracteres no arquivo em disco especificado por fd do buffer apontado por buf. O buffer pode ser uma regio alocada na memria ou uma varivel. A funo write() devolve o nmero de bytes escritos no caso de uma operao bem-sucedida. No caso de erro a funo devolve EOF. Para a leitura de dados tem-se a funo read(). Seu prottipo : Sintaxe: int read (int fd, const void *buf, unsigned size); onde fd, buf e size so os mesmos parmetrosde write(), exceto pro read() colocar os dados do arquivo em buf. No caso da operao ser bem-sucedido devolvido o nmero de bytes lidos. Caso contrrio, ela devolve 0 se o final do arquivo for ultrapassado e -1 se ocorrerem erros. O exemplo 15.13 mostra um programa que utiliza alguns aspectos da E/S sem buffer. Este programa l linhas de texto, escreve-as em um arquivo em disco e as l de volta. Exemplo 15.303

101/105

LINGUAGEM C

#include stdio.h #include io.h #include stlib.h #include string.h #include fnctl.h #define BUF_SIZE 128 void input(char *buf, int fd1); void display(char *buf, int fd2); void main(void) { char buf[BUF_SIZE]; int fd1,fd2; if((fd1=open(test,O_WRONLY))==-1) { printf(Arquivo no pode ser aberto\n); exit(1); } input(buf,fd1); close(fd1); if((fd1=open(test,O_RDONLY))==-1) { printf(Arquivo no pode ser aberto\n); exit(1); } display(buf,fd2); close(fd2); } /* Insere texto */ void input(char *buf, int fd1) { register int t; do { for(t=0; t<BUF_SIZE; t++) buf[t] = \0; gets(buf); if (write(fd1, buf, BUF_SIZE) != BUF_SIZE) { printf(Erro de escrita \n); exit(1); } } while (strcmp(buf, sair); } /* Mostra o arquivo */ void display(char *buf, int fd2); { for(;;) { if (read(fd2, buf, BUF_SIZE) == 0) return; printf(%s\n, buf); } }

102/105

LINGUAGEM C

15.19.5

unlink()

Esta funo utilizada para excluir um arquivo. Seu prottipo Sintaxe: int unlink(const char *nomearq); onde nomearq um ponteiro de caracteres para algum nome vlido de arquivo. A funo unlink() devolve -1 caso seja incapaz de excluir o arquivo.

15.19.6

lseek() e tell()

Para o acesso aleatrio as funes lseek() e tell() so as equivalentes em baixo-nvel das funes fseek() e ftell() discutidas em alto-nvel. Os prottipos das duas funes so Sintaxe: long lseek(int fd, long offset, int origem); long tell(int fd); onde os parmetros so idnticos s esquivalentes em alto-nvel, exceto o primeiro argumento que um identificador de arquivo e no um ponteiro FILE.

15.19.7
de tipo.

Funes para manipulao de buffers

Para trabalhar com buffers utilizam-se algumas funes especializadas que so independentes

A funo memchr() procura, no vetor apontado por buffer, pela primeira ocorrncia de ch nos primeiros count caracteres. Devolve um ponteiro para a primeira ocorrncia de ch em buffer ou um ponteiro nulo se ch no for encontrado. O prottipo da funo Sintaxe: void *memchr(const void*buffer, int ch, size_t count); Exemplo 15.314 #include stdio.h #include string.h void main(void) { char *p; p = memchr(isto e um teste. ,14); printf(p); } A funo memcmp() compara os primeiros count coracteres das matrizes apontadas por buf1 e buf2. O valor devolvido segue os valores da funo strcmp(). O prottipo da funo Sintaxe: int memcmp(const void*buf1, const void*buf2, size_t count);

103/105

LINGUAGEM C A funo memcpy() copia os primeiros count coracteres do vetor origem para o vetor apontado por destino. Ela devolve um ponteiro para destino. O prottipo da funo Sintaxe: void *memcpy(void*destino, const void*origem, size_t count); Exemplo 15.15 #include stdio.h #include string.h #define SIZE 80 void main(void) { char buf1[SIZE], buf2[SIZE]; strcpy(buf1, Quando, no curso do ...); memcpy(buf2, buf1, SIZE); printf(buf2); } A funo memmove() copia count caracteres do vetor apontado por origem para o vetor apontado por destino. Se as matrizes se sobrepem, a cpia ocorrer corretamente, colocando o contedo correto em destino, porm origem ser modificado. Ela devolve um ponteiro para destino. O prottipo da funo Sintaxe: void *memmove(void*destino, const void*origem, size_t count); Exemplo 15.16 #include stdio.h #include string.h #define SIZE 80 void main(void) { char buf1[SIZE], buf2[SIZE]; strcpy(buf1, Quando, no curso do ...); memmove(buf2, buf1, SIZE); printf(buf2); } A funo memset() copia o byte menos significativo de ch nos primeiros count caracteres do vetor apontado por buf. Ela devolve buf. muito utilizado na inicializao de uma regio de memria com algum valor conhecido. O prottipo da funo Sintaxe: void *memset(void*buf, int ch, size_t count); Exemplo 15.17 /* Inicaliza com nulo os 100 primeiros bytes */ memset(buf, \0, 100); /*do vetor apontado por buf */ /* Inicializa com X os 10 primeiros bytes */ memset(buf, X, 10); printf(buf);

104/105

LINGUAGEM C

16.

Bibliografia
BERRY, J. Programando em C++. So Paulo: Makron Books, 1991. ECKEL, B. C++. So Paulo: McGraw-Hill, 1991. ELLIS, M. A. et alli C++: Manual de referncia completo. Rio de Janeiro: Campus, 1993. IBPI. Dominando a Linguagem C. Rio de Janeiro: IBPI, 1993. MIZRAHI, V. V. Treinamento em Linguagem C. So Paulo: McGraw-Hill, 1990. PAPPAS, C. H.; MURRAY, W. Turbo C++ completo e total. So Paulo: McGraw-Hill, 1991. SCHILDT, H. C Completo e total. So Paulo: McGraw-Hill, 1991.

105/105

S-ar putea să vă placă și