P. 1
apostila_linguagem_c

apostila_linguagem_c

|Views: 695|Likes:

More info:

Published by: Rafael Andrade de Moura on Sep 25, 2011
Copyright:Attribution Non-commercial

Availability:

Read on Scribd mobile: iPhone, iPad and Android.
download as DOC, PDF, TXT or read online from Scribd
See more
See less

11/27/2012

pdf

text

original

Sections

  • 1.1Visão geral de um programa C
  • FIGURA 1.1 - Codificação de um programa C
  • 2.Estrutura Básica de um Programa em C
  • 3.Tipos de Dados
  • 3.2Modificadores de Tipo de Acesso
  • 3.2.2Volatile
  • 3.3Constantes
  • 3.4Constantes pré-definidas
  • 3.5As bibliotecas disponíveis e algumas funções interessantes
  • 4.Comando de Escrita
  • 5.2.1Tipos de Declarações de Variáveis
  • 5.2.1.1Variáveis locais
  • 5.2.1.2Parâmetros Formais
  • 5.2.1.3Variáveis Globais
  • 5.3Palavras reservadas
  • 6.Operadores
  • 6.1.1Conversão de Tipos em Atribuições
  • 6.2.1Incremento e Decremento
  • 6.2.2Operadores Aritméticos de Atribuição
  • 6.3Operadores Relacionais e Lógicos
  • 6.4Operadores Bit a Bit
  • 6.5Operador ?
  • 6.6Operadores de Ponteiros & e *
  • 6.8.1Conversão de Tipos em Expressões
  • 6.8.3Espacejamento e Parênteses
  • 7.3Lendo e escrevendo caracteres
  • 8.Comandos Condicionais
  • 8.1Comando if
  • 8.2Comando switch
  • 9.Comandos Repititivos ou Laços
  • 9.4Comandos break, continue e exit()
  • 10.1.1Corpo da função antes do programa principal (no mesmo arquivo)
  • 10.1.2Corpo da função depois do programa principal (no mesmo arquivo)
  • 10.1.3Corpo da função escrito em arquivo separado
  • 10.4Retorno de Ponteiros
  • 10.5.1Funções para número variável de argumentos
  • 10.6Classes de Armazenamento
  • 10.6.1Classe de Armazenamento - auto
  • 10.6.2Classe de Armazenamento - extern
  • 10.6.3Classe de Armazenamento - static
  • 10.6.3.1 Variáveis Locais static
  • 10.6.3.2 Variáveis Globais static
  • 10.6.4Classe de Armazenamento - register
  • 10.7Diretiva #define
  • 11.Vetores e Matrizes
  • 11.1Inicialização de Vetores e Matrizes
  • 11.2Matrizes e Vetores como argumento de Funções
  • 11.4.1Leitura de Strings
  • 11.4.1.1 Função scanf()
  • 11.4.1.2 Função gets()
  • 11.4.2Escrita de Strings
  • 11.4.2.1 Função printf()
  • 11.4.2.2 Função puts()
  • 11.4.3Funções de Manipulação de Strings
  • 11.4.3.1 Função strlen()
  • 11.4.3.2 Função strcat()
  • 11.4.3.3 Função strcmp()
  • 11.4.3.4 Função strcpy()
  • 11.4.3.5 Função strchr()
  • 11.4.3.6 Função strstr()
  • 11.4.4Exemplo Geral
  • 12.Ponteiros
  • 12.1Expressões com Ponteiros
  • 12.1.1Atribuição de Ponteiros
  • 12.1.2Aritmética de Ponteiros
  • 12.2.1Comparação de Ponteiros
  • 12.3Ponteiros e Matrizes
  • 12.3.1Matrizes de Ponteiros
  • 12.3.2Acessando partes de Matrizes como vetores
  • Figura 12.2 Indireção simples e múltipla
  • 12.6Mais Sobre declarações de Ponteiros
  • 13.1Estruturas
  • 13.1.1Inicializando Estruturas
  • 13.1.2Estruturas Aninhadas
  • 13.1.3Estruturas e funções
  • 13.1.4Vetor de Estruturas
  • 13.1.5Ponteiros para Estruturas
  • 13.2Campos de Bits
  • 13.4Sizeof()
  • 14.1.1Função malloc()
  • 14.1.2Função calloc()
  • 14.1.3Função free()
  • 14.1.4Função realloc()
  • 14.2Matrizes Dinamicamente Alocadas
  • 14.3Listas Encadeadas
  • 14.3.1Listas Singularmente Encadeadas
  • 14.3.2Listas Duplamente Encadeadas
  • Figura 14.3 Exemplo de uma árvore binária
  • 15.E/S com Arquivo
  • 15.1E/S ANSI x E/S UNIX
  • 15.3Arquivos
  • 15.4 Sistema de Arquivos
  • 15.5Estrutura FILE
  • 15.6Abertura de Arquivos
  • 15.7Fechamento de Arquivo
  • 15.8.1Gravação
  • 15.8.2Leitura
  • 15.9Verificando fim de arquivo
  • 15.10Trabalhando com arquivos
  • 15.11Trabalhando com Strings: fputs() e fgets()
  • 15.12Funções de tratamento de arquivos
  • 15.12.1 rewind()
  • 15.12.2 ferror()
  • 15.12.3 remove()
  • 15.12.4 fflush()
  • 15.12.5 Função ftell()
  • 15.13Lendo e gravando registros
  • 15.13.1 Escrita de um bloco de dados
  • 15.13.2 Leitura de um bloco de dados
  • 15.13.3 Utilizando os comandos de leitura e gravação de registros
  • 15.15Comando de gravação em modo texto formatado
  • 15.19Sistema de Arquivo tipo UNIX
  • 15.19.1 open()
  • 15.19.2 creat()
  • 15.19.3 close()
  • 15.19.4 read() e write()
  • 15.19.5 unlink()
  • 15.19.6 lseek() e tell()
  • 15.19.7 Funções para manipulação de buffers

Linguagem de Programação

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

LINGUAGEM C

LINGUAGEM C

2/105

LINGUAGEM C

Sumário
1. INTRODUÇÃO....................................................................................................................................9 1.1 VISÃO GERAL DE UM PROGRAMA C......................................................................................................9 2. ESTRUTURA BÁSICA DE UM PROGRAMA EM C..................................................................10 2.1 BIBLIOTECAS.................................................................................................................................10 3. TIPOS DE DADOS............................................................................................................................11 3.1 ENUMERAÇÃO................................................................................................................................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 DISPONÍVEIS E ALGUMAS FUNÇÕES INTERESSANTES...........................................................14 4. COMANDO DE ESCRITA..............................................................................................................17 4.1 MODIFICADORES DE SAÍDA...............................................................................................................18 4.2 EXERCÍCIOS ..................................................................................................................................19 5. VARIÁVEIS.......................................................................................................................................20 5.1 NOME DE VARIÁVEIS......................................................................................................................20 5.2 DECLARAÇÃO DE VARIÁVEIS.............................................................................................................20 5.2.1 Tipos de Declarações de Variáveis...........................................................................................20
5.2.1.1 Variáveis locais..................................................................................................................................21 5.2.1.2 Parâmetros Formais...........................................................................................................................21 5.2.1.3 Variáveis Globais...............................................................................................................................21

5.3 PALAVRAS RESERVADAS...................................................................................................................22 6. OPERADORES..................................................................................................................................23 6.1 ATRIBUIÇÃO..................................................................................................................................23 6.1.1 Conversão de Tipos em Atribuições..........................................................................................23 6.2 OPERADORES ARITMÉTICOS..............................................................................................................24 6.2.1 Incremento e Decremento..........................................................................................................24 6.2.2 Operadores Aritméticos de Atribuição......................................................................................25 6.3 OPERADORES RELACIONAIS E LÓGICOS...............................................................................................25 6.4 OPERADORES BIT A BIT..................................................................................................................25 6.5 OPERADOR ?.................................................................................................................................26 6.6 OPERADORES DE PONTEIROS & E *....................................................................................................26 6.7 OPERADOR VÍRGULA.......................................................................................................................27 6.8 EXPRESSÕES ..................................................................................................................................27 6.8.1 Conversão de Tipos em Expressões...........................................................................................27 6.8.2 Casts...........................................................................................................................................28 6.8.3 Espacejamento e Parênteses......................................................................................................28 7. ALGUMAS FUNÇÕES DE E/S ......................................................................................................30 7.1 FUNÇÃO SCANF()............................................................................................................................30 7.2 FUNÇÃO GETCHE() E GETCH()............................................................................................................31 7.3 LENDO E ESCREVENDO CARACTERES...................................................................................................31 7.4 EXERCÍCIOS...................................................................................................................................32 8. COMANDOS CONDICIONAIS......................................................................................................33

3/105

....3 Classe de Armazenamento ............................4 Exemplo Geral..........................1 INICIALIZAÇÃO DE VETORES E MATRIZES....................................................9 EXERCÍCIOS.................................................................................................................5 11........53 strcpy()..........1 Classe de Armazenamento ............4...43 10.............47 10...........................2 Função puts().........................................................LINGUAGEM C 8..............................3.........................................................3.......................................6............2 11....................................4.........51 11..................................................6.................2 Escrita de Strings...............................................................2 Classe de Armazenamento ........................................................................................52 strcat()...........................2 Corpo da função depois do programa principal (no mesmo arquivo).............................................................................................6 Função Função Função Função Função Função 11..................37 9........56 12......extern..........................................................................................................1..................44 10..........................................................5 EXERCÍCIOS........................2 Função gets()........2.................................50 11......3 LIMITES ........................................6 CLASSES DE ARMAZENAMENTO... FUNÇÕES...................static............49 11............4 STRINGS......................3 Corpo da função escrito em arquivo separado.....................................................................................................3........................................................46 10..........................................1 Funções para número variável de argumentos...................................................................................................................................................3 PROTÓTIPO DE FUNÇÕES....................................................................................5 NÚMEROS DE PARÂMETROS VARIÁVEL.....................................................................................................................46 10........................................................................................................................................36 9...............1...............3.....................................................................................................................1 Função printf()......................1 11.......2 MATRIZES E VETORES COMO ARGUMENTO DE FUNÇÕES.................................................................3..............................46 10....52 strcmp().....................................................................................53 11..................................... VETORES E MATRIZES........4 COMANDOS BREAK.......34 9..............................4 RETORNO DE PONTEIROS..................................................................................................................................4..........................................................................................................................4..........................................................1 Leitura de Strings..................................................................46 10...............................................56 12.48 11................33 8.........1.......1 Corpo da função antes do programa principal (no mesmo arquivo)..............................................................................4.............................................................. CONTINUE E EXIT()................................6.....................2 ARGUMENTOS PARA FUNÇÃO MAIN()....................................52 11................................................................................................................................................register......1 LAÇO FOR...43 10......................3.............45 10.........................5.............................................................53 strchr()..2 COMANDO SWITCH...............46 10.......1 Função scanf()........3 11.....1 Atribuição de Ponteiros........................................................................................................................................................................8 FUNÇÕES RECURSIVAS....................................................53 11...........42 10..............................auto...................................................54 12..................................43 10....4...........................................................................................................................1 COMANDO IF.............................................................2 LAÇO WHILE...........................................................................................37 9............3 EXERCÍCIOS................36 9............................ COMANDOS REPITITIVOS OU LAÇOS......................................................4............................................................................................1 Variáveis Locais static...........................................................47 11.....................................1 EXPRESSÕES COM PONTEIROS...................................49 11.........................4..2 Variáveis Globais static..............................................................56 4/105 ................6.....7 DIRETIVA #DEFINE..............................4......45 10....................48 11.......................................................................6......................5 EXERCÍCIOS.........4 Classe de Armazenamento ..........................................................................................1 LOCALIZAÇÃO DAS FUNÇÕES...................................................................................................................................... PONTEIROS.................................................51 11.....................................................53 strstr()...............4 11.................................6................................33 8......3 Funções de Manipulação de Strings............................38 10..........50 11.1.....................3..............1....................................4..41 10.....................................................1...........51 strlen().......2.4.......40 10......4........................3.......................................50 11..............41 10...........................................................................................................................3 LAÇO DO-WHILE.............................................51 11............................................45 10...............................................36 9......................................................................................................................................4.41 10........4.....................................................................44 10....................................................................................

..........1 Gravação.............................1.......................................6 ABERTURA DE ARQUIVOS..................................................................................................................4 Vetor de Estruturas..........................................................................................................................2 Listas Duplamente Encadeadas.........................8.................78 14....................90 15...............................3 Estruturas e funções..................................................................................................................1 Inicializando Estruturas...............................................................................................................92 5/105 ...............................................................................62 12........90 15.....89 15........................................................................................................57 12...........................................1..............................58 12.................................................................................................................................................................92 15..................72 13..........................87 15...5 EXERCÍCIOS..........................3 UNIÕES...............12......1 Comparação de Ponteiros................................80 14................................................................... ESTRUTURAS E UNIÕES..........2 Aritmética de Ponteiros..........................................................................12 FUNÇÕES DE TRATAMENTO DE ARQUIVOS...2 Função calloc()..................................................75 14....1 Função malloc().....................................................................................................................................................................................................................78 14...............1 FUNÇÕES DE ALOCAÇÃO DINÂMICA EM C.....................................................2 Leitura.................81 14............................................................................................................88 15...................LINGUAGEM C 12........................91 15.................................87 15..........88 15...75 14....................................................................83 14........8 LEITURA E GRAVAÇÃO DE CARACTERES.....11 TRABALHANDO COM STRINGS : FPUTS () E FGETS ()...........69 13..................8.....................................................................................89 15.................................................................5 TYPEDEF................4 INDIREÇÃO MÚLTIPLA.....57 12..........................1.........................................60 12..................................................................................................................................9 VERIFICANDO FIM DE ARQUIVO..................................................................................................... ALOCAÇÃO DINÂMICA..................................................................1 E/S ANSI X E/S UNIX.....................................................4 ÁRVORES BINÁRIAS.......................................64 13.....................5 ESTRUTURA FILE...............................65 13....................................................................................................................................................73 14.6 EXERCÍCIOS................................................................................................................................................3 ARQUIVOS.1....... E/S COM ARQUIVO.........................................................................................................................................................................................................................4 SISTEMA DE ARQUIVOS.......................................................................1...............................4 SIZEOF()........................3 LISTAS ENCADEADAS............2 CAMPOS DE BITS............................3...................................10 TRABALHANDO COM ARQUIVOS......................................................61 12................5 Ponteiros para Estruturas............1.1............1 rewind()..............7 FECHAMENTO DE ARQUIVO............................................................................2 INICIALIZAÇÃO DE PONTEIROS.......................................76 14.........................66 13...................................68 13......................1 ESTRUTURAS.........................................................87 15................................................77 14.........................................7 EXERCÍCIOS......5 PONTEIROS PARA FUNÇÕES.................68 13.......................1 Listas Singularmente Encadeadas...........................................................................................................1........................75 14.......................................................................................................................................................4 Função realloc().........2 Acessando partes de Matrizes como vetores...................86 15......58 12........80 14.................................................................................................................................................................65 13..............................................1.......................2.....66 13...................................................1.........................................................3 Função free()....................................................................................70 13.............................................87 15.....................................................67 13...59 12.....................3...........................................................................................................................2 Estruturas Aninhadas.............................................................................................89 15.......................................................3 PONTEIROS E MATRIZES..........................................................6 MAIS SOBRE DECLARAÇÕES DE PONTEIROS................................................................................................................................................................2 MATRIZES DINAMICAMENTE ALOCADAS..........................................................................................................87 15..............................................................................................60 12.........................................72 13..........................................2 STREAMS..............................................................................................3.............3...................90 15.1 Matrizes de Ponteiros..................

..............95 15..................................................................................103 15.........................................................................LINGUAGEM C 15.....................105 6/105 ..........19.......100 15..........99 15.................................................................................................................................................................................5 unlink().........................................103 15.................................97 15..................................................................19.............................................................................................3 remove()........................7 Funções para manipulação de buffers.............................................19...........................................103 16.......................................14 ACESSO ALEATÓRIO..............4 fflush()..................................................................................................93 15.................................................12....12.............19...................................................... BIBLIOGRAFIA.16 CONDIÇÕES DE ERRO.............94 15.................99 15......................................................101 15.....................................................................................................................13....................13 LENDO E GRAVANDO REGISTROS.............18 EXERCÍCIO:........98 15....................................................................................4 read() e write()..............95 15..............94 15................................................98 15..........................................................................................12...............................13...........12.2 ferror().......................................5 Função ftell()...................................................................................................3 close().........................................................................................19....3 Utilizando os comandos de leitura e gravação de registros...............94 15........................................2 creat().......................101 15......1 Escrita de um bloco de dados.................................................19........94 15......................19 SISTEMA DE ARQUIVO TIPO UNIX....1 open()................................................93 15.........................................................................................................................96 15..............................................................13........................101 15..............................6 lseek() e tell()............................................................................17 STREAMS PADRÃO.......19.....................................................2 Leitura de um bloco de dados.................15 COMANDO DE GRAVAÇÃO EM MODO TEXTO FORMATADO...................................................................................................................

.....................................................LINGUAGEM C Lista de Figuras FIGURA 1.......................CODIFICAÇÃO DE UM PROGRAMA C..............................................3 EXEMPLO DE UMA ÁRVORE BINÁRIA.84 7/105 ..1 .........................................9 FIGURA 12......2 INDIREÇÃO SIMPLES E MÚLTIPLA......61 FIGURA 14......................

LINGUAGEM C Lista de Tabelas 8/105 .

O compilador C gera códigos mais enxutos e velozes do que muitas outras linguagens.1 . pois permite acesso e programação direta do microprocessador. A linguagem C tornou-se muito popular devido a características como: • O C é uma linguagem de alto nível com uma sintaxe bastante estruturada e flexível tornando sua programação bastante simplificada. processadores de texto. FIGURA 1. • O C compartilha recursos tanto de alto quanto de baixo nível. • Embora estruturalmente simples (poucas funções intrínsecas) o C não perde funcionalidade pois permite a inclusão de uma farta quantidade de rotinas do usuário. No início da década de 80 a linguagem C é padronizada pelo American National Standard Institute: surge o ANSI C.Codificação de um programa C Editor (módulo fonte em C) Pré-processador (novo fonte expandido) Compilador (arquivo objeto) Linkador (executável) . rotinas cuja dependência do tempo é crítica. podem ser facilmente implementadas usando instruções em Assembly. que termina com o executável criado pelo linkador. Um exemplo clássico é o sistema operacional UNIX. Essa ação desencadeia uma seqüência de etapas. Introdução A linguagem C foi criada por Dennis M. sistemas de transmissão de dados. a linguagem C vem sendo usada para desenvolver novas linguagens. o programador aciona o compilador. Atualmente. 1. baseada na linguagem B de Thompson que era uma evolução da antiga BCPL. Depois de escrever o módulo fonte em um editor de textos. entre outros. Os fabricantes de compiladores fornecem uma ampla variedade de rotinas pré-compiladas em biblioteca Como uma ferramenta poderosa a linguagem C é usada na construção de vários aplicativos como sistemas operacionais. • O C é uma linguagem estruturalmente simples e de grande portabilidade. • Programas em C são compilados.1 Visão geral de um programa C A geração do programa executável a partir do programa fonte obedece a uma seqüência de operações ante de tornar-se um executável. entre elas a linguagem C+ + e Java. planilhas eletrônicas. Com isto. o qual foi implementado em C.1. cada qual traduzindo a codificação do usuário para uma forma de linguagem de nível inferior. Por esta razão o C é a linguagem preferida dos programadores de aplicativos. gerando programas executáveis. Ritchie e Ken Thompson no Laboratório Bell em 1972.

os caracteres “<>“ significam ao compilador que deve procurar somente no diretório padrão ou nos diretórios definidos pelas variáveis de ambiente. deve existir um mecanismo que garanta que todos os programas inicializem da mesma forma. • As instruções C são sempre encerradas por um ponto-e-vírgula.1 #include <stdio. 10/105 . 2. A diretiva é #include instrui o compilador a ler outro arquivo-fonte. Para fazer isto. os parênteses e as chaves são os únicos elementos obrigatórios de uma função. Sintaxe: main() { } primeira função a ser executada inicia o corpo da função termina a função Abaixo relacionam-se algumas regras para a programação em C: • Toda função C deve ser iniciada e encerrada por um abre chaves e um fecha chaves respectivamente. Sintaxe: #include nome_arq onde: nome_arq tem que estar entre aspas ou símbolos de maior ou menor Em algumas plataformas existe somente uma das duas formas. Baseado nesta afirmação. Exemplo 2. Cada comando pré-definido em C está prototipado em alguma biblioteca (isto é informado conjuntamente ao comando). • Todas as instruções devem estar dentro das chaves.LINGUAGEM C 2. Este tipo de declaração é muito usado nos programas profissionais. Também. Tal função chama-se main(). aspas significa para o compilador que a biblioteca em questão deve ser buscada primeiramente no diretório atual e depois no diretório padrão do turbo ou pelas variáveis de ambiente.h> Não se usa o ponto-e-vírgula após diretivas de compilação. • O nome da função. No caso da plataforma DOS/Windows 95. usa-se uma diretiva de compilação a qual é colocada fora de qualquer função do programa.1 Bibliotecas Para não ter que criar programas grandes devido a linkedição de um arquivo objeto a linguagem inclui as bibliotecas para que no momento da compilação seja gerado um programa com as funções utilizadas. Este mecanismo pode ser entendido como a padronização da função que será chamada primeiramente. Estrutura Básica de um Programa em C Um programa C consiste em uma ou várias “funções”.

O uso mais importante de signed é modificar char em implementações em que esse tipo.”.”.147. printf(“Comprei %d camisas de tamanho %c. isso reduz a portabilidade de seu código e geralmente não é recomendado. pois ele passa de 2 bytes para 4 bytes de armazenamento. ele é permitido porque a declaração default de inteiros assume um número com sinal.1 é válida.483.7E-308 a 1. char tam. Exemplo 3. float total.483.925 Dez dígitos de precisão • • signed.147.Tipos de dados básicos TIPO char int float double void BIT 8 16 32 64 0 FAIXA MÍNIMA -128 a 127 .1 . long também pode ser aplicado a double.483. custo).647 a 2.32768 a 32767 3. No entanto. total = 20.Utilização 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 MÍNIMA 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. paguei R$ %f. long e unsigned podem ser aplicados aos tipos básicos caractere e inteiro. short. Os modificadores signed.147. No caso do sistema operacional ser 32 bits o tipo int será o único a ser alterado. A tabela 3. os tipos de dados básicos podem estar acompanhados por modificadores na declaração de variáveis.483. não tem sinal.967. Porém.647 -2. O uso de signed com inteiros é redundante. qtde = 2. Algumas implementações podem permitir que unsigned seja aplicado aos tipos de ponto flutuante (como em unsigned double). • short.647 0 a 4.LINGUAGEM C 3. unsigned.2 . qtde.2 mostra todas a combinações de tipos de dados Tabela 3.147. Tabela 3. 11/105 . tam).2 main() { int qtde. por padrão. O modificador unsigned altera o valor da faixa mínima do tipo através do uso do bit mais significativo (indicador de sinal).647 a 2. tam = ‘G’. Contudo. Tipos de Dados Em C existem 5 tipos de variáveis básicas. Nos computadores da linha IBM-PC (sistema operacional 16 bits) a tabela 3. printf(“\nNo total. Isto também faz com que o intervalo de valores seja aumentado.4E+38 1.7E+308 sem valor Com exceção de void.70. Os modificadores de tipos da linguagem C são: • long.4E-38 a 3.294.

que a execução será a mesma da versão anterior.70. As variáveis podem ser inicializadas no momento em que se faz a declaração das mesmas. printf (“%d %d”. float total=20. Pode-se ver isto usando o programa anterior.”.3 enum cores { amarelo. tanto o nome da enumeração quanto a lista de variáveis são opcionais. qtde. mostra 1 2 na tela. custo). Para melhor compreensão da enumeração entende-se que cada símbolo representa um valor inteiro. O nome da enumeração é usado para declarar variáveis daquele tipo.2 enum cores {amarelo.”. vermelho }. verde. char tam=‘G’. paguei R$ %f. main() { int qtde=2. Aqui.1 Enumeração Enumeração é um conjunto de constantes inteiras que especifica todos os valores legais de uma variável desse tipo pode ser. printf(“Comprei %d camisas de tamanho %c. os tipos de comandos seguintes são perfeitamente válidos: semaforo = verde. paguei R$ 20.LINGUAGEM C } Execução: Comprei 2 camisas de tamanho G.70. } 3. verde. Agora os valores destes símbolos são amarelo verde vermelho 0 10 11 12/105 . printf(“\nNo total. enum cores semaforo. A forma geral para enumeração é: Sintaxe: enum nome { lista_de_enumeração } lista_de_variáveis. O valor do primeiro símbolo da enumeração é 0. if (semaforo==verde) printf(“Passagem permitida \n”). tam). Como extensão. Assim. verde=10. No total. pode-se inicializar os símbolos de forma alternada para algum problema específico. Dada essa definição e declaração. Com isso pode-se declarar as cores Exemplo 3. Exemplo 3. vermelho}. vermelho).

Esses modificadores são const e volatile. Isto pode ser exemplificado pelos exemplos 3.2 da função printf(). se 0x30 é assumido como sendo o valor de uma porta que é mudado por condições externas.4 const int a=10.2 Modificadores de Tipo de Acesso O padrão ANSI introduziu dois novos modificadores de tipo que controlam a maneira como a variáveis podem ser acessadas ou modificadas. 3. É possível usar const e volatile juntos.5 ‘C’ “programa” 8 465.1 e 3. com um valor inicial 10.1 Const Variáveis do tipo const não podem ser modificadas por seu programa (por isso ela recebe um valor inicial). Para tipos em ponto flutuante coloca-se um F após o número. O exemplo 5. Para evitar efeitos colaterais deve-se declarar da seguinte forma: const volatile unsigned char *port = 0x30. Um exemplo do uso do const é para verificar se uma variável em particular é modificada pelo seu programa.2 Volatile O modificador volatile é usado para informar ao compilador que o valor de uma variável pode ser alterado de maneira não explicitamente especificada pelo programa.2. Pode-se especificar precisamente o tipo da constante numérica através da utilização de um sufixo. Por exemplo. ele tornar-se-á um long double. A maneira como cada constante é representada depende do seu tipo.67 Constantes em C podem ser de qualquer um dos cinco tipos de dados básicos. Isso ajuda o programa no sentido de avisar ao compilador que o conteúdo de uma variável é mutável. mesmo que sua referência não aparecer no lado esquerdo da expressão. Devem preceder os modificadores de tipo e os nomes que eles modificam. 3.3 Constantes Uma constante tem valor fixo e inalterável durante a execução do programa. Se for colocado um L. Nessa situação. Por exemplo. Em uma constante caractere é escrita entre aspas simples (‘’). 3. ele será tratado como float.4 cria uma variável inteira chamada a. Exemplo 3. Exemplo 3. uma constante cadeia de caracteres entre aspas duplas (“”) e constantes numéricas como o número propriamente dito. o conteúdo de uma variável é alterado sem nenhum comando de atribuição explicito no programa. que seu programa não pode modificar.LINGUAGEM C 3. Para tipos 13/105 . um endereço de uma variável global pode ser passado para a rotina de relógio do sistema operacional e usado para guardar o tempo real do sistema.2.

0. 0. e.h limits.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. A seguir segue uma tabela contendo algumas (existem muitas outras) constantes simbólicas pré-definidas no compilador Turbo C++ da Borland..23 12312333 -0...). limites de tipos etc.3 mostra alguns exemplos de constantes..h conio.h conio. 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.h conio.h math.h math.78539. Estas constantes em geral definam alguns valores matemáticos (π.h math. Uma constante octal começa com 0.14159. o sufixo U representa unsigned e o L representa long. A tabela 5..h math.57079.3 . Uma constante hexadecimal deve consistir em um 0x seguido por uma constante na forma hexadecimal.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. 1. /* 128 em decimal */ /* 10 em decimal */ 3. algumas constantes simbólicas já estão pré-definidas. Usam-se tais sistemas numéricos para facilitar a programação. π/2. etc. Tabela 3.h conio.4 Constantes pré-definidas Em alguns compiladores C. Exemplo 3...LINGUAGEM C inteiros.31830.h conio.34e-3F 123..2L Além deste tem-se as constantes Hexadecimais e Octais.23F 2. int oct = 012..h conio..6 int hex = 0x80. Biblioteca math.41421. 1.9876324 1001.h limits.5 As bibliotecas disponíveis e algumas funções interessantes A seguir segue uma lista de algumas as bibliotecas disponíveis no compilador Turbo C++ Borland: Ao longo do texto veremos o uso de muitas funções cobrindo uma boa parte destas 14/105 .

h setjmp.h sys\types.h stdarg.h dir. double asin(double arco). Ex. double sin(double arco). double fabs(double d).h bcd. ceil() arredonda para cima.h iostream. Ex. 15/105 . Biblioteca math.h stddef.h mem.h stdio.h stdlib. Calcula o valor absoluto do inteiro i e do real d. porém o leitor que desejar tornar-se "fluente" na linguagem C pode (e deve) estudá-las com profundidade.h complex.h limits.h math. double ceil(double num).h dirent. ceil(3.h iomanip.h int abs(int i).h stream. alloc.h strstrea.h time. Funções trigonométricas do ângulo arco.h errno.h ctype.h io.h string.h fcntl. double tan(double arco).h locale.h assert. double acos(double arco).0.h share.2) == 3.h bios.h float.h malloc. double floor(double num). floor(3.h fstream.h sys\stat. double cos(double arco).h values.h Vejamos algumas funções disponíveis nas bibliotecas C. double log(double num).h signal.h conio. double log10(double num). respectivamente.h stdiostr.2) == 4.h graphics.h sys\timeb. double atan(double arco). floor() arredonda para baixo. Funções de arredondamento para inteiro.h process.h dos.0.LINGUAGEM C bibliotecas.h generic. em radianos.

0. 16/105 .h int random(int num).6) = 3. log10() é logaritmo decimal (base 10). double exp).6.2.1. Raiz quadrada: sqrt(9.LINGUAGEM C Funções logarítmicas: log() é logaritmo natural (base e). Biblioteca stdlib.25.0) = 3. double pow(double base. Potenciação: pow(3.5. Gera um número inteiro aleatório entre 0 e num . double sqrt(double num).

Comando de Escrita A função printf() é uma das funções de E/S (entrada e saída) que mostra na tela os parâmetros que são passados como argumento. Tabela 4. os quais estã relacionados na tabela 4. Seu protótipo está na biblioteca stdio.LINGUAGEM C 4.4 .h.Códigos para formatação de impressão CÓDIGO printf() %c %d ou %i %e ou %E (minúsculo ou maiúsculo) %f %g ou %G (minúsculo ou maiúsculo) %o %s %u %x ou %X (minúsculo ou maiúsculo) %% Exemplo 4. lista_de_argumentos) expressão_de_controle = contém caracteres que serão exibidos na tela e códigos de formatação que indicam o formato em que os argumentos (da lista_de_argumentos) devem ser impressos.3 . existem os códigos para formatação de impressão dos argumentos passados para a função. A tabela 4. Tal lista não tem tamanho máximo e cada argumento deve ser separado por uma vírgula.1 mostra os códigos na linguagem para caracteres que não podem ser inseridos diretamente do teclado. Sintaxe: onde: printf(“<expressao_de_controle>”.3 main() FORMATO Caractere Simples Decimal Notação Científica Ponto Flutuante %e ou %f (o mais curto) Octal Cadeia de Caracteres Decimal sem Sinal Hexadecimal Escreve o símbolo % 17/105 .2. lista_de_argumentos = lista de argumentos que serão apresentadas na expressão_de_controle. Tabela 4.Código para os caracteres especiais CÓDIGOS ESPECIAIS \n \t \b \” \\ \f \r \’ \v \a \N \xN \0 SIGNIFICADO Nova Linha (LF) Tab (HT) Retrocesso (BS) ” Barra invertida Salta Página de Formulário (FF) Retorno de Carro (CR) ’ Tabulação Vertical Alerta (beep) Constante octal (onde N é uma constante octal) Constante Hexadecimal (onde N é uma constante hexadecimal) Nulo Além destes.

10). segundo um código especial para representar caracter de nova linha \n. “Numero”.1 percebe-se o uso de dois tipos de códigos: primeiro de formatação com %s (para strings) representando a constante string “Linguagem” e %d (decimais) representando a constante ano 1972. 1972). mas o seu valor é o próximo parâmetro. Para isto relacionam-se: • ‘-’ : alinhamento pela esquerda. } Execução: A Linguagem C foi criada em 1972 No exemplo 3. printf(“%-8s %4d”. • * : substitui um dos n. printf(“%8s %4d”.10.representa 1 espaço em branco.LINGUAGEM C { printf(“A %s C foi criada em %d \nOk?”.10). nota-se que ‘C’ é delimitado por aspas simples enquanto que “Linguagem” é delimitado por aspas duplas.“Numero”.99 Long 57485784 18/105 . • ‘+’: coloca o sinal de menos ou mais se o valor for numérico. printf(“Long %ld”. • ‘l’ : indica que segue um dado longo. onde: # . printf(“ criada em %d ”. “Numero”. “Linguagem”. 57485784).5s %2. • n (número) : indica o tamanho mínimo do campo. printf(“%-3.99). Exemplo 4.m : tamanho máximo do campo.2f”.3 COMANDO printf(“%s %d”. Isto indica ao compilador como diferenciar um caractere de uma cadeia de caracteres. ‘C’). 1972).10).4 main() { printf(“A %s %c foi ”. Se o tamanho iniciar com 0 (ex.1 Modificadores de Saída Para complementar os códigos de formatação a linguagem C oferece alguns códigos especiais para melhorar a apresentação dos dados. } Execução:: A Linguagem C foi criada em 1972 Ok? No exemplo 3. Exemplo 4. • . “Linguagem”.2. “Numero”. TELA Numero 10 ##Numero ##10 Numero## ##10 Numer 10. 05). menos para os reais onde é usado para indicar o número de casas decimais. O preenchimento é feito com espaços em branco. 4. o preenchimento passa a ser feito com zeros.

Escreva os comandos de saída formatada que gerem as seguintes saídas: 01234567890123456789012 a) Camisa estampada 40.LINGUAGEM C 4.00 00040.00 00035.00 19/105 .00 35.00 b) Camisa estampada Camisa lisa c) Camisa estampada Camisa lisa d) Camisa e Camisa l 40 35 40.00 Camisa lisa 35.2 Exercícios 1.

isto é. ano = 1972. ano). ano. 5. pode-se declará-la de uma vez separando seus nomes por vírgulas. Em C.2 Declaração de Variáveis A declaração de variáveis serve para reservar uma quantidade de memória apropriada para armazenar o tipo especificado. Em C todas as variáveis devem ser declaradas. int ano. O número de caracteres válidos é definido de ambiente para ambiente. é um exemplo de declaração de variável.2. 5. Estas são variáveis locais. Se existir mais de uma variável do mesmo tipo. 5. atribui um valor à variável e este valor será acessado através de seu nome.1 Regras: Nome de Variáveis • • • Uma variável não pode ter o mesmo nome de uma palavra-chave de C.1 Tipos de Declarações de Variáveis O tipo de declaração de variável é definido pela localização onde a mesma é declarada. O conteúdo da mesma pode variar segundo os comandos de alteração do programa. printf(“A Linguagem C foi criada em %d ”. e um nome. seguido do nome da variável. int. ano = 1972. Para realizar isto foi usado o operador de atribuição (=). } A primeira instrução. Tal declaração consiste no nome de um tipo. parâmetros formais e variáveis globais. Variáveis Variável em C é um espaço de memória reservado para armazenar um certo tipo de dado e tendo um nome para referenciar o seu conteúdo. dia. letras maiúsculas diferem das letras minúsculas.5 main() { int ano. apresenta um tipo. mes. na definição dos parâmetros das funções e fora de todas as funções. 20/105 . A segunda instrução. int ano. respectivamente.LINGUAGEM C 5. Existem três lugares básicos: dentro de funções. Exemplo 5.

2. printf(“%d } %d ”. num * num.4 int num=10.3 int soma(int x. Tais variáveis são reconhecidas pelo programa inteiro e podem ser usadas por qualquer pedaço de código. num * num).LINGUAGEM C 5.1.1. int x) { return ((x+z)/num).2 Parâmetros Formais Variáveis que são declaradas para passagem de parâmetros em funções.2 void main() { int num. media(x1. } void main() { int x1 = 15.2.1 Variáveis locais Variáveis que são declaradas dentro de uma função. int x2 = 4. Exemplo 5. não são reconhecidas fora de seu próprio bloco de código.2. } Exemplo 5.5 int num=2. void main() { printf(“%d”. } 5. 21/105 .x2)).3 Variáveis Globais Variáveis que são declaradas fora de qualquer função. int y) { return (x+y). Exemplo 5. Tais variáveis só podem ser referenciadas por comandos que estão dentro do bloco no qual as variáveis foram declaradas. num = 10. Exemplo 5. } 5.1. int media(int y. isto é.

3 Palavras reservadas Existem certos nomes que não podem ser usados como identificadores. São chamadas as palavras reservadas e são de uso restrito da linguagem C (comandos.). 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 . declarações. estruturas. etc.LINGUAGEM C 5.

exceto por f converter um valor inteiro de 16 bits no formato de ponto flutuante. Isso também acontece na linha 4. a regra de conversão de tipos é muito simples: o valor do lado direito (lado da expressão) de uma atribuição é convertido no tipo do lado esquerdo (variável destino).5 . 6. o resultado é arredondado Precisão. isto é. Conversão de tipos refere-se à situação em que variáveis de um tipo são misturadas com varáveis de outro tipo. Na linha 2. os bits mais significativos da variável inteira x são ignorados. 6. o valor de ch reflete apenas os bits menos significativos de x. relacionais.2 void main() { int x. a = b = c = 10. Além disso. ch = x. C tem alguns operadores especiais para tarefas particulares.1 mostra-se algumas conversões de tipos e seus efeitos. Além disto. Se x está entre 255 e 0. a linguagem oferece um tipo de atribuição múltipla. 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 fracionária e possivelmente mais Precisão.LINGUAGEM C 6.1 Conversão de Tipos em Atribuições A linguagem C permite a conversão automática de tipos. lógicos e bit a bit. deixando ch com os 8 bits menos significativos. Operadores A linguagem C é muito rica em operadores internos. Em um comando de atribuição. como no exemplo 6. x recebe a parte inteira de f.6 x = 10. C define quatro classes de operadores: aritméticos. Tabela 6. } // // // // Linha Linha Linha Linha 1 2 3 4 Na linha 1.2: Exemplo 6.1 Atribuição Para o operador de atribuição é utilizado o símbolo =. Para essas conversões foi assumido uma palavra de 16 bits. em um comando só pode-se atribuir o mesmo valor a muitas variáveis. f = x. De outra forma. x = f. char ch. o resultado é arredondado 23/105 . Na linha 3.1.Conversões de tipos e seus efeitos Tipo Destino signed char char char char int int float double Tipo da Expressão char short int int long int long int float double long double Possível Informação Perdida Se valor > 127. f = ch. f converte o valor inteiro de 8 bits armazenado em ch no mesmo valor em formato de ponto flutuante. então ch e x têm valores idênticos. Na tabela 6. float f. por exemplo. Exemplo 6. o que não acontece em Pascal.

também menos unário Adição Multiplicação Divisão Módulo da Divisão (resto) Decremento Incremento O menos unário multiplica seu único operando por -1.LINGUAGEM C Para utilizar a tabela acima a fim de fazer uma conversão não mostrada.1. qualquer número precedido por Quando / é aplicado a um inteiro ou caractere. x++.2. 6. Tabela 6. y = x++.2 Operadores Aritméticos A tabela 6. ou ou x = x + 1. os quais somam 1 ao seu operando. então.2 mostra os operadores aritméticos suportados pela linguagem. Isso é. por exemplo.2 . ou --x. Se o operador de incremento ou decremento preceder seu operando. respectivamente. 6. y = ++x. Contudo. devolvendo o resto de uma divisão inteira. float em int. Se o operador estiver após seu operando.Operadores aritméticos Operador + * / % -++ um sinal Ação Subtração. Exemplo 6. trabalha em C da mesma forma que em outras linguagens. % não pode ser usado nos tipos em ponto flutuante. simplesmente converta um tipo por vez até acabar. -/ % Mais alta Mais baixa Os operadores do mesmo nível de precedência são avaliados pelo compilador da esquerda para 24/105 . Quando usados em uma expressão tem seus efeitos alterados pela posição do sinal de decremento e incremento. /* y recebe 10 */ A precedência dos operadores aritméticos é a seguinte: ++ * + a direita. x = x . para converter double em int. /*y recebe 11*/ x = 10. São os operadores de incremento (++) e decremento (--).1 Incremento e Decremento A linguagem C inclui dois operadores que geralmente não encontramos em outras linguagens. x--. qualquer resto é truncado. primeiro converta double em float e. C usa o valor do operando antes de incrementá-lo ou decrementá-lo. ou ++x. O operador módulo % também.3 x = 10. e subtraem 1 de seu operando. C executa a operação de incremento ou decremento antes de usar o valor do operando.

Operadores aritméticos de atribuição Operador x -= y x += y x *= y x /= y x %= y Ação x=x-y x=x+y x=x*y x=x/y x=x%y As expressões com este operadores são mais compactas e normalmente produzem um código de máquina mais eficiente. verdadeiro é qualquer valor diferente de zero. Tabela 6.6 mostra o resultado de operações com deslocamento.3 Operadores Relacionais e Lógicos A tabela 6.2. 6.4 Operadores Bit a Bit A tabela 6. 25/105 . Tabela 6.4 mostra os operadores relacionais e lógicos suportados pela linguagem C.5 .2 Operadores Aritméticos de Atribuição A tabela 6. e falso é zero.4 . Lembre-se de que toda expressão relacional e lógica produz como resiltado 0 ou 1.Operadores relacionais e lógicos Operador > >= < <= == != Ação Maior que Maior ou igual que Menor que Menor ou igual que Igual Diferente Operador && || ! Ação AND OR NOT Em C.3 mostra os operadores aritméticos de atribuição suportados pela linguagem. As expressões que usam operadores relacionais ou lógicos devolvem zero para falso e 1 para verdadeiro. A precedência dos operadores relacionais e lógicos é a seguinte: ! > == && || Mais alta >= != < <= Mais baixa 6.5 mostra os operadores bit a bit suportados pela linguagem.LINGUAGEM C 6.3 .Operadores bit-a-bit Operador & | ^ ~ >> << Ação AND OR OR exclusivo (XOR) Complemento de um Deslocamento à direita Deslocamento à esquerda A tabela 6. Tabela 6.

LINGUAGEM C Tabela 6.6 - Exemplo de operações de deslocamento bit-a-bit char x; x =7 x << 1 x << 3 x << 2 x >> 1 x >> 2 x a cada execução da sentença 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 padrão C. Operações bit não podem ser usadas em float, double, long double, void ou outros tipos mais complexos.

6.5

Operador ?
O operador ? substitui sentenças da forma Se-então-senão.

Sintaxe: Exp1 ? Exp2 : Exp3; Onde Exp1, Exp2 e Exp3 são expressões. Onde Exp1 é avaliada e se a mesma for verdadeira, então Exp2 é avaliada e se torna o valor da expressão. Se Exp1 é falso, então Exp3 é avaliada e se torna o valor da expressão. 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 expressão equivalente seria x = 10; if (x > 9) y = 100; else y = 200;

6.6

Operadores de Ponteiros & e *

Um ponteiro é um endereço na memória de uma variável. Uma variável de ponteiro é uma variável especialmente declarada para guardar um ponteiro para seu tipo especificado. O primeiro operador de ponteiro é &. Ele é um operador unário que devolve o endereço na memória de seu operando. Por exemplo, m = &cont; atribui o endereço de memória da variável cont em m. Este tipo de operando não pode ser utilizado em três casos: 1. &(cont + 4) - sempre associa-se a uma variável e não expressão; 2. &3 - constantes não são válidas; 3. variáveis declaradas com classe de armazenamento register (não existe endereço para registrador).

26/105

LINGUAGEM C O segundo operador é *. Ele é um operador unário que devolve o valor da variável localizada no endereço que o segue. Por exemplo, se m contém o endereço da variável cont, q = *m; coloca o valor de cont em q. Os seguintes operadores * e & colocam o valor 10 na variável 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 Vírgula

O operador vírgula é usado para encadear diversas expressões. O lado esquerdo de um operador vírgula é sempre avaliado como void. Isso significa que a expressão do lado direito se torna o valor de toda a expressão separada por vírgulas. 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

Expressões

Operadores, constantes e variáveis são os elementos que constituem as expressões. Uma expressão é qualquer combinação válida desses elementos.

6.8.1 Conversão de Tipos em Expressões
Quando constantes e variáveis de tipos diferentes são misturadas em uma expressão, elas são convertidas a um mesmo tipo. O compilador C converte todos os operandos no tipo do maior operando, o que é denominado promoção de tipo. Isso é feito operação por operação, como descrito nas regras de conversão de tipos abaixo. SE um operando é long double ENTÃO o segundo é convertido para long double. SENÃO, SE um operando é double ENTÃO o segundo é convertido para double. SENÃO, SE um operando é float ENTÃO o segundo é convertido para float. SENÃO, SE um operando é unsigned long ENTÃO o segundo é convertido para unsigned long. SENÃO, SE um operando é long

27/105

LINGUAGEM C ENTÃO o segundo é convertido para long. SENÃO, SE um operando é unsigned ENTÃO 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 não pode ser representado por um long, os dois operandos são convertidos para unsigned long. Considere as conversões 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 são 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 expressão pode ser forçada a ser de um tipo especificado usando uma construção chamada cast. A forma geral de um cast é (tipo) expressão onde um tipo é um tipo de dado padrão de C. Por exemplo, para ter certeza de que a expressão x /2 será do tipo float, escreve-se (float) x/2; Neste caso se a variável x fosse um inteiro ímpar sem o cast seu valor reria um inteiro (o que não seria verdadeiro). Entretanto, com o uso do Cast oa variável x é definida como um float o que tornará o seu resultado um float. Como um operador, um cast é unário e tem a mesma precedência de qualquer outro operador unário.

6.8.3 Espacejamento e Parênteses
A linguagem C não limita o espaçamento ou tabulações em uma expressão. Ajudam a aumentar a legibilidade do programa.

28/105

29/105 . não provoca erros.LINGUAGEM C O excesso de parênteses não causa erros. mas dificulta a leitura do programa. isto é. colocar parênteses onde não necessita.

lista_de_argumentos) A expressão de controle pode conter códigos de formatação. printf (“ octal e hexadecimal. %o oct.Códigos de formatação do comando scanf() CÓDIGO printf() %c %d ou %i %e %f %g %o %s %u %x %l %% Exemplo 7. printf(“Digite um caractere e veja-o em decimal.&a). Sintaxe: scanf(“expressão_de_controle”.a). Sua sintaxe é similar à de printf(). o caractere * colocado após o % que avisa à função que deve ser lido um valor do tipo indicado pela especificação. mas não deve ser atribuído a nenhuma variável (não deve ter parâmetros na lista de argumentos para estas especificações).a.a.6 .h. Para enviar o endereço de cada argumento utiliza-se o operador &. uma expressão de controles seguida por uma lista de argumentos separados por vírgulas. exceto getch() e getche() que encontram-se seus protótipos em conio. ”).h. } Execução (faça você mesmo): FORMATO Lê um único caractere simples Lê um inteiro decimal Lê um número em notação científica Lê um número em ponto flutuante Lê um número em ponto flutuante Lê um número em octal Lê um número em cadeia de Caracteres Lê um decimal sem sinal Lê um hexadecimal Lê um inteiro longo Busca por um conjunto de caracteres 30/105 . Além disso. precedidos por um sinal %. isto é. Tais funções encontram-se no arquivo stdio. Tabela 7.1 Função scanf() Esta função serve para ler dados formatados da entrada padrão (teclado).. getchar() e putchar().7 main() { char a. e %x hex. A principal diferença é que os argumentos de scanf() devem ser endereços de variáveis. 7.LINGUAGEM C 7. \n”. \n”). Algumas funções de E/S Neste capítulo será visto algumas funções como scanf().a. getche(). scanf(“%c”. printf(“\n%c=%d dec. getch().

printf(“\n A tecla pressionada eh %c. Além disso.”. } Execução: Digite algum caractere: A tecla pressionada eh a. Exemplo 7. A função getchar() devolve um inteiro. putchar(ch).4 main() { char ch.3 Lendo e escrevendo caracteres A função getchar() lê um caractere do teclado (este comando necessita o pressionamento da tecla <ENTER> após o caractere).2 main() { char ch. printf(“\n A tecla pressionada eh ”). A função putchar() devolve o caractere escrito. int putchar(int c). ch). 7.h e geralmente é igual a -1). e putchar() escreve um caracter na tela. } Execução: Digite algum caractere: a A tecla pressionada eh a. Esta função não aceita argumentos e devolve o caracter lido para a função que a chamou. A função getch() lê um caractere do teclado sem pressionar <ENTER> e não mostra o que foi digitado. printf(“Digite algum caractere:”). Exemplo 7. A função putchar() escreve seu argumento caractere na tela a partir da posição atual do cursor. ou EOF (definida em stdio. Os protótipos para getchar() e putchar() são mostrados aqui: int getchar(void). } 31/105 . printf(“\n A tecla pressionada eh %c. printf(“Digite algum caractere:”).”. ch=getchar(). mas o byte de baixa ordem contém o caractere. ch). pode-se chamar putchar() com um argumento caractere. ch=getch(). A função getchar() espera até que uma tecla seja pressionada (a qual é mostrada na tela) e devolve o seu valor. A função putchar() não acrescenta um \n a saída.LINGUAGEM C 7. Exemplo 7. printf(“Digite algum caractere:”).3 main() { char ch. se ocorreu algum erro. Esta função não aceita argumentos e devolve o caracter lido para a função que a chamou. ch=getche().2 Função getche() e getch() A função getche() lê um caractere do teclado sem pressionar <ENTER> e mostra o que foi digitado.

Escreva um programa onde o usuário entra com um número qualquer e o programa responda se o número e par ou impar .LINGUAGEM C 7. Escreva um programa que leia 2 números e mostre qual é o maior. Escreva um programa que leia 3 números e mostre a sua média.4 Exercícios 1. −b ± ∆ .o produto a soma e a subtração entre eles. Faça um programa que leia dois números e em seguida mostre . Faça um programa que leia 3 variáveis a. 4. 2. coeficientes de uma equação do 2º grau e escreva as duas raízes da equação. b e c. x= 32/105 . Se for par emite a mensagem “ O número é par ” ou caso contrário “O número é impar ”. 3. onde ∆ = b 2 − 4ac 2a 5.

8. Sintaxe: 33/105 .LINGUAGEM C 8. &tentativa).2 Comando switch C tem um comando interno de seleção múltipla.8 if (x != 0) x = 0.h” #include “stdlib.1 Sintaxe: Comando if if (<expressão>) <comando>.10 /* Programa para adivinhar um numero */ #include “stdio. 8.2. o else pertenceria ao mesmo e não ao mais externo. Exemplo 8. Obs. num = rand(). } Lembre-se que para montar um bloco de comando é somente necessário usar o abre e fecha chaves para marcar início e fim de bloco de comandos respectivamente. tentativa. um bloco de comandos ou nada (no caso de comandos vazios). que testa sucessivamente o valor de uma expressão contra uma lista de constantes inteiras ou de caractere.h” void main() { int num. Onde comando pode ser um único comando. A cláusula else é opcional. else <comando>.9 if (a > 5) { if (a < 10) b = 3. Comandos Condicionais Neste capítulo serão vistos os comandos condicionais da linguagem C. if (tentativa == num) printf(“* * * CERTO * * *”). /*gera numero aleatorio entre 0 e 32767*/ scanf(“%d”. se o comando if mais interno não fosse separado por chaves. Exemplo 8. Exemplo 8.: Caso haja um else ele pertence ao if mais próximo. No exemplo 8. } else b = 7. switch.

break. case ‘3’: printf (“\n Você escolheu a opcao 3”). Escreva um programa que leia 3 números e os escreve em ordem crescente. • acutângulo. printf(“1. opcao=getchar(). 4. break. case ‘2’: printf (“\n Você escolheu a opcao 2”). } } 8. case <valor2> : <seqüência de comandos> break.4 #include <stdio. 3. printf(“2. verifique se é positivo ou negativo e escreva uma mensagem apropriada. Faça um programa contendo um menu com as seguintes opções : S .sair 34/105 . • calcular os lados do triângulo.LINGUAGEM C switch (<expressão>) { case <valor1> : <seqüência de comandos> break. isósceles ou escaleno. Opcao 3 \n”). break. que definam 3 pontos e: • Verificar se eles formam um triângulo : não podem estar alinhados e não podem haver pontos sobrepostos. Escrever um programa que leia 3 pares de cordenadas (x.subtração D . default: printf (“\n Nenhuma opcao selecionada”). Quando uma coincidência for encontrada. obtusângulo ou retângulo 2. Faça um programa que leia um número inteiro. a seqüência de comandos associada àquele case será executada até que o comando break ou o fim do comando switch seja alcançado. … default: <seqüência de comandos> } O valor da expressão é testado. contra os valores das constantes especificadas nos comandos case. break. • classificar o tipo do triângulo: • eqüilátero. O comando default (opcional) é executado no momento em que não coincidir nenhum valor. Opcao 1 \n”).y). printf(“3. printf(“Opcao:”).h> void main() { char opcao. Opcao 2 \n”). na ordem. switch(opcao) { case ‘1’: printf (“\nVocê escolheu a opcao 1”).soma P .produto U .divisão Q .3 Exercícios 1. Exemplo 8.

subtração etc . 35/105 .LINGUAGEM C O programa deve conter uma função para executar cada tarefa pedida: soma . Quando o usuário teclar ESC o programa deve terminar.

Depois é testada a condição (expressão relacional) de controle do laço.incremento) comando. Exemplo 9. Onde comando é um comando vazio. Sintaxe: for(inicialização. for(x=1. printf(“Foram lidos %d caracteres”.2 Laço while Comando de repetição condicional. x<=100. Então este programa imprime na tela os números de 1 a 100.LINGUAGEM C 9.h” main() { int x. condição. Sintaxe: while(condição) comando. } 36/105 .1 Comandos Repititivos ou Laços Laço for Comando de repetição condicional com inicialização e incremento. O incremento é executado após a execução do comando ou bloco de comandos. x++) printf(“%d”.12 #include “stdio. Onde comando é um comando vazio. uma comando simples. O fim do laço é determinado pelo valor falso que a condição se apresenta. } No programa acima x é inicializado com 1.cont). Uma vez que x é menor que 100. Primeiro é testada a condição (expressão relacional) de controle do laço.h” main() { int cont=0. o laço termina. ou um bloco de comandos. Esse processo se repete até que x fique maior que 100. 9.11 #include “stdio. O fim do laço é determinado pelo valor falso que a condição se apresenta. E a cada execução de comando é repetido o teste de condição. 9.x). ou um bloco de comandos. um comando simples. nesse ponto. printf() é executado e x é incrementado em 1 e testado para ver se ainda é menor ou igual a 100. Primeiro é executado a inicialização que consiste em atribuições iniciais. char ch. Exemplo 9. while((c=getchar()) != ‘0’) cont++.

printf(“2. printf(“Opcao:”). 37/105 . printf(“3. continue e exit() O comando break pode ser usado no corpo de qualquer estrutura de laço C. printf(“1. break. }} while (opcao != ‘1’ && opcao != ‘2’ && opcao != ‘3’). o laço dowhile verifica a condição ao final do laço. Sintaxe: void exit(int código_de_retorno). break. Opcao 2 \n”).LINGUAGEM C 9. pode-se sair de um programa usando a função exit() da biblioteca padrão. Causa a saída imediata do laço e o controle passa para o próximo comando do programa. break. Essa função provoca uma terminação imediata do programa inteiro. forçando um retorno ao sistema operacional. do { opcao=getchar(). Exemplo 9. que testam a condição do laço no começo. break. Nos laços 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 laço. printf (“\n Nenhuma opcao selecionada”). switch(opcao) { case ‘1’: printf (“\nVocê escolheu a opcao 1”).h> void main() { char opcao.3 Laço do-while Ao contrário dos comandos for e while. } default: 9. Sintaxe: continue. case ‘3’: printf (“\n Você escolheu a opcao 3”). Sintaxe: break. Opcao 1 \n”). Sintaxe: do <comando> while(condição). case ‘2’: printf (“\n Você escolheu a opcao 2”). Da mesma forma que pode-se sair de um laço.4 Comandos break. O comando continue força a próxima iteração do laço e pula o código que estivar abaixo. Opcao 3 \n”).2 #include <stdio.

Abandonar \n”). Faça um programa que calcule para um dado N o número de iterações até se chegar ao primeiro 1 . e mostre a soma e média dos respectivos números ao ser lido um valor negativo. Escreva um programa para calcular o fatorial de um número lido. printf(“3. Escrever um programa que mostre os números primos entre 1 e 100. printf(“1. 6.h> void main() { char opcao. Faça um programa que leia um número (inteiro) e escreva todos os seus divisores. 7. break. Opcao 2 \n”). do { opcao=getchar(). Escreva um programa para ler um caracter de comparação e vários caracteres de entrada finalizados por ‘0’ e contar o número de vezes que o caracter de comparação apareceu. Suponha um número N qualquer: se N é par então N agora é N / 2. 2. O programa deve contabilizar a partir das notas de 100. 3. case ‘2’: printf (“\n Você escolheu a opcao 2”). Faça um programa que receba como entrada uma quantia em dinheiro e mostre na tela a quantidade de notas de 5.3 #include <stdio. break.LINGUAGEM C O valor de código_de_retorno é retornado ao processo chamador (sistema operacional). Assim para N = 3 calculamos a seguinte tabela : 3  10 42 10  5 21 5  16 14 16  8 42 8 4 21 Observe que a partir de sete iterações a seqüência 4 2 1 começa a se repetir . break. } 9. 10. Exemplo 9. 4. case ‘3’: printf (“\n Você escolheu a opcao 3”). printf(“Opcao:”). 50 e 100 são necessárias para representar o valor. printf(“4. printf(“2. 38/105 . O zero é geralmente usado como um código de retorno que indica uma terminação normal do programa. Faça um programa que leia um número de no máximo 3 dígitos e escreva-o na tela. /* retorna ao SO */ }} while (opcao != ‘1’ && opcao != ‘2’ && opcao != ‘3’). 5. switch(opcao) { case ‘1’: printf (“\nVocê escolheu a opcao 1”).5 Exercícios 1. case ‘4’: exit(0). se N é ímpar N agora é 3*N + 1. 8. Opcao 1 \n”). Opcao 3 \n”). Escreva um programa que leia um número não determinado de valores positivos.

c onde a é maior que 1 . Faça um programa onde o usuário entra com dois números A e B o programa devolve como resultado A elevado a B .b. 13. Faça um programa que imprima um elemento da seqüência de Fibonacci . numero de termos e razão 10. Escreva um programa que solicite ao usuário três números inteiros a. 39/105 . 12. Faça um programa que imprima os elementos de uma PA e o somatório da mesma dados : primeiro termo .LINGUAGEM C 9. Faça um programa onde o usuário entra com um número decimal e o mesmo calcula e imprime o número no sistema binário . dado o numero do elemento. 11. Seu programa deve somar todos os inteiros entre b e c divisíveis por a .

n>0. { . os argumentos foram passados por valor e a função retorna um valor do tipo inteiro. for(p=1.14 int pot(x.b) int *a.n--) p *= x. { int p.2. } As funções retornam um valor (do tipo indicado em tipo_função). } Exemplo 10. O valor retornado pela função é dado pelo comando return (o valor retornado pode ou não ser utilizado).15 void troca(a. /* troca os valores das variáveis */ /* usa-se ponteiros para referenciar */ /* o conteúdo do endereço da variável */ 40/105 .. return p.3. aux = *a. int y) { .y. { int aux. *a = *b.. Funções A forma geral de uma função é: Sintaxe: tipo_função nome_função (lista_de_parâmetros) declaração_parâmetros { corpo_função.2). *b.13 int soma(int x. necessitando de uma passagem de parâmetros por referência. } /* x elevado na n potência */ No exemplo 11. A segunda é realizada através de apontadores.LINGUAGEM C 10. } ou int soma(x. No exemplo 11. Exemplo 10.n) int x. nenhum valor é retornado (por isso usa-se o tipo void) mas é realizado uma troca dos valores das variáveis. y) int x. Exemplo 10. A chamada seria: a = pot(10.. Existem dois tipos de passagem de argumentos: por valor e por referência.n..

// chamada da função printf(”\nA media destes números e´ %f”. . float b){ float med. } // função void main(){ // programa principal float num_1. med = (a + b) / 2. 10. Quando o argumento for uma matriz automaticamente será passado o endereço da matriz para a função. med). num_2).1 Corpo da função antes do programa principal (no mesmo arquivo) Quando escrevemos a definição de uma função antes do programa principal e no mesmo arquivo deste. med.&y).. nenhuma outra instrução é necessária.). seu tipo de retorno e a quantidade e o tipo dos argumentos da função. scanf(”%f %f”.y=2. num_2. O protótipo de uma função indica ao compilador quais são as funções usadas no programa principal os tipo. &num_2). A linguagem C aceita chamadas recursivas de funções.LINGUAGEM C *b = aux. // programa principal // protótipo da função 41/105 ..1.4 float media2(float a.. Um protótipo é uma instrução que define o nome da função.0.1 Localização das funções Existem basicamente duas posições possíveis para escrevermos o corpo de uma função: ou antes ou depois do programa principal. troca(&x. &num_1. } A chamada para esta função seria: int x=1. Na passagem de parâmetros por referência é passado explicitamente o endereço da variável com o uso do operador &. } 10. return(med). med = media2(num_1.2 Corpo da função depois do programa principal (no mesmo arquivo) Quando escrevemos a definição de uma função depois do programa principal e no mesmo arquivo deste. A sintaxe geral para isto é a seguinte: Sintaxe: void main(){ tipo nomef(.. puts(”Digite dois números:”). 10. devemos incluir um protótipo da função chamada. Podemos ainda escrever uma função no mesmo arquivo do programa principal ou em arquivo separado.1. Exemplo 10.

med.0.. Quando escrevemos a definição de uma função em arquivo separado do programa principal devemos incluir este arquivo no conjunto de arquivos de compilação do programa principal. num_2). Esta inclusão é feita com a diretiva #include...){ [corpo de função] } Exemplo 10. var = nomef(. Esta facilidade permite a criação de bibliotecas de usuário: um conjunto de arquivos contendo funções escritas pelo usuário.4. } Observe que o protótipo de uma função nada mais é que a declaração da função sem o seu corpo. é permitido que o usuário crie uma função em um arquivo e um programa que a chame em outro arquivo distinto.7. // protótipo de media2() float num_1.h” void main(){ // inclusão da função // programa principal 42/105 . Esta possibilidade é uma grande vantagem utilizada em larga escala por programadores profissionais.. } tipo nomef(. med = media2(num_1.1. } float media2(float a.. return(med). // chamada a função printf(”\nA media destes números e´ %f”.1. med). Esta diretiva.float). indicamos entre aspas duplas o caminho de localização do arquivo onde está definida a função chamada. instrui o compilador para incluir na compilação do programa outros arquivos que contem a definição das funções de usuário e de biblioteca..) . // definição da função // chamada a função 10. puts(”Digite dois números:”). num_2. como em muitas outras linguagens. &num_2)....LINGUAGEM C var = nomef(.2 e 3. &num_1.. float b){ // função media2() float med. Observe ainda que na lista de argumentos do protótipo podem ser escritos apenas os tipos dos argumentos..6 #include ”c:\tc\userbib\stat. } // inclusão da função // programa principal // chamada a função Na diretiva #include.3 Corpo da função escrito em arquivo separado Em C.) . scanf(”%f %f”. Exemplo 10. Sintaxe: #include ”path” void main(){ .5 void main(){ // programa principal float media2(float. med = (a + b) / 2. vista nas seções 2..

med). puts(”Digite dois números:”). } O primeiro argumento (argv[0]) é o nome do programa.4 Retorno de Ponteiros Ponteiros para variáveis não são variáveis e tampouco inteiros sem sinal.argc -1). argv: vetor de argumentos (vetor de apontadores para strings). argv[cont]). &num_2). char *argv[]) { int cont. med. char *argv[]) É importante lembrar que Exemplo 10. 10. int pot(int x. num_2). Existem três tipos de declaração de protótipos: Sintaxe tipo_função nome_função(). São endereço na memória de um certo tipo de dado. É verificado número de parâmetros. } 10. compatibilidade de tipos.LINGUAGEM C float num_1. num_2. A forma geral é: Sintaxe: 43/105 . Sintaxe: main(int argc.cont++) printf(“Argumento %d: %s \n”. Os dois argumentos são: argc: contador de argumentos.cont < argc. &num_1. Protótipos de funções ajudam a detectar erros antes que eles ocorram.3 Protótipo de funções O padrão ANSI C expandiu a declaração tradicional de função. med = media2(num_1. permitindo que a quantidade e os tipos dos argumentos das funções sejam declarados.7 #include “stdio. tipo_função nome_função(lista_tipo_nome_argumentos). for (cont=1. printf(“Foram encontrados %d argumentos \n”. Protótipos permitem que C forneça uma verificação mais forte dos tipos. tipo_função nome_função(lista_tipo_argumentos). Protótipos de funções não faziam parte da linguagem C original. 10. int pot(int. cont. A definição expandida é chamada protótipo de função.int). // chamada a função printf(”\nA media destes números e´ %f”.2 Argumentos para função main() A função main() aceita argumentos para a passagem de parâmetros realizada através da chamada do programa. scanf(”%f %f”. entre outras.h” void main(int argc. int y). Exemplo int pot().

deve ser feita uma chamada à va_end() para garantir que a pilha seja corretamente restaurada. 10.). func(int a. isso está incorreto: func(.5. Finalmente. Para poder utilizar esta característica tem-se que utilizar as funções descritas na próxima seção. last_parm).. utiliza-se sum_series() para devolver a soma de uma série de números. } 44/105 . O tipo va_list é definido em STDARG. type va_start(va_list argptr. 0.125..0625.. va_start() e va_end(). essa declaração especifica que func() terá ao menos dois parâmetros inteiros e um número desconhecido (incluindo 0) de parâmetros após eles. Sintaxe: void va_arg(va_list argptr. O exemplo mais comum é printf(). type). sum_series(). com type sendo o tipo do próximo parâmetro. . Por exemplo. é last_parm. parâmetros são devolvidos via chamadas à va_arg().03125). 0.d).H: va_arq().. O parâmetro conhecido.h” #include “stdarg. o argumento ponteiro argptr deve ser inicializado através de uma chamada à va_start().H. deve-se terminar a declaração dos seus parâmetros usando três pontos. Por exemplo.h” double sum_series(int num.. podendo. após todos os parâmetros terem sido lidos e antes de retornar a função.LINGUAGEM C tipo_função *nome_função(lista_de_argumentos).1 Funções para número variável de argumentos Para este tipo de aplicação é necessário o uso de três macros definidas em STDARG. porém. void va_end(va_list argptr). 0..5. Se va_end() não for chamada. int b. mais à direita.). #include “stdio. printf(“soma da serie: %f \n”. pode-se especificar uma função que possui a quantidade e os tipos de parâmetros variáveis. ter mais anterior à lista variável de parâmetros. Antes que qualquer dos parâmetros de comprimento variável possa ser acessado. d = sum_series(5. 10. O primeiro argumento contém o número de argumentos que se sucedem. 0. Qualquer função que usa um número variável de argumentos deve ter pelo menos um argumento verdadeiro.). . Para informar ao compilador que um número desconhecido de parâmetros será passado para uma função. void main() { double d. 0. O procedimento geral para criar uma função que pode receber um número variável de argumentos é o seguinte: a função deve ter pelo menos um parâmetro conhecido. é muito provável que ocorra um crash do programa. No exemplo abaixo. Em seguida. Essa forma de declaração também é usada por um protótipo de função.25.5 Números de parâmetros variável Em C.

Exemplo 10. As variáveis declaradas dentro de uma função são automáticas por padrão. o compilador acusará um erro de duplicidade de variável.auto As variáveis declaradas nos exemplos anteriores só podem ser acessadas somente às funções onde estão declaradas. O código main() { auto int x.. char ch.. /* finaliza a lista de argumentos */ return sum. A classe de variáveis automáticas pode ser explicitada usando-se a palavra auto.num--) /* soma a serie */ { t = va_arg(argptr.0. Como pode-se somente uma única vez declarar uma variável global. t.1 Classe de Armazenamento . /* inicializa argptr */ for (.. } é equivalente a 10.8 Arquivo 1 int x.2 Classe de Armazenamento .num). va_start(argptr. } main() { int x.. sum += t. } func1() { x = 123.double). por exemplo) deve-se utilizar a declaração extern nos outros arquivos onde a variável é utilizada. ao usar diversos arquivos para um mesmo programa (por ser grande. Tais variáveis são chamadas locais ou automáticas. main() { . va_list argptr. .extern Toda variável declarada fora de qualquer função têm a classe de armazenamento extern..y.6 Classes de Armazenamento São quatro as classes de armazenamento de variáveis C: • • • • auto extern static register (automáticas) (externas) (estáticas) (em registradores) 10.) { double sum=0. são criadas quando a função é chamada e destruídas quando a função ou o bloco de código termina a sua execução. .. 45/105 . } va_end(argptr).. Se não proceder assim. . } 10.6..6.LINGUAGEM C double sum_series(int num.num.

14159 Só pode ser escrito um comando destes por linha. Ao contrário das variáveis globais. No caso do IBM-PC pode ser colocado o tipo int e char associado a register pois o registrador tem apenas 16 bits. variáveis static são variáveis permanentes. elas não são reconhecidas fora de sua função ou arquivo.6. 10.14159. 10.LINGUAGEM C } } Arquivo 2 x = y / 10.6. Por exemplo. e não há ponto-e-vírgula após qualquer diretiva do pré-processador. } 10. O especificador static tem efeitos diferentes em variáveis locais e em variáveis globais. 10. variáveis register são usadas para aumentar a velocidade de processamento.3. chamada registrador. func23() { y = 10. variáveis de uso freqüente como variáveis de laços e argumentos de funções. Em termos simples. Por exemplo. extern char ch. Basicamente.static Dentro de sua própria função ou arquivo. #define PI 3. mas mantêm seus valores entre chamadas.2 Variáveis Globais static Quando o modificador static é aplicado a uma variável global. uma variável local static é uma variável local que retém seu valor entre chamadas.6.y. O especificador extern diz ao compilador que os tipos de variável e nomes que o seguem foram declarados em outro lugar.3 Classe de Armazenamento . Isto é.4 Classe de Armazenamento . Mas ela só é reconhecida apenas no bloco em que está declarada. o compilador cria armazenamento permanente para ela quase da mesma forma como cria armazenamento para uma variável global. extern int x.register A classe de armazenamento register indica que a variável associada deve ser guardada fisicamente numa memória de acesso muito mais rápido.7 Diretiva #define A diretiva #define pode ser usada para definir constantes simbólicas com nomes apropriados. func22() { No arquivo 2. o compilador cria uma variável que é reconhecida apenas no arquivo na qual a mesma foi declarada.1 Variáveis Locais static Quando o modificador static é aplicado a uma variável local. a lista de variáveis globais foi copiada do arquivo 1 e o especificador extern foi adicionado às declarações.3. 46/105 . a constante PI pode ser definida com o valor 3. 10.6. o compilador não reserva um espaço de memória para essas variáveis declaradas com o especificador extern na certeza de estarem declaradas em outro módulo.

Escreva uma função que receba um caracter como argumento e que retorne a letra maiúscula se a mesma for minúscula.h> #include <conio. Usa recursao #include <stdio. getch(). } void inverte ( ) { char ch . 4.9 // imprime uma frase invertida . A função que transforma uma string em um float é atof(char *x). uma função e´ recursiva quando dentro dela está presente uma instrução de chamada a ela própria. 3. funções: islower(int ch). toupper(int ch). 10.9 Exercícios 1. if ((ch=getche( )) != ‘\r’ ) inverte( ). Não deve haver espaços entre o nome da macro e seus identificadores. #define AREA(x) (4*PI*x*x) A declaração acima define a função AREA() a qual calcula a área de uma esfera. Escreva um programa que receba como parâmetro um índice (float). inverte( ). Isto é. Após. Exemplo 10. Escreva uma função que calcule o fatorial de forma recursiva. Implementar as seguintes funções:  strlen()  strcat()  strcpy() 47/105 .ch) } 10. A vantagem desta declaração é não tipagem do argumento x. scanf(“%c”.h> void inverte( ) void main( ) { clrscr( ). 2. ler uma sequência de números (a qual termina por 0) e exibir o seu valor multiplicado pelo índice.8 Funções Recursivas Uma função é dita recursiva quando se é definida dentro dela mesma.LINGUAGEM C Esta diretiva é usada para definir macros com argumentos.

}. { 0. O que diferencia a declaração de uma matriz ou vetor da declaração de qualquer variável é a parte que segue o nome. 1. Exemplo 11. como quaisquer outras variáveis. 1. 1. { 1.: Quando houver uma inicialização de um vetor ou uma matriz na declaração. isto é. isto é. para três dimensões assim int notas[5][5][5]. }. 0. 0. }. Os elementos do vetor ou da matriz são sempre enumerados por índices iniciados por 0 (zero).5.10. 1. pelo número de argumentos ele assume o número do primeiro colchete. 0. Para a declaração de mais de uma dimensão em C é necessário o número de par de colchetes ser igual ao número de dimensões.20} int MAT[5][6]={ { 1. 0. 1. Em C. { 0. Exemplo 11. 0. 1.LINGUAGEM C 11. A declaração acima aloca um intervalo de memória com nome notas para armazenar 5 elementos do tipo int. } Obs. para que o compilador conheça o tipo do vetor ou da matriz e reserve espaço de memória suficiente para armazená-lo.i). 1. Por definição um vetor ou matriz é composto por elementos de um único tipo. estas estruturas precisam ser declaradas. os pares de colchetes ([ e ]) que envolvam um número inteiro. 0.: A linguagem C não realiza verificação de limites em matrizes!!! 11. que declara uma matriz tridimensional e assim por diante. 1. Obs. também é permitido a inicialização de vetores e matrizes. O limite de índices é definido pelo compilador ou pela memória. scanf(“%d”.1 Inicialização de Vetores e Matrizes Como o C permite a inicialização de variáveis básicas. 1.15. 0.i<5. 0 1 0 1 0 }. que declara uma matriz bi-dimensional. &notas[i]). que indica ao compilador o tamanho da matriz. Isto é. se a matriz for de duas dimensões teremos uma declaração assim: int notas[5][5]. 1. 48/105 . int notas[5].2 int TAB[5]={1. 0.i++) { printf(“Digite a nota do aluno %d:”. { 1. 0. pode-se suprimir sempre o valor do primeiro colchete. } }.16 for (i=0. Vetores e Matrizes Vetores e matrizes são estruturas de dados usada para representar uma certa quantidade de variáveis de valores homogêneos. 0.

0..3 Limites Na linguagem C. 0. Embora na sua declaração. 0.20} int MAT[][6]={ { { { { { 1. 1. de modo que vet[0] será localizado no segmento base. 0. Porém. 11. O nome de uma matriz ou vetor desacompanhado de colchetes é equivalente ao endereço da matriz ou do vetor... estamos reservando 6 bytes (3 segmentos de 2 bytes) de memória para armazenar os seus elementos. 1. 0. passagem por referência. 0 1 0 1 0 }. o C não faz nenhum teste de verificação de acesso a um elemento dentro do vetor ou não. O primeiro segmento será reservado para vet[0]. A princípio este fato poderia parecer um defeito da linguagem. Porém. 0. 1. isto é. passagem por valor. 0. Observe que acessar um segmento fora do espaço destinado a um vetor pode destruir informações reservadas de outras variáveis. tenhamos definido o tamanho de um vetor. . }.2 Matrizes e Vetores como argumento de Funções O C permite que passe matrizes ou vetores como argumento de uma função. 1. 1.5.LINGUAGEM C Exemplo 11. A memória do microcomputador é um espaço (físico) particionado em porções de 1 byte. }. Se i for igual a 2. Estes erros são difíceis de detectar pois o compilador não gera nenhuma mensagem de erro. 1. 11. 1. Poder manipular sem restrições todos os segmentos de memória é uma flexibilidade apreciada pelos programadores. estamos a acessando segmento base+7 que não foi reservado para os elementos do vetor e que provavelmente está sendo usado por uma outra variável ou contém informação espúria (lixo). mas na verdade trata-se de um recurso muito poderoso do C.10. Este fato se deve a maneira como o C trata vetores. estamos acessando o segmento base+2 ou vet[2](o ultimo segmento reservado para o vetor). o C não acusa erro se usarmos valor[12] em algum lugar do programa.15. se i for igual a 7. 1. Mas há uma peculiaridade na passagem de parâmetros: a forma como ela é passada. A solução mais adequada é sempre avaliar os limites de um vetor antes de manipulá-lo. 0. o segundo segmento para vet[1] e o terceiro segmento para vet[2]. 0. 1. Estes testes de limite devem ser feitos logicamente dentro do programa. 49/105 . O segmento inicial é chamado de segmento base.. } }. teoricamente só tem sentido usarmos os elementos valor[0]. 1. 0. valor[4]. devemos ter cuidado com os limites de um vetor.. Por exemplo se declaramos um vetor como int valor[5]. }. Se declaramos um vetor como int vet[3]. Quando acessamos o elemento vet[i]. Quando o nome estiver acompanhado de um indexador é passado como argumento o conteúdo daquela posição da matriz ou do vetor. o processador acessa o segmento localizado em base+i. 1. 0. isto é.3 int TAB[]={1. 0. 1.

LINGUAGEM C 11. O que vier após o espaço em branco é eliminado. “Andre”.1 Função scanf() A função scanf() é bastante limitada para a leitura de strings. as string são implementadas como cadeia de caracteres. Como em qualquer vetor. char nomes[][8]={“Eduardo”. str[1] = ‘/0’.’r’.’a’. Exemplo 11.’\0’}. pois o décimo-quinto byte é para o caracter null. 11. printf(“Digite seu nome:”). reserva um espaço de memória para uma string de tamanho 14. Exemplo 11. } Execução 50/105 . como mostram o exemplo 10. Pois não pode haver espaços em branco na string lida.4. /* Caracter NULL para finalizar string */ Como todo vetor as strings podem ser inicializadas. A declaração: char nome[15].4 Strings Em C não existe um tipo de dados string como na linguagem "Pascal". “Adriana”. “Carla”. os caracteres da string podem ser individualmente acessados. char nome[]=“Carlos”.6 #include <stdio.5 char nome[]={‘C’.’s’.nome).4.h> main() { char nome[15]. Ao contrário.’l’.1. “Jose”}. str[0] = ‘U’. A manipulação de strings pode ser feita através de funções ou elemento a elemento como se fosse um vetor. terminados pelo caracter null (‘\0’).1 Leitura de Strings Para ler uma string pode-se utilizar a função scanf() ou a função gets() da biblioteca C para receber a string. O caracter null serve como uma marca de fim de string para as funções que lidam com strings.4 char str[2]. 11. scanf(“%s”.’o’.5: Exemplo 11.&nome). printf(“Saudacoes %s”.

Carlos Alberto 11.2.2 Função puts() A função puts() é o complementa de gets(). printf(“Digite seu nome:”). gets(nome). Visto que uma string não tem um tamanho pré-determinado.LINGUAGEM C Digite seu nome: Carlos Alberto Saudacoes. Carlos 11. 51/105 .7 #include <stdio.4. Em compensação é uma função que pode ser usada para impressão de mais que uma string por linha. puts(“Saudacoes.h> main() { char nome[81]. O seu propósito é unicamente imprimir a string apontada pelo seu argumento.4. } Execução Digite seu nome: Carlos Alberto Saudacoes. Caracteres brancos como espaços e tabulações são aceitáveis como parte da string.nome).2 Função gets() A função gets() é bastante conveniente para a leitura de strings. 11.1 Função printf() A função printf() ao imprimir a string não realiza uma nova linha.2 Escrita de Strings Para escrever uma string pode-se utilizar a função printf() ou a função puts() da biblioteca C. Exemplo 11. 11. /* mostra o uso de putc() */ #include <stdio.1. O endereço desta string deve ser mandado para puts() como argumento. gets(nome). O próximo exemplo ilustra algumas das muitas possibilidades de seu uso. O seu propósito é unicamente ler uma string da sua entrada padrão que por default é o teclado.2.h> main() { char nome[15]. gets() lê caracteres até encontrar o de nova linha (‘\n’) que é gerado ao pressionar a tecla [Enter].4. ”). como é definido na sua implementação. Todos os caracteres anteriores ao ‘\n’ são armazenados na string e é então incluído o caractere ‘\0’.4. printf(“Saudacoes %s”. puts(“Digite seu nome:”).

3. 11. Sintaxe: char *strcat(char *str1. Como não existe verificação de limites. 11. O nulo não é size_t strlen(char *str).4. os operadores usuais não podem ser aplicados sobre este tipo de dado. “ mundo”)).strcat(“ola”. é de inteira responsabilidade do usuário que o tamanho de str1 seja suficientemente grande para armazenar seu conteúdo original e o de str2.strlen(“ola”)).3 Funções de Manipulação de Strings Como strings são implementadas como vetores.2 Função strcat() Concatena uma cópia de str2 em str1 e termina str1 com um nulo.LINGUAGEM C puts(nome). ele acaba com um caracter de nova linha.H. Carlos Alberto puts() pula de linha sozinha los Alberto A função puts() reconhece ‘/0’como fim de string.nome). Utilizando a função printf() o mesmo efeito seria: printf(“%s\n”. } Execução Digite seu nome: Carlos Alberto Saudacoes. Exemplo 11. Exemplo 11. As funções descritas nas próximas seções utilizam o cabeçalho padrão STRING. /* O resultado é ola mundo */ 52/105 . Por exemplo: comparação atribuição não são suportados por este tipo de dado.9 printf(“%s”. puts(“puts() pula de linha sozinha”). /* O resultado é 3 */ 11.8 printf(“%d”. puts(nome). Cada impressão de puts().1 contado.4. puts(&nome[4]).3.4. Sintaxe: Função strlen() Devolve o comprimento da string terminada por um nulo apontada por str. const char *str2).

6 Função strstr() Devolve um ponteiro à primeira ocorrência da string apontada por str2 na string apontada por str1. Sintaxe: char *strstr(const char *str1.3.11 #include “stdio.3 Função 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. Sintaxe: char *strcpy(char *str1. 11.3. Exemplo 11.h” void main() 53/105 . strcpy(str. Sintaxe: char *strchr(const char *str. int ch). const char *str2).3. 11. Se não for encontrada nenhuma coincidência. será devolvido um ponteiro nulo.5 Função strchr() Devolve um ponteiro à primeira ocorrência do byte menos significativo de ch na string apontada por str. será devolvido um ponteiro nulo.4 Exemplo Geral O programa abaixo exemplifica o uso das funções descritas anteriormente.4.LINGUAGEM C 11.4. str2 deve ser um ponteiro para uma string terminada com um nulo.4.4 Função strcpy() Copia o conteúdo de str2 em str1.h” #include “string.4. 11.10 char str[80]. Se não for encontrada nenhuma coincidência. A função strcpy() devolve um ponteiro para str1. const char *str2). Exemplo 11. /* copia mundo na string str */ 11.4. const char *str2).3. “mundo”).

3.  ao final os números que possuem 0 no vetor são primos. 2. strlen(s1). “ola”)) printf(“ola encontrado”). 6. Faça um programa que leia uma matriz M[10][10] e some todos os elementos abaixo da diagonal principal. strlen(s2)). Escreva um programa cuja execução se segue abaixo : 54/105 . gets(s2). printf(“%s\n”. if (!strcmp(s1. 7.s2)) printf(“As strings sao iguais\n”).’o’)) printf(“o esta em alo \n”). if (strstr(“ola aqui”. Faça um programa que leia 10 valores inteiros. gets(s1). 4. Escreva um programa que leia um vetor de 100 posições e mostre-o em ordem crescente e decrescente. 8. Faça um programa que leia uma matriz M[4][4] e mostra a sua transposta. s2[80].5 1. Exercícios Faça um programa que leia 10 valores inteiros e escreva-os na ordem inversa a que foram lidos. printf(“comprimento: %d %d \n”. Termina com o caracter ´0´. 9. a saída será comprimentos: 3 3 As strings são iguais aloalo Isso e um teste o esta em alo ola encontrado 11. if (strchr(“alo”.s1). } Ao rodar este programa e entrar com as strings “ola” e “ola”. Calcular os números primos entre 0 e 100 (inclusive) utilizando o crivo de Eritóstenes:  Usar um vetor de 101 inteiros. printf(s1). strcat(s1. Escreva um programa que leia um número indeterminado de caracteres e conta o número de vezes que cada letra (A-Z) aparece:   Desconsiderar se a letra é maiúscula ou minúscula. 5.LINGUAGEM C { char s1[80]. strcpy(s1. calcule sua média e escreva todos os valores que estão abaixo da média.  repetir de 2 a 100  para cada número: somar 1 a todos os contadores dos seus múltiplos.  zerar o vetor. “Isso e um teste \n”). Faça um programa que leia 3 nomes (até 30 letras) e os escreva em ordem alfabética.s2).

55/105 . A função retorna um ponteiro que é a concatenação de s2 com s1 .mat2). char mat2[80]=”grande”. 13. Escreva uma função que realize a multiplicação de matrizes. 12. Exemplo de chamada : char mat1[80]=”casa ” . char * s2) . o 2º com o penúltimo e assim por diante). printf( “%s”. Escreva uma função que receba um vetor e o tamanho do mesmo e troque os elementos (1º com o último. Faça um programa que use a função (definida por você) : char *concat( char *s1 .p). 11.LINGUAGEM C digite uma frase : carlos <enter> digite uma letra dessa frase : r <enter> rlos 10. Escrever a função atoi() (recebe uma string como parâmetro e transforma em um inteiro). p = concat(mat1. char *p.

O endereço de x é mostrado usando o modificador de formato de printf() %p. qualquer tipo ponteiro pode apontar para qualquer lugar.LINGUAGEM C 12. Os operadores utilizados são * e &.6. que faz com que printf() apresente um endereço no formato usado pelo computador hospedeiro. Ponteiros Para uma boa utilização dos ponteiros deve-se compreender corretamente o seu uso.h” void main() { int x. eles são usados para suportar as rotinas de alocação dinâmica de C. Mas. tipo base int. Exemplo 12. Basicamente.1 Atribuição de Ponteiros Como é o caso com qualquer variável. o uso de ponteiros para aumentar a eficiência de certas rotinas. na memória.1 Expressões com Ponteiros Nesta seção serão analisados alguns aspectos especiais de expressões com ponteiros. A forma geral é: tipo *nome. segundo. um "*" e o nome da variável.ponteiros selvagens) podem provocar quebra do sistema. p2 = p1. um ponteiro pode ser usado no lado direito de um comando de atribuição para passar seu valor para um outro ponteiro. um ponteiro é uma variável que contém um endereço de memória. Por definição. */ p1 = &x.*p2. valor */ } /* declaração do ponteiro p1 e p2 com o /* escreve o endereço de x.p2). onde tipo é qualquer tipo válido em C e nome é o nome da variável ponteiro. Esse endereço é normalmente uma posição de uma outra variável na memória. 12. Uma declaração de ponteiros consiste no tipo base. tanto p1 quanto p2 apontam para x. 56/105 . Por ser um dos aspectos mais poderosos da linguagem também são os mais perigosos. Por erros no uso de ponteiros (como a não inicialização de ponteiros . int *p1. Existem três razões para isso: primeiro. printf(“%p”. e terceiro. como já foi explicado na seção 6. não seu Agora.1. O tipo base do ponteiro define que tipo de variáveis o ponteiro pode apontar.17 #include “stdio. 12. ponteiros fornecem os meios pelos quais as funções podem modificar seus argumentos. para a aritmética de ponteiros é feita através do tipo base.

Exemplo 12. char *name) { register int t. entre outros). Os operadores permitidos no caso seriam: +. 57/105 .++t) if(!strcmp(p[t].11. Isto é. /* não encontrado */ } O laço for dentro de search() é executado até que seja encontrada uma coincidência ou um ponteiro nulo. Exemplo 12. ptrf = ptrf . char *ptrc=4000.int. ilustra esse tipo de abordagem. ptri = ptri . ptri++. O incremento é sempre realizado do tamanho básico de armazenamento do tipo base. ptrc = ptrc . Como um ponteiro nulo é assumido como sendo não usado. ptrf++. ptrc++.name)) return t. 12. Por exemplo.2 Aritmética de Ponteiros Existem apenas duas operações aritméticas que podem ser usadas com ponteiros: adição e subtração. no caso de um caracter (char) será de um byte. pode-se utilizar o ponteiro nulo para fazer rotinas fáceis de codificar e mais eficientes. a condição de controle do laço falha quando ele é atingido.1. Lembre-se! Não altera-se o valor de um ponteiro constante (ponteiro para um tipo básico .10.p[t]. float *ptrf=4000. ele contém um valor desconhecido. Como o final da matriz é marcado com um ponteiro nulo. float double.2 Inicialização de Ponteiros Após um ponteiro ser declarado. matrizes. -. somente de um ponteiro variável (ponteiro de estruturas complexas vetores. Ao usar este ponteiro antes de inicializar. Isto é. entre outros). Uma rotina que acessa essa matriz sabe que chegará ao final ao encontrar o valor nulo. strings.10. provavelmente provocará uma falha do programa ou até do sistema operacional. mas antes que lhe seja atribuído um valor.18 int *ptri=3000. nenhuma outra operação aritmética pode ser efetuada com ponteiros.10. não pode multiplicar ou dividir ponteiros. /* /* /* /* /* /* ptri ptrc ptrf ptri ptrc ptrf apontará apontará apontará apontará apontará apontará para para para para para para o o o o o o endereço endereço endereço endereço endereço endereço 3002 4001 5004 2982 3991 4964 */ */ */ */ */ */ Além de adição e subtração entre um ponteiro e um inteiro. o apontador apontará para o próximo inteiro (no caso do inteiro ocupar 2 bytes o incremento será de dois bytes). A função search(). --.19 /* procura um nome */ search(char *p[]. pode-se utilizar um ponteiro nulo para marcar o fim de uma matriz de ponteiros. não pode aplicar os operadores de deslocamento e de mascaramento bit a bit com ponteiros e não pode adicionar ou subtrair o tipo float ou o tipo double a ponteiros. for (t=0. se o tipo base for um inteiro e incrementarmos em uma unidade. retrun -1.LINGUAGEM C 12. mostrada no exemplo 13. ++.

t > -1.12) não é uma matriz. Para acessar a string str pode-se utilizar estes dois mecanismos str[4] ou *(p1 + 4) /* aritmética de ponteiros */ /* indexação de matrizes */ Os dois comandos devolvem o quinto elemento.1. Exemplo 12. t--) printf(“%c”. 58/105 .2 if (p<q) printf(“p aponta para uma memória mais baixa que q /n”).21 #include “stdio. onde é verificado se o ponteiro de início e fim da pilha estão apontando para a mesma posição de memória. Por isso.p[t]). 12. Isto pode ser levado como uma variação no tema de inicialização usado na variável argv. O ponteiro p (exemplo 13.20 char *p= “alo mundo \n”. for (t=strlen(p) . void main() { register int t. p1 = str.2. Geralmente.13). inicializar uma matriz de strings usando ponteiros aloca menos memória que a inicialização através de matriz. Exemplo 12.LINGUAGEM C Uma outra utilização de inicialização de ponteiros é a inicialização de strings. Aritmética de ponteiros pode ser mais rápida que indexação de matrizes. Pois C fornece dois métodos para acessar elementos de matrizes: aritmética de ponteiros e indexação de matrizes.h” #include “string. Exemplo 12. Exemplo disto é a pilha.3 Ponteiros e Matrizes Existe uma estreita relação entre matrizes e ponteiros. Normalmente utiliza-se ponteiros para acessar elementos de matrizes devido a velocidade de acesso. mas como o compilador C cria uma tabela de strings.1 Comparação de Ponteiros É possível comparar dois ponteiros em uma expressão relacional. a utilização de comparação entre ponteiros é quando os mesmos apontam para um objeto comum.3 char str[80]. printf(p).h” char *p=“alo mundo”. significando pilha vazia. 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. } 12. *p1. Exemplo 12.

i<20. i++) scanf(“%d”. ++t) putchar(s[t]).1 Matrizes de Ponteiros Ponteiros podem ser organizados em matrizes como qualquer outro tipo de dado. 59/105 .s[t]. for(i=0. é int *x[10]. de tamanho 10.5 #include “stdlib. Para uma melhor compreensão ou facilidade de programação as funções de indexação trabalham com ponteiros (como mostra o exemplo 13. } /* Acessa s como um ponteiro */ void put(char *s) { while (*s) putchar(*s++). Para atribuir o endereço de uma variável inteira.5 a implementação da função puts()). deve-se escrever x[2] = &var. } void main(void) { int mat[20]. i++) printf(“%d”. for (t=0. Exemplo 12. chamada var. } No caso da passagem de parâmetros é possível tratar uma matriz como se fosse um ponteiro.h” #include “string.4 /* Indexa s como uma matriz */ void put(char *s) { register int t.LINGUAGEM C *(matriz + índice) é o mesmo que matriz[índice].*(p+i)). mostra_tab(mat).3. Exemplo 12. for(i=0.h” void le_tab(int *p) { register int i. } void mostra_tab(int *p) { register int i. } 12. le_tab(mat).h” #include “stdio. i<20. A declaração de uma matriz de ponteiros int. ao terceiro elemento da matriz de ponteiros.(p+i)).

i<10.LINGUAGEM C para encontrar o valor de var. 12. t<10.3.6 void display_array(int *q[]) { register int t. Isto é.1 mostra o conceito de indireção múltipla. e segundo. q é um ponteiro para uma matriz de ponteiros para inteiros. Mais especificamente. for (i = 0. A figura 12. t++) printf(“%d”. ordena(p).7. Se for necessário passar uma matriz de ponteiros para uma função. matriz como argumento de função é automaticamente passada por referência por questão da implementação da linguagem. é uma matriz de ponteiros e consequentemente sua declaração é caracterizada pelo asterisco na frente do nome da variável. não é uma passagem de parâmetros por referência por dois motivos: primeiro.*q[t]).7 main() { static char nome[10][10]. Exemplo 12.i++) p[i] = nome[i]. Portanto.simplesmente chama-se a função com o nome da matriz sem qualquer índice (como mostra o exemplo 13. por exemplo.2 Acessando partes de Matrizes como vetores A linguagem C trata partes de matrizes como matrizes. } 12. escreve-se *x[2]. Isto pode ser muito útil no tratamento de matrizes. Ponteiro endereço Indireção Simples Ponteiro Ponteiro Variável Variável valor 60/105 . pode ser usado o mesmo método que é utilizado para passar outras matrizes . Matrizes de ponteiros são usadas normalmente como ponteiros de strings como. O exemplo 13. char *p[10]. o argumento da linha de comandos argv. } Lembre-se de que q não é um ponteiro para inteiros. Exemplo 12. for (t=0. cada linha de uma matriz de duas dimensões pode ser considerada como uma matriz de uma dimensão.4 Indireção Múltipla Indireção múltipla é uma situação onde o ponteiro aponta para um outro ponteiro e que o mesmo aponta para um valor final.8 mostra a atribuição de uma linha da matriz nome para um ponteiro.7). é necessário declarar o parâmetro q como uma matriz de ponteiros para inteiros. como é mostrado no exemplo 13.

Mas para declarar este tipo de apontador tem que se seguir uma sintaxe especial como mostra o exemplo 13. check(s1. } void check(char *a.24 #include “stdio. você deve utilizar o operador asterisco duas vezes. gets(s2). s2[80]. **q). como no exemplo 13. como mostra o exemplo 13. Tal exemplo mostra a declaração da variável ptrptrint como um ponteiro para um ponteiro do tipo int.h” void main() { int x.10: Exemplo 12.2 Indireção simples e múltipla A indireção múltipla pode ser levada a qualquer dimensão desejada.h” #include “string. q = &p.23 #include “stdio. int (*p)(). **q.h” void check(char *a. Exemplo 12. 61/105 . p = &x.s2. p = strcmp.p). char *b.: Não confunda indireção múltipla com listas encadeadas. um ponteiro de função pode ser usado para chamar uma função.LINGUAGEM C endereço endereço Indireção Múltipla Figura 12. int (*cmp)()). gets(s1). Exemplo 12.5 Ponteiros para Funções A linguagem C permite apontadores para funções. mas raramente é necessário mais de um ponteiro para um ponteiro. char *b.9. Para acessar o valor final apontado indiretamente por um ponteiro a um ponteiro. A declaração deste tipo de variável é feita colocando-se um * adicional em frente ao nome da variável. O endereço de uma função é obtido usando o nome da função sem parênteses ou argumentos.22 int **ptrptrint. printf(“%d”. Isto é permitido pois toda função tem uma posição física na memória que pode ser atribuída a um ponteiro. *p.14. Obs. int (*cmp)()). } valor /* imprime o valor de x */ 12. Portanto. x = 10. void main() { char s1[80].

} Quando a função check() é chamada. no caso de strings pode-se pensar em um comparador de strings genérico onde como terceiro parâmetro é enviado a função que vai realizar a comparação. Onde o programador lê o arquivo do driver para a memória e o executa de acordo com as especificações do fabricante. o primeiro par de parênteses é usado para o aninhamento e o segundo par.. a declaração original representa um ponteiro para uma função que aceita um ponteiro para um vetor de inteiros como argumento e devolve um ponteiro para um inteiro. considere a declaração int *(*p)(int (*a)[]). placas de vídeo. dois ponteiros para caracter e um ponteiro para uma função são passados como parâmetros. note como o ponteiro para função é declarado.14 o qual dispensa o uso de um ponteiro adicional. (*p)(int (*a)[]) representa um ponteiro para uma função cujo argumento é um ponteiro para um vetor de inteiros. pois esta é a forma correta de se declarar este tipo de ponteiro. principalmente em declarações que envolvem funções e matrizes. indica um ponteiro para uma função que aceita um argumento inteiro e retorna um inteiro. Uma outra forma de fazer a chamada é mostrada no exemplo 13.) indica um ponteiro para uma função.LINGUAGEM C { if (!(*cmp) (a. Os parênteses ao redor de *cmp são necessários para que o compilador interprete o comando corretamente. Juntando todas as peças. A interpretação de declarações mais complexas pode ser extremamente mais trabalhosa.6 Mais Sobre declarações de Ponteiros As declarações de ponteiros podem ser complicadas e é necessário algum cuidado na sua interpretação. Outra utilidade é o programador poder enviar a função que se apropria para a comparação por exemplo. indica uma função que aceita um argumento inteiro e retorna um ponteiro para um inteiro. strcmp). b)) printf(“igual”). Nessa última declaração. 12. else printf(“diferente”). a declaração int (*p)(int a). (*a)[] indica um ponteiro para um vetor. (*p)(. Assim. Isto é. check(s1. Os parênteses e colchetes têm maior precedência do que qualquer operador. para indicar uma função. Nessa declaração. finalmente. Assim int (*a)[] representa um ponteiro para um vetor de inteiros. entre outros) que fornecem rotinas de tratamento para aquele hardware específico. Por exemplo. Por outro lado.. Uma das grandes utilidades é o uso de drivers de dispositivos (placas de som.) indica um ponteiro para uma função que retorna um ponteiro para um inteiro. Antes da chamada da função genérica pode verificar se a string é composta por caracteres alfanuméricos (através da função isalpha()) e enviar a função strcmp(). E. int *(*p)(. Dentro da função check(). 62/105 . caso contrário uma função que realize uma comparação de números inteiros (nesta função conterá a conversão das strings em um inteiro (função atoi()). Por isso. a declaração int *p(int a). s2.. Dentro do último par de parênteses (a especificação dos argumentos da função). Lembre-se que se logo após um identificador existir um “abre parênteses” indica que o identificador representa uma função e os colchetes representam uma matriz. modems.

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 função que retorna um ponteiro para um valor inteiro p é uma função que aceita um argumento que é um ponteiro para um caracter e retorna um ponteiro para um valor inteiro p é m ponteiro para uma função que aceita um argumento que é um ponteiro para um caracter e retorna um valor inteiro p é uma função que aceita um argumento que é um ponteiro para um caracter e retorna um ponteiro para uma matriz inteira de 10 elementos p é uma função que aceita um argumento que é um ponteiro para uma matriz de caracter e retorna um valor inteiro p é uma função que aceita um argumento que é uma matriz de ponteiros para caracter e retorna um valor inteiro p é uma função que aceita um argumento que é uma matriz de caracter e retorna um ponteiro para um valor inteiro p é uma função que aceita um argumento que é um ponteiro para uma matriz de caracter e retorna um ponteiro para um valor inteiro p é uma função que aceita um argumento que é uma matriz de ponteiros para caracteres e retorna um ponteiro para um valor inteiro p é um ponteiro para uma função que aceita um argumento que é um ponteiro para uma matriz de caracter e retorna um valor inteiro p é um ponteiro para uma função 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 função 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 funções. int *(*p)(char *a[]). int *p(void). int (*p)(char (*a)[]). int *p[10]. int (*p[10])(char a). int (*p)(char *a). int *p(char (*a)[]). int (*p(char *a))[10]. 63/105 . int *p(char *a[]).LINGUAGEM C A seguir será mostrado várias declarações envolvendo ponteiros e seu significado. int p(char (*a)[]). int p(char *a[]). int *p. int *(*p)(char (*a)[]). int *p(char *a). cada função aceita um argumento que é um caracter e retorna um valor inteiro int (*p)[10]. int *p(char a[]).

7. p = &i. Faça a declaração de uma função (nome: teste) que receba um ponteiro para uma função que possui dois argumentos (int e char) e retorne um ponteiro para um float. 6.**&p. *p+2. Faça uma função que receba um ponteiro para uma matriz e que realize a ordenação da mesma. 2. cada função aceita um argumento que é um ponteiro para um caracter e retorna um ponteiro para um valor inteiro int *(*p[10])(char *a). Faça uma função que receba uma matriz de ponteiros para caracteres e realize a ordenação alfabética da mesma. Como referenciar mat[x][y] em notação de ponteiros.7 Exercícios 1.LINGUAGEM C int *(*p[10])(char a). int *p. } 3. printf(“%u %d %d %d %d \n”. Qual será a saída deste programa? main() { int i=5. p. Crie uma função que receba como parâmetro uma matriz de ponteiros para strings e devolve a matriz ordenada. 4.**&p+4). cada função aceita um argumento que é um caracter e retorna um ponteiro para um valor inteiro p é uma matriz de ponteiros com 10 elementos para funções. 12. 8. Faça a declaração e inicialização de uma matriz de ponteiros para os dias da semana. Escreva uma função que inverta a ordem dos caracteres de uma string. 64/105 .3**p. p é uma matriz de ponteiros com 10 elementos para funções. 5.

} conta1. que é um agrupamento de variáveis sobre um nome e. float saldo. Como mostra o exemplo acima. Em C. No caso de um programa que utilize esta estrutura para passar parâmetros. como é mostrado no exemplo abaixo: struct cad_conta { char nome[30]. a linguagem permite a criação de rótulos de estruturas (nome_struct).} [nome_var]. … tipo varN. Na declaração acima. 13. pode-se obter estruturas que contenham mais de um tipo de dado. declarar variáveis locais. struct cad_conta { char nome[30]. algumas vezes. isto é. Estruturas e Uniões A linguagem C permite criar tipos de dados definíveis pelo usuário de cinco formas diferentes. int idade. Tal estrutura é conhecida em outras linguagens como registros. float saldo. tipo var2. O segundo tipo definido pelo usuário é o campo de bit.5.1 Estruturas O tipo estruturado struct possibilita a criação de estruturas de dados complexas. a qual permite que a mesma porção da memória seja definida por dois ou mais tipos diferentes de variáveis. int idade. Quando rotula-se a estrutura pode-se omitir a declaração das variáveis. que é uma variação da estrutura que permite o fácil acesso aos bits dentro de uma palavra. Deve-se encerrar com um ponto-e-vírgula a declaração porque a definição de estrutura é na realidade uma instrução C. é chamada de tipo de dado conglomerado.LINGUAGEM C 13. Para utilizar esta estrutura na definição de outras variáveis temse que declará-las juntas com a definição da estrutura. Tais como: struct { char nome[30]. O terceiro é a união. conta2. } conta1. A primeira é estrutura. a declaração de uma estrutura é feita da seguinte forma: struct [nome_struct] { tipo var1. Um quarto tipo de dado é a enumeração. assim como a estrutura pode ser acessada como um todo. int codigo. Cada elemento que compõe a estrutura (chamado campo) pode ser acessado individualmente. O último tipo definido pelo usuário é criado através do uso de typedef e define um novo nome para um tipo existente. o nome_struct não é utilizado pois esta estrutura será utilizada pelas variáveis de estrutura conta1 e conta2. como foi visto na seção 1. 65/105 . foram declaradas as variáveis conta1 e conta2 como sendo uma estrutura do tipo cad_conta. entre outros. conta2. int idade. que é uma lista de símbolos. int codigo. A declaração de estruturas pode se apresentar de diversas formas.

main() { static struct cad_conta conta1 = {“Andre”. float saldo. char mes[10].LINGUAGEM C int codigo. 1000. struct data { int dia. … } 13.nome. ela terá um escopo global.59}. Observe que a classe de uma estrutura é dada pelo ponto em que as variáveis foram declaradas e não pelo ponto onde a estrutura foi definida. conta1.26 conta2 = conta1. conta1. strcpy(conta1. 13. conta2. int idade.idade = 21. É permitida a atribuição entre struct. Exemplo 13. também é permitido o uso de estruturas na declaração.1.saldo = 0. a estrutura tem escopo local para aquela função.1 Inicializando Estruturas Uma estrutura só pode ser inicializada se pertencer às classes static ou extern. As estruturas seguem o padrão do escopo de variáveis. int ano. }. 9507. conta2 = {“Carlos”. Neste caso todos os campos são copiados. }.1.2 Estruturas Aninhadas Como os campos da estrutura podem ser de qualquer tipo. Para acessar um campo específico de uma struct utiliza-se o operador . se a declaração estiver contida numa função. float saldo. struct cad_conta { char nome[30]. 1567. Exemplo 13. 33. Da mesma forma que os vetores. as estruturas são inicializadas com uma lista de valores (cada um correspondente a um campo de estrutura) entre chaves e separados por vírgulas. int codigo.25 conta1. }. (ponto). 23. se a declaração estiver fora de todas as funções. isto é.codigo = 0. 9678. 66/105 . Para usar esta estrutura em outras declarações deve-se especificar desta forma: struct cad_conta conta1.89}.”Joao”).

a responsabilidade da decisão fica a cargo do programador. int codigo. return(aux). conta1 = ins_conta(). float salario. O acesso a um campo de uma estrutura aninhada é feito na forma: funcionário. } void lista(aux) 67/105 . &aux. scanf(“%d”.nome). “Janeiro”. 5634.nascimento. scanf(“%f”.saldo). 13.28. main() { static struct cad_conta conta1.44. 456.LINGUAGEM C struct func { char nome[20]. gerente = {“Jose”. Desta forma. lista(conta1). Assim. uma função pode passar ou retornar uma estrutura. A estrutura é inicializada também com uma lista de valores entre chaves e separados por vírgulas. 1967}}.1. gets(aux.mes. main() { static struct func funcionario = {“Marcio”. 1234. {18.3 Estruturas e funções Em versões mais antigas de compiladores C. 1950}}. {10. struct data nascimento. &aux. }. No Turbo C e outros compiladores mais recentes.”Abril”). 3743. as estruturas eram obrigatoriamente passadas por referência. } Observe a inicialização das variáveis. &aux. uma vez que uma estrutura pode ser muito grande e a cópia de todos os seus campos para a pilha poderia consumir um tempo exagerado.idade). strcpy(gerente. Isto se devia a razões de eficiência. “Marco”. … } struct cad_conta ins_conta() { struct cad_conta aux. usando-se o operador de endereço (&).dia = 10. as estruturas não podiam ser usadas em passagem de parâmetros por valor para funções. }. float saldo.codigo).nascimento. int codigo. scanf(“%d”. struct cad_conta { char nome[30]. int idade.

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 criação de tabela de estruturas mantém a sintaxe normal de definição 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 variáveis. 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 primários para ponteiros de estrutura: gerar uma chamada por referência para uma função e criar estruturas de dados dinâmicas (listas, pilhas, filas, entre outras) utilizando-se do sistema de alocação 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 declaração, atribuição e utilização 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

o

endereco

da

13.2

Campos de Bits

Ao contrário das linguagens de computador, C tem um método intrínseco para acessar um único bit dentro de um byte. Isso pode ser útil por um certo número de razões: • Se o armazenamento é limitado, você pode armazenar diversas variáveis Booleanas (verdadeiro/falso) em um byte. • • Certos dispositivos transmitem informações 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 método 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 definição 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 não pode ter sinal. (Alguns compiladores só permitem campos do tipo unsigned). Um exemplo de campos de bits é a comunicação via serial que devolve um byte de estado organizado desta forma: Bit 0 1 2 3 4 5 6 7 Significado quando ligado alteração na linha clear-to-send alteração em data-set-ready borda de subida da portadora detectada alteração na linha de recepção clear-to-send data-set-ready chamada do telefone sinal recebido Pode-se representar a informação 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 atribuição de outro tipo de elemento de estrutura. status.ring = 0; Não é necessário dar um nome a todo campo de bit. Isto torna fácil alcançar o bit que se deseja acessar, contornando os não 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;

Além disso, nota-se que os bits após dsr não precisam ser especificados se não são usados. Variáveis de campo de bit têm certas restrições: • Não pode obter o endereço de uma variável de campo de bit. • Variáveis de campo de bit não podem ser organizadas em matrizes. • Não pode ultrapassar os limites de um inteiro. • Não pode saber, de máquina para máquina, se os campos estarão dispostos da esquerda para a direita ou da direita para a esquerda. • Em outras palavras, qualquer código que use campos de bits pode ter algumas dependências da máquina. Finalmente, é válido 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; /* deduções de imposto */ }; define um registro de um empregado que usa apenas um byte para conter três informações: o estado do empregado, se o empregado é assalariado e o número de deduções. Sem o campo de bits, essa variável ocuparia três bytes.

13.3

Uniões

Uma união é um tipo de dado que pode ser usado de muitas maneiras diferentes. Por exemplo, uma união pode ser interpretada como sendo um inteiro numa operação e um float ou double em outra. Embora, as uniões possam tomar a aparência de uma estrutura, elas são muito diferentes.

70/105

Para criar uma união utiliza-se a seguinte sintaxe: union [nome_union] { tipo var1. No entanto. }. se a declaração estiver fora de todas as funções. } data. int i. double d. union tipos { char c. } data. Como mostra o exemplo acima. float f. uma união só pode conter informações de um tipo de dados de cada vez. tipo var2. As estruturas seguem o padrão do escopo de variáveis. float f. struct so_int { int i1. }. Para usar esta união em outras declarações deve-se especificar desta forma: union tipos data1. int i.LINGUAGEM C Uma união pode conter um grupo de muitos tipos de dados. Para acessar um campo específico de uma union utiliza-se o operador . Para utilizar esta união na definição de outras variáveis tem-se que declará-las juntas com a definição da união.} [nome_var]. como é mostrado no exemplo abaixo: union tipos { char c. foi declarada a variável data como sendo uma união do tipo tipos. Deve-se encerrar com um ponto-e-vírgula a declaração porque a definição de união é na realidade uma instrução C. (ponto). isto é. Quando rotula-se a união pode-se omitir a declaração das variáveis. se a declaração estiver contida numa função.i2. A declaração de uniões pode se apresentar de diversas formas. float f. double d. o nome_union não é utilizado pois esta união será utilizada pela variável data. struct so_float { float f1. No caso de um programa que utilize esta união em várias partes do programa a linguagem C permite a criação de rótulos de estruturas (nome_union). }. Na declaração acima. data2. Pode-se declarar estruturas dentro de uniões. double d. Tais como: union { char c. todos eles compartilhando a mesma localização na memória. a estrutura tem escopo local para aquela função. … tipo varN. int i. ela terá um escopo global. 71/105 .f2.

teste.f1.4 Sizeof() Com uso de estruturas.i. No tempo de execução.i2).teste. int i.i. usando boolean boolean ok. uniões e enumerações pode-se utilizá-las para a criação de variáveis de diferentes tamanhos e que o tamanho real dessas variáveis pode mudar de máquina para máquina. %-3d i2 = %-3d\n”.f2). A forma geral de um comando typedef é typedef tipo nome.5 union tipos { char c. %. 13.i.5.teste. Também é válida a redefinição.i2 printf(“i1 teste. mas sim.f1 teste.5. 3.f.i1 teste. Não há criação de uma nova variável. 3. struct so_float f.f. } data.5 Typedef C permite que defina-se explicitamente novos nomes aos tipos de dados. O sizeof(data) é 8. Exemplo 13. Esse comando diz ao compilador para reconhecer boolean como outro nome para char. não importa o que a união data está realmente guardando. Assim.f. poderia ser criado um novo nome para char utilizando typedef char boolean.f. 13.LINGUAGEM C union { struct so_int i. 72/105 . } teste. para se criar uma variável char. main() { teste.h> typedef char boolean.1f f2 = %.1f\n”. #include <stdio. Por exemplo.f2 printf(“f1 = = = = = = 2. typedef boolean bool. Tudo o que importa é o tamanho da maior variável que pode ser armazenada porque a união tem de ser do tamanho do seu maior elemento. float f. Serve para uma boa documentação ou até tornar os programas dependentes de máquina um pouco mais portáteis.i.i1. utilizar um novo nome para um nome atribuído a um dado previamente estabelecido. 2. O operador unário sizeof() calcula o tamanho de qualquer variável ou tipo e pode ajudar a eliminar códigos dependentes da máquina de seus programas. double d.teste. isto é. definindo-se um novo nome para um tipo já existente. utilizando a palavrachave typedef.

}. main() { cad_conta *ptr.6) Exemplo 13. } 13.retirada. float saldo.b).6 Exercícios 1. } ou struct conta { char nome[30]. valor da operação código do cliente. float saldo. ptr->codigo = 1000. int codigo. ptr = &conta. int idade. ptr->idade = 23.a. a = 1. typedef struct conta cad_conta. main() { cad_conta *ptr.LINGUAGEM C void main() { boolean a. ptr->idade = 23. int codigo. 73/105 .0 depósito. printf("%d %d". ptr->codigo = 1000. int idade.6 typedef struct conta { char nome[30]. b = 2. bool b. 1 . } A declaração typedef é usado também para definir tipos estruturados (struct e union) para facilitar a nomenclatura dos tipos na declaração de variáveis (exemplo 12. } cad_conta. Faça um programa que leia os dados de 10 clientes de um banco e após leia 100 conjuntos de 3 valores: • • • código de operação . ptr = &conta.

O cadastro deve ser da seguinte forma: • • • nome (30 caracteres). Faça um programa de cadastro de clientes que contenham as seguintes opções: incluir. 74/105 . código (0 a 255).LINGUAGEM C Realize as movimentações nas contas correspondentes e ao final escreva o nome e saldo de cada cliente. alteração. idade(char). 2. excluir e consultar por código ou por nome.

As funções são utilizadas para alocar e desalocar esta memória. Sintaxe.H. 14.: void *malloc(size_t size). No caso em que não houver memória suficiente. o que estiver livre.1 Função malloc() Esta função devolve um ponteiro para o primeiro byte de uma região de memória de tamanho size que foi alocada do heap. onde encontram-se mais funções de alocação dinâmica. além das funções descritas. Existem vários mecanismos que realizam este tipo de processamento. Entretanto. A escolha e a implementação de uma estrutura de dados são tão importantes quanto as rotinas que manipulam os dados. alguns compiladores mais antigos devolvem ponteiros para char. Onde size_t pode ser considerado um inteiro sem sinal e size é o número de bytes de memória que se quer alocar. tais funções estão especificadas na biblioteca ALLOC. a área permanente e a pilha. a função devolve um ponteiro nulo. Cuidado! Ao usar um ponteiro nulo. Porém. serão estudadas. Essa função devolve um ponteiro void. O padrão C ANSI especifica que o sistema de alocação dinâmica devolve ponteiros void. deve-se usar um cast quando atribuir a ponteiros de tipos diferentes. O padrão C ANSI especifica que os protótipos para as funções de alocação dinâmica definidas pelo padrão estão em STDLIB. Alocação Dinâmica Programas consistem em duas coisas: algoritmos e estruturas de dados. Abaixo estão listados alguns mecanismos básicos: • • Listas Pilhas • • Filas Árvores Cada um destes mecanismos pode ter variações de acordo com a política de processamento (armazenamento/recuperação). Um bom programa é uma combinação de ambos. como mostra a sintaxe. 75/105 .H. No entanto.1. Para a manipulação de dados é utilizado mecanismos que auxiliam tanto na forma de como é armazenado ou recuperado. free(). porque serão como base para a construção dos demais. O padrão C ANSI define apenas quatro funções para o sistema de alocação dinâmica: calloc(). 14. Neste capítulo será abordado com mais ênfase as listas encadeadas.1 Funções de Alocação dinâmica em C A memória alocada pelas funções de alocação dinâmica de C é obtida do heap . malloc(). Nesse caso.a região de memória livre que está o programa. algumas funções que estão sendo largamente utilizadas. pode ocorrer uma quebra do sistema. portanto pode-se atribuir a qualquer tipo de ponteiro. podendo apontar para qualquer objeto. que são ponteiros genéricos.LINGUAGEM C 14. realloc().

p = (char*)malloc(1000). char cep[10]. Exemplo 14. O compilador deve conhecer duas informações sobre qualquer ponteiro: o endereço da variável apontada e seu tipo.LINGUAGEM C Para assegurar a portabilidade de um programa que utilize a alocação dinâmica. char *p. char rua[40]. No fragmento abaixo é alocado memória suficiente para 50 inteiros. Essa função devolve um ponteiro void. p=(struct addr*) malloc(sizeof(addr)) Este tipo de conversão deve ser realizado em todas as funções de alocação como calloc(). faz-se necessário a utilização da função sizeof(). precisa-se fazer uma conversão de tipo (cast) do valor retornado por malloc().2 Função calloc() Esta função devolve um ponteiro para o primeiro byte de uma região de memória de tamanho size * num que foi alocada do heap. char cidade[40]. portanto pode-se atribuir a qualquer tipo de ponteiro. como mostra a sintaxe. } return p. realloc() e malloc(). Onde size_t pode ser considerado um inteiro sem sinal e size é o número de bytes de memória que se quer alocar. 14. } O fragmento do código mostra a alocação de 1000 bytes de memória. a função devolve um ponteiro nulo.: void *calloc(size_t num. char estado[3]. Portanto. Por isso. if ((p=(struct addr*)malloc(sizeof(addr)))==NULL) { printf(“ erro de alocação . 76/105 .1. Sintaxe.abortando”).}. no exemplo 13. size_t size). No caso em que não houver memória suficiente.27 Esta função aloca memória suficiente para conter uma estrutura do tipo addr: struct addr { char nome[40]. int *p. já que o mesmo retorna um void. struct addr *get_struct(void) { struct addr *p. p = (int*)malloc(50 * sizeof(int)). exit(1).15 deve-se indicar ao compilador que o valor retornado por malloc() é do tipo ponteiro para struct addr.

} return p. sizeof(float)). faz-se necessário a utilização da função sizeof(). A diferença entre calloc() e malloc() é que a primeira aloca a memória e inicializa-a com zeros. tornando a memória disponível para alocação futura. Exemplo 14. p=(float*)calloc(100.h> #include <stdio. Exemplo 14.LINGUAGEM C Para assegurar a portabilidade de um programa que utilize a alocação dinâmica. /* libera a memoria */ 77/105 . if (!p) { printf(“ erro de alocação . exit(1). free() deve ser chamada somente com um ponteiro que foi previamente alocado com uma das funções do sistema de alocação dinâmica. /* aloca memoria para uma string */ str = (char*)malloc(10). str).h> int main(void) { char *str. } No fragmento abaixo é alocado memória suficiente para 50 inteiros.3 #include <string. int *p. p = (int*)calloc(50.3 Função free() Esta função devolve ao heap a memória apontada por ptr.1. /* mostra a string */ printf("String: %s\n". /* copia "Hello" para a string */ strcpy(str.abortando”).sizeof(int)).h> #include <alloc.2 Esta função aloca memória suficiente para conter umvetor de 100 elementos: #include “stdlib.h” float *get_mem(void) { float *p. "Hello"). 14.h” #include “stdio. A utilização de um ponteiro inválido na chamada provavelmente destruirá o mecanismo de gerenciamento de memória e provocará uma quebra do sistema.

”isso são 22 caracteres”). Sintaxe. é devolvido um ponteiro nulo e o bloco original é deixado inalterado.: void *realloc(void *ptr.”. #include “stdlib. } strcpy(p. Se isso ocorre. Se size é zero. size_t size).1.h” #include “stdio. Exemplo 14. copia a string “isso são 22 caracteres” neles e.24). Se não há memória livre suficiente no heap para alocar size bytes. em seguida. exit(1). } 14. nenhuma informação é perdida.abortando”). Se ptr é um nulo. p=(char*)malloc(23). p = (char*)realloc(p. realloc() simplesmente aloca size bytes de memória e devolve um ponteiro para a memória alocada.4 Função realloc() Esta função modifica o tamanho da memória previamente alocada apontada por ptr para aquele especificado por size. portanto não haverá nenhum problema para utilizar (exemplo 13. printf(p). if (!p) { printf(“ erro de alocação . exit(1). return 0. O valor de size pode ser maior ou menor que o original. if (!p) { printf(“ erro de alocação .4 Esta programa primeiro aloca 23 caracteres.h” #include “string. pôr um ponto no final.LINGUAGEM C free(str).”). Um ponteiro para o bloco de memória é devolvido porque realloc() pode precisar mover o bloco para aumentar seu tamanho. } 14. 78/105 .2 Matrizes Dinamicamente Alocadas Qualquer ponteiro pode ser indexado como se fosse uma matriz unidimensional. o conteúdo do bloco antigo é copiado no novo bloco. } strcat(p. assim. usa realloc() para aumentar o tamanho para 24 e.abortando”).h” void main(void) { char *p. a memória apontada por ptr é liberada. free(p).19).

free(s). sizeof(int)).h” void le_tab(int mat[20][5]) { register int i.j. i<20. register int t. j++) printf(“%d”. */ #include “stdlib. i++) for(j=0. t>=0. register int t.LINGUAGEM C Exemplo 14. i<20. j<5.abortando”).20. if (!p) { 79/105 . } gets(s). j<5.h” void main(void) { char *s. Isto é mostrado no exemplo 13.mat[i][j]). solicita */ /* a entrada do usuário e.h” #include “stdio.j.h” #include “stdio. imprime a string */ /* de trás para frente. j++) scanf(“%d”. for(i=0. Dessa forma.h” #include “string.h” #include “string. exit(1). i++) for(j=0. } Para acessar uma matriz unidimensional é simples. Para conseguir uma matriz alocada dinamicamente. permitindo. mas para mais de uma dimensão levam alguns problemas com a indexação.7 #include “stdlib. s=(char*)malloc(80). deve-se utilizar um truque: passar um ponteiro como um parâmetro a uma função. a função pode definir as dimensões do parâmetro que recebe o ponteiro. if (!s) { printf(“ erro de alocação . s=(int*)calloc(100. t--) putchar(s[t]). for (t=strlen(s)-1.&mat[i][j]). assim. } void main(void) { char *p. for(i=0. a indexação normal da matriz. Exemplo 14.6 /* Aloca memória para uma string dinamicamente. em seguida. } void mostra_tab(int mat[20][5]) { register int i.

3 Listas Encadeadas Listas encadeadas são usadas para dois propósitos fundamentais. figura **inicio.encadeadas. Isto é. figura **fim) { if (!*fim) /* Primeiro elemento da lista */ { *fim = i. } figura1. } le_tab(p). } } Os parâmetros início e fim da função têm dois asteriscos porque representam uma indireção múltipla. Isto é necessário para poder implementar a passagem de parâmetros por referência.um elo para o próximo item . mostra_tab(p).ou duplamente .LINGUAGEM C printf(“ erro de alocação . Listas encadeadas podem ser singularmente (simplesmente) .y. void inclui(figura *i. A função inclui() constrói uma lista singularmente encadeada colocando cada novo item no final da lista. são apontadores para apontadores da estrutura figura.z. struct ponto *prox.3.z) para representação de uma figura geométrica. } else { (*fim)->prox = i.elos para o anterior e próximo elemento da lista . Considere um exemplo de armazenamento de coordenadas cartesianas (x. o qual pode ser utilizado em todo o programa. foi definido que figura é um tipo. 80/105 . Cada item de dado geralmente consiste em uma estrutura que inclui campos de informação e ponteiro de enlace (ou de ligação). Após a declaração. Deve ser passado um ponteiro para uma estrutura do tipo ponto. *inicio = i. *fim = i.y. exit(1). 14. } 14. precisa-se definir a estrutura de dados que contenha a informação e os elos. Listas encadeadas também são usadas em armazenamento de banco de dados em arquivos em disco. é declarado um apontador para a próxima estrutura.abortando”).1 Listas Singularmente Encadeadas Uma lista singularmente encadeada requer que cada item de informação contenha um elo como o próximo da lista. Na estrutura acima. typedef struct ponto figura. A estrutura de dados para cada elemento é definido aqui: struct ponto { int x. Antes. por isso declara-se um apontador para a própria estrutura (auto-referência). que representa uma struct ponto. O primeiro é criar matrizes de tamanho desconhecido na memória. ponteiro para o primeiro elemento e ponteiro para o último elemento.

A função a seguir excluirá um item de uma lista de estruturas do tipo ponto: void exclui( figura *p. void incord(figura *i. figura **ultimo) { if (p) p->next = i->next. struct ponto *ant. i->prox = NULL.3. 14.LINGUAGEM C Apagar um item de uma lista singularmente encadeada pode ocorrer em três situações: apagar o primeiro item. }.2 Listas Duplamente Encadeadas Consistem em dados e elos para o próximo item e para o item precedente. if (i==*last && p) *last = p.. figura **fim) /* novo elemento */ /* primeiro elemento da lista */ /* ultimo elemento da lista */ 81/105 . struct ponto *prox. i->ant = *fim. figura **inicio. apagar um item intermediário e apagar o último item. *fim = i. } /* /* /* /* item anterior */ item a apagar */ início da lista */ final da lista */ Listas singularmente encadeadas têm uma desvantagem é que a lista não pode ser lida em ordem inversa. else *start = i->next. } Para armazenagem de um dados em uma posição específica a função abaixo realiza a inclusão em ordem crescente pelo eixo x de uma lista duplamente encadeada. figura **fim) { if (!*fim) *fim = i. Um novo elemento pode ser inserido em uma lista duplamente encadeada de três maneiras: inserir um novo primeiro elemento. figura **inicio. exceto pelo fato de que dois elos devem ser mantidos. a função seguinte constrói uma lista duplamente encadeada. será mostrado a declaração de um nodo de lista duplamente encadeada. figura *i. Utilizando a estrutura ponto. struct ponto { int x. inserir um elemento intermediário ou inserir um novo último elemento. A construção de uma lista duplamente encadeada é semelhante à de uma lista singularmente encadeada. /* é o primeiro item da lista */ else (*fim)->prox = i. typedef struct ponto figura. Usando figura como o item de dado básico.y. Esta função inclui um novo dado no fim da lista: void incfim(figura *i.

/* intermediária da lista */ i->prox = p. /* primeiro elemento da lista */ figura **fim) /* ultimo elemento da lista */ { figura *old. /* inserir no fim da lista */ i->prox = NULL. i->ant = old. old = NULL. p->ant = i. *fim = i. } if (!old) { i->prox = p. p = p->prox.LINGUAGEM C { if (!*fim) /* é o primeiro item da lista */ { i->prox = NULL. old = NULL. p = *inicio. i->ant = NULL. /* item a apagar */ figura **inicio. } else { old->prox = i. } else { figura *old. *p. *inicio = i. a função incord() atualiza automaticamente estes ponteiros através das variáveis inicio e fim. *fim = i. i->ant = p->ant. while (p && (p->x < i->x)) { old = p. p->ant = i. Há três casos a considerar ao excluir um elemento de uma lista duplamente encadeada: excluir o primeiro item. p = *inicio. 82/105 . *p. p = p->prox. while (p && (p->x != i->x) &&(p->y != i->y)) { old = p. /* inserir no inicio da lista */ i->ant = NULL. } } } Como o ponteiro de início e fim de lista podem ser alterados. *inicio = i. excluir um item intermediário ou excluir o último item. } else { if (p->ant) { /* inserir em uma posição */ p->ant->prox = i. void delord(figura *i.

struct tree *dir. } } 14. if (!raiz) return r. } r->esq = NULL. /* intermediária da lista */ p->prox->ant = old. char info). else { if (!p->prox) * exclusao do ultimo elemento da lista */ { old->prox = NULL. } else { /* excluir item de uma posição */ old->prox = p->prox. struct tree *esq. { if (!r) { r = (arvore *) malloc(sizeof(arvore)).LINGUAGEM C } if ((p->x = i->x) &&(p->y = i->y)) { if (!old) /* exclusao unico elemento da lista */ *inicio=*fim=NULL. /* primeira entrada */ if (info < raiz->info) raiz->esq = r. }. arvore *stree ( arvore *raiz. r->dir = NULL. typedef struct tree arvore. else raiz->dir = r. A função abaixo constrói uma árvore binária ordenada recursivamente: struct tree { char info. *fim = old. } } free(p). exit(0). if (!r) { printf(“Sem memória \n”). arvore *r. 83/105 . r->info = info.4 Árvores Binárias A estrutura utilizada para a cosntrução de árvores binárias é semelhante a listas duplamente encadeadas. A diferença está na política de organização das mesmas.

a raiz. info). subárvore da esquerda e. em seguida. Na pós-ordenada. tanto o primeiro quanto os elementos subsequentes podem ser inseridos corretamente. d b a c e f g Figura 14. Na preordenada. é visitado a subárvore da esquerda. raiz->info). rt. a ordem de acesso á árvore usando cada método é ordenada preordenada pós-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. preorder(raiz->dir). raiz->info). preordenada e pósordenada.1.r->dir. visita-se a raiz. A função stree() é um algoritmo recursivo. pode-se utilizar as funções descritas abaixo: void inorder(arvore *raiz) { if(!raiz) return. a raiz e em seguida a subárvore da direita. visita-se a subárvore da esquerda.LINGUAGEM C return r. rt. printf(“%c”. a subárvore da direita. inorder(raiz->dir).3 Exemplo de uma árvore binária Utilizando a figura 14.r->esq. inorder(raiz->esq). subárvore da direita e. 84/105 . pelas formas descritas anteriormente. else stree (rt. info). Dessa forma. else stree(r. } if (info < r->info) stree(r. info). Existem três formas de acessar os dados de uma árvore: ordenada. preorder(raiz->esq). } void preorder(arvore *raiz) { if(!raiz) return. depois. A chamada desta função é realizada desta forma: if (!rt) rt = stree(rt. info). Onde a ordenada. printf(“%c”.

raiz->info). } Para exclusão de um nó de uma árvore tem que ser verificado se o nó é a raiz. return p2. while (p->esq) p = p->esq. } } if (raiz->info < key) raiz->dir = dtree(raiz->dir. if (raiz->info==key) /* apagar a raiz */ { if (raiz->esq== raiz->dir) /*não tem filhos */ { free(raiz). arvore *dtree(arvore *raiz. free(raiz). return p. char key) { arvore *p. else raiz->esq = dtree(raiz->esq. } else { p2 = raiz->dir. free(raiz). printf(“%c”. postorder(raiz->dir). Na função a seguir é realizada uma exclusão recursiva observando as restrições delineadas anteriormente.LINGUAGEM C } void postorder(arvore *raiz) { if(!raiz) return. postorder(raiz->esq). } Árvores binárias oferecem grande poder. return NULL. flexibilidade e eficiência quando usadas em programas de gerenciamento de banco de dados. return p. } else if (raiz->dir == NULL) { p = raiz->esq. return raiz. Principalmente pela sua política de organização e a não limitação do tamanho (exceto aquela imposta pela memória). um nodo esquerdo ou direito e que os mesmos podem ter subárvores ligadas a ele. 85/105 . *p2. p->esq = raiz->esq. p = raiz->dir. key). } else if (raiz->esq == NULL) { p = raiz->dir. key). free(raiz).

0 8. 9. onde N é o número de alunos e 4 as respectivas notas de cada aluno. Faça um programa que leia o número de alunos. Escreva um programa que gerencie uma pilha.5 7. imprima a lista em ordem alfabética. rearranje os nomes em ordem alfabética e. Utilize várias estruturas. double).5 Exercícios 1. Calcule a média e mostre na tela conforme descrição a seguir: ALUNO N1 N2 N3 N4 MEDIA 1 8.LINGUAGEM C 14.5 7.0 9.0 2 7. construa uma matriz dinamicamente alocada de tamanho N X 4. depois.0 86/105 . O mesmo deve conter a função de empilhar e desempilhar para o usuário os quatro tipos de dados básicos da linguagem C (char. Escreva um programa que leia vários nomes e endereços. 3.0 6.0 7.5 7. Escreva um programa que gerencie uma fila circular do tipo FIFO (Primeiro que entra é o primeiro que sai).5 7. float. 2. int.

H seja incluído em qualquer programa em que são utilizadas. mas não todos os arquivos.4 Sistema de Arquivos O sistema de arquivos ANSI é composto de diversas funções inter-relacionadas. E/S com Arquivo São grupos de dados armazenados em meio não volátil (disco.isto é. Em contraste. 15.3 Arquivos Um arquivo pode ser qualquer coisa. desde um arquivo em disco até um terminal ou uma impressora. O sistema de E/S de C é único. normalmente com main() retornando ao sistema operacional ou uma chamada à exit(). Essa estrutura é definida no cabeçalho STDIO. porque dados podem ser transferidos na sua representação binária interna ou em um formato de texto. As mais comuns são mostradas na tabela 15. fita. acionadores de disco. Os arquivos não são fechados quando um programa quebra (crash). um arquivo disco pode suportar acesso aleatório enquanto um teclado não pode. 87/105 . Todos as streams são iguais.H. A primeira é uma seqüência de caracteres organizados em linhas e terminadas por um caractere de nova linha (depende da implementação). Cada stream associada a um arquivo tem uma estrutura de controle de arquivo do tipo FILE. Essas funções exigem que o cabeçalho STDIO. São utilizados para armazenar dados de forma permanente.LINGUAGEM C 15. 15. Associa-se uma stream com um arquivo específico realizando uma operação de abertura. 15. independente do dispositivo real (terminais. Sendo que o dispositivo real é chamado de arquivo. O segundo é o sistema de arquivo tipo UNIX (algumas vezes chamado de não formatado ou sem buffer) definido apenas sob o antigo padrão UNIX. A segunda é uma seqüência de bytes com uma correspondência de um para um com aqueles encontrados no dispositivo externo . A linguagem C não contém nenhum comando de E/S. todas as operações de E/S ocorrem através de chamadas a funções da biblioteca C padrão. O primeiro método é denominado de sistema de arquivo com buffer (algumas vezes os termos formatado ou alto nível são utilizados para referenciá-lo). Isto é. acionadores de fita. entre outros) que é acessado. 15. Ao contrário. não ocorre nenhuma tradução de caracteres. Todos os arquivos são fechados automaticamente quando o programa termina.1 E/S ANSI x E/S UNIX O padrão ANSI define um conjunto completo de funções de E/S que pode ser utilizado para ler e escrever qualquer tipo de dado. Essa abordagem faz o sistema de arquivos de C extremamente poderoso e flexível.2 Streams A linguagem C oferece uma abstração da interface para controle de E/S. o antigo padrão C UNIX contém dois sistemas distintos de rotinas que realizam operações de E/S. Existem dois tipos de streams: texto e binária.1. entre outros).

que é uma função que executa acesso aleatório em um arquivo.H define várias macros como: EOF. 15. como o seu nome. Um ponteiro de arquivo é uma variável ponteiro do tipo FILE . Tabela 15.7 . O tipo FILE é discutido na próxima seção. um ponteiro para informações que definem vários dados sobre o arquivo. status.H fornece os protótipos para as funções de E/S e define estes três tipos: size_t.LINGUAGEM C Tabela 15. Sintaxe: FILE *fopen(const char * <nome_ arquivo>.6 Abertura de Arquivos A função fopen() abre uma stream para uso e associa um arquivo a ela. e a posição atual do arquivo. fpos_t e FILE. O tipo size_t é essencialmente o mesmo que um unsigned.2 . leitura e escrita. 15. A macro EOF é geralmente definida como -1 e é o valor quando uma função de entrada tenta ler além do final do arquivo.5 Estrutura FILE Para a manipulação de arquivos é utilizado a declaração de ponteiro (ponteiro de arquivo). SEEK_SET.2. As outras macros são usadas com fseek(). Todas as funções são realizadas utilizando o ponteiro.Funções mais comuns do sistema de arquivo com buffer Nome fopen() fclose() putc() fputc() getc() fgetc() fseek() fprintf() fscanf() feof() ferror() rewind() remove() fflush() Função 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 específico É 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 Repõe o indicador de posição de arquivo no início do arquivo Apaga um arquivo Descarrega um arquivo O arquivo cabeçalho STDIO. STDIO. O modo de abertura define a forma como é feito o acesso aos dados (somente leitura. Para a declaração de um ponteiro de arquivo utiliza-se a seguinte sintaxe: Sintaxe: FILE *<var> Exemplo 15. SEEK_CUR e SEEK_END. etc).Os modos de abertura válidos Modo r w Significado Abre um arquivo texto para leitura Cria um arquivo texto para escrita 88/105 . As forma principais são apresentadas na tabela 15. Isto é.28 FILE *fp. Retorna o ponteiro de arquivo associado a esse arquivo. const char *<modo_abertura>). assim como o fpos_t.

As outras funções têm a mesma sintaxe que suas equivalentes.”wb”). as quais são equivalentes (putc() é uma macro). O valor de retorno 0 significa uma operação de fechamento bem-sucedida. Esta função tem a seguinte sintaxe: Sintaxe: int fclose(FILE *fp).8 Leitura e Gravação de caracteres Para as operações de leitura e gravação são utilizadas duas funções padrões: getc() e putc() (consideradas tecnicamente macros) .dat”. /* ponteiro de arquivo */ arq = fopen(“dados. Qualquer outro valor indica erro.1 Gravação Para escrita de caracteres em um arquivo utilizam-se as funções putc() e fputc().7 Fechamento de Arquivo A função fclose() fecha uma stream que foi aberta através de uma chamada à fopen().2 FILE *arq.8.dat”. Nas seções a seguir serão estudadas as funções declaradas padrão ANSI (as duas primeiras). 15. onde fp é o ponteiro de arquivo devolvido pela chamada à fopen().”wb”). 89/105 . 15.dat”. FILE *fp).LINGUAGEM C a rb wb ab r+ w+ a+ r+b ou rb+ w+b ou wb+ a+b ou ab+ Exemplo 15.”rb”). if (arq= =NULL) arq=fopen(“dados. Se ao abrir um arquivo para leitura o mesmo não existir a função fopen retorna um ponteiro nulo (NULL). que pode ser diagnosticada pela função ferror() (discutida mais adiante). O protótipo para essa função é Sintaxe: int putc(int ch. Anexa a um arquivo texto Abre um arquivo binário para leitura Cria um arquivo binário para escrita Anexa a um arquivo binário 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 binário para leitura/escrita Cria um arquivo binário para leitura/escrita Anexa a um arquivo binário para leitura/escrita 15. arq = fopen(“dados. Para cada uma destas funções existem duas equivalentes: fgetc() e fputc().

O nome do arquivo é passado pela linha de comando.LINGUAGEM C onde fp é um ponteiro de arquivo devolvido por fopen() e ch é o caractere a ser escrito.3 pode-se utilizar uma função como feof() que devolve verdadeiro quando for encontrado o fim de arquivo. 90/105 . O protótipo para essa função é Sintaxe: int getc(FILE *fp). Exemplo 15.10 Trabalhando com arquivos As funções fopen().3 do { ch = getc(fp). onde fp é um ponteiro de arquivo devolvido por fopen(). 15. O exemplo 15.4 while (!feof(fp)) ch = getc(fp).4 lê um arquivo binário até que o final do arquivo seja encontrado.h” #include “stdlib. Se a operação putc() foi bem-sucedida. putc() e fclose() constituem o conjunto mínimo de rotinas de arquivos. O programa a seguir lê caracteres do teclado e os escreve em um arquivo em disco até que o usuário digite um cifrão ($). O protótipo desta função está declarado abaixo: Sintaxe: int feof(FILE *fp).h” void main(int argc. } while (ch!=EOF). ela devolve o caractere escrito.2 Leitura Para leitura de caracteres em um arquivo utilizam-se as funções getc() e fgetc(). Se a operação getc() foi bem-sucedida. Esta função pode ser aplicada tanto para arquivo texto como para arquivos binários. as quais são equivalentes (getc() é uma macro). char *argv[]) { FILE *fp. ela devolve o caractere lido. Caso contrário. ela devolve EOF. Exemplo 15. Caso contrário. #include “stdio. 15. ela devolve EOF.8. 15.3 mostra um laço que realiza uma leitura de um arquivo texto até que a marca de final de arquivo seja lida. A rotina do exemplo 15.9 Verificando fim de arquivo Além de realizar um teste para fim de arquivo como no exemplo 15. getc().

91/105 .LINGUAGEM C char ch. ch = getc(fp). char *fgets(char *str. char *argv[]) { FILE *fp.h” void main(int argc. putc(ch.”r”))==NULL) { printf(“Arquivo nao pode ser aberto\n”). } tela. FILE *fp). exit(1). } ch = getc(fp). exit(1). char ch. O programa complementar descrito a seguir lê qualquer arquivo ASCII e mostra o conteúdo na #include “stdio. if(argc !=2) { printf(“Voce esqueceu de entrar o nome do arquivo \n”). } 15. exit(1). } if((fp=fopen(argv[1].11 Trabalhando com Strings: fputs() e fgets() Para a gravação e leitura de strings de caractere para e de um arquivo em disco são utilizadas as funções fgets() e fputs().”w”))==NULL) { printf(“Arquivo nao pode ser aberto\n”). int length. while (ch!=EOF) { putchar(ch). if(argc !=2) { printf(“Voce esqueceu de entrar o nome do arquivo \n”). fclose(fp).fp). } if((fp=fopen(argv[1].h” #include “stdlib. } while(ch!=‘$’). exit(1). respectivamente. São os seguintes os seus protótipos: Sintaxe: int fputs(const char *str. } do { ch = getchar(). } fclose(fp). FILE *fp).

h” 92/105 . mas escreve a string na stream especificada.h” #include “stdlib. fclose(fp). gets(str). } while (*str != ‘\n”). strcat(str. } do { printf(“entre uma string (CR para sair): \n”).h” void main(void) { char str[80]. 15.”\n”).fp). } 15. A função fgets() lê uma string da stream especificada até que um caractere de nova linha seja lido ou que length-1 caracteres tenham sido lidos.h” #include “string.h” #include “string.dat”. A condição de saída é uma linha em branco. Se uma nova linha é lida. é adicionado um antes que a string seja escrita no arquivo para que o arquivo possa ser lido mais facilmente. exit(1). A string resultante será terminada por um nulo. Como gets() não armazena o caractere de nova linha.h” #include “stdlib.LINGUAGEM C A função fputs() opera como puts().”w”))==NULL) { printf(“Arquivo nao pode ser aberto\n”).dat. Seu protótipo é: Sintaxe: void rewind(FILE *fp).12 Funções de tratamento de arquivos Nas próximas seções serão vistas algumas funções utilizadas em operações com arquivos com buffer.5 rebobina o arquivo do programa anterior e mostrar o conteúdo do mesmo. Exemplo 15. FILE *fp. O exemplo 15. #include “stdio. O programa a seguir lê strings do teclado e escreve-as no arquivo chamado frase.12. if((fp=fopen(“frase. ela será parte da string (diferente de gets()).1 rewind() Esta função reposiciona o indicador de posição de arquivo no início do arquivo especificado como seu argumento. fputs(str.5 #include “stdio. A função devolve um ponteiro para str se bem-sucedida ou um ponteiro nulo se ocorre um erro. EOF é devolvido se ocorre um erro.

} do { printf(“entre uma string (CR para sair): \n”).6 if (remove(“dados.12. FILE *fp. O exemplo 15.dat. } fclose(fp).fp). fp). } while (*str != ‘\n”). } 15. exit(1). Seu protótipo é: Sintaxe: int remove(char *nome_arq) Ela devolve zero caso seja bem-sucedido e um valor diferente de zero caso contrário. } 93/105 . retorna falso. 79. /* reinicializa o file pointer */ while(!feof(fp)) { fgets(str.12.”w”))==NULL) { printf(“Arquivo nao pode ser aberto\n”). if((fp=fopen(“frase.6 apresenta um trecho de programa que apaga o arquivo dados.3 remove() A função remove() apaga o arquivo especificado. rewind(fp).dat”. caso contrário. A função ferror() tem esse protótipo: Sintaxe: int ferror(FILE *fp). fputs(str. strcat(str. exit(1). Exemplo 15.”\n”).dat”)) { printf(“Arquivo nao pode ser apagado\n”). Ela retorna verdadeiro se ocorreu um erro durante a última operação no arquivo. printf(str).LINGUAGEM C void main(void) { char str[80]. gets(str).2 ferror() A função ferror() determina se uma operação com arquivo produziu um erro. 15.

cujo protótipo é mostrado a seguir: Sintaxe: int fflush(FILE *fp).LINGUAGEM C 15. A função ftell() pode não retornar o número exato de bytes se for usada com arquivos em modo texto. Exemplo 15. caso contrário. finalmente. ou um registro. onde buffer é um ponteiro para uma região de memória que contém as informações que serão escritas no arquivo. fp é um ponteiro de arquivo para uma stream aberta anteriormente. O argumento count determina quantos itens serão gravados. que é o ponteiro para a estrutura FILE do arquivio. 15. size_t count. que representa o número de bytes do começo do arquivo até a posição atual. devolve EOF. O número retornado pode ser menor que count quando o final de arquivo for atingido ou ocorrer um erro de gravação. devido à combinação CR/LF que é representada por um único caractere em C.12. Retorna um valor do tipo long. deve-se utilizar a função fflush(). FILE *fp).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 função fwrite(). E.13 Lendo e gravando registros As funções fread() e fwrite() possibilitam uma maneira de transferir blocos de dados do disco para a memória 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. Esta função aceita um único argumento. 15. Seu protótipo está definido a seguir: Sintaxe: size_t fwrite(void *buffer. O número de bytes para gravar é especificado por num_bytes.13. ou até um vetor de registros). matriz. Essa função escreve o conteúdo de qualquer dado existente no buffer arquivo associado a fp.4 fflush() Para se esvaziar o conteúdo de uma stream de saída. size_t num_bytes. Se fflush() devolve 0 para indicar sucesso.12. Seu protótipo é mostrado aqui: Sintaxe: long ftell (FILE *fp).5 Função ftell() Esta função retorna a posição do ponteiro de um arquivo binário em relação ao seu começo.7 94/105 . 15. Esta função devolve o número de itens escritos.

arq). O argumento count determina quantos itens serão lidos. fwrite(&var_int.13.13.x). arq = fopen(“dados.1.y). size_t count. Exemplo 15.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 função fread(). especialmente estruturas.dat”.&coord[i]. FILE *arq. Esta função devolve o número de itens lidos. ponto coord[10].dat”. 15. void main() { FILE *fp. 15. typedef struct pto ponto. O número de bytes para ler é especificado por num_bytes. finalmente. for (i=0.y. scanf(“%d \n”. i++) { printf(“Coordenada x:”). E. var_int = 5.sizeof(var_int). } if((fp=fopen(“figura.h” struct pto { int x. }. size_t num_bytes. #include “stdio. FILE *arq.&coord[i].arq). arq = fopen(“dados. int i. fp é um ponteiro de arquivo para uma stream aberta anteriormente.3 Utilizando os comandos de leitura e gravação de registros Uma das mais úteis aplicações de fread() e fwrite() envolve ler e escrever tipos de dados definidos pelo usuário.”wb”).”rb”). scanf(“%d \n”. Seu protótipo está definido a seguir: Sintaxe: size_t fread(void *buffer. onde buffer é um ponteiro para uma região de memória que receberá os dados do arquivo. O número retornado pode ser menor que count quando o final de arquivo for atingido ou ocorrer um erro de leitura. i < 10. fread(&var_int.10. printf(“Coordenada y:”).sizeof(var_int).”w”))==NULL) { 95/105 . FILE *fp).LINGUAGEM C int var_int.dat”.8 int var_int.

} for (i=0. Onde.9 mostra a utilização da função fseek().H. Este exemplo recebe pela linha de comando o deslocamento a ser realizado sempre a partir do início do arquivo (SEEK_SET).y) = (%d. Seu protótipo é mostrado aqui: Sintaxe: int fseek (FILE *fp. que se tornará a nova posição corrente. } fclose(fp).3 – Macros definidas em STDIO. é o número de bytes a partir de oriem. um inteiro longo. e origem é uma das seguintes macros definidas em STDIO.coord[i]. Exemplo 15. sizeof(ponto).y).1. exit(1). i = 0. sizeof(ponto). int origem). Origem Início do arquivo Posição atual Final do arquivo Nome da Macro SEEK_SET SEEK_CUR SEEK_END A função fseek() devolve 0 se a operação for bem-sucedida e um valor diferente de zero se ocorre um erro. O exemplo 15. numbytes. Tabela 15.14 Acesso aleatório Operações de leitura e escrita aleatórias podem ser executadas utilizando o sistema de E/S bufferizado com a ajuda de fseek(). 1. if(argc !=3) { printf(“Uso: SEEK nomearq byte \n”). char ch.H para as posições permitidas na função fseek(). 96/105 .LINGUAGEM C printf(“Arquivo nao pode ser aberto\n”). long numbytes. que modifica o indicador de posição de arquivo. while(!feof(fp)) { fread(&coord[i].%d).h” void main(int argc.h” #include “stdlib. exit(1). rewind(fp).x. char *argv[]) { FILE *fp. fp).9 #include “stdio. fp).coord[i]. } 15. i++) fwrite(&coord[i]. printf(“Coordenadas (x. i < 10.

int t. fclose(fp).).). A fscanf() devolve o número de elementos lidos. const char *control_string. exit(1). O exemplo 15. . exit(1). /* le do teclado */ 97/105 . onde fp é um ponteiro de arquivo devolvido por uma chamada à fopen(). char s[80].. que tem por função converter uma string em um inteiro longo.h” void main(void) { FILE *fp. convertidos e armazenados.”r”))==NULL) { printf(“Arquivo nao pode ser aberto\n”).290 #include “stdio. } if(fseek(fp.. const char *control_string.9 verifica-se a utilizção da função atol(). SEEK_SET)) { printf(“erro na busca\n”). atol(argv[2]). } printf(“entre com uma string e um número: “ ). . } No exemplo 15. exit(1). Essas funções se comportam exatamente como printf() e scanf() exceto por operarem em arquivos. } printf(“O byte em %ld é %c\n”. o sistema de E/S com buffer inclui fprintf() e fscanf().. fscanf(stdin.. if((fp=fopen(“teste”. &t). escreve-os em um arquivo em disco e em seguida lê e mostra a informação na tela. No printf() utiliza-se o modo de formatação %ld que é para apresentação de um decimal longo ou um inteiro longo. getc(fp)). int fscanf(FILE *fp. atol(argv[2]).10 mostra um programa que lê uma string e um inteiro do teclado. Exemplo 15. No caso de fim de arquivo o fscanf() devolve o valor EOF. “%s%d”. 15.h” #include “stdlib. s. fprintf() e fscanf() direcionam suas operações de E/S para o arquivo apontado por fp.15 Comando de gravação em modo texto formatado Como extensão das funções básicas de E/S já discutidas.”w”))==NULL) { printf(“Arquivo nao pode ser aberto\n”).h” #include “io.LINGUAGEM C } if((fp=fopen(argv[1]. Os protótipos de fprintf() e fscanf() são Sintaxe: int fprintf(FILE *fp.

exit(1). “%s %d”. “%s%d”. pelo sistema operacional. O argumento de perror() é uma string fornecida pelo programa que normalmente é uma mensagem de erro que indica em que parte do programa ocorreu erro.LINGUAGEM C fprintf(fp. if((fp=fopen(“teste”. onde nomearq é um ponteiro para o nome do arquivo que se deseja associar à stream apontada por stream. como mostra o exemplo 15. Para redirecionar as streams padrão utiliza-se a função freopen(). /* escreve no arquivo */ fclose(fp). Se for detectado um erro de disco.porta serial). t). Exemplo 15. O programa do exemplo 15. (impressora padrão . s. const char *modo. e a segunda parte.11 98/105 . mas esta informação não basta para a solução por parte do usuário. s.teclado).16 Condições de erro Para determinar se um erro ocorreu utiliza-se a função ferror(). Para isso utiliza-se a função perror() em conjunto com a função ferror(). t). /* imprime na tela */ } A formatação realizada para leitura e escrita de dados pode comprometer a velocidade de processamento do programa. “%s %d”. Sintaxe: void perror (const char *str). 15.”w”))==NULL) { printf(“Arquivo nao pode ser aberto\n”).impressora paralela). (saída padrão . FILE *stream).tela). &t).17 Streams Padrão Sempre que um programa é iniciado três streams padrões são abertas automaticamente: • • • • • stdin stdout stderr stdaux stdprn (entrada padrão .10 na leitura de variáveis pelo teclado. ferror() retornará um valor verdadeiro (não zero) e perror() imprimirá a seguinte mensagem Erro de Busca: Bad data A primeira parte da mensagem é fornecida pelo programa.2 redireciona a stdout para o arquivo chamado OUTPUT. /* le do arquivo */ fprintf(stdout. 15. Essas streams podem ser utilizadas normalmente para executar operações de E/S bufferizada. } fscanf(fp.tela). (saída de erro padrão . (saída auxiliar padrão . Sintaxe: FILE *freopen(const char *nomearq. s.

3 Tabela 15. 4. o qual é lido pelo teclado.18 Exercício: 1. Isto é.LINGUAGEM C #include “stdio. as quais estão descritas na tabela 15. cujo nome é fornecido pelo usuário. stdout). } 15. Faça um programa que verifique se o número de abre-chaves corresponde ao número de fechachaves de um arquivo de programa fonte C.19 Sistema de Arquivo tipo UNIX Como C foi originalmente desenvolvida sobre o sistema operacional UNIX.3 .H em muitas implementações.Funções de E/S tipo UNIX sem buffer Nome open() close() read() write() lseek() tell() unlink() Função 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 posição de arquivo Apaga um arquivo do diretório O arquivo-cabeçalho usado pelo sistema de arquivo tipo UNIX é chamado IO. “w”. Para as operações em disco utilizam-se algumas funções especiais.H (definição de algumas macros). Faça um programa que gere um novo arquivo com registros ordenados (crescente) pelo código de um arquivo. freopen(“OUTPUT”. gets(str). Faça um programa que leia 11 números de um arquivo. A diferença está no fato que tanto a leitura como a gravação são realizadas sem buffer. ela inclui um segundo sistema de E/S com arquivos em disco que reflete as operações em disco de baixo nível do UNIX. 2. char idade. 99/105 . A estrutura do arquivo é: struct reg { int cod. 3.h” void main(void) { char str[80]. printf(str). }. o programador fica com o trabalho de criar e manter o buffer de dados. printf(“entre com uma string: ”). Faça um programa que escreva os números de 0 a 10 em um arquivo. 15. Em algumas funções é necessário a inclusão do cabeçalho FNCTL. char nome[30].

O protótipo para open() é: Sintaxe: int open(const char *nomearq. O comando open() devolve um inteiro para i como descritor do arquivo para futuras operações no mesmo.12. 100/105 .1 open() Ao contrário do sistema de arquivos com buffer. onde nomearq é qualquer nome de arquivo válido e modo é uma das seguintes macros que são definidas no arquivo-cabeçalho FNCTL. } No exemplo 16.h> #include <fnctl.O_RDONLY | O_BINARY)) < 0) perror(“Não posso abrir arquivo:”). nem todas podem existir.5.4 Modos de abertura de arquivos em baixo nível 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/gravação coloca o ponteiro de arquivo no fim dele cria um novo arquivo para gravação (não faz efeito se o arquivo já existe) Abre e trunca umarquivo existente para tamanho 0 Abre um arquivo em modo binário Abre um arquivo em modo texto Os modos de abertura de arquivo em baixo nível são mostrados na tabela 16. A existência destas macros dependem do compilador.H. devem ser combinadas usando-se o operador bit-a-bit OR (|). /* identificador do arquivo /* definição do buffer */ */ if((i=open(“teste. char buff[512]. Exemplo 15. mas descritores de arquivo do tipo int..19.12 #include <io. Tabela 15. .h> main() { int i. é mostrado a abertura de um arquivo somente para leitura (O_RDONLY) e binário (O_BINARY). Quando dois ou mais macros são utilizadas ao mesmo tempo. o sistema de baixo nível (sem buffer) não utiliza ponteiros de arquivo do tipo FILE. Algumas das macros listadas são mutuamente exclusivas.LINGUAGEM C 15.txt”.. int modo). por exemplo. não pode abrir o arquivo para somente leitura e somente gravação ao mesmo tempo. isto é.

const void *buf. const void *buf. Exemplo 15.303 101/105 .4 read() e write() Uma vez o arquivo aberto pela função open(). O descritor_de_arquivos deve ser um descritor de arquivos válido. A sintaxe para creat() é: Sintaxe: int creat(const char *nomearq. Caso contrário. A função close() devolve -1 se for incapaz de fechar o arquivo. O protótipo para a função write() é Sintaxe: int write (int fd. onde fd.2 creat() Se o compilador não permitir criar um arquivo novo com a função open() ou se quer garantir a portabilidade. O exemplo 15. 15. Para a leitura de dados tem-se a função read(). unsigned size). exceto pro read() colocar os dados do arquivo em buf.19. buf e size são os mesmos parâmetrosde write(). Ao chamar a função write() são escritos size caracteres no arquivo em disco especificado por fd do buffer apontado por buf. A função write() devolve o número de bytes escritos no caso de uma operação bem-sucedida. deve-se utilizar a função creat() para criar um arquivo novo para operações de escrita.LINGUAGEM C 15. int modo). unsigned size). Este programa lê linhas de texto.19.19. Sintaxe: int close(int descritor_de_arquivo). Os argumentos desta função seguem a mesma sintaxe da função open().13 mostra um programa que utiliza alguns aspectos da E/S sem buffer.3 close() A função close() libera o identificador ou descritor do arquivo para que ele possa ser reutilizado por outro arquivo. para escrever alguma informação utiliza-se a função write(). previamente obtido através de uma chamada open() ou creat(). ela devolve 0 se o final do arquivo for ultrapassado e -1 se ocorrerem erros. No caso de erro a função devolve EOF. Seu protótipo é: Sintaxe: int read (int fd. 15. O buffer pode ser uma região alocada na memória ou uma variável. escreve-as em um arquivo em disco e as lê de volta. e 0 caso contrário. No caso da operação ser bem-sucedido é devolvido o número de bytes lidos.

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

103/105 . Funções para manipulação de buffers Para trabalhar com buffers utilizam-se algumas funções especializadas que são independentes A função memchr() procura. long offset. O valor devolvido segue os valores da função strcmp(). size_t count). const void*buf2.19.LINGUAGEM C 15.6 lseek() e tell() Para o acesso aleatório as funções lseek() e tell() são as equivalentes em baixo-nível das funções fseek() e ftell() discutidas em alto-nível. size_t count). ´ ´. A função unlink() devolve -1 caso seja incapaz de excluir o arquivo. pela primeira ocorrência de ch nos primeiros count caracteres.h” void main(void) { char *p.19. Devolve um ponteiro para a primeira ocorrência de ch em buffer ou um ponteiro nulo se ch não for encontrado. onde nomearq é um ponteiro de caracteres para algum nome válido de arquivo. } A função memcmp() compara os primeiros count coracteres das matrizes apontadas por buf1 e buf2.5 unlink() Esta função é utilizada para excluir um arquivo. int ch. Os protótipos das duas funções são Sintaxe: long lseek(int fd. O protótipo da função é Sintaxe: int memcmp(const void*buf1. 15. exceto o primeiro argumento que é um identificador de arquivo e não um ponteiro FILE. onde os parâmetros são idênticos às esquivalentes em alto-nível. Exemplo 15. no vetor apontado por buffer. printf(p). 15. int origem).14). p = memchr(“isto e um teste”. O protótipo da função é Sintaxe: void *memchr(const void*buffer. Seu protótipo é Sintaxe: int unlink(const char *nomearq).7 de tipo. long tell(int fd).19.314 #include “stdio.h” #include “string.

h” #include “string. “Quando. printf(buf2). buf1.. buf1.17 /* Inicaliza com nulo os 100 primeiros bytes */ memset(buf. 10).h” #define SIZE 80 void main(void) { char buf1[SIZE]. no curso do . SIZE). no curso do . memcpy(buf2. 100). Exemplo 15. strcpy(buf1.”). size_t count). 104/105 .16 #include “stdio. ’\0’. /*do vetor apontado por buf */ /* Inicializa com X os 10 primeiros bytes */ memset(buf.”).h” #define SIZE 80 void main(void) { char buf1[SIZE]. “Quando. } A função memmove() copia count caracteres do vetor apontado por origem para o vetor apontado por destino. Ela devolve um ponteiro para destino. } A função memset() copia o byte menos significativo de ch nos primeiros count caracteres do vetor apontado por buf. porém origem será modificado. O protótipo da função é Sintaxe: void *memmove(void*destino. Exemplo 15. size_t count). Se as matrizes se sobrepõem. Ela devolve um ponteiro para destino. memmove(buf2. buf2[SIZE]. ’X’. Exemplo 15. const void*origem.. buf2[SIZE]. printf(buf2).. size_t count). const void*origem.LINGUAGEM C A função memcpy() copia os primeiros count coracteres do vetor origem para o vetor apontado por destino. é muito utilizado na inicialização de uma região de memória com algum valor conhecido.h” #include “string. a cópia ocorrerá corretamente. colocando o conteúdo correto em destino. int ch. O protótipo da função é Sintaxe: void *memcpy(void*destino. O protótipo da função é Sintaxe: void *memset(void*buf. printf(buf).. strcpy(buf1. SIZE). Ela devolve buf.15 #include “stdio.

1991. IBPI. Rio de Janeiro: IBPI. M. MIZRAHI. MURRAY. H.. et alli C++: Manual de referência completo. 1991. Rio de Janeiro: Campus. São Paulo: McGraw-Hill. B. São Paulo: McGraw-Hill. SCHILDT. V. Dominando a Linguagem C. ELLIS. H. C. 1993.LINGUAGEM C 16. São Paulo: Makron Books. Programando em C++. ECKEL. São Paulo: McGraw-Hill. 1991. São Paulo: McGraw-Hill. C Completo e total. 1991. Treinamento em Linguagem C. 1993. Turbo C++ completo e total. PAPPAS. Bibliografia BERRY. 1990. V. W. J. C++. A. 105/105 .

You're Reading a Free Preview

Download
scribd
/*********** DO NOT ALTER ANYTHING BELOW THIS LINE ! ************/ var s_code=s.t();if(s_code)document.write(s_code)//-->