Você está na página 1de 97

Programao Bsica em C

SUMRIO
SUMRIO................................................................................................................................. 2 1 INTRODUO.................................................................................................................... 6 1.1 Um Breve Histrico da Linguagem C ........................................................................ 6 1.2 Por que C?................................................................................................................... 7 1.3 Um Pouco de Terminologia........................................................................................ 8 1.4 O Que um Compilador? ........................................................................................... 9 2 O MUNDO UNIX LIKE................................................................................................ 11 2.1 Comando de Auxlio................................................................................................. 11 2.2 Comandos de Navegao e Controle de Diretrios .................................................. 12 2.3 Comandos de Manuteno de Arquivos ................................................................... 13 2.4 Recursos do Sistema ................................................................................................. 13 2.5 Impresso de Arquivos ............................................................................................. 14 2.6 Comandos Diversos .................................................................................................. 14 3 GNU gcc .............................................................................................................................. 15 3.1 Especificando o Arquivo de Sada............................................................................ 15 3.2 Somente Compilar, No Gerar Arquivo Executvel ................................................ 15 3.3 Solicitando uma Compilao com Verificao Completa de Erros ......................... 15 3.4 Biblioteca Matemtica .............................................................................................. 15 3.5 Gerando Informaes de Depurao......................................................................... 16 3.6 Outras Opes ?! Lembre-se Sempre do man .......................................................... 17 3.7 Outros Compiladores ................................................................................................ 17 4 A ANATOMIA DE UM PROGRAMA EM LINGUAGEM C...................................... 19 5 O PR-PROCESSADOR C.............................................................................................. 20 5.1 Definir Constantes Simblicas: #define ................................................................... 20 5.2 Cancelar uma Definio Simblica: #undef ............................................................. 20 5.3 Incluso de Arquivos: #include ................................................................................ 21 5.4 Contato Imediato com C ........................................................................................... 21
5.4.1 Primeiro Programa....................................................................................................................21 5.4.2 Segundo Programa....................................................................................................................23

6 TIPOS, OPERADORES E EXPRESSES... .................................................................. 24 6.1 Identificadores .......................................................................................................... 24 6.2 Tipos de Dados ......................................................................................................... 24 6.3 O Que So Variveis?............................................................................................... 25 6.4 Criando Variveis Imutveis (As Constantes).......................................................... 26 6.5 Classes de Armazenamento e Escopo das Variveis ................................................ 27 6.6 Converso Momentnea de Tipos (Casts) ................................................................ 29 6.7 Operadores Aritmticos, Lgicos e Relacionais....................................................... 29

7 ENTRADA E SADA......................................................................................................... 32 7.1 Entrada e Sada de Caracteres................................................................................... 32 7.2 Entrada e Sada de Cadeias de Caracteres (Strings) ................................................. 33 7.3 Entrada e Sada Formatada de Dados ....................................................................... 34
7.3.1 A Funo de Entrada Formatada scanf .....................................................................................34 7.3.2 A Funo de Sada Formatada printf ........................................................................................36

8 COMANDOS DE CONTROLE DE FLUXO.................................................................. 41 8.1 Comando if ............................................................................................................... 41 8.2 Comando if-else........................................................................................................ 41 8.3 Comando switch ....................................................................................................... 42 8.4 Comando for ............................................................................................................. 44 8.5 Comando while ......................................................................................................... 45 8.6 Comando do-while.................................................................................................... 46 8.7 Comando break ......................................................................................................... 46 8.8 Comando continue .................................................................................................... 47 8.9 Comando goto........................................................................................................... 47 9 MATRIZES, STRINGS, PONTEIROS E SIZEOF( ) .................................................... 49 9.1 Matrizes (Arrays)...................................................................................................... 49 9.2 Cadeias de Caracteres (Strings) ................................................................................ 50 9.3 Ponteiros ................................................................................................................... 51 9.4 Operadores Utilizados com Ponteiros....................................................................... 52 9.5 Aritmtica de Ponteiros ............................................................................................ 54 9.6 Ponteiros Constantes para char ................................................................................. 55 9.7 O Operador sizeof( ) ................................................................................................. 56 10 ALOCAO DINMICA DE MEMRIA.................................................................... 57 10.1 Alocao de Memria............................................................................................. 58 10.2 Liberao da Memria ............................................................................................ 58 11 FUNES .......................................................................................................................... 59 11.1 Anatomia de uma Funo ....................................................................................... 59 11.2 Prottipos de Funo .............................................................................................. 60 11.3 A Passagem de Parmetro(s) para as Funes........................................................ 60
11.3.1 11.3.2 11.3.3 Passagem por valor...........................................................................................................60 Passagem por referncia...................................................................................................61 Matrizes Passadas para Funes ..........................................................................................62

11.4 Recursividade.......................................................................................................... 63 11.5 Ponteiros para Funes ........................................................................................... 64 12 TIPOS DE DADOS COMPLEXOS OU DEFINIDOS PELO USURIO.................... 66 12.1 Estruturas ................................................................................................................ 66
12.1.1 12.1.2 12.1.3 12.1.4 12.1.5 Ponteiros para Estruturas .....................................................................................................68 Operadores de Seleo.........................................................................................................69 Estruturas Aninhadas ...........................................................................................................70 Matrizes de Estruturas .........................................................................................................71 Passando Estruturas para Funes .......................................................................................71

Joelson Coelho

Programao Bsica em C 3

12.2 Estrutura de Campos de Bit .................................................................................... 72 12.3 Unies ..................................................................................................................... 73 12.4 Enumeraes ........................................................................................................... 74 12.5 Definio de Novos Tipos ...................................................................................... 77 13 ARQUIVOS........................................................................................................................ 79 13.1 Funes Bsicas Para Manipular Arquivos ............................................................ 80
13.1.1 13.1.2 13.1.3 13.1.4 13.1.5 13.1.6 13.1.7 13.2.1 13.2.2 13.2.3 13.2.4 13.2.5 13.2.6 13.3.1 13.3.2 13.4.1 13.4.2 13.4.3 13.4.4 13.4.5 Abrir Arquivo: fopen().........................................................................................................80 Fechar um Determinado Arquivo: fclose() ..........................................................................81 Fechar Todos os Arquivos Abertos: fcloseall() ...................................................................81 Limpar ou Descarregar o Buffer de um Arquivo: fflush() ...................................................81 Limpar ou Descarregar Todos os Buffers de Arquivos: fflushall()......................................81 Detectar o Final de um Arquivo: feof() ...............................................................................82 Reposicionar o Ponteiro de um Arquivo: fseek().................................................................82 Ler um Caractere de um Arquivo: fgetc() ou getc().............................................................82 Escrever um Caractere de um Arquivo: fput() ou putc() .....................................................83 Ler uma Seqncia de Caracteres de um Arquivo: fgets()...................................................83 Escrever uma Seqncia de Caracteres de um Arquivo: fputs() ..........................................83 Ler Dados Formatados de Arquivo: fscanf() .......................................................................83 Escrever Dados Formatados em Arquivo: fprintf()..............................................................84 Ler uma Seqncia de Bytes de um Arquivo: fread()..........................................................84 Escrever uma Seqncia de Bytes em um Arquivo: fwrite() ...............................................84 Limpar Indicadores de Erro e de Fim de Arquivo: clearerr()...............................................85 Verificando a Ocorrncia de Erros: ferror().........................................................................85 Escreve Mensagem de Erro na Sada Padro: perror() ........................................................85 Descobrir Texto da Mensagem de Erro Relativa a um Cdigo: strerror() ...........................86 Exemplo de Cdigo Tratando Erro ......................................................................................86

13.2 Funes Bsicas para Entrada e Sada em Arquivos Texto.................................... 82

13.3 Funes Bsicas para Entrada e Sada em Arquivos Binrios................................ 84 13.4 Funes de Tratamento de Erros ............................................................................ 85

14 EXERCCIOS .................................................................................................................... 87 14.1 Seqenciais: ............................................................................................................ 87 14.2 Condicionais ........................................................................................................... 88 14.3 Repetio: ............................................................................................................... 89 15 ALGUMAS FUNES TEIS........................................................................................ 91 15.1 Funes de Controle de Fluxo ................................................................................ 91 15.2 Funes de Converso de ASCII para Binrio ....................................................... 91 15.3 Funes de Converso de Binrio para ASCII ....................................................... 92 15.4 Funes de Gerenciamento de Memria ................................................................ 92 15.5 Funes de Ambiente.............................................................................................. 92 15.6 Funes de Nmeros Aleatrios ............................................................................. 92 15.7 Funes Relacionadas com Tempos e Datas .......................................................... 92 15.8 Funes Manipuladoras de Strings ......................................................................... 93 15.9 Funes de Buffer................................................................................................... 94 15.10 Funes Matemticas............................................................................................ 95 REFERNCIA BIBLIOGRFICA...................................................................................... 97

Joelson Coelho

Programao Bsica em C 4

Joelson Coelho

Programao Bsica em C 5

1 INTRODUO
Seja bem-vindo ao mundo do C. Este captulo ir prepar-lo para o aprendizado e a utilizao desta poderosa, e cada vez mais popular, linguagem de programao. Mas e o que voc necessita para comear? Bom, em primeiro lugar voc precisa estar motivado, estar interessado. Mais do que voc j est; por isto lhe apresentaremos nos prximos pargrafos alguns dos aspectos mais atraentes desta linguagem. Segundo: voc precisa de um guia. Esta apostila ser uma base para tal, mas sempre recomendvel ter outras referncias para aqueles momentos confusos. Depois, voc precisa ter acesso a um equipamento com um compilador C instalado, o que no to complicado atualmente, considerando que existem compiladores C que rodam em PCs XT. No final desta introduo, daremos algumas dicas de como tirar o melhor proveito de um ambiente de programao mais comumente utilizado.

1.1 Um Breve Histrico da Linguagem C


Saber um pouco sobre o passado poder ajud-lo a melhor apreciar esta linguagem e por que ela evoluiu at a forma atual. A linguagem C foi projetada originalmente como um cdigo simblico para formalizar prticas de programao em uso na poca, em meados de 1970. Um pesquisador chamado Dennis M. Ritchie, que trabalhava nos laboratrios da Bell (Bell Labs - New Jersey/USA), criou-a em 1972 quando ele e Ken Thompson estavam desenvolvendo o sistema UNIX. O UNIX (uma verso monousuria do Multics) teve sua primeira implementao na mesma Bell em 1969, num computador hoje considerado modelo para estudos acadmicos, o DEC PDP-7 da Digital (atualmente Compaq). Na verdade a linguagem C no surgiu assim to de repente na cabea de Ritchie. Ela foi baseada na linguagem B, criada por Thompson, que se baseou na... Esta outra estria. O ponto mais importante que a linguagem C foi criada como uma ferramenta para programadores. Portanto seu objetivo ser o mais til possvel. Muitas linguagens se propem a ser teis, mas muitas delas tem outros aspectos. Um dos objetivos principais do PASCAL, por exemplo, prover os princpios bsicos para o aprendizado da programao de computadores. BASIC, por outro lado, lembra muito o ingls, e foi desenvolvida para ser facilmente aprendida por estudantes no familiarizados com os computadores. claro que estes tambm so aspectos importantes, mas no so sempre compatveis com as necessidades dirias dos programadores. Como sendo uma ferramenta para programadores, no entanto, C considerada uma linguagem bastante amigvel, como veremos.

Joelson Coelho

Programao Bsica em C 6

Em 1978, C floresceu e tornou-se a mais popular linguagem de programao de todos os tempos. Naquele ano ocorreu a publicao de C - A Linguagem de Programao, escrito por Brian W. Kernigham e Dennis M. Ritchie, que estabeleceu os padres pelos quais os compiladores C foram julgados por mais de uma dcada (o padro nomeado K&R C). C e UNIX esto intimamente ligados. A tal ponto que em todos os ambientes UNIX ela est presente. Contudo, no est restrita somente ao mundo UNIX. Este co-desenvolvimento deu ao C uma reputao de a linguagem de desenvolvimento de sistemas, pois til para escrever desde sistemas operacionais, compiladores, etc., at utilitrios. A partir de 1980, o UNIX passou a ter uma comercializao mais agressiva pela AT&T. No ano seguinte, a IBM lanou o PC. Com o lanamento da verso 2.0 do MS-DOS em 1983, que incorporou uma srie de conceitos do UNIX, a utilizao da linguagem C no mundo PC tornou-se cada vez maior. Basta citar, por exemplo, que alguns dos softwares best-sellers anteriores a 1983, tanto para o MS-DOS quanto para o CP/M, que foram escritos primeiramente em Assembly (dBASE II, dBASE III, WordStar, Lotus 1-2-3 V1.0, etc.) foram reescritos em C (dBASE III Plus, Lotus 1-2-3 V2.0, MS-Word, MS-Chart, etc.). Atualmente, temos ambientes RAD de desenvolvimento para linguagem C, como por exemplo, o C++ Builder da empresa Borland que est em sua verso 6.0 (igual ao Delphi, porm utilizando C/C++ ao invs de Object Pascal). Com o incremento da utilizao do Linux e do FreeBSD a difuso da linguagem est aumentando cada vez mais. A Borland promete para o 2 quarto deste ano a verso equivalente ao C++ Builder que completar o projeto Kylix.

1.2 Por que C?


C, pois: Tornou-se rapidamente em uma das mais importantes e populares linguagens de programao. Sua utilizao cada vez aumenta mais porque as pessoas a conhecem e adotam-na. Aps conhec-la mais intimamente, voc tambm ir reconhecer muitas de suas virtudes. Vamos mencionar algumas delas. uma linguagem moderna que incorpora caractersticas de controle que a teoria e a prtica da cincia de computao recomendam. O projeto do C torna natural para os usurios o uso da metodologia top-down, da programao estruturada e do projeto modular. Utiliza comandos de estrutura tais como while e for, para loops, ao invs dos comandos goto, que so facilmente mal utilizados e provocam a proliferao de bugs (erros). O resultado um programa mais fcil de entender e manter. uma linguagem eficiente, pois o seu projeto tira a mxima vantagem dos computadores atuais. O cdigo gerado tende a ser pequeno e rpido. uma linguagem portvel. Isto significa que programas escritos em C em um sistema ou ambiente operacional podem ser executados, com poucas ou nenhumas modificaes, em outros sistemas, bastando, para isso, compil-los novamente. a linguagem lder em portabilidade.

Joelson Coelho

Programao Bsica em C 7

Compiladores para C esto disponveis nos mais diversos tipos de computadores. Desde os de 8 bits at os mais avanados supercomputadores hoje existentes. poderosa e flexvel (as duas palavras mais favoritas na literatura da cincia da computao). Por exemplo, a maior parte do cdigo do poderoso e flexvel sistema UNIX escrito em C. Ela uma linguagem de propsitos gerais. Podemos utiliz-la para escrever desde jogos, programas comerciais, utilitrios, modelos matemticos e fsicos, processadores de textos, planilhas eletrnicas, compiladores, interpretadores, criao das seqncias de animaes em vinhetas, comerciais e filmes, como por exemplo O Retorno do Jedi, da srie Guerra nas Estrelas. Exibe alguns dos refinados controles usualmente associados com a linguagem Assembly. Se voc quiser voc pode fazer um ajuste fino no seu programa para obter a mxima eficincia. amigvel. Ela suficientemente estruturada para encorajar os hbitos da boa programao sem, no entanto, colocar o programador numa espcie de camisa de fora, cheio de restries.

Em reconhecimento ao crescente uso do C - e, talvez, pelo receio de que se perdesse o controle sobre o padro de fato que havia surgido - o Instituto Nacional de Padronizao Americano (American Standards National Institute - ANSI) criou e encarregou em 1983 o comit X3J11 de Linguagem de Programao C de adotar um rigoroso padro a ser seguido pelos implementadores. Aps cinco anos de exaustivos trabalhos e duelos de egos, o comit conseguiu o que era quase impossvel. Eliminou conflitos, particularidades e ambigidades da linguagem, adicionando alguns atributos especialmente selecionados, resistindo a tentao de satur-la com incontveis facilidades, como diversas correspondncias propuseram durante a avaliao. Alm do mais, C uma excelente base; depois de domin-la, voc no ter nenhuma dificuldade para aprender outras linguagens por conta prpria.

1.3 Um Pouco de Terminologia


Palavras-chave: so as palavras reservadas por uma determinada linguagem de programao. No C, por exemplo, as palavras while e for no podem ser usadas para propsitos particulares. Veremos que o nmero de palavras-chave ou reservadas bastante pequeno. Sintaxe: refere-se s regras que devemos seguir ao digitar os comandos. Siga religiosamente as indicaes da sintaxe, assim voc evita problemas. Semntica: o significado por detrs das regras de sintaxe. Algoritmos: so os mtodos de resoluo para os problemas. a descrio passo a passo para garantirmos a soluo do problema, normalmente escrito em pseudocdigo. Funes da biblioteca: so funes que estendem as possibilidades naturais de qualquer linguagem. No C, a biblioteca padro inclui uma srie de funes para a entrada e sada, para o manuseio de strings (cadeia de caracteres), para o tratamento de arquivos, para efetuar clculos matemticos, para gerenciar a memria, para executar chamadas do sistema e muitas outras.

Joelson Coelho

Programao Bsica em C 8

Pr-processar: uma etapa pelo qual o compilador C procura e substitui automaticamente determinadas informaes a partir de determinadas instrues especais (as para o pr-processador). Isto feito sem que o programador precise se preocupar. semelhante ao que fazemos num texto para procurar e substituir determinada seqncia de caracteres. Cdigo-fonte: o arquivo ASCII puro contendo os comandos e instrues que desejamos efetuar para resolver determinado problema ou executar uma tarefa especfica. Cdigo-objeto: contm as instrues do programa no seu formato bruto. Nada mais do que a substituio das nossas instrues colocadas no cdigo-fonte pelos respectivos comandos (ou seqncia destes) que a mquina capaz de compreender (linguagem de mquina). Cdigo-executvel: o resultado da link-edio de um ou mais arquivos e das bibliotecas contendo as funes utilizados pelo programa. Aps, feito alguns acertos de endereos e ento se tem o arquivo executvel (*.EXE). Tempo de compilao: o tempo necessrio para efetuar a compilao do programa. Os erros em tempo de compilao so os erros de sintaxe detectados durante a compilao. Tempo de execuo: o tempo durante o qual o programa est executando. Erros em tempo de execuo so erros de lgica, como, por exemplo, efetuar incorretamente um clculo ou exibir uma informao em local errado. Depurao: o processo de localizar e corrigir erros de execuo - os bugs. A verso do compilador que usaremos possui um depurador, includo no ambiente, que facilitar o processo. Pode ser usado para fazer um rastreamento na execuo de todo ou parte do programa, inspecionar e alterar o contedo de variveis em tempo de execuo e tambm marcar pontos de parada obrigatria - os breakpoints. LIB vs. DLL: ambas so bibliotecas. LIB a extenso usada para bibliotecas estticas, isto , so adicionadas ao programa executvel sempre que o programa a referenciar claro, uma vez em cada programa. As DLLs, como a prpria sigla indica, so bibliotecas de viculao dinmicas, isto , elas residem em um diretrio do sistema operacional (por exemplo, o SYSTEM do Windows 9X). L residem espera de que algum programa as invoque. Ou seja, se eu tenho 10 programas que utilizam a biblioteca xyz.dll, em nenhum deles existir a prpria DLL. Quando uma funo desta biblioteca for chamada, o sistema operacional que sabe onde ela est a carregar para a memria afim de que seja executado o seu cdigo.

1.4 O Que um Compilador?


O propsito essencial de um compilador seja qual for a linguagem, transformar os comandos simblicos em um programa acabado (veja a figura 1). O processo de produo de um programa executvel em C dividido em trs etapas. A primeira delas a criao do(s) arquivo(s) fonte(s). Neste(s) arquivo(s), colocamos definies e comandos. Para tanto, utilizamos qualquer editor de texto capaz de gravar no formato ASCII puro

Joelson Coelho

Programao Bsica em C 9

(sem comandos de formatao). No caso do C, existem dois tipos de arquivos-fonte: os *.H (cabealhos ou headers) e os *.C (corpo do programa). A segunda tarefa a compilao, o processo de traduo das instrues do(s) programas-fonte(s) para uma seqncia de comandos que a mquina consegue manipular; aqui so gerados os arquivos objeto (*.OBJ).
Fonte 1 *.C Fonte 2 *.C Fonte n *.C

Compilador C

Objeto 1

Objeto 2

Objeto n

Biblioteca Padro Link-editor Bibliotecas de Terceiros

Arquivo Executvel

Figura 1 Os passos para a gerao de um programa executvel em C.

A ltima fase a link-edio. A maioria das linguagens possui bibliotecas (funes prontas para utilizar). Como o C no possui nenhuma instruo ou palavra-reservada capaz de, por exemplo, fazer entrada e sada de dados, todos os servios so efetuados por um conjunto de funes que acompanham o compilador - a chamada biblioteca (*.LIB). O comit ANSI definiu uma srie de funes-padro, que todo compilador C deve possuir. No entanto, cada empresa acrescenta funes prprias. A maioria apresenta os mesmos servios, porm com funes de nomes diferentes (gotoxy - Borland e moveto Microsoft, que posicionam o cursor em uma determinada linha e coluna da tela). Para utilizarmos tais funes, basta cham-las, ou seja, mencion-las no nosso cdigo-fonte, passando, claro, todo o argumento necessrio para o seu funcionamento. O processo de linkedio a aglutinao do cdigo objeto gerado a partir de nosso programa (os *.OBJ) com os cdigos prontos de todas as funes da biblioteca que estamos utilizando (*.LIB). Aps esta etapa, temos o programa executvel, que poder ser executado em qualquer mquina para a qual foi compilado, com total independncia. No curso utilizaremos o compilador Turbo C verso 2.01 da empresa Borland International; um compilador leve que pode tranqilamente ser executado em XTs e tambm o GNU gcc.

Joelson Coelho

Programao Bsica em C 10

2 O MUNDO UNIX LIKE


Existem vrios sabores de UNIX disponveis atualmente no mercado. Alguns so pagos, e bem caros, alis. Outros so gratuitos, ou quase de graa, como o caso da distribuio brasileira mais conhecida do Linux, a Conectiva. Os sistemas UNIX so robustos, confiveis e muito eficientes no gerenciamento de tudo o que ocorre no computador. Como a maioria dos usurios que chegam a este novo mundo, todos enfrentamos as dificuldades do novo, da mudana. Mas, depois de conhec-lo e verificar as suas virtudes, rarssimas vezes nos decepcionamos. Os empreendedores da famosa empresa que gosta de ter tudo para si, espalham horrores de infmias pela net, visando a manter os seus rebentos presos nas suas prprias janelas. Mas basta um dia de peregrinao pela web para verificarmos que a diversidade de programas existentes para o mundo Linux, mais especificamente, aumenta em propores gigantescas, dia aps dia. E o que mais importante: so em sua grande maioria gratuitos, quando no disponibilizam o cdigo-fonte. A maioria das distribuies Linux instala o que l no DOS tnhamos de carregar opcionalmente: o DOSKEY. No Linux, portanto, j instalado automaticamente. Um outro recurso que auxilia em muito a digitao de comandos a possibilidade do autocomplemento do comando ou do nome do arquivo que se deseja trabalhar. Isto obtido atravs da tecla TAB. Digamos que se queira ver o contedo de um arquivo chamado teste.txt. Para tanto, usa-se o comando cat e digitaramos: cat t<TAB> cat teste.txt

Se, por um acaso, existirem mais de um arquivo comeando com a mesma letra, ento soaria um beep. Um segundo toque na tecla <TAB> far com que o sistema apresente na tela os arquivos cujo nome comece com a letra em questo (ou com as letras at ento digitadas). Bom, para desbravarmos este novo mundo operacional, que tambm tem janelinhas porm voc tem mais sabores a escolher, preparamos um guia de referncia rpido, com os principais comandos. CUIDADO !!! Assim como a linguagem C, os sistemas operacionais UNIX-like so sensveis ao caso, ou seja, fazem distino das letras maisculas das minsculas.

2.1 Comando de Auxlio


Todo sistema operacional UNIX tem o seu manual on-line, mais conhecido como man. Ele est disponvel para explicar o uso do sistema e seus comandos, inclusive os da linguagem C (C e UNIX

Joelson Coelho

Programao Bsica em C 11

so quase que um s). Para ativar o auxlio, basta digitar man seguida do identificador de comando ou de uma palavra na qual voc precisa de maiores informaes. A sintaxe do comando : man [options] command_name As opes mais comuns so: 1. -k keyword : lista um resumo do comando para todas as ocorrncias encontradas 2. -M path : path indica o caminho para encontrar as pginas do auxlio 3. a : mostra todas as pginas do manual com ocorrncias encontradas Um exemplo: man k password

2.2 Comandos de Navegao e Controle de Diretrios


O sistema de arquivos do UNIX construdo como sendo uma rvore que vai se preenchendo a partir da raiz, simbolizada pela barra (/). Os diretrios dos usurios e do sistema so organizados sob a raiz. No UNIX, os usurios no possuem diretrios raiz; eles geralmente se logam no seu diretrio prprio (lembrem-se que aqui o sistema multi-usurio) que est criado abaixo do diretrio /home. A tabela a seguir resume os comandos de navegao e controle de diretrios no Linux (a partir deste momento, vamos nos deter ao Linux, sem esquecer, porm, que ele tamb um sabor do UNIX).
Comando/Sintaxe cd [diretrio] ls [options][diretrio ou arquivo] mkdir [options] diretrio pwd rmdir [options] diretrio Qual o seu propsito Torna o diretrio como sendo o corrente Mostra o contedo do diretrio ou as informaes do arquivo. Cria o diretrio Mostra qual o diretrio corrente Remove o diretrio

Se voc estiver mais familiarizado com o MS-DOS, ento esta tabelinha vai lhe ajudar:
Ao Listar o contedo do diretrio Criar um diretrio Alterar o diretrio atual Remover o diretrio Retornar par o diretrio padro do usurio Localizao na rvore de diretrios Linux ls mkdir cd rmdir cd pwd MS-DOS DIR MD / MKDIR CD / CHDIR RD / RMDIR CD\ CD

Joelson Coelho

Programao Bsica em C 12

2.3 Comandos de Manuteno de Arquivos


Para criar, copiar remover e alterar permisses de arquivos voc utiliza os seguintes comandos:
Comando/Sintaxe chgrp [options] grupo arquivo chmod [options] arquivo/diretrio chown [options] proprietrio arquivo cp [options] origem destino mv [options] origem destino rm [options] arquivo/diretrioe Qual o seu propsito Altera o grupo do arquivo Altera as permisses de accesso do arquivo ou do diretrio Altera o proprietrio de um arquivo. Somente o super-usurio Copia o arquivo origem para o arquivo destino. Move o arquivo origem para o destino Exclui o arquivo ou o diretrio (-r exclui recursivamente o diretrio e o seu contedo) (-i pergunta antes de remover)

Se voc estiver mais familiarizado com o MS-DOS, ento esta tabelinha vai lhe ajudar:
Ao Copiar arquivo Mover o arquivo Renomear o arquivo Excluir o arquivo Visualizar todo contedo do arquivo Visualizar o contedo uma pgina por vez Linux cp mv mv rm cat more, less, pg MS-DOS COPY MOVE RENAME / REN ERASE / DEL TYPE TYPE /P

2.4 Recursos do Sistema


Para reportar e gerenciar os recursos do sistema voc utiliza os seguintes comandos:
Comando/Sintaxe date df du kill [options] pid# %job ps [options] Qual o seu propsito Verificar/Alterar a data e hora do sistema Visualisar um resumo da rea livre no disco Visualisar um resumo da rea em uso no disco Envia um sinal ao processo identificado por pid# ou job% Mostra os processos que esto atualmente em execuo na mquina

Joelson Coelho

Programao Bsica em C 13

who ou w bg fg

Mostra os usurios logados na sua mquina e os processos que esto executando. Coloca o ltimo processo disparado em execuo background Recoloca o processo em execuo foreground

2.5 Impresso de Arquivos


Para imprimir arquivos e gerenciar a fila de impresso do sistema voc utiliza os seguintes comandos:
Comando/Sintaxe lpq (lpstat) [options] lpr (lp) [options] arquivo lprm (cancel) [options] pr [options] arquivo Qual o seu propsito Verificar o estado das solicitaes ainda na fila de impresso Imprimir o arquivo usando a impressora especificada Remover uma solicitao da fila de impresso Filtra o arquivo e mostra-o no terminal

2.6 Comandos Diversos


Comando/Sintaxe grep / egrep/ fgrep [options] string arquivo(s) Qual o seu propsito Procura pela ocorrncia da string no(s) arquivo(s) especificados. Compara o arquivo1 com o arquivo2 e lista onde ocorrem as diferenas (arquivos texto ou binrios) Compara os dois arquivos e mostra as diferenas (somente arquivos texto) Cria o arquivo se este no existir. Altera a data da ltima utilizao do arquivo para date. Se no for fornecido date usa a data e hora do sistema. Procura por um arquivo.

cmp [options] arquivo1 arquivo2

diff [options] arquivo1 arquivo2

touch [options] date arquivo find [options] arquivo

Todos os comandos aqui apresentados possuem as suas prprias opes. Muitos dele possuem dezenas e dezenas de opes o que torna praticamente impraticvel a apresentao destas nesta apostila, uma vez que todas elas podero ser visualizadas on the fly pelo programador/usurio atravs do comando: man find, por exemplo. No se preocupe, com o tempo voc vai se acostumando com o ambiente e ficar tudo mais fcil, pois das dezenas de opes apresentadas para um determinado comando, utilizamos mais freqentemente 3 ou 4, no mximo.

Joelson Coelho

Programao Bsica em C 14

3 GNU gcc
O compilador de C para o Linux o comando gcc. Geralmente interessante saber qual a verso do compilador de que voc dispe para quando a soluo de algumas complicaes for feita utilizando-se dos recursos dos grupos de usurios de Linux disponveis na internet. Para tanto, digite: ~> gcc --version Na maioria dos UNIX o comando de compilao C o cc. No Linux, no entanto, os comandos cc ou gcc referem-se ao mesmo programa.

3.1 Especificando o Arquivo de Sada


O arquivo de sada padro do compilador o arquivo a.out, que armazenado no diretrio atual. Se voc quizer especificar o nome do arquivo de sada (executvel), coloque a opo: o <nome_arquivo>. Digamos que queiramos compilar o arquivo hello.c e gerar o arquivo executvel hello. Ento a linha de cmando ficaria assim: ~> gcc hello.c o hello

3.2 Somente Compilar, No Gerar Arquivo Executvel


Para somente compilar o programa, sem gerar a verso executvel do arquivo, voc deve utilizar o argumento c na linha de comando. Digamos que queiramos somente compilar o arquivo hello.c, ento devemos montar a linha de comando desta forma: ~> gcc hello.c c

3.3 Solicitando uma Compilao com Verificao Completa de Erros


Para compilar um cdigo-fonte solicitando para o compilador ser o mais rigoroso possvel com relao aos warnings e errors, devemos incluir a opo wall na linha de comando. Eis uma linha de comando deste tipo: ~> gcc hello.c c -wall

3.4 Biblioteca Matemtica


Nem todas as aplicaes desenvolvidas utilizam-se de funes matemticas avanadas. Por isso, o compilador C no inclui automaticamente a biblioteca math, mesmo que voc fornea o comando de #include <math.h> no seu cdigo fonte. Par, efetivamente, incluir a biblioteca matemtica no seu cdigo executvel, voc deve incluir a opo lm na linha de comando do compilador.

Joelson Coelho

Programao Bsica em C 15

~> gcc hello.c lm wall o hello

3.5 Gerando Informaes de Depurao


O gcc pode incluir informaes de depurao no cdigo executvel para que um programa de depurao consiga ligar as instrues geradas em linguagem de mquina ao cdigo-fonte. Para tanto, devemos incluir a opo g na linha de comando. Vamos criar um programa exemplo que vai facilitar o seu entendimento, chamaremos de bug1.c.
1. 2. 3. 4. 5. 6. 7. 8. 9. 10. 11. 12. 13. 14. 15. 16. 17. /* Exemplo de um programa contendo erro para depurao */ #include <stdio.h> #include <stdlib.h>

static void funcao1( void ) { char *ptr_c = 0; ptr_c = !; /* Aqui teremos o erro */ } int main( int argc, char **argv ) { funcao1( ); return( 0 ); } Cdigo 2.1 Exemplo cdigo com erro: bug1.c.

Um dos programas para depurao existentes no Linux o gdb e ele possui uma verso grfica tambm, chamada de kgdb. Vamos gerar o cdigo executvel. ~> gcc g o bug1 bug1.c Agora tente executar o arquivo. ~> ./bug1 <ENTER> (Note a presena do ./ no incio da linha) Dever, se tudo sair como eu planejei, a seguinte mensagem: Segmentation fault (core dumped) Isto significa que o seu programa gerou uma falha e que uma imagem da memria do sistema quando da ocorrncia do erro foi salva em um arquivo chamado core (use o cmando ls para certificar-se da existnncia dele: ls l core).

Joelson Coelho

Programao Bsica em C 16

Agora, vamos ao processo de depurao. Primeiro, para verificar a verso do gdb que voc possui aplique a mesma frmula usada no gcc, ou seja, passe o argumento -version, desta forma: ~> gdb version Agora para verificar informaes adicionais pos-morten sobre o erro gerado pela aplicao, use o seguinte comando: ~> gdb ./bug1 core Vai aparecer um texto explicativo sobre o gdb e logo a seguir informaes a respeito do arquivo core e da linha onde ocorreu o problema. Isto no a stima maravilha da humanindade, mas ajuda em muito a encontrar problemas. Quando nem o gdb ajudar, a meu amigo, o jeito embutir cdigo de depurao dentro do programa, tipo: passei por aqui... tudo bem!, ou qualquer outra mensagem que nossa v imaginao ainda puder gerar no momento de pnico, talvez at de dio. No adianta, o jeito relaxar e esfriar a cabea. O gdb tambm possui uma srie de comandos internos. Da mesma forma que os demais coamandos, use o comando man para buscar maiores informaes a respeito deles.

3.6 Outras Opes ?! Lembre-se Sempre do man


O compilador C presente no Linux considerado um comando do sistema, logo, tambm existem informaes a respeito de como utiliz-lo. Para acessarmos estas informaes, basta digitarmos a linha de comando: ~> man gcc

3.7 Outros Compiladores


Existem muitos outros compiladores de linguagem C disponveis no mercado; alguns so livres ou gratuitos. O Turbo C, que foi um dos precursores em ambientes integrados de desenvolvimento est disponvel no site da Community da Borland (http://community.borland.com), que exige o preenchimento de um cadastro rpido. Depois disso, libera o acesso a todo o site Borland Developer Network (BDN), contendo enorme quantidade de cdigos-fonte, artigos e downloads diversos. O Turbo C (disponvel no link http://community.borland.com/article/images/20841/tc201.zip) j faz parte do museu (http://community.borland.com/museum/). Basta baix-lo, descompacta-lo e executar o programa install.exe e seguir os menus. A figura 2 apresenta os principais elementos do IDE. O menu de comandos localiza-se na parte superior da tela. O menu acessado atravs da tecla de funo F10, ou ento, mantendo-se pressionada a tecla ALT e digitando-se a letra inicial dos comandos. Por exemplo, para acessar o (seta menu Options, basta digitar F10 e depois deslocar a barra de seleo, usando as teclas esquerda) ou (seta direita) - o menu circular - at a opo desejada (no caso, Options). Ou, se preferir, usando as chamadas teclas de atalho: ALT + O.

Joelson Coelho

Programao Bsica em C 17

Figura 2 O ambiente integrado de desenvolvimento do Turbo C.

Na parte de downloads da pgina da Borland (http://www.borland.com), mais precisamente na seo de downloads http://www.borland.com/products/downloads/download_cbuilder.html) voc encontra as verses livres do compilador de linha de comando C++ Builder e do Turbo Debugger. Tambm est disponvel o to aguardado ambiente de desenvolvimento C++ da Borland para o Linux. O C++ Builder agora parte integrante do projeto Kylix (em sua verso 3.0 voc pode escolher a linguagem C/C++ ou a linguagem Delphi antigo Object Pascal). A verso trial e a livre voc pode encontrar no link: http://www.borland.com/products/downloads/download_kylix.html. Outro ambiente de desemvolvimento para Linux o K-Develop, que est cada vez mais consistente e interessante. Vale a pena dar uma olhada no site http://www.kdevelop.org/.

Joelson Coelho

Programao Bsica em C 18

4 A ANATOMIA DE UM PROGRAMA EM LINGUAGEM C


Todo programa em C formado por uma ou mais funes. Podemos dizer que as funes se comparam aos tijolos de construo, ou seja, so os elementos bsicos na construo de programas em C. As funes so formadas por comandos de declarao de variveis, de atribuies, de controle de fluxo, comandos nulos e tambm comandos para efetuar chamadas de funes. Veja a figura a seguir.
Programa C Tpico #include #define main( )

Instrues para o pr-processador "main" sempre a primeira funo executada comandos

funo_1( ) comandos funo_2( ) comandos declaraes atribuio So 5 os tipos de comandos funes controle operadores nulos palavras-chave dados As funes so o bloco de construo da linguagem C Funes so compostas por comandos

Linguagem C
Figura 3 A anatomia de um programa em C.

A parte principal de qualquer programa em linguagem C uma funo chamada main. Esta funo a que recebe o controle do sistema operacional quando executamos um programa construdo em C. quem gerencia a execuo de todo o programa. Todo programa deve possuir uma e somente uma funo main. No prximo captulo veremos os comandos de pr-processador.

Joelson Coelho

Programao Bsica em C 19

5 O PR-PROCESSADOR C
C foi desenvolvida para suprir as necessidades dos programadores, e estes gostavam de prprocessadores. Antigamente este programa era separado do compilador; atualmente j fazem parte do compilador propriamente dito. Porm, tambm est embutido na maioria dos pacotes de desenvolvimento como um programa separado no Turbo C o CPP (C Pr-processor). Este utilitrio trabalha sobre o programa antes de envi-lo ao compilador (por isto so chamados pr-processadores) e, seguindo suas instrues, substituem abreviaes simblicas existentes no programa pelas diretivas que representam. A seguir veremos os comandos mais importantes.

5.1 Definir Constantes Simblicas: #define


A diretiva de pr-processamento #define, como todas as diretivas, comeam com o smbolo #. Pode aparecer em qualquer parte, valendo desde o seu aparecimento at o final do programa. A maior utilizao para este comando se d para definio de constantes simblicas, no entanto a sua utilizao pode ser ampliada. O #define uma espcie de procura e substitui existente na maioria dos editores de texto. Porm, o faz automaticamente antes de repassar o cdigo-fonte para o compilador, criando uma espcie de imagem, mantendo o programa-fonte inalterado. Pode tambm ser usado para definir macros. Uma macro se parece em muito com uma funo. Podemos passar parmetros para macros assim como para funes. No entanto, as macros so assim chamadas, pois cada vez que aparecem so substitudas pelo seu respectivo cdigo. As macros diminuem o overhead (trfego no sistema), comparando-as com as funes, entretanto aumentam o tamanho do cdigo executvel. Aguarde o exemplo no final do captulo para compreendermos melhor, por enquanto analise o fragmento de cdigo para o pr-processador C: #define #define #define #define #define #define #define DOIS QUATRO MSG01 QUADRADO( X ) MAIOR( X, Y ) VERDADEIRO FALSO 2 /* Podemos usar comentrios para explicar / (DOIS + DOIS) /* os comandos em C */ Pressione uma tela para continuar ... (X * X) /* isto uma macro */ ( X > Y ? X : Y ) /* isto tambm uma macro */ 1 /* C nao possui tipos booleanos */ !VERDADEIRO /* ou 0 (zero) */

5.2 Cancelar uma Definio Simblica: #undef


Como j diz o ttulo, a instruo #undef cancela uma definio criada com um comando #define. Trocando em midos: o #define cria uma macrosubstituio e o #undef, a invalida. A partir da linha contendo a instruo #undef, a constante simblica no ter mais validade.

Joelson Coelho

Programao Bsica em C 20

#undef VERDADEIRO #undef FALSO

5.3 Incluso de Arquivos: #include


Quando o pr-processador encontra uma diretiva #include ele entende como uma solicitao de mesclar, inserir um outro arquivo no programa. Esta insero se d no momento da compilao o programa fonte no alterado. Veja os exemplos: #include #include <stdio.h> meu_arq.h

Na primeira linha, o pr-processador procurar pelo arquivo cujo nome stdio.h no(s) diretrio(s) especificado(s) como de incluso l no menu Options-Directories. No padro, ele procurar no diretrio INCLUDE do seu compilador favorito. A segunda linha procura o arquivo especificado no diretrio corrente. Ento, lembre-se de que nomes de arquivos que estejam entre os sinais de < > so procurados no diretrio INCLUDE e os que aparecerem entre aspas so verificados no diretrio atual. Existem outras diretivas de pr-processamento, porm atualmente no se fazem normalmente necessrias. So elas: #if, #ifdef, #ifndef, #else, #elif e #endif. Falaremos sobre elas durante a explanao terica nas aulas. Agora, veremos um exemplo mais completo, com vrias instrues de pr-processamento.

5.4 Contato Imediato com C


A seguir veremos nosso primeiro programa em C. Para tanto, faa o login no Linux e entre no ambiente grfico (KDE, Gnome, WindowMaker, etc.) de sua escolha. Aqui no curso vamos padronizar o KDE para facilitar as coisas. No ambiente do KDE, temos um Editor Avanado, que possibilita a digitao de cdigos-fonte com o recurso de syntax hilight (processo de destacar com cores diferentes os componentes de um cdigo-fonte: identificadores, palavras-chave, etc.). 5.4.1 Primeiro Programa
01. 02. 03. 04. 05. 06. 07. 08. 09. 10. 11. 12. 13. /* Nosso primeiro programa em C */ #include <stdio.h> #define INCREMENTO 3 #define DECREMENTO 2 main( ) { int num; num = 1; printf( Eu sou um simples ); printf( computador.\n ); num = num * INCREMENTO; num = num - DECREMENTO;

Joelson Coelho

Programao Bsica em C 21

14. 15.

printf( Meu nmero favorito %d pois o primeiro.\n, num ); } Cdigo 5.1 Primeiro exemplo de programa em C.

Vamos fazer um passeio rpido por este exemplo para identificar seus elementos: A primeira linha do programa simplesmente um comentrio para efeitos de documentao interna, o que muito importante em todas as linguagens, porm em C essencial. A segunda, a terceira e quarta linhas indicam comandos de pr-processador (todos comeam pelo smbolo de cardinal - #). A segunda linha instrui ao compilador para incluir o arquivo de cabealho STDIO.H. Este arquivo possui todas as definies necessrias para fazer a entrada e sada (I/O) padro do computador. A terceira e a quarta linhas criam definies, uma espcie de constantes, chamadas de INCREMENTO e DECREMENTO, com valores 3 e 2 respectivamente. A quinta linha indica o incio do programa propriamente dito. Os programas em C so compostos por funes, como a maioria das linguagens estruturadas. Porm C possui uma peculiaridade: todo programa em C deve possuir uma, e s uma, funo com o nome de main. Este nome especial para indicar que esta a funo principal, que gerenciar a execuo do programa. A sexta linha apresenta somente o caractere abre chaves ({). Este smbolo para o C o que o begin para outras linguagens, ou seja, o incio de um bloco de codificao, no caso, o incio do corpo da funo principal (main). A stima linha mostra a definio de uma varivel, chamada num, como sendo inteira. Toda varivel deve ser declarada imediatamente no incio do corpo das funes, antes de qualquer utilizao. A oitava linha deixada em branco para simples questo de documentao. O compilador C ignora todos os espaos. Use e abuse desta facilidade. A varivel num inicializada na linha nove. Devemos proceder sempre a inicializao das variveis, pois o compilador C nem sempre o faz. Na linha 10, temos uma chamada de funo. A funo printf mostra mensagens na tela. No caso, mostrar a seqncia de caracteres entre as aspas. Continuamos apresentando mensagens tambm na linha 11. Repare que entre as aspas aparecem dois caracteres estranhos - \n. C uma linguagem que utiliza metasseqncias de caracteres para efetuar tarefas especiais, todas comeando pela contra-barra. Neste caso, solicitando uma quebra de linha ou linefeed. Agora temos operaes matemticas. A linha doze faz com que a varivel num seja incrementada de 3 unidades. Logo aps, na linha treze, recebe o seu valor anterior deduzida de 2 unidades. Na linha quatorze temos uma nova apresentao de mensagens usando a funo printf. Esta funo poderia ser traduzida para imprime mensagens formatadas na tela. Aqui aparece mais um

Joelson Coelho

Programao Bsica em C 22

conjunto de caracteres estranho - %d. Esta seqncia indica funo printf que ela deve inserir na mensagem o valor da varivel que est logo aps a prpria mensagem. A ltima linha o encerramento da funo principal. O smbolo fecha-chaves utilizado sempre para encerrar um bloco de cdigo ou uma funo. 5.4.2 Segundo Programa
01. 02. 03. 04. 05. 06. 07. 08. 09. 10. 11. 12. 13. 14. 15. 16. 17. 18. 19. 20. 21. 22. 23. 24. 25. 26. 27. 28. 29. 30. 31. 32. 33. 34. 35. 36. 37. 38. 39. 40. 41. /* Nosso segundo programa em C */ #include <stdio.h> #define VERDADEIRO 1 #define MAIS_UM( X ) (X+1) #define MAIOR( X, Y ) (X>Y?X:Y) #define Z80 1 #define M6502 2 #define I8086 3 #define I80386 4 #define COMPUTADOR I8086 main( ) { int num1, num2; #ifndef FALSO #ifdef VERDADEIRO #define FALSO #else #define FALSO endif #endif #if

/* incremento de um */ /* retorna o maior dos dois valores */ /* definio para micro Z-80 */ /* definio para micros Apple II */ /* definio para micros PC XT */ /* definio para micros AT 386 */ /* programa est ajustado para XT */

!VERDADEIRO 0

COMPUTADOR == Z80 num1 = Z; num2 = 80; #elif COMPUTADOR == M6502 num1 = M; num2 = 6502; #elif COMPUTADOR == I8086 num1 = I; num2 == 86; #elif COMPUTADOR == I80386 num1 = I; num2 == 80386 #else num1 = X; num2 = 9999; #endif printf( O meu computador utiliza o chip %c80%d\n\n, num1, num2 ); if( num2 == 86 || num2 == 386 ) { MAIS_UM( num2 ); printf(Utiliza o coprocessador %c80%d\n\n,num1, num2 ); } printf( Pressione <ENTER> para continuar ... ); getchar(); } Cdigo 5.2 Segundo exemplo de programa em C.

Joelson Coelho

Programao Bsica em C 23

6 TIPOS, OPERADORES E EXPRESSES...


6.1 Identificadores
Os identificadores so definidos como sendo os nomes utilizados para fazer referncia s variveis, funes, rtulos e vrios outros tipos de objetos definidos pelo usurio. Em C, um identificador pode ter no mnimo um caractere e o tamanho mximo depende da implementao do compilador. Normalmente, o comprimento limite de 32 posies. Isto no quer dizer que no possamos utilizar identificadores com mais de 32 posies. O tamanho livre, porm o compilador somente os diferencia at a 32a posio. Todos os nomes de identificadores devem seguir algumas regras: 1. Devem sempre iniciar com uma letra ou o sublinhado (underline - no recomendado); 2. Nas demais, so permitidos somente letras, nmeros e o caractere de sublinhado; 3. Ter tamanho mximo de 32 posies (pode ter mais, porm compilador distingue os identificadores somente at a 32a posio). Lembre-se tambm que C sensvel ao caso, ou seja, diferencia as letras maisculas das minsculas. Procure utilizar nomes indicativos, que possuem alguma informao implcita.

6.2 Tipos de Dados


A linguagem C est intimamente ligada ao computador hospedeiro, ou seja, mquina onde est sendo executado o compilador. Esto disponveis todos os tipos que o equipamento pode tratar. Os tipos bsicos da linguagem so o caractere - char, o inteiro - int, o ponto flutuante de preciso simples - float e o de preciso dupla - double. A estes tipos so adicionados alguns modificadores para alterar o tipo bsico, visando melhor adapt-lo s situaes. Os modificadores so: signed, unsigned, short e long. A seguir veremos os tipos que podem ser manipulados com suas respectivas caractersticas, lembrando que o computador em questo de 16 bits. O tamanho do tipo int est atrelado ao tamanho da palavra de processamento do processador, sendo assim, os processadores de 32 bis, como os Pentium e Athlon, possuem um inteiro de 32 bits, o short int possui 16 bits e o long int, 64 bits. Tudo isto, claro, se o seu compilador foi escrito para suportar tal arquitetura. Verifique na documentao do seu compilador para obter mais detalhes. Vejamos, ento a tabela dos tipos de dados para o compilador para um processador padro 8086/80286, como o caso do Borland Turbo C.

Joelson Coelho

Programao Bsica em C 24

TIPO DE DADO
unsigned char char short int unsigned int int unsigned long int long int float double long double

ESPAO OCUPADO
8 bits 8 bits 16 bits 16 bits 16 bits 32 bits 32 bits 32 bits 64 bits 80 bits

CAPACIDADE
0 a 255 -128 a 127 -32.768 a 32.767 0 a 65.535 -32.768 a 32.767 0 a 4.294.967.295 -2.147.483.648 a 2.147.483.847 +/-3.4 X 10 +/-1.7 X 10 +/-3.4 X 10
-38 +38 +308 +4932

a +/-3.4 X 10

-308

a +/-1.7 X 10

-4932

a +/-1.1 X 10

Tabela 8 Os tipos de dados da linguagem C.

6.3 O Que So Variveis?


Toda linguagem de programao necessita de algum lugar para armazenar o resultado de seus clculos ou simplesmente controlar o fluxo do programa. O gerenciamento feito pela prpria linguagem, em tempos de compilao e/ou de execuo. Uma varivel nada mais do que uma posio de memria do computador reservada exclusivamente para guardar informaes/dados. Esta posio de memria referenciada no programa atravs de um nome num1 e num2 no nosso exemplo anterior. O formato bsico da declarao de variveis : Tipo_de_Dado ou Tipo_de_Dado Identificador_1, Identificador_2, ..., Identificador_N; Identificador;

As variveis tambm podem ser inicializadas durante a sua criao, embora tenhamos algumas restries. O local onde aparece a declarao da varivel afeta a maneira como as outras partes do programa a encaram - veja classes de armazenamento e escopo, logo a seguir. Exemplos: char c_opmenu = A; int i_valor = 0; float f_salario = 1234.56; unsigned int ui_sopositivos;

Utilize identificadores sugestivos, que indiquem o contedo da varivel.

Joelson Coelho

Programao Bsica em C 25

Tome cuidado, pois a linguagem C sensvel ao caso e, portanto, os nomes num1, Num1, NUm1, NUM1, nUM1 e NuM1, por exemplo, so variveis totalmente distintas. Atente para o fato da linguagem C no possuir o tipo lgico. Para tanto se utiliza a seguinte conveno: Valor zero indica falso (todos os bits em 0) Valor diferente de zero indica verdadeiro (pelo menos um bit ligado)

Identificando alguns tipos de dados: A 32 32L 567893 032 0x32 caractere A ou ASCII( 65 ) /* repare os apstrofos */ inteiro inteiro longo explcito (note a presena do L) inteiro longo implcito (valor no pode ser armazenado em 2 bytes) inteiro em octal (pois precedido de 0) inteiro em hexadecimal (pois precedido de 0x ou de 0X zero xis)

6.4 Criando Variveis Imutveis (As Constantes)


s vezes interessante criarmos variveis cujo valor no pode ser mexido em nenhuma parte do programa. meio contraditrio: definir uma varivel cujo valor constante. Mas exatamente isto. Existe um modificador, o const, de variveis que as tornam imutveis, constantes. Quando este modificador usado, ningum poder atualizar, mexer, enfim, ter acesso para escrita na varivel. Um detalhe importante a ser observado que devemos atribuir-lhes valores na sua declarao, pois, se esquecermos de faz-lo, jamais poderemos uma vez que so imutveis. Isto , somente aceitam receber um valor na sua declarao, na sua criao. O formato bsico da declarao de variveis : const Tipo_de_Dado ou const Tipo_de_Dado Identificador_1 = contedo, Identificador_2 = contedo, ... , Identificador_N = contedo; Identificador = contedo;

Exemplos: const char letra_A = A; const double PI = 3.141592653; const int deiz = 10;

Joelson Coelho

Programao Bsica em C 26

6.5 Classes de Armazenamento e Escopo das Variveis


A classe de armazenamento precede a declarao do tipo da varivel e instrui ao compilador como este deve armazen-la. Os itens declarados com o especificador auto ou register possuem uma vida local. Os declarados com extern ou static possuem vida global. O formato bsico da declarao de variveis : Classe_de_Armazenamento Tipo_de_Dado Ou Classe_de_Armazenamento Tipo_de_Dado Identificador _1, Identificador _2, ... , Identificador _N; Identificador;

Exemplos: auto char c_opmenu = A; register int i_valor = 0; extern float f_salario = 1234.56; static unsigned int ui_sopositivos; Os quatros especificadores de classe de armazenamento afetam a visibilidade (ou escopo) de uma varivel ou funo, assim como sua classe de armazenamento. Visibilidade refere-se ao espao de programa-fonte no qual uma varivel ou uma funo pode ser referenciada. Os itens com vida global sobrevivem durante toda a execuo do programa, enquanto que aqueles que possuem vida local, perduram por um determinado perodo de tempo (enquanto o bloco de cdigo onde foi declarada estiver em execuo). CLASSE DE ARMAZENAMENTO
Automtica Registrador Esttica Externa Esttica externa

PALAVRA-CHAVE
auto register static extern (Veja observao) static

DURAO DA VARIVEL
Temporria Temporria Persistente Persistente Persistente

VISIBILIDADE (ESCOPO)
local local local global (a todos os arquivos do projeto) global (ao arquivo onde declarada)

Os itens acima da linha de separao so declaraes feitas dentro de funes. Os itens abaixo so declaraes feitas fora de funes. Observao: A palavra-chave extern usada somente para referenciar variveis que j tenham sido declaradas em algum local; o ato de declarar uma varivel fora de qualquer funo a torna externa aos elementos do mdulo e todas as funes do arquivo podem acess-la. Se um outro arquivo-fonte quiser acess-la, necessitar declar-la como externa. Veja a figura logo a seguir. Tabela 9 O escopo das variveis na linguagem C.

Joelson Coelho

Programao Bsica em C 27

As variveis declaradas dentro de uma funo so visveis somente nesta funo. Podemos, portanto, criar vrias variveis com o mesmo nome, porm dentro de funes diferentes. Sempre que uma varivel referenciada (utilizada) e no foi declarada dentro da funo, o compilador procura por uma definio global (fora de todas as funes). Se encontrar, tudo bem, seno, indica um erro (varivel no declarada). Existe ainda a possibilidade de declararmos dentro de uma funo uma varivel com o mesmo nome de uma outra global. Quando isto acontecer, o compilador utiliza, na funo, a declarao local. Se, por ventura, quisermos utilizar a varivel global, basta utilizar o especificador global (::) antes do nome da varivel. A posio da declarao de uma varivel ou funo dentro do arquivo-fonte tambm afeta a classe de armazenamento e a visibilidade. As declaraes feitas fora de qualquer funo so ditas declaraes de nvel externo, enquanto que aquelas feitas dentro das funes so chamadas de nvel interno. O significado exato de cada especificador de classe depende do nvel onde colocado e se a declarao de uma varivel ou de uma funo. Veja um exemplo que ilustra o que foi explicado anteriormente sobre as classes de armazenamento na figura de nmero 4, a seguir.

Fonte_1 e Fonte_2 so compilados juntos

Fonte_1.c int twit; static int tum; main( ) { --------------} figaro( ) { --------------}

Fonte_2.c extern int twit;

hedge( ) { --------------} mostly( ) { --------------}

twit conhecido (visto) por main( ), figaro( ), hedge( ) e mostly( ). tum conhecido (visto) somente por main( ) e figaro( ).
Figura 4 Exemplo de escopo de variveis.

Existe um quinto modificador de comportamento para variveis que o volatile. Este modificador evita que a varivel seja alocada em um registrador e que seja alvo de otimizaes. Adverte ao compilador que a varivel est sujeita a modificaes externas durante a sua utilizao. Logo, devemos ter muito cuidado e muita certeza ao utiliz-lo. Joelson Coelho Programao Bsica em C 28

6.6 Converso Momentnea de Tipos (Casts)


A linguagem C permite uma adaptao de tipos em tempo de execuo, para evitar conflitos em operaes matemticas, operaes com ponteiros, etc. Esta adaptao, uso de cast, nada mais do que a converso temporria do tipo de uma varivel em outro. O formato bsico dos casts o seguinte: (tipo_desejado) identificador ou (tipo_desejado) valor

Exemplo: int x = 9; float k = 0.0; k = (float) x; /* Converte o valor inteiro 9 em valor float 9.0 e armazena-o em k */ x = (int) 3.141; /* Converte o valor 3.141 para inteiro (3) e armazena-o em x */ Para usarmos o cast basta colocarmos o tipo desejado, entre parnteses, na frente da varivel ou da expresso que queremos adaptar. Imagine que tenhamos uma operao de multiplicao entre inteiros, que depois ter de ser multiplicado por um nmero real (float) e cujo resultado tenha de ser transformado em um inteiro longo. Assim, vejamos o fragmento de cdigo mostrado abaixo: long int k; float real; int meu_num; real = 3.141592653; meu_num = 5; /* CAST CAST */ /* | | */ k = ( long int ) ( ( ( float ) (meu_num) * 2.0) * real ); No fragmento acima, a varivel meu_num, definida como inteiro, continuar sendo inteira depois de executada a instruo, porm, na realizao do clculo para atribuio do novo valor varivel k, seu valor ser convertido de inteiro (2 bytes) para o tipo float (que ocupa 4 bytes). Todo o resultado da expresso, que resulta no tipo float, vai, depois de calculada, sofrer uma transformao para o tipo long int (que o tipo de k). Tudo isto para evitar conflitos entre tipos.

bastante til e deve ser amplamente utilizado quando trabalhamos com variveis de tipos diferentes, cujos espaos de armazenamentos so variados e dependentes da arquitetura hospedeira do compilador.
6.7 Operadores Aritmticos, Lgicos e Relacionais A linguagem C apresenta muitos operadores, que atuam exatamente da mesma forma que nas demais linguagens, e outros, que no fazem parte do acervo comum. Abaixo apresentamos uma tabela contendo todos os operadores aritmticos da Linguagem C.

Joelson Coelho

Programao Bsica em C 29

SMBOLO OPERADOR
+ /

OPERAO EXECUTADA
Adio Subtrao Multiplicao Diviso

EXPRESSO EXEMPLO
5+i x-y 22.3 f K/3

RESULTADO DA AVALIAO DA EXPRESSO


5 somado ao valor da varivel i o valor da var. x menos o valor da var. y 22.3 multiplicado pelo valor da varivel f O valor da varivel k dividido por 3 O valor de um inteiro dividido por outro inteiro truncado (22/3 = 7) Resto da diviso de inteiros; s funciona para inteiros. Inverso do sinal do valor contido na varivel k

OPERADORES M ATEMTICOS

Mod Resto da diviso Menos unrio

22 % 3 =1 -k

OPERADOR CONDICIONAL (?:) Condicional k = (c > 2 ? 1 : 0) S c for maior do que dois, ento k recebe o valor 1, seno, recebe zero OPERADORES BIT A BIT | & ^ ~ << >> OU bit a bit E bit a bit OU exclusivo Complemento de um Deslocamento esquerda Deslocamento Direita 1|2 =3 0xFF & 0x0F = 0x0F 0xFF ^ 0x0F = 0xF0 ~0x03 = 0xFC 0x0F << 2 = 0x3C 0x1C >> 1 = 0x0E Efetua uma operao OU bit a bit Efetua a operao AND bit a bit Efetua a operao OU-EXCLUSIVO bit a bit Inverte todos os bits 0 para 1 e 1 para 0 Efetua o deslocamento de dois bits esquerda (insere zeros direita) Efetua o deslocamento de 1 bit direita (incluindo zero(s) esquerda)

OPERADORES DE ATRIBUIO OP = Opera e atribui automaticamente Vale para todos os operadores acima Atribuio A += 3 X /= 7 + 2 A=A+3 X = X / (7 + 2)

x = k * 3;

Coloca o resultado da multiplicao da varivel k por 3 na varivel x

OPERADORES INCREMENTAIS E DECREMENTAIS ++Var Var++ Pr-incremento Ps-incremento ++A A++ Incrementa a varivel A e depois utiliza o valor de A Utiliza o valor da varivel A e depois incrementa o valor de A

Joelson Coelho

Programao Bsica em C 30

-- Var Var--

Pr-decremento Ps-decremento

--C C--

Decrementa a varivel C e depois utiliza o valor de C Utiliza o valor da varivel C e depois decrementa o valor de C

OPERADORES RELACIONAIS == != ! > < >= <= Igualdade No-igual Diferente Negao Maior Menor Maior ou igual Menor ou igual i == 3 j != 5 !2 (No 2) !0 (No 0) k>5 t<7 k >= 5 t <= 7 Ter valor 1(V) se i for igual a 3 Ter valor 0(F) se i for diferente de 3 Ter valor 1(V) se j for diferente de 5 Ter valor 0(F) se j for igual a 5 Ter valor 0 (!V -> F) Ter valor 1 (!F -> V) Ter valor 1(V) se k for maior que 5 Ter valor 0(F) se k for menor ou igual a 5 Ter valor 1(V) se t for menor que 7 Ter valor 0(F) se t for maior ou igual a 7 Ter valor 1(V) se k for maior ou igual a 5 Ter valor 0(F) se k for menor que 5 Ter valor 1(V) se t for menor ou igual a 7 Ter valor 0(F) se t for maior que 7

OPERADORES LGICOS && E k > 5 && t < 7 Ter valor verdadeiro se e somente se ambas as condies (k for maior do que 5 e t for menor que 7) forem satisfeitas Ter valor verdadeiro se pelo menos uma das condies (k for maior ou igual a 5 ou t for menor ou igual a 7) for satisfeita.

||

Ou

k>=5 || t <=7

Tabela 10 Os operadores da Linguagem C.

Joelson Coelho

Programao Bsica em C 31

7 ENTRADA E SADA
A entrada e a sada - E/S - de dados nos programas C efetuada por funes da biblioteca, uma vez que a linguagem no possui tais comandos (a diretiva ANSI manter a linguagem pequena e portvel). No entanto, temos um conjunto completo de funes de E/S na biblioteca padro definida pelo comit ANSI. O Turbo C segue o padro, possuindo todas as implementaes exigidas. A maioria das funes da biblioteca de qualquer compilador C exige que sejam fornecidos alguns tipos de dados e informaes de controle para o seu perfeito funcionamento. Tais informaes ficam armazenadas em arquivos separados, chamados de arquivos de cabealho (header files) - os *.H - que devem ser includos no programa atravs das diretivas #include do pr-processador. O Turbo C apresenta trs arquivos de cabealho para as funes de entrada e sada: stdio.h: todas as funes de E/S padro do C que utilizam bufferizao (padro); conio.h: todas as funes de E/S que acessam diretamente o console (MS-DOS); io.h: todas as funes de E/S de baixo nvel que efetuam a transferncia direta, sem buffer (UNIX).

7.1 Entrada e Sada de Caracteres


Para a leitura de caracteres, utilizamos as funes abaixo relacionadas: Bufferizada (aguarda pressionamento de <ENTER>) - devemos incluir stdio.h getchar() c = getchar(); /* Aceita tudo at detectar o <ENTER> */ No bufferizada - devemos incluir conio.h (natural do DOS, deve ser criada no Linux) getch() c = getch(); /* No mostra o caractere digitado na tela */ getche() c = getche(); /* Mostra o caractere digitado na tela */

Devemos tomar alguns cuidados quando utilizamos a leitura atravs de getchar(). Uma vez que a entrada bufferizada, necessrio pressionar o <ENTER> para que seja lido o caractere. No entanto, se for digitado mais de um caractere (o que freqente), a funo getchar() retira somente o primeiro. Os demais (vale tambm para o <ENTER>) ficam no buffer, o que s vezes faz com que sejam puladas as prximas leituras de caractere. Para contornar o problema utilize uma funo que limpa o buffer de entrada, chamada de fflush, aps a realizao de getchar(), assim: c = getchar(); fflush( stdin ); /* stdin o codinome da entrada padro (teclado) */ A funo getchar tambm capaz de realizar a leitura de caracteres diretamente a partir de um arquivo quando efetuamos o redirecionamento da entrada (programa < entrada.txt). Quando for assim utilizada, para informar o trmino do arquivo ela retornar o valor EOF, que o cdigo para final de arquivo. Utilize-o assim mesmo: EOF.

Joelson Coelho

Programao Bsica em C 32

A funo getchar(), por ser da biblioteca padro, no respeita as definies de cores feitas pelo usurio. Logo, se estiver trabalhando com cores, utilize getch() ou getche(). Para mostrarmos caracteres na tela utilizamos as funes abaixo: Biblioteca padro - devemos incluir stdio.h: putchar() putchar( A); ou putchar( 65 ); Biblioteca de console - devemos incluir conio.h: putch() putch( b ); ou putch( 96 ); Note que podemos fornecer tanto o caractere quanto o seu cdigo ASCII. Se houver redirecionamento de sada, ento a funo putchar() deve ser utilizada.

7.2 Entrada e Sada de Cadeias de Caracteres (Strings)


Para a leitura de strings devemos incluir o arquivo de cabealho stdio.h, o que possibilita a utilizao das funes abaixo relacionadas: Ler strings: gets() scanf() gets( var_string ); scanf( %s, var_string ); Possibilita leitura de espaos em branco. Encerra leitura ao encontrar o 1o separador.

Como voc observou nas observaes acima, existem diferenas no funcionamento das funes. Ambas so bufferizadas, o que significa que s encerraro a leitura quando for detectado o pressionamento da tecla <ENTER>. gets automaticamente substitui o <ENTER> pelo terminador (\0) e aceita espaos em branco e tabulaes. J a scanf, que uma funo curinga, capaz de ler vrios tipos de dados (note o %s - string) retorna somente o que foi digitado at o primeiro separador (um espao em branco ou tabulao), substituindo-o pelo terminador, o restante permanece no buffer. Em ambas as funes, lembrem-se de declarar sempre a string com uma posio a mais do que o necessrio, espao necessrio para o terminador. No existe um controle do tamanho, logo se voc declarar uma string com 10 posies, poder ler no mximo 9. No possvel controlar a quantidade de caracteres lidas com estas funes, logo podemos ter problemas, principalmente se for lida uma quantidade que extrapola o tamanho definido. Se isto acontecer, sero preenchidos os bytes consecutivos varivel, no importando se esto alocados para outras variveis ou no. Para escrever strings devemos utilizar as seguintes funes: puts() printf() puts( var_string ); ou puts (Ola mundo !); printf(%s, var_string) ou printf(Oi mundo!);

Joelson Coelho

Programao Bsica em C 33

As funes acima colocam na tela (ou em um arquivo - quando redirecionamento da sada) uma cadeia de caracteres. Se for o contedo de uma varivel, ambas mostraro todos os caracteres at que seja encontrado o terminador de string.

7.3 Entrada e Sada Formatada de Dados


As funes scanf e printf so funes da biblioteca padro responsvel pela entrada e sada formatada de dados, respectivamente. Formatada, pois respeitam uma definio de tipo e tambm porque fazem transformaes automticas de dados.

7.3.1 A Funo de Entrada Formatada scanf O formato da funo scanf sempre o seguinte: scanf( formato, argumento ); ou scanf( lista_identificadora_dos_formatos, lista_de_argumentos ); O formato, sempre como uma string, segue o seguinte esqueleto: % [*] [comprimento] [F|N] [h|l|L] caractere_identificador_do_tipo Cada especificao de formato comea pelo caractere de percentual. Aps, seguem em ordem: Caractere opcional supressor de atribuio: [*]; Definio opcional de tamanho: [tamanho]; Modificador opcional do tipo de ponteiro do argumento [F|N]; N = transforma o argumento em ponteiro para perto; F = transforma o argumento em ponteiro para longe; Modificador opcional do tipo de argumento: [h|l|L]; h = inteiro curto l = inteiro longo (se o identificador de tipo especifica um inteiro) l = real em dupla preciso (se o especificador de tipo for real) L = real longo em dupla preciso (vlido somente para especificadores de tipo real); Caractere identificador do tipo a ser lido (ver tabela abaixo):
IDENTIFICADOR ENTRADA ESPERADA TIPOS PARA NMEROS d D o O i I Inteiro decimal Inteiro decimal Inteiro octal Inteiro octal Ponteiro para inteiro Ponteiro para inteiro longo Ponteiro para inteiro Ponteiro para inteiro longo TIPO DO ARGUMENTO

Inteiro decimal, octal ou hexadecimal Ponteiro para inteiro Inteiro decimal, octal ou hexadecimal Ponteiro para inteiro longo

Joelson Coelho

Programao Bsica em C 34

u U x X e E F g G

Inteiro decimal sem sinal Inteiro decimal sem sinal Inteiro hexadecimal Inteiro hexadecimal Real - ponto flutuante Real - ponto flutuante Real - ponto flutuante Real - ponto flutuante Real - ponto flutuante

Ponteiro para inteiro sem sinal Ponteiro para inteiro longo sem sinal Ponteiro para inteiro Ponteiro para inteiro longo Ponteiro para real Ponteiro para real Ponteiro para real Ponteiro para real Ponteiro para real

TIPOS PARA CARACTERES


S C % Cadeia de caracteres (string) Caractere Caractere de percentual Ponteiro para um vetor de caracteres Ponteiro para caractere Ponteiro para caractere para armazenar o %

TIPOS PARA PONTEIROS


N Ponteiro para inteiro. Armazena o nmero de caracteres lidos com sucesso at o aparecimento deste %n. Ponteiro na forma hexadecimal: YYYY: ZZZZ ou ZZZZ %p converte o ponteiro para o tipo de ponteiro utilizado pelo modelo de memria especificado

Tabela 15 Identificadores de tipo na leitura de dados.

Campos de entrada podem ser qualquer um dos tipos abaixo: Todos os caracteres at o prximo caracter de espao(sem inclu-lo); Todos os caracteres at o primeiro que no puder ser convertido para o tipo especificado (como um 8 ou 9 quando solicitado inteiro em octal); At n caracteres, onde n o tamanho especificado. Existe a possibilidade de restringirmos a entrada de dados atravs do fornecimento de um conjunto de pesquisa, colocado entre colchetes. No entanto s valem para leitura de dados que sero armazenados em strings. Vejamos os exemplos: %[abcd] = procura por um dos caracteres a, b, c ou d no campo de entrada. %[^abcd] = procura por caracteres exceto a, b, c e d no campo de entrada. Podemos tambm utilizar a facilidade da definio de um intervalo de leitura. Se quisssemos restringir a leitura aos dgitos decimais poderamos fazer de duas formas: %[0123456789] = forma normal; %[0-9] = utilizando a facilidade do intervalo. Outros exemplos:

Joelson Coelho

Programao Bsica em C 35

%[A-Z] %[0-9A-Za-z] %[A-FT-Z]

para ler s as letras maisculas; para ler todos os dgitos decimais e todas as letras; para ler todas as letras maisculas de A at F e de T at Z.

Veja alguns exemplos onde o hfen no define o intervalo, mas sim o prprio hfen: %[-+*/] %[z-a] %[+0-9-A-Z] %[+0-9A-Z-] %[^-0-9+A-Z] para ler os 4 operadores matemticos; para ler os caracteres z, - e a; para ler + e -, intervalo de 0 a 9 e de A at Z; idem ao anterior; para ler todos os caracteres exceto + e -, e os intervalos de 0 9 e de A at Z.

A funo scanf ir encerrar a leitura de um campo, e comear a processar o prximo (se existir), quando: O caractere supressor de atribuio (*) aparecer na especificao de formato; o campo de entrada corrente lido, mas no armazenado; J foi lido a quantidade especificada de caracteres; O prximo caractere no pode ser convertido segundo o tipo especificado (por exemplo, uma letra quando o tipo for um nmero); O prximo caractere no aparece no conjunto (normal ou invertido) de pesquisa. Retorna: A quantidade de variveis de lidas, convertidas e armazenadas com sucesso; O EOF ao detectar o final de arquivo (quando do redirecionamento da entrada); 0 (zero) se nenhuma varivel foi lida. Exemplos: int var_i; float var_f; char var_str[50]; --scanf( %d %f, & var_i, &var_f ); scanf( %[^-0-9]s, var_str ); Veja tambm as variaes desta funo (cscanf, sscanf e fscanf) na biblioteca.

7.3.2 A Funo de Sada Formatada printf O formato da funo printf sempre o seguinte:

Joelson Coelho

Programao Bsica em C 36

printf( formato, argumento ); ou printf( lista_identificadora_dos_formatos, lista_de_argumentos ); O formato, sempre como uma string segue o seguinte esqueleto: % [flags] [comprimento] [.prec] [F|N|h|l|L] caractere_identificador_do_tipo Cada especificao de formato comea pelo caractere de percentual. Aps, seguem em ordem: Seqncia opcional de caracteres de sinalizao: [flags]: -: Alinha o resultado esquerda, preenchendo o espao restante direita com espaos em branco. Se no aparecer, o resultado vai ser alinhado direita, preenchendo o vazio esquerda com zeros ou brancos; +: Mostra o sinal do valor; branco: Mostra um espao em branco para os nmeros positivos e o sinal de - para os negativos; #: Especifica que o argumento deve ser convertido usando uma forma alternativa (veja a tabela abaixo das formas alternativas); Note que o sinal de mais (+) tem prioridade sobre o espao em branco, se ambos aparecerem. CARACTER DE CONVERSO c, s, d, i, u 0 x ou X e, E, f COMO O # (CARDINAL) AFETA O ARGUMENTO No sofre alterao. Um algarismo 0 (zero) preceder o argumento (quando este for diferente de zero). 0x (ou 0X) preceder o argumento. O resultado sempre conter um ponto decimal mesmo que o valor no possua casas decimais. Normalmente, o ponto decimal s aparece nestes resultados se um dgito o sucede. O mesmo que e e E, porm os zeros desnecessrios, predecessores ou sucessores, iro aparecer.
Tabela 16 Formas alternativas de converso.

g ou G

Definio opcional de tamanho: [tamanho]; n: Pelo menos n posies sero mostradas. Se o valor possuir menos do que n posies, o restante preenchido com brancos, respeitando a flag de alinhamento. 0n: Pelo menos n posies so mostradas. Se o valor possuir menos do que n caracteres, o espao esquerda sero preenchidos com zeros. : A lista de argmento fornece a especificao de tamanho, que deve preceder o argumento que est sendo formatado atualmente.

Joelson Coelho

Programao Bsica em C 37

Especificador opcional de preciso: [.prec]; no especificado: usa o padro: 1 para os tipos d,i,o,x e X; 6 para os tipos e, E e f; todos os dgitos significativos para os tipos g e G; todos os caracteres at o NULL para o tipo s; o tipo c no afetado pela preciso .0: usa o padro para os tipos d, i, o, u, x e X; para os tipos e, E e f o ponto decimal no mostrado; .n: n caracteres ou n casas decimais sero mostradas. Se o valor de sada possuir mais do que n caracteres, a sada ser truncada ou arredondada (dependendo do tipo de dado); : A lista de argumento fornece o especificador de preciso, que deve ser fornecido antes do argumento, preced-lo; Note que o fornecimento de uma preciso explcita de 0 (zero) casas decimais para os tipos inteiros (d, i, o, u, x e X) e o valor a ser mostrado vale 0 (zero), nenhum dgito ser mostrado (ser branco), como se no fosse apresentado. CARACTER DE CONVERSO d, i, o, u, x, X e, E, f g, G c s COMO A PRECISO (.PREC) AFETA A CONVERSO .n especifica que pelo menos n dgitos sero mostrados. Se o valor a ser impresso possuir menos do que estes n dgitos, o valor ser preenchido esquerda com zeros (0). .n especifica que n caracteres sero mostrados depois do ponto decimal, sendo que o ltimo dgito representa um arredondamento das demais casas (0-4 -> +0; 5-9 -> +1). .n especifica que, quando muito, n dgitos significativos sero mostrados. .n no afeta a sada em nada.. .n especifica que sero mostrados no mximo n caracteres.
Tabela 17 Modificando a preciso dos nmeros.

Modificador opcional do tipo de argumento: [F|N|h|l|L]; F= argumento lido como sendo um ponteiro longo; N = argumento lido como um ponteiro curto - NO deve ser usado no modelo de memria HUGE; h= argumento interpretado como sendo um inteiro curto para os tipos d, i, o, u, x ou X; l= argumento interpretado como sendo: um inteiro longo (para os tipos d, i, o, u, x ou X); um real com dupla preciso- double - (para os tipos e, E, f, g ou G); L= argumento interpretado como sendo um real com dupla preciso longo long double - (para os tipos e, E, f, g ou G);

Joelson Coelho

Programao Bsica em C 38

Caractere identificador de tipo a ser mostrado (veja a tabela a seguir):


Identificador Argumento de Entrada Tipos Para Nmeros d i o u x X f e E g Inteiro Inteiro Inteiro Inteiro Inteiro Inteiro Real - ponto flutuante Real - ponto flutuante Real - ponto flutuante Real - ponto flutuante Inteiro decimal com sinal Inteiro decimal com sinal Inteiro octal sem sinal Inteiro decimal sem sinal Inteiro hexadecimal sem sinal com as letras minsculas (a, b, c, d, e, f) Inteiro hexadecimal sem sinal com as letras maisculas (A, B, C, D, E, F) Valor real com sinal na forma [-]dddd.dddd Valor real com sinal na forma: [-]d.dddd e [+/-]ddd (exponencial) Valor real com sinal na forma: [-]d.dddd E [+/-]ddd (exponencial) Valor real tanto na forma e ou f, baseado no tipo do valor e na preciso: usa formato exponencial se valor for maior do que a preciso especificada ou se o valor for menor do que 4. Valor real tanto na forma e ou f, baseado no tipo do valor e na preciso, mas usa E para o expoente: usa formato exponencial se valor for maior do que a preciso especificada ou se o valor menor do que -4. Formato da Sada

Real - ponto flutuante

Tipos Para Caracteres s Ponteiro para a string Mostra todos os caracteres at que o terminador NULL (\0) seja encontrado ou tenha alcanado a preciso desejada Um s caractere Mostra o prprio caractere % Tipos Para Ponteiros n p Ponteiro para inteiro Ponteiro Armazena o nmero de caracteres escritos com sucesso at o aparecimento deste %n. Imprime o argumento como um ponteiro: ponteiros far: XXXX: XXXX ponteiros near: YYYY (somente o offset)

c %

Caractere

Tabela 18 Identificadores de tipo para a sada de dados.

No formato, podemos utilizar as seqncias de escape para efetuar algumas operaes especiais, como avanar para a linha seguinte. Lembre-se de que uma seqncia de escape considerada como sendo UM caractere simples, logo deve estar entre apstrofos.

Joelson Coelho

Programao Bsica em C 39

A tabela a seguir apresenta estes caracteres especiais. CONSTANTE \a \b \t \n \v \f \r \ \ \? \\ \0 \000 \xHH VALOR ASCII 0x07 0x08 0x09 0x0A 0x0B 0x0C 0x0D 0x22 0x27 0x3F 0x5C 0 000 0xHH SIGNIFICADO Alarme (beep) Retrocesso ou backspace Tabulao horizontal Nova linha Tabulao vertical Avano de formulrio ou formfeed Enter ou return Aspas () Apstrofo () Ponto de interrogao (?) Contra-barra (\) NULL (terminador de strings) Valor em octal Valor em hexadecimal

Tabela 19 Os caracteres especiais ou seqncias de escape.

Joelson Coelho

Programao Bsica em C 40

8 COMANDOS DE CONTROLE DE FLUXO


Em C, todos os comandos devem ser terminados com um ponto-e-vrgula. Por este motivo, dizemos que tal caractere um terminador de comando. As chaves, { e }, so usadas para delimitar um bloco de comandos, fazendo com que a linguagem veja o bloco como se fosse um comando simples; porm, nunca colocamos o ponto-evrgula aps o fechamento do bloco }. Note tambm que todas as condies que devero ser avaliadas nos comandos if, do e while, devem necessariamente aparecer entre parnteses.

8.1 Comando if
responsvel pela execuo condicional de um comando ou um bloco de comandos (sempre delimitados por { e por }). Se a condio for avaliada como sendo verdadeira, isto , resultar em um valor diferente de zero, o comando, ou bloco de comandos, ser executado. Sintaxe: ou if( <condio> ) { comando_verd_1; comando_verd_2; } if( K < 2 ) { y = 3; z = k - 4*y; } if( <condio> ) comando_verdadeiro; if( x == 10 ) y = 1;

8.2 Comando if-else


Estrutura de controle para executar um de dois comandos ou um de dois blocos de comandos exclusivos entre si. Se a condio de controle for avaliada como verdadeira, o comando - ou bloco de comandos - que segue o comando if executado. Caso contrrio, o comando - ou bloco de comandos - que segue o comando else, se existir, ser executado. Sintaxe: if( <condio> ) comando_verdadeiro; else comando_falso; if( c > 0 ) num = 1; else num = -1;

Ou

Joelson Coelho

Programao Bsica em C 41

if( <condio> ) { comando_verd_1; comando_verd_2; } else { comando_fals_1; comando_fals_2; }

if( c > 0 ) { num = 1; strcpy( txt, Pos); } else { num = -1; puts( Negativo!); }

O comando o mesmo que o if, pois a parte referente ao else opcional. Cada comando else referese estritamente ao ltimo comando if aberto. Veja o fragmento de cdigo a seguir: if( n > 0 ) if( a > b ) z = a; else z = b; O else refere-se ao ltimo if - if( a > b ). Se tal comando else fosse referente ao primeiro if, ento deveramos colocar o segundo if num bloco de comandos, desta forma: if( n > 0 ) { if( a > b ) z = a; } else z = b;

8.3 Comando switch


uma construo especial de deciso mltipla que testa o valor de uma expresso contra uma lista de constantes inteiras (ou de caracteres), desviando a execuo do programa de acordo com o resultado. Usado para fazer uma escolha dentre diversos valores apresentados, como em if-else aninhados. Lembramos mais uma vez que o resultado da expresso avaliada deve ser um valor inteiro. Sintaxe: switch( expresso ) { case const_1 : comando_1; comando_2; break; case const_2 : comando_3; comando_4; break; ... default : comando_5; comando_6; switch( x ) { case 1 : case 2: case 3: case 4: case 5: default: t = 3; break; t = 4; break; t = 2; v=x/4; break;

Joelson Coelho

Programao Bsica em C 42

} }

printf( X invalido!!! );

Tudo o que se faz com o comando switch pode ser feito com comandos if-else aninhados, porm o primeiro facilita a vida do programador. Observe, abaixo, a traduo do exemplo do comando switch, colocado direita da sintaxe do comando, para seqncias de if-else. if( x == 1 ) t = 3; else if( x == 2 || x == 3 ) t = 4; else if( x == 4 ) { t = 2; v = x/4; } else if( x == 5 ) v = x / 4; else printf( X invalido!!! ); O switch avalia a expresso inteira entre parnteses e compara o seu valor com todos os casos. Cada caso deve ser rotulado por uma constante do tipo inteiro ou caractere, ou ainda uma expresso constante. Se o valor da expresso for igual ao de algum caso, ento o programa continua a execuo no primeiro comando deste caso. Um caso rotulado como default opcional e executado somente se nenhum dos casos anteriores corresponder ao valor da expresso. Vejamos mais um exemplo de cdigo:
1. 2. 3. 4. 5. 6. 7. 8. 9. 10. 11. 12. 13. 14. 15. 16. 17. 18. 19. 20. 21. 22. main() /* Calculadora com 4 operaes */ { float oper1, oper2; char op; while( 1 ) { printf( "Digite operando1, operador, operando2\n" ); scanf( "%f %c %f", &oper1, &op, &oper2 ); switch( op ) { case '+' : printf( = %f, oper1 + oper2n2 ); break; case '-' : printf( = %f, oper1 - oper2 ); break; case '*' : printf( = %f, oper1 * oper2 ); break; case '/' : printf( = %f, oper1 / oper2 ); break; default : printf( "Operador desconhecido !" ); } printf("\n\n"); } } Cdigo 8.1 Exemplo de aplicao do comando switch.

Joelson Coelho

Programao Bsica em C 43

Note, no entanto, que para separar cada caso utilizamos o comando break, que fora a sada - o encerramento - do comando switch. Se tal comando no aparecer para indicar a finalizao de um determinado caso, o programa continua sendo executado, mesmo que os comandos sejam referentes ao caso subsequente. S ir encerrar a execuo de um determinado caso quando encontrar o comando break. Veja a construo abaixo: switch( expresso ) { case const_1 : comando_1; case const_2 : comando_2; case const_3 : comando_3; break; } Nesta construo, caso o resultado da avaliao da expresso for const_1, os comandos de 1 at 3 sero executados, pois no existe o comando break entre eles. Se o resultado for igual a const_2, ento os comandos 2 e 3 sero executados. Porm se o resultado for igual a const_3, somente o comando_3 ser executado. No utilize este truque de prolongamento dos casos no comando switch, exceto se voc tiver excelentes razes para faz-lo, pois esta tcnica induz um enorme potencial de erros e tambm considerada uma programao deselegante.

8.4 Comando for


um comando bastante prtico quando necessrio executar um ciclo de instrues um determinado nmero de vezes. A forma geral do comando a seguinte: Sintaxe: for( <inicializao>; <condio>; <atualizao> ) { j = 65; comando_1; comando_2; for( i = 5; i > 0; i-- ) { ... j += 2*i; comando_n; putchar( j ); } }

Em sua forma mais simples, a <inicializao> um comando de atribuio usado para inicializar a varivel de controle do lao. Pode-se inicializar mais de uma varivel, bastando, para tanto, separar os comandos por vrgulas. A <condio> uma expresso relacional para determinar se o lao ainda vlido (leia-se como enquanto a condio for verdadeira). A <atualizao> define a maneira com que ser atualizada a varivel que controla o lao. Da mesma forma que na inicializao, podemos alterar mais de uma varivel, separando cada um dos comandos por vrgulas. Veja o exemplo:
1. 2. 3. 4. 5. main( ) { int x, y; for( x = 0, y = 0; x + y < 100; ++x, y*=2 )

Joelson Coelho

Programao Bsica em C 44

6. 7.

printf( X = %-2d Y = %-2d X + Y = %-3d\n, x, y, x + y ); } Cdigo 8.2 Exemplo de aplicao do comando for.

No exemplo, ambas as variveis participam do controle do lao. Porm, o teste de controle do lao pode ser a verificao de uma outra situao qualquer, como por exemplo, o pressionamento de uma tecla (funo kbhit()). Na verdade, <condio> pode ser qualquer expresso vlida em C, o que possibilita uma total liberdade para o programador. Qualquer um dos trs componentes do comando for( ; ; ) pode ser omitido. Se <inicializao> ou <atualizao> forem omitidas, sero simplesmente desconsideradas. Porm, se a <condio> no se fizer presente, o lao ser considerado verdadeiro para sempre (vale 1 - verdadeiro). Assim, para construir um lao que executar para sempre, podemos usar a seguinte construo: for( ; ; ) { comando_1; comando_2; ... comando_n; } Um detalhe do comando for( ; ; ) que o teste verificado ao iniciar o lao. Isto significa que o cdigo dentro do lao no ser executado se a condio for inicialmente falsa.

8.5 Comando while


Tambm um comando de repetio. No entanto mais indicado quando no sabemos o nmero de execues que devero ser efetuadas do lao (quando isto factvel, prefervel utilizar o comando for). Da mesma forma que o comando for, o teste realizado antes de entrar no lao propriamente dito, ou seja, o lao pode ser executado 0 (zero) ou mais vezes. Novamente, <condio> qualquer expresso vlida em C, que resulte em 0 (falso) ou outro valor - geralmente 1 - (verdadeiro). Sintaxe: while( <condio> ) { comando_1; comando_2; ... comando_n; } i = 0; while( i < 5 ) { j+= 2; i++; }

Devemos garantir dentro do lao uma atualizao da(s) varivel(veis) que fazem o controle do lao, caso contrrio, teremos um lao infinito. No exemplo abaixo, a atualizao garantida, pois a cada execuo (antes de iniciar o lao) feita uma leitura do teclado. Se for detectado o pressionamento de uma tecla diferente do <ENTER>, os comandos do lao (no caso o comando count++) so todos executados uma vez, retornando, logo aps, o controle para o teste. Repare que o comando de leitura da tecla no a armazena, pois o intuito do programa contar o nmero de caracteres

Joelson Coelho

Programao Bsica em C 45

digitados at ser pressionado o <ENTER>. O aparecimento na tela do smbolo digitado providenciado pela prpria funo de leitura utilizada, getche().
1. 2. 3. 4. 5. 6. 7. 8. 9. main( ) { unsigned int count = 0; printf( Digite uma frase:\n ); while( getche() != 13 ) /* ASCII(13) == ENTER */ count ++; printf( \n A frase que voc digitou contem %d caractere%c., count, ( count > 1 ? s : ) ); } Cdigo 8.3 Exemplo de aplicao do comando while.

8.6 Comando do-while


O comando do-while a lgica reversa do comando while. A grande diferena entre eles que o primeiro ir efetuar o teste de validao do lao somente ao encerr-lo, o que implica na execuo de pelo menos uma vez todos os comandos. No esquea de incluir um comando para atualizar a(s) varivel(eis) que fazem parte da <condio> dentro do lao. Sintaxe: do { comando_1; comando_2; ... comando_n; } while( <condio> ); do { Mostra_menu( Arquivo ); res = Le_opcao( ); Executa( res ); } while( res != ESC );

No exemplo direita da sintaxe, temos um fragmento de cdigo que vai executar pelo menos uma vez. Chegando ao lao, a funo Mostra_menu( Arquivo ) disparada. Logo aps, chamada a funo Le_opcao( ), que devolve o valor lido para a varivel res. O ltimo comando do lao a execuo da opo selecionada pelo usurio, o que feito pela chamada da funo Executa( res ). Isto tudo efetuado enquanto a varivel res contiver um valor diferente de ESC (que pode ser uma varivel ou uma constante por #define). Tenha em mente de que tudo que foi feito com o comando for( ; ; ) pode ser feito pelo comando while( ). E que ambos podem ser reescritos utilizando-se o comando do-while( ), claro que com algumas pequenas adaptaes no cdigo.

8.7 Comando break


s vezes necessrio interromper incondicionalmente a execuo de um lao. Para tanto usa-se o comando break. Ao encontrar o comando o compilador encerra o lao e pula para executar o comando seguinte aps o lao. Usado em comandos for, do-while e while. Tambm usado em comandos de escolha mltipla ou seleo (switch - case).

Joelson Coelho

Programao Bsica em C 46

Sintaxe

break;

j = 0; for( i = 0;i < 5; i++ ) { if( j > 2 ) break; j++; }

8.8 Comando continue


Este comando desvia o programa para a linha onde feita a avaliao da condio para o lao (usado em comandos for, while e do-while). Sintaxe: continue; j = 0; for( i = 0; i < 5; i++ ) { if( i > 3 ) continue; j++; }

Este comando uma espcie de break condicional, ou seja, interrompe a execuo do lao se a condio de trmino j foi atingida, isto , o resultado da condio deixar de ser verdadeiro. Ateno!!! Quando utilizado em laos for( ; ; ), o comando continue desvia a execuo do programa primeiro para a atualizao da(s) varivel(eis) que aparecem como terceiro termo para, depois, efetuar o novo teste. Isto pode ser visto se executarmos passo-a-passo o exemplo direita da sintaxe do comando. Em laos do-while ou while ele simplesmente desvia o programa para o teste da condio.

8.9 Comando goto


Os devotos da programao estruturada sentem pavor quando algum menciona goto. Antes de lhes mostrar como funciona o comando, quero lhes recomendar que procurem evit-lo ao mximo. Se voc estiver sentindo a necessidade de utilizar o comando goto, descobriu que est na hora de reprojetar o seu cdigo. No h nada que um goto faa que no possa ser feito de maneira igual, ou melhor, utilizando um comando estruturado como while ou for. Sendo assim, voc deve estar se perguntando: Sim, mas por que ele existe ento?. Provavelmente, quando o C foi inventado, muitas outras linguagens de programao tinham um comando jump ou goto (ou uma outra instruo similar de salto) para espelhar comandos de controle similares em linguagem Assembly. Logo, nada mais natural do que C tambm possuir o seu goto, embora completamente desnecessrio. Suspeita-se que este comando foi includo na linguagem porque seria mais fcil justificar a sua presena do que a sua ausncia.

Joelson Coelho

Programao Bsica em C 47

Este comando destinado a alterar o fluxo seqencial do programa. Entretanto, ele pode ser utilizado de forma incorreta, tornando o cdigo completamente ilegvel (comumente denominado de cdigo spaghetti). O goto trabalha exatamente da mesma forma que em outras linguagens. Ele transfere a execuo para um outro comando do programa, que necessita ser identificado por um rtulo. Os rtulos so como valores em um switch, ou seja, seguidos do caracter dois-pontos (:). sintaxe: goto LABEL; if( x == 2 ) goto LBL_1; comando_1; comando_2; comando_3; LBL_1: t = (x % 4) * 5;

... LABEL : comando;

Vejamos ver um fragmento de cdigo exemplo de programao completamente no estruturada, um lao que utiliza comando goto.
int count = 1; TOP: printf( %d\n, count ); count++; if( count <= 10 ) goto TOP; Cdigo 8.4 Fragmento de cdigo mostrando o comando goto.

H algumas regras para utilizar este comando, como por exemplo, o fato de que no se pode saltar de uma funo para outra. Porm no vejo razo alguma para aprofundar a discusso sobre um comando que jamais ser utilizado na prtica. Na verdade, no lembro de ter usado tal comando, a no ser em exemplos para mostrar o seu funcionamento. Temos coisas mais importantes para discutir. A seguir veremos como construir funes em C.

Joelson Coelho

Programao Bsica em C 48

9 MATRIZES, STRINGS, PONTEIROS E SIZEOF( )


9.1 Matrizes (Arrays)
Podemos definir variveis organizadas (colees). Tambm so conhecidos por vetores ou matrizes, onde os elementos componentes da varivel so todos do mesmo tipo. Sua declarao segue o mesmo formato da declarao de variveis, porm acrescenta-se o nmero de elementos desejados em cada dimenso, colocando-os entre colchetes, assim: Tipo_de_Dado ou Tipo_de_Dado Identificador[ dim_1 ] [ dim_2 ] ... [ dim_n ]; /* Vetor(matriz-linha) com 15 inteiros */ /* Matriz de reais preciso simples - 3 lin X 3 col */ Identificador[ Num_colunas ];

Exemplo: int vet_int[ 15 ]; float mat_float[ 3 ][ 3 ];

Os elementos so enumerados a partir do 0 (zero), at o nmero especificado como quantidade subtrada de 1, logo: em vet_int: em mat_float: o primeiro vet_int[0] e o ltimo vet_int[14] o primeiro mat_float[0][0] e o ltimo mat_float[2][2]

Utilize os valores como se fossem variveis comuns, no esquecendo, para tanto, de fornecer o ndice desejado. Para utilizar o 5o elemento de vet_int em uma expresso, basta referenci-lo por vet_int[ 4 ]. Para as matrizes multidimensionais, voc dever fornecer quantos ndices forem necessrios para cobrir todas as dimenses. Para um matriz bi-dimensional, sero necessrios dois: a linha e a coluna do elemento desejado. Para acessar o 2o elemento da 3a linha, use: mat_float[ 2 ][ 1 ]. Tambm podemos inicializar as variveis multidimensionais quando de sua criao, como se fossem variveis comuns. Basta colocar os valores iniciais separados por vrgulas e entre chaves. Veja os exemplos: int ivetor[ 5 ] = { 1, 2, 3, 4, 5 }; float fmat33[ 3 ][ 3 ] = { { 1, 2, 3 }, { 4, 5, 6 }, { 7, 8, 9 } };

Joelson Coelho

Programao Bsica em C 49

Note que no segundo exemplo, os valores de cada dimenso so tambm delimitados por chaves, e cada dimenso separada da outra tambm por vrgulas. As matrizes bidimensionais so vistas pelo compilador como se fosse uma pilha de vetores. Apesar da linguagem C no ter problemas de tratamento com matrizes acima de 3a ordem, procure no utiliz-las ou restringir ao mximo, pois podem surgir confuses ao nvel do programador, uma vez que difcil representar graficamente tais variveis. Veja mais alguns exemplos: int mat_int[ 6 ][ 5 ] = { { 1, { 6, { 11, { 16, { 21, { 26, }; mat_int[2][3] vale: 14 mat_int[5][0] vale: 26 Diagrama da memria (supondo que mat_int inicie em 1000 e que o tipo inteiro ocupe 2 bytes): ELEMENTO mat_int[0][0] mat_int[0][1] mat_int[0][2] mat_int[5][2] mat_int[5][3] mat_int[5][4] ENDEREO 1000 1002 1004 1054 1056 1058 CONTEDO 1 2 3 28 29 30 2, 7, 12, 17, 22, 27, 3, 8, 13, 18, 23, 28, 4, 9, 14, 19, 24, 29, 5 10 15 20 25 30 }, }, }, }, }, }

Tabela 11 Diagrama de Memria para a varivel mat_int.

9.2 Cadeias de Caracteres (Strings)


A linguagem C no possui o tipo string. Todo o trabalho com strings feito utilizando-se um vetor de caracteres. Para definirmos uma string, usamos: char varivel [ Tamanho_necessrio + 1 ]; Exemplo: char msg[ 50 ]; /* define uma varivel para at 49 caracteres */ No exemplo acima, note que declaramos espao para 50 caracteres, porm s podemos utilizar 49 deles. necessrio reservar espao para um caractere especial que indica que a seqncia de caracteres (string) se encerrou. Este caractere o \0, que representa o NULL ou o ASCII de zero.

Joelson Coelho

Programao Bsica em C 50

Da mesma forma que as matrizes de valores numricos, vistos anteriormente, tambm podemos inicializar as matrizes de caracteres. Veja: char cstatus[ 60 ] = Mensagem que aparecer na linha de estado !; char cmsg[ 20 ] = { A, , M,e,n,s,a,g,e,m }; Cuidado: Lembre-se: A : caracter A ou o ASCII(65) - ocupa somente 1 byte A : string composta por A + ASCII(0) - ocupa 2 bytes

Necessitando de n posies, declare n+1, garantindo, assim, espao para o terminador.


Para tratar as strings em tempo de execuo, devemos utilizar funes especficas para tal. No podemos utilizar o sinal de adio (+) para concatenar strings, como em outras linguagens. Em C, para a mesma operao, temos de usar a funo chamada strcat. Para conhecer e saber mais sobre as funes de tratamento de strings d uma olhada, via HELP On Line (CTRL=F1 no Turbo C e man no Linux), no arquivo de cabealho string.h.

9.3 Ponteiros
Entender e usar corretamente os ponteiros so pontos cruciais para a criao de programas bem sucedidos em C. Existem motivos para isto: Os ponteiros fornecem as maneiras pelas quais as funes podem modificar o contedo de variveis locais das funes chamadoras; Os ponteiros servem para dar apoio s rotinas de alocao dinmica de memria; Os ponteiros podem substituir as matrizes para aumentar a eficincia.

Ponteiros so variveis que guardam como contedo um endereo de memria. Este valor pode ser o endereo de uma outra varivel, de um perifrico, etc. Sempre que uma varivel contiver um endereo de memria, dizemos ento que tal varivel aponta para determinada varivel ou perifrico - tornando-se ento um ponteiro. A forma geral da declarao de variveis ponteiros : Tipo_de_Dado_Apontado ou Tipo_de_Dado_Apontado Identificador _1, Identificador _2, ..., Identificador _N; Identificador;

Joelson Coelho

Programao Bsica em C 51

O Tipo_de_Dado_Apontado serve apenas para que o compilador saiba quantos bytes de memria ele ir utilizar ou referenciar sempre que utilizarmos a varivel ponteiro declarada. Note que estes valores so novamente dependentes da implementao do compilador e da mquina para o qual ele foi construdo. Exemplos: char *ptr_c = A; int *ptr_i; float *ptr_temp; unsigned int ptr_inicio;

9.4 Operadores Utilizados com Ponteiros


Existem dois operadores que so utilizados com ponteiros: o & e o (asterisco).

O & retorna (descobre) o endereo de memria da varivel que o sucede. O (asterisco) faz o uso (dizemos que referencia) do endereo de memria apontado pelo ponteiro. Vamos a um exemplo. Suponha que tenhamos uma varivel inteira xis, outra ypsilon e um ponteiro para inteiro ptr_i. Veja o cdigo:
int xis, ypsilon; int *ptr_i; ptr_i = &xis; xis = 10; ypsilon = *ptr_i; *ptr_i = xis+ypsilon; /* Coloca em ptr_i o endereo inicial na memria de xis */ /* Atribui xis o valor 10 - poderia ser escrito *ptr_i = 10 */ /* Atribui ypsilon o valor contido na memria apontada por ptr_i, */ /* que na verdade xis, ou seja, 10 */ /* Coloca no endereo de memria apontado por ptr_i */ /* (na verdade xis) o resultado da adio de xis e ypsilon (10 + 10 ) */ /* - igual a xis = xis + ypsilon ou ainda xis += ypsilon */ Cdigo 9.1 Exemplo de ponteiros.

Infelizmente o operador de dereferncia (ou que referencia posio de memria) - (asterisco) - o mesmo smbolo que indica a multiplicao. Ao escrever seus programas, tenha em mente que esses operadores no tem relao alguma. Tanto o & como o tem precedncia mais alta que todos os outros operadores aritmticos, exceto o menos unrio, com o qual se equiparam. Ponteiros podem ser utilizados em expresses. Logo poderamos adicionar as linhas abaixo ao cdigo apresentado acima. ypsilon = *ptr_i * 3 printf(Posio de xis na memria: [%p]. Valor de xis: %d\n, ptr_i, *ptr_i ); printf(Posio de ypsilon na memria: [%p]. Valor de ypsilon: %d\n, &ypsilon, ypsilon); Finalmente, como ponteiros so, de certa forma, variveis comuns, podemos fazer atribuies entre variveis ponteiros. Assim, se tivermos as variveis ponteiros ptr_1 e ptr_2, que apontam para o mesmo tipo de dado (digamos que ambos apontam para regies de memria onde esto ou sero

Joelson Coelho

Programao Bsica em C 52

armazenados floats), podemos faz-los apontar para a mesma regio atravs da seguinte linha de comando: ptr_1 = ptr_2. Veja o cdigo completo: float var_f = 15.50; /* Cria a varivel float var_f e atribui-lhe o valor 15.50 */ float *ptr_1, *ptr_2; /* Cria duas variveis ponteiro */ ptr_2 = &var_f; /* Atribui ptr_2 o endereo de memria de var_f */ ptr_1 = ptr_2; /* Atribui ptr_1 o valor de ptr_2 (&var_f) */ Existe uma correspondncia muito grande entre ponteiros e matrizes. Qualquer operao que se faz atravs dos ndices de uma matriz, pode ser feita utilizando-se ponteiros. Vejamos um trecho de cdigo: char string[ 50 ] = Ponteiros_e_Matrizes_so_semelhantes_!!!; char *ptr_c; ptr_c = string; Este trecho de cdigo declara uma cadeia de caracteres chamada de string e um ponteiro para caracteres ptr_c. Logo a seguir fazemos com que ptr_c aponte para o endereo de memria onde marca o incio de string (na verdade o 1o caractere de string). O primeiro caractere de string pode ser acessado de trs formas distintas: string[ 0 ] ou *ptr_c ou ainda ptr_c[ 0 ]

O dcimo primeiro caractere pode ser acessado por: string[ 10 ] ou *(ptr_c + 10) ou ainda ptr_c[ 10 ]

Isto vale tambm para matrizes de todos os outros tipos de dados. Veja o cdigo:
1. 2. 3. 4. 5. 6. 7. 8. main() { int i[5] = { 1, 2, 3, 4, 5 }, *ptr_i = NULL, t = 0; ptr_i = i; for( t = 0; t < 5; t++ ) printf(\n I[%1d] = %-3d, t, p[ t ] ); } Cdigo 9.2 Exemplo de ponteiros com vetores.

A linguagem trata os nomes de matrizes como se fossem ponteiros para o primeiro elemento que a compe. No entanto, tais ponteiros so fixos, ou seja, jamais podero apontar para outras regies de memria, como pode ser feito com as variveis ponteiro normais. Todo compilador cria no cdigo algo chamado de tabela de smbolos. O Turbo C no foge regra. Logo a declarao abaixo cria um ponteiro ptr_str fixo, ou seja, que jamais poder mudar o seu o seu contedo, caso contrrio perderia a referncia matriz de caracteres.

Joelson Coelho

Programao Bsica em C 53

char string[50] = Ol apaixonados pela linguagem C, tudo bem ?; char ptr_str = A linguagem C sada os seus admiradores.\n; Logo, jamais poderemos efetuar uma atribuio como a que segue: ptr_str = string; Como todas as variveis locais, as variveis ponteiro devem ser inicializadas antes de serem utilizadas. Se tentarmos utilizar uma varivel que no foi inicializada, corremos o risco de danificar uma rea de cdigo. Convencionalmente, devemos atribuir a um ponteiro que no aponta para lugar algum o valor NULL (seu valor definido na biblioteca C, normalmente zero), como mostrado abaixo. char *ptr_str = NULL; int *ptr_int = NULL;

9.5 Aritmtica de Ponteiros


O significado da adio ou da subtrao de um INTEIRO a um ponteiro simplesmente adicionar ou subtrair o espao de memria ocupado pelo tipo da varivel relacionado ao ponteiro (para o qual este foi declarado). Exemplo: Ento: unsigned int mat_uint[ 5 ] = { 5, 8, 31, 7, 18 ]; unsigned int *ptr_uint; ptr_uint = &mat_uint[0] equivale a ptr_uint = mat_uint;

Vejamos o diagrama da memria (supondo mat_uint iniciando em 630): ELEMENTO mat_uint[0] mat_uint[1] mat_uint[2] mat_uint[3] mat_uint[4] ptr_uint Partindo destas declaraes, observe: ENDEREO 630 632 634 636 638 802 CONTEDO 5 8 31 7 18 630

Tabela 12 Diagrama de memria da varivel mat_uint.

Joelson Coelho

Programao Bsica em C 54

EXPRESSO Ptr_uint *ptr_uint (ptr_uint+1) *(ptr_uint+1) *ptr_uint+1

VALOR 630 5 632 8 6

NOTAS Endereo do 1o elem. de mat_uint Valor contido na posio 630 Endereo do 2o elem. de mat_uint Valor contido na posio 632 (Valor contido em 630) + 1

Tabela 13 Expresses utilizando ponteiros.

Ponteiros e indexao de matrizes podem ser usados indistintamente. O nome de uma matriz atua como um ponteiro constante, que jamais poder fazer-se apontar para outra regio de memria. Exemplo: Logo: mat_uint[0] = 5 mat_uint[1] = 8 equivale a equivale a *(mat_uint) *(mat_uint + 1) que = 5 que = 8

mat_uint[ i ] equivale a *(ptr_uint + i )

9.6 Ponteiros Constantes para char


Podemos utilizar ponteiros para definir constantes de caractere. Por exemplo: char *ptr_c = ABCDEF; Este comando inicializa um vetor esttico (seu valor constante) na memria e inicializa o ptr_c com o endereo de onde esta seqncia de caracteres foi colocada na memria. Ou seja, faz com que ptr_c aponte para a string. Vejamos o diagrama de memria (supondo que a string foi colocada a partir do endereo 731):

Joelson Coelho

Programao Bsica em C 55

VARIVEL constante constante constante constante constante constante constante ptr_c As definies:

ENDEREO 731 732 733 734 735 736 737 800

CONTEDO ASCII CONTEDO REAL A B C D E F \0 No Aplicvel 65 66 67 68 69 70 0 731

Tabela 14 Ponteiro esttico para seqncia de caracteres.

char *ptr_c; char ptr_c[]; so equivalentes, logo: char *ptr_c = ABCDEF; equivale char ptr_c[] = ABCDEF; char ptr_c[7] = { A,B,C,D,E,F,\0 };

Ambas equivalem :

9.7 O Operador sizeof( )


O operador sizeof() calcula e retorna o nmero de bytes ocupados (veja o tipo size_t no help online) na memria pelo tipo que foi passado como parmetro. Sintaxe: ou sizeof( Varivel ); Exemplo: tam_int = sizeof( int ); tam_flo = sizeof( float ); tam_var = sizeof( xis ); tam_dist = sizeof( union distancia ); tam_md = sizeof( MALA_DIRETA ); tam_mst = sizeof( struct mystruct ); sizeof( Tipo_de_Dado );

Note que o operador sizeof() pode ser usado com qualquer tipo de dado nativo que j faz parte da linguagem - ou criados pelo usurio atravs das palavraschave struct, union e typedef - que sero vistas mais adiante no curso. O valor retornado est intimamente ligado ao tamanho dos tipos de dados que a mquina capaz de manipular.
Joelson Coelho Programao Bsica em C 56

10 ALOCAO DINMICA DE MEMRIA


Projetar um programa de computador de alguma forma parecido com o projeto de um prdio, com numerosas consideraes estticas e funcionais que contribuem para a construo final. Por exemplo, alguns programas so funcionalmente rgidos como uma casa, que possui um certo nmero de quartos, uma cozinha, dois banheiros, e assim por diante. Outros programas devem ser abertos e livres como os centros de convenes, que possuem paredes mveis e teto modular, permitindo que estes se adaptem a todas as situaes ou necessidades. Apresentaremos aqui os mecanismos de armazenamento que permitiro a voc escrever programas flexveis que se adaptem s necessidades do usurio e capacidade do computador. Existem duas maneiras pelas quais um programa C pode armazenar informaes na memria principal do computados. A primeira usar varivel global e local - incluindo matrizes (vetores) e estruturas (ser abordado no captulo 10). Com as variveis globais, a capacidade de armazenamento fixa durante toda a execuo do programa. Com as variveis locais, os dados so armazenados no espao reservado para a pilha. Apesar de as variveis locais e globais serem eficientemente implementadas e montadas em C, elas requerem que o programador saiba com antecedncia a quantidade de memria necessria para todas as situaes possveis. A segunda e mais eficiente maneira de se armazenar informaes usar as funes de alocao dinmica de memria: malloc(), calloc(), free(), etc. O mtodo de alocao dinmica utiliza a rea de memria livre que fica entre o espao ocupado pelo executvel (permanente) e a pilha, onde a linguagem C mantm as variveis locais. Esta rea chamada de heap. A pilha cresce de cima para baixo, ou seja, do maior para o menor endereo de memria. A quantidade de memria que ela necessita est diretamente ligada ao projeto do seu sistema ou programa. Por exemplo, um programa repleto funes recursivas demanda uma quantidade de memria para a pilha bem superior quela necessitada por um programa que no possui recursividade, pois cada nova chamada recursiva aloca novo espao de memria na pilha. J a memria necessria para o programa e para as variveis globais fixa durante toda a execuo do programa. A memria para satisfazer solicitaes de alocao dinmica obtida da rea de memria livre, comeando logo aps as variveis globais, indo at a pilha. Em casos extremos, possvel que a pilha entre no espao da heap, ou seja, cresa tanto que invada a rea da heap, gerando um problema chamado de stack overflow. Um exemplo prtico o caso das matrizes. Se voc declarar uma matriz com 10 (dez) linhas por 50 (cinqenta) colunas, para o compilador no vai interessar se voc utiliza somente 3 linhas e 5 colunas, o espao alocado vai ser sempre o mesmo, 10x50. O segundo mtodo que pode ser utilizado a alocao dinmica de memria, ou seja, o programa vai solicitando memria, medida que for necessrio, e devolvendo o espao alocado, quando este no for mais requisitado, para o sistema operacional.

Joelson Coelho

Programao Bsica em C 57

O responsvel pelo gerenciamento do espao da heap a dupla formada pelo programador e pelo Sistema Operacional. O verdadeiro gerenciador o programador. O Sistema Operacional o coadjuvante necessrio para fazer o interfaceamento homem-mquina. Todo o espao - ou recurso alocado por um programa deve ser desalocados no seu final, ou quando no forem mais necessrios. Isto implica que o programador deve prestar uma ateno especial sobre as operaes de solicitao e liberao de memria, seno corre o risco de ao tentar alocar no futuro receba uma resposta curta e grossa: NULL.

10.1 Alocao de Memria


A funo malloc solicita ao sistema operacional o nmero de bytes passado como parmetro, retornando um ponteiro do tipo void, pois ela uma funo da biblioteca capaz de alocar memria para qualquer tipo de varivel. Cabe ao programador forar uma tipagem do ponteiro retornado para o tipo de dado requerido (usando o cast). Para saber o espao necessrio para armazenagem, use o operador sizeof(). Veja a sintaxe e os exemplos: Sintaxe: ptr = malloc( ( size_t ) ( sizeof( Tipo_de_Dado ) * numero_elementos ) ); ptr = calloc( ( size_t ) numero_elementos, ( size_t ) sizeof( Tipo_de_Dado ) );

int *ptr_i; float *ptr_f; char *ptr_c; ptr_i = (int *)malloc( sizeof( int ) * 10 ); /* Aloca espao para 10 inteiros */ ptr_f = (float *)malloc( sizeof( float) * 5 ); /* Aloca espao para 5 reais */ ptr_c = (char *)malloc( sizeof( char ) * 25 ); /* Aloca espao para 2 caracteres - ltimo o \0 */ Cdigo 10.1 Exemplo de utilizao da alocao dinmica de memria.

10.2 Liberao da Memria


Quando no for mais necessrio o espao requisitado ao sistema, devemos devolv-lo para o sistema atravs da funo free(). Ao chamarmos a funo free, esta avisa ao sistema operacional que todo o espao usado a partir do endereo, passado como parmetro, est agora disponvel para uso e automaticamente atribui NULL ao ponteiro. Veja a sintaxe e a devoluo de todos os espaos alocados no exemplo anterior. Sintaxe: free( ptr ); free( ptr_i ); free( ptr_f ); free( ptr_c );

As funes malloc e free trabalham com ponteiros para quaisquer tipos de dados, tanto para os nativos da linguagem, como para aqueles criados pelo usurio. Lembre-se:

Quando o espao de memria alocado no for mais necessrio, devolva-o para o Sistema Operacional atravs do comando free.

Joelson Coelho

Programao Bsica em C 58

11 FUNES
Uma funo uma coleo de comandos identificada por um nome. Utilizar o nome de uma funo em um comando significa executar as suas instrues. As funes executam aes e podem retornar valores. Algumas linguagens possuem procedimentos e funes. A diferena bsica entre elas que os procedimentos no podem, por definio, retornar valores para que o disparou. No entanto, em C, temos somente funes, mas para tornar uma funo um procedimento fcil, basta faz-la no retornar valor. Algumas j vm prontas para o uso na biblioteca da linguagem C. Agora vamos criar as nossas prprias.

11.1 Anatomia de uma Funo


Voc j viu vrios programas que fazem uso das funes da biblioteca, como por exemplo, a getchar(), a scanf() e a printf(). Agora vamos ver como a anatomia de uma funo: Sintaxe: tipo_ retornado nome_da_funo( tipo par_1, ..., tipo par_n ) { declarao das variveis locais comandos } Onde: Tipo_retornado: pode ser qualquer um dos tipos que j vimos (int, short int, long int, float, char, char e seus respectivos ponteiros) ou ento void, que indica que a funo no retornar nenhuma informao (foi transformada em um procedimento). Tambm podemos retornar outros tipos de dados criados a partir dos tipos bsicos (structs, unions e enums). Nome_da_funo: obedece s mesmas regras dos nomes de identificadores, qual seja, iniciar por letra ou sublinha e ser seguido de letra, nmero ou sublinha. Distingue identificadores at a 32a posio. Tipo_par_?: se a funo recebe alguma informao para trabalhar, chamamos estes valores de parmetros, devemos declar-la. Cada parmetro deve ser declarado individualmente, separandoos por vrgulas. Para as funes que no recebem parmetros devemos declarar entre parnteses a palavra void. Os parmetros, na verdade, constituem-se de variveis locais da funo, e podem ser manipuladas como se fosse qualquer outra varivel. O compilador assume que toda funo que no declara explicitamente qual o tipo de valor que ser retornado retornar (por padro - ou default).

Joelson Coelho

Programao Bsica em C 59

Existe um comando que fora o retorno de uma funo: return. Este comando utilizado para finalizar uma funo, possibilitando que esta retorne um, e somente um, valor para quem a chamou (se foi declarado um tipo de retorno diferente de void).

11.2 Prottipos de Funo


O prottipo a repetio da declarao da funo, porm no necessita dos nomes das variveis locais que recebem os parmetros e encerra-se a linha com um ponto-e-vrgula, o que avisa ao compilador que o cdigo da funo est em outro ponto do arquivo. Devem ser colocados logo abaixo das instrues de #include. muito til criar um prottipo de todas as funes utilizadas nos programas. Isto ajuda o compilador a verificar se os parmetros que esto sendo passados para as funes esto de acordo com os tipos que elas esperam receber, isto , se estes no esto em conflito. Veja, abaixo, o prottipo para a funo soma_dois_val_int, mostrada h algumas pginas atrs: Prottipo: int soma_dois_val_int( int, int );

A construo do prottipo feita extraindo-se: 1. Tipo retornado pela funo; 2. Nome da funo; 3. Os tipos dos parmetros recebidos pela funo, entre parnteses; 4. Encerrando sempre com um ponto-e-vrgula. Existe uma palavra reservada, void, que indica um tipo indefinido. Se uma funo no deve retornar valores, ou seja, deve ser um procedimento, ento o tipo que deve preceder ao nome da funo void. Para as funes que no recebem parmetros devemos colocar entre os parnteses a palavra void.

11.3 A Passagem de Parmetro(s) para as Funes


11.3.1 Passagem por valor A linguagem C normalmente utiliza um sistema de passagem de parmetros denominada de chamada por valor. Isto significa que so fornecidas cpias dos valores dos parmetros na expresso que chama a funo. A funo no pode alterar o valor dos parmetros na rotina de chamada, pois estar trabalhando, na verdade, em cpias das variveis. Como so clones, tudo o que a funo fizer sobre elas no ter efeito sobre as originais. Vejamos o exemplo abaixo:
int soma_dois_int( int v1, int v2 ) { int ret = 0;

Joelson Coelho

Programao Bsica em C 60

ret = v1 + v2; return( ret ); } void main( void ) { int x, y, z; printf( Digite dois valores inteiros separados por espao em branco:\n ); scanf( %d %d, &x, &y ); z = soma_dois_int( x, y ); printf( \n\n%d + %d = %d\n, x, y, z ); } Cdigo 11.1 Exemplo da utilizao de funes.

Esta funo soma_dois_int recebe dois valores inteiros, um em v1 e outro em v2, soma-os, colocando o resultado em ret, e retorna o valor calculado. Para efetuar a chamada de uma funo usa-se: nome_da_funo( lista_de_parmetros ) No exemplo da funo acima, poderamos cham-la da seguinte forma: z = soma_dois_int( 5, 2 ); ou como aparece: z = soma_dois_int( x, y );

No primeiro exemplo de chamada, o valor 5 ser armazenado na varivel v1, local da funo, e o 2 ser colocado em v2. Qualquer alterao que for feita sobre v1 e v2, no influenciar os valores 5 e 2 passados como parmetros. Bom, mas o que acontece quando passamos as variveis, como no segundo exemplo? Acontece exatamente a mesma coisa! Digamos que a varivel x contenha 13 e que y contenha 4. O compilador ento ir transformar a chamada z = soma_dois_int( x, y ) em z = soma_dois_int( 13, 4 ). Logo, tudo o que se fizer dentro da funo soma_dois_int jamais afetar as variveis x e y.

11.3.2 Passagem por referncia A linguagem C permite a chamada por referncia. Este tipo de chamada possibilita que a funo que est sendo disparada possa alterar o contedo de variveis que foram declaradas pela funo que a chamou. A funo chamada recebe o endereo de memria (uma referncia) como parmetro. Ela necessita, portanto, declarar uma varivel ponteiro, pois estas guardam (apontam) valores numricos que indicam posies de memria.

Joelson Coelho

Programao Bsica em C 61

exatamente o que acontece quando utilizamos uma funo scanf, por exemplo. Ns necessitamos inform-la que os dados que sero lidos devero ser colocadas em variveis visveis funo chamadora. Para tanto, precisamos autorizar, fornecer para a funo scanf o local, o endereo de memria alocado para tal. Sendo assim, ao chamarmos a funo scanf, precedemos todos os identificadores das variveis que sero lidas pelo operador &. Veja:
1. 2. 3. 4. 5. 6. 7. 8. 9. 10. 11. 12. 13. 14. 15. 16. 17. void main( void ) { int i; float f; char c; printf( Digite um valor inteiro: ); scanf( %d, &i ); /* <----- Note o &i */ printf( Digite outro valor, mas pode ser real: ); scanf( %f, &f ); printf( Agora digite um caractere: ); c = getchar(); clrscr(); printf( O valor inteiro lido e o: %d\n\n, i ); printf( O valor real digitado foi o %f\n\n, f ); printf( O caracter digitado foi: %c\n\n, c ); } Cdigo 11.2 Exemplo da utilizao da passagem de parmetros por valor e por referncia.

11.3.3 Matrizes Passadas para Funes Como j vimos, C trata o nome de uma matriz ou vetor como sendo um ponteiro esttico - fixo, para o primeiro elemento. Isto significa que, quando passarmos uma matriz como parmetro para uma funo, o argumento passado como se fosse por referncia. Isto permite que a funo que recebe o parmetro est habilitada, tem a possibilidade, de alterar os valores desta matriz. Quando passarmos uma matriz com mais de uma dimenso para uma funo, devemos, na declarao dos argumentos especificar, sempre, o valor da ltima dimenso. No exemplo abaixo, declara-se uma matriz de inteiros sem sinal, chamado mat_si, que passada para a funo func_tal, que deve declarar o parmetro recebido, assim: Exemplo: signed int mat_si[5][4]; Chamada da funo: func_tal( mat_si ); Declarao da funo: <tipo> func_tal( signed int mat_si[][4])

Joelson Coelho

Programao Bsica em C 62

11.4 Recursividade
A linguagem C suporta rotinas recursivas. Uma rotina recursiva quando, no seu bloco de comandos, chamar a si prpria. Um exemplo simples de recursividade a funo fatorial, como veremos abaixo:
1. 2. 3. 4. 5. 6. 7. 8. 9. long int fatorial_r( int n ) { long int ret; if( n == 1) return( 1 ); ret = fatorial_r( n - 1 ) * n; return( ret ); } Cdigo 11.3 Exemplo de uma funo recursiva.

Todo algoritmo recursivo pode ser escrito de forma no-recursiva. Veja, a seguir, o cdigo da funo fatorial de forma no-recursiva:
1. 2. 3. 4. 5. 6. 7. 8. 9. 10. 11. 12. 13. long int fatorial_nr( int n ) { long int ret; if( n == 0 ) ret = 1L; else { ret = (long int) n; while( --n > 0 ) ret *= n; } return( ret ); } Cdigo 11.4 Exemplo da mesma funo fatorial, porm no-recursiva.

Quando uma funo chama a si prpria, o computador aloca memria aloca memria na pilha para as novas variveis locais e para os parmetros e executa o cdigo da funo com essas novas variveis desde o incio. Isto , uma chamada recursiva no faz uma nova cpia da funo. Apenas as variveis locais e os argumentos so novos. medida que cada chamada recursiva retorna, o computador remove da pilha as variveis locais e os parmetros antigos e prossegue executando a partir do prximo comando aps a chamada da funo. Como no existe uma economia significativa no armazenamento de variveis e tambm por tornar o cdigo executvel mais lento, no recomendamos sua utilizao. Um outro problema que pode ocorrer um estouro da capacidade da pilha; isto acontece quando a funo chama a si prpria inmeras vezes. Ao criar uma funo recursiva, voc deve colocar um comando if em algum lugar do corpo da funo com a misso de forar um retorno antes da prxima chamada recursiva da funo. Se isto no for feito a funo vai executar eternamente.

Joelson Coelho

Programao Bsica em C 63

11.5 Ponteiros para Funes


Os ponteiros normalmente endeream objetos, mas tambm podem enderear blocos de cdigo, como por exemplo, uma funo em memria. O programa pode utilizar o ponteiro para invocar a funo, uma tcnica extremamente til que permite aos programas atribuir diferentes endereos de funes a um determinado ponteiro, alterando com isso dinamicamente o programa em tempo de execuo. Sendo o nome de uma funo o eqivalente ao seu endereo (exatamente como no caso das matrizes), possvel ter-se ponteiros para funes. O cdigo comea por um pequeno truque, mas pode ser um recurso muito til. Veja a declarao a seguir: int (*fp)(); A linha acima declara fp como sendo um ponteiro para uma funo que retorna um inteiro. Se a funo no vai retornar valor algum, ento sua declarao deveria ser: void (*pf1)(); Logo, a declarao de ponteiros para funo segue o padro, ou seja: Tipo_retornado ( Identificador_ptr_funo )( );

Temos de ter muito cuidado, pois os ponteiros para funes s podem ser atribudos com o endereo de funes, o que pode ser feito de duas formas (lembrando novamente matrizes), como mostramos abaixo:
1. float power( int x, int y ) 2. { 3. float ret = 0.0; 4. 5. if( y == 0 ) 6. return( ret ); 7. else { 8. while( --y > 0 ) 9. ret *= x; 10. return( ret ); 11. } 12. } 13. float (*ptrf_power) (); /* Declarao do ponteiro para a funo power */ 14. float xis; 15. ptrf_power = &power(); /* Ou pode ser tambm ptrf_power = power; */ 16. /* A partir do aparecimento da ltima linha de cdigo podemos usar qualquer uma das chamadas abaixo */ xis = power( 5, 2 ); /* Ou */ xis = (*ptrf_power ) ( 5, 2 ); Cdigo 11.5 Exemplo de aplicao usando ponteiro para funo.

Joelson Coelho

Programao Bsica em C 64

Tome muito cuidado com a declarao dos ponteiros para funo, pois a falta dos parnteses envolvendo o asterisco e o nome do ponteiro para a funo modifica completamente a declarao. Veja: int (* f1) (); declara um ponteiro para uma funo que retorna um inteiro.

No deve ser confundido com: int *f1(); que significa que f1 uma funo que retorna o endereo de um inteiro.

Joelson Coelho

Programao Bsica em C 65

12 TIPOS DE DADOS COMPLEXOS OU DEFINIDOS PELO USURIO


12.1 Estruturas
Programas avanados necessitam de maneiras sofisticadas para representar os seus dados pois alguns problemas necessitam que seus itens de dados sejam agrupados. Tais itens de dados podem ser heterogneos, ou seja, de tipos diferentes. Por exemplo, uma estrutura pode definir um item de dado para representar um empregado, composto pelos seguintes itens: o nome, o endereo, o telefone, o cdigo do PIS/PASEP e outras informaes similares acerca do funcionrio. Estrutura uma definio que agrupa todos os itens separados sob um mesmo rtulo, no nosso exemplo o rtulo seria empregado. Uma estrutura , ento, um agregado de dados muito semelhante aos registros de dBase, Clipper e o record do Pascal. Uma estrutura uma coleo sistemtica de elementos que podem ser de tipos diferentes, incluindo ponteiros. Sintaxe: struct [ Etiqueta ] { TIPO campo_1; TIPO campo_2; ... TIPO campo_n; } [ varivel_tipo_estrutura ]; struct funcionario { char nome[51]; long int id_func; float salario; char fone[12]; unsigned char num_filhos; }; /* Isto define um novo tipo de dado */

A palavra reservada struct introduz a declarao de uma estrutura, que nada mais do que uma lista de declaraes entre chaves, ou seja, empacotadas. Podemos, opcionalmente, dar um nome para a estrutura, atravs da Etiqueta, que deve necessariamente estar imediatamente a seguir da palavra struct. Os elementos ou as variveis definidas entre as chaves so ditos membros da estrutura. O nome de um membro de uma estrutura pode ter o mesmo nome que outro membro de outra estrutura ou de uma varivel local ou global, pois sempre podem ser diferenciados pelo contexto. Logo aps o encerramento da estrutura, ou seja, do seu fecha-chave, pode vir uma varivel, ou uma lista de variveis, que ser(ro) do tipo da estrutura que est sendo definida; exatamente como na declarao usando um tipo bsico, isto , a declarao struct { . . . } x, y, z sintaticamente anloga int x, y, z;

Joelson Coelho

Programao Bsica em C 66

no sentido de que cada comando declara x, y e z como sendo variveis do tipo indicado e, como efeito, determina a alocao de espao de memria para as mesmas. O tamanho, ou espao, de memria necessria para a estrutura a soma dos espaos necessrios para cada um dos seus elementos. Porm, nunca tente calcular este valor, utilize sempre o operador sizeof(). Partindo do exemplo da estrutura funcionrio, definida anteriormente, para criarmos variveis, normais ou ponteiros, poderamos t-las listado entre o fecha-chaves e o ponto-e-vrgula logo na definio da estrutura; ou ento declar-las como segue: struct funcionario patrao, trabalhador, novo_func; /* Declarando variveis do tipo estrutura funcionario */ struct funcionario *ptr_func, *ptr_patrao, *ptr_novo; /* Declarando variveis ponteiro para estrutura funcionario */ Podemos omitir a Etiqueta ou a lista de Variveis_tipo_estrutura quando da declarao, mas no ambas simultaneamente. Se no declararmos uma Etiqueta, no poderamos fazer as declaraes das variveis e dos ponteiros mostrados agora h pouco, pois no teramos como referenciar a estrutura. Veja: struct ??? patrao, trabalhador, novo_func; /* Declarando variveis do tipo estrutura ??? */ struct ??? *ptr_func, *ptr_patrao, *ptr_novo; /* Declarando variveis ponteiro para estrutura ??? */ Logo, se no declararmos uma Etiqueta para a estrutura, teremos de definir todas as variveis desta estrutura quando da declarao da mesma. Por outro lado, se colocarmos a Etiqueta, poderemos declarar quantas variveis forem necessrias e em qualquer ponto do programa aps a definio da estrutura. A Etiqueta se faz imprescindvel quando necessitamos declarar, como membro, um ponteiro para a prpria estrutura. Veja o exemplo para a montagem de uma lista encadeada simples (onde cada elemento estrutura aponta paro prximo): struct lista_simples { unsigned int codigo; char nome[ 36 ]; struct lista_simples *proximo; }; Note que neste exemplo no foi criada nenhuma varivel de memria, pois para tanto, deveriam estar entre o fecha-chaves e o ponto-e-vrgula (terminadores da estrutura). Repare na declarao do ponteiro prximo. Se no tivssemos a etiqueta da estrutura, no teramos como defini-lo; saberamos apenas que um ponteiro para struct, mas para qual?

Joelson Coelho

Programao Bsica em C 67

Voltaremos a abordar mais sobre listas, filas, etc., em estruturas de dados ainda nesta apostila.

12.1.1 Ponteiros para Estruturas O C permite o uso de ponteiros para estruturas da mesma forma que para qualquer outro tipo de dado. Para declarar ponteiros para estruturas, basta colocar um na frente do nome da varivel, da mesma forma que feito para declarar ponteiros para outros tipos de dados. A sintaxe : struct [Etiqueta] Ptr_struct1, ..., Ptr_structn;

Veja alguns exemplos nas declaraes feitas anteriormente. Existe uma grande desvantagem na passagem de estruturas para funes: o esforo despendido para empilhar todos os seus componentes, fazendo com que a funo chamada disponha dos dados para trabalhar. Em estruturas maiores, que contenham matrizes ou muitos membros, o desempenho pode cair sensivelmente, chegando at a nveis inaceitveis, se chamarmos muitas funes passando como argumento a estrutura em questo. A soluo para o problema: usar a passagem por referncia, ou seja, s um ponteiro. Quando assim for utilizado, o computador somente empilha (e desempilha) o endereo da estrutura, o que significa que a chamada da funo se torna muito mais rpida. Como a funo estar referenciando a estrutura real, e no a cpia local, esta poder modificar os elementos da estrutura, o que, s vezes, indesejvel. Porm, programando com cuidado se consegue contornar o problema. Para trabalhar com ponteiros para estruturas, podemos referenciar variveis normais ou ento alocar memria na rea de alocao dinmica (Heap - mostrado logo abaixo). Vejamos os exemplos de declarao mostrados anteriormente: struct funcionario patrao, trabalhador, novo_func; /* Declarando variveis do tipo estrutura funcionario */ struct funcionario *ptr_func, *ptr_patrao, *ptr_novo; /* Declarando variveis ponteiro para estrutura funcionario */ Para fazer com que uma varivel ponteiro para uma estrutura receba o endereo de uma varivel estrutura, usamos o operador &, como foi utilizado para outras variveis. Partindo das definies acima, teramos: ptr_func = &patrao; claro que as variveis tm de ser do mesmo tipo, ou seja, no exemplo, do tipo struct funcionrio; a diferena, lgico, que uma ponteiro (aloca o espao s para o endereo) e a outra uma varivel comum (aloca o espao para todos os elementos da estrutura). Esta construo no muito

Joelson Coelho

Programao Bsica em C 68

elegante, ou seja, temos que alocar o espao para o ponteiro e para a varivel. Mesmo em variveis locais, ficam ocupando espao, mesmo depois de no serem mais necessrias, principalmente a varivel estrutura. A maneira mais elaborada de tratamento seria declarar ponteiros para a estrutura e alocar o espao necessrio para os elementos da estrutura na Heap (memria para alocao dinmica). Para tanto, depois de declarado o ponteiro, para a estrutura, usar ptr_novo, alocamos o espao para uma varivel estrutura, no exemplo struct funcionrio, atravs do seguinte comando: ptr_novo = (struct funcionario *)malloc( sizeof( struct funcionario ) ); Este comando solicita ao sistema operacional que aloque uma rea de memria suficiente o bastante para que caiba todo o elemento da estrutura. Se o sistema dispuser da quantidade de memria contgua solicitada (sizeof( struct funcionario ) ), retornar o endereo do incio desta rea demarcada. Caso no possua, retornar NULL. Quando esta rea de memria no for mais necessria, recomendamos liberar imediatamente o espao, atravs do comando: free( ptr_novo ); A instruo acima libera a rea de memria para onde apontava o ponteiro (ptr_novo) e atribui-lhe NULL. A seguir veja os operadores de seleo para manipular os elementos da estrutura.

12.1.2 Operadores de Seleo Cada membro da estrutura o equivalente a uma varivel simples de seu tipo. para referenciar um membro da estrutura podemos utilizar o . (ponto) ou -> (flecha direita, formada por um hfen seguido do sinal de maior). O smbolo a ser utilizado depender de como foi declarada a varivel. Se for uma varivel normal, ento usamos o ponto. Se for uma varivel ponteiro para a estrutura, ento usamos a flecha direita. Ponto (.): para acessar os elementos de uma varivel do tipo estrutura; Flecha direita (->): para acessar os elementos de uma varivel do tipo ponteiro para uma estrutura.

Partindo da definio: struct funcionario patrao; /* Declarando variveis do tipo estrutura funcionario */ Para atribuirmos valores, ou acessarmos, aos membros ou elementos salario e num_filhos da varivel patrao usaramos:

Joelson Coelho

Programao Bsica em C 69

patrao.salario = 1234.56; patrao.num_filhos = 2; Se a declarao fosse feita desta forma: struct funcionario *ptr_func, patrao; ptr_func = &patrao; /* Ou alocao dinmica - veja tpico anterior */ Uma vez alocado o espao para a varivel, para fazermos as mesmas atribuies aos elementos salrio e num_filhos, mostrados anteriormente, usaramos: ptr_func->salario = 1234.56; ptr_func->num_filhos = 2; Note que a nica alterao feita foi a troca do ponto (.) pela flecha direita (->).

12.1.3 Estruturas Aninhadas Podemos aninhar estruturas, ou seja, colocar uma estrutura dentro da outra, mas para tanto, a estrutura que estiver contida dentro de outra necessita, necessariamente, j estar definida. Veja um exemplo: struct sdata { unsigned char dia; unsigned char mes; unsigned int ano; }; struct agenda { char nome[ 36 ]; char fone[ 12 ]; struct sdata data_nasc; }; struct agenda ag; Para atribuirmos 05/NOV/97 para o elemento data_nasc da varivel ag, usaramos: ag.data.dia = 5; /* Acessou o dia */ ag.data.mes = 11; /* Acessou o ms */ ag.data.ano = 1997; /* Acessou o ano O raciocnio anlogo se usarmos ponteiros para estrutura dentro de uma outra estrutura. Devemos primeiramente alocar memria para o elemento. Muda, no entanto, o operador de seleo. Veja:

Joelson Coelho

Programao Bsica em C 70

struct agenda { char nome[ 36 ]; char fone[ 12 ]; struct sdata *ptr_dt_nasc; /* Agora um ponteiro para estrutura */ }; struct agenda ag; /* Primeiro alocamos espao na HEAP para um elemento sdata */ ag.ptr_dt_nasc = (struct sdata *) malloc( sizeof( struct sdata ) ); /* Agora podemos usar o elemento sdata */ ag.ptr_dt_nasc->dia = 5; ag.ptr_dt_nasc->mes = 11; ag.ptr_dt_nasc->ano = 1997;

12.1.4 Matrizes de Estruturas Uma vez definida uma estrutura, podemos declarar matrizes de tais tipos de dados. struct funcionario { char Nome[51]; long int id_func; float salario; char fone[12]; unsigned char num_filhos; }; /* Isto define um novo tipo de dado */ struct funcionario func[ 10 ]; A linha acima declara uma varivel, chamada func, capaz de conter 10 elementos do tipo struct funcionario. Para alterarmos o salrio do 5o elemento de func usamos: func[ 4 ].salario = 2345.67; E assim para os demais, ou seja, especificando o ndice antes do operador de seleo.

12.1.5 Passando Estruturas para Funes Quando voc usa uma estrutura como argumento de uma funo, o compilador C passa toda estrutura usando o mtodo padro, ou seja, passagem por valor. O que significa que qualquer alterao que seja feita no contedo da estrutura dentro da funo para a qual ela foi passada no afeta a estrutura que foi usada como argumento. A estrutura original se mantm intacta.

Joelson Coelho

Programao Bsica em C 71

12.2 Estrutura de Campos de Bit


Idem struct, porm voc pode definir o nmero de bits que cada um dos campos pertencentes estrutura vai ocupar. Podemos utilizar somente os tipos int e derivados ou char. Veja, a seguir, a sintaxe da definio de estruturas de campo de bit: Sintaxe: struct [ Etiqueta ] { TIPO campo_1 : nmero_de_bits_alocados; TIPO campo_2 : nmero_de_bits_alocados; ... TIPO campo_n : nmero_de_bits_alocados; } [nome_varivel_estrutura_de_bits];

A alocao de memria sempre feita em blocos mltiplos de 8 bits. Exemplo: struct mystruct { unsigned int unsigned int unsigned int unsigned int unsigned int } a, b, c; i : 2; j : 5; k: 1; : 4; m:4;

Aloca dois bytes e produz o seguinte layout: 15 14 13 12 11 10 9 8 7 k 6 5 4 3 2 1 0

< ------- m ------->

< -- no-usado ->

< ---------- j ------------>

< -- i -->

Figura 5 Layout (varia entre os compiladores) de uma estrutura de campos de bit. O layout est intimamente ligado arquitetura da mquina. Algumas ordenam os elementos da esquerda para a direita e outras fazem o contrrio (da direita para a esquerda), como no nosso exemplo. Para acessar os campos da estrutura de campos de bit usa-se os mesmos operadores das estruturas, dependendo de como foram declaradas as variveis. Um exemplo de utilizao de estruturas de campo de bit pode ser a declarao de uma estrutura com 1 byte, capaz de manipular 8 variveis lgicas (2 estados: V-1 ou F-0) ao invs de manipul-las separadamente, o que consumiria, no mnimo, 8 bytes.

Jamais poderemos utilizar o operador de endereo (&) em elementos de estruturas campos de bit. (xis = &a.m;)

Joelson Coelho

Programao Bsica em C 72

12.3 Unies
Uma unio uma estrutura especial com membros que se sobrepem. Esse comando se parece com uma struct, porm, sendo uma unio, os seus membros so colocados na mesma posio da memria, provendo interpretaes diferentes para as mesmas posies de memria. Permite que as mesmas localizaes de memria sejam referenciadas de mais de uma forma. Visa: Economizar espao com variveis estticas; ou Referenciar variveis de modo diferente da mquina. Sintaxe: union [Etiqueta] { TIPO campo_1; TIPO campo_2; ... TIPO campo_n; } [nome_varivel_unio];

A alocao sempre feita com respeito ao espao ocupado pelo maior tamanho de varivel encontrado nas definies dos elementos que compem a unio. Exemplo: union distancia { int milhas; long int metros; }; union distancia dist1, dist2, dist3; union distancia *ptr_d1, *ptr_d2; /* Tamanho da union = 4 bytes */ /* referindo-se ao maior tipo que */ /* o long int, que ocupa 4 bytes */ /* Declara variveis */ /* Declara ponteiros */

Tudo o que foi visto para estruturas vale para as unies, menos o que se refere ao tamanho. Nas estruturas o tamanho a soma do tamanho dos elementos que a constitui. Nas unies, o tamanho exatamente o espao necessrio para o maior tipo. Para acessar os campos da unio, utilizamos os operadores ponto e seta direita (exatamente da mesma forma que nas estruturas). Exemplo: dist1.metros = 35000; ptr_d1 = &dist1; ptr_dist1->milhas = 1210;

No momento que feita a ltima atribuio, perde-se o valor de metros, ou melhor, desfez-se, pois como eles compartilham o mesmo espao de memria, o contedo de metros agora totalmente diferente de 35000.
1. 2. 3. 4. 5. /* Exemplo de unies */ union demo { char inicial; int idade; float salario;

Joelson Coelho

Programao Bsica em C 73

6. 7. 8. 9. 10. 11. 12. 13. 14. 15. 16. 17. 18. 19.

}; void main( void ) { union demo pessoal; printf( Sizeof( union demo ) = %d\n, sizeof( union demo ) ); pessoal.inicial = A; printf( Inicial = %c endereco = %p\n, pessoal.inicial, &pessoal.inicial ); pessoal.idade = 35; printf( Idade = %d endereco = %p\n, pessoal.idade, &pessoal.idade ); pessoal.salario = 10800.00; printf( Salario = %.2f endereco = %p\n, pessoal.salario, &pessoal.salario ); } Cdigo 12.1 Exemplo da utilizao do tipo de dado union.

12.4 Enumeraes
Os computadores armazenam valores numericamente como colees de bits 0 e 1 em memria, mas muito difcil escrever programas de computador em nvel binrio. Em vez disso, mais claro e mais fcil representar os valores simbolicamente. Um programa grfico, por exemplo, deve especificar a cor de um objeto como um smbolo RED (vermelho), mas em memria, essa cor e outros atributos so representados numericamente. Smbolos corretamente escolhidos acrescentam clareza aos programas. Suponhamos que voc necessite armazenar o valor de uma cor como um inteiro. Voc definiria uma varivel int chamada cor: int cor, fundo; Os comandos podem atribuir valores varivel cor, porm constantes literais inteiras no teriam sentido, veja: cor = 3; fundo = 7;

Para uma maior clareza, poderamos definir algumas constantes simblicas que representam as cores: #define #define #define PRETO AZUL VERDE 0 1 2

Os valores so arbitrrios - poderiam ser quaisquer inteiros que o compilador ou a linguagem entendesse como sendo identificadores de cores. Logo, aps esta definio poderamos usar:

Joelson Coelho

Programao Bsica em C 74

cor = VERDE; fundo = PRETO; Tal comando tem significados bvios, dispensando comentrios. Sempre que possvel utilize smbolos ao invs de valores literais, pois fazem o cdigo parecer-se mais com um texto literrio do que um programa-fonte de computador. Mas no temos outra forma de organizar isto ? Sim, claro que temos. Usando o tipo enum, que significa enumerao. O tipo de dado enumerado do C define constantes simblicas mais ou menos automaticamente. Ao invs de utilizarmos os trs comandos: #define #define #define PRETO AZUL VERDE 0 1 2

podemos obter o mesmo resultado usando a instruo: enum cores { PRETO, AZUL, VERDE }; A palavra reservada enum identifica cores como sendo um novo tipo de dado, que representa uma lista de itens. Os itens listados so constantes inteiras, s quais so automaticamente atribudos valores inteiros, comeando pelo zero (0), se outro valor no for atribudo. Para poder utilizar um tipo de dado enumerado temos que definir uma varivel para tal, assim, seguindo o exemplo: enum cores frente, fundo; A partir deste ponto, a varivel frente e a varivel fundo podem receber qualquer um dos elementos listados na enumerao: frente = AZUL; fundo = PRETO; Uma varivel do tipo enumerao somente estar apta a receber valores definidos no intervalo durante a declarao do tipo. Veja o formato da declarao: Sintaxe: enum [Etiqueta] { Texto_1 = 2, Texto_2, Texto_3, Texto_4=20, Texto_5, ... /* Inicia por zero se no houver atribuio */ /* Valor = valor anterior + 1 => 3 */ /* Nova atribuio => 20 */ /* Valor = valor anterior +1 => 21 */

Joelson Coelho

Programao Bsica em C 75

Texto_n /* Valor = Valor de (n-1)+1 */ } [nome_varivel_enumerao]; As constantes enumeradas comportam-se como inteiros, mas permitem que o compilador execute uma verificao de tipo em atribuies. Por exemplo, suponha que tenhamos declarado uma outra enumerao alm de cores: enum temperatura = { GELIDO = -2, FRIO, AGRADAVEL, QUENTE, INFERNAL }; Mais tarde, ao modificar o seu cdigo, cuidadosamente construdo, algum programador menos talentoso fazendo manuteno poderia inadvertidamente tentar atribuir um dos elementos de temperatura fundo: fundo = QUENTE; Compiladores bem projetados, como o caso da famlia Borland, avisam que FRIO no um valor apropriado para a varivel fundo, muito embora, internamente, sejam valores inteiros. Logo, a utilizao de enumeraes pode prevenir atribuies invlidas. Vamos a mais um exemplo:
1. 2. 3. 4. 5. 6. 7. 8. 9. 10. 11. 12. 13. 14. 15. 16. 17. 18. 19. 20. 21. 22. 23. 24. 25. 26. 27. 28. /* Exemplo de constantes numeradas */ /* Coloque aqui os #includes necessrios */ #define ENTER 13 enum meses { JAN, FEV, MAR, ABR, MAI, JUN, JUL, AGO, SET, OUT, NOV, DEZ }; void pausa( void ) { char tecla; printf( Pressione <ENTER> para continuar ... ); while( ( tecla = getch() ) != ENTER ); } void main(void ) { enum meses mes; int dia, ano; mes = AGO; dia = 13; ano = 1997; clrscr(); printf( Hoje e: %02d de, dia ); switch( mes ) { case JAN: printf( janeiro de ); break; case FEV: printf( fevereiro de ); break; case MAR: printf( maro de ); break; case ABR: printf( abril de ); break;

Joelson Coelho

Programao Bsica em C 76

29. 30. 31. 32. 33. 34. 35. 36. 37. 38. 39. 40.

case MAI: case JUN: case JUL: case AGO: case SET: case OUT: case NOV: case DEZ:

printf( maio de ); break; printf( junho de ); break; printf( julho de ); break; printf( agosto de ); break; printf( setembro de ); break; printf( outubro de ); break; printf( novembro de ); break; printf( dezembro de ); break;

} printf( %04d.\n, ano ); pausa(); } Cdigo 12.2 Exemplo de aplicao utilizando o tipo de dado enum.

12.5 Definio de Novos Tipos


A linguagem C permite que sejam definidos, explicitamente, novos identificadores de tipos de dados. Para tanto basta usar a palavra reservada typedef. Na realidade no est sendo criado um novo tipo, mas sim um sinnimo para o tipo de dado. Este processo ajuda a tornar os programas mais portveis, escondendo algumas caractersticas e ajudando a tornar mais claro o cdigo. Sintaxe: Exemplo: typedef typedef TIPO SINNIMO; int TAMANHO;

Esta instruo declara TAMANHO como um tipo que pode ser utilizado em substituio ao tipo inteiro. Logo, para declararmos um inteiro, podemos proceder de duas formas distintas: int i, j; ou TAMANHO i, j;

Pode ser utilizado tambm com estruturas, unies e enumeraes, da seguinte forma: Sintaxe: typedef <struct/union/enum> [Etiqueta] { declarao dos elementos; } Nome_do_Tipo; /*ou do sinnimo */ typedef struct maladir{ char nome[41]; char endereco[41]; char bairro[15]; char cidade[21]; char uf[3]; char CEP[ 9 ]; unsigned int codigo; } MALA_DIRETA; /* Cria um sinnimo para a estrutura */

Exemplo:

Agora, para definir variveis do tipo da estrutura definida acima, podemos usar: MALA_DIRETA mala_dir, *ptr_mala_dir;

Joelson Coelho

Programao Bsica em C 77

O compilador enxergar como sendo: struct maladir mala_dir, *ptr_mala_dir; Veja outros exemplos: typedef int inteiro; typedef float real; typedef double realbig; inteiro i, j, *ptr_i; real xis, *ptr_real; realbig var_rbig, *ptr_big;

Joelson Coelho

Programao Bsica em C 78

13 ARQUIVOS
A linguagem C no fornece diretamente qualquer instruo para entrada e sada. Ao invs disso, a maioria dos compiladores fornece uma biblioteca padro de entrada e sada (E/S). As funes desta biblioteca proporcionam muitas das operaes de comandos de E/S. Normalmente esto divididas em duas verses: as funes de alto nvel e as de baixo nvel. As rotinas de alto nvel utilizam reas auxiliares de memria (os buffers) de entrada ou de sada que permitem a um programa ler ou escrever em arquivos byte a byte ou caracter a caracter. J as rotinas de baixo nvel acessam diretamente os dispositivos. Trs arquivos esto implicitamente presentes em todos os programas C. So a entrada padro (stdin), a sada adro (stdout) e a sada de erro padro (stderr). stdin atribudo o teclado, stdout e stderr atribudo o monitor de vdeo do terminal, a menos que seja redirecionada a entrada ou a sada, ou ainda ambas, para algum outro dispositivo. Tudo para a linguagem C so arquivos. Quando executamos uma funo getchar(), estamos na verdade lendo caracteres da entrada padro, ou seja, stdin. Analogamente, quando chamamos a funo printf(), estamos ativando a sada padro, ou o stdout. Outra sada padro, que automaticamente criada pelo C no caso de sistemas operacionais padro DOS, a stdprn, que a sada para a porta paralela. Para acess-la, deveremos usar as funes para manipular arquivos, indicando stdprn como sendo o ponteiro para o arquivo. Ela v os arquivos como sendo uma seqncia, um trem, de bytes. No importa se o arquivo um banco de dados, a foto da Madona escaneada, um documento, etc., C sempre o v como um aglomerado, um amontoado de bytes. Devido a este tipo de tratamento, precisou ser criado um elemento que indicasse que o arquivo est encerrado ou que o arquivo terminou, da mesma forma que foi necessrio um indicador para determinar o encerramento de uma string. Para as strings, temos o \0. Para os arquivos temos o EOF (End Of File), Durante a leitura de um arquivo, sempre existe a possibilidade de no haver mais dados para serem lidos. Este caso normalmente tratado pela funo de entrada, que retorna o valor EOF. EOF uma constante simblica criada atravs de um #define em dois arquivos de cabealho distintos, o io.h e o stdio.h, quase sempre possui o valor de substituio -1 (menos hum). Para que os outros arquivos, alm da entrada e sadas padro, possam ser manipulados necessitamos abri-los, fech-los e referenci-los explicitamente. As funes fopen() e fclose() so utilizadas para abrir e fechar os arquivos em alto nvel, que sempre so referenciados atravs de um ponteiro para um tipo chamado FILE, que sempre dependente da arquitetura da mquina onde est rodando o compilador e est definido, atravs de um typedef, no arquivo de cabealho stdio.h. Sendo assim, para trabalharmos com arquivos necessitamos declarar ponteiros para os mesmos, da seguinte forma:

Joelson Coelho

Programao Bsica em C 79

Sintaxe: Exemplo:

FILE

ptr_arquivo; /* FILE o tipo de estrutura definido em stdio.h */

FILE *ptr_arq_clientes;

Todas as operaes que forem feitas sobre o arquivo, devero necessariamente utilizar sempre esta varivel ponteiro. Para ver os componentes da estrutura FILE, consulte a ajuda de seu compilador ou a documentao que o acompanha. No TC possvel descobrir a partir do help on-line (F1). A seguir veremos as funes bsicas para manipular arquivos.

13.1 Funes Bsicas Para Manipular Arquivos


13.1.1 Abrir Arquivo: fopen() Sintaxe: fopen( nome_do_arquivo, modo_de_abertura );

A funo fopen procura pelo arquivo definido como nome_do_arquivo. Se este arquivo existir, se houver manipuladores disponveis (FILES = XX) e possuir espao na memria para uma varivel do tipo FILE, ento a funo alocar memria para as informaes sobre o arquivo (estrutura do tipo FILE) e retornar o endereo desta estrutura que servir de ponteiro para manipular o arquivo. Se ocorrer algum erro, a funo retorna NULL. O modo_de_abertura identifica a operao que desejamos fazer sobre este arquivo que estamos abrindo: r: abre um arquivo j existente somente para leitura; w: sobrepe ou cria um arquivo apenas para efetuar escrita; a: adiciona dados, ou seja, abre um arquivo para escrita no final do arquivo r+: abre o arquivo para atualizao, ou seja, permite alteraes (leitura e escrita), porm no permite que o arquivo aumente de tamanho; w+: cria um novo arquivo para escrita; se este j existir, apagado; a+: abre para adicionar novas informaes (no fim do arquivo) e tambm para efetuar leitura e escrita; Existem ainda dois identificadores que servem para indicar como o arquivo dever ser visto, se no modo texto ou binrio. Devem ser postos como sendo o ltimo caractere no modo_de_abertura (veja o exemplo), so eles: t: indica que o arquivo deve ser encarado como arquivo texto; b: indica que o arquivo vai ser visto como binrio. Exemplo: ptr_arq = fopen( C:\\AUTOEXEC.BAT, rt );

Joelson Coelho

Programao Bsica em C 80

Abre o arquivo autoexec.bat, que est no raiz do drive C: (note as duas contra-barras), no modo texto e somente para leitura (rt).

13.1.2 Fechar um Determinado Arquivo: fclose() Sintaxe: fclose( ponteiro_para_arquivo );

Fecha o arquivo apontado por ponteiro_para_arquivo, descarregando o buffer para disco (como sendo um comit) se este foi aberto para escrita ou limpando o buffer se este foi aberto para leitura. Preenche o ponteiro_para_arquivo com NULL e libera o espao alocado para a varivel, para informar que este no est mais conectado ao arquivo. Se houver sucesso a funo retorna 0 (zero), seno, retorna EOF. Exemplo: fclose( ptr_arq );

13.1.3 Fechar Todos os Arquivos Abertos: fcloseall() Sintaxe: fcloseall( );

Fecha todos os arquivos abertos, incondicionalmente. Exemplo: fcloseall();

13.1.4 Limpar ou Descarregar o Buffer de um Arquivo: fflush() Sintaxe: fflush( ponteiro_para_o_arquivo );

Grava em disco o buffer do arquivo, se este foi aberto para escrita ou atualizao, ou esvazia, limpa, o buffer se o arquivo foi aberto para leitura. claro que o arquivo ainda deve estar aberto. Se a operao for executada com sucesso retorna 0 (zero). Em caso de erro, retorna EOF. Exemplo: fflush( stdin ); fflush( ptr_arq );

13.1.5 Limpar ou Descarregar Todos os Buffers de Arquivos: fflushall() Sintaxe: flushall( );

Grava o contedo de todos os buffers dos arquivos abertos para escrita ou atualizao e esvazia, limpa, todos os buffers dos arquivos abertos para leitura.

Joelson Coelho

Programao Bsica em C 81

Exemplo:

flushall( );

13.1.6 Detectar o Final de um Arquivo: feof() Sintaxe: feof( ponteiro_para_o_arquivo );

Detecta se foi atingido o final do arquivo indicado por ponteiro_para_o_arquivo. Retorna 0 (zero) se no houver erro e tambm no for o final do arquivo e outro valor, diferente de zero, se o fim do arquivo j foi atingido (EOF). Exemplo: feof( ptr_arq );

13.1.7 Reposicionar o Ponteiro de um Arquivo: fseek() Sintaxe: fseek( ponteiro_para_arq, deslocamento, a_parti_de_onde );

Reposiciona o ponteiro que indica a posio atual do arquivo indicado por ponteiro_para_arquivo, deslocando a quantidade de bytes indicada por deslocamento partir da posio indicada por a_partir_de_onde, que pode ter os seguintes valores: SEEK_SET: Comeo do arquivo SEEK_CUR: Posio atual SEEK_END: Fim do arquivo Retorna 0 (zero) se tudo bem. Se ocorreu erro, retorna um valor diferente de 0 (zero). Exemplo: fseek( ptr_arq, (long int)(sizeof(MALA_DIRETA) * 10), SEEK_SET );

Posiciona o ponteiro do arquivo no incio do registro nmero 11, se existir claro, no arquivo indicado por ptr_arq, que deve conter elementos do tipo MALA_DIRETA (note o sizeof).

13.2 Funes Bsicas para Entrada e Sada em Arquivos Texto


13.2.1 Ler um Caractere de um Arquivo: fgetc() ou getc() Sintaxe: fgetc( ponteiro_para_o_arquivo ); getc( ponteiro_para_o_arquivo ); L um caractere do arquivo apontado por ponteiro_para_o_arquivo. Deve ser usado, normalmente, em arquivos texto.

Joelson Coelho

Programao Bsica em C 82

Retorna o caractere lido ou EOF se encontrar o final do arquivo. Exemplo: c = fgetc( ptr_arq );

13.2.2 Escrever um Caractere de um Arquivo: fput() ou putc() Sintaxe: fputc( caractere, ponteiro_para_o_arquivo ); putc( caractere, ponteiro_para_o_arquivo ); Escreve um caractere, indicado por caractere, no arquivo apontado por ponteiro_para_o_arquivo. Deve ser usado, normalmente, em arquivos texto. Retorna o prprio caracter escrito se houver sucesso, ou o EOF se acontecer algum erro. Exemplo: fputc( A, ptr_arq ); ou fputc( 65, ptr_arq );

13.2.3 Ler uma Seqncia de Caracteres de um Arquivo: fgets() Sintaxe: fgets( ptr_destino, quantidade, ponteiro_para_o_arquivo );

L (quantidade - 1) caracteres do arquivo apontado por ponteiro_para_o_arquivo, depositando o resultado da leitura no endereo indicado por buffer_car. A funo garante o espao e coloca o terminador de strings (\0) no final da leitura (por isso quantidade - 1). Deve ser usado, normalmente, em arquivos texto. Se acontecer algum erro ou for final do arquivo, retorna NULL em buffer_car. Exemplo: fgets( buffer_car, 35, ptr_arq );

13.2.4 Escrever uma Seqncia de Caracteres de um Arquivo: fputs() Sintaxe: fputs( ptr_origem, ponteiro_para_o_arquivo );

Escreve o contedo da string indicada ou apontada por buffer_car no arquivo apontado por ponteiro_para_o_arquivo. Se obtiver sucesso, ela retorna o ltimo caractere escrito, caso contrrio, retorna EOF. Exemplo: fputs( buffer_car, ptr_arq );

13.2.5 Ler Dados Formatados de Arquivo: fscanf() Sintaxe: fscanf( ponteiro_para_o_arquivo, formato, end_destinos );

Joelson Coelho

Programao Bsica em C 83

L do arquivo apontado por ponteiro_para_o_arquivo os elementos do tipo indicado por formato para as variveis indicadas por end_destinos. Retorna o nmero, a quantidade, de variveis que foram lidas e armazenadas com sucesso. Se o nmero retornado for menor do que o nmero de variveis solicitadas, ento aconteceu um erro. Exemplo: fscanf( ptr_arq, %d %f %c, &var_int, &var_float, &var_c );

13.2.6 Escrever Dados Formatados em Arquivo: fprintf() Sintaxe: fprintf( ponteiro_para_o_arquivo, formato, lista_variveis );

Escreve no arquivo apontado por ponteiro_para_o_arquivo as variveis passadas como argumento seguindo a formatao definida por formato. Retorna o nmero de bytes escritos se tudo correu bem. Se ocorrer algum erro, retorna EOF. Exemplo: fscanf( ptr_arq, %d %f %c, var_int, var_float, var_c );

13.3 Funes Bsicas para Entrada e Sada em Arquivos Binrios


As funes abaixo so utilizadas geralmente quando trabalhamos com estruturas de dados, ou registros, bancos de dados, etc., manipulando de forma binria o arquivo, como se este fosse uma imagem da memria. Desta forma, ao escrevermos num arquivo uma varivel float, por exemplo, estaremos ocupando o mesmo espao que esta ocupa na memria, ou seja, 4 bytes. Se gravarmos de forma textual, ocuparemos 1 byte para cada smbolo representado. 13.3.1 Ler uma Seqncia de Bytes de um Arquivo: fread() Sintaxe: fread( end_destino, tamanho_tipo, quantidade_de_elementos, ponteiro_para_o_arquivo );

L do arquivo apontado por ponteiro_para_o_arquivo o nmero de bytes representado pela multiplicao de quantidade_de_elementos por tamanho_tipo para o endereo especificado por end_destino. Retorna o nmero de elementos lidos se ocorreu tudo bem, ou um nmero pequeno, possivelmente 0, se ocorrer erro. Exemplo: fread( ptr_mala_direta, sizeof(MALA_DIRETA), 1, ptr_arq );

13.3.2 Escrever uma Seqncia de Bytes em um Arquivo: fwrite() Sintaxe: fwrite( end_destino, tamanho_tipo, quantidade_de_elementos, ponteiro_para_o_arquivo );

Escreve o nmero de bytes representando a multiplicao de quantidade_de_elementos por tamanho_tipo, iniciando em end_destino (que est na memria), no arquivo apontado por

Joelson Coelho

Programao Bsica em C 84

ponteiro_para_o_arquivo. Retorna o nmero de elementos escritos se obtiver sucesso, ou um nmero pequeno, possivelmente 0, se ocorrer erro. Exemplo: fwrite( ptr_mala_direta, sizeof(MALA_DIRETA), 1, ptr_arq );

13.4 Funes de Tratamento de Erros


13.4.1 Limpar Indicadores de Erro e de Fim de Arquivo: clearerr() Sintaxe: clearerr( ponteiro_para_o_arquivo );

Limpa quaisquer flags de erro e indicadores de fim de arquivo relacionados ao arquivo indicado pelo ponteiro_para_o_arquivo. Chame esta funo aps detectar e responder a um erro de I/O. Voc pode ento executar operaes adicionais de I/O no arquivo. No retorna nenhum valor. Exemplo: clearerr( ptr_arq );

13.4.2 Verificando a Ocorrncia de Erros: ferror() Sintaxe: ferror( ponteiro_para_o_arquivo );

Serve para verificar e identificar a ocorrncia de um erro em uma operao de I/O imediatamente anterior no dispositivo apontado por ponteiro_para_o_arquivo. Retorna 0 (zero) se no houve erros e um valor no-zero se ocorreu algum erro. Exemplo: ferror( ptr_arq );

13.4.3 Escreve Mensagem de Erro na Sada Padro: perror() Sintaxe: perror( ponteiro_para_o_arquivo );

Escreve no arquivo padro de sada de erros stderr, a mensagem indicada pela string, alm da mensagem de erro correspondente a um valor errno global, definido em ERRNO.H (e tambm por stdef e stdlib.h). No entanto no precisamos incluir estes arquivos de cabealho para utiliz-la. O trabalho feito por uma chamada de printf. No retorna nenhum valor. Exemplo: perror( string );

Joelson Coelho

Programao Bsica em C 85

13.4.4 Descobrir Texto da Mensagem de Erro Relativa a um Cdigo: strerror() Sintaxe: strerror( cdigo_erro );

Tambm definido em string.h, etrerror retorna o endereo de uma string de mensagem de erro definida para o erro cdigo_erro. As mensagens de erro so dependentes do sistema diferem entre compiladores e sistemas operacionais. Retorna o endereo da mensagem quando o cdigo for vlido ou o endereo da mensagem Unknown Error para valores de cdigo_erro desconhecidos. Exemplo: puts( strerror( errno ) );

13.4.5 Exemplo de Cdigo Tratando Erro


1. 2. 3. 4. 5. 6. 7. 8. 9. 10. 11. 12. 13. 14. 15. 16. 17. 18. 19. 20. 21. 22. 23. 24. 25. 26. 27. 28. 29. 30. 31. 32. 33. 34. /* Exemplo de funes que tratam erros */ #include <stdio.h> #include <stdlib.h> #include <conio.h> char espera( void ) { char c; printf( \n Pressione <ENTER> para continuar ..."); while( ( c = getchar() ) != \n ) ; return c; } int main( void ) { FILE *fp; char *msg_err;

/* Definir ponteiro para o arquivo */ /* Mensagem de erro gerada */

puts( Tentando abrir um arquivo que no existe ... ); /* Algumas mensagens */ puts( Chamado de NOARQUIV.XEQ ); puts( Isto deve causar um erro de I/O previsto pelo sistema\n ); puts( Abrindo o arquivo NOARQUIV.XEQ . . . ); fp = fopen( NOVOSRQ.XEQ, r ); /* Causando o erro */ if( !fp ) perror( Erro detectado ); es = strerror( errno ); /* Descobre a mensagem de erro e exibe */ puts( \nMensagem de erro: ); puts( es ); clearerr( stdin ); espera(); return( 0 ); } Cdigo 13.1 Exemplo de tratamento de erros em arquivos. /* Limpa qualquer erro pendente em stdin; */

Joelson Coelho

Programao Bsica em C 86

14 EXERCCIOS
14.1 Seqenciais:
1. Ler 2 nmeros quaisquer, calcular a soma deles e aps mostrar os nmeros lidos e o resultado da soma. 2. Ler 2 nmeros quaisquer, dividir o primeiro pelo segundo. Mostrar os nmeros lidos e o resultado calculado. 3. Ler 3 nmeros quaisquer e calcular a media aritmtica entre eles. Escrever os nmeros lidos e a media calculada. 4. Ler 2 nmeros. Multiplicar o primeiro por 4 e o segundo por 0.6. Calcule a media aritmtica dos resultados obtidos. Escrever os valores lidos, os calculados e a media aritmtica. 5. Ler os seguintes nmeros: A, B e C. Aps, calcular o valor de D segundo a expresso: D = B2 - 4AC e mostrar os valores lidos e o resultado. 6. Escrever um algoritmo que leia o cdigo da pea 1, a quantidade de peas 1, o valor unitrio da pea 1, o cdigo da pea 2, a quantidade de peas 2, o valor unitrio da pea 2 e o percentual de IPI a ser acrescentado ao valor de cada pea. Calcule o valor a ser pago para cada pea e o valor total da compra. Escrever a quantidade, o cdigo, o valor unitrio, o valor unitrio com IPI e o valor total para cada pea e tambm o valor total da compra. 7. Escrever um algoritmo que leia o cdigo de um funcionrio, o nmero de horas trabalhadas e o valor que recebe por hora. Calcule o salrio deste funcionrio. Escrever o cdigo e o salrio do funcionrio. 8. Escrever um algoritmo que leia o valor de um emprstimo e calcule o valor de cada amortizao, considerando um total de 24 amortizaes e uma taxa de 48%. O valor de cada amortizao obtido segundo a frmula: Valor _ emprestimo * taxa valor _ amortizacao = numero _ de _ amortizacoes 9. Escrever um algoritmo que leia o cdigo de um vendedor, seu salrio fixo, o total de vendas por ele efetuadas e o percentual de comisso que recebe sobre as vendas. Calcular o salrio total do vendedor. Escrever o cdigo do vendedor e o seu salrio total. 10.Considerando que o ndice de reajuste para determinada classe social foi acordado para ser um ndice de reposio salarial mais um ndice de produtividade que cada empresa ir definir, crie um algoritmo que leia o cdigo de um funcionrio, seu salrio atual, o ndice de reposio e o de produtividade e calcule o novo salrio do funcionrio. Escrever o cdigo do funcionrio, seu salrio atual, quanto ter de aumento e o novo salrio.

Joelson Coelho

Programao Bsica em C 87

14.2 Condicionais
1. Ler dois nmeros, diferentes entre si, e imprimir o de maior valor. 2. Ler dois nmeros quaisquer e imprimir o de menor valor. 3. Ler 2 nmeros. Se os nmeros forem iguais imprimir a mensagem: NMEROS IGUAIS e encerrar a execuo; caso contrrio, imprimir o de maior valor. 4. Ler 3 nmeros, diferentes entre si, e imprimir o de maior valor. 5. Ler e imprimir 3 nmeros. Se o primeiro for positivo, imprimir sua raiz quadrada, caso contrrio, imprimir o seu quadrado; se o segundo nmero for maior que 10 e menor que 100, imprimir a mensagem: NMERO EST ENTRE 10 E 100 - INTERVALO PERMITIDO; se o terceiro nmero for menor que o segundo, calcular e imprimir a diferena entre eles, caso contrrio, imprimir o seu inverso( 1/x ). 6. Escrever um algoritmo que leia o cdigo de um vendedor, seu salrio fixo e o total de vendas por ele efetuadas. Cada vendedor recebe o salrio fixo mais uma comisso proporcional s vendas efetuadas. A comisso de 3% sobre o total de vendas at R$1000,00 e de 5% sobre o que ultrapassar este valor. Escrever o cdigo do vendedor, seu salrio fixo, o total de vendas, a comisso recebida e o salrio total. 7. A empresa XYZ resolveu conceder um aumento diferenciado aos seus funcionrios de acordo com a tabela abaixo. Escrever um algoritmo que leia o cdigo do funcionrio e o seu salrio atual. Escreva o cdigo do funcionrio, o salrio atual, o percentual que receber de aumento e o valor deste aumento e o novo salrio. Salrio Atual < 500 >=500 e <1000 >=1000 e <2000 >=2000 e <3000 >=3000 e <4000 >=4000 e <5000 >= 5000 ndice aumento 100% 95% 90% 80% 70% 50% 30%

8. Escrever um algoritmo que leia o cdigo de identificao de um aluno e as suas trs notas (3 provas + 1 nota referente aos exerccios). Calcular para cada aluno a mdia usando a frmula: mdia = ( N1 + N2 x 2 + N3 x 3 + NE) / 7. O algoritmo deve escrever o cdigo do aluno, suas notas, a mdia e o conceito correspondente (ver tabela) e a mensagem APROVADO (se conceito for A, B, ou C) ou REPROVADO. Mdia > = 9.0 >= 7.5 e < 9.0 >= 6.0 e < 7.5 >= 4.0 e < 6.0 < 4.0 Conceito A B C D E

Joelson Coelho

Programao Bsica em C 88

9. Escrever um algoritmo que leia um cdigo e trs valores: a, b e c. Os cdigos vlidos so 1, 2, 3, 4 e 5. Consistir a entrada de dados para que sejam diferentes de zero e positivos. Se o cdigo for diferente destes, apresentar a mensagem CDIGO INVLIDO e terminar o programa. cdigo = 1: multiplicar os 3 valores; cdigo = 2: somar os 3 valores; cdigo = 3: subtrair os 3 valores; cdigo = 4: somar o cubo dos 3 valores; cdigo = 5: somar o quadrado dos 3 valores.

14.3 Repetio:
1. Ler e imprimir uma srie de 5 nmeros, um de cada vez. 2. Ler e imprimir o nome de 10 pessoas, um de cada vez. 3. Ler uma srie de 10 nmeros e imprimir somente os positivos. 4. Ler, multiplicar por 2 e imprimir o resultado encontrado para cada um dos 20 nmeros lidos. 5. Ler uma srie de 30 nmeros, imprimindo o valor lido e o seu quadrado. 6. Ler uma srie de 25 nmeros e imprimir somente os maiores que 99. 7. Ler 8 valores (assumir que sejam diferentes de 0) e imprimi-los. Contar quantos dos nmeros lidos foram negativos e imprimir o resultado. 8. Ler e imprimir as notas de uma turma de 25 alunos. Ao final do algoritmo imprimir quantas notas da turma ficaram abaixo de 5. 9. Ler o nome e a nota de 20 alunos e imprimir somente o nome dos alunos aprovados, sabendo-se que a mdia para aprovao e 7. 10.Ler as notas referentes a uma turma de 35 alunos, onde cada aludo tem 3 notas. Para cada aluno, imprimir suas notas, sua mdia aritmtica e a mensagem "*** APROVADO ***" se sua mdia for superior ou igual a 7 e "!!! REPROVADO !!!" se for inferior a 7. No final informar qual o percentual de reprovao da turma. 11.Ler o nome e a quantidade de filhos de 30 pessoas, imprimindo: quantas pessoas tm entre 1 e 3 filhos; quantas pessoas tm entre 4 e 7 filhos; quantas pessoas tm mais de 8 filhos; quantas pessoas no tm filhos. 12.Ler o nome, o sexo e a idade de 40 pessoas e aps imprimir: nmero de pessoas do sexo masculino;

Joelson Coelho

Programao Bsica em C 89

nmero de pessoas do sexo feminino; nmero de pessoas com idade inferior a 30 anos; nmero de pessoas com idade superior a 60 anos. 13.Em uma fbrica, as fichas cadastrais de seus 50 funcionrios contem o nome, o sexo, a idade e o salrio. Ler estas informaes e imprimir: total de empregados do sexo masculino e do sexo feminino; total de funcionrios maiores que 25 anos; nmero de empregados com idade entre 30 e 40 anos (inclusive)

Joelson Coelho

Programao Bsica em C 90

15 ALGUMAS FUNES TEIS


Como a maioria dos cabealhos da biblioteca padro, stdlib.h define algumas constantes e estruturas variadas. Alguns destes so os seguintes: NULL embora esteja definido em stdlib.h, o compilador reconhece este valor, que significa nulo, mesmo que stdlib no esteja includo. RAND_MAX Significa 0x7FFF. Utilize esta constante em programas que necessitam determinar o valor mximo possvel retornado pela funo rand. erno varivel para armazenar os cdigos de erro gerados em operaes de I/O. size_t tipo de dado til que ajuda a eliminar conflitos entre programas que sero compilados por diferentes compiladores C, nos quais inteiros podem ter diferentes tamanhos binrios. Equivale ao tipo inteiro sem sinal.

15.1 Funes de Controle de Fluxo


void abort( void ) Finaliza o programa, gerando uma mensagem de erro que varia de compilador para compilador. No turbo C Abnormal program termination. int atexit( atexit_t func ) Designa a funo a ser chamada automaticamente quando o programa termina de maneira normal. void exit( int status ) Encerra imediatamente o programa, retornando o valor status para o sistema operacional. int system( const char *command ) Faz com que o sistema operacional execute o comando indicado por command.

15.2 Funes de Converso de ASCII para Binrio


double atof( const char *s ) Transforma a string s em um valor real. int atoi( const char *s ) Transforma a string s em um valor inteiro. long atol( const char *s ) Transforma a string s em um valor inteiro longo. double strtod( const char *s, char **endptr ) Converte a string s em um valor real. double strtol( const char *s, char **endptr, int radix ) Converte a string s em um valor inteiro longo. radix indica a base usada para a converso. unsigned log strtoul( const char *s, char **endptr, int radix ) Idem funo anterior, retornando, porm, um valor inteiro longo sem sinal.

Joelson Coelho

Programao Bsica em C 91

15.3 Funes de Converso de Binrio para ASCII


char *itoa( int value, char *string, int radix ) Converte o numero inteiro value em uma string, utilizando a base indicada por radix. char *ltoa( long value, char *string, int radix ) Idem anterior, porm trabalha com valores inteiros longos. char *ultoa( unsigned long value, char *string, int radix ) Exclusiva da Borland. Semelhante s anteriores, operando sobre valores inteiros longos sem sinal.

15.4 Funes de Gerenciamento de Memria


void *calloc( size_t nitems, size_t size ) Aloca memria necessria para armazenar nitems objetos, cada um deles com size bytes. Ajusta toso os bytes para 0. Retorna o endereo do primeiro byte alocado. NULL se memria insuficiente. void free( void *block ) Devolve um espao de memria alocado por calloc, malloc ou realloc. void *malloc( size_t size ) Aloca size bytes de memria. Retorna o endereo do primeiro byte. NULL se no existir memria sufuciente. void *realloc( void *block, size_t size ) Ajusta o tamanho da memria alocada, indicada por block, que deve ser um valor retornado por calloc, malloc ou realloc.

15.5 Funes de Ambiente


char *getenv( const char *name ) Pesquisa no ambiente do sisema por uma varivel indicada por name e retorna o seu valor, se estiver definida, seno retorna NULL. int putenv( const char *name ) Exclusiva da Borland. Insere uma nova varivel de sistema. name deve ser estar na forma [nome = [ valor ] ].

15.6 Funes de Nmeros Aleatrios


int rand( void ) Retorna o prximo nmero numa seqncia pseudo-aleatria na faixa de zero RAND_MAX. Gera a mesma srie de nmeros se inicializado com o mesmo valor. int random( int num ) Gera um nmero aleatrio entre zero e num - 1. void randomize( void ) Inicializa o gerador de nmeros randmicos com um valor aleatrio. lemre-se de incluir time.h. void srand( unsigned seed ) Inicializa o gerador de nmeos aleatrios com o valor seed. Para gerar sencias totalmente aleatrias, coloque valores diferentes em cada execuo na varivel seed.

15.7 Funes Relacionadas com Tempos e Datas


clock_t clock( void ) Retorna o nmer de tiques de relgio que se passaram desde o inicio do programa. Para converter em segundos, divida por CLK_TCK.

Joelson Coelho

Programao Bsica em C 92

double difftime( time_t time2, time_t time1 ) Subtrai dois tempos calendrios: time2 - time1. Note que o ltimo tempo deve ser fornecido primeiro. Retorna o nmero de segundos decorridos dntre os dois tempos. time_t time( time_t **timer ) Retorna o tempo calendrio corrente como uma estrutura time_t, igual ao nmero de segundos decorridos a partir de GMT (Greenwich Mean Time) 00:00:00 (01 de janeiro de 1970). struct tm *gmtime( const time_t *timeptr ) Converte um valor time_t indicado por timeptr em GMT, retornado atravs do endereo da estrutura interna tm. struct tm *localtime( const time_t *timeptr ) Converte um valor time_t indicado por timeptr em hora local. Retorna a hora convertida em uma esrutura tm. time_t mktime( struct tm *timeptr ) Converte a estrutura tm endereada por timeptr em um valor time_t. char *asctime( const struct tm *tblock ) Converte uma estrutura endereada por tblock em uma string ASCII, contendo dia da semana, ms, dia do ms, hora e o ano. char *ctime( const time_t *time) Converte um valor de calendrio local time_t, indicado por time, em uma string ASCII. Equivalente : asctime( localtime( time ) ); void settime( struct time *timeptr ) Atribui os valores contidos na esrutura time apontada por timeptr data e hora do sistema.

15.8 Funes Manipuladoras de Strings


size_t strlen( const char *str ) Devolve o nmero de caracteres contidos na string apontada por str. No conta o terminador NULL (\0). char *strnset( char *str, int ch, size_t n ) Exclusiva da Borland. Inicializa os n primeiros bytes da string indicada por str com o caractere ch. char *strset( char *str, int ch ) Exclusiva da Borland. Atribui o caracter ch a todos os bytes da string str. Interrompe a atribuio nao detectar o NULL (\0). char *strupr( char *str ) Exclusiva da Borland. Converte para maisculos todos os caracteres minsculos da string apontada por str. char *strlwr( char *str ) Exclusiva da Borland. Converte para minsculos todos os caracteres maisculos da string indicada por str. char *stpcpy( char *dest, const char *src ) Copia a string indicada por src sobra a indicada por dest. Igual a strcpy, no entanto retorna o endereo do ltimo caractere copiado: dest + strlen( src ). char *strcpy( char *dest, char *src ) Copia a string apontada por src sobre a indicada por dest. sua a responsabilidade quanto ao tamanho da string destino. Cuidado !! char *strdup( const char *str ) Aloca um espao de memria suficientemente grande para conter a string str, copia o contedo de str para este local e retorna o endereo que foi alocado.

Joelson Coelho

Programao Bsica em C 93

No se esquea de desalocar esta memria com a funo free. Se no houver memria suficiente, retorna NULL. char *strncpy( char *dest, char *src, size_t maxlen ) Copia at maxlen caracteres da string apontada por src para aquela apontada por dest. Retorna o endereo de dest. int strcmp( const char *s1, const char *s2 ) Compara duas strings alfabeticamente. Retorna um valor menor que zero se s1 form menor que s2; zero se forem iguais; ou um valor positivo se a s1 for maior do que s2. int stricmp( const char *s1, const char *s2 ) Idntico anterior, porm no distinge as letras minsculas das maisculas e vice-versa. int strncmp( const char *s1, const char *s2, size_t maxlen ) Idem strcmp, porm s compara no mximo os maxlen primeiros caracteres. int strnicmp( const char *s1, const char *s2, size_t maxlen ) Idem stricmp, porm s compara no mximo os maxlen primeiros caracteres. char *strcat( char *dest, char *src ) Concatena, junta, a string src string dest. Exige que a string dest tenha sido inicializada. Retorna dest. char *strncat( char *dest, char *src, size_t maxlen ) Idntica strcat, porm concatena no mximo os primeiros maxlen caracteres. char *strchr( const char *s, int c ) Pesquisa a ocorrncia do caractere c em uma string endereada por s. Retorna o endereo do primeiro caractere c encontrado ou NULL, se este no for encontrdo. char *strrchr( const char *s, int c ) Idem anterior, porm retorna o endereo da ltima ocorrncia do caractere c na string s ou NULL se c no fizer parte de s. char *strstr( const char *s1, const char *s2 ) Retorna o endereo da primeir ocorrncia da string s2 dentro da string s1. Retorna NULL se s2 no puder ser encontrada em s1. char *strrev( char *s ) Inverte os caracteres na string s, por exemplo, se a string s for ABCD, depois de chamar a funo, teremos s como sendo DCBA. Retorna a prpria string s.

15.9 Funes de Buffer


void *memchr( const void *s, int c, size_t n ) Pesquisa o caractere c em n bytes de um buffer endereado por s. Retorna um ponteiro para aquele caractere no buffer ou NULL se c no for encontrado. int memcmp( const void *s1, const void *s2, size_t n ) Idntico funo strcnmp, porm trabalha sobre buffers de memria. void *memcpy( void *dest, const void *src, size_t n ) Copia n bytes do buffer endereado pr src para o buffer endereado por dest. De novo, garanta que dest tenha espao suficiente para conter src. int memicmp( const void *s1, const void *s2, size_t n ) Idem memcmp, porm ignora letras minsculas de maisculas.

Joelson Coelho

Programao Bsica em C 94

void *memmove( void *dest, void *src, size_t n ) o mesmo que memcpy, porm funciona corretamente ainda que o ponteiro src enderece um byte dentro do buffer dest i.e., se os dois buffers se superpuserem. Retorna dest. void *memset( void *s, int c, size_t n ) Atribui aos n primeiros bytes de memria apontada por s o caractere c. O programador deve garantir, no mnimo, n bytes em s.

15.10 Funes Matemticas


As funes prototipadas no arquivo de cabealho MATH.H so de diversas categorias, entre elas temos as funes trigonomtridas, as logartmicas, as de potenciao e as gerais. Este arquivo de cabealho tambm define algumas constantes e estruturas utilizadas por funes deste tpico. Trs constantes muito importantes so: 1. HUGE_VAL Valor de overflow igual ao mximo valor double positivo permitido para argumentos de funo. Os argumentos maiores ajustam a varivel global errno para EDOM. 2. EDOM Erro de domnio (valor fora do domnio para a funo utilizada), atribudo a errno. 3. ERANGE Erro de escopo (o valor no pode ser representado utilizando o tipo de dado double) atribudo a errno. Tambm encontramos no cabealho MATH.H um tipo de dado enumerado no-padro, listando possveis valores de erro transportados por uma estrutura exception. Abra o arquivo MATH.H e verifique a estrutura _mexcep. Algumas definioes que voc encontra no arquivo MATH.H so exclusivas da Borland. Sugerimos que voc faa a definio de tipos e de constantes dentro de seu prprio arquivo quando quizer garantir a portabilidade, ou seja, gerar executvel para uma outra plataforma. int abs( int x ) Retorna o valor absoluto (no negativo) de valores inteiros x. double fabs( double x ) Retorna o valor absoluto de valores reais x. long labs( long x ) Idem abs, porm com valores inteiros longos. double ceil( double x ) Retorna o menor inteiro (como um double) de x. double floor( double x ) Retorna o menor inteiro (como um double) de x. double exp( double x ) Retorna o valor e elevado potncia de x. double fmod( double x, double y ) Retorna o resto da diviso de x por y. double frexp( double x, int *exponent ) Divide um valor real em mantissa e expoente. Passe o valor em x. Retorna a mantissa e armazena o expoente na varivel exponent (deve ser passado o endereo de um inteiro). Veja tambm modf. double hypot( double x, double y ) Retorna a hipotenusa do tringulo de lados x e y. double modf( double x, double *ipart ) Separa um valor real em suas partes inteira e fracionria. A funo retorna a parte fracionria e armazena a parte inteira na varivel ipart (deve ser passado o endereo de um double).

Joelson Coelho

Programao Bsica em C 95

div_t div( int numer, int denom ) Divide numer/denom e retorna, na estrutura div_t, o quociente e o resto da diviso. ldiv_t ldiv( long numer, long denom ) O mesmo que div, porm com valores longos e refere-se a uma estrutura ldiv_t, cujos componentes so todos inteiros longos. double acos( double x ) Retorna o arco, em radianos, cujo cosseno x. double asin( double x ) Retorna o arco, em radianos, cujo seno x. double atan( double x ) Retorna o arco, em radianos, cuja tangente x. double atan2( double y, double x ) Retorna o arco, em radianos, cuja tangente vale y/x no intervalo de - . double cos( double x ) Retorna o cosseno de x (deve estar em radianos). double cosh( double x ) Retorna o cosseno hiperblico de x (tambm em radianos). double sin( double x ) Retorna o seno de x (em radianos). double sinh( couble x ) Retorna o seno hiperblico de x (em radianos). double tan( double x ) Retorna a tangente de x (em radianos). double tanh( double x ) Retorna a tangente hiperblica de x (em radianos). double log( double x ) Retorna o logaritmo natural de x. double log10( double x ) Retorna o logaritmo na base 10 de x. double pow( double x, double y ) Retorna o valor de x elevado potncia de y. double pow10( int p ) Retorna 10 elevado potncia de p. double ldexp( double x, int exp ) Retorna o valor de x multiplicado por 2 elevado potncia exp. Equivalente a x * pow(2, exp ). double sqrt( double x ) Retorna a raiz quadrada de x).

Joelson Coelho

Programao Bsica em C 96

REFERNCIA BIBLIOGRFICA
Borland International Inc. Turbo C Reference Guide. Scotts Valley, Borland, 1988. Pugh, Kenneth. Programando em Linguagem C. So Paulo, Editora McGraw-Hill, 1990. Gay, Warren W. Aprenda em 24 horas programao para Linux. Rio de Janeiro, Editora Campus, 1999. Schildt, Herbert. Turbo C Guia do Usurio. So Paulo, Editora McGraw-Hill, 1987. Schildt, Herbert. Linguagem C Guia Prtico e Interativo. So Paulo, Editora McGraw-Hill, 1989. Schildt, Herbert. C Completo e Total. So Paulo, Editora McGraw-Hill, 1997. Swan, Tom. Tecle & Aprenda C. Rio de Janeiro, Berkeley Brasil Editora, 1994. Mayer, Roberto Carlos. Linguagem C ANSI Guia do Usurio. So Paulo, Editora McGraw-Hill, 1989. Mizrahi, Victorine Viviane. Treinamento em Linguagem C Mdulo 1. So Paulo, Editora McGraw-Hill, 1990. Mizrahi, Victorine Viviane. Treinamento em Linguagem C Mdulo 2. So Paulo, Editora McGraw-Hill, 1990. Duntemann, Jeff e Weiskamp, Keith. C/C++ Ferramentas Poderosas. Rio de Janeiro, Berkeley Brasil Editora, 1993. Grady, M. Tim. Turbo C Programming Principles and Practices. Santa Cruz - USA, Mitchel Publishing Inc., 1989. Waite, Mitchell, Prata, Stephen and Martin, Donald. The Waite Groups C Primer Plus. Indianapolis - USA, Howard W. Sams & Company, 1988.

Joelson Coelho

Programao Bsica em C 97

Você também pode gostar