Escolar Documentos
Profissional Documentos
Cultura Documentos
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.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.
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.
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.
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.
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
Arquivo Executvel
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
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.
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
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
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
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
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.
Joelson Coelho
Programao Bsica em C 15
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.
Joelson Coelho
Programao Bsica em C 17
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
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.
Joelson Coelho
Programao Bsica em C 20
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.
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
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
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;
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)
Exemplos: const char letra_A = A; const double PI = 3.141592653; const int deiz = 10;
Joelson Coelho
Programao Bsica em C 26
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.c int twit; static int tum; main( ) { --------------} figaro( ) { --------------}
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
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
OPERADORES M ATEMTICOS
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;
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
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).
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.
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.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
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
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
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
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
Joelson Coelho
Programao Bsica em C 40
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;
Ou
Joelson Coelho
Programao Bsica em C 41
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;
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.
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.
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.
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.
Joelson Coelho
Programao Bsica em C 46
Sintaxe
break;
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.
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;
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
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 }, }, }, }, }, }
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
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;
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;
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
Joelson Coelho
Programao Bsica em C 54
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
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
Joelson Coelho
Programao Bsica em C 55
VARIVEL constante constante constante constante constante constante constante ptr_c As definies:
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 :
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
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.
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.
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.
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).
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.
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
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
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
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;
< -- 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.
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
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.
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).
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 );
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 );
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( );
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).
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 );
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 );
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 );
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 ) );
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
Joelson Coelho
Programao Bsica em C 91
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.
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.
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.
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