Sei sulla pagina 1di 147

Jaime Evaristo Aprendendo a Programar Programando na Linguagem C Para Iniciantes Terceira Edio Revisada/Ampliada Edio Digital (cpias autorizadas)

Aprendendo a Programar Programando na Linguagem C Jaime Evaristo Professor Adjunto Instituto de Computao Universidade Federal de Ala goas

Aos meus netos Mateus, Vitor e Lucas

Sumrio 1 Introduo Programao................................................................ ................................................. 4 1.1 Organizao bsica de um compu tador........................................................................... .......... 4 1.2 Linguagem de mquina............................................. .................................................................4 1.3 Programas de computadores................................................................ ...................................... 5 1.4 Lgica de programao.................... ................................................................................ ..........6 1.5 Resoluo de problemas.............................................. .............................................................. 6 1.6 Processador de um algoritmo................................................................ .....................................9 1.7 Exemplos de algoritmos matemticos..... ................................................................................ 10 1.8 Linguagens de alto nvel.................................................. ........................................................ 13 1.9 Sintaxe e semntic a de uma instruo.................................................................. ................... 14 1.10 Sistemas de computao.................................. ...................................................................... 14 1.11 E xerccios propostos............................................................... ............................................... 15 2. Introduo Linguagem C........ ................................................................................ ..................... 17 2.1 Variveis simples.................................... ................................................................................ . 17 2.2 Constantes............................................................. ................................................................... 18 2.3 Expre sses aritmticas................................................................... .......................................... 19 2.4 Relaes.......................... ................................................................................ ......................... 20 2.5 Expresses lgicas................................. ................................................................................ .. 20 2.6 Estrutura de um programa em C......................................... ..................................................... 21 2.7 Entrada dos dados d e entrada....................................................................... ............................21 2.8 Sada de dados................................. ................................................................................ ........ 23 2.9 Comando de atribuio............................................... ............................................................. 28 2.10 Exemplos P arte I.......................................................................... .......................................... 30 2.11 Funes de biblioteca............ ................................................................................ .................33 2.12 Exerccios propostos..................................... ......................................................................... 34 3 E struturas de seleo................................................................ ....................................................... 36 3.1 O que uma estrutu ra de seleo....................................................................... ......................36 3.2 O comando if....................................... ................................................................................ .... 36 3.3 O comando if else................................................... ................................................................. 37 3.4 O opera dor condicional ternrio.......................................................... .................................... 38 3.5 Exemplos Parte II................... ................................................................................ ..................38 3.6 O comando switch....................................... ............................................................................ 44 3.7 Exemplos Parte III.......................................................... ......................................................... 45 3.8 Exerccios propos tos............................................................................. ................................... 47 4. Estruturas de repetio................... ................................................................................

................ 49 4.1 Para que servem as estruturas de repetio.................. ............................................................49 4.2 O comando for ................................................................................ ......................................... 50 4.3 O comando while................ ................................................................................ ..................... 52 4.4 O comando do while................................. ............................................................................... 56 4.5 O comando break em estruturas de repetio................................... ....................................... 57 4.6 Exemplos Parte IV................ ................................................................................ ................... 58 4.7 Exerccios propostos................................... ............................................................................. 63 5. Funes e ponteiros............................................................. ........................................................... 65 5.1 O que so funes.. ................................................................................ .................................. 65 5.2 Para que servem funes................... ................................................................................ .......67 5.3 Passagem de parmetros.............................................. ............................................................ 68 5.4 Ponteiros... ................................................................................ ............................................... 72

5.5 Passagem de parmetros por referncia no Turbo C 2.01........................... ............................ 73 5.6 Uma urna eletrnica........................... ................................................................................ ......73 5.7 Recursividade...................................................... .....................................................................75 5.8 Usan do funes de outros arquivos....................................................... .................................. 79 5.9 "Tipos" de variveis.................... ................................................................................ .............80 5.10 Uma aplicao Histria da Matemtica............................... ............................................... 82 5.11 Exerccios propostos...... ................................................................................ ........................ 83 6 Vetores........................................... ................................................................................ ..................84 6.1 O que so vetores........................................ ............................................................................. 84 6.2 Declarao de um vetor unidimensional.......................................... ........................................84 6.3 Vetores e ponteiros.............. ................................................................................ .................... 85 6.4 Lendo e escrevendo um vetor......................... ......................................................................... 85 6.5 Exemplos Parte IV.............................................................. ..................................................... 86 6.6 Vetores multidimens ionais.......................................................................... ............................ 90 6.7 Exemplos Parte V............................ ................................................................................ ........ 92 6.8 Uma aplicao esportiva............................................. ............................................................. 94 6.9 Exerccios pr opostos......................................................................... ....................................... 95 7 Pesquisa e ordenao................... ................................................................................ .................... 99 7.1 Introduo.............................................. ................................................................................ .. 99 7.2 Pesquisa sequencial................................................... ...............................................................99 7.3 Pesquisa b inria............................................................................ ........................................... 99 7.4 Ordenao........................ ................................................................................ ...................... 101 7.5 Exerccios propostos............................... ............................................................................... 103 8. Cadeias de caracteres (strings).......................................... ........................................................... 104 8.1 Introduo...... ................................................................................ ........................................ 104 8.2 Funes de biblioteca para manipulao de cadeias de caracteres........................................ 105 8.3 Exemplo s Parte VI...................................................................... ........................................... 107 8.4 Exerccios propostos.......... ................................................................................ .................... 111 9 Estruturas e Arquivos................................ ................................................................................ .... 113 9.1 O que so estruturas................................................. .............................................................. 113 9.2 Exemplos Parte VII....................................................................... .........................................114 9.3 O que so arquivos............... ................................................................................ ..................116 9.4 Arquivos de registros (Arquivos binrios)............... ..............................................................117 9.5 Arquivo te xto............................................................................. ............................................ 126 9.6 Exerccios propostos......... ................................................................................ ..................... 130 10 Noes bsicas de alocao dinmica de memria ...............

.................................................. 132 10.1 O que alocao dinmica... ................................................................................ ............... 132 10.2 Armazenando dinamicamente um polinmio................... ................................................... 133 10.3 Listas............. ................................................................................ ....................................... 134 10.4 Exerccios propostos............. ................................................................................ ............... 136 Bibliografia................................................ ................................................................................ .......137 ndice remissivo....................................................... .........................................................................138

1 Introduo Programao 1.1 Organizao bsica de um computador Um computador constitudo de quatro unidades bsicas: unidade de entrada, unidade de sada, unidade de processamento central e memria. Como indica sua denominao, uma uni dade de entrada um dispositivo que permite que o usurio interaja com o computador , fornecendo-lhe dados e informaes que sero processadas, sendo o teclado o seu exem plo mais trivial. Uma unidade de sada, por seu turno, serve para que sejam fornec idos ao usurio do computador os resultados do processamento realizado. O monitor de vdeo e uma impressora so exemplos de unidades de sada. A unidade central de proc essamento responsvel por todo o processamento requerido, sendo muito conhecida po r cpu, acrossemia de central processing unit. J a memria armazena dados e informaes que sero utilizados no processamento, armazenamento temporrio, pois quando o compu tador desligado tudo que est nela armazenado deixa de s-lo (dizemos que toda a memr ia "apagada").

1.2 Linguagem de mquina Linguagens de comunicao Evidentemente, h a necessidade de que as unidades que compem um computador se comu niquem umas com as outra. Por exemplo, um dado fornecido pelo teclado deve ser a rmazenado na memria; para a cpu realizar uma operao aritmtica, ela vai buscar valores que esto armazenados na memria, e assim por diante. Para que haja comunicao entre as unidades do computador necessrio que se estabelea uma linguagem. Os seres humanos se comunicam basicamente atravs de duas linguagens: a linguagem escrita e a fala . Uma comunicao atravs de uma linguagem escrita constituda de pargrafos, os quais co tm perodos, que contm frases, que so constitudas de palavras, sendo cada uma das pala vras formadas por letras e esta sequncia termina a. Assim, uma letra um ente indiv isvel da linguagem escrita e, em funo disto, chamada smbolo bsico desta linguagem. E te exemplo foi apresentado para que se justifique a afirmao de que toda linguagem requer a existncia de smbolos bsicos, como - e para mais um exemplo - os fonemas pa ra a linguagem falada.

A linguagem de comunicao entre as unidades Como a comunicao entre as unidades do computador teria que ser obtida atravs de fenm enos fsicos, os cientistas que conceberam os computadores atuais estabeleceram do is smbolos bsicos para a linguagem. Esta quantidade de smbolos foi escolhida pelo f ato de que atravs de fenmenos fsicos muito fcil obter dois estados distintos e no co fundveis, como passar corrente eltrica/no passar corrente eltrica, estar magnetizado /no estar magnetizado, etc., podendo cada um destes estados ser um dos smbolos. As sim a linguagem utilizada para comunicao interna num computador, chamada linguagem de mquina, possui apenas dois smbolos. Cada um destes smbolos denominado bit (bina ry digit) e eles so representados por 0 (zero) e 1 (um). Esta forma de representa r os bit's justifica a sua denominao: binary digit, que significa dgito binrio (alm d isto, bit em ingls significa fragmento). Portanto, as palavras da linguagem de mqu ina so sequncias de bits, ou seja, sequncias de dgitos zero e um.

O cdigo ASCII Para que haja a possibilidade da comunicao do homem com o computador, necessrio que as palavras da linguagem escrita sejam traduzidas para a linguagem de mquina e v ice-versa. Para que isto seja possvel, necessrio que se estabelea qual a sequncia de bit's que corresponde a cada caractere usado na linguagem escrita. Ou seja, nec essrio que se estabelea uma codificao em sequncia de bit's para cada um dos caractere s. Uma codificao muito utilizada o cdigo ASCII (American Standard Code for Informat ion Interchange ou Cdigo Padro Americano para Intercmbio de Informaes), estabelecido pelo ANSI (American National Standards Institute). Nesta codificao, cada caractere representado por uma sequncia de oito bits (normalmente, um conjunto de oito bit 's chamado byte). S para exemplificar (ser visto ao longo do livro que, em geral, no h necessidade de que se conhea os cdigos dos caracteres), apresentamos a tabela a baixo com os cdigos ASCII de alguns caracteres. Tabela 1 Cdigos ASCII de alguns caracteres Caractere Espao em branco ! " ... 0 1 ... A B ... Z ... a ... Cdigo ASCII 00100000 00100001 00100010 ... 00110000 00110001 ... 01000001 0100001 0 ... 01011010 ... 01100001 . ..

Observe a necessidade de se haver codificado o espao em branco (este "caractere" utilizado para separar nossas palavras) e de se haver codificado diferentemente as letras maiusculas e minsculas, para que se possa consider-las como coisas disti ntas. Levando em conta que cada sequncia de zeros e uns pode ser vista como a rep resentao de um nmero inteiro no sistema binrio de numerao [Evaristo, J 2002], podemos at para facilitar a sua manipulao, associar a cada cdigo ASCII o inteiro correspond ente, obtendo assim o que se costuma chamar de cdigo ASCII decimal. Por exemplo, como 1000001 a representao do nmero (decimal) 65 no sistema binrio de numerao, dize que o cdigo ASCII decimal de A 65. 1.3 Programas de computadores Para que um computador tenha alguma utilidade, ele deve executar um programa que tenha uma finalidade especfica. Games so programas que tm como objetivo propiciar entretenimento aos seus usurios. Processadores de texto so programas que permitem que textos sejam digitados, impressos e armazenados para futuras modificaes ou imp resses. Planilhas eletrnicas so programas que oferecem recursos para manipulao de tab elas de valores numricos. Navegadores permitem acessos a pginas da internet, a red e mundial de computadores. Estes programas destinam-se a usurios finais, aquelas pessoas que vo utilizar o computador com um determinado objetivo especfico, usando para tal um programa que ela aprendeu a usar, no tendo nenhuma preocupao relativa ao funcionamento interno do sistema computador/programa. Por exemplo, um usurio d e um processador de texto deve aprender o que fazer para que o processador desta que em negrito alguma parte do texto ou localize uma palavra, no havendo necessid ade de saber como o programa realiza estas aes. Na verdade, para que um processado r de texto propicie ao usurio a possibilidade de que textos sejam digitados, corr igidos, gravados, inseridos em outros textos e de que palavras sejam localizadas dentro de um

texto, necessria a execuo de muitas instrues com objetivos bem mais especficos e re itos. Um programa de computador , na realidade, um conjunto de instrues que podem s er executadas pelo computador, de tal forma que a execuo de subconjuntos destas in strues permitem a realizao de aes mais genricas. muito grande o nmero de instru ramas citados acima, chegando casa dos milhares. Rigorosamente falando, um progr ama dos acima citados so conjunto de programas menores, cada um deles com objetiv os mais restritos, e que podem ser executados de forma integrada. comum se utili zar a palavra inglesa software para designar um conjunto de programas com objeti vos mais restritos que, sendo executados de forma integrada, propiciam a execuo de aes bem mais genricas. A parte da Cincia da Computao que trata do desenvolvimento de softwares denominada Engenharia de Software. Naturalmente, o estudo da Engenhari a de Software deve ser precedido da aprendizagem do desenvolvimento de programas menores, ao que comumente denominada de Programao de Computadores.

1.4 Lgica de programao Sendo um conjunto de instrues cujas execues redundam na realizao da tarefa para a qua foi desenvolvido, o desenvolvimento de um programa requer a utilizao de um raciocn io mpar em relao aos raciocnios utilizados na soluo de problemas de outros campos do aber. Por exemplo (e de forma simplificada) ao se tentar resolver um problema de Mecnica Newtoniana deve-se procurar capturar da especificao da questo as grandezas fsicas envolvidas e aplicar as frmulas que relacionam estas grandezas. Para se des envolver um programa que resolva um determinado problema necessrio que encontremo s uma sequncia de instrues que cujas execues resultem na soluo da questo. comum s zar a termo algoritmo para indicar uma sequncia de instrues que resolvem um dado pr oblema, ficando, neste caso, o termo programa para indicar um algoritmo que pode ser executado num computador. A Lgica de Programao pode ser entendida como o conju nto de raciocnios utilizados para o desenvolvimento de algoritmos (e, portanto, d e programas). Por exemplo, imagine a seguinte questo: um senhor, infelizmente bas tante gordo, est numa das margens de um rio com uma raposa, uma dzia de galinhas e um saco de milho. O senhor pretende atravessar o rio com suas cargas, num barco a remo que s comporta o senhor e uma das cargas. Evidentemente, o senhor no pode deixar em uma das margens, sozinhos, a raposa e a galinha, nem a galinha e o mil ho. A questo escrever um algoritmo que oriente o senhor a realizar o seu intento. Naturalmente, na primeira viagem, ele no pode levar a raposa (neste caso, as gal inhas comeriam o milho), nem o milho (caso em que a raposa devoraria as galinhas ). Logo, na primeira viagem ele deve levar as galinhas. Como ele estar presente n a chegada, na segunda viagem ele pode levar a raposa ou o milho. Mas, e a volta para apanhar terceira carga? A soluo ele voltar com as galinhas e, a, atravessar o milho, j que no h problema em que a raposa e o milho fiquem juntos. Escrevendo as i nstrues na sequncia em que elas devem ser executadas, teremos o seguinte algoritmo. 1. Atravesse as galinhas. 2. Retorne sozinho. 3. Atravesse a raposa. 4. Retorne com as galinhas. 5. Atravesse o milho. 6. Retorne sozinho. 7. Atravesse as gali nhas. 1.5 Resoluo de problemas Uma pergunta que o leitor pode estar se fazendo : como vou "descobrir" que a prim eira instruo deve ser a travessia das galinhas? Algumas tarefas para as quais se p retende escrever um algoritmo podem ser vistas como um problema

a ser resolvido. O exemplo anterior um exemplo claro de uma tarefa com esta cara cterstica. Existem algumas tcnicas que podem ser utilizadas para a resoluo de proble mas. No exemplo anterior, para se definir qual seria a primeira instruo, como exis tem apenas trs possibilidades, verifica-se o que aconteceria ao se escolher deter minada instruo. Foi o que, de passagem, foi feito acima: se o homem atravessasse p rimeiro o milho, a raposa devoraria as galinhas; se o homem atravessasse primeir o a raposa, as galinhas comeriam o milho. Neste caso, podemos dizer que foi util izada a tcnica da exausto: como o nmero de alternativas era pequeno, analisamos tod as elas, uma a uma. Esta tcnica pode ser utilizada tambm na soluo do seguinte proble ma: dispe-se de trs esferas idnticas na forma, sendo duas delas de mesmo peso e a t erceira de peso maior. A questo descobrir qual a esfera de peso diferente, realiz ando-se apenas uma pesagem numa balana de dois pratos. Para isto chamemos de A e B as esferas de mesmo peso e de C a de maior peso. Se optarmos por colocar duas esferas num dos pratos e a outra esfera no outro, temos as seguintes possibilida des: a) (A+B, C). b) (A+C, B). c) (B+C, A). No primeiro caso, pode acontecer qua lquer coisa: a balana pode ficar equilibrada, se Peso(C) = Peso(A+B); ficar incli nada para o lado esquerdo, se Peso(C) > Peso(A+B) ou ficar inclinada para o lado direito se Peso(C) < Peso(A+B). Observe que nada pode distinguir a esfera C. No s dois ltimos casos, a balana se inclinar para a esquerda, mas, outra vez, nada dis tingue a esfera C. Por exausto, resta ento escolhermos duas esferas e colocarmos c ada uma delas num dos pratos da balana. Agora os casos possveis so: a) (A, B). b) ( A, C). c) (B, C). No primeiro caso, a balana ficar equilibrada, o que indica que a mais pesada aquela no escolhida; nos outros dois casos, a balana se inclinar para a direita, indicando que a esfera mais pesada aquela que ocupa o prato respectiv o. Temos ento o seguinte algoritmo: 1. Escolha duas esferas. 2. Coloque cada uma das esferas escolhidas num dos pratos da balana. 3. Se a balana ficar equilibrada, fornea como resposta a esfera no escolhida; caso contrrio, fornea como resposta a e sfera do prato que est num nvel mais baixo. Uma outra tcnica de resoluo de problemas consiste em se tentar resolver casos particulares da questo ou resolver a questo p ara dados menores do que os dados que foram fixados. Para exemplificar, consider emos a seguinte questo: como obter exatamente 4 litros de gua dispondo de dois rec ipientes com capacidades de 3 litros e 5 litros1? Como 4 = 3 + 1 ou 4 = 5 1 cons eguiremos resolver a questo se conseguirmos obter 1 litro. Mas isto fcil, pois 1 = 3 + 3 5! Temos ento o seguinte algoritmo: 1. Encha o recipiente de 3 litros. 2. Transfira o contedo do recipiente de 3 litros para o recipiente de 5 litros. 3. E ncha o recipiente de 3 litros. 4. Com o contedo do recipiente de 3 litros, comple te o recipiente de 5 litros. 5. Esvazie o recipiente de 5 litros. 6. Transfira o contedo do recipiente de trs litros para o recipiente de 5 litros. 7. Encha o rec ipiente de 3 litros. 8. Transfira o contedo do recipiente de 3 litros para o reci piente de 5 litros. Para compreender o algoritmo, sejam A e B os recipientes de 3 litros e de 5 litros, respectivamente, e indiquemos por (X, n) o fato de o rec ipiente X conter n litros de gua. No incio temos (A, 0) e (B, 0) e, aps a execuo de c ada instruo, teremos: 1. (A, 3), (B, 0). 2. (A, 0), (B, 3). 3. (A, 3), (B, 3). 4. (A, 1), (B, 5). 1 A soluo desta questo foi necessria num filme da srie Duro de Matar para o protagonist a desativar uma bomba.

5. (A, 1), (B, 0). 6. (A, 0), (B, 1). 7. (A, 3), (B, 1). 8. (A, 0), (B, 4). Outr as questes que podem ser levantadas so: h outras solues? Existe alguma soluo que rea e a mesma tarefa com uma quantidade menor de instrues? Para responder a estas ques tes talvez seja interessante lembrar que 4 = 5 1. Significa que, se conseguirmos tirar 1 litro do recipiente de 5 litros quando ele estiver cheio, resolveremos a questo. Para conseguir isto, basta que o recipiente de 3 litros contenha 2 litro s. E para se obter 2 litros? A basta ver que 2 = 5 3. Podemos ento resolver a ques to com o seguinte algoritmo, constitudo de apenas seis instrues: 1. Encha o recipien te de 5 litros. 2. Com o contedo do recipiente de 5 litros, encha o de 3 litros. 3. Esvazie o recipiente de 3 litros. 4. Transfira o contedo do recipiente de 5 li tros para o recipiente de 3 litros. 5. Encha o recipiente de 5 litros. 6. Com o contedo do recipiente de 5 litros, complete o recipiente de 3 litros. Aps a execuo d e cada uma das instrues teremos: 1. (A, 0), (B, 5). 2. (A, 3), (B, 2). 3. (A, 0), (B, 2). 4. (A, 2), (B, 0). 5. (A, 2), (B, 5). 6. (A, 3), (B, 4). Uma outra tcnica bastante utilizada se tentar raciocinar a partir de uma soluo conhecida de uma ou tra questo. Para compreender isto considere as duas seguintes questes: imagine uma relao de n nmeros, os quais podem ser referenciados por ai com i = 1, 2, ..., n e queiramos som-los com a restrio de que s sabemos efetuar somas de duas parcelas. Par a resolver esta questo, podemos pensar em casos particulares: se n = 2, basta som ar os dois nmeros; se n = 3, basta somar os dois primeiros e somar esta soma com o terceiro. Naturalmente este raciocnio pode ser reproduzido para n > 3. A questo que a soma dos dois primeiros deve estar "guardada" para que se possa som-la com o terceiro, obtendo-se a soma dos trs primeiros; esta soma deve ser "guardada" pa ra que seja somada com o quarto e assim sucessivamente. Para isto podemos estabe lecer uma referncia soma "atual", a qual ser alterada quando a soma com o elemento seguinte for efetuada. At para somar os dois primeiros, pode-se pensar em somar "a soma do primeiro" com o segundo. Temos ento o seguinte algoritmo: 1. Faa i = 1. 2. Faa Soma = a1. 3. Repita n 1 vezes as instrues 3.1 e 3.2. 3.1. Substitua i por i + 1. 3.2. Substitua Soma por Soma + ai. Por exemplo: se n = 5 e a1 = 8, a2 = 4 , a3 = 9, a4 = 13 e a5 = 7, a execuo do algoritmo resultaria nas seguintes aes: 1. i = 1. 2. Soma = 8. 3.1.1. i = 2. 3.2.1. Soma = 8 + 4 = 12 3.1.2. i = 3. 3.2.2. S oma = 12 + 9 = 21. 3.1.3. i = 4. 3.2.3. Soma = 21 + 13 = 34. 3.1.4. i = 5. 3.2.4 . Soma = 34 + 7 = 41. Naturalmente, na execuo acima estamos indicando por 3.1.x e 3.2.x a execuo de ordem x das

instrues 3.1 e 3.2. Como veremos ao longo do livro, este algoritmo bastante utiliz ado em programao, sendo mais comum at o primeiro termo da relao ser "somado" dentro d a repetio. Neste caso, para que o primeiro seja somado, necessrio que Soma seja ini cializado com 0 (zero), ficando assim o algoritmo: 1. Faa i = 0. 2. Faa Soma = 0. 3. Repita n vezes as instrues 3.1 e 3.2. 3.1. Substitua i por i + 1. 3.2. Substitu a Soma por Soma + ai. Conhecendo este algoritmo, fcil ento resolver a questo de se calcular o produto de n nmeros nas mesmas condies, e a vemos como utilizar uma soluo onhecida para resolver um problema. Deve-se inicializar uma referncia Produto com 1 e, numa repetio, multiplicar os nmeros como foi feito no caso da soma: 1. Faa i = 0. 2. Faa Produto = 1. 3. Repita n vezes as instrues 3.1 e 3.2. 3.1. Substitua i p or i + 1. 3.2. Substitua Produto por Produto x ai. 1.6 Processador de um algoritmo Obviamente, um algoritmo deve ser executado por algum agente. Este agente pode s er uma pessoa munida de certos equipamentos e utenslios ou por mquinas projetadas para executar automaticamente algumas instrues bsicas. O algoritmo para a travessia do senhor gordo com as galinhas, sua raposa e seu saco de milho seria executado pelo tal senhor, que estava para tal munido do barco e de remos. O algoritmo pa ra obteno de quatro litros de gua a partir de recipientes de contedos cinco litros e trs litros poderia ser executado por uma pessoa que dispusesse dos dois recipien tes e de gua em abundncia. Neste ltimo caso, quem sabe, a pessoa poderia ser substi tuda por um rob. O agente que executa um algoritmo chamado processador e evidente que para que o algoritmo seja executado necessrio que o processador seja capaz de executar cada uma das suas instrues. Se o senhor gordo no souber remar ele no ser ca paz de atravessar o rio. Uma pessoa que no seja capaz de esvaziar um recipiente q ue pese cinco quilos no ser capaz de executar o algoritmo dos quatro litros de gua. Alguns autores de livros com objetivos idnticos a este - facilitar a aprendizage m da programao de computadores - iniciam seus textos discorrendo exclusivamente so bre resoluo de problemas, encarando o processador como uma "caixa preta" que receb e as instrues formuladas pelo algoritmo e fornece a soluo do problema, no levando em conta o processador quando da formulao do tal algoritmo. Entendemos que esta no a m elhor abordagem, visto que o conhecimento do que o processador pode executar pod e ser definidor na elaborao do algoritmo. Por exemplo: imagine que queiramos elabo rar um algoritmo para extrair o algarismo da casa das unidades de um inteiro dad o (apresentaremos posteriormente uma questo bastante prtica cuja soluo depende deste algoritmo). Evidentemente, o algoritmo para resolver esta grande questo depende do processador que vai execut-lo. Se o processador for um ser humano que saiba o qu e nmero inteiro, algarismo e casa das unidades, o algoritmo teria uma nica instruo: 1. Fornea o algarismo das unidades do inteiro dado. Porm, se o processador for um ser humano que saiba o que nmero inteiro e algarismo, mas no saiba o que casa das unidades, o algoritmo no poderia ser mais esse. Neste caso, para resolver a questo , o processador deveria conhecer mais alguma coisa, como, por exemplo, ter a noo d e "mais direita", ficando o algoritmo agora como: 1. Fornea o algarismo "mais dir eita" do nmero dado. E se o processador uma mquina e no sabe o que algarismo, casa das unidades, "mais direita", etc.? Nesta hiptese, quem est elaborando o algoritmo deveria conhecer que instrues o processador capaz de executar para poder escrever o seu algoritmo. Por exemplo, se a mquina capaz de determinar o resto de uma div iso inteira, o algoritmo poderia ser:

1. Chame de n o inteiro dado; 2. Calcule o resto da diviso de n por 10; 3. Fornea este resto como o algarismo pedido. Algumas das questes anteriores so importantes para se desenvolver o raciocnio, mas no este tipo de questo que se pretende discuti r ao longo deste livro. Estamos interessados em algoritmos para: 1. Resolver pro blemas matemticos, como algoritmos para determinar a mdia aritmtica de vrios nmeros d ados, determinar as razes de uma equao do segundo grau, encontrar o mximo divisor co mum de dois nmeros dados, totalizar as colunas de uma tabela, etc. 2. Resolver qu estes genricas, como algoritmos para colocar em ordem alfabtica uma relao de nomes de pessoas, atualizar o saldo de uma conta bancria na qual se fez um depsito, corrig ir provas de um teste de mltipla escolha, cadastrar um novo usurio de uma locadora , etc.. Na linguagem coloquial, o algoritmo para o clculo da mdia pode ser escrito de forma muito simples: 1. Determine a quantidade de nmeros; 2. Some os nmeros da dos; 3. Divida esta soma pela quantidade de nmeros. Qualquer pessoa que saiba con tar, somar e dividir nmeros capaz de executar este algoritmo dispondo apenas de lp is e papel. A questo que se pe : e se a relao contiver 13.426 nmeros? A tal pessoa az de executar, porm, quanto tempo levar para faz-lo? Um outro aspecto a ser observ ado que nem sempre a linguagem coloquial eficiente para se escreverem as instrues. Nessa linguagem o algoritmo para determinao das razes de uma equao do segundo grau t eria uma instruo difcil de escrever e difcil de compreender como: n. Subtraia do qua drado do segundo coeficiente o produto do nmero quatro pelo produto dos dois outr os coeficientes. Isto pode ser parcialmente resolvido utilizando-se uma linguage m prxima da linguagem matemtica que j foi utilizada em exemplos da seo anterior. No c aso da equao do segundo grau teramos o seguinte algoritmo, que nos ensinado nas ltim as sries do ensino fundamental: 1. Chame de a, b e c os coeficientes da equao. 2. C alcule d = b - 4ac. 3. Se d < 0 fornea como resposta a mensagem: A equao no possui ra es reais. 4. Se d 0 4.1 Calcule x1 = (-b + raiz(d))/2a e x2 = (-b - raiz(d))/2a. 4.2 Fornea x1 e x2 como razes da equao. De maneira mais ou menos evidente, raiz(d) est representando a raiz quadrada de d e a execuo deste algoritmo requer que o proc essador seja capaz de determinar valores de expresses aritmticas, calcular razes qu adradas, efetuar comparaes e que conhea a linguagem matemtica. Algoritmos para probl emas genricos so mais complicados e as linguagens utilizadas anteriormente no so ade quadas (para o caso da ordenao de uma relao de nomes, foram desenvolvidos vrios algor itmos e teremos oportunidade de discutir alguns deles ao longo deste livro).

1.7 Exemplos de algoritmos matemticos Para uma primeira discusso em termos de aprendizagem de desenvolvimento de algori tmos e utilizando a linguagem usada no exemplo da equao do segundo grau, apresenta mos a seguir alguns exemplos de algoritmos que objetivam a soluo de questes da mate mtica. Para eles supomos que o processador seja capaz de efetuar somas, subtraes e divises decimais, de realizar comparaes, de repetir a execuo de um conjunto de instru um nmero determinado de vezes ou enquanto uma condio seja atendida. 1. No exemplo do algoritmo para obteno do algarismo da casa das unidades de um inteiro dado supo mos que o processador seria capaz de calcular o resto de uma diviso inteira. Obse rvando que no est suposto que o nosso processador seja capaz de determinar restos de divises inteiras, vamos discutir um

algoritmo para a determinao do quociente e do resto da diviso de dois inteiros posi tivos dados. Por exemplo: se o dividendo for 30 e o divisor for 7, o algoritmo d eve fornecer os valores 4 para o quociente e 2 para o resto. Fomos ensinados que , para determinar o quociente, deveramos, por tentativa, encontrar o nmero que mul tiplicado pelo divisor resultasse no maior nmero menor que o dividendo. No exempl o numrico citado, poderamos tentar o 5 e teramos 5x7 = 35 que maior que 30; tentaram os o 3 obtendo 3x7 = 21 que talvez seja pequeno demais em relao ao 30; a tentaramos o 4 obtendo 4x7 = 28, encontrando ento o quociente 4. Um algoritmo para soluciona r esta questo poderia ser: 1. Chame de D1 e D2 o dividendo e o divisor dados. 2. Faa I = 1. 3. repita 3.1 at IxD2 > D1. 3.1. Substitua I por I + 1. 4. Calcule Q = I 1. 5. Calcule R = D1 - QxD2. 6. Fornea R para o resto e Q para o quociente pedi dos. No exemplo numrico proposto, teramos a seguinte tabela com os valores obtidos durante a execuo do algoritmo: D1 30 D2 7 I 1 2 3 4 5 QxI 7 14 21 28 35 4 2 Q R

2. O algoritmo abaixo determina o menor divisor maior que 1 de um inteiro dado. A ideia verificar se d = 2 divisor e, no sendo, verificar se 3 ou 4 ou 5, etc, di visor. A procura por um divisor vai at que um divisor seja encontrado. Naturalmen te, utilizando o algoritmo anterior, o nosso processador agora sabe determinar o resto da diviso inteira de um inteiro x por outro inteiro y no nulo. Isto ser indi cado por Resto(x, y). Para encontrar um divisor de n basta encontrar um inteiro d tal que Resto(n, d) = 0. 1. Chame de N o inteiro dado. 2. Faa D = 2. 3. Repita 3.1 enquanto Resto(N, D) 0 3.1 Substitua D por D + 1 4. Fornea D para o divisor p rocurado. 3. Como se depreende facilmente da sua denominao, o mximo divisor comum ( mdc) de dois nmeros dados o maior nmero que os divide. Antes o mdc s era utilizado para simplificaes de fraes ordinrias; atualmente ele utilizado na determinao de ch pblicas para sistemas de criptografia RSA [Evaristo, J, 2002]. Por exemplo, mdc(6 4, 56) = 8. De maneira bvia, o algoritmo abaixo determina o mdc de dois nmeros dad os: 1. Chame de x e de y os nmeros. 2. Determine D(x), o conjunto dos divisores d e x. 3. Determine D(y), o conjunto dos divisores de y. 4. Determine I, a interseo de D(x) e D(y). 5. Determine M, o maior elemento do conjunto I. 6. Fornea M como o mdc procurado. O clculo de mdc(120, 84) com este algoritmo seria: 1. x = 120, y = 84. 2. D(120) = {1, 2, 3, 4, 5, 6, 8, 10, 12, 15, 20, 24, 30, 40, 60, 120}. 3 . D(84) = {1, 2, 3, 4, 6, 7, 12, 14, 21, 28, 42, 84}. 4. I = {1, 2, 3, 4, 6, 12} . 5. M = 12. Observe que o algoritmo anterior determina o menor divisor de um in teiro no determinando todos os

divisores, como necessrio neste exemplo. Observe tambm que estamos supondo que o n osso processador capaz de determinar a interseo de dois conjuntos. A matemtica forn ece uma outra forma de se calcular o mdc de dois inteiros: determina-se a decomp osio em fatores primos dos dois inteiros e o mdc o produto dos fatores primos comu ns as duas decomposies com as menores multiplicidades. Para o exemplo dado acima t eramos: 120 2 84 2 60 2 42 2 30 2 21 3 15 3 77 5 5 1 1 1 o que nos d 120 = 23x3x5 e 84 = 22x3x7 e, portanto, mdc(120, 84) = 22x3 = 12. Vale observar que escrever este algoritmo na linguagem informal que estamos utilizando bastante complicado. Na h dvida que o primeiro algoritmo para o clculo do mdc apresentado de compreenso bastante simples. Porm, comentaremos posteriormente que ele computacionalmente ba stante ineficiente no sentido de que sua execuo pode, dependendo dos valores de x e y, demandar um tempo acima do razovel. Por incrvel que possa parecer, o algoritm o mais eficiente para o clculo do mximo divisor comum de dois nmeros foi desenvolvi do pelo matemtico grego Euclides duzentos anos Antes de Cristo. O algoritmo de Eu clides nos apresentado nas sries intermedirias do ensino fundamental atravs de um e squema como o diagrama do exemplo abaixo, cujo objetivo determinar (de novo!) o mximo divisor comum de 120 e 84. 1 2 3 120 84 36 12 O esquema funciona da seguint e forma: divide-se 120 por 84 obtendo-se resto 36; a partir da, repetem-se divises at que o resto seja zero, sendo o dividendo da diviso atual o divisor da diviso an terior e o divisor da diviso atual o resto da diviso anterior. O ltimo divisor o mxi mo divisor procurado. Como se pode ver, estas instrues escritas desta forma no so na da compreensveis, o que faz com elas sejam transmitidas oralmente nas salas do en sino fundamental. No captulo 4 (quatro), teremos a oportunidade de discutir este algoritmo com detalhes e veremos que ele um algoritmo bastante interessante no d esenvolvimento da lgica de programao. 4. Discutiremos agora o algoritmo para o clcul o da mdia de uma relao contendo um nmero grande (digamos, 10 000) de nmeros dados. No caso da equao do segundo grau, eram trs os dados de entrada e, portanto, os chamam os de a, b, e c. Mas agora so 10 000 os dados de entrada! Uma soluo possvel receber os nmeros um a um, somando-os antes de receber o seguinte, conforme vimos na seo 1. 5. 1. Chame de A o primeiro nmero dado. 2. Faa S = A. 3. Repita 9 999 vezes as ins trues 3.1 e 3.2. 3.1 Chame de A o prximo nmero dado. 3.2 Substitua o valor de S por S + A. 4. Calcule M = S/10 000. 5. Fornea M para o valor da mdia. Por exemplo, se a relao de nmeros fosse {5, 3, 8, 11, ...} at a quarta execuo de 3.1 e 3.2 teramos a guinte tabela: A 5 3 8 11 S 5 8 16 27 M Est fcil perceber que aps 9.999 execuo das instrues 3.1 e 3.2 a varivel S conter todos os nmeros da relao, o que justifica a instruo 4. 5. Um outro exemplo que justi fica plenamente a necessidade do conhecimento do que o processador capaz de exec utar a determinao do maior nmero de uma relao de nmeros. Se o processador for um

aluno do ensino mdio e a relao contiver poucos nmeros, uma simples olhada na relao pe mitir se identificar o maior nmero. Mas, e se o processador for um aluno das class es iniciais do ensino fundamental? E se a relao contiver 10 000 nmeros? E se os nmer os estiverem escritos em forma de frao ordinria? Uma soluo possvel supor que o maio ero o primeiro da relao e comparar este suposto maior com os demais nmeros, alteran do-o quando for encontrado um nmero na relao maior do que aquele que at aquele momen to era o maior. 1. Chame de A o primeiro nmero dado. 2. Faa M = A. 3. Repita 9 999 vezes as instrues 3.1 e 3.2. 3.1 Chame de A o prximo nmero dado. 3.2 Se A > M subst itua o valor de M por A. 4. Fornea M para o valor do maior nmero. Para exemplifica r, suponha que a entrada fosse o conjunto {5, 3, 8, 11, 10...}. At a quinta execuo das instrues 3.1 e 3.2 teramos a seguinte tabela: A 5 3 8 11 10 M 5 8 11

1.8 Linguagens de alto nvel Computadores digitais foram concebidos para executarem instrues escritas em lingua gem de mquina. Isto significa que um computador capaz de executar um algoritmo es crito nesta linguagem. Um algoritmo escrito em linguagem de mquina normalmente ch amado de programa objeto. Nos primrdios da computao, os algoritmos que se pretendia m que fossem executados por um computador eram escritos em linguagem de mquina, o que tornava a tarefa de desenvolvimento de algoritmos muito trabalhosa, devido ao fato de que era necessrio que se conhecesse qual sequncia de bits correspondia instruo pretendida. Naturalmente, esta dificuldade acontecia pelo fato de que o se r humano no est habituado a uma linguagem com apenas dois smbolos bsicos. Um grande avano ocorreu na computao quando se conseguiu desenvolver programas que traduzissem instrues escritas originariamente numa linguagem dos seres humanos para a linguag em de mquina. O surgimento de programas para esta finalidade permitiu o desenvolv imento de algoritmos em linguagens que utilizam caracteres, palavras e expresses de um idioma, ou seja, uma linguagem cujos smbolos bsicos e cujas palavras esto no cotidiano do ser humano. Uma linguagem com esta caracterstica chamada linguagem d e alto nvel, onde alto nvel a no se refere qualidade e sim ao fato de que ela est ma s prxima da linguagem do ser humano do que da linguagem da mquina (quando alguma c oisa est mais prxima da mquina do que do ser humano dizemos que ela de baixo nvel). Como exemplos de linguagens de alto nvel temos Pascal, C, Delphi, Visual Basic, J ava e C++. Um algoritmo escrito numa linguagem de alto nvel chamado programa font e ou simplesmente programa Como foi dito acima, um programa fonte deve ser tradu zido para a linguagem de mquina. H dois tipos de programas que fazem isto: os inte rpretadores que traduzem os comandos para a linguagem de mquina um a um e os comp iladores que traduzem todo o programa para a linguagem de mquina. Um compilador a o receber como entrada um programa fonte fornece como sada um programa escrito em linguagem de mquina, chamado programa objeto. A compilao do programa, portanto, ge ra um programa que pode ento ser executado. comum nos referirmos execuo do programa fonte quando se est executando o programa objeto. J um interpretador traduz para a linguagem de mquina os comandos do programa um a um, executando-os em seguida. Assim a interpretao de um programa no gera um programa objeto.

1.9 Sintaxe e semntica de uma instruo O que sintaxe Dissemos que um programa escrito em linguagem de alto nvel traduzido para a lingu agem de mquina por um compilador ou cada instruo traduzida por um interpretador. na tural se admitir que, para que o compilador consiga traduzir uma instruo escrita c om caracteres de algum idioma para instrues escritas como sequncias de zeros e uns, necessrio que cada instruo seja escrita de acordo com regras preestabelecidas. Est as regras so chamadas sintaxe da instruo e quando no so obedecidas dizemos que existe erro de sintaxe. Se o programa fonte contm algum erro de sintaxe, o compilador no o traduz para a linguagem de mquina (isto , o compilador no compila o programa) e indica qual o tipo de erro cometido e a instruo onde este erro aconteceu. Se o pro grama fonte for interpretado, ele executado at a instruo que contm o erro, quando en to interrompida a sua execuo e o tal erro indicado.

O que semntica Naturalmente, cada instruo tem uma finalidade especfica. Ou seja, a execuo de um inst ruo resulta na realizao de alguma ao, digamos parcial, e a sequncia das aes parc redunda na realizao da tarefa para a qual o programa foi escrito. A ao resultante da execuo de uma instruo chamada semntica da instruo. Infelizmente, um programa pode nter erros de sintaxe (e, portanto, pode ser executado), mas a sua execuo no fornec er como sada o resultado esperado para alguma entrada. Neste caso, dizemos que o programa contm erros de lgica que, ao contrrio dos erros de sintaxe que so detectado s pelo compilador ou pelo interpretador, so, s vezes, de difcil deteco. No nosso ente ndimento, para aprender a programar numa determinada linguagem necessrio que se a prenda as instrues daquela linguagem (para que se conhea o que o processador capaz de fazer), a sintaxe de cada um destes instrues e as suas semnticas. Aliado a isto, deve-se ter um bom desenvolvimento de lgica programao para que se escolha as instr ues necessrias e a sequncia segundo a qual estas instrues devem ser escritas, para qu o programa, ao ser executado, execute a tarefa pretendida. Felizmente ou infeli zmente, para cada tarefa que se pretende no existe apenas uma sequncia de instrues q ue a realize. Ou seja, dado um problema no existe apenas um programa que o resolv a. Devemos procurar o melhor programa, entendendo-se como melhor programa um pro grama que tenha boa legibilidade, cuja execuo demande o menor tempo possvel e que n ecessite, para sua execuo, a utilizao mnima da memria. Existe um conjunto de instru e comum a todas as linguagens de alto nvel e cujas semnticas permitem executar a m aioria das tarefas. A aprendizagem das semnticas destas instrues e das suas sintaxe s em alguma linguagem de programao (aliado ao desenvolvimento da lgica de programao) permite que se aprenda com facilidade outra linguagem do mesmo paradigma. 1.10 Sistemas de computao Como foi dito anteriormente, a cpu de um computador capaz de executar instrues (es critas em linguagem de mquina, permitam a repetio). Ou seja, um computador capaz de executar programas e s para isto que ele serve. Se um computador no estiver execu tando um programa ele para nada est servindo. Como foram concebidos os computador es atuais, um programa para ser executado deve estar armazenado na sua memria. O armazenamento dos programas (e todo o gerenciamento das interaes entre as diversas unidades do computador) feito por um programa chamado sistema operacional. Um d os primeiros sistemas operacionais para gerenciamento de microcomputadores foi o DOS (Disk Operating System). Quando um computador ligado, de imediato o sistema operacional armazenado na memria e s a partir da o computador est apto a executar o utros programas. Estes programas podem ser um game, que

transforma o "computador" num poderoso veculo de entretenimento; podem ser um pro cessador de texto, que transforma o "computador" num poderoso veculo de edio de tex tos; podem ser uma planilha eletrnica, que transforma o "computador" num poderoso veculo para manipulao de tabelas numricas, podem ser programas para gerenciar, por exemplo, o dia a dia comercial de uma farmcia e podem ser ambientes que permitam o desenvolvimento de games ou de programas para gerenciar o dia a dia comercial de uma farmcia. Talvez com exceo de um game, os programas citados acima so, na verda de, conjuntos de programas que podem ser executados de forma integrada. Um conju nto de programas que podem ser executados de forma integrada chamado software. P or seu turno, as unidades do computador, associadas a outros equipamentos chamad os perifricos, como uma impressora, constituem o hardware. O que nos til um conjun to software + hardware. Um conjunto deste tipo chamado de um sistema de computao. De agora em diante, os nossos processadores sero sistemas de computao. Isto , querem os escrever programas que sejam executado por um sistema de computao. Como foi dit o acima, o desenvolvimento de um programa que gerencie o dia a dia comercial de uma farmcia requer um compilador (ou um interpretador) que o traduza para a lingu agem de mquina. Antigamente, as empresas que desenvolviam compiladores desenvolvi am apenas estes programas, de tal sorte que o programador necessitava utilizar u m processador de texto parte para edio do programa fonte. Atualmente, os compilado res so integrados num sistema de computao que contm, entre outros: 1. Processador de texto, para a digitao dos programas fontes; 2. Depurador, que pe rmite que o programa seja executado comando a comando, o que facilita a descoberta de erros de lgica; 3. Help, que descreve as sintaxes e as semnticas de todas as instrues da linguagem; 4. Linker, que permite que um programa utilize out ros programas. Rigorosamente falando, um sistema constitudo de um compilador e os softwares listados acima deveria ser chamado de ambiente de programao; mais comum , entretanto, cham-lo, simplesmente, de compilador. Os ambientes de programao que u tilizamos para desenvolver os programas deste livro foram o compilador Turbo C, verso 2.01, e Turbo C++, verso 3.0, ambos desenvolvidos pela Borland International , Inc., o primeiro em 1988 e o segundo em 1992. Como se pode ver, so sistemas des envolvidos h bastante tempo (as coisas em computao andam muito mais rpido), j estando disponveis gratuitamente na internet. Estaremos, portanto, utilizando um compila dor puro C e um compilador C++, que up grade da linguagem C para a programao orienta da a objeto, paradigma que no est no escopo deste livro.

1.11 Exerccios propostos 1. Trs ndios, conduzindo trs brancos, precisam atravessar um rio dispondo para tal de um barco cuja capacidade de apenas duas pessoas. Por questes de segurana, os ndi os no querem ficar em minoria, em nenhum momento e em nenhuma das margens. Escrev a um algoritmo que oriente os ndios para realizarem a travessia nas condies fixadas . (Cabe observar que, usualmente, este exerccio enunciado envolvendo trs jesutas e trs canibais. A alterao feita uma modesta contribuio para o resgate da verdadeira hi tria dos ndios). 2. O jogo conhecido como Torre de Hani consiste de trs torres chama das origem, destino e auxiliar e um conjunto de n discos de dimetros diferentes, colocados na torre origem na ordem decrescente dos seus dimetros. O objetivo do j ogo , movendo um nico disco de cada vez e no podendo colocar um disco sobre outro d e dimetro menor, transportar todos os discos para torre destino, podendo usar a t orre auxiliar como passagem intermediria dos discos. Escreva algoritmos para este jogo nos casos n = 2 e n = 3. 3. Imagine que se disponha de trs esferas numerada s 1, 2 e 3 iguais na forma, duas delas com pesos iguais e diferentes do peso da outra. Escreva um algoritmo que, com duas pesagens numa balana de dois pratos, de termine a esfera de peso diferente e a relao entre seu peso e o peso das esferas d e pesos iguais. 4. A mdia geomtrica de n nmeros positivos a raiz n-sima do produto d estes nmeros. Supondo que o processador capaz de calcular razes n-simas, escreva um algoritmo para determinar a mdia geomtrica de n nmeros dados. 5. Sabendo que o dia 01/01/1900 foi uma segunda-feira, escreva um algoritmo que determine o dia da s emana correspondente a uma data, posterior a 01/01/1900, dada. Por exemplo, se a data dada for 23/01/1900, o algoritmo deve fornecer como resposta tera-feira.

6. O show de uma banda de rock, que ser realizado na margem de um rio, deve comear exatamente s 21 h. Atrasados, s 20 h 43 min, os quatro integrantes da banda esto n a outra margem do rio e necessitam, para chegar ao palco, atravessar uma ponte. H somente uma lanterna e s podem passar uma ou duas pessoas juntas pela ponte, e s empre com a lanterna. Cada integrante possui um tempo diferente para atravessar a ponte: o vocal leva 10 minutos, o guitarrista 5 minutos, o baixista 2 minutos e o baterista 1 minuto. Evidentemente, quando dois atravessam juntos, o tempo ne cessrio o do mais lento. Escreva um algoritmo que permita que a banda atravesse a ponte de modo que o show comece na hora marcada. 7. Resolva a questo 3 para o ca so de oito esferas, com trs pesagens. 8. Escreva um algoritmo para determinar o r esto de uma diviso inteira utilizando uma mquina de calcular que efetue apenas as quatro operaes: adio, subtrao, multiplicao e diviso. Observao Propostas de solu s propostos podem ser solicitadas atravs de mensagem eletrnica para jaime@ccen.ufa l.br com assunto RESPOSTAS LIVRO C, anexando o formulrio abaixo devidamente preen chido. Nome 1 2 Categoria1 Instituio2 Curso2 Cidade/Estado Categoria: docente, estudante, autodidata Se docente ou estudante

2. Introduo Linguagem C 2.1 Variveis simples O que uma varivel No captulo 1 foi dito que uma das unidades bsicas de um computador a memria, cuja f inalidade armazenar dados e informaes que sero manipulados pela unidade central de processamento. Naquele captulo tambm foi dito que os programas para serem executad os devem estar armazenados na memria. Ou seja, a memria armazena programas que sero executados e dados que estes programas vo manipular. Naturalmente, os dados que o programa vai manipular podem ser dados de entrada ou dados gerados pela execuo d o programa. Para que possa armazenar dados e informaes, a memria dividida em partes , chamadas posies de memria. O sistema operacional que gerencia o sistema de comput ao pode acessar cada uma destas posies para armazenar tais dados. Para que o acesso s posies de memria seja possvel, a cada uma delas est associada uma sequncia de bits, amada endereo da posio de memria. Como uma sequncia de bit s corresponde a um nmero i teiro escrito no sistema binrio, cada endereo pode ser visto como um inteiro escri to no sistema decimal. Assim temos posies de memria de endereo 1209 ou 2114, por exe mplo. Uma varivel simples (ou simplesmente varivel) uma posio de memria cujo conted ode ser modificado durante a execuo de um programa. A referncia a uma varivel no pro grama feita atravs do seu identificador; os valores que podem ser nela armazenado s dependem do seu tipo de dado. O identificador O identificador uma sequncia de letras, dgitos e caractere para sublinhamento esco lhida pelo programador e (como foi dito acima) ser utilizado no programa para se fazer referncia quela varivel (o primeiro caractere do identificador no pode ser um dgito). Como um programa deve ser legvel por outros programadores (e pelo prprio pr ogramador), uma boa prtica se escolher um identificador de uma varivel que tenha a lguma relao com a sua finalidade. Se uma varivel deve armazenar uma soma, um identi ficador muito bom para ela ser Soma. Se uma varivel vai receber nmeros, ela poderia ser identificada por Num ou por Numero. Os compiladores da linguagem C fazem di stino entre letras maiusculas e minsculas e, portanto, Numero e numero so dois ident ificadores diferentes. Manteremos, de um modo geral, a seguinte conveno ao longo d o texto: quando um identificador possuir mais de um caractere, inici-lo-emos por letra maiuscula e quando o identificador tiver um nico caractere, utilizaremos le tra minscula. Como veremos ao longo do livro, a linguagem C fixa alguns identific adores para a sintaxe de suas instrues. Estes identificadores no podem ser utilizad os nos programas, sendo conhecidos por palavras reservadas. Algumas das palavras reservadas em C so: Tabela 2 Palavras reservadas da linguagem C auto break case char const continue default do double else enum extern float for goto if int long register return short Signed sizeof static struct switch typedef union unsigned void volatile while

O tipo de dado O tipo de dado associado a uma varivel o conjunto dos valores que podem ser nela armazenados. A linguagem C dispe dos tipos de dados discriminados na tabela a seg uir. Tabela 3 Tipos de dados da Linguagem C Denominao char int long ou long int float double void Nmero de Bytes 1 2 4 4 8 0 Conjunto de valores caracteres codificados no cdigo ASCII nmeros inteiros de 32768 a 32767 nmeros inteiros de 65536 a 65535 nmeros reais de 3,4x1038 a 3,4x10-38 e 3,4x1 0-38 a 3,4x1038 nmeros reais de 1,7x10308 a -1,7x10-308 e 1,7x10-308 a 1,7x10308 c onjunto vazio

A utilizao void ser melhor explicada no captulo 5, quando estudarmos funes. Uma obser ao importante que os tipos float e double, rigorosamente falando, no armazenam nmero s reais e sim nmeros de um sistema de ponto flutuante, que no contm todos os reais entre dois nmeros reais dados. O estudo de sistemas de ponto flutuante foge ao es copo deste livro e feito, normalmente, em disciplinas do tipo Organizao e Arquitet ura de Computadores e Clculo Numrico. Vale lembrar que, de um modo geral, um byte contm oito bit s e cabe ressaltar que, em algumas situaes, importante se conhecer a quantidade necessria de bytes para uma varivel de um determinado tipo.

Declarao de variveis Para que o sistema de computao possa reservar as posies de memria que sero utilizadas pelo programa, associar identificadores aos endereos destas posies de memria e defin ir a quantidade de bytes de cada posio de acordo com o tipo de dado pretendido, um programa escrito em C deve conter a declarao de variveis, feita atravs da seguinte sintaxe: Tipo de dado Lista de identificadores; Por exemplo, um programa para de terminar a mdia de uma relao de nmeros dados pode ter a seguinte declarao: int Quant; float Num, Soma, Media; A ideia que Quant seja utilizada para armazenar a quanti dade de nmeros; Num para armazenar os nmeros (um de cada vez); Soma para armazenar a soma dos nmeros; e Media para armazenar a mdia procurada. Nas sees 2.7 e 2.9 vere mos as instrues em C para o armazenamento em variveis de dados de entrada e de dado s gerados pela execuo do algoritmo. Um valor armazenado em uma varivel comumente re ferido como sendo o contedo da varivel ou o valor da varivel. Tambm comum se referir ao identificador da varivel como sendo a prpria varivel.

2.2 Constantes Como uma varivel, uma constante tambm uma posio de memria qual devem ser associado m identificador e um tipo de dado. O que caracteriza uma constante (e da sua deno minao, emprestada da matemtica) o fato de que o contedo de uma constante no pode ser modificado durante a execuo do programa. Este contedo fixado quando da declarao da c nstante o que deve ser feito de acordo com a seguinte sintaxe: const Tipo de Dad o Identificador = Valor;

Por exemplo, um programa para processar clculos qumicos poderia ter uma declarao do tipo const float NumAvogadro = 6.023E+23; onde a expresso 6.023E+23 a forma que os com piladores C utilizam para representar os valores do tipo float na notao cientfica, ou seja 6.023E+23 = 6.023 x 1023. Um programa para clculos de reas de figuras plan as, permetros de polgonos inscritos em circunferncias, etc., poderia ter uma declar ao do tipo const float Pi = 3.1416; Esta declarao desnecessria quando o sistema util zado o Turbo C++ 3.0, pois esse sistema disponibiliza uma constante pr-definida, identificada por M_PI, que pode ser utilizada em qualquer parte do programa e cu jo valor uma aproximao do nmero irracional .

2.3 Ex resses aritmticas Como era de se es erar, os com iladores da linguagem C so ca azes de avaliar ex r esses aritmticas que envolvam as o eraes binrias de multi licao, diviso, soma e sub a o erao unria de troca de sinal. Para isto so usados os seguintes o eradores aritmti cos binrios: Tabela 4 O eradores aritmticos O erador + * / O erao adio subtrao multi licao diviso

e o o erador aritmtico unrio (-) ara a troca de sinal. Esses o eradores atuam com o erandos do ti o int ou do ti o float. Se um dos o erandos for do ti o float o resultado da o erao ser do ti o float; se os dois o erandos forem do ti o int o re sultado tambm do ti o int. No caso do o erador de diviso /, se os dois o erandos f orem do ti o int o resultado da o erao do ti o int e igual ao quociente da diviso d o rimeiro o erando elo segundo. Por exem lo, o resultado de 30/4 7. Se quiserm os a diviso decimal teremos de escrever 30.0 / 7.0 ou 30.0 / 7 ou 30 / 7.0. Ou se ja cada uma destas divises igual a 7.5 e este valor, tal como ele , ode ser armaz enado numa varivel do ti o float. O que acontece que no armazenamento de um valor do ti o float numa varivel do ti o int a arte decimal do valor des rezada, s sen do armazenada a arte inteira do nmero. Uma ex resso que envolva diversas o eraes av aliada de acordo com as regras de rioridade da matemtica: em rimeiro lugar real izada a o erao troca de sinal, em seguida so realizadas as multi licaes e divises e, inalmente, as somas e subtraes. Por exem lo, a ex resso 8 + 2*-3 avaliada como 8 + (-6) = 2. Naturalmente, a rioridade ode ser alterada com a utilizao de arnteses: a ex resso (8 + 2)*-3 resulta em 10*(-3) = -30. Embora, o sistema no exija, vamos sem re utilizar arnteses ara se arar o o erador unrio ara troca de sinal de al gum o erador binrio. Assim, 8 + 2*-3 ser indicada or 8 + 2*(-3). Uma ex resso no a rentesada contendo o eradores de mesma rioridade avaliada da esquerda ara dire ita. Por exem lo, 10/2*3 igual a (10/2)*3 = 5*3 = 15. O erandos odem ser contedo s de variveis. Neste caso, o o erando indicado elo identificador da varivel ( ara isto que serve o identificador, ara se fazer referncia aos valores que na varive l esto armazenados). Alm dos o eradores aritmticos usuais, os com iladores C dis on ibilizam o o erador mdulo, indicado or %, que calcula o resto da diviso do rimei ro o erando elo segundo. Por exem lo, 30 % 4 = 2 e 5 % 7 = 5. Este o erador atu a a enas em o erandos do ti o int, resultando um valor deste mesmo ti o. Por exe m lo, se S uma varivel do ti o float, a ex resso S % 5 gerar um erro de com ilao. Um ex resso do ti o 30.0 % 7 tambm gerar erro de com ilao, elo fato de que um dos o er andos no inteiro. Este erro indicado elo sistema ela mensagem Illegal use of fl oating oint in function ... (Uso ilegal de ti o float na funo ...), onde as reticn cias esto substituindo o identificador da funo, como ser discutido osteriormente.

2.4 Relaes Os ambientes que im lementam a linguagem C efetuam com araes entre valores numricos , realizadas no sentido usual da matemtica. Essas com araes so chamadas relaes e so idas atravs dos o eradores relacionais > (maior do que), >= (maior do que ou igua l a), < (menor do que), <= (menor do que ou igual a), == (igual) e != (diferente ). O resultado da avaliao de uma relao 1 (um), se a relao for matematicamente verda ra, ou 0 (zero), se a relao for matematicamente falsa. Assim, 3 > 5 resulta no val or 0 (zero), enquanto que 7 <= 7 resulta no valor 1 (um). Sendo um valor 1 (um) ou 0 (zero), o resultado da avaliao de uma relao ode ser armazenado numa varivel do ti o int. Os o erandos de uma relao odem ser ex resses aritmticas. Nestes casos, as ex resses aritmticas so avaliadas em rimeiro lugar ara, em seguida, ser avaliada a relao. Por exem lo, a relao 3*4 - 5 < 2*3 - 4 resulta no valor 0 (zero), ois 3*4 - 5 = 7 e 2*3 - 4 = 2. Isto significa que os o eradores relacionais tm rioridad e mais baixa que os aritmticos.

2.5 Ex resses lgicas Os com iladores C tambm avaliam ex resses lgicas obtidas atravs da a licao dos o erad res lgicos binrios &&, e ^ a duas relaes ou da a licao do o erador lgico unrio ! a relao. Se R1 e R2 so duas relaes, a avaliao da a licao dos o eradores lgicos bi acordo com os valores de R1 e R2, so dados na tabela abaixo. Tabela 5 Avaliao de ex resses lgicas R1 1 1 0 0 R2 1 0 1 0 (R1)&&(R2) 1 0 0 0 (R1) (R2) 1 1 1 0 (R1) ^ (R2) 0 1 1 0 Ou seja, uma ex resso lgica do ti o (R1)&&(R2) s recebe o valor 1 (um) se os valore s de R1 e de R2 forem iguais a 1 (um); uma ex resso lgica do ti o (R 1) (R2) s rec ebe o valor 0 (zero) se os valores de R 1 e de R2 forem iguais a 0 (zero); uma e x resso lgica do ti o (R1) ^ (R2) s recebe o valor 1 (um) se a enas um dos valores de R1 e R2 for igual a 1. O leitor j deve ter ercebido que o o erador && age com o o conectivo e da nossa linguagem; o o erador atua como o nosso e/ou e o o e rador ^ como o conectivo ou. A a licao do o erador unrio ! sim lesmente inverte o v alor original da relao: Tabela 6 O erador unrio ! R1 1 0 !R1 0 1

Considerando que os o eradores &&, e ^ ossuem o mesmo grau de rioridade, se uma ex resso no arentesada ossuir mais de uma relao, ela ser avaliada da esquerda ara direita. O o erador unrio ! tem rioridade em relao aos o eradores binrios. Ass im, ! (5 > 3) (5 < 3) tem valor 0 (zero), ois ! (5 > 3) uma relao falsa e 5 < 3 tambm . Considerando que os o eradores lgicos tm rioridade mais baixa que os o er adores relacionais, os arnteses nas ex resses acima so desnecessrios; orm entendemo s que a colocao deles facilita a leitura da ex resso. Os sistemas C 2.01 e C++ 3.0 tambm dis onibilizam os o eradores lgicos & e cujas a licaes so idnticas s a lica && e , res ectivamente. A diferena entre & e &&, or exem lo, a seguinte: se em (R1) && (R2) o valor de R1 for 0 (zero) o valor R2 no mais avaliado, enquanto qu e em (R1) & (R2) o valor de R2 avaliado, inde endentemente do valor de R1.

2.6 Estrutura de um rograma em C Estamos tentando a render a escrever rogramas na linguagem C. J vimos que se o rograma necessitar mani ular variveis, estas devem ser declaradas. Veremos no ca t ulo 5 que um rograma ode conter funes. Na verdade, veremos que um rograma em C um conjunto de funes definidas elo rogramador, funes que utilizaro outras funes de idas elo rogramador e algumas funes oferecidas elo sistema (as funes oferecidas elo sistema so chamadas funes de biblioteca ou funes r-definidas). Veremos no citado ca tulo que uma funo deve ser definida com a seguinte estrutura. Ti o de Dado Ident ificador da funo(Lista de armetros) { Declarao de variveis Sequncia de instrues } significado de Lista de armetros ser ex licado no ca tulo j referido e a Sequncia d e instrues contm comandos, ativaes de funes r-definidas e ativaes de funes def surio no r rio rograma ou em outros rogramas. Todo rograma em C deve conter um a funo identificada or main (cuja traduo rinci al), com lista de armetros vazia e ti o de dado no obrigatrio. Esta ser sem re a rimeira funo do rograma a ser executa da. Desta forma, o menor rograma em C main() { } Este rograma ode ser executa do, mas nada realiza, devido ao fato de que ele no contm nenhuma instruo. Observe qu e todo o cor o da funo deve estar dis osto entre chaves. As chaves so utilizadas em outros ontos de um rograma e so chamadas delimitadores. Os delimitadores, o id entificador main e os arnteses, dis ostos ao lado do identificador main, so os nic os elementos obrigatrios de um rograma. Como os com iladores C ignoram es aos em branco, caracteres de tabulao e caracteres de mudana de linha, no existe um estilo o brigatrio de se editar rogramas em C. Por exem lo, o rograma acima oderia ser escrito de uma das seguintes maneiras. main ( ) { } ou main(){} ou main( ){} Evi dentemente, um rogramador em C deve rocurar escrever seus rogramas num estilo que oferea uma boa legibilidade, o que vai facilitar a sua com reenso or outra essoa e a descoberta de ossveis erros de lgica. 2.7 Entrada dos dados de entrada A funo scanf() A maioria dos rogramas mani ula dados que so fornecidos elo usurio durante a exe cuo do

rograma. Estes dados constituem a entrada do rograma e, naturalmente, devem se r armazenados em variveis. Por exem lo, um rograma ara determinao das razes de uma equao do segundo grau deve receber como entrada os valores dos trs coeficientes da equao: so estes valores que identificam a equao. De um modo geral, os com iladores C ermitem a rece o de dados de entrada (e o consequente armazenamento em variveis) atravs da funo de biblioteca scanf() que ossui a seguinte sintaxe: scanf(Ex resso d e controle, Lista de variveis); A, Ex resso de controle deve ser escrita entre as a s e contm os cdigos de converso que indicam como o sistema deve armazenar os dados digitados no teclado e caracteres que o usurio deve digitar se arando a digitao des tes dados. Na Lista de variveis as variveis so se aradas or vrgulas e cada uma dela s deve ser recedida do o erador de endereo &. Este o erador indica o endereo da osio de memria definida ara a varivel identificada na lista de variveis. Quando da e xecuo desta funo, a janela de edio substituda ela janela do usurio e o sistema f ardando que o usurio digite um nmero de valores igual ao nmero de variveis da lista de variveis ( medida que so digitados, os valores a arecem na tela do usurio). A con cluso da entrada dos dados feita com a digitao da tecla <enter> e quando isto feito , o sistema armazena os dados digitados na varivel res ectiva (no sentido da orde m da colocao da varivel na lista e da digitao do valor), de acordo com o cdigo de con erso. Por exem lo, #include <stdio.h> main() { int Anos scanf("%d", &Anos) } um rograma em C que armazena um valor inteiro digitado no teclado na varivel Anos (o u seja, ara nada serve, ois o inteiro armazenado naquela osio de memria esvanece q uando a execuo do rograma encerrada). Quando se vai dar entrada em mais de um dad o atravs de uma mesma ativao da funo scanf(), ode-se fixar caracteres que devero ser digitados quando da entrada dos dados. Por exem lo, se retendemos dar entrada n uma data, odemos ter o seguinte trecho de rograma: #include <stdio.h> main() { int Dia, Mes, Ano; scanf("%d/%d/%d", &Dia, &Mes, &Ano); ... } e a data retendi da deve ser digitada no formato dd/mm/aaaa, devendo o usurio digitar as barras en tre as digitaes do dia e do ms e deste e do ano. A concluso se d com a digitao da te <enter>, como se estivesse digitando um nico dado. A digitao das barras necessria elo fato de que elas esto se arando os cdigos de formatao na ex resso de controle. Se a s a digitao do valor da varivel Dia for acionada a tecla <enter>, a execuo da fun cerrada e os valores de Mes e Ano no odem ser digitados. Se no h nenhum caractere se arando os cdigos de formatao, a digitao dos dados ode ser intercalada ela digita da tecla <enter> ou da <barra de es aos>. o caso, or exem lo, do trecho de rogr ama main() { int i; char c; scanf("%c %d", &c, &i); ... }

onde as digitaes do caractere que se retende armazenar na varivel c e do inteiro a ser armazenado em i devem ser se aradas elo acionamento da tecla <enter> ou da <barra de es ao>. necessrio notar que a digitao de um valor de um ti o diferente do ti o da varivel no rovoca erro de execuo, mas, evidentemente, ode rovocar erro d e lgica do rograma. Por exem lo, se na execuo do comando scanf("%c %d", &c, &i); d igitarmos w<enter>5.9<enter>, o caractere w armazenado na varivel c e o inteiro 5 armazenado na varivel i. Portanto, se o dado de entrada fosse realmente 5.9, o r esultado do rocessamento oderia ser fornecido com erros. Se o dado de entrada oderia ser 5.9, a varivel ara seu armazenamento deveria ter sido definida com f loat.

Os cdigos de converso e a instruo #include <stdio.h> Os cdigos de converso de acordo com o ti o de dado da varivel onde os valores digit ados sero armazenados so a resentados na tabela a seguir. Tabela 7 Cdigos de converso da funo scanf() Cdigo %c %d ou %i %o %x %ld %e %f %s Elemento armazenado um nico caractere um inteiro do sistema decimal um inteiro do sistema octal um inteiro do sistema hexadecimal um valor do ti o long um nmero n a notao cientfica um nmero em onto flutuante uma cadeia de caracteres

A instruo #include <stdio.h> que recede a funo main() necessria elos seguintes fat s. Como dissemos acima, ara se definir uma funo necessrio fixar o ti o de dado que ela retorna, o identificador da funo e a lista de armetros, com seus identificado res e seus ti os de dados; este conjunto de elementos chamado rotti o da funo. Par a que a funo main() ative uma outra funo (seja uma funo definida elo usurio ou uma de biblioteca), o seu rotti o deve ser definido antes ou no interior da funo main( ). Os rotti os das funes do sistema encontram-se reunidos, de acordo com objetivos semelhantes, em arquivos chamados arquivos de cabealhos (header files) (o cabealh o de uma funo inclui o seu rotti o, as variveis declaradas dentro da funo e outras d claraes e definies que no so instrues ro riamente ditas). A instruo #include <st nexa" funo main() os rotti os das funes de biblioteca que executam aes adres de a e de sada (stdio vem de standard in ut out ut, entrada e sada adro e h a extenso adro dos arquivos de cabealhos). A no incluso de um include rovoca erro de com ilao no sistema C++ 3.01. Isto no acontece no C 2.01, orm, h casos em que esta no incluso gera erros de lgica (a entrada de dados no feita do modo que se es erava).

2.8 Sada de dados A funo rintf() A exibio dos resultados do rocessamento e de mensagens feita atravs da funo r-def da rintf(), cujo rotti o est contido tambm no arquivo stdio.h. Sua sintaxe a segu inte: rintf(Ex resso de controle, Lista de argumentos); onde Ex resso de controle contm mensagens que se retende que sejam exibidas, cdigos de formatao (idnticos aos cdigos de converso da funo scanf()) que indicam como o contedo de uma varivel deve s r exibido e cdigos es eciais ara a exibio de alguns caracteres es eciais e realizao de aes que ermitam formatar a sada do rograma. A Lista de argumentos ode conter identificadores de variveis,

ex resses aritmticas ou lgicas e valores constantes. No rimeiro caso, o contedo da varivel exibido; no segundo caso, a ex resso avaliada e o seu resultado exibido; n o terceiro caso o valor constante exibido. A ordem de exibio dos contedos de varivei s, dos resultados das ex resses e dos valores constantes relacionados na lista de argumentos dada ela ordem em que estes elementos esto listados; a osio dentro da mensagem contida na ex resso de controle fixada ela osio do cdigo de formatao re ctivo. Quando, na ex resso de controle, um cdigo de formatao encontrado o contedo da varivel, o resultado da ex resso ou o valor constante res ectivo (no sentido da or dem da colocao da varivel na lista e da colocao do cdigo de formatao na ex resso d ole) exibido. Por exem lo, a funo rintf() no rograma abaixo contm uma ex resso de controle que no ossui cdigos de formatao. Isto significa que a enas a mensagem ser e xibida. Assim, o rograma #include <stdio.h> main() { rintf("Estou a rendendo a rogramar em C"); } um rograma em C que faz com que seja exibida na tela a men sagem Estou a rendendo a rogramar em C. J o rograma abaixo, contm uma funo rintf( ) que ossui quatro caracteres de controle #include <stdio.h> main() { float a, b, c; scanf("%f %f %f", &a, &b, &c); rintf("%f , %f e %f %f", a, b , c, (a + b + c)/3); } Quando da execuo deste rograma, o sistema, ara execuo da funo scanf(), a uarda que sejam digitados trs valores numricos. Quando isto feito, o sistema armaz ena estes trs valores nas variveis a, b e c, res ectivamente. Na execuo do ltimo coma ndo, o sistema exibe os valores armazenados nas variveis a, b e c, em seguida ava lia a ex resso (a + b + c)/3 e exibe o seu valor na tela. Assim, o rograma forne ce a mdia aritmtica de trs nmeros dados. Como um outro exem lo e considerando que o resultado de uma ex resso lgica um inteiro, o rograma #include <stdio.h> main() { rintf("%d", 5 > 3); } exibe na tela o valor 1, ois a relao 5 > 3 verdadeira. No s dois exem los anteriores, utilizamos ex resses, uma aritmtica e uma lgica, como a rgumentos de uma funo rintf(). No nosso entendimento, no uma boa rtica de rograma se utilizar ex resses como argumentos de uma funo rintf(). Se o valor de uma ex re sso til ara alguma coisa, ele deve ser armazenado em alguma varivel (veremos isto na rxima seo) e esta deve ser utilizada ara o fornecimento de resultados.

Facilitando a execuo de um rograma A ossibilidade de que mensagens ossam ser exibidas ermite que o r rio rogram a facilite a sua execuo e que torne com reensveis os resultados fornecidos. Da form a em que est escrito acima, a execuo do rograma que fornece a mdia de trs nmeros dad s dificultada elo fato de que a execuo da funo scanf() faz com que o sistema aguard e a digitao dos nmeros retendidos (o cursor fica sim lesmente iscando na tela do usurio) e o usurio ode no saber o que est se assando. Alm disto, a

execuo da funo rintf() exibe a enas o resultado da ex resso, sem indicao a que aque valor se refere. Sem dvida, o rograma referido ficaria muito melhor da seguinte forma. #include <stdio.h> main() { float a, b, c; rintf("Digite trs nmeros"); sca nf("%f %f %f", &a, &b, &c); rintf("A media dos numeros %f , %f e %f igual a %f" , a, b, c, (a + b + c)/3); } A exibio de uma mensagem ode ser tambm obtida atravs d a funo uts(), cujo rotti o est no arquivo stdio.h. Por exem lo, o comando rintf(Di gite trs nmeros) ode ser substitudo elo comando uts(Digite trs nmeros).

Fixando o nmero de casas decimais O adro utilizado ela maioria dos com iladores C exibir os nmeros de onto flutua nte com seis casas decimais. O nmero de casas decimais com as quais os nmeros de onto flutuante sero exibidos ode ser alterado elo rograma. Para isso deve-se a crescentar .n ao cdigo de formatao da sada, sendo n o nmero de casas decimais retend ido. Por exem lo, se o rograma que determina a mdia de trs nmeros fosse executado ara a entrada 6.2, 8.45 e 7 seria exibido na tela o seguinte resultado A media dos numeros 6.200000, 8.550000 e 7.000000 igual a 7.250000 Se o comando de sada d o rograma fosse rintf("A media dos numeros %.2f , %.2f e %.2f igual a %.1f", a , b, c, (a + b + c)/3); a sada seria A media dos numeros 6.20, 8.55 e 7.00 igual a 7.3 Observe que a mdia dos nmeros dados, de fato, igual a 7.26. Como o cdigo da f ormatao da sada da mdia foi %.1f, ela foi exibida com uma casa decimal e o sistema e fetua os arredondamentos necessrios. Observe tambm a utilizao do onto (e no da vrgul ) como se arador das artes inteiras e fracionrias. Isto sem re necessrio quando o ambiente de rogramao que se est utilizando foi desenvolvido nos Estados Unidos, o que o mais frequente. Alinhando a sada O rograma ode fixar a coluna da tela a artir da qual o contedo de uma varivel, ou o valor de uma constante ou o valor de uma ex resso ser exibido. Isto obtido ac rescentado-se um inteiro m ao cdigo de formatao. Neste caso, m indicar o nmero de col unas que sero utilizadas ara exibio do contedo da varivel ou do valor da constante. Por exem lo, levando-se em conta que a frase "Estou a rendendo a rogramar" contm vinte e oito caracteres, o rograma abaixo #include <stdio.h> main() { rintf(" %38s", "Estou a rendendo a rogramar"); } exibe na tela a frase referida a arti r da dcima coluna. Observe que este rograma tambm exem lifica a utilizao de uma con stante (no caso, uma cadeia de caracteres) como um argumento da funo rintf(). Obs erve tambm que referncias a constantes do ti o cadeia de caracteres devem ser feit as com a cadeia escrita entre as as. As as as distinguem ara o sistema

uma cadeia de caracteres constante de um identificador de varivel. O mesmo efeito oderia ser obtido com o rograma #include <stdio.h> main() { rintf(" Estou a rendendo a rogramar"); } onde existem dez es aos em branco entre o abre as as e a letra E. Para se fixar a coluna a artir da qual e o nmero de casa decimais com que um nmero de onto flutuante ser exibido, deve-se utilizar dois armetros se ar ados or um onto. Por exem lo, considerando que se exibirmos o nmero 3.1416 com duas casas decimais ele ficar com quatro caracteres, o rograma #include <stdio.h > main() { rintf("%14.2f", 3.1416); } exibir na tela 3.14 a artir da dcima colun a. O recurso da exibio de valores utilizando um nmero r-definido de colunas ode se r utilizado ara alinhar direita a sada do rograma. Por exem lo, se os contedos d as variveis do ti o float x, y e z so 103.45, 5.3678 e 45.0, a sequncia de comandos rintf("%13.2f", x); rintf("%13.2f", y); rintf("%13.2f", z); exibe na tela 10 3.45 5.37 45.00 Vale observar que ossvel obter o mesmo efeito com uma nica ativao ( ou chamada) da funo rintf(), como veremos a seguir: rintf("%13.2f \n %13.2f \n % 13.2f ", x, y, z);

Exibindo nmeros "como caracteres" e vice-versa Uma varivel do ti o char armazena os cdigos ASCII dos caracteres su ortados elo s istema. Como este armazenamento feito atravs de cadeias de bit's, na verdade, o q ue armazenado so nmeros inteiros com reendidos entre 128 e 127. Aos nmeros de 0 a 12 7 corres ondem os caracteres de cdigo ASCII iguais ao r rio nmero e aos nmeros de 1 a -128 corres ondem os caracteres de cdigo ASCII iguais aos nmeros situados no i ntervalo de 128 a 255, res ectivamente. O cdigo de formatao da sada que indicar a fo ma como o contedo de uma varivel do ti o char ser exibido. Se c uma varivel do ti o char, ode-se associar a sua sada com os cdigos %d, %o, %x, %c. No rimeiro caso o nmero armazenado em c exibido; no segundo caso este nmero ser exibido no sistema o ctal; no terceiro, o nmero ser exibido no sistema hexadecimal e no ltimo caso ser ex ibido o caractere como comentado acima. Por exem lo, se o contedo da varivel char c 67, o comando rintf("%c %d %o %x", c, c, c, c); exibir na tela C 67 103 43

A razo disto que 67 o cdigo ASCII de C no sistema decimal, 103 este cdigo no sis a octal e 43 o cdigo ASCII de C no sistema hexadecimal. Quando um argumento uma constante, ele ser exibido de forma que de ende do cdigo d e

formatao. Quando a constante uma cadeia de caracteres, no h muito o que fazer: a exe cuo do comando rintf("Este comando exibir a alavra %s", " az"); exibir na tela a f rase Este comando exibir a alavra az da mesma maneira que o comando rintf("Est e comando exibir a alavra az"); que muito mais sim les. Porm, quando a constante um caractere ou um nmero inteiro, o que ser exibido de ende do cdigo de formatao. P r exem lo, o comando rintf("%c", 'A'); exibe o caractere A, enquanto que o coma ndo rintf("%d", 'A'); exibir o nmero 65. Por sua vez, o comando rintf("%d", 65); exibe o nmero 65, enquanto que o comando rintf("%c", 65); exibe o caractere A. Observe que referncias a constantes caracteres feita com o caractere escrito entr e a strofos, enquanto que referncias a cadeias de caracteres so feitas com as cadei as escritas entre as as, como j foi observado antes.

Os cdigos es eciais De acordo com a tabela abaixo, os cdigos es eciais ermitem a exibio de alguns cara cteres, como %, \, dentro de uma mensagem e a realizao de aes que ermitem a formatao da sada de modo que esta seja elegante e agradvel ara o usurio. Tabela 9 Cdigos es eciais da funo rintf() Cdigo \n \t \b \f \a \" \\ \% Ao leva o cursor ara a rxima linha executa uma tabulao executa um retrocesso leva o cursor ara a rxima gina emite um sinal sonoro (bee ) exibe o caractere " exibe o caractere \ exibe o caractere %

Uma observao interessante que o cdigo \a ode ser obtido atravs do caractere de cdig ASCII igual a 7. Assim, a execuo dos comandos rintf("\a"); e rintf("%c", 7); re alizam a mesma ao de emisso de um sinal sonoro. A utilizao do cdigo \n ermite que a xibio de constantes ou de contedos de variveis atravs da funo rintf() ossa ser fei em linhas diferentes. No exem lo dado na seo anterior sobre o alinhamento da sada d os dados, a sada oderia ser feita com uma nica chamada da funo rintf(). Re etindo o referido exem lo, se os contedos das variveis do ti o float x, y e z so 103.45, 5 .3678 e 45.0, o comando rintf("%13.2f"/n %13.2f \n %13.2f", x, y, z); exibe na tela

103.45 5.37 45.00 2.9 Comando de atribuio Armazenando dados gerados elo rograma A seo 2.7 a resentou o comando que ermite que se armazene em variveis a entrada do rograma. Agora veremos como armazenar dados gerados durante a execuo de um rogr ama. Considere um rograma ara o clculo da mdia de uma relao de nmeros. Naturalmente , a quantidade de nmeros da relao (se no foi fornecida a riori) deve ser de alguma forma determinada e armazenada em alguma varivel ara que ossa ser utilizada no clculo final da mdia retendida. O armazenamento de dados gerados elo r rio rograma, alteraes no contedo de varivei s e determinaes de resultados finais de um rocessamento so realizados atravs do com ando de atribuio, que deve ser escrito com a seguinte sintaxe. Identificador de va rivel = ex resso;

A ex resso do segundo membro ode se resumir a um valor constante ertencente ao ti o de dado da varivel do rimeiro membro, caso em que o valor armazenado naquel a varivel. Se no for este o caso, a ex resso avaliada e, se for do mesmo ti o da va rivel do rimeiro membro, o resultado armazenado na varivel. A ex resso do segundo membro ode envolver a r ria varivel do rimeiro membro. Nes te caso, o contedo anterior da varivel ser utilizado ara a avaliao da ex resso e ser ubstitudo elo valor desta ex resso. Por exem lo, se i uma varivel do ti o int ou d o ti o float o comando i = i + 1; faz com que o seu contedo seja incrementado de uma unidade. Veremos ao longo do livro que comandos do ti o i = i + 1; a arecem com muita frequncia. A linguagem C oferece uma forma sim lificada de escrever est e comando: i++;. Esta sintaxe se tornou to caracterstica da linguagem C que sua "a m liao" ara incor orar recursos de rogramao orientada a objetos foi denominada C++ (de forma semelhante, o comando i = i 1 ode ser escrito i--;). O incremento de uma varivel de uma unidade tambm ode ser obtido atravs do comando ++i e estas ex resses odem figurar em ex resses aritmticas. A diferena entre i++ e ++i ode ser en tendida no seguinte exem lo. A sequncia de comandos i = 2; j = i++; k = ++i; real iza as seguintes aes: i = 2, armazena em i o valor 2; j = i++, armazena em j o val or 2 e armazena em i o valor 3 (incrementa o valor de i); k = ++i, armazena em i o valor 4 (incrementa o valor de i) e armazena o valor 4 na varivel j. Um exem lo sim les: determinando a arte fracionria de um nmero Como dissemos na seo 2.3, o armazenamento de um valor de onto flutuante numa variv el do ti o int faz com que seja armazenada na varivel a arte inteira do valor de onto flutuante. Isto ermite que se extraia facilmente a arte fracionria de um nmero. Por exem lo, o rograma a seguir fornece a arte fracionria de um nmero dad o, calculada como a diferena entre ele e a sua arte inteira.

/* Programa que fornece a arte fracionria de um nmero dado */ #include <stdio.h> main() { float Num, Frac; int Inteiro; rintf("Digite um numero "); scanf("%f", &Num); Inteiro = Num; Frac = Num - Inteiro; rintf("A arte fracionaria de %f e' %f ", Num, Frac); } H que se ter cuidado com nmeros fracionrios. J foi dito que o s istema (e qualquer ambiente ara rogramao) no armazena exatamente todos os nmeros r eais, armazenando, de fato, a roximaes da maioria deles. Por exem lo, se modificsse mos o comando de sada do rograma anterior ara rintf("A arte fracionaria de %f e' %.9f ", Num, Frac); e o executssemos ara a entrada 2.41381 teramos como sada a frase A arte fracionaria de 2.41381 e' 0.413810015! O onto de exclamao (que no faz art e da sada do rograma) foi osto elo fato de que a sada es erada ara esta entrad a seria 0.41381. Combinando comandos de atribuio com o eradores aritmticos O comando de atribuio ode ser combinado com o eradores aritmticos ara substituir atribuies cuja ex resso do segundo membro contenha a varivel do rimeiro membro. Se x for o identificador da varivel e $ for um o erador aritmtico, a atribuio x = x $ ( ex resso); ode ser indicada, sim lesmente, or x $= ex resso; Por exem lo, x *= 4 ; equivale a x = x*4; x += 5; equivale a x = x + 5; x %= y + 1; equivale a x = x % (y + 1); x -= 5; equivale a x = x 5; x /= 2; equivale a x = x/2;. De acordo com o objetivo do livro, evitaremos a utilizao destas o es oferecidas ela linguagem C, or entendermos que elas odem dificultar a legibilidade do comand o. No nosso entendimento, s rogramadores mais ex erientes devem usar estes recur sos.

Lendo caracteres Alem da ossibilidade de se dar entrada em caracteres atravs da funo scanf() com cdi go de converso "%c", ode-se dar entrada em caracteres utilizando-se as funes getch () e getche() cujos cabealhos encontram-se no arquivo conio.h. Para a execuo destas funes necessrio que se acione uma tecla; quando isto feito, o caractere corres ond ente retornado ela funo e ode ento ser armazenado numa varivel do ti o char atravs de um comando de atribuio. A diferena entre estas funes que na rimeira o caractere igitado no a arece na tela de trabalho, o que acontece com a segunda funo. Por

exem lo, a execuo do rograma #include <stdio.h> #include <conio.h> main() { char c; c = getch(); rintf("Voce digitou a letra %c \n", c); } digitando-se a letra A deixa a tela de trabalho da seguinte forma Voce digitou a letra A enquanto que a execuo do rograma #include <stdio.h> #include <conio.h> main() { char c; c = g etche(); rintf("Voce digitou a letra %c \n", c); } deixa a tela de trabalho da seguinte forma: A Voc digitou a letra A 2.10 Exem los Parte I 1. Voltando ao rograma do clculo da mdia de trs nmeros dados, observe que a mdia foi calculada e exibida, mas no foi armazenada. Se este rograma fizesse arte de um rograma maior (e isto normalmente acontece! No se usa com utao ara uma questo to s im les!) e esta mdia fosse necessria em outra arte do rograma, aquele trecho ter ia que ser rescrito. uma boa rtica, ortanto, que resultados finais de rocessam ento sejam armazenados em variveis, sendo ento os contedos destas variveis exibidos atravs da funo rintf(). Assim, o rograma referido ficaria melhor escrito da segui nte forma. /* Programa que determina a mdia de trs nmeros dados */ #include <stdio. h> main() { float a, b, c, Media; uts("Digite trs nmeros"); scanf("%f %f %f", &a, &b, &c); Media = (a + b + c)/3; rintf("A media dos nmeros %f , %f e %f igual a %f ", a, b, c, Media); } 2. Agora a resentaremos um rograma que recebendo um nme ro inteiro como entrada fornece o algarismo da casa das unidades deste nmero, que sto discutida no ca tulo 1. Como vimos naquele ca tulo, o algarismo rocurado o res to da diviso do nmero dado or 10. Temos ento o seguinte rograma (no ca tulo 6 vere mos um rograma que necessita da soluo desta questo). /* Programa que determina o a lgarismo da casa das unidades de um inteiro dado */ #include <stdio.h> main() {

int Num, Unidades; rintf("Digite um inteiro"); scanf("%d", &Num); Unidades = Nu m % 10; rintf("O algarismo da casa das unidades de %d e' %d ", Num, Unidades); } 3. Se quisssemos um rograma ara inverter um nmero com dois algarismos ( or exe m lo, se a entrada fosse 74, a sada deveria ser 47) oderamos utilizar o seguinte fato: se x e y so os algarismos de um nmero (casa das dezenas e casa das unidades, res ectivamente), ento este nmero x . 10 + y. Assim, a inverso seria y . 10 + x e bastaria extrair os dois algarismos do nmero dado e utilizar a ex resso acima. A e xtrao do algarismo da casa das unidades foi mostrada no exem lo anterior. E o alga rismo da casa das dezenas? Basta ver que ele o quociente da diviso do nmero or 10 e este quociente obtido atravs do o erador / com o erandos inteiros. Temos ento o seguinte rograma. /* Programa que inverte um nmero com dois algarismos */ #incl ude <stdio.h> main() { int Num, Unidades, Dezenas, Invertido; rintf("Digite um inteiro com dois algarismos"); scanf("%d", &Num); Unidades = Num % 10; Dezenas = Num/10; Invertido = Unidades * 10 + Dezenas; rintf("O invertido de %d e' %d ", Num, Invertido); } Dificilmente o caro leitor vai escrever um rograma com este objetivo ( ara que serve inverter um nmero com dois algarismos?). Esta questo e algumas outras esto se ndo discutidas aqui a enas como exem los ara o desenvolvimento da lgica de rogr amao e elo fato de que odem ser trechos de rogramas maiores, o que ser mostrado no rximo exem lo. 4. Imagine que queiramos um rograma que determine o menor mlti lo de um inteiro dado maior do que um outro inteiro dado. Por exem lo, se a entrada fosse 13 e 10 0, a sada deveria ser 104 (104 o menor mlti lo de 13 que maior que 100). Como divi dendo = divisor x quociente + resto e resto < divisor, temos que o valor da ex r esso dividendo - resto + divisor o mlti lo rocurado.

/*Programa que determina o menor mlti lo de um inteiro maior que outro inteiro*/ #include <stdio.h> main() { int Num, Divisor, MenMulti lo; rintf("Digite o inte iro do qual o nmero rocurado deve ser mlti lo"); scanf("%d", &Divisor); rintf("D igite o inteiro que deve ser menor que o mlti lo \n"); scanf("%d", &Num); MenMult i lo = Num - Num % Divisor + Divisor; rintf("O menor multi lo de %d maior do qu e %d e' %d \n", Divisor, Num, MenMulti lo); } 5. Vamos utilizar o raciocnio desen volvido no exem lo anterior ara escrever um rograma que ser arte fundamental d e uma a licao rtica a ser discutida no rximo ca tulo. O exem lo mostrar tambm algo is ou menos bvio, mas que deve ser destacado: um rogramador s ca az de escrever u m rograma que resolva um determinado roblema se ele souber resolver o tal rob lema "na mo", ou seja,

com a utilizao a enas de l is e a el. Trata-se de um rograma ara determinar a qu antidade de mlti los de um inteiro dado k com reendidos (estritamente) entre dois inteiros x e y dados. Por exem lo, se a entrada for k = 7, x = 10 e y = 42, o rograma deve retornar a mensagem a quantidade de mlti los de 7 com reendidos entr e 10 e 42 4 (que so 14, 21, 28, 35). Uma soluo na mo desta questo utiliza rogress tmticas, assunto da Matemtica que estudada no Ensino Mdio. Uma rogresso aritmtica d rimeiro termo a1 e razo r uma sequncia de nmeros a1, a2, ..., an cuja diferena ent re dois termos consecutivos constante e igual a r. fcil rovar que an = a1 + (n 1 )r. Na nossa questo, a1 o menor mlti lo de k maior que x (exem lo anterior), an o maior mlti lo de k menor que y e r igual a k. fcil ver que o maior mlti lo de k men or que y dado or (y 1) (y 1) % k, sendo y 1 utilizado ara gerenciar o caso em que y mlti lo de k, j que queremos mlti los de k menor que y. /*Programa que determ ina o nmero de mlti los de um inteiro k situados entre dois inteiros x e y*/ #incl ude <stdio.h> main() { int i, x, y, a, k, NumMulti los = 0; rintf("Digite os in teiros x e y (y > x)"); scanf("%d %d", &x, &y); a = y - 1; rintf("Digite o inte iro k \n"); scanf("%d", &k); NumMulti los = (a - a % k - x + x % k)/k; rintf("O nmero de multi los de %d com reendidos entre %d e %d e' %d \n", k, x, y, NumMult i los); } 6. O rograma a seguir, alm de ser muito interessante no sentido do des envolvimento da lgica de rogramao, ser utilizado (a sequncia de comandos da funo ma )) em outros rogramas. Seu objetivo ermutar os contedos de duas variveis. Ou sej a, su onhamos que, atravs de comandos de entrada o rograma armazenou nas variveis x e y os valores 7 e 18 e retendamos que o rograma faa com que o contedo de x asse a ser 18 e o de y asse a ser igual a 7. rimeira vista, bastaria a sequncia de comandos x = y; y = x; Ocorre que, quando o segundo comando fosse executado, o rimeiro j teria sido e o contedo de x no seria mais o original. No nosso exem l o, teramos a seguinte situao x 17 8 y 8 8 e a ermuta no teria sido feita, alm do fat o de que o contedo original de x teria sido erdido. Uma alternativa considerar u ma varivel auxiliar que "guarde" o contedo de x antes que este seja substitudo elo contedo de y. Teramos assim o seguinte rograma. /* Programa que ermuta os conted os de duas variveis */ #include <stdio.h> main() { float x, y, Aux; rintf("Digit e os dois numeros "); scanf("%f %f", &x, &y); rintf("Entrada x = %0.1f, y = %0. 1f \n", x, y); Aux = x;

x = y; y = Aux; rintf("Saida x = %0.2f, y = %0.2f \n", x, y); } Cabe observar q ue a ermuta dos contedos ode ser obtida sem a utilizao da varivel Aux. Isto deixad o ara que o leitor descubra a soluo, sendo a resentado como exerccio ro osto.

2.11 Funes de biblioteca Como dissemos na seo 2.5, os com iladores C oferecem diversas funes com objetivos rd eterminados e que odem ser executadas durante a execuo de um rograma. Para isto a execuo da funo deve ser solicitada no rograma como uma instruo, como o erando de u a ex resso ou como argumento de outra funo (a solicitao da execuo de uma funo no chamada de ativao ou chamada da funo). Para que o rogramador ossa colocar no seu rograma uma instruo que ative uma funo necessrio que ele conhea o identificador da no, quantos e de que ti o so os argumentos com que elas devem ser ativadas e o ti o de valor que ela retorna ao rograma quando termina sua execuo (como j foi dito, e ste conjunto constitui o rotti o da funo). A definio de uma funo r-definida se fa avs da seguinte sintaxe.

Identificador da funo(Lista de argumentos) sendo que a lista de argumentos ode ser vazia. A tabela a seguir a resenta algu mas das funes rdefinidas dos com iladores C, indicando o ti o dos seus argumentos e comentando o seu valor de retorno. Tabela 12 Algumas funes de biblioteca

Identificador Argumentos O que retorna fabs(x) double Valor absoluto do argument o x acos(x) double Arco cujo valor do co-seno o argumento x asin(x) double Arco cujo valor do seno o argumento x atan(x) double Arco cujo valor da tangente o ar gumento x cos(x) double Co-seno do argumento x log(x) double Logaritmo natural d o argumento x log10(x) double Logaritmo decimal do argumento x ow(x, y) double, double Argumento x elevado ao argumento y ow10(x) int 10 elevado ao argumento x random(x) int Um nmero aleatrio entre 0 e x - 1 sin(x) double Seno do argumento x sqrt(x) double Raiz quadrada do argumento x tan(x) doubl Tangente do argumento x tolower(x) char Converte o caractere x ara minsculo tou er(x) char Converte o caractere x ara maiusculo O rotti o da funo random() se encontra no arquivo stdl ib.h e os rotti os das funes tolower() e tou er() esto no arquivo cty e.h. Os rott i os das outras funes esto no arquivo math.h que, como seu nome indica, contm os ro tti os das funes matemticas. Para que a funo random() seja ativada necessrio que s ivao seja recedida ela ativao da funo randomize() que ativa o gerador de nmero ale o. Por exem lo, o rograma abaixo exibir um nmero aleatrio entre 0 e 99. /* rogram a que exibe, aleatoriamente, um nmero entre 0 e 99 */ #include <stdio.h> #include <stdlib.h> main() { int x; randomize(); x = random(100);

rintf("%d \n", x); } O exem lo a seguir, alm de retender motivar o rximo ca tulo , ressalta uma observao j feita anteriormente: um rogramador s ca az de escrever um rograma que resolva um determinado roblema se ele souber resolver o tal robl ema "na mo", ou seja, com a utilizao a enas de l is e a el. Trata-se de um rograma que calcule a rea de um tringulo, dados os com rimentos dos seus lados. Naturalme nte, s ca az de escrever este rograma aquele que conhecer a frmula abaixo, que d a rea do tringulo cujos lados tm com rimentos a, b e c:

S= onde

p= a+ b+ c 2 o semipermetro do tringulo. Com isto, temos o seguinte programa. /*Programa que de termina a rea de um tringulo de lados de comprimentos dados*/ #include <stdio.h> # include <math.h> main() { float x, y, z, Area, SemiPer; printf("Digite os compri mentos dos lados do triangulo"); scanf("%f %f %f", &x, &y, &z); SemiPer = (x + y + z)/2; Area = sqrt(SemiPer * (SemiPer x) * (SemiPer y) * (SemiPer z)); p rintf("A area do triangulo de lados %f , %f e %f e' igual a %f \n", x, y, z, Are a); } Se este programa for executado com entrada 3, 4 e 5 temos SemiPer = 6 e S= 6 . (6 3) . (6 4) . (6 5) = 36 e, como era de se esperar, a rea do tringulo cujos lados tm comprimento 3, 4 e 5 un idades de comprimento igual a 6 unidades de rea. Agora, se este programa fosse ex ecutado para entrada 1, 2 e 5 teramos SemiPer = 4, S= 4 . (4 1) . ( 4 2 ) . ( 4 5 ) = 24 S= 4 . (4 1) . (4 2) . (4 5) = 24 e ocorreria erro de execuo pois o sistema (como era de se esperar) no calcula raiz quadrada de nmero negativo. O que acontece que nem sempre trs nmeros podem ser comprimentos dos lados de um tringulo (a matemtica prova que i sto s acontece se cada um deles for menor do que a soma dos outros dois). Assim, o comando que calcula a Area s deveria ser executado se os valores digitados para x, y, e z pudessem ser comprimentos dos lados de um tringulo. 2.12 Exerccios propostos 1. Avalie cada uma das expresses abaixo. a) ( ( 9) + sqrt(( 9)*( 9) 4*3*6))/(2* 3). b) ((pow(3, 2) == 9) && (acos(0) == 0)) (4 % 8 == 3). 2. Escreva rograma s ara a) Converter uma tem eratura dada em graus Fahrenheit ara graus Celsius. b) Gerar o invertido de um nmero com trs algarismos (exem lo: o invertido de 498 894). c) Somar duas fraes ordinrias, fornecendo o resultado em forma de frao. d) Dete rminar o maior mlti lo de um inteiro dado menor do que ou igual a um outro inteir o dado

. (

a ) . ( p b) . ( p c )

(exem lo: o maior mlti lo de 7 menor que 50 49). e) Determinar o ermetro de um o lgono regular inscrito numa circunferncia, dados o nmero de lados do olgono e o rai o da circunferncia. 3. Escreva um rograma que ermute o contedo de duas variveis s em utilizar uma varivel auxiliar (ver exem lo 5 da seo 2.9). 4. Uma loja vende seus rodutos no sistema entrada mais duas restaes, sendo a entrada maior do que ou i gual s duas restaes; estas devem ser iguais, inteiras e as maiores ossveis. Por ex em lo, se o valor da mercadoria for R$ 270,00, a entrada e as duas restaes so igua is a R$ 90,00; se o valor da mercadoria for R$ 302,75, a entrada de R$ 102,75 e as duas restaes so a iguais a R$ 100,00. Escreva um rograma que receba o valor da mercadoria e fornea o valor da entrada e das duas restaes, de acordo com as regra s acima. Observe que uma justificativa ara a adoo desta regra que ela facilita a confeco e o consequente agamento dos boletos das duas restaes. 5. Um intervalo de tem o ode ser dado em dias, horas, minutos, segundos ou sequncias "decrescentes" destas unidades (em dias e horas; em horas e minutos; em horas, minutos e segun dos), de acordo com o interesse de quem o est mani ulando. Escreva um rograma qu e converta um intervalo de tem o dado em segundos ara horas, minutos e segundos . Por exem lo, se o tem o dado for 3 850 segundos, o rograma deve fornecer 1 h 4 min 10 s. 6. Escreva um rograma que converta um intervalo de tem o dado em mi nutos ara horas, minutos e segundos. Por exem lo, se o tem o dado for 145.87 mi n, o rograma deve fornecer 2 h 25 min 52.2 s (vale lembrar que o onto o se ara dor da arte inteira). 7. Um rograma ara gerenciar os saques de um caixa eletrn ico deve ossuir algum mecanismo ara decidir o nmero de notas de cada valor que deve ser dis onibilizado ara o cliente que realizou o saque. Um ossvel critrio s eria o da "distribuio tima" no sentido de que as notas de menor valor dis onveis fos sem distribudas em nmero mnimo ossvel. Por exem lo, se a mquina s dis e de notas de 50, de R$ 10, de R$ 5 e de R4 1, ara uma quantia solicitada de R$ 87, o rogra ma deveria indicar uma nota de R$ 50, trs notas de R$ 10, uma nota de R$ 5 e duas notas de R$ 1. Escreva um rograma que receba o valor da quantia solicitada e r etorne a distribuio das notas de acordo com o critrio da distribuio tima. 8. De acord com a Matemtica Financeira, o clculo das restaes ara amortizao de um financiamento de valor F em n restaes e a uma taxa de juros i dada ela frmula P = F/ani, onde an = ((1 + i)n 1)/(i . (1 + i)n). Escreva um rograma que determine o valor das r estaes ara amortizao de um financiamento, dados o valor do financiamento, o nmero de restaes ara amortizao e a taxa de juros. Observao Pro ostas de solues dos exerc o ostos odem ser solicitadas atravs de mensagem eletrnica ara jaime@ccen.ufal.br com assunto RESPOSTAS LIVRO C, anexando o formulrio abaixo devidamente reenchid o. Nome 1 2 Categoria1 Instituio2 Curso2 Cidade/Estado Categoria: docente, estudante, autodidata Se docente ou estudante

3 Estruturas de seleo 3.1 O que uma estrutura de seleo O ltimo exem lo do ca tulo anterior a resentava um rograma ara calcular a rea de um tringulo, dados os com rimentos dos seus lados. Foi visto que o comando que ca lculava a rea solicitada s devia ser executado com a certeza anterior de que os va lores dados como entrada oderiam ser com rimentos dos lados de um tringulo. Ou s eja, o tal comando s deveria ser executado se x < y + z e y < x + z e z < x + y, condio que garante que os valores armazenados nas variveis x, y e z so com rimentos dos lados de um tringulo. Assim, em algumas situaes, alguns comandos s devem ser exe cutados se alguma condio for satisfeita. muito fcil encontrar situaes em que a execu e uma ou mais instrues deve estar condicionada ao fato de que uma condio seja satisf eita. Por exem lo, veremos algoritmos ara ordenar uma relao de nmeros que necessit am colocar em ordem crescente os contedos de duas variveis. bvio que ara ordenar e m ordem crescente os contedos de duas variveis x e y s necessrio se fazer alguma coi sa se o contedo de x for maior que o contedo de y, ou seja, se x > y. H situaes tambm em que h necessidade de que se faa uma escolha entre duas ou mais sequncias de inst rues qual a sequncia deve ser executada. Por exem lo, se retendemos verificar se u m nmero n ar odemos determinar o resto da diviso de n or 2. Se este resto for z ero, ento o nmero ar. Se este resto for 1, o nmero m ar. Vale lembrar que os algor tmos que o viver exige que executemos diuturnamente so ontuados de escolhas e de cises: se no chover, iremos ara a raia, se chover, iremos ara o sho ing; se es tiver fazendo frio, vista um casaco. A verificao de que uma condio satisfeita e, a artir da, uma determinada sequncia de comandos deve ser executada chamada de estru tura de seleo, estrutura de deciso ou comando de seleo.

3.2 O comando if O comando if uma estrutura de deciso que decide se uma sequncia de comandos ser ou no executada. Sua sintaxe if (Ex resso) { sequncia de comandos } sendo os delimitad ores o cionais se a sequncia de comandos contm um nico comando. A semntica deste com ando muito sim les: se o valor da Ex resso for diferente de zero, o sistema execu tar a sequncia de comandos; caso contrrio o sistema no executar a sequncia de comando e a instruo a s o comando if assa a ser executada. Por exem lo, se queremos um r ograma que determine o maior de dois nmeros dados, odemos su or que o rimeiro d eles o maior, armazenando-o numa varivel Maior e de ois, atravs de um comando if, verificar se o maior rocurado o segundo dos nmeros dados; neste caso o contedo da varivel Maior deve ser alterado. /*Programa ara determinar o maior de dois nmero s dados */ #include <stdio.h> main() { float a, b, Maior; rintf("Digite os dois numeros"); scanf("%f %f", &a, &b); Maior = a;

if (b > a) Maior = b; rintf("O maior dos numeros %f , %f e' %f ", a, b, Maior); } Um outro exem lo de utilizao do comando if a arece num rograma que retenda or denar os contedos de variveis x e y. Para isto s h de necessidade de se realizar alg uma ao se o contedo de y for maior do que o contedo de x. Neste caso, o que deve ser feito a ermuta dos contedos de x e de y. Temos ento o seguinte rograma. /* Prog rama ara ordenar os contedos de duas variveis */ #include <stdio.h> main() { floa t x, y, Aux; rintf("Digite os dois numeros"); scanf("%f %f", &x, &y); rintf("C onteudos originais de x e de y: %f , %f \n: ", x, y); if (y < x) { Aux = x; x = y; y = Aux; } rintf("Conteudos de x e de y ordenados: %f , %f: \n", x, y); } Ob serve que a sequncia de comandos Aux =x; x = y; y = Aux; realiza a ermuta dos co ntedos das variveis x e y, como discutido em exem lo do ca tulo anterior.

3.3 O comando if else O comando if else uma estrutura de deciso que decide entre duas sequncias de coman dos qual vai ser executada, sendo definido atravs da seguinte sintaxe: if (Ex res so) { Sequncia de comandos 1 } else { Sequncia de comandos 2 } A semntica deste coma ndo a seguinte: se o valor de Ex resso for diferente de zero, o sistema executar a sequncia de comandos 1; caso contrrio o sistema executar a sequncia de comandos 2. Por exem lo, se queremos um rograma que verifique a aridade de um nmero dado, oderamos verificar se o resto da diviso do nmero or dois igual a 0. Se isto for ve rdade, o nmero ar; se no for verdade, o nmero dado m ar. /* Programa ara verifica se um nmero e' ar */ #include <stdio.h> main() {

int x, y; rintf("Digite o numero"); scanf("%d", &x); if (x % 2 == 0) rintf("%d e' ar \n", x); else rintf("%d e' im ar \n", x); } Mesmo considerando que os c om iladores da linguagem C no consideram es aos nem mudanas de linha, observe que e stamos rocurando escrever cada instruo em uma linha e a sequncia vinculada estrutu ra de deciso com uma tabulao diferente da tabulao em que esto ostos o if e o else. E ta forma de se editar um rograma, chamada indentao, deve ser raticada or todo rogramador ois ela facilita sobremaneira a legibilidade dos rogramas. Se o ro grama acima fosse digitado da forma seguinte /* Programa ara verificar se um nme ro ar*/ #include <stdio.h> main(){ int x, y; rintf("Digite o numero"); scanf(" %d", &x); if (x % 2 == 0) rintf("%d e' ar \n", x); else rintf("%d e' im ar \n ", x); } ele seria executado da mesma forma, orm a sua legibilidade estaria rej udicada.

3.4 O o erador condicional ternrio Quando as duas o es de um comando if else contm a enas uma atribuio a uma mesma variv l, ode-se utilizar o o erador condicional ternrio que ossui a seguinte sintaxe: Varivel = Ex resso lgica ? Ex resso 1 : Ex resso 2; Na execuo deste comando a Ex re lgica avaliada e se for diferente de zero o valor da Ex resso 1 atribudo Varivel; so contrrio, o valor da Ex resso 2 atribudo. Por exem lo, se x, y e Maior so trs var eis do ti o float o armazenamento do maior dos contedos de x e de y na varivel Mai or oderia ser obtido com a seguinte atribuio: Maior = (x > y) ? x : y; Como um ou tro exem lo, ara se armazenar na varivel AbsNum o valor absoluto do contedo de um a varivel Num (sem utilizar a funo fabs()) bastaria o comando: AbsNum = (Num >= 0) ? Num : -Num;

3.5 Exem los Parte II 0. De um modo geral, as ligaes telefnicas so cobradas elas suas duraes. O sistema re istra os instantes em que a ligao foi iniciada e concluda e acionado um rograma qu e determina o intervalo de tem o decorrido entre aqueles dois instantes dados. O rograma abaixo recebe dois instantes dados em horas e minutos e determina o in tervalo de tem o (em horas e minutos) decorrido entre eles. /*Programa que deter mina o intervalo de tem o decorrido entre dois instantes*/ include <stdio.h> mai n() { int h1, min1, h2, min2, h, min; uts("Digite o instante inicial (horas e m inutos)"); scanf("%d %d", &h1, &min1);

uts("Digite o instante final"); scanf("%d %d", &h2, &min2); h = h2 - h1; min = min2 - min1; if ((h < 0) ((h == 0) && (min < 0))) uts("\aDados invalidos! O segundo instante anterior ao rimeiro"); else { if (min < 0) { h = h - 1; min = min + 60; } rintf( "Entre os instantes %dh %dmin e %dh %dmin assaram-se %dh %d min", h1, min1, h2, min2, h, min); } } 1. No ltimo exem lo do ca tulo 2, a resenta mos um rograma que calculava a rea de um tringulo, dados os com rimentos dos seus lados. No final dele, mostramos que o mesmo no fornecia res ostas satisfatrias a ra todas as entradas e comentamos que o clculo da rea deveria ser recedido da ver ificao de que os dados de entrada so de fato com rimentos dos lados de um tringulo. O rograma referido, escrito agora de forma com leta e correta, seria o seguinte . /* Programa ara calcular a rea de um tringulo*/ #include <stdio.h> #include <ma th.h> main() { float x, y, z, Area, SemiP; rintf("Digite os com rimentos dos la dos do triangulo"); scanf("%f %f %f", &x, &y, &z); if ((x < y + z) && (y < x + z ) && (z < x + y)) { SemiP = (x + y + z)/2; Area = sqrt(SemiP * (SemiP - x) * (Se miP - y) * (SemiP - z)); rintf("A area do triangulo de lados %f , %f e %f e' ig ual a %f \n", x, y, z, Area); } else rintf("Os nmeros %f, %f %f no odem ser com rimentos dos lados de um tringulo\n", x, y, z); } 2. Programas que mani ulam data s ( or exem lo, um rograma que determine o nmero de dias entre duas datas dadas) contm trechos que verificam se um ano dado bissexto. Sabendo que um ano bissexto se ele mlti lo de quatro, teramos o seguinte rograma. /*Programa que verifica se um dado ano bissexto */ #include <stdio.h> main() { int Ano; rintf("Digite o a no"); scanf("%d", &Ano); if (Ano % 4 == 0) rintf("%d e' bissexto %d \n", Ano); else rintf("%d no e' bissexto %d \n", Ano); }

Rigorosamente falando, h anos mlti los de quatro que no so bissextos. So aqueles mlti los de 100 que no so mlti los de 400. Por exem lo, o ano 2000 foi um ano bissexto, mas o ano de 2100 no ser. Para que o rograma detecte estas excees, a ex resso lgica ue controla o comando if deve ser am liada e talvez seja mais fcil considerar a c ondio ara que um ano no seja bissexto: no deve ser mlti lo de quatro ou se for mlti o de 100 no deve ser mlti lo de 400. Observe que agora o tamos or uma ex resso lgic a que garantisse o fato de que o ano dado no bissexto. /* Programa que verifica s e um dado ano bissexto */ #include <stdio.h> main() { int Ano; rintf("Digite o ano"); scanf("%d", &Ano); if ((Ano % 4 != 0) ((Ano % 100 == 0) && (Ano % 400 != 0))) rintf("%d nao e' bissexto \n", Ano); else rintf("%d e' bissexto \n", A no); } 3. O rograma ara ordenar os contedos de duas variveis, visto na seo 3.2, um caso muito articular da questo mais geral da ordenao de uma relao de nmeros ou de n mes, roblema que tem vasta a licao na vida rtica, rinci almente na ordenao de uma lista de nomes (este roblema tambm conhecido como classificao). Para a soluo geral xistem diversos algoritmos com este objetivo. No ca tulo 7 teremos o ortunidade d e discutir rogramas baseados em alguns destes algoritmos. Por enquanto, vejamos um rograma que ordene trs nmeros dados. Alm de exem lificar o comando if, o rogr ama abaixo mostra como se ode (e se deve) utilizar raciocnios anteriores ara se escrever rogramas. Seja ento um rograma que receba trs nmeros inteiros, armazene -os nas variveis x, y e z e que ao final da sua execuo deixe os contedos de x, de y e de z na ordem crescente. Uma ideia bem interessante armazenar na varivel x o me nor dos nmeros e em seguida ordenar os contedos de y e de z, que exatamente o rob lema de ordenar os contedos de duas variveis, que foi referido acima. Obviamente, ara se executar a rimeira ao retendida (armazenar na varivel x o menor dos nmeros ) s necessrio se fazer alguma coisa se o valor de x j no for o menor dos nmeros dado , ou seja, se x > y ou x > z. Nesta hi tese, o menor deles y ou z e este menor de ve ser ermutado com x. Temos ento o seguinte rograma. /* Programa ara ordenar trs nmeros dados*/ #include <stdio.h> main() { float x, y, z, Aux; rintf("Digite os tres numeros"); scanf("%f %f %f", &x, &y, &z); rintf("Numeros dados: %f , %f , %f \n", x, y, z); if ((x > y) (x > z)) /* verifica se x no o menor */ if (y < z) /* neste caso y o menor */ { Aux = x; /* troca os contedos de x e de y */ x = y; y = Aux; } else /* neste caso z o menor */ { Aux = x; /* troca os contedos de x e de z */ x = z; z = Aux; } if (y > z) /* verifica se z e y ainda no esto ord enados */ { Aux = y; /* troca o contedo de y e de z */

y = z; z = Aux; } rintf("Numeros ordenados: %f , %f , %f \n", x, y, z); } Obser ve que se a ex resso lgica do rimeiro comando if for verdadeira, o sistema execut ar outro comando if. Neste caso, dizemos que os comandos esto aninhados. Observe t ambm que escrevemos no rograma algumas frases ex licativas das aes retendidas. Es ta frases so chamadas comentrios e devem ser escritas entre os ares de caracteres /* e */. Quando o com ilador encontra o ar de caracteres /* rocura um outro ar */ e desconsidera tudo o que vem entre os dois ares. Isto ermite que o rog ramador deixe registrado no r rio rograma as observaes que ele achar conveniente. Como a edio dos rogramas com indentao, a rtica de se colocar comentrios nos rogra as muito im ortante. Como os rogramas discutidos neste livro sero recedidos de ex licaes rvias, a utilizao de comentrios aqui vai se restringir indicao do obje rograma (como j vamos fazendo). A ao realizada ela rimeira estrutura de deciso do rograma acima ode ser obtida atravs de outro algoritmo. A ideia a seguinte: co loca-se na varivel x o menor dos valores inicialmente armazenados nas variveis x e y. Em seguida, re ete-se o raciocnio com os valores armazenados (agora) em x e e m z. /* Programa ara ordenar trs nmeros dados (verso 2)*/ #include <stdio.h> main( ) { float x, y, z, Aux; rintf("Digite os tres numeros"); scanf("%f %f %f", &x, &y, &z); rintf("Numeros dados: %f , %f , %f \n", x, y, z); if (x > y) { Aux = x ; x = y; y = Aux; } if (x > z) { Aux = x; x = z; z = Aux; } if (y > z) { Aux = y ; y = z; z = Aux; } rintf("Numeros ordenados: %f , %f , %f \n", x, y, z); } 4. Um outro exem lo que ilustra muito bem a utilizao do comando if um rograma ara d eterminar as razes de uma equao do segundo grau. Sabemos da matemtica que uma equao a 2 + bx + c = 0 s tem razes reais se b2 - 4ac < 0. Assim, um rograma ara encontra r as razes reais (deixaremos o caso com leto da determinao das razes reais e com lex as como exerccio ro osto) oderia ser o seguinte. /*Programa que calcula as razes de uma equao do segundo grau */ #include <stdio.h> #include <math.h> main() { float a, b, c, Delta, x1, x2;

rintf("Digite os coeficientes"); scanf("%f %f %f", &a, &b, &c); if (a != 0) { D elta = b*b - 4*a*c; if (Delta >= 0) { x1 = (-b + sqrt(Delta))/(2*a); x2 = (-b sqrt(Delta))/(2*a); rintf("As raizes da equacao de coeficientes %f , %f e %f sa o %f e %f ", a, b, c, x1, x2); } else rintf("A equacao nao tem raizes reais"); } else rintf("A equacao nao e do segundo grau"); } 5. Imaginemos agora uma esco la que adote no seu rocesso de avaliao a realizao de duas avaliaes bimestrais e que regime de a rovao dos alunos seja o seguinte: i) Se a mdia das avaliaes bimestrais f or su erior ou igual a 7,0, o aluno est a rovado, com mdia final igual mdia das ava liaes bimestrais. ii) Se a mdia das avaliaes bimestrais for inferior a 5,0, o aluno e st re rovado, com mdia final igual mdia das avaliaes bimestrais. iii) No ocorrendo hum dos casos anteriores, o aluno se submete a uma rova final e a sua mdia final ser a mdia onderada desta rova final (com eso 4) e a mdia das avaliaes bimestrais (com eso 6). Neste caso, o aluno estar a rovado se a sua mdia final for su erior ou igual a 5,5. O rograma abaixo recebendo as notas das avaliaes bimestrais e, s e for o caso, a nota da rova final, fornece a mdia final do aluno e a sua condio e m relao a rovao. /* Programa ara verificar a rovao de um aluno*/ #include <stdio.h ain() { float Bim1, Bim2, MedBim, PrFinal, MedFinal; rintf("Digite as duas nota s bimestrais"); scanf("%f %f ", &Bim1, &Bim2); MedBim = (Bim1 + Bim2)/4; MedFina l = MedBim; if ((MedBim < 7) && (MedBim >= 5)) { rintf("Digite a nota da rova final"); scanf("%f", &PrFinal); MedFinal = (MedBim * 6 + PrFinal * 4)/10; } if ( MedFinal > 5.5) rintf("Aluno a rovado com media final %.2f \n", MedFinal); else rintf("Aluno re rovado com media final %0.2f \n", MedFinal); } 6. Para um exem lo de um rograma que utiliza vrios comandos if aninhados, su onhamos que uma em resa decidiu dar um aumento escalonado a seus funcionrios de acordo com a seguin te regra: 13% ara os salrios inferiores ou iguais a R$ 200,00; 11% ara os salrio s situados entre R$ 200,0 e R$ 400,00 (inclusive); 9 % ara os salrios entre R$ 4 00,00 e R$ 800,00 (inclusive) e 7% ara os demais salrios. Um rograma que receba o salrio atual de um funcionrio e fornea o valor do seu novo salrio oderia ser o s eguinte. /*Programa ara atualizar salrios*/

#include <stdio.h> main() { float SAtual, SNovo, Indice; rintf("Digite o salrio atual"); scanf("%f", &SAtual); if (SAtual <= 200) Indice = 1.13; else if (SAtual <= 400) Indice = 1.11; else if (SAtual <= 800) Indice = 1.09; else Indice = 1.0 7; SNovo = SAtual*Indice; rintf("Atual = %.2f \n Novo = %.2f \n" , SAtual, SNov o); } Observe que a sequncia associada o o else iniciada com um outro comando if. A lguns autores referem destacar um fato como este definindo um "novo comando" de nominando-o else if. 7. Um outro exem lo que utiliza comandos de seleo aninhados e em que a escolha da ex resso lgica que controlar o comando if im ortante um rogra ma que determine o nmero de dias de um ms (um rograma como este seria arte integ rante de um rograma que mani ulasse datas). Como os meses de trinta dias so quat ro e os de trinta e um dias so sete, usamos os rimeiros ara o controle do coman do de seleo. /* Programa que determina o nmero de dias de um ms dado */ #include <st dio.h> main() { int Mes, Ano, NumDias; rintf("Digite o mes"); scanf("%d", &Mes) ; if ((Mes == 4 ) (Mes == 6) (Mes == 9) (Mes == 11)) NumDias = 30; else if (Mes == 2) { rintf("Digite o ano"); canf("%d", &Ano); if (Ano % 4 != 0) Num Dias = 28; else NumDias = 29; } else NumDias = 31; rintf("O mes %d tem %d dias" , Mes, NumDias); } No ca tulo 6 veremos que o rograma acima ode ser bastante si m lificado.

3.6 O comando switch Muitos rogramas so desenvolvidos de modo que eles odem realizar vrias tarefas, d e forma inde endente. Por exem lo, um rograma que gerencie um caixa eletrnico de um banco deve oferecer ao usurio algumas o es em relao ao que ele retende realiz sua conta como a emisso do saldo atual, a emisso de um extrato, a realizao de um sa que e a realizao de um de sito. comum que um rograma que ermita a realizao de vri tarefas inicie a resentando ao usurio um menu de o es com a indicao das diversas tare fas que o rograma ode executar e a ermisso de que o usurio escolha a tarefa re tendida. Como, em geral, so vrias as o es dis onveis (cada uma delas com uma sequncia es ecfica de comandos) e s uma das o es ser a escolhida, necessria uma estrutura qu ecide entre vrias sequncias de comandos qual vai ser executada ou quais vo ser exec utadas. O comando switch tem este objetivo e deve ser escrito com a seguinte sin taxe: switch(Ex resso) { case constante1 : Sequncia de instrues 1 case constante2 : Sequncia de instrues 2 ... case constante n : Sequncia de instrues n default : Sequn de comando x } A, a Ex resso argumento do comando deve resultar num valor do ti o int ou num valor do ti o char e, o cionalmente, a ultima instruo de cada uma das sequncias Sequncia de instrues i break. A semntica deste comando bem sim les: a Ex sso avaliada e as sequncias de instrues situadas entre o valor da ex resso a resenta o nos cases e um comando break ou o delimitador do comando so executadas. Se o va lor da Ex resso for diferente de todas as o es dadas elas constantes associadas ao s cases, a sequncia de instrues vinculada ao default ser executada. Por exem lo, o rograma #include <stdio.h> main() { int x; rintf("Digite um nmero inteiro entre 1 e 5 \n"); scanf("%d", &x); switch (x) { case 1 : rintf("Valor de x: %d \n", x ); case 2 : rintf("Valor do dobro de %d: %d \n", x, 2*x); case 3 : rintf("Valo r do tri lo de %d: %d \n", x, 3*x); case 4 : rintf("Valor do quadru lo de %d: % d \n", x, 4*x); default : rintf("Valor digitado: %d \n", x); } } executado ara x = 1 executa todas as sequncias vinculadas aos cases fornecendo a seguinte sada: Valor de x: 1 Valor do dobro de 1: 2 Valor do tri lo de 1: 3 Valor do quadru lo de 1: 4 Valor digitado: 1 Se for executado ara x = 3, s as sequncias a artir do case 3 sero executadas e a sada ser: Valor do tri lo de 3: 9

Valor do quadru lo de 3: 12 Valor digitado: 3 e se for executado x = 10 a enas a sequncia vinculada condio default ser a executada e a sada ser: Valor digitado : 1 rs observaes: 1. A sequncia de instrues vinculada a uma o o case ode ser vazia, ca que, evidentemente, nada executado; 2. Se a enas uma sequncia de comandos deve s er executada, deve-se encerr-la com um break; 3. A o o default o cional: se ela no a arece no comando e o valor da Ex resso for diferente de todos os valores dis onve is, nada executado e a instruo logo a s o comando switch assa a ser executada. 3.7 Exem los Parte III 1. O rograma ara determinar o nmero de dias de um ms (exem lo 7 da seo anterior) oderia utilizar o comando switch: /* Programa ara determinar o numero de dias d e um mes*/ #include <stdio.h> main() { int Mes, Ano, NumDias; rintf("Digite o m es \n"); scanf("%d", &Mes); switch (Mes) { case 2 : rintf("Digite o ano"); scan f("%d", &Ano); if (Ano % 4 != 0) NumDias = 28; else NumDias = 29; break; case 4 : case 6 : case 9 : case 11 : NumDias = 30; break; default : NumDias = 31; } ri ntf("O mes de numero %d tem %d dias \n", Mes, NumDias); } Observe que se o ms de entrada for 2, o rograma ede o ano ara determinar se ele bissexto. A, determin a o nmero de dias e a instruo break encerra o comando switch. Se a entrada for 4, c om a sequncia de comandos vinculada ao case 4 vazia (e, ortanto, no contm break) a s sequncias vinculadas aos cases seguintes so executadas at o break do case 11 ( ar a os meses 4, 6, 9 e 11 o nmero de dias igual a 30!). Se a entrada no for 2, 4, 6, 9 e 11 a o o default ser executada e, ortanto, o ms ter 31 dias. Evidentemente, fic a faltando discutir a ossibilidade de uma entrada invlida como, or exem lo, 13. Isto ser discutido no rximo ca tulo. 2. Vejamos um exem lo onde a ex resso do coma ndo switch retorna um valor do ti o char. Trata-se da gerao de uma calculadora ar a as quatro o eraes aritmticas bsicas. /*Calculadora eletrnica*/ #include <stdio.h>

#include <conio.h> main() { float O 1, O 2, Res; char O erador; clrscr(); rintf ("Digite a o eraao desejada\n"); scanf("%f %c %f", &O 1, &O erador, &O 2); switch (O erador) { case '+': Res = O 1 + O 2; break; case '-': Res = O 1 - O 2; break ; case '*': Res = O 1 * O 2; break; case '/': if (O 2 != 0) Res = O 1 / O 2; bre ak; } clrscr(); if (O erador == '/' && O 2 == 0) rintf("Divisao or zero!!!"); else rintf("%.2f %c %.2f = %.2f \n", O 1, O erador, O 2, Res); getch(); } 3. Um outro exem lo interessante de utilizao do comando switch um rograma que determin e o dia da semana de uma data dada. Tomando como base o ano de 1600 (em 1582 o P a a Gregorio III instituiu mudanas no calendrio ento vigente) e sabendo que o dia rimeiro daquele ano foi um sbado, ara se determinar o dia da semana de uma data dada basta se calcular o nmero de dias decorridos entre a data dada e o dia 01/01 /1600. Como a associao do dia da semana a uma data eridica, de erodo 7, o resto da diviso do nmero de dias referido acima or 7 indica a relao entre o dia da semana rocurado e o sbado: se o tal resto for 0 (zero), o dia da semana sbado; se o resto for 1 o dia da semana domingo, e assim sucessivamente. Para calcular o nmero de dias entre uma data dada e 01/01/1600 basta multi licar o nmero de anos or 365 e acrescentar a quantidade de anos bissextos e o nmero de dias decorridos no ano c orrente. Para calcular a quantidade de anos bissextos entre 1600 e o ano da data dada basta calcular a ex resso Quantidade de mlti los de 4 Quantidade de mlti los de 100 + Quantidade de mlti los de 400, onde Quantidade de mlti los de x refere-se quantidade de mlti los de x com reendidos entre 1600 e o ano da data dada, como discutido no exem lo 5 da seo 2.10. Para calcular o nmero de dias decorridos no ano da data dada basta ...(isto est ex licado nos comentrios do rograma). /* Program a ara determinar o dia da semana de uma data dada */ #include <stdio.h> #includ e <conio.h> main() { int Dia, Mes, Ano, DiasDoAno, Dias31, AnosBiss, Aux, Mult4, Mult100, Mult400; long int Anos, NumDias; clrscr(); rintf("Digite a data no fo rmato dd/mm/aaaa\n"); scanf("%d/%d/%d", &Dia, &Mes, &Ano); Anos = Ano - 1600; /* Numero de meses com 31 dias ate o ms dado */ if (Mes < 9)

Dias31 = Mes/2; else Dias31 = (Mes + 1)/2; /*Numero de dias do ano dado, conside rando fevereiro com tendo 30 dias*/ DiasDoAno = 30*(Mes - 1) + Dia + Dias31; /*R etifica o numero de dias de fevereiro*/ if (Mes > 2) if ((Ano % 4 != 0) ((Ano % 100 == 0) && (Ano % 400 != 0))) DiasDoAno = DiasDoAno - 2; else DiasDoAno = D iasDoAno - 1; /*Numero de anos bissextos entre o ano dado e 1600*/ Aux = Ano - 1 ; Mult4 = (Aux - (Aux % 4) - 1600)/4; Mult100 = (Aux - (Aux % 100) - 1600)/100; Mult400 = (Aux - (Aux % 400) - 1600)/400; AnosBiss = Mult4 - Mult100 + Mult400; /*Numero de dias entre a data dada e 01/01/1600*/ NumDias = Anos*365 + DiasDoAno + AnosBiss; /*Dia da semana*/ rintf("\nData: %d/%d/%d Dia da semana:", Dia, Me s, Ano); switch(NumDias % 7) { case 0 : rintf(" Sabado"); break; case 1 : rint f(" Domingo"); break; case 2 : rintf(" Segunda"); break; case 3 : rintf(" Terc a"); break; case 4 : rintf(" Quarta"); break; case 5 : rintf(" Quinta"); break ; case 6 : rintf(" Sexta"); break; } getch(); } Vale observar que este rograma dar uma res osta mesmo que a data dada no seja uma data vlida, como 29/02/2009 or e xem lo. Isto ser discutido no rximo ca tulo. Vale observar tambm que o rograma rea liza elo menos duas aes com objetivos es ecficos e raciocnios r rios: o clculo do n ro de anos bissextos entre 1600 e ano da data dada e a determinao do nmero de dias decorridos no referido ano. No ca tulo 5 vamos mostrar que se ode (se deve) escr ever sub rogramas (funes) ara realizar cada uma destas aes. 3.8 Exerccios ro ostos 1. Reescreva o rograma do exem lo zero da seo 3.5 de modo que os instantes sejam dados (e o intervalo de tem o fornecido) em horas minutos e segundos. 2. Escreva um rograma que realize arredondamentos de nmeros utilizando a regra usual da ma temtica: se a arte fracionria for maior do que ou igual a 0,5, o nmero arredondado ara o inteiro imediatamente su erior, caso contrrio, arredondado ara o inteiro imediatamente inferior. 3. Escreva um rograma ara verificar se um inteiro dad o um quadrado erfeito, exibindo, nos casos afirmativos, sua raiz quadrada. 4. E screva um rograma ara determinar o maior de trs nmeros dados. 5. Escreva um rog rama ara classificar um tringulo de lados de com rimentos dados em escaleno (os trs lados de com rimentos diferentes), issceles (dois lados de com rimentos iguais ) ou equiltero (os trs lados de com rimentos iguais). 6. Escreva um rograma ara verificar se um tringulo de lados de com rimentos dados retngulo,

exibindo, nos casos afirmativos, sua hi otenusa e seus catetos. 7. Escreva um r ograma ara determinar as razes reais ou com lexas de uma equao do segundo grau, da dos os seus coeficientes. 8. Escreva um rograma ara determinar a idade de uma essoa, em anos meses e dias, dadas a data (dia, ms e ano) do seu nascimento e a data (dia, ms e ano) atual. 9. Escreva um rograma que, recebendo as duas notas b imestrais de um aluno da escola referida no exem lo 5 da seo 3.5, fornea a nota mnim a que ele deve obter na rova final ara que ele seja a rovado. Observao Pro ostas de solues dos exerccios ro ostos odem ser solicitadas atravs de mensagem eletrnica ara jaime@ccen.ufal.br com assunto RESPOSTAS LIVRO C, anexando o formulrio abai xo devidamente reenchido. Nome 1 2 Categoria1 Instituio2 Curso2 Cidade/Estado Categoria: docente, estudante, autodidata Se docente ou estudante

4. Estruturas de re etio 4.1 Para que servem as estruturas de re etio Um locutor brasileiro ao narrar um jogo de futebol americano nos Estados Unidos recebe a informao do lacar eletrnico sobre a tem eratura do estdio medida em graus Fahrenheit. Naturalmente, ele deve fornecer aos teles ectadores brasileiros a te m eratura em graus Celsius. Para isto, o locutor, de osse de um com utador, od eria utilizar o rograma abaixo, que foi solicitado no rimeiro item do segundo exerccio da seo 2.12. /*Programa que converte uma tem eratura dada em graus Fahrenh eit ara graus Celsius*/ #include <stdio.h> main() { float Fahrenheit, Celsius; rintf("Digite a tem eratura em Fahrenheit"); scanf("%f", &Fahrenheit); Celsius = 5 * (Fahrenheit - 32)/9; rintf("A tem eratura de %.2f Fahrenheit corres onde a %.2f Celsius ", Fahrenheit, Celsius); } Se o lacar eletrnico indicasse uma tem eratura de 60o F, o narrador executaria o rograma com a entrada 60 e receberia a sada A tem eratura de 60 graus Fahrenheit corres onde a 15.55 graus Celsius Ce rtamente, seria mais rtico a roduo da transmisso do evento dis onibilizar ara o l ocutor uma tabela contendo as tem eraturas ossveis em graus Fahrenheit e as corr es ondentes em graus Celsius. A confeco desta tabela oderia ser feita atravs de um rograma que contivesse vrios comandos que calculassem ara cada tem eratura em graus Fahrenheit retendida a corres ondente tem eratura em graus Celsius e exib issem estas tem eraturas. Neste caso, no haveria necessidade de comando de entrad a; orm, ara cada tem eratura em graus Fahrenheit retendida, haveria, elo meno s, um comando de atribuio e a chamada da funo rintf(). Se a faixa de tem eratura em graus Fahrenheit a ser coberta ela tabela fosse de vinte a oitenta graus, teram os um rograma como o rograma abaixo. /*Programa (muito ruim) que gera uma tabe la de converso de tem eraturas em graus Fahrenheit ara graus Celsius */ #include <stdio.h> main() { int Fahrenheit; rintf("Tabela de conversao graus Fahrenheit /graus Celsius \n"); rintf("-------------------------------------------------\n "); rintf("\t Fahrenheit \t \t Celsius\n"); rintf("------------------------------------------------\n"); Fahrenheit = 10; rintf("\t %f \t \t %f \n", Fah renheit, 5.0*(Fahrenheit - 32)/9); Fahrenheit = 11; rintf("\t %f \t \t %f \n" , Fahrenheit, 5.0*(Fahrenheit - 32)/9); ... /*Mais "uma oro" de comandos! */ Fahr enheit = 80; rintf("\t %f \t \t %f \n", Fahrenheit, 5.0*(Fahrenheit - 32)/9); } Isto seria contornado se udssemos re etir a execuo dos comandos que gerariam as tem eraturas em graus Fahrenheit e as corres ondentes em graus Celsius. A lingu agem C ossui os comandos for; while e

do while, chamados estruturas de re etio ou laos, cujas execues redundam em re eties execuo de uma determinada sequncia de comandos.

4.2 O comando for O comando for uma estrutura de re etio que re ete a execuo de uma dada sequncia de c mandos um nmero de vezes que ode ser determinado elo r rio rograma, devendo se r escrito com a seguinte sintaxe: for (inicializaes; condies de manuteno da re etio rementos) { sequncia de comandos } Como os nomes indicam, em inicializaes, so atribud os valores iniciais a variveis; em condies de manuteno da re etio, estabelecem-se, a vs de uma ex resso, as condies nas quais a execuo da sequncia de comandos ser re et em incrementos, incrementam-se variveis. Quando um comando for executado, a sequnc ia de comandos da rea das inicializaes executada. Em seguida, a ex resso que fixa as condies de manuteno da re etio avaliada. Se o valor desta ex resso no for nulo, ia de comandos executada, sendo em seguida executada a sequncia de comandos da rea dos incrementos. Novamente a ex resso das condies de manuteno da re etio avaliada do se re ete at que o seu valor seja igual a zero. Por exem lo, o rograma #inclu de <stdio.h> main() { int i; for (i = 1; i <= 10; i = i + 1) rintf("%d ", i); } exibe na tela os nmeros 1, 2, 3, 4, 5, 6, 7, 8, 9, 10. Por seu turno, o rograma #include <stdio.h> main() { int i; for (i = 10; i >= 0; i = i - 2) rintf("%d " , i); } exibe na tela os nmeros 10, 8, 6, 4, 2, 0. J o rograma #include <stdio.h> main() { int i; for (i = 1; i <= 10; i = i + 20) rintf("%d ", i); } exibe, a e nas, o nmero 1. A semntica do comando for im lica que a sequncia de comandos ode no ser executada nem uma nica vez. Basta que na " rimeira" execuo do comando for a ex resso que controla a re etio assuma o valor zero. Por exem lo, o rograma abaixo no exibe nenhum valor na tela. #include <stdio.h> main()

{ int i; for (i = 11; i <= 10; i = i + 20) rintf("%d ", i); } Com o comando for , a questo da gerao de uma tabela de converso de tem eraturas em graus Fahrenheit a ra graus Celsius seria sim les. #include <stdio.h> #include <conio.h> main() { i nt Fahrenheit; float Celsius; clrscr(); rintf("Tabela de converso graus Fahrenhe it/graus Celsius \n"); rintf("------------------------------------------------\n"); rintf("\t Fahrenheit \t \t Celsius\n"); rintf("------------------------------------------------\n"); for (Fahrenheit = 20; Fahrenheit <= 80; Fahrenhe it = Fahrenheit + 1) { Celsius = 5.0*(Fahrenheit - 32)/9; rintf("\t %.2f \t \ t %.2f \n", Fahrenheit, Celsius); } } Na execuo do comando for, a varivel Fahrenhei t inicializada com o valor 20, este valor com arado com 80, a corres ondente tem eratura em graus Celsius calculada e os dois valores so exibidos. Em seguida, o contedo de Fahrenheit incrementado de uma unidade e tudo se re ete at que Fahrenhe it atinja o valor 81. Desta forma, a execuo deste rograma gera a seguinte tabela Tabela de converso graus Fahrenheit/graus Celsius Fahrenheit Celsius 20 -6.67 21 -5.11 22 -5.56 23 -5.00 ... ... 79 26,11 80 26,67 Observe que toda a re etio contr olada ela varivel Fahrenheit. Num caso como este, a varivel em foco chamada varive l de controle da estrutura de re etio. Vale observar tambm que, ao contrrio de outra s linguagens (Pascal, or exem lo), a varivel de controle no tem que ser necessari amente do ti o int. Por exem lo, se quisssemos que a tabela tambm fornecesse tem e raturas em graus Fahrenheit fracionrias (meio em meio grau, or exem lo), oderamo s executar o seguinte rograma. #include <stdio.h> #include <conio.h> main() { f loat Celsius, Fahrenheit; clrscr(); rintf("Tabela de converso graus Fahrenheit/g raus Celsius \n"); rintf("-------------------------------------------------\n") ; rintf("\t Fahrenheit \t \t Celsius\n"); rintf("------------------------------------------------\n"); for (Fahrenheit = 20; Fahrenheit <= 80; Fahrenheit = Fahrenheit + 0.5) {

Celsius = 5.0*(Fahrenheit - 32)/9; rintf("\t %.2f \t \t %.2f \n", Fahrenheit, Celsius); } } Cabe observar que a sequncia de comandos cuja execuo se retende re etir ode ser colocada na rea dos incrementos. O rograma acima ficaria ento com a seguinte forma: #include <stdio.h> #include <conio.h> main() { float Celsius, F ahrenheit; clrscr(); rintf("Tabela de converso graus Fahrenheit/graus Celsius \n "); rintf("-------------------------------------------------\n"); rintf("\t Fa hrenheit \t \t Celsius\n"); rintf("------------------------------------------------\n"); for (Fahrenheit = 20; Fahrenheit <= 80; Celsius = 5.0*(Fahrenheit 3 2)/9, rintf("\t %.2f \t \t %.2f \n", Fahrenheit, Celsius), Fahrenheit = Fahre nheit + 0.5); } Observe que, neste caso, o comando for concludo com um onto-e-vrg ula e que a leitura do rograma fica bastante dificultada. Este fato faz com que esta rtica no seja incentivada ao longo do livro. Observe tambm que a roveitamos a o ortunidade ara a resentar mais uma funo de biblioteca do sistema; trata-se de clrscr() cuja execuo resulta na lim eza da janela do usurio, o que evita que resul tados da execuo de um rograma sejam confundidos com resultados de execues anteriore s (clrscr vem de clear screen que significa "lim a tela"). Como indicado na segu nda instruo do rograma, o cabealho da funo clrscr() encontra-se no arquivo conio.h.

4.3 O comando while Para introduzir uma nova estrutura de re etio e cotej-la com o comando for, conside re um rograma ara encontrar um divisor r rio de um inteiro dado (um divisor r rio de um inteiro n um divisor de n diferente dele e de 1). Esta questo im ortant e na verificao da rimalidade de um inteiro: um nmero que no tem divisores r rios d to rimo. Com a utilizao do comando for teramos a seguinte soluo ara esta questo. /* rograma que determina um divisor r rio de um inteiro */ #include <stdio.h> main( ) { int Num, i, Divisor; rintf("Digite um numero: "); scanf("%d", &Num); Diviso r = 0; for (i = 2; i < Num; i = i + 1) if (Num % i == 0) Divisor = i; if (Diviso r != 0) rintf("%d divisor r rio de %d \n", Divisor, Num); else rintf("%d no tem divisores r rios \n", Num); } Um roblema com este rograma que ele retorna sem re, se existir, o maior divisor r rio. Isto significa que se a entrada for um nm ero ar a estrutura de re etio no interrom ida quando o divisor 2

encontrado, o que, evidentemente, vai rejudicar a erformance do rograma. Isto ode ser contornado ois os com iladores C ermitem que uma varivel de controle de um comando for tenha o seu contedo alterado dentro do r rio comando. Com isto, o rograma acima ficaria da seguinte forma. #include <stdio.h> main() { int Num , i, Divisor; rintf("Digite um nmero inteiro: "); scanf("%d", &Num); Divisor = 0 ; for (i = 2; i < Num; i = i + 1) if (Num % i == 0) { Divisor = i; i = Num; } if (Divisor != 0) rintf("%d e' divisor r rio de %d \n", Divisor, Num); else rint f("%d no tem divisores r rios \n", Num); } Nesta verso, quando o rimeiro divisor r rio encontrado, o comando i = Num; faz com que a execuo do comando for seja inte rrom ida. A rtica de encerrar um comando for atravs da alterao do contedo da varivel de controle no ser aqui incentivada elo fato de que isto desestrutura o rograma, dificultando sua legibilidade. Alm disso, h situaes em que no se ode conhecer o nme o mximo de re eties de uma estrutura de re etio. Na verdade, a questo central que o mando for deve ser utilizado quando o nmero de re eties de execuo de uma sequncia de omandos conhecido a riori. Quando isto no acontece (que o caso do exem lo anteri or: no se sabe a riori se e quando um divisor r rio vai ser encontrado), deve-se usar o comando while, que ossui a seguinte sintaxe: while (Ex resso) { Sequncia de comandos } sendo os delimitadores o cionais se a sequncia ossui um s comando (como acontece nas outras estruturas de re etio). A semntica deste comando bvia: a sequncia de comandos executada enquanto o valor da Ex resso for diferente de zero. Naturalmente, ode ocorrer que a sequncia de coma ndos no seja executada nenhuma vez, isto ocorrendo se o valor da Ex resso for igua l a zero quando da " rimeira" execuo do comando (o teste feito antes da execuo da se quncia de comandos). Por outro lado, necessrio que um dos comandos da sequncia de c omandos altere contedos de variveis que a arecem na Ex resso de modo que em algum i nstante ela se torne igual a zero. Do contrrio, a sequncia de comandos ter sua exec uo re etida indefinidamente, o rograma nunca termina e, evidentemente, no executa a tarefa ara a qual foi desenvolvido. Quando isto acontece comum se dizer que o rograma est em loo ing. Com o comando while as questes levantadas acima sobre o rograma ara determinar um divisor r rio de um inteiro dado so resolvidas e temo s o seguinte rograma: /*Programa que determina o menor divisor r rio de um inte iro */ #include <stdio.h> #include <conio.h> main() { int Num, d, Met; rintf("D igite o numero: "); scanf("%d", &Num); Met = Num/2; d = 2;

while (Num % d != 0 && d < Met) d++; if (d <= Met) rintf("%d divisor de %d \n", d, Num); else rintf("%d no tem divisores r rios", Num); getch(); } Observe que, ao contrrio dos exem los anteriores, a estrutura tambm seria interrom ida quando a varivel com a qual se rocura um divisor atingisse a "metade" do inteiro; isto se ex lica elo fato de que se um inteiro no ossui um divisor r rio menor do que sua "metade", ento ele rimo. Esta verso ainda ode ser melhorada utilizando-se o fato discutido em [Evaristo, J 2002] de que se um inteiro no ossui um divisor r rio menor do que ou igual a sua raiz quadrada, ele no tem divisores r rios. Leva ndo isso em conta, teramos o seguinte rograma. /*Programa que determina o menor divisor r rio de um inteiro*/ #include <stdio.h> #include <conio.h> #include <ma th.h> main() { int Num, d; float r; rintf("Digite o numero: "); scanf("%d", &Nu m); r = sqrt(Num); d = 2; while (Num % d != 0 && d <= r) d++; if (d <= r) rintf ("%d divisor de %d \n", d, Num); else rintf("%d no tem divisores r rios", Num); getch(); } Como j foi dito, um nmero inteiro que no tem divisores r rios chamado nm ro rimo. Assim, o comando de sada vinculado o o else oderia ser rintf("%d rimo" , Num); Vale observar que o comando d = 2; dos rogramas acima atribuiu um valor inicial varivel d. Este valor incrementado de uma unidade enquanto um divisor no foi encontrado. Um comando de atribuio de um valor inicial a uma varivel chamado in icializao da varivel e os com iladores da linguagem C ermitem que inicializaes de va riveis sejam feitas no instante em que elas so declaradas. Assim, as declaraes de va riveis dos rogramas acima oderiam ter sido feitas da seguinte forma: int Num, i , d = 2; Neste livro, na maioria das vezes vamos o tar or inicializar as varivei s imediatamente antes da necessidade. A razo desta o o que h situaes, como mostrare no rximo exem lo, em que no se ode sim lesmente inicializar uma varivel quando d a sua declarao. Observe que o ltimo comando dos ltimos dois rogramas foi uma chamad a da funo getch(). Como j foi dito, a execuo desta funo requer a digitao de alguma Isto faz com a janela do usurio (que exibe o resultado do rocessamento) ermanea ativa at que uma tecla seja acionada.

Re etindo a execuo de um rograma Uma outra a licao im ortante do comando while diz res eito a a licaes sucessivas de um rograma. O leitor deve ter observado que os rogramas anteriores so executado s a enas ara uma entrada. Se quisermos a sua execuo ara outra entrada recisamos executar o rograma de novo. Pode-se re etir a execuo de um rograma quantas veze s se queira, colocando-o numa estrutura definida or um comando while, controlad a elo valor de algum dado de entrada. Neste caso, o valor que encerra a execuo o de ser informado dentro da mensagem que indica a necessidade da digitao da entrada . O rograma anterior oderia ser ento escrito da seguinte forma. /*Programa que determina o menor divisor r rio de um inteiro */ #include <stdio.h> #include <co nio.h> #include <math.h> main() { int Num, d; float r; rintf("Digite o numero ( zero ara encerrar): "); Num = 1; while (Num != 0) { scanf("%d", &Num); r = sqrt (Num); d = 2; while (Num % d != 0 && d <= r) d++; if (d <= r) rintf("%d divisor de %d \n", d, Num); else rintf("%d rimo", Num); } } Observe que, neste caso, a varivel d no ode ser inicializada quando da sua declarao. Observe tambm que no h essidade da funo getch(), ois a r ria re etio da execuo deixa a janela do usurio a. Alguns rogramadores referem que a re etio da execuo de um rograma seja determi nada or uma ergunta ao usurio do ti o Deseja continuar (S/N)?. Neste caso, h neces sidade de uma varivel do ti o char ara receber a res osta e controlar a re etio da execuo do rograma. #include <stdio.h> #include <cty e.h> #include <conio.h> #inc lude <math.h> main() { int Num, d; float r; char c; c = 'S'; while (tou er(c) = = 'S') { rintf("Digite o numero: "); scanf("%d", &Num); r = sqrt(Num); d = 2;

while (Num % d != 0 && d <= r) d++; if (d <= r) rintf("%d divisor de %d \n", d, Num); else rintf("%d rimo", Num); uts("Deseja continuar (S/N)?"); c = getch( ); } } Vale lembrar que a funo tou er() retorna o argumento no formato maiusculo. Esta funo foi ativada aqui ara que o usurio no se reocu e em digitar como res ost a letras maiusculas. Qualquer letra que for digitada, a funo a torna maiuscula e o sistema a com ara com S (maiusculo).

4.4 O comando do while Como dissemos na seo anterior, o nmero de execues da sequncia de comandos associada a um comando while ode ser zero. H situaes onde im ortante se garantir a execuo de um sequncia de comandos elo menos uma vez. Uma situao onde isto im ortante a verific ao da consistncia dos dados de entrada. Esta ao consiste em se dotar o rograma de re cursos ara recusar dados incom atveis com a entrada do rograma, s "recebendo" da dos que satisfaam s es ecificaes (lgicas ou estabelecidas) dos dados de entrada. Por exem lo, se a entrada um nmero corres ondente a um ms do ano, o rograma no deve ac eitar uma entrada que seja menor do que 1 nem maior do que 12. Uma soluo ara esta questo utilizando o comando while oderia ser a seguinte: int Mes; rintf("Digit e o ms: "); scanf("%d", &Mes); while ((Mes < 1) (Mes > 12)) { rintf("\a Digit acao errada! Digite de novo \n"); rintf("Digite o ms: "); scanf("%d", &Mes); } O bserve que, como a verificao da condio de re etio feita no "incio" do comando, h sidade de uma leitura antes da estrutura e outra dentro dela (s ara lembrar, \a emite um bee ). O comando do while define uma estrutura de re etio que garante que uma sequncia de comandos seja executada elo menos uma vez. Sua sintaxe : do { Se quncia de comandos; } while (Ex ressao); e sua semntica a seguinte: a sequncia de c omandos executada e a Ex resso avaliada; se o valor da Ex resso for diferente de z ero, a sequncia de comandos novamente executada e tudo se re ete; do contrrio, o c omando que segue a estrutura executado. im ortante observar a necessidade do on to-evrgula encerrando o do while. A consistncia da entrada de um dado relativo a u m ms utilizando um comando do while oderia ser a seguinte. int Mes; do { rintf( "Digite mes: ");

scanf("%d", &Mes); if ((Mes < 1) (Mes > 12)) rintf("\a Digitacao errada! Dig ite de novo \n"); } while ((Mes < 1) (Mes > 12)); A utilizao do comando do whil e ara execues sucessivas de um rograma mais natural, quando a re etio da execuo a atravs da res osta ergunta Deseja continuar (S/N)? . Teramos algo como: #includ e <stdio.h> main() { char Res ; do { Sequncia de comandos do rograma ro riament e dito; rintf("Deseja continuar (S/N)?"); scanf("%c", &Res ); } while (tou er( Res ) == 'S'); }

4.5 O comando break em estruturas de re etio Da mesma forma que sua ativao num case interrom e a execuo de uma estrutura switch, a execuo de um comando break dentro de uma estrutura de re etio interrom e as execues da sequncia de comandos da estrutura, mesmo que a condio de manuteno da re etio no sido negada. Com o uso do break, o rograma acima que determinava o menor divis or r rio de um inteiro oderia ter a seguinte forma: #include <stdio.h> #include <math.h> main() { float r; int Num, d; rintf("Digite um numero : "); scanf("%d ", &Num); d = 2; r = sqrt(Num); while (d <= r) if (Num % d == 0) break; else d = d + 1; if (d <= r) rintf("%d e' divisor ro rio de %d \n", d, Num); else rint f("%d e' rimo \n", Num); } Neste livro, o uso do break em estruturas de re etio no ser estimulado visto que sua utilizao ode trazer roblemas de legibilidade aos r ogramas.

4.6 Exem los Parte IV 1. Consideremos um rograma ara determinar a soma dos n rimeiros nmeros m ares, n dado. Por exem lo, se for fornecido ara n o valor 6, o rograma deve retornar 36, ois 1 + 3 + 5 + 7 + 9 + 11 = 36. Naturalmente, o sistema ode gerar os nmer os im ares que se retende somar, atravs do comando Im ar = 1 e da re etio do coman do Im ar = Im ar + 2. Naturalmente, tambm, ara que o sistema gere o rximo m ar, o anterior j deve ter sido somado. Isto ode ser feito atravs do comando Soma = 0 e da re etio do comando Soma = Soma + Im ar. Temos ento o seguinte rograma. /*Progr ama que soma os n rimeiros nmeros m ar, n dado*/ #include <stdio.h> main() { int Soma, Im ar, n, i; rintf("Digite o valor de n: "); scanf("%d", &n); Im ar = 1; Soma = 0; for (i = 1; i <= n; i = i + 1) { Soma = Soma + Im ar; Im ar = Im ar + 2; } rintf("Soma dos %d rimeiros nmeros im ares: %d \n", n, Soma); } Observe qu e os comandos Im ar = 1 e Soma = 0 atribuem um valor inicial s variveis ara que e stes valores iniciais ossam ser utilizados nas rimeiras execues dos comandos Som a = Soma + Im ar e Im ar = Im ar + 2. Como j dissemos, nos referimos a comandos q ue atribuem valores iniciais a variveis ara que estes valores ossam ser utiliza dos na rimeira execuo de um comando que ter sua execuo re etida como inicializao da rivel. Uma outra observao interessante que, como existe uma frmula que d o i-simo n m ar (ai = 2i - 1), o rograma acima oderia ser escrito de uma forma mais elega nte, rescindindo, inclusive, da varivel Im ar. /*Programa que soma os n rimeiro s nmeros im ar, n dado*/ #include <stdio.h> main() { int Soma, n, i; rintf("Digi te o valor de n: "); scanf("%d", &n); Soma = 0; for (i = 1; i <= n; i = i + 1) S oma = Soma + 2*i - 1; rintf("Soma dos %d rimeiros nmeros im ares: %d \n", n, So ma); } O tamos or a resentar a rimeira verso elo fato de que nem sem re a frmul a ara gerar os termos da sequncia que se retende somar to sim les ou muito conhe cida. Por exem lo, o exerccio nmero 2 da seo 4.7 ede ara somar os quadrados dos n rimeiros nmeros naturais e, neste caso, embora a frmula exista, ela no to conhecida . 2. Um dos exem los da seo anterior a resentava um rograma que determinava, se e xistisse, um divisor r rio de um inteiro dado. Imaginemos agora que queiramos um rograma que a resente a lista de todos os divisores de um inteiro n dado. Nest e caso, o rograma ode ercorrer todos os inteiros desde um at a metade de n ver ificando se cada um deles um seu divisor. Temos ento o seguinte rograma. #includ e <stdio.h>

main() { int Num, i; rintf("Digite o numero: "); scanf("%d", &Num); rintf("Div isores r rios de %d: \n", Num); for (i = 2; i <= Num/2; i = i + 1) if (Num % i = = 0) rintf("%d \n", i); } Vale observar que, ao contrrio do que foi dito na seo 2. 9, os valores de sada deste rograma no esto sendo armazenados. O que acontece que ainda no temos condies de armazenar uma quantidade indefinida de elementos. Este r oblema ser resolvido no ca tulo 6. 3. Na seo 1.5 discutimos um algoritmo que determi nava o quociente e o resto da diviso entre dois inteiros ositivos dados. Embora os com iladores de C ossuam o o erador % que calcula o resto de uma diviso intei ra entre dois inteiros ositivos, vamos a resentar, or ser interessante, a im l ementao do algoritmo referido. /*Programa que determina o quociente e o resto da d iviso entre dois inteiros ositivos*/ #include <stdio.h> main() { int Dividendo, Divisor, Quoc, Resto; rintf("Digite o dividendo e o divisor (diferente de zero! ): "); scanf("%d %d", &Dividendo, &Divisor); Quoc = 1; while (Quoc * Divisor <= Dividendo) Quoc = Quoc + 1; Quoc = Quoc - 1; Resto = Dividendo - Quoc * Divisor; rintf("Quociente e resto da diviso de %d or %d: %d e %d\n", Dividendo, Divisor , Quoc, Resto); } 4. Em muitos casos h necessidade de que um dos comandos da sequn cia que ter sua execuo re etida atravs de uma estrutura de re etio seja uma outra est utura de re etio (num caso deste dizemos que as estruturas esto aninhadas). Para um exem lo, sejam A = {1, 2, 3, ..., n} e um rograma que retenda exibir o rodut o cartesiano AxA. Observe que ara cada valor da rimeira com onente o rograma deve gerar todas as segundas com onentes. Devemos ter, ortanto, uma estrutura d e re etio ara gerar as rimeiras com onentes e uma outra, vinculada a cada valor da rimeira com onente, ara gerar as segundas com onentes. /*Programa ara gera r um roduto cartesiano*/ #include <stdio.h> main() { int n, i, j; rintf("Digit e o numero de elementos do conjunto: "); scanf("%d", &n); rintf("{"); for (i = 1; i <= n; i = i + 1) for (j = 1; j <= n; j = j + 1) rintf("(%d, %d), ", i, j); rintf("}"); } 5. interessante observar que a varivel de controle da estrutura i nterna ode de ender da varivel de controle da estrutura externa. Por exem lo, se ao invs dos ares ordenados, quisssemos os subconjuntos do conjunto A com dois el ementos, o rograma no deveria exibir o subconjunto {1, 1}, que ossui um s elemen to, e deveria exibir a enas um dos subconjuntos {1, 2} e {2, 1} j que eles so igua is. Isto ode ser

obtido inicializando j com uma unidade maior do que o valor de i. /*Programa ar a gerar um conjunto de subconjuntos de um conjunto*/ #include <stdio.h> main() { int n, i, j; rintf("Digite o numero de elementos do conjunto: "); scanf("%d", &n); rintf("{"); for (i = 1; i <= n; i = i + 1) for (j = i + 1; j <= n; j = j + 1) rintf("{%d, %d}, ", i, j); rintf("}"); } 6. Seja um rograma ara o clculo da mdia de uma dada quantidade de nmeros. Na seo 1.5 discutimos um algoritmo ara de terminar a mdia de 10.000 nmeros dados. Na ocasio discutimos que utilizaramos uma nic a varivel ara receber os nmeros sendo que um valor subsequente s seria solicitado de ois que o anterior fosse " rocessado". A diferena agora que a quantidade de nme ros ser um dado de entrada, o que torna o rograma de a licao mais variada. Como a quantidade de nmeros ser dada, odese utilizar uma estrutura for ara receber e so mar os nmeros. /*Programa ara calcular a media de n numeros, n dado*/ #include < stdio.h> main() { int n, i; float Num, Soma, Media; Soma = 0; rintf("Digite o n umero de elementos: "); scanf("%d", &n); rintf("\n Digite os elementos:"); for (i = 1; i <= n; i = i + 1) { scanf("%f", &Num); Soma = Soma + Num; } Media = Som a/n; rintf("Media = %f", Media); } 7. O exem lo acima tem o inconveniente de qu e sua execuo exige que se saiba anteriormente a quantidade de nmeros e isto no ocorr e na maioria dos casos. Vejamos ento um rograma ara determinar a mdia de uma rel ao de nmeros dados, sem que se conhea reviamente a quantidade deles. Neste caso, no devemos utilizar o comando for, ois no sabemos o nmero de re eties! Assim, o comand o while deve ser utilizado; orm, uma ergunta deve ser formulada: qual a ex resso lgica que controlar a estrutura? A soluo "acrescentar" relao um valor sabidament erente dos valores da relao e utilizar este valor ara controlar a re etio. Este val or conhecido como flag. Como dito logo acima, devese ter certeza que o flag no co nsta da relao. Isto no com licado, ois ao se escrever um rograma se tem conhecime nto de que valores o rograma vai mani ular e a escolha do flag fica facilitada. Por exem lo, se o rograma vai mani ular nmeros ositivos ode-se usar -1 ara o flag. Alm do flag, o rograma necessita de uma varivel (no caso Cont de contador) que determine a quantidade de nmeros da relao, ois este valor ser utilizado no clcu lo da mdia. /*Programa ara calcular a media de uma relacao de numeros*/ #include <stdio.h> main() { int Cont;

float Num, Soma, Media; Soma = 0; rintf("\n Digite os elementos(-1 ara encerra r):"); scanf("%d", &Num); Cont = 0; while (Num != -1) { Soma = Soma + Num; Cont = Cont + 1; scanf("%f", &Num); } Media = Soma/Cont; rintf("Media = %f", Media); } 8. Na seo 1.6 a resentamos o algoritmo de Euclides ara a determinao do mximo divi sor comum de dois nmeros dados. Para relembrar, vejamos como calcular o mximo divi sor comum de 204 e 84. 204 2 84 2 36 3 12

O algoritmo o seguinte: divide-se 204 or 84 obtendo-se resto 36; a artir da re ete-se divises at que o resto seja zero, sendo o dividendo da diviso atual o diviso r da diviso anterior e o divisor da diviso atual o resto da diviso anterior. O ltimo divisor o mximo divisor rocurado. Escrever este algoritmo numa linguagem de ro gramao muito sim les, ois uma estrutura de re etio e comandos de atribuio ermitem e se obtenha facilmente a sequncia de divises desejadas, atualizando o dividendo, o divisor e o resto. /*Programa ara determinar o mximo divisor comum de dois nmeros ositivos*/ #include <stdio.h> main() { int x, y, Dividendo, Divisor, Mdc, Rest o; rintf("Digite os dois numeros \n"); scanf("%d %d", &x, &y); Dividendo = x; D ivisor = y; Resto = Dividendo % Divisor; while (Resto != 0) { Dividendo = Diviso r; Divisor = Resto; Resto = Dividendo % Divisor; } Mdc = Dividendo; rintf("mdc( %d, %d) = %d \n", x, y, Mdc); } Note a necessidade da utilizao das variveis Dividen do e Divisor. Alm de facilitarem a com reenso do algoritmo, elas so utilizadas no rocessamento e tero seus contedos alterados durante a execuo do rograma. Se usssemos as variveis x e y, os valores dos dados de entrada seriam erdidos o que, eviden temente, no deve ocorrer. No ca tulo 5, quando estudarmos funes, estas variveis tero utra conotao. rimeira vista, o rograma deveria inicialmente determinar o maior d os nmeros x e y, armazenando-o em a. O quadro seguinte mostra que isto no necessrio , a resentando a simulao da execuo do rograma ara x = 68 e y = 148.

x 68 y 148 a 68 148 68 12 8 b 148 68 12 8 4 Resto 68 12 8 4 0 Mdc

4 9. Um outro algoritmo matemtico cuja im lementao numa linguagem de rogramao a rese nta um bom exem lo do uso de estruturas de re etio o algoritmo ara a determinao do mnimo mlti lo comum (mmc) de dois nmeros dados. Como indica a r ria denominao, o mn mlti lo comum de dois nmeros o menor nmero que divisvel elos dois nmeros. A mate a rova que o mmc de dois nmeros o roduto dos divisores rimos dos dois nmeros, c omuns ou no, ambos com as suas multi licidades. Para se obter os divisores rimos , realiza-se divises sucessivas elos rimos que so divisores de elo menos um dos nmeros. A tabela seguinte mostra o clculo do mnimo mlti lo comum dos nmeros 360 e 42 0, como nos ensinado no ensino fundamental. 360, 180, 90, 45, 15, 5, 1, 1, 4202 2102 1052 1053 353 355 77 1MMC = 2*2*2*3*3*5*7 = 2 520

Observe que, quando um divisor rimo encontrado, re ete-se a diviso, com o quocie nte no lugar do dividendo at se obter um nmero que no mlti lo daquele divisor. A, in rementa-se o tal divisor. Isto feito at que ambos os quocientes sejam iguais a 1. Temos o seguinte rograma. /*Programa ara determinar o minimo multi lo comum d e dois numeros ositivos*/ #include <stdio.h> main() { int x, y, d, a, b, i, Mmc ; rintf("Digite os dois numeros \n"); scanf("%d %d", &x, &y); a = x; b = y; Mmc = 1; i = 2; while ((a != 1) (b != 1)) { while ((a % i == 0) (b % i == 0)) { if (a % i == 0) a = a/i; if (b % i == 0) b = b/i; Mmc = Mmc * i; } i = i + 1; } rintf("mmc(%d, %d) = %d \n", x, y, Mmc); } 10. A questo do mnimo mlti lo comum muito interessante como exem lo ara a a rendizagem de rogramao elo fato de que odemos a resentar um outro algoritmo de com reenso bem mais sim les

que o anterior. A ideia a seguinte: x, 2x, 3x, etc. so mlti los de x. Para se obte r o mnimo mlti lo comum basta que se tome o rimeiro destes nmeros que seja mlti lo tambm de y. /*Programa ara determinar o mnimo mlti lo comum de dois nmeros ositivo s*/ #include <stdio.h> main() { int x, y, i, Mmc; rintf("Digite os dois numeros \n"); scanf("%d %d", &x, &y); Mmc = x; while (Mmc % y != 0) Mmc = Mmc + x; rin tf("mmc(%d, %d) = %d \n", x, y, Mmc); } 4.7 Exerccios ro ostos 1. Mostre a configurao da tela a s a execuo do rograma #include <stdio.h> main() { i nt i, a, q, Termo; for (i = 5; i > 0; i = i - 1) { a = i; q = 3; Termo = a; whil e (Termo <= 9 * a) { rintf("%d \n", Termo); Termo = Termo * q; } } } 2. Escreva um rograma que determine a soma dos quadrados dos n rimeiros nmeros naturais, n dado. 3. Escreva um rograma ara calcular a soma dos n rimeiros termos das s equncias abaixo, n dado.

1 3 5 , , , ... 2 5 8 11 1 b) 1, , , , ... 23 4 a) 4. O exemplo 10 da seo anterior apresentava uma soluo para a questo do mnimo ml comum de simples compreenso. Um problema que esta soluo possui que se o primeiro v alor digitado fosse muito menor do que o segundo, o nmero de repeties necessrias par a se chegar ao mmc seria muito grande. Refaa o exemplo, tomando o maior dos nmeros dados como base do raciocnio ali utilizado. 5. Um nmero inteiro dito perfeito se o dobro dele igual soma de todos os seus divisores. Por exemplo, como os divisor es de 6 so 1, 2, 3 e 6 e 1 + 2 + 3 + 6 = 12, 6 perfeito. A matemtica ainda no sabe se a quantidade de nmeros perfeitos ou no finita. Escreva um programa que liste to dos os nmeros perfeitos menores que um inteiro n dado. 6. O nmero 3.025 possui a s eguinte caracterstica: 30 + 25 = 55 e 55 2 = 3 025. Escreva um programa que escre va todos os nmeros com quatro algarismos que possuem a citada caracterstica. 7. Es creva um programa que escreva todos os pares de nmeros de dois algarismos que apr esentam a

seguinte propriedade: o produto dos nmeros no se altera se os dgitos so invertidos. Por exemplo, 93x13 = 39x31 = 1.209. 8. Escreva um programa para determinar o nmer o de algarismos de um nmero inteiro positivo dado. 9. Um nmero inteiro positivo di to semiprimo se ele igual ao produto de dois nmeros primos. Por exemplo, 15 semip rimo pois 15 = 3 x 5; 9 semiprimo pois 9 = 3 x 3; 20 no semiprimo pois 20 = 2 x 1 0 e 10 no primo. Os nmeros semiprimos so fundamentais para o sistema de criptografi a RSA {Evaristo, J, 2002]. Escreva um programa que verifique se um inteiro dado semiprimo. 10. Quando um nmero no semiprimo, a Matemtica prova que ele pode ser esc rito de maneira nica como um produto de potncias de nmeros primos distintos. Este p roduto chamado de decomposio em fatores primos do nmero e os expoentes so chamados d e multiplicidade do primo respectivo. Por exemplo, 360 = 23x32x5. Escreva um pro grama que obtenha a decomposio em fatores primos de um inteiro dado. 11. Escreva u m programa que transforme o computador numa urna eletrnica para eleio, em segundo t urno, para presidente de um certo pas, s quais concorrem os candidatos 83 Alibab e 93Alcapone. Cada voto deve ser dado pelo nmero do candidato, permitindo se ainda o voto 00 para voto em branco. Qualquer voto diferente dos j citados considerado nulo; em qualquer situao, o eleitor deve ser consultado quanto confirmao do seu voto . No final da eleio o programa deve emitir um relatrio contendo a votao de cada candi dato, a quantidade votos em branco, a quantidade de votos nulos e o candidato el eito. 12. A sequncia de Fibbonaci a sequncia (1, 1, 2, 3, 5, 8, 13, ...) definida por Escreva um programa que determine o n simo termo desta sequncia, n dado. 13. A srie harmnica S = 1 + existe n0 tal que 1 + 1, se n = 1 ou n = 2 an = a n 1 + an 2 , se n > 2

11 1 + + ...+ + ... divergente. Isto significa que dado qualquer real k 23 n 11 1 + + ...+ > k . Escreva um programa que dado um real k determine o menor 23 n0 inteiro n0 tal que S > k. Por exemplo se k = 2, o programa deve fornecer n0 = 4, pois 1+ 111 11 + + = 2 ,083.... e 1 + + = 1,8333.... 234 23

14. Dois nmeros inteiros so ditos amigos se a soma dos divisores de cada um deles (menores que eles) igual ao outro. Por exemplo, os divisores de 220 so 1, 2, 4, 5 , 10, 11, 20, 22, 44, 55 e 110 e 1 + 2 + 4 + 5 + 10 + 11 + 20 + 22 + 44 + 55 + 1 10 = 284 e os divisores de 284 so 1, 2, 4, 71 e 142 e 1 + 2 + 4 + 71 + 142 = 220. Escreva um programa que determine todos os pares de inteiros amigos menores que um inteiro dado. 15. Escreva um programa que escreva todos os subconjuntos com trs elementos do conjunto {1, 2, 3, ..., n}, n dado. 16. Um inteiro positivo x di to uma potncia prima se existem dois inteiros positivos p e k, com p primo, tais que x = pk. Escreva uma funo que receba um inteiro e verifique se ele uma potncia p rima. 17. Um inteiro positivo x dito uma potncia perfeita de base z e expoente y se existem dois inteiros positivos z e y tais que x = zy. Escreva uma funo que rec eba um inteiro e verifique se ele uma potncia perfeita. Observao Propostas de solues dos exerccios propostos podem ser solicitadas atravs de mensagem eletrnica para jai me@ccen.ufal.br com assunto RESPOSTAS LIVRO C, anexando o formulrio abaixo devida mente preenchido. Nome 1 2 Categoria1 Instituio2

Curso2 Cidade/Estado Categoria: docente, estudante, autodidata Se docente ou estudante

5. Funes e ponteiros 5.1 O que so funes Como dissemos no captulo 2, um programa em C pode (e deve) ser escrito como um co njunto de funes que so executadas a partir da execuo de uma funo denominada main(). a funo pode conter declaraes de variveis, instrues, ativaes de funes do sistema funes definidas pelo programador. Naturalmente, o objetivo de uma funo deve ser a r ealizao de alguma "sub tarefa" especfica da tarefa que o programa pretende realizar . Assim, pode se escrever funes para a leitura dos dados de entrada, para a sada do programa, para a determinao da mdia de vrios elementos, para a troca dos contedos de uma varivel, para o clculo do mximo divisor comum de dois nmeros dados, etc. Normal mente, a realizao da "sub tarefa" para a qual a funo foi escrita chamada de retorno da funo. Este retorno pode ser a realizao de uma ao genrica, como a leitura dos dado e entrada, ou um valor especfico, como o clculo do mximo divisor comum de dois nmero s dados.

Como foi dito na seo citada, uma funo deve ser definida com a seguinte sintaxe: Tipo de Dado Identificador da funo(Lista de parmetros) { Declarao de variveis Sequnc de instrues } onde, como tambm j foi dito, o conjunto Tipo de Dado Identificador da funo(Lista de parmetros) chamado prottipo da funo. A, Tipo de dado int, char, fl um dos seus "mltiplos", quando a funo deve retornar um valor especfico e void se a funo deve realizar uma ao genrica sem retornar um valor definido. Por seu turno, List a de parmetros um conjunto de variveis utilizadas para a funo receber os valores par a os quais a funo deve ser executada; estes valores so chamados argumentos, que, co mparando uma funo com um programa, constituem os dados de entrada da funo. Na declar ao de variveis so declaradas as variveis que as instrues da funo vo manipular int . Estas variveis (e os parmetros da funo) s so acessveis pelas instrues da funo razo, so chamadas variveis locais (na seo 5.5 so apresentados maiores detalhes). Se funo deve retornar um valor, uma de suas instrues deve ter a seguinte sintaxe: retu rn (expresso); sendo os parnteses facultativos. A semntica desta instruo evidente: a expresso avaliada e o seu valor retornado funo que a ativou. Alm disso (e isto ag no evidente), a execuo desta instruo interrompe a execuo da funo e o processame na funo que ativou a funo em discusso. A ativao (ou chamada) da funo por outra f com a referncia ao identificador da funo seguido dos argumentos em relao aos quais se pretende executar a funo. Por exemplo, o clculo do mximo divisor comum de dois nmero s dados, discutido no captulo anterior, poderia ser reescrito da seguinte forma: /*Funo que retorna o mximo divisor comum de dois nmeros positivos dados*/ int MaxDiv Com(int x, int y) { int Resto; Resto = x % y; while (Resto != 0) { x = y; y = Re sto; Resto = x % y; } return (y); }

/*Funo principal: recebe os nmeros e ativa a funo MaxDivCom()*/ main() { int Mdc, a, b; printf("Digite os dois inteiros"); scanf("%d %d", &a, &b); Mdc = MaxDivCom(a, b); printf("Mdc(%d, %d) = %d \n", a, b, Mdc); } Se este programa for executado para a entrada a = 204 e b = 184, a execuo do comando Mdc = MaxDivCom(a, b) chamar ia a execuo da funo, recebendo o parmetro x o contedo de a e o parmetro y o contedo . Ou seja, as instrues da funo seriam executadas para a entrada x = 204 e y = 184 e teramos a seguinte sequncia de valores para as variveis locais x, y e Resto at a int errupo da estrutura while: x 204 184 20 Mdc = MaxDivCom(a, b) e o valor 4 armazena do na varivel Mdc. Em alguns sistemas, uma funo s pode ativar uma outra funo que foi efinida previamente (como no exemplo anterior) ou cujo prottipo esteja explicitad o como uma das suas instrues. Por exemplo, o programa aqui referido poderia ter o seguinte formato: main() { int Mdc, a, b; int MaxDivCom(int x, int y); /*Prottipo da funo que vai ser definida posteriormente */ printf("Digite os dois inteiros"); scanf("%d %d", &a, &b); Mdc = MaxDivCom(a, b); printf("Mdc(%d, %d) = %d \n", a, b, Mdc); } int MaxDivCom(int x, int y) { int Resto; Resto = x % y; while (Resto != 0) { x = y; y = Resto; Resto = x % y; } return (y); } y 184 20 4 Resto 20 4 0 Neste instante, a instruo return (y) executada e o processamento retorna ao comand o 5.2 Para que servem funes Evidentemente, no h grandes vantagens do programa que calcula o mximo divisor comum escrito

com uma funo em relao quele do exemplo j citado, que realizava todas as aes necess ntro da funo main(). Na verdade, a utilizao de funes s bastante vantajosa quando s ta de programas grandes, capazes de realizar diversas tarefas independentes, mas relacionadas. Por exemplo, um programa que gerencie as contas correntes de um b anco deve ser capaz, entre outras coisas, de fornecer o saldo de uma dada conta; atualizar o saldo em funo da ocorrncia de uma retirada ou de um depsito; cadastrar uma nova conta; excluir do cadastro uma dada conta, etc. Naturalmente, embora es tas tarefas estejam relacionadas, deve se pretender que elas sejam realizadas de forma independente, pois um dado cliente num dado momento pode querer a realizao de apenas uma delas. Num caso como este, o programa deve possuir uma funo para cad a uma das tarefas pretendidas, ficando a cargo da funo main() a chamada de uma ou de outra funo de acordo com a tarefa pretendida. Isto permite que vrios programador es desenvolvam o programa (cada um desenvolvendo algumas funes), facilita a realiz ao de testes de correo do programa (as funes podem ser testadas de forma isolada) e a manuteno posterior do programa (modificaes necessrias no programa podem ficar restrit as a modificaes em algumas das funes). Na verdade, a modularizao do programa s traz efcios e deve ser uma prtica de todo programador. comum que um programa "multi tar efa" como o exemplificado acima seja iniciado com a disponibilizao para o usurio da s diversas tarefas que ele capaz de executar. Normalmente, este conjunto de tare fas chamado de menu de opes e pode ser obtido atravs de uma funo que no retorna nen valor. Considerando apenas as tarefas listadas acima, o menu de opes do programa referido poderia ser construdo a partir da seguinte funo. void Menu() { printf("1 S aldo \n 2 Depsito \n 3 Retirada \n 4 Nova conta \n 5 Encerra conta \n 6 Sai do pr ograma);" } Neste caso, uma das primeiras instrues da funo main() a ativao da fun ) com a simples referncia ao seu identificador seguido de parnteses vazios e de po nto e vrgula: main() { Menu(); ... } Observe que esta funo exemplifica uma funo que n retorna um valor (da ser do tipo void) e cuja Lista de parmetros vazia. Atualment e, com a disponibilizao das linguagens visuais (VisualBasic, Delphi e outras), os menus de opes so disponibilizados atravs de interfaces programa/usurio (contendo bote , banners e outras denominaes) e as ativaes das funes que executam a tarefa pretendid feita atravs de mouses ou mesmo atravs de toque manual na tela do computador. Exi stem algumas bibliotecas grficas que permitem que se criem interfaces de programa s em C; porm, o estudo destas bibliotecas no est no escopo deste livro. Outra aplic ao importante de funes se d quando h necessidade de que o programa determine a mesma randeza para valores diferentes. Um exemplo tpico desta necessidade aparece num p rograma que determine medidas estatsticas, como mdia aritmtica, mediana, desvio mdio , desvio padro, de uma relao de nmeros. Como o desvio mdio a mdia aritmtica dos va absolutos dos desvios em relao mdia, o seu clculo exigir a determinao da mdia ar da relao e a mdia aritmtica dos desvios. Escreveremos ento uma funo para o clculo d de uma relao qualquer e a utilizaremos para os clculos das duas mdias necessrias. Es te exemplo ser visto no captulo seguinte. 5.3 Passagem de parmetros Uma outra possvel utilizao de funes para substituir uma sequncia de instrues que te em vrias partes do programa. Por exemplo, o exemplo 3 da seo 3.4 apresentava um programa para ordenar trs nmeros:

/* Programa para ordenar tres numeros dados*/ #include <stdio.h> main() { float x, y, z, Aux; printf("Digite os tres numeros"); scanf("%f %f %f", &x, &y, &z); p rintf("Numeros dados: %f , %f , %f \n", x, y, z); if ((x > y) (x > z)) /* ver ifica se x no o menor */ if (y < z) /* neste caso y o menor */ { Aux = x; /* troc a os contedos de x e de y */ x = y; y = Aux; } else /* neste caso z o menor */ { Aux = x; /* troca os contedos de x e de z */ x = z; z = Aux; } if (y > z) /* veri fica se z e y ainda no esto ordenados */ { Aux = y; /* troca o contedo de y e de z */ y = z; z = Aux; } rintf("Numeros ordenados: %f , %f , %f \n", x, y, z); } Ob serve que uma sequncia de comandos com o mesmo objetivo (trocar os contedos de dua s variveis) se re ete. Num caso como este oderamos escrever uma funo que realizasse aquela ao retendida e, ento, esta funo seria utilizada ara substituir a sequncia r ferida. Por enquanto temos o seguinte roblema. Se definirmos a funo void Troca(fl oat x, float y) { float Aux; Aux = x; x = y; y = Aux; } e a executarmos assando as variveis a e b, a enas os contedos de a e de b sero assados ara x e ara y e a troca realizada ela funo s afeta os contedos de x e de y, no modificando os conted s de a e de b que o que se retendia. Ou seja, a funo Troca recebe a enas os "valo res" de a e de b e as aes realizadas ela funo interfere a enas nos armetros x e y, no alterando nada em relao aos argumentos a e b. Neste caso, dizemos que os armetro s foram assados or valor. O sistema Turbo C++ 3.0 oferece a ossibilidade de q ue a execuo de uma funo altere contedos de variveis no locais. Para isto, no rot uno os armetros devem ser recedidos de &. Neste caso, os argumentos ara ativao da funo tm que ser variveis e qualquer alterao no contedo do armetro se reflete no co da varivel argumento. Diz-se ento que a assagem dos armetros feita or referncia. Com este ti o de assagem de armetro, o rograma acima oderia ser escrito da se guinte forma: /* Programa ara ordenar tres numeros dados*/ #include <stdio.h> void Troca(floa t &a, float &b)

{ float Aux; Aux = a; a = b; b = Aux; } main() { float x, y, z, Aux; rintf("Dig ite os tres numeros"); scanf("%f %f %f", &x, &y, &z); rintf("Numeros dados: %f , %f , %f \n", x, y, z); if ((x > y) (x > z)) if (y < z) Troca(x, y); else Tr oca(x, z); if (y > z) Troca(y, z); rintf("Numeros ordenados: %f , %f , %f \n", x, y, z); } A assagem de armetro or referncia ermite que entrada de dados seja feita atravs de uma funo. Isto ode ser til, or exem lo, em rogramas multitarefas em que o nmero de entradas ode variar de acordo com a tarefa retendida. Para e xem lificar a resentaremos um rograma ara tratar nmeros com lexos. Naturalmente , um rograma com este objetivo deve estar a to a somar e multi licar com lexos, casos em que a entrada ser dois nmeros com lexos, e a determinar o mdulo e a forma olar de um com lexo, quando entrada ser a enas de um nmero. Alm de exem lificar a entrada de dados atravs de uma funo, o rograma abaixo exem lifica um rograma mul titarefa com leto. /*Programa ara lgebra dos nmeros com lexos*/ #include <stdio.h> #include <math.h> void LeCom lexo(float &a, float &b) { uts("Digite a arte rea l <enter> arte imaginaria"); scanf("%f %f", &a, &b); } float Modulo(float a, fl oat b) { return sqrt(a*a + b*b); } void Polar(float a, float b, float &c, float &d) { c = Modulo(a, b); d = asin(b/c); } void Soma(float a, float b, float c, fl oat d, float &e, float &f) { e = a + c; f = b + d; } void Produto(float a, float b, float c, float d, float &e, float &f) { e = a*c - b*d;

f = a*d + b*c; } void Menu() { uts("1-Modulo \n 2- Forma olar \n 3-Soma \n 4-P roduto \n 5-Encerra \n Digite sua o cao: "); } main() { float x, y, z, w, t, u; int O c; Menu(); scanf("%d", &O c); switch (O c) { case 1: LeCom lexo(x, y); z = Modulo(x, y); rintf(" %.2f + %.2fi = %.2f", x, y, z); break; case 2: LeCom le xo(x, y); Polar(x, y, z, w); rintf("%.2f + %.2fi = %.2f(cos%.2f + isen%.2f)", x , y, z, w, w); break; case 3: LeCom lexo(x, y); LeCom lexo(z, w); Soma(x, y, z, w, t, u); rintf("(%.2f + %.2fi) + (%.2f + %.2fi) = %.2f + %.2fi", x, y, z, w, t , u); break; case 4: LeCom lexo(x, y); LeCom lexo(z, w); Produto(x, y, z, w, t, u); rintf("(%.2f + %.2fi) + (%.2f + %.2fi) = %.2f + %.2fi", x, y, z, w, t, u); break; } } O exem lo a seguir melhora sobremaneira a legibilidade do rograma ( arte dele) que determina o dia da semana de uma data osterior ao ano de 1600 da da a resentado no ca tulo 3. L recisvamos determinar o nmero de dias decorridos ent re 01/01/1600 e a data dada. Vimos que recisvamos determinar, entre outras coisa s: o nmero de dias j decorridos no ano da data dada ( ara isto recisvamos determin ar se tal ano era bissexto e o nmero de dias 31 j ocorridos) e a quantidade de ano s bissextos entre 1600 e o ano da data dada. A boa tcnica de rogramao sugere que c ada ao arcial do rograma seja executada or uma funo. Temos ento a seguinte ro ost a ara um rograma que determine o nmero de dias dias decorridos entre duas datas dadas (este rograma utilizado em a osentadorias: ela legislao atual (novembro d e 2008) um trabalhador de uma em resa rivada adquire o direito de se a osentar quando com leta 35 anos de servio, sendo este clculo a artir da soma do nmero de d ias trabalhados nas ( ossivelmente) vrias em resas nas quais o interessado trabal hou). /*Programa ara determinar o nmero de dias entre duas datas dadas*/ #includ e <conio.h> #include <stdio.h> #include <conio.h>

/*Verifica se um ano bissexto (retorno: Sim-1/Nao-0)*/ int EhBissexto(int Ano) { return ((Ano % 4 == 0) && ((Ano % 100 != 0) (Ano % 400 == 0))); } /*Retorna o nmero de dias 31 ocorridos at o ms dado*/ int NumDias31(int Mes) { if (Mes < 9) r eturn Mes/2; else return (Mes + 1)/2; } /*Retorna o nmero de dias de um ano at uma data dada*/ int NumDiasAteUmaData(int Dia, int Mes, int Ano) { int NumDias; //N umero de dias considerando todos os meses com 30 dias NumDias = 30*(Mes - 1); // Acrescentando o nmero de dias 31 j ocorridos no ano e o nmero de dias do ms corrente NumDias = NumDias + NumDias31(Mes) + Dia; //Retificando o nmero de dias de fever eiro (se ele j ocorreu) if (Mes > 2) if (EhBissexto(Ano)) NumDias = NumDias - 1; else NumDias = NumDias - 2; return NumDias; } /*Retorna o nmero de dias de uma a s uma data dada*/ int NumDiasA osUmaData(int Dia, int Mes, int Ano) { if (EhBisse xto(Ano)) return 367 - NumDiasAteUmaData(Dia, Mes, Ano); else return 366 - NumDi asAteUmaData(Dia, Mes, Ano); } /*Retorna o nmero de anos bissextos entre dois ano s dados*/ int NumAnosBissextos(int Ano1, int Ano2) { int Aux, Mult4, Mult100, Mu lt400; Aux = Ano2 - 1; Mult4 = (Aux - (Aux % 4) - Ano1 + (Ano1 % 4))/4; Mult100 = (Aux - (Aux % 100) - Ano1 + (Ano1 % 100))/100; Mult400 = (Aux - (Aux % 400) Ano1 + (Ano1 % 400))/400; return Mult4 - Mult100 + Mult400; } main() { int Dia1, Mes1, Ano1, Dia2, Mes2, Ano2, Anos, NumDias, DiasDoAnoFinal, DiasDoAnoInicial; clrscr(); rintf("Data inicial (dd/mm/aaaa)\n"); scanf("%d/%d/%d", &Dia1, &Mes1, &Ano1); rintf("Data final (dd/mm/aaaa)\n"); scanf("%d/%d/%d", &Dia2, &Mes2, &A no2);

Anos = Ano2 - Ano1 - 1; DiasDoAnoFinal = NumDiasAteUmaData(Dia2, Mes2, Ano2); Di asDoAnoInicial = NumDiasA osUmaData(Dia1, Mes1, Ano1); NumDias = Anos*365 + Dias DoAnoFinal + DiasDoAnoInicial + NumAnosBissextos(Ano1, Ano2); rintf("\nData ini cial: %d/%d/%dData final: %d/%d/%d Numeros de dias: %d", Dia1, Mes1, Ano1, Dia2, Mes2, Ano2, NumDias); getch(); } Embora o hel do Turbo C++ 3.0 afirme que em C a nica assagem de armetro or valor, conseguimos, no Turbo C 2.01, uma forma de assagem de armetros or referncia. Para isto utilizaremos onteiros que alm de ermitir esta forma de assagem de armetros tem outras a licaes im ortantes em rog ramao em C e em C++.

5.4 Ponteiros No ca tulo 2, foi dito que a cada osio de memria associado um nmero inteiro chamado endereo da osio de memria. Como uma varivel uma osio de memria, a cada varivel o um endereo. Um onteiro uma varivel ca az de armazenar um endereo de outra varivel , sendo declarado com a seguinte sintaxe: Ti o de dado *Identificador; A semntica desta declarao ode ser assim entendida: Identificador ca az de armazenar o ender eo de uma varivel de ti o Ti o de dado. Por exem lo, uma declarao do ti o int * ; in dica que uma varivel ca az de armazenar o endereo de uma varivel do ti o int. Na rtica dizemos que a onta ara um inteiro. Assim, onteiros tambm so chamados a o ntadores. Como onteiros so variveis, ode-se atribuir um onteiro a outro do mesm o ti o. Por exem lo, so vlidas as seguintes instrues: int * , *t, i; = &i; t = ; ois, como dissemos no ca tulo 2, o o erador de endereo & fornece o endereo da variv el em que ele est o erando. Deste modo, receber o endereo de i o que tambm acontec er com t quando da execuo do comando t = . Se um onteiro, a indicao * num rogr ma acessa o contedo da varivel ara a qual a onta. Assim odemos ter o seguinte rograma: #include <stdio.h> main() { float *a, *b; float Aux, x, y; x = 1; /* o contedo de x agora igual a 1 */ y = 2; /* o contedo de y agora igual a 2 */ a = & x; /* a a onta ara x */ b = &y; /* b a onta ara y */ Aux = *a; /* o contedo de Aux agora 1 (contedo de x) */ *a = *b; /* o contedo de x agora 2 (contedo de y) */ *b = Aux; /* o contedo de y agora 1 */ rintf("x = %f e y = %f \n", x, y); }

Temos ento um rograma - certamente um ouco sofisticado - ara ermutar os conted os de duas variveis. Qualquer que seja o ti o de varivel a ontada or um onteiro, ode-se "atribuir-lhe" a constante 0 (zero) e ode-se com arar um onteiro com esta constante. O sistema oferece uma constante simblica NULL que ode (e normalm ente o ) ser utilizado no lugar do zero ara, mnemonicamente, indicar mais claram ente que este um valor es ecial ara um onteiro. Como veremos daqui or diante, este valor es ecial de onteiro ser utilizado ara inicializaes de onteiros, ara valores de esca e de estruturas de re etio e ara retorno de funes quando alguma ao retendida no conseguida.

5.5 Passagem de armetros or referncia no Turbo C 2.01 A utilizao de onteiros como armetros de funes ermite a assagem de armetros or r ferncia no Turbo C 2.01. Considere um armetro do ti o onteiro. Como armazena r um endereo, se for assado ara o endereo de uma varivel que ossa ser a ontada or ele, qualquer ao realizada no onteiro afetar o contedo da varivel. O caso da fun Troca(), comentada na seo anterior, oderia ser definida da seguinte forma: void t roca(float *a, float *b) { float Aux; Aux = *a; *a = *b; *b = Aux; } e suas ativ aes deveriam ser feitas atravs de Troca(&x, &y).

5.6 Uma urna eletrnica A assagem de armetros or referncia tambm muito til quando se retende que uma fun retorne mais de um valor. Um destes valores ode ser retornado elo comando retu rn() e os demais odem ser retornados ara variveis que foram assadas or refernc ia ara armetros da funo. O exem lo abaixo, uma melhor res osta de um exerccio ro osto no ca tulo anterior, transforma um com utador numa urna eletrnica ara a eleio, em segundo turno, ara a residncia de um certo as, s quais concorrem dois candid atos Alibab, de nmero 89, e Alca one, de nmero 93, sendo ermitido ainda o voto em branco (nmero 99) e considerando como voto nulo qualquer voto diferente dos anter iores. A funo Confirma() deve retornar dois valores: o rimeiro ara, no caso de c onfirmao do voto, ermitir sua contabilizao e o segundo ara, ainda no caso de confi rmao do voto, interrom er a estrutura do while, o que ermitir a rece o do voto segui nte. Observe tambm a assagem or referncia do armetro da funo Com utaVoto(). H nece sidade de que seja desta forma, elo fato de que esta funo alterar contedos de varive is diferentes. #include <stdio.h> #include <cty e.h> #include <dos.h> #include < conio.h> /*Funo ara confirmao do voto*/ int Confirma(char *s, char * ) { int r; cha r Conf; rintf("Voce votou em %s! Confirma seu voto (SN)? ", s); fflush(stdin);

scanf("%c", &Conf); if (tou er(Conf) == 'S') { * = 's'; r = 1; } else { * = ' n'; rintf("\a Vote de novo: "); sound(1000); delay(80000); nosound(); r = 0; } return r; } /*Funo ara com utar cada voto confirmado ara o candidato*/ void Com utaVoto(int * ) { * = * + 1; } /*Funo rinci al*/ main() { int Alibaba, Alca one , Nulos, Brancos, Eleitores, Voto; char Sim, Cont; clrscr(); Alibaba = Alca one = Nulos = Brancos = 0; do { do { rintf(" 89 - Alibaba \n 93 - Alca one \n 99 Branco \n"); rintf("Digite seu voto: "); scanf("%d", &Voto); switch (Voto) { ca se 89: if (Confirma("Alibaba", &Sim) == 1) Com utaVoto(&Alibaba); break; case 93 : if (Confirma("Alca one", &Sim) == 1) Com utaVoto(&Alca one); break; case 99: i f (Confirma("Brancos", &Sim) == 1) Com utaVoto(&Brancos); break; default: if (Co nfirma("Nulo", &Sim) == 1) Com utaVoto(&Nulos); break; } clrscr();

} while (Sim != 's'); rintf("Outro eleitor (S/N)? "); fflush(stdin); scanf("%c" , &Cont); } while (tou er(Cont) == 'S'); Eleitores = Alibaba + Alca one + Branc os + Nulos; rintf("Total de eleitores %d \n Alibaba %d \n Alca one %d \n Branco s %d \n Nulos %d", Eleitores, Alibaba, Alca one, Brancos, Nulos); } O arquivo de cabealhos dos.h contm as funes sound(n), nosound() e delay(n). A rimeira emite um som de frequncia n hertz; a segunda interrom e a emisso de som e a terceira sus en de a execuo do rograma or n milissegundos. A razo da chamada da funo fflush() a se uinte. Em alguns sistemas, quando algum dado de entrada digitado ara execuo da fu no scanf(), os com iladores C no o armazena diretamente na osio de memria res ectiva armazenando-o inicialmente numa regio chamada buffer ara, ao final da execuo da f uno de leitura transferir o contedo do buffer ara a memria. Se quando da execuo de u a funo de leitura o contedo do buffer no estiver vazio, este contedo (naturalmente, ndesejado) que ser armazenado na varivel. A ativao de fflush(stdin) "descarrega" tod o o buffer dos dados digitados no teclado e assim a funo de leitura aguardar que o dado realmente retendido seja digitado. rudente, ortanto, receder leituras d e caracteres e de cadeias de caracteres ela chamada de fflush(stdin). Observe q ue um onteiro do ti o char ca az de armazenar uma cadeia de caracteres (mais deta lhes no ca tulo 8). Observe tambm que utilizamos inicializaes sucessivas no comando Alibaba = Alca one = Nulos = Brancos = 0. Esta forma de inicializar variveis tambm vlida, mas no ser muito utilizada neste livro. Para concluir ( or enquanto) o estu do de onteiros, vale ressalvar que, sendo variveis ca azes de receber endereos ( ortanto, valores do ti o int) ode-se somar e subtrair onteiros. No ca tulo 7, v eremos um exem lo onde isto ser til. 5.7 Recursividade Algumas funes matemticas odem ser estabelecidas de tal forma que as suas definies ut ilizem, de modo recorrente, a r ria funo que se est definindo. Um exem lo trivial ( no bom sentido) de um caso como este a funo fatorial. No ensino mdio a rendemos que o fatorial de um nmero natural n o roduto de todos os nmeros naturais de 1 at o r eferido n, ou seja, n! = 1 . 2 . 3 . ... . n. Como mostra o exem lo abaixo, muit o sim les se escrever uma funo (funo iterativa) que calcule o fatorial de n: basta s e inicializar um varivel com 1 e, numa estrutura de re etio, calcular os rodutos 1 x 2 = 2, 2 x 3 = 6; 6 x 4 = 24; 24 x 5 = 120; ...; etc., at multi licar todos os naturais at n. long int Fatorial(int n) { long int Fat; int i; Fat = 1; for (i = 2; i <= n; i = i + 1) Fat = Fat * i; return (Fat); } Embora o conceito anterior seja de sim les com reenso, matematicamente mais elegante definir o fatorial de um natural n or 1, se n = 0 ou n = 1 n!= n . (n 1)!, se n > 1

Desta forma, o fatorial de n definido a partir dos fatoriais dos naturais menore s que ele. Isto significa que para o clculo do fatorial de um determinado nmero na tural h necessidade de que se recorra aos fatoriais dos naturais anteriores. Por exemplo, 4! = 4 . 3! = 4 . (3 . 2!) = (4 . 3) . (2 . 1!) = 4 . 3 . 2 . 1 = 24. U ma definio com estas caractersticas dita uma definio por recorrncia ou uma defini siva. Um outro exemplo de uma definio recursiva foi dada no exerccio 12 da seo 4.5: a sequncia de Fibbonaci a sequncia (an) definida por

1, se n = 1 ou n = 2 Fibb(n) = Fibb(n 1) + Fibb(n 2), se n > 2 Observe que o termo de ordem n definido a partir de termos anteriores. Isto sign ifica que para o clculo de um determinado termo h necessidade de que se recorra a valores de todos os termos anteriores. Por exemplo, para a determinao de a5 necess itamos conhecer a4 e a3; para a determinao destes dois, necessitamos conhecer a2 e a1. Naturalmente, uma definio recursiva deve conter uma condio que interrompa a rec orrncia. Esta condio chamada condio de escape. No caso do fatorial a condio de esc = 0 ou n = 1; na sequncia de Fibbonaci, a condio de escape n = 1 ou n = 2. A expre sso que realiza propriamente a recorrncia pode ser chamada expresso de recorrncia

O surpreendente que os ambientes para desenvolvimento de programas, de um modo g eral, oferecem recursos para implementao de funes recursivas da mesma maneira que el as so escritas em matemtica. Por exemplo, a implementao recursiva do fatorial em C p ode ser feita simplesmente da seguinte forma: long int FatRec(int n) { if ((n == 0) (n == 1)) return (1); else return (n * FatRec(n - 1)); } interessante ter uma ideia do que acontece na recursividade. Q uando se ativa uma funo recursiva, cada nova chamada da mesma em ilhada na chamada ilha de memria, at que a condio de esca e atingida. A artir da, cada ativao en desem ilhada (evidentemente, na ordem inversa do em ilhamento) e as o eraes vo sen do realizadas.

Se ativarmos a funo acima com n = 5 (com um comando rintf("%d"%, FatRec(5)), or exem lo) teramos a seguinte sequncia de o eraes: 1 - A s a ativao de Fat(5) Fat(5) n 5*Fat(4) 5 2 - A s a ativao de Fat(4) Fat(5) n 5* at(4) 5 Fat(4) 4*Fat(3) n 3 3 - A s a ativao de Fat(3) Fat(5) n 5*Fat(4) 5 Fat(4) 4*Fat(3) n 3 Fat(3) 3*Fat(2) n 2 4 - A s a ativao de Fat(2) Fat(5) 5*Fat(4) n 5 Fat(4) 4*Fat(3) n 3 Fat(3) 3*Fat(2) n 2 Fat(2) 2*Fat(1) n 1

5 - A s a ativao de Fat(1) Fat(5) 5*Fat(4) Fat(5) 5*Fat(4) Fat(5) 5*Fat(4) n 5 n 5 n 5 n 5 Fat(4) 4*Fat(3) Fat(4) 4*Fat(3) Fat(4) 4*6 = 24 n 3 n 3 n 3 Fat(3) 3*Fat (2) Fat(3) 3*2 = 6 n 2 n 2 Fat(2) 2*1 = 2 n 1 Fat(5) 5*24 = 120

Embora a utilizao da recursividade a resente a vantagem de rogramas mais sim les, ela tem o inconveniente de sacrificar a eficincia do rograma. Isto ocorre devid o necessidade de chamadas sucessivas da funo e das o eraes de em ilhamento e desem i lhamento, o que demanda um tem o maior de com utao e uma maior necessidade de uso de memria. Esta observao faz com que a soluo no recursiva (chamada, como j dissemos, no iterativa) seja refervel. No ca tulo 7 a resentaremos um exem lo de uma funo recu siva que to eficiente quanto a funo iterativa. Mesmo funes que no ossuam intrinsec nte um definio recursiva ode ser im lementada recursivamente, muitas das vezes co m uma lgica mais fcil de com reender do que a da soluo iterativa. Por exem lo, a funo que determina o mximo divisor comum de dois inteiros dados a resentada na seo 5.1 ode ser escrita recursivamente da seguinte forma: /*Funo recursiva que retorna o mx imo divisor comum de dois inteiros ositivos dados*/ int MaxDivCom(int x, int y) { int Resto; Resto = x % y; if (Resto == 0) return y; else return MaxDivCom(y, Resto); } Um outro exem lo interessante de recursividade a im lementao do jogo con hecido como Torre de Hani, jogo que consiste em trs torres chamadas origem, destin o e auxiliar e um conjunto de n discos de dimetros diferentes, colocados na torre origem, na ordem decrescente dos seus dimetros. O objetivo do jogo , movendo um ni co disco de cada vez e no odendo colocar um disco sobre outro de dimetro menor, t rans ortar todos os discos ara ilha destino, odendo usar a torre auxiliar com o assagem intermediria dos discos. Indicando torre 1 torre 2 o movimento do disco que no momento est arte su erior da torre 1 ara a torre 2, teramos a seguinte soluo ara o caso n = 2: 1. origem auxiliar 2. origem destino 3. auxiliar destino Para n = 3, a soluo seria : 1. origem destino 2. origem auxiliar 3. destino auxiliar 4. origem destino 5. auxiliar origem 6. auxiliar destino

7. origem destino Observe que os trs movimentos iniciais transferem dois discos d a torre origem ara a torre auxiliar, utilizando a torre destino como auxiliar; o quarto movimento transfere o maior dos discos da origem ara destino e os ltimo s movimentos transferem os dois discos que esto na auxiliar ara destino utilizan do origem como torre auxiliar. Assim, a o erao Move(3, origem, auxiliar, destino) - move trs discos da origem ara destino usando auxiliar como torre auxiliar - o de ser decom osta em trs eta as: 1) Move(2, origem, destino, auxiliar) - move doi s discos de origem ara auxiliar usando destino como auxiliar; 2) Move um disco de origem ara destino 3) Move(2, auxiliar, origem, destino) - move dois discos de auxiliar ara destino usando origem como auxiliar. O interessante que fcil mos trar que este raciocnio se generaliza ara n discos, de modo que a o erao Move(n, a , b, c) ode ser obtida com as seguintes o eraes: 1) Move(n-1, a, c, b) 2) Move um disco de a ara c 3) Move(n-1, b, a, c) O mais interessante ainda que isto ode ser im lementado em C, atravs do seguinte rograma: /* Programa que im lementa o jogo Torre de Hanoi*/ #include <stdio.h> void MoveDisco(char t1[10], char t2[10 ]) { rintf("%s --> %s \n", t1, t2); } void Hanoi(int x, char o[10], char a[10], char d[10]) { if (x > 0) { Hanoi(x - 1, o, d, a); MoveDisco(o, d); Hanoi(x - 1, a, o, d); } } main() { int n; rintf("Digite o numero de discos \n"); scanf("%d ", &n); Hanoi(n, "origem", "auxiliar", "destino"); } 5.8 Usando funes de outros arquivos Os com iladores C ermitem que um rograma utilize funes definidas em outros rogr amas. Basta que o referido rograma seja includo na instruo #include "NomeArquivo". Por exem lo, imagine que a declarao de variveis e a funo abaixo #include <stdio.h> i nt x, y; int MaxDivCom(int a, int b) { int Resto;

Resto = a % b; while (Resto != 0) { a = b; b = Resto; Resto = a % b; } return b; } estejam num arquivo mdc.c. Como a matemtica rova que o roduto de dois nmeros inteiros igual ao roduto do mximo divisor comum dos nmeros elo mnimo mlti lo comum , a funo MaxDivCom() oderia ser utilizada ara se escrever um rograma ara o clcu lo do mnimo mlti lo comum de dois nmeros dados. Este rograma oderia utilizar as v ariveis x, y e Mdc declaradas no arquivo mdc.c. Teramos ento o seguinte rograma: / *Programa que calcula o minimo multi lo comum de dois numeros utilizando uma funo definida em outro arquivo*/ #include <stdio.h> #include "mdc.c" main() { int m, Mmc; rintf("Digite os numeros "); scanf("%d %d", &x, &y); m = MaxDivCom(x, y); Mmc = (x * y)/m; rintf("Mmc(%d, %d) = %d \n", x, y, Mmc); } A referncia ao arqui vo que vai ser includo no rograma ode ser feita com o caminho do arquivo escrito entre as as ou com o nome do arquivo entre < >, se ele est gravado na asta adro dos arquivos de cabealho .h.

5.9 "Ti os" de variveis Variveis locais Como foi dito na seo 5.1, as variveis declaradas no interior de uma funo (variveis lo ais, ara lembrar) s so acessveis or instrues desta funo. Na realidade, elas s exi durante a execuo da funo: so "criadas" quando a funo ativada e so "destrudas" qu ina a execuo da funo. Por esta ltima razo, variveis locais tambm so chamadas vari mticas e variveis dinmicas. Tambm so variveis locais os armetros da funo. Isto ex necessidade de declar-los, definindo-se seus identificadores e seus ti os de dad os. Variveis globais e o modificador extern Se uma varivel deve ser acessada or mais de uma funo ela deve ser declarada fora d e qualquer funo, sendo chamada, neste caso, de varivel global. Uma varivel global o de ser referenciada em qualquer funo do rograma e, embora isto no seja aconselhvel, ode-se identificar uma varivel local com o mesmo identificador de uma varivel gl obal. Neste caso, referncias ao identificador comum dentro da funo na qual a varivel local foi definida refere-se a esta varivel local. Isto, naturalmente, im ede a funo de acessar a varivel global. O modificador de varivel extern ermite que um ro grama utilize variveis definidas e inicializadas em funes de um outro arquivo que t enha sido "includo" atravs da instruo #include "NomeArquivo", como visto na seo 5.8. o ca tulo seguinte a resentaremos um exem lo bastante esclarecedor do uso do

modificador extern.

Variveis estticas Como uma varivel local deixa de existir quando se encerra a execuo da funo, o ltimo v lor nela armazenado erdido. Pode ocorrer que o ltimo valor armazenado numa varive l local seja necessrio ara uma chamada subsequente da funo. A s a execuo de uma fun ltimo valor armazenado numa varivel local ode ser reservado ara ser utilizado numa chamada osterior da funo atravs do modificador de varivel static. No Turbo C 2 .01 e no Turbo C++ 3.0, uma varivel local static deve ser inicializada or um val or constante ou o endereo de uma varivel global, quando da sua declarao. Neste caso, considerando que receber endereos, uma varivel static deve ser definida como um o nteiro. Por exem lo, o rograma abaixo utiliza uma varivel esttica ara guardar o valor de Termo em cada ativao da funo GeraPA() ara, com este valor, obter o valor d o termo seguinte. #include <stdio.h> #include <conio.h> int a1; int GeraPA(int r ) { static int *Termo = &a1; *Termo = *Termo + r; return (*Termo); } main() { in t i, Razao; clrscr(); rintf("Digite o rimeiro termo e a razo: "); scanf("%d %d" , &a1, &Razao); rintf("Progressao Aritmetica de rimeiro termo %d e razao %d: \ n%d ", a1, Razao, a1); for (i = 1; i <= 9; i = i + 1) rintf("%d ", GeraPA(Razao )); } Naturalmente, concordo com o leitor que est ensando que existem rogramas ara gerao de rogresses aritmticas bem mais sim les. Uma outra a licao de variveis icas ode ser obtida numa funo que determine a decom osio em fatores rimos de um in teiro dado, exerccio ro osto no ca tulo anterior. Um algoritmo ara determinar a decom osio em fatores rimos de um inteiro efetuar divises sucessivas elos rimos divisores, sendo o nmero de divises elo rimo realizadas a sua multi licidade. Po r exem lo, ara se obter a decom osio de 1.400 teramos 1400 700 350 175 35 7 1 2 2 2 5 5 7 1400 = 23x52x7 As funes abaixo, a rimeira iterativa e a segunda recursiva, retornam a decom osio d e um inteiro assado ara o armetro n. void Decom Fatores(int n) { int d, m; d = 2;

while (n > 1) { m = 0; while (n % d == 0) { m++; n = n / d; } if (m > 0) rintf( "\t%d\t%d\n", d, m); d++; } } void Decom FatoresRec(int n) { static int d = 2; i nt m = 0; if (n > 1) { while (n % d == 0) { m++; n = n / d; } if (m > 0) rintf( "\t%d\t%d\n", d, m); d++; Decom FatoresRec(n); } } Observe que como d foi defini da como esttica, o seu valor da ultima execuo da funo, obtido atravs do comando d++, reservado ermitindo que um novo divisor rimo seja rocurado.

O valor de uma varivel esttica reservado ara uma rxima execuo da funo elo fato ue, na verdade, ela no destruda quando se encerra a execuo da funo, como se ela fos uma varivel global. A diferena entre varivel local esttica e varivel global que a r meira continua s odendo ser acessada ela funo onde ela foi definida. 5.10 Uma a licao Histria da Matemtica Em 1817, Christian Goldbach, um rofessor de Matemtica e de Histria nascido na Ale manha, numa carta que escreveu ao matemtico Leonard Euler fez a seguinte afirmao: t odo nmero ar maior quer dois a soma de dois nmeros rimos. Embora a veracidade de sta afirmao, conhecida hoje como Conjectura de Goldbach, j tenha sido verificada a ra todos os nmeros ares menores do que 12x10 17 (htt ://www.ieeta. t/~tos/goldba ch.html, acessada em 14/12/2008), ainda no se conseguiu rov-la integralmente, a e sar dos esforos j des endidos or muitos matemticos. O rograma abaixo, ermite a v erificao da Conjectura de GoldBach ara qualquer nmero ar menor que 32.767. #inclu de <math.h> #include <stdio.h> int Primo(int n) { int d = 2; float r = sqrt(n);

while (n%d != 0 && d <= r) d++; if (d <= r) return 0; else return 1; } void Gold bach(int n, int &a, int &b) { int i = 2; while (!Primo(i) !Primo(n - i)) i++; a = i; b = n - i; } main() { int x, y, z; rintf("Digite um inteiro ar "); sca nf("%d", &x); Goldbach(x, y, z); rintf("Primos cuja soma igual a %d: %d e %d \n ", x, y, z); } 5.11 Exerccios ro ostos 1. Escreva uma funo que retorne o k-simo dgito (da direita ara esquerda) de um inte iro n, k e n dados. Por exem lo, K_esimoDigito(2845, 3) = 8. 2. O fatorial m ar d e um nmero n m ar ositivo o roduto de todos os nmeros m ares ositivos menores do que ou iguais a n. Indicando o fatorial m ar de n or n temos, n = 1 . 3. 5 . . .. . n. Por exem lo, 7 = 1 . 3 . 5 . 7 = 105. Escreva funes iterativas e recursiv as ara a determinao do fatorial m ar de um inteiro m ar dado. 3. Como na questo ante rior, o fatorial rimo (ou rimorial) de um nmero rimo ositivo o roduto de tod os os rimos ositivos menores do que ou iguais a ele: # = 2 . 3 . 5 . 7 . ... . (sendo 2# = 2). Por exem lo, 7# = 2 . 3 . 5 . 7 = 210. Escreva um rograma qu e determine o fatorial rimo de um rimo dado. 4. Escreva funes, iterativa e recur siva, que retornem a soma dos algarismos de um inteiro ositivo dado. 5. Escreva uma funo recursiva que retorne o n-simo termo da sequncia de Fibbonaci, n dado. 6. Escreva uma funo recursiva que gere uma tabuada de multi licao, exibindo-a no format o ( ara osicionar a sada ode-se utilizar a funo gotoxy()). 1x2 = 2 1x3 = 3 1x4 = 4 ... 2x2 = 4 2x3 = 6 2x4 = 8 ... 3x2 = 6 3x3 = 9 3x4 = 12 ... ... ... ... ... 9 x2 = 18 9x3 = 27 9x4 = 36 ... 7. Escreva uma funo recursiva que determine o mnimo ml ti lo comum de dois inteiros dados. 8. Escreva funes, recursiva e iterativa, que i m lementem a funo ow(). Observao Pro ostas de solues dos exerccios ro ostos odem solicitadas atravs de mensagem eletrnica ara jaime@ccen.ufal.br com assunto RESP OSTAS LIVRO C, anexando o formulrio abaixo devidamente reenchido.

Nome 1 2 Categoria1 Instituio2 Curso2 Cidade/Estado Categoria: docente, estudante, autodidata Se docente ou estudante

6 Vetores 6.1 O que so vetores No exem lo 6 da seo 4.6 discutimos uma funo ara a determinao da mdia de uma relao os dados. Para tal, utilizamos uma varivel sim les ara receber os nmeros, sendo q ue cada vez que um nmero, a artir do segundo, era recebido o anterior era " erdi do". Ou seja, a relao de nmeros no era armazenada. Imagine que a relao fosse uma rela e notas escolares e alm da mdia se quisesse tambm saber a quantidade de alunos que obtiveram nota acima da mdia ou uma outra medida estatstica (desvio mdio, or exem lo) que de endesse da mdia. Neste caso, haveria a necessidade de que a relao fosse redigitada o que, alm da du licidade do trabalho, facilitaria os erros de digitao. im ortante ento que exista uma "varivel" ca az de armazenar vrios valores simultane amente de tal forma que se ossa acessar cada um deles inde endentemente de se a cessar os demais. Um outro exem lo o caso do exem lo 2 da seo 4.6. L queramos a rela dos divisores de um inteiro dado e estes divisores eram a enas exibidos, no sendo armazenados, como recomendado na seo 2.9. At aquele momento, a dificuldade de se a rmazenar os divisores residia no fato de que no se sabe a riori o nmero de diviso res de um inteiro dado e, ortanto, no saberamos quantas variveis deveramos declarar . Um vetor um conjunto de variveis de um mesmo ti o de dado as quais so acessadas e referenciadas atravs da a osio de ndices ao identificador do vetor. 6.2 Declarao de um vetor unidimensional Um vetor unidimensional (ou sim lesmente vetor) declarado atravs da seguinte sint axe: Ti o de dado Identificador[n]; onde Ti o de dado fixar o ti o de dado das va riveis com onentes do vetor e n indicar o nmero das tais com onentes. Por exem lo, a declarao int Vetor[10] definir um conjunto de dez variveis do ti o int, enquanto q ue a declarao char Cadeia[100] definir um conjunto de cem variveis do ti o char. Com o cada varivel do ti o int utiliza dois bytes de memria e cada varivel do ti o char utiliza a enas um byte, a varivel Vetor ocu ar vinte bytes de memria enquanto que a varivel Cadeia ocu ar cem bytes. Os com iladores C ossuem uma funo de biblioteca, sizeof(), que retorna o nmero de bytes ocu ado or uma varivel ou or um vetor. P or exem lo, o rograma #include <stdio.h> main() { float x; int v[30]; rintf("N umero de bytes de x = %d \nNumero de bytes de v = %d \n", sizeof(x), sizeof(v)); } exibir na tela a seguinte sada: Numero de bytes de x = 4 Numero de bytes de v = 60 Cada com onente de um vetor ode ser acessada e referenciada atravs de ndices associados ao identificador do vetor, sendo o ndice da rimeira com onente igual a zero. Assim, as com onentes do vetor Cadeia do exem lo acima sero identificadas or Cadeia[0], Cadeia[1], ..., Cadeia[99]. O ndice de uma com onente ode ser re ferido atravs de uma ex resso que resulte num valor

inteiro. Por exem lo, a sequncia de comandos int i, Quadrados[100]; for (i = 1; i <= 100; i = i + 1) Quadrados[i - 1] = i * i; armazena no vetor Quadrados os qua drados dos cem rimeiros inteiros ositivos. Uma coisa em que o rogramador em C deve se reocu ar o fato de que os com iladores C no verificam se os valores atr ibudos a um ndice esto dentro dos limites definidos na declarao do vetor. Se os limit es no forem obedecidos, odem ocorrer erros de lgica na execuo rograma ou conflitos com o sistema o eracional ( rovocando, at mesmo, travamento no sistema). 6.3 Vetores e onteiros muito im ortante observar que o identificador de um vetor em C , na verdade, um onteiro que a onta ara o rimeiro elemento do vetor. Quando se declara int v[10 ]; est se reservando um conjunto de dez osies de memria contguas, cada uma delas com dois bytes, como mostra a figura abaixo: v v[0] v[1] v[9] A artir da, qualquer referncia ao identificador v uma referncia ao endereo da com onente v[0], de tal fo rma que, se tivermos a declarao int * ; os comandos = &v[0]; = v; executam a m esma ao: armazenam no onteiro o endereo de v[0]. Sendo um onteiro que a onta a ra sua rimeira com onente, um vetor ode ser um armetro de uma funo, odendo rece ber endereos. Dessa forma, qualquer ao realizada no vetor afetar o contedo do vetor assado como argumento; ou seja, a assagem de armetros do ti o vetor sem re feit a or referncia. Esta observao tambm justifica a ossibilidade de que armetros do ti o vetor sejam declarados como um onteiro: void funcao(int *v).

6.4 Lendo e escrevendo um vetor Como foi dito na seo 6.1, vetores servem ara armazenar uma relao de dados do mesmo ti o. Uma funo ara fazer este armazenamento de ende do conhecimento ou no da quant idade de elementos da relao. Na hi tese do nmero de elementos da relao ser conhecido, basta usar uma funo, do ti o void, com dois armetros: um ara receber o vetor que vai armazenar a relao e outro ara receber a quantidade de elementos da relao. Dentr o da funo, ode-se utilizar um comando for. #include <stdio.h> void ArmazenaRelaca oN(int *v, int t) { int i; rintf("Digite os elementos da relacao \n"); for (i = 0; i < t; i++) scanf("%d", &v[i]); } Se o nmero de elementos da relao no conhecido a riori, deve-se utilizar um flag ara encerrar a entrada dos dados, de acordo com o que foi comentado na seo 4.6. im ortante que a funo, ara utilizaes osterior determine o nmero de elementos da relao. Este valor ode ser retornado atravs

do comando return(). Dentro da funo ode-se utilizar um comando while que dever ser executado enquanto o dado de entrada for diferente do flag escolhido. int Armaz enaRelacao(int *v) { int i; i = 0; rintf("Digite os elementos da relacao (-1 a ra encerrar)"); scanf("%d", &v[i]); while (v[i] != -1) { i = i + 1; scanf("%d", &v[i]); } return (i); } Observe a du la finalidade da varivel i: ela serve ara i ndexar as com onentes e ara determinar a quantidade de elementos da relao. Para s e exibir uma relao de dados armazenados num vetor, basta uma funo com dois armetros: um ara receber o vetor onde a relao est armazenada e o outro ara receber a quant idade de elementos da relao. Esta quantidade est armazenada em alguma varivel: ela f oi um dado de entrada ou foi determinada na ocasio do armazenamento da relao. void ExibeRelacao(int *v, int t) { int i; for (i = 0; i < t; i++) rintf("%d ", v[i]) ; rintf("\n"); }

6.5 Exem los Parte IV Os exem los a seguir, alm de reforar vrios as ectos da utilizao de vetores, so muito is no desenvolvimento da lgica de rogramao. 1. Para introduzir o estudo dos vetore s nos referimos, na seo 6.1, ao roblema de se determinar o nmero de alunos de uma turma que obtiveram notas maiores que a mdia. Com a utilizao de vetores, odemos ca lcular a tal mdia e de ois " ercorrer" novamente o vetor, com arando cada nota co m a referida mdia. Teramos ento o seguinte rograma: #include <stdio.h> int Armazen aNotas(float *v) { int i; i = 0; rintf("Digite as notas (-1 ara encerrar)"); s canf("%f", &v[i]); while (v[i] != -1) { i = i + 1; scanf("%f", &v[i]); } return (i); } /*Funo ara determinar a mdia de uma relao de nmeros*/ float Media(float *v, i t t) {

int i; float Soma; Soma = 0; for (i = 0; i < t; i++) Soma = Soma + v[i]; return (Soma/t); } main() { int i, Quant, NotasBoas; float * , Med; Quant = ArmazenaNot as( ); Med = Media( , Quant); NotasBoas = 0; for (i = 0; i < Quant; i = i + 1) i f ( [i] > Med) NotasBoas = NotasBoas + 1; rintf("Media das notas: %f \n", Med); rintf("Notas maiores que a media: %d", NotasBoas); } 2. Imagine que quisssemos o desvio mdio das notas do exem lo anterior. Esta medida estatstica assim definida : o desvio de um elemento em relao mdia aritmtica a diferena entre o elemento e a aritmtica da relao; o desvio mdio a mdia aritmtica dos valores absolutos dos desvi Podemos ento, como fizemos acima, escrever uma funo ara calcular a mdia da relao de notas, armazenar os valores absolutos dos desvios em um vetor e utilizar a funo qu e calcula a mdia ara calcular a mdia destes valores absolutos. float DesvioMedio( float *v, int t) { int i; float *d; float Med; Med = Media(v, t); for (i = 0; i < t; i++) d[i] = abs(v[i] - Med); return(Media(d, t)); } Observe que este exem l o ilustra outra vantagem do uso de funes: a mesma funo Media foi utilizada ara dete rminao de mdias de relaes diferentes. 3. Imaginemos agora que queiramos uma funo que torne o maior valor de uma relao armazenada em um vetor. Uma ossvel soluo su or que o maior valor rocurado o rimeiro elemento do vetor e, em seguida, ercorrer o vetor com arando cada com onente com o valor que, at o momento, o maior, substitu indo o valor deste maior elemento quando se encontra uma com onente maior que el e. float MaiorElemento(float *v, int t) { int i; float Maior; Maior = v[0]; for (i = 1; i < t; i = i + 1) if (v[i] > Maior) Maior = v[i]; return(Maior); } Obser ve que a funo acima retorna o maior elemento armazenado no vetor, mas no retorna a osio deste maior elemento, o que em muitas situaes indis ensvel. Para isto necess um armetro com assagem or referncia, como visto no ca tulo anterior. Este armetr o recebe o valor zero e em seguida o

valor da osio onde foi encontrada uma com onente maior do que Maior. float MaiorE lemento(float *v, int t, int * ) { int i; float Maior; Maior = v[0]; * = 0; for (i = 1; i < t; i = i + 1) if (v[i] > Maior) { Maior = v[i]; * = i; } return(Ma ior); } Uma chamada desta funo vai requerer, alm do vetor onde est armazenada a re lao, duas variveis, digamos Maior e Pos; nestas condies a ativao da funo ser feit o comando Maior = MaiorElemento( , Quant, &Pos); onde o vetor onde est armazena da a relao, Quant a quantidade de elementos da relao e &Pos o endereo da varivel r armazenar a osio da ocorrncia do maior elemento rocurado. Vale ressaltar que, na funo acima, adotamos a assagem or referncia "formato Turbo C 2.01" que tambm func iona no Turbo C++ 3.0. 4. O exem lo a seguir tem o objetivo de mostrar que o ndic e de acesso s com onentes de um vetor ode ser dado atravs de ex resses, como j foi dito anteriormente. O exem lo mostra uma funo que, recebendo dois vetores com a me sma quantidade de elementos, gera um vetor intercalando as com onentes dos vetor es dados. Assim se v1 = {4, 8, 1, 9} e v2 = {2, 5, 7, 3} a funo deve gerar o vetor v = {4, 2, 8, 5, 1, 7, 9, 3}. Observe que as com onentes m ares de v so os elemen tos de v1 e as com onentes ares so os elementos de v2. void IntercalaVetor(float *v1, float *v2, float *v, int t) { int i; for (i = 0; i < 2 * t; i = i + 1) if (i % 2 == 1) v[i] = v2[(i - 1)/2]; else v[i] = v1[i/2]; } 5. Agora a resentaremo s um exem lo que mostra um vetor cujas com onentes so cadeias de caracteres, alm d e mostrar como um vetor de caracteres ode ser inicializado. Trata-se de uma funo que retorna o nome do ms corres ondente a um nmero dado, que oderia ser usada num rograma que escrevesse or extenso uma data da no formato dd/mm/aaaa. char *No meMes(int n) { char *Nome[13] = {"Mes ilegal", "Janeiro", "Fevereiro", "Marco", "Abril", "Maio", "Junho", "Julho", "Agosto", "Setembro", "Outubro", "Novembro", "Dezembro"}; if ((n > 0) && (n < 13)) return(Nome[n]); else return(Nome[0]); } O bserve que a inicializao do vetor se faz quando da sua declarao, com a enumerao dos v lores das com onentes entre chaves, como a matemtica faz com conjuntos. Observe t ambm que a funo NomeMes() retorna um onteiro ara uma varivel do ti o char, o que s ignifica que retornar uma cadeia de caracteres (uma string), ois, como veremos n o rximo ca tulo, uma string um vetor de caracteres. Este

fato tambm indicado no vetor Nome que um vetor de onteiros ara variveis do ti o char. 6. Este exem lo mostra uma situao em que h a necessidade de vrios vetores. Tra ta-se de um rograma ara administrar os edidos de uma lanchonete, cujo card io o seguinte: Codigo 101 102 103 104 105 Produto Refrigerante Suco Sanduche Salgado Torta Preo 1.20 1.00 2.50 1.00 2.00 Uma ossvel soluo considerar trs vetores globais, inicializados como no exem lo ante rior, de tal forma que seja ossvel ara cada edido gerar vetores com os cdigos d os rodutos solicitados e, a artir da, se ossa armazenar as quantidades de cada item do edido. #include <stdio.h> #include <conio.h> int Cod[5] = {101, 102, 1 03, 104, 105}; char *Prod[5] = {"Refrigerante", "Suco", "Sanduiche", "Salgado", "Torta"}; float Precos[5] = {1.20, 1.00, 2.50, 1.00, 2.00}; int Pedido(int *c, i nt *q, float *v) { int i = 0; do { do { uts("Cdigo (100 ara encerrar o edido): "); scanf("%d", &c[i]); if (c[i] < 100 c[i] > 105) rintf("\a Codigo invalido "); } while (c[i] < 100 c[i] > 105); if (c[i] != 100) { uts("Quantidade"); s canf("%d", &q[i]); v[i] = q[i]*Precos[c[i] - 101]; i++; } } while (c[i] != 100); return i; } void ExibePedido(int *c, int *q, float *v, int t) { int i; float To tal = 0.0; clrscr(); uts("Cdigo Discriminao Quantidade Valor \n"); for (i = 0; i < t; i++) { rintf("%d %s %10.d %10.2f\n", Cod[c[i] - 101], Prod[c[i] - 101], q[i ], v[i]); Total = Total + v[i]; } rintf("\nValor total do edido: %.2f\n\n", To tal); } main() {

int NumItens, *Itens, *Quant; float *Valor; char S = 'n'; do { clrscr(); NumIten s = Pedido(Itens, Quant, Valor); if (NumItens != 0) ExibePedido(Itens, Quant, Va lor, NumItens); uts("Outro edido (S/N)?"); fflush(stdin); scanf("%c", &S); } w hile (tou er(S) != 'N'); } 7. Mostraremos agora um exem lo cujo objetivo desenv olver o raciocnio recursivo utilizando vetores. Trata-se de uma funo recursiva ara a determinao da soma das com onentes de um vetor, coisa j feita iterativamente no interior da funo Media() desenvolvida no exem lo 1. Ora, como uma funo que trata vet ores recebe sem re o vetor e o seu tamanho, odemos recursivamente diminuir o tama nho do vetor atravs do decremento do armetro res ectivo at que o vetor tenha a enas uma com onente, quando ento a soma das com onentes se reduzir a esta nica com onente /*Funo recursiva que retorna a soma das com onentes de um vetor*/ int SomaCom Rec (float *v, int t) { if (t == 1) return v[i 1]; else return v[t - 1] + SomaComRec (v, t 1); }

6.6 Vetores multidimensionais Na seo 6.1 foi dito que um vetor um conjunto de variveis de mesmo ti o, chamadas co m onentes do vetor. A linguagem C ermite que as com onentes de um vetor sejam t ambm vetores, admitindo que se armazene uma matriz da matemtica, uma tabela de du la entrada que, or exem lo, enumere as distncias entre as ca itais brasileiras o u um livro considerando a gina, a linha e a coluna em que cada caractere se loca liza. A declarao de um vetor multidimensional uma extenso natural da declarao de um etor unidimensional: Ti o de dado Identificador[n1][n2] ... [nk]; onde k indica a dimenso e n1, n2, ..., nk indicam o nmero de com onentes em cada dimenso. Por exe m lo, a declarao int Mat[10][8]; define um vetor de dez com onentes, cada uma dela s sendo um vetor de oito com onentes. Ou seja, Mat um conjunto de 10 x 8 = 80 va riveis do ti o int. Para um outro exem lo, a declarao char Livro[72][30][30]; defin e uma varivel ca az de armazenar os caracteres de um livro com at setenta duas gin as, cada gina ossuindo trinta linhas e cada linha ossuindo trinta colunas. A i nicializao de um vetor multidimensional tambm segue o adro da inicializao de um veto unidimensional, com a ressalva de que as com onentes, que agora so vetores, deve m estar entre chaves. Por exem lo, se quisssemos um vetor bidimensional ara arma zenar os nmeros de dias dos meses do ano, fazendo a distino entre anos bissextos e no bissextos oderamos declarar e inicializar um vetor

DiasMeses da seguinte forma: int DiasMeses = {{0, 31, 28, 31, 30, 31, 30, 31, 31 , 30, 31, 30, 31}, {0, 31, 29, 31, 30, 31, 30, 31, 31, 30, 31, 30, 31}}; onde a rimeira com onente refere-se aos dias dos meses de um ano no bissexto e a segund o, aos dias dos meses de um ano bissexto (este vetor ser utilizado num exem lo a seguir e, na ocasio, ser ex licada a razo da rimeira com onente de cada vetor com onente ser zero). Um vetor bidimensional usualmente chamado de matriz e os nmeros de com onentes so chamados, res ectivamente, nmero de linhas e nmero de colunas. E stes dois nmeros se arados or x (que lido or) a ordem da matriz. Assim, a varive l Mat do exem lo acima est a ta a armazenar at uma matriz de ordem 8 x 10. Estas d enominaes, em restadas da matemtica, so justificadas elo fato de que, embora as com onentes de um vetor bidimensional sejam armazenadas de forma consecutiva (a ri meira com onente do segundo vetor logo a s a ltima com onente do rimeiro vetor), uma matriz, ara facilitar sua com reenso, ode ser imaginada como constituda de l inhas e de colunas. Por exem lo, o vetor DiasMeses do exem lo acima ode ser ima ginado como sendo 0 0 31 31 28 29 31 31 30 30 31 31 30 30 31 31 31 31 30 30 31 3 1 30 30 31 31 facilitando a com reenso de referncias do ti o DiasMeses[1][2] que indica o elemen to da segunda linha (a rimeira de ndice zero) e da terceira coluna (a rimeira d e ndice zero). Se o nmero de linhas e o nmero de colunas de uma tabela so conhecidos , o seu armazenamento em uma matriz muito sim les. Basta utilizar dois comandos for aninhados, controlados elo nmero de linhas e elo nmero de colunas, res ectiv amente. void ArmazenaTabelaMN(float Mat[10][10], int m, int n) { int i, j; rint f("Digite, or linha, os elementos da matriz"); for (i = 0; i < m; i = i + 1) fo r (j = 0; j < n; j = j + 1) scanf("%f", &Mat[i][j]); } Se o nmero de linhas e o nm ero de colunas de uma tabela no so conhecidos, ode-se usar um du lo while aninhad o, definindo-se um flag ara encerramento da digitao dos elementos de cada linha e um outro flag ara encerramento da digitao da matriz. Naturalmente, a funo dever ret ornar o nmero de linhas e o nmero de colunas da tabela, o que justifica os onteir os m e n da ro osta abaixo. void ArmazenaTabela(float Mat[10][10], int &m, int &n) { int i, j; rintf("Digite, or linha, os elementos da matriz (-1 ara encer rar cada linha e -2 ara encerrar a matriz"); i = 0; j = 0; scanf("%f", &Mat[i][ j]); while (Mat[i][j] != -2) { while (Mat[i][j] != -1) { j = j + 1; scanf("%f", &Mat[i][j]); n = j; } i = i + 1; j = 0; scanf("%f", &Mat[i][j]); } m = i; }

Uma funo ara exibir uma tabela armazenada numa matriz tambm muito sim les. Basta, ara que a matriz seja exibida na forma de tabela, mudar a linha cada vez que a exibio de uma linha concluda. void ExibeTabela(float Mat[10][10], int m, int n) { i nt i, j; for (i = 0; i < m; i = i + 1) { for (j = 0; j < n; j = j + 1) rintf("% .1f ", Mat[i][j]); rintf("\n"); } }

6.7 Exem los Parte V 1. Um dos exem los do ca tulo 3 a resentava uma funo que recebia uma data e forneci a o dia da semana corres ondente. Neste rograma recisamos calcular o nmero de d ias do ano decorridos at aquela data. Com a utilizao da matriz DiasMeses comentada acima, odemos escrever facilmente uma funo com este objetivo. int DiaAno(int d, i nt m, int a) { int DiasMes[2][13] = {{0, 31, 28, 31, 30, 31, 30, 31, 31, 30, 31, 30, 31}, {0, 31, 29, 31, 30, 31, 30, 31, 31, 30, 31, 30, 31}}; int i; if (((a % 4 == 0) && (a % 100 != 0)) (a % 400 == 0)) for (i = 1; i < m; i = i + 1) d = d + DiasMes[1][i]; else for (i = 1; i < m; i = i + 1) d = d + DiasMes[0][i]; re turn(d); } Lembrando que o valor de uma ex resso lgica 1 (um) se ela for verdadeir a e 0 (zero) se ela for falsa, oderamos armazenar o valor da ex resso lgica que ga rante que um ano bissexto e utilizar o contedo desta varivel ara escolher a com o nente do vetor DiasMeses que ser utilizada: 1 (um) se for bissexto e (0) zero, ca so contrrio. int DiaAno(int d, int m, int a) { int i,Biss; Biss = ((a % 4 == 0) & & (a % 100 != 0)) (a % 400 == 0); for (i = 1; i < m; i = i + 1) d = d + DiasM es[Biss][i]; return(d); } A razo de termos considerado a rimeira com onente igua l a 0 (zero) foi ara com atibilizar o nmero corres ondente a cada ms com a com on ente do vetor, j que (re etindo ela ltima vez) a rimeira com onente de um vetor de ndice zero. 2. Como no exem lo em que o r rio sistema gerou os quadrados dos c em rimeiros nmeros inteiros, o sistema ode gerar uma matriz. Para exem lificar isto, a resentaremos uma funo que gera a matriz identidade de ordem n. Para um int eiro ositivo dado, a matriz identidade de ordem n a matriz In = (irs), de ordem nxn, dada or irs = 1, se r = s, e irs = 0, se r s. Esta matriz muito im ortant e no estudo das matrizes, sendo utilizada, or exem lo, ara a determinao da matri z inversa de uma matriz inversvel. Por exem lo, se n = 3, temos

1 0 0 I 3 = 0 1 0 0 0 1 void GeraMatrizUnidade(int Mat[10][10], int m) { int i, j; for (i = 0; i < m; i = i + 1) for (j = 0; j < m; j = j + 1) if (i == j) Mat[i][j] = 1; else Mat[i][j] = 0; } 3. Quando o nmero de linhas de uma matriz igual ao nmero de colunas a matr iz dita matriz quadrada. Neste caso, os elementos de ndices iguais constituem a d iagonal rinci al. A soma dos elementos da diagonal rinci al de uma matriz quad rada o trao da matriz. Como mais um exem lo de rogramas que mani ulam matrizes, a funo abaixo determina o trao de uma matriz quadrada dada. Observe que ara ercor rer a diagonal rinci al no h necessidade de um du lo for. float Traco(float Mat[1 0][10], int m, int n) { int i; float Tr; Tr = 0; if (m == n) { for (i = 0; i < m ; i = i + 1) Tr = Tr + Mat[i][i]; return(Tr); } else rintf("A matriz nao e quad rada"); } 4. Uma tabela que enumere as distncias entre vrias cidades uma matriz si mtrica: os termos simtricos em relao diagonal rinci al so iguais, ou seja Mat[i][j] = Mat[j][i]. Obviamente, a digitao de uma matriz com esta ro riedade ode ser sim lificada, devendo-se digitar a enas os termos que esto acima da diagonal rinci al. void ArmazenaMatrizSimetrica(float Mat[10][10], int m) { int i, j; rintf("D igite, or linha, os elementos da matriz, a artir da diagonal"); for (i = 0; i < m; i = i + 1) for (j = i; j < m; j = j + 1) { scanf("%f", &Mat[i][j]); Mat[j][ i] = Mat[i][j]; } } Observe que a inicializao de j no segundo comando for foi com o valor de cada i do rimeiro. A razo disto que s sero digitados os termos acima da diagonal rinci al, termos em que j i. 5. Nos exemplos anteriores, sempre "perc orremos a matriz pelos elementos de suas linhas". O prximo exemplo mostra um caso em que necessrio percorrer as colunas. Trata se de uma questo muito comum da tota lizao das colunas de uma tabela. void TotalizaColunas(float Mat[10][10], int m, in t n)

{ int i, j; for (j = 0; j < n; j = j + 1) { Mat[m][j] = 0; for (i = 0; i < m; i = i + 1) Mat[m][j] = Mat[m][j] + Mat[i][j]; } } 6.8 Uma aplicao esportiva Nesta seo, apresentaremos um programa para administrar o placar de um set de um jo go de vlei de praia. De acordo com as regras em vigoravam nas Olimpadas de Pequim (2008), para uma equipe vencer um set de uma partida ela deveria obter um mnimo d e 21 pontos para os sets normais ou de 15 pontos para um set de desempate, desde q ue a diferena entre sua pontuao e a do adversrio fosse superior ou igual a dois. #in clude <stdio.h> #include <conio.h> #include <math.h> void MostraPlacar(char *Tim e1, char *Time2, int Pontos1, int Pontos2) { printf("%20s %2d x %2d % 20s\n", Ti me1, Pontos1, Pontos2, Time2); } void VerificaMudanca(int Pontos1, int Pontos2, int mud) { if ( (Pontos1+Pontos2)%mud == 0) { puts("Atencao! mudanca de quadra! Digite uma tecla para continuar" ); getch(); } } void FimdeSet(char *Time1, char *Time2, int Pontos1, int Pontos2) { puts("FIM DE SET!"); if(Pontos1>Pontos2) pri ntf("%s",Time1); else printf("%s" ,Time2); puts(" ganhou o set!"); puts("Placar final: "); MostraPlacar(Time1,Time2,Pontos1,Pontos2); } void main() { char *Nome [2]; int Equipe1[200], Equipe2[200]; int Set, Mudanca, Saque, Ponto, Dif; clrscr (); puts("Digite os nomes dos paises:"); gets(Nome[0]); flushall(); gets(Nome[1] ); puts("Digite a quantidade de pontos do set (15/21):"); scanf("%d",&Set); Muda nca = Set/3;

Equipe1[0] = 0; Equipe2[0] = 0; Saque = 0; clrscr(); do { /* Exibe o placar atua l */ puts("Placar atual:"); MostraPlacar(Nome[0], Nome[1], Equipe1[Saque], Equip e2[Saque]); if (Saque != 0) VerificaMudanca(Equipe1[Saque], Equipe2[Saque], Muda nca); Saque++; puts("Digite a equipe que marcou ponto (1/2):" ); scanf("%d",&Pon to); if (Ponto==1) { Equipe1[Saque] = Equipe1[Saque 1]+1; Equipe2[Saque] = Equip e2[Saque 1]; } else { Equipe1[Saque] = Equipe1[Saque 1]; Equipe2[Saque] = Equipe 2[Saque 1]+1; } Dif = abs(Equipe1[Saque] Equipe2[Saque]); clrscr(); } while((( Equipe1[Saque]<Set) && (Equipe2[Saque] < Set)) (Dif < 2) ); FimdeSet(Nome[0], Nome[1],Equi e1[Saque],Equi e2[Saque]); getch(); }

6.9 Exerccios ro ostos 0. Escreva uma funo recursiva que retorne o maior elemento de um vetor. 1. Escreva uma funo que exiba as com onentes de um vetor na ordem inversa daquela em que for am armazenadas. 2. Um vetor alndromo se ele no se altera quando as osies das com o nentes so invertidas. Por exem lo, o vetor v = {1, 3, 5, 2, 2, 5, 3, 1} alndromo. Escreva uma funo que verifique se um vetor alndromo. 3. Escreva uma funo que receb um vetor e o decom onha em dois outros vetores, um contendo as com onentes de o rdem m ar e o outro contendo as com onentes de ordem ar. Por exem lo, se o vetor dado for v = {3, 5, 6, 8, 1, 4, 2, 3, 7}, o vetor deve gerar os vetores u = {3, 6, 1, 2, 7} e w = {5, 8, 4, 3}. 4. Escreva uma funo que decom onha um vetor de in teiros em dois outros vetores, um contendo as com onentes de valor m ar e o outro contendo as com onentes de valor ar. Por exem lo, se o vetor dado for v = {3, 5, 6, 8, 1, 4, 2, 3, 7} a funo deve gerar os vetores u = {3, 5, 1, 3, 7} e w = {6, 8, 4, 2}. 5. Um vetor do Rn uma n-u la de nmeros reais v = {x1, x2, ..., xn}, se ndo cada xi chamado de com onente. A norma de um vetor v = {x1, x2, ..., xn} def inida or 2 2 x12 + x2 + ... + xn . Escreva uma

funo que receba um vetor do Rn, n dado, e fornea sua norma. 6. O roduto escalar de dois vetores do Rn a soma dos rodutos das com onentes corres ondentes. Isto e, se u = {x1, x2, ..., xn} e v = {y1, y2, ..., yn}, o roduto escalar x1.y1 + x2. y2 ... + xn.yn. Escreva uma funo que receba dois vetores do Rn, n dado, e fornea o roduto escalar deles. 7. A am litude de uma relao de nmeros reais a diferena entre o maior e o menor valores da relao. Por exem lo, a am litude da relao 5, 7, 15, 2, 2 3 21, 3, 6 23 - 2 = 21. Escreva uma funo que receba uma relao de nmeros e fornea su m litude. 8. O desvio adro de uma relao de nmeros reais a raiz quadrada da mdia ari mtica dos quadrados dos desvios (ver exem lo 2, seo 6.4). Escreva uma funo que receba uma relao de nmeros

reais e fornea o seu desvio adro. 9. Escreva uma funo que fornea as com onentes dist intas de um vetor dado. Por exem lo, se o vetor dado for v = {3, 2, 1, 3, 4, 1, 5, 5, 2} a funo deve fornecer v = {3, 2, 1, 4, 5}. 10. No ca tulo 2 foi edida uma funo ara extrair o algarismo da casa das unidades de um inteiro dado. A arentemen te esta questo no tem interesse rtico. Vejamos um roblema cuja soluo de ende deste roblema. Algumas em resas que realizam sorteios de rmios entre seus clientes o fazem atravs dos sorteios da loteria federal, sendo ganhador o nmero formado elos algarismos das casas das unidades dos nmeros sorteados no cinco rmios da referid a loteria. Por exem lo, se o sorteio da loteria federal deu como resultado os nme ros 23451, 00234, 11236, 01235 e 23452, o rmio da tal em resa seria dado ao clie nte que ossusse o bilhete de nmero 14652. Escreva uma funo que receba os nmeros sort eados ela loteria federal e fornea o nmero que ganhar o rmio de acordo com as regr as acima. 11. Escreva uma funo que insira um valor dado num vetor numa osio dada. P or exem lo, se o vetor for v = {3, 8, 5, 9, 12, 3}, o valor dado for 10 e a osio dada for 4, a funo deve fornecer v = {3, 8, 5, 10, 9, 12, 3}. 12. Escreva uma funo q ue insira um valor dado num vetor ordenado de modo que o vetor continue ordenado . Por exem lo, se o vetor dado for v = {2, 5, 7, 10, 12, 13} e o valor dado for 6, a funo deve fornecer o vetor v = {2, 5, 6, 7, 10, 12, 13}. 13. Escreva uma funo q ue delete uma com onente de ordem dada de um vetor dado. Por exem lo, se o vetor dado for v = {2, 5, 7, 10, 12, 13} e a com onente a ser deletada for a de ordem 4, rograma deve fornecer o vetor v = {2, 5, 7, 12, 13}. 14. Escreva uma funo que , dadas duas relaes de nmeros, cada uma delas com nmeros distintos, fornea os nmeros ue a arecem nas duas listas. Por exem lo, se as relaes forem u = {9, 32, 45, 21, 5 6, 67, 42, 55} e w = {24, 42, 32, 12, 45, 11, 67, 66, 78}, a funo deve fornecer o vetor v = {32, 45, 67, 42}. 15. Escreva uma funo que, dado um vetor ordenado, forn ea a maior diferena entre duas com onentes consecutivas, fornecendo tambm as ordens das com onentes que geraram esta maior diferena. Por exem lo, se o vetor dado fo r v = {3, 5, 9, 16, 17, 20, 26, 31}, a funo deve fornecer como maior diferena o val or 7 (16 - 9) e as ordens 4 e 3. 15'. Imagine que as inflaes mensais ocorridas num certo as no erodo de 01/2000 a 12/2008 estejam armazenadas num vetor. Escreva u ma funo que determine os meses e os res ectivos anos em que ocorreram a maior infl ao do erodo. 16. Uma avaliao escolar consiste de 50 questes objetivas, cada uma dela com 5 o es, v = {1, 2, 3, 4 e 5}, sendo a enas uma delas verdadeira. Escreva uma funo que receba a sequncia de res ostas corretas, o gabarito, e corrija um carto-res osta dado. 17. Escreva uma funo que fornea o valor numrico de um olinmio P(x) dado, ara um valor de x dado. Por exem lo, se o olinmio dado for P(x) = x3 + 2x - 1 e o valor de x dado for 2, a funo deve fornecer P(2) = 23 + 2x2 - 1 = 11. 18. O(s) valor(es) de maior frequncia de uma relao de valores numricos (so) chamado(s) moda d relao. Escreva uma funo que receba uma relao de notas escolares maiores do que zero menores do que ou iguais a 10, com uma casa decimal, e fornea a(s) moda(s) desta relao. Por exem lo, se a relao de notas for v = {8,0; 3,5, 4,5; 8,0; 6,0; 4,5; 6,0; 3,5; 2,5; 6,0; 9,0} a funo deve fornecer o valor 6,0 (frequncia 3). 19. Escreva um a funo que receba um nmero inteiro n e fornea o nmero formado elos algarismos de n e scritos na ordem inversa. Por exem lo, se o nmero dado for 3876, a funo deve fornec er 6783. 20. A matemtica rova que a converso de um nmero do sistema decimal ara o sistema binrio ode ser feita atravs de divises sucessivas do nmero e dos quociente s sucessivamente obtidos or 2, sendo ento o nmero binrio dado ela sequncia iniciad a or 1 e seguida elos restos obtidos nas divises sucessivas, na ordem inversa e m que so obtidos. Por exem lo, ara se converter 22 do sistema decimal ara o sis tema binrio temos: 22 % 2 = 0; 11 % 2 = 1; 5 % 2 = 1; 2 % 2 = 0 e, ortanto, 22 = (10110) 2. Escreva uma funo que converta um nmero ositivo dado no sistema decimal de numerao ara o sistema binrio, usando o algoritmo acima. 21. O exerccio 10 da seo 4.5 solicitava uma funo que determinasse a decom osio em fatores rimos, fornecendo os fatores rimitivos e suas res ectivas multi licidades. Na ocasio os fatores r imos e suas multi licidades eram a enas exibidos no sendo armazenados. Modifique a funo referida ara que os fatores rimos e as suas multi licidades sejam armazen ados, antes de serem exibidos. 22. A Universidade Federal de Alagoas adota o sis tema de verificao de a rendizagem listado no exem lo 5 da seo 3.4, com o adendo de q ue ter direito a uma reavaliao um aluno que obtiver uma nota inferior a 7,0 em algu m bimestre. Neste caso, a nota obtida na reavaliao substitui a menor das notas bim

estrais obtidas. Escreva uma funo que, recebendo as notas das avaliaes bimestrais e, se for o caso, a nota da reavaliao e, se for o caso, a nota da rova final, fornea a mdia final de um aluno da UFAL e a

sua condio em relao a rovao. 23. Escreva uma funo que fornea a trans osta de uma ada. 24. Um dos mtodos ara a se estudar as solues de um sistema linear de n equaes a n incgnitas a lica o eraes elementares sobre as linhas da matriz dos coeficientes, sendo a ermuta de duas linhas uma destas o eraes elementares. Escreva uma funo que ermute as osies de duas linhas de uma matriz dadas. 25. Uma matriz quadrada dit a triangular se os elementos situados acima de sua diagonal rinci al so todos nu los. Escreva uma funo que receba uma matriz quadrada e verifique se ela triangular . 26. O exem lo 4 deste ca tulo a resentou uma funo ara armazenar uma matriz simtri ca. Este exerccio quer algo contrrio: escreva uma funo que verifique se uma matriz d ada simtrica. 27. Escreva uma funo que determine o roduto de duas matrizes. 28. Es creva uma funo que determine as mdias de cada uma das linhas de uma matriz. Por exe m lo, 3 7 4 6 3 4 4 ,5 . 29. Escreva um a matriz dada, o, se a matriz

7 4 6 5,0 se a matriz dada for 5 4 5 4 a funo deve fornecer a 2 6 5 1 2 6 5 1 3,5 rograma que determine o menor valor de cada uma das linhas de um fornecendo o ndice da coluna que contm este menor valor. Por exem l dada for 2 6 5 1

3 7 4 6 5 2 5 4 , a funo deve fornecer uma tabela do ti o Linha 1 2 3 Menor valor 3 2 1 Coluna 1 2 4

Uma funo como esta oderia receber os reos de diversos rodutos raticados or vrio s su ermercados e forneceria, ara cada roduto, o menor reo e o su ermercado qu e ratica este melhor reo. 30. No exem lo 4 da seo anterior vimos como armazenar u ma matriz simtrica. Na rtica, uma matriz deste ti o ocorre, or exem lo, numa tab ela de distncias entre cidades, como a seguinte tabela, que d as distncias areas, em km, entre as ca itais dos estados nordestinos (Aracaju, Fortaleza, Joo Pessoa, M acei, Natal, Recife, Salvador, So Lus, Teresina). A F A 0 812 F 812 0 JP 418 562 M 210 730 N 550 414 R 398 640 S 267 1018 SL 1218 640 T 1272 432 JP 438 562 0 294 1 44 118 758 1208 987 M 210 730 284 0 423 191 464 1220 1126 N 550 444 144 423 0 25 2 852 1064 843 R 398 640 110 191 252 0 654 1197 935 S 267 1018 758 464 852 654 0 1319 1000 SL 1218 640 1208 1220 1064 1197 1319 0 320 T 1272 432 987 1126 843 93 5 1000 320 0

Imagine que uma com anhia de trans orte areo estabelea que uma viagem entre duas c idades que distem mais de 400 Km deve ter uma escala. Escreva um rograma que ar mazene uma tabela das distncias areas entre n cidades e, dadas duas cidades, deter mine, se for o caso, a cidade em que deve se realizar uma escala ara que o erc urso seja o menor ossvel. Por exem lo, nas condies estabelecidas, a viagem entre M acei e So Lus deve ter uma escala em Fortaleza (o ercurso Macei/Fortaleza/So Lus d 370 Km; o ercurso, or exem lo, Macei/Recife/So Lus de 1388 Km). 31. (Problema no t rivial) Utilizando uma funo recursiva, escreva um rograma que gere as combinaes dos nmeros 1, 2, ..., n com taxa k, n e k dados. Por exem lo, se n = 5 e k = 3, o r ograma deve gerar as combinaes 1, 2, 3

1, 2, 4 1, 2, 5 1, 3, 4 1, 3, 5 1, 4, 5 2, 3, 4 2, 3, 5 3, 4, 5 Observao Pro ostas de solues dos exerccios ro ostos odem ser solicitadas atravs de mensagem eletrnica ara jaime@ccen.ufal.br com assunto RESPOSTAS LIVRO C, anexando o formulrio abai xo devidamente reenchido. Nome 1 2 Categoria1 Instituio2 Curso2 Cidade/Estado Categoria: docente, estudante, autodidata Se docente ou estudante

7 Pesquisa e ordenao 7.1 Introduo Neste ca tulo, discutiremos dois roblemas clssicos de com utao. O rimeiro deles, esquisa, busca ou consulta, consiste em se verificar se um dado valor est armazen ado num vetor (ou num cam o de um registro de um arquivo, como veremos no ca tulo 9). So vrios os exem los de esquisas em com utao. Uma busca or ginas da internet que contenham um determinado assunto; uma busca no Registro Nacional de Veculos A utomotores (RENAVAM) na tentativa de se encontrar o nome do ro rietrio do veculo de uma laca dada; uma busca nos registros da Receita Federal a res eito de um C PF dado. O segundo roblema conhecido como ordenao ou classificao (introduzido su er ficialmente no ca tulo 3) consiste em se colocar numa ordem reestabelecida uma r elao de valores. No ca tulo referido, mostramos como ordenar uma relao contendo trs v lores. Neste ca tulo, a resentaremos algoritmos ara ordenar uma lista com qualqu er nmero de valores. A ordenao de uma relao realizada ara que a leitura dos resulta os seja facilitada ou ara que, como veremos abaixo, esquisas sejam realizadas com mais eficincia. Um exem lo rtico da necessidade da ordenao ocorre na confeco da ista dos a rovados num concurso vestibular. Algumas universidades divulgam esta lista com os nomes dos a rovados em ordem alfabtica e outras em ordem de classifi cao. Tanto num caso como no outro h necessidade de ordenao. 7.2 Pesquisa sequencial O mtodo de busca de mais fcil com reenso o que temos utilizado at agora e chamado squisa sequencial. Este mtodo consiste em se ercorrer, a artir da com onente ze ro, todo o vetor com arando-se o valor de cada com onente com o valor esquisado . Naturalmente, a esquisa se encerra quando o valor esquisado encontrado ou qu ando se atinge o final do vetor, significando, neste caso, que a esquisa no foi bem sucedida. A funo abaixo esquisa, numa relao de inteiros armazenada em v, um int eiro assado ara o armetro x. Observe que o armetro t receber a quantidade de el ementos da relao e que a funo retornar a osio do valor rocurado na relao, se a for bem sucedida, e -1 se o valor rocurado no for encontrado. int PesqSeq(int * v, int t, int x) { int i; i = 0; while ((v[i] != x) && (i < t)) i = i + 1; if (i == t) return -1; else return i + 1; }

7.3 Pesquisa binria muito fcil erceber que o mtodo da esquisa binria bastante ineficiente: imagine qu e este mtodo fosse utilizado ara se esquisar a alavra zumbaia num dicionrio da lngua ortuguesa (a ro sito, zumbaia significa cortesia exagerada; cum rimento ru idoso e servil). Quando a relao est ordenada, existe um mtodo de busca, chamado esq uisa binria, bem mais eficiente do que a esquisa sequencial: com ara-se o elemen to esquisado com a com onente "central" da relao; se forem iguais, a esquisa enc errada com sucesso; se o elemento esquisado for menor que a

com onente central re ete-se a esquisa em relao " rimeira metade" da relao; se o el emento esquisado for maior re ete-se a esquisa em relao "segunda metade" da relao. Por exem lo, uma esquisa do nmero 7 na relao {1, 3, 4, 5, 6, 8, 10, 11, 12, 15, 1 8, 19, 20, 21, 22, 25, 26} comearia com arando-se 7 com 12; como 7 < 12, esquisa -se 7 na relao {1, 3, 4, 5, 6, 8, 10, 11}; ara isto com arase 7 com 5 e, como 7 > 5, esquisa-se este valor na relao {6, 8, 10, 11}; esquisa-se na relao {6, 8}; es quisa-se em {6} e conclui-se que 7 no est relao. int PesqBinaria(int *v, int t, int x) { int i, Central; i = 0; Central = t/2; while ((x != v[Central]) && (i <= t)) { if (x < v[Central]) t = Central - 1; else i = Central + 1; Central = (i + t)/ 2; } if (i > t) return (-1); else return(Central); } A esquisa binria tambm im or tante no desenvolvimento da lgica de rogramao elo fato de que uma funo que ode se im lementada recursivamente, sem que a im lementao recursiva seja menos eficiente do que a no recursiva. Para erceber a recursividade basta ver que a mesma esqu isa se re ete, sendo que, em cada re etio, o vetor esquisado tem alterado a osio d a sua ltima com onente ou da sua rimeira com onente. int PesqBinRec(int *v, int i, int t, int x) { int Central; Central = (i + t)/2; if (v[Central] == x) return (Central + 1); else if (t < i) return (-1); else if (x < v[Central]) PesqBinRec (v, i, Central - 1, x); else PesqBinRec(v, Central + 1, t, x); } 7.4 Ordenao O SelecSort O algoritmo SelectSort consiste em se selecionar, sucessivamente, o maior elemen to, o segundo maior elemento, o terceiro maior elemento, etc., e, a s cada seleo, a rmazenar o valor selecionado num vetor auxiliar na osio que mantm o tal vetor auxi liar ordenado. Por exem lo, se se retende a ordenao em

ordem crescente, o " rimeiro maior valor" armazenado na ltima osio do vetor auxili ar; o "segundo maior valor" armazenado na enltima osio do vetor auxiliar e assim sucessivamente. Para que se obtenha o "segundo maior valor" do vetor, exclumos o " rimeiro maior valor" atribuindo a esta com onente um valor sabidamente menor d o que todos os valores armazenados no vetor. Por exem lo, se os valores do vetor so ositivos ode-se atribuir -1 a cada com onente j selecionada e j armazenada no vetor auxiliar. Para exem lificar o mtodo, vamos ordenar o vetor v = {5, 2, 7, 1 , 8}. Basta ercorrer o vetor 5 vezes selecionando sucessivamente 8, 7, 5, 2 e 1 e realizando as seguintes atribuies: 1. Aux = { , , , , 8} v = {5, 2, 7, 1, -1} 2 . Aux = { , , , 7, 8} v = {5, 2, -1, 1, -1} 3. Aux = { , , 5, 7, 8} v = {-1, 2, -1, 1, -1} 4. Aux = { , 2, 5, 7, 8} v = {-1, -1, -1, 1, -1} 5. Aux = {1, 2, 5, 7 , 8} v = {-1, -1, -1, -1, -1}, Para finalizar, basta armazenar nas com onentes d e v as com onentes de Aux. void MaiorElemento(int *v, int t, int &m, int & ) { i nt i, Pos; m = v[0]; Pos = 0; for (i = 1; i < t; i = i + 1) if (v[i] > m) { m= v [i]; Pos = i; } = Pos; } void SelectSort(int *v, int t) { int i, Pos, Aux[500] ; for(i = 0; i < t; i = i + 1) { MaiorElemento(v, t, Aux[t - 1 - i], Pos); v[Pos ] = -1; } for (i = 0; i < t; i = i + 1) v[i] = Aux[i]; } Observe que, como o arm etro m assado or referncia, a funo MaiorElemento() j armazena no vetor Aux os maio res elementos de v, nas suas osies definitivas. H uma outra verso do SelectSort que rescinde de um vetor auxiliar. Se o vetor contm k com onentes, esta verso consis te em se com arar a maior dentre as k - 1 rimeiras com onentes com a com onente de ordem k, ermutando-se suas osies se aquela maior com onente for menor do que esta ltima. Esta o erao coloca o maior elemento na ltima osio do vetor, como deseja o. Este raciocnio re etido no vetor das k - 1 rimeiras com onentes e assim suces sivamente. void SelectSortVersao2(int *v, int t) { int Pos, k, m; k = t - 1; whi le (k > 0)

{ MaiorElemento(v, k, m, Pos); if (v[k] < v[Pos]) { v[Pos] = v[k]; v[k] = m; } k --; } }

O BubbleSort O algoritmo BubbleSort consiste em se ercorrer o vetor a ser ordenado vrias veze s, com arando-se cada elemento com o seguinte, ermutando suas osies se eles no es tiverem na ordem retendida. Assim, cada vez que o vetor ercorrido o maior (ou o menor) elemento ainda no ordenado colocado na sua osio de ordenao definitiva. Nat ralmente, o vetor ser ercorrido at que no haja mais trocas a se fazer, quando ento ele estar ordenado. Por exem lo, se o vetor a ser ordenado em ordem crescente for v = {5, 1, 9, 3, 7, 2}, teramos as seguintes configuraes ara v, de acordo com a o rdem de ercurso: Percurso 0 1 2 3 4 void BubbleSort(int *v, int t) { int j, s, Aux; do { s = 1; t = t - 1; for (j = 0; j < t; j = j + 1) if (v[j] > v[j + 1]) { Aux = v[j]; v[j] = v[j + 1]; v[j + 1 ] = Aux; s = 0; } } while (s == 0); } v {5, 1, 9, 3, 7, 2} {1, 5, 9, 3, 7, 2} {1, 5, 3, 9, 7, 2} {1, 5, 3, 7, 9, 2} {1 , 5, 3, 7, 2, 9} {1, 3, 5, 7, 2, 9} {1, 3, 5, 2, 7, 9} {1, 3, 2, 5, 7, 9} {1, 2, 3, 5, 7, 9} A seguinte funo im lementa o algoritmo descrito acima. Observe que a varivel s verifica se houve alguma troca ara que outro ercurso se ja realizado. Observe tambm que o comando t = t 1 se justifica elo fato de que n o ercurso de ordem i, i 1 elementos j esto em suas osies definitivas.

7.5 Exerccios ro ostos 1. Algumas essoas acham que so azaradas quando rocuram uma ficha numa ilha, se m re tendo receio que a ficha rocurada seja uma das ltimas da ilha. Uma essoa que acredite ser assim azarada ode esquisar a tal ficha esquisando, sucessiva mente, a arte su erior e a arte inferior da ilha. Assim, verifica a rimeira ficha, em seguida, a ltima, em seguida, a segunda ficha, em seguida, a enltima e assim sucessivamente. Escreva uma funo que im lemente este mtodo de esquisa. 2. A algoritmo InsertSort ara ordenao de um vetor Vet consiste em se tomar um vetor au xiliar Aux, contendo uma nica com onente Vet[0]. Em seguida, inserem-se as demais com onentes de Vet, uma a uma, em Aux de modo que Aux se mantenha ordenado. Esc reva uma funo que im lemente o InsertSort. 3. Escreva uma verso recursiva do Select Sort. Observao Pro ostas de solues dos exerccios ro ostos odem ser solicitadas atra vs de mensagem eletrnica ara jaime@ccen.ufal.br com assunto RESPOSTAS LIVRO C, an exando o formulrio abaixo devidamente reenchido. Nome 1 2 Categoria1 Instituio2 Curso2 Cidade/Estado Categoria: docente, estudante, autodidata Se docente ou estudante

8. Cadeias de caracteres (strings) 8.1 Introduo Como j sabemos uma declarao do ti o char Cad[10]; define um conjunto de dez osies de memria, cada uma delas de um byte, ca azes de armazenar variveis do ti o char. Co mo dissemos de assagem no ca tulo anterior, um vetor cujas com onentes so do ti o char constitui uma cadeia de caracteres ou, em restado do ingls, uma string. Alm da quantidade de bytes, o que diferencia a declarao acima da declarao int v[10]; que , enquanto o vetor v no ode ser referenciado globalmente com um comando do ti o scanf("%v", v) ou rintf("%v", v) os com iladores C contm recursos ara referncia a uma string como se ela fosse uma varivel sim les. Desta forma, com a declarao aci ma, odemos ter um rograma como o seguinte: #include <stdio.h> main() { char Ca d[10]; rintf("Digite uma alavra"); scanf("%s", Cad); rintf("A alavra digitad a foi: %s ", Cad); } Vale lembrar que, de acordo com o ca tulo 2, "%s" tanto o cdi go de converso da funo scanf() ara armazenamento de uma cadeia de caracteres como o cdigo de formatao da funo rintf() ara exibio de uma string. Vale tambm observar colocao do o erador de endereo & em scanf("%s", Cad). Para com reender este fato ba sta lembrar que um vetor um onteiro. Ainda vale observar que a tentativa de se armazenar em Cad uma cadeia com mais de 10 caracteres no recusada elo sistema, m as odem ocorrer armazenamentos indesejados. Para que o tamanho da cadeia no fiqu e limitado, deve-se declarar a cadeia como um onteiro: char *Cad;. Tambm ossvel se fazer atribuies ex lcitas a uma string. Por exem lo, oderamos "sofisticar" o ro grama acima, escrevendo-o: #include <stdio.h> main() { char Cad[40], Str[40] = " Digite uma alavra"; rintf("%s", Str); scanf("%s", Cad); rintf("A alavra digi tada foi: %s\n", Cad); } A referncia ex lcita a uma string ossvel elo fato de que o sistema coloca no final da cadeia o caractere nulo, indicado or '\0', tanto numa atribuio (como Str = "Digite uma alavra";) como numa entrada atravs da funo sca nf(). este caractere nulo que indica ao sistema o final da string ara que ele ossa rocess-la de acordo com o retendido, como exibi-la atravs da funo rintf(), or exem lo. necessrio lembrar que a a osio automtica do caractere nulo no final da s tring fora se definir n numa declarao do ti o char Cad[n]; uma unidade maior do que o nmero de caracteres da cadeia que se retende armazenar em Cad. Neste formato de declarao, ode-se inicializar uma string quando da sua declarao, colocando o valo r inicial retendido entre chaves, que no so necessrias no Turbo C++ 3.0.

#include <stdio.h> main() { char Cad[100], Str[20] = {"Digite uma alavra"}; ri ntf("%s \n", Str); scanf("%s", Cad); rintf("A alavra digitada foi: %s \n", Cad ); } Agora o sistema verifica o nmero de caracteres da cadeia que se retende arm azenar, recusando, em nvel de com ilao, se este nmero for maior do que n. O armazena mento de uma cadeia de caracteres atravs da funo scanf() tem uma limitao em funo de esta funo considera tambm (alm da digitao de <enter>) o es ao em branco como finali or da string. Isto im lica que uma cadeia de caracteres que ossua um es ao em br anco (o nome de uma essoa, or exem lo) no ossa ser com letamente armazenada. P ara estes casos, deve-se utilizar a funo gets() cujo rotti o est no arquivo stdio.h e armazena no argumento com o qual foi ativado uma cadeia de caracteres digitad a no teclado. Assim ara se armazenar uma frase ou o nome com leto de uma essoa , o rograma acima deveria ser modificado ara o seguinte rograma: #include <st dio.h> main() { char Cad[40]; rintf("Digite a frase"); gets(Cad); rintf("A fra se digitada foi: %s \n", Cad); } Re etindo o que j foi dito, necessrio um certo cu idado com execues sucessivas das funes scanf() ( ara strings) e gets(). O que aconte ce o seguinte: quando os dados esto sendo digitados, eles so armazenados numa rea c hamada buffer e as execues das funes aqui referidas fazem o sistema armazenar os dad os do buffer na varivel retendida. Assim, se no estiver vazio, o contedo do buffer ser armazenado or uma rxima ativao de uma destas funes. rudente, ento, "esvazi buffer antes de uma chamada de uma segunda chamada de scanf() ou de gets(), ist o odendo ser feitos atravs da instruo fflhush(stdin) (no rximo ca tulo, faremos com entrios sobre stdin).

8.2 Funes de biblioteca ara mani ulao de cadeias de caracteres Ao contrrio de outras linguagens, C no ossui o erador que atue com o erandos do t i o cadeia de caracteres. Qualquer mani ulao de strings feita atravs de funes da bib ioteca adro de C. Nesta seo, a resentaremos algumas destas funes, cujos rotti os es no arquivo string.h. a) Determinando o com rimento de uma string. A funo de rotti o int strlen(char *s) retorna o nmero de caracteres da string armazenada em s, s em considerar o caractere nulo. Por exem lo, a sequncia de instrues char *Cad; int Com ; Cad = "Universidade Federal de Alagoas"; Com = strlen(Cad); armazenar na v arivel Com o valor 31. Vale observar que o armetro de strlen() ode ser uma cons tante: odemos ter um comando

rintf("%d", strlen("Brasil")); b) Com arando duas strings. A com arao entre duas strings em relao ordem alfabtica feita atravs da funo de rotti o int strcm (cha char *s2); que retorna a diferena entre os cdigos ASCII dos rimeiros caracteres d iferentes do dois armetros, que odem ser constantes. Por exem lo, a chamada str ("Casa", "Caso"); retorna 14, que a diferena entre os cdigos ASCII de 'o' (111) e o de 'a' (97). Naturalmente, se as cadeias so iguais, a funo retorna 0 (zero). c) C onvertendo maiusculas ara minsculas e vice-versa. A converso das letras de uma st ring de minsculas ara maiusculas feita atravs da funo de rotti o char *stru r(char *s); enquanto que a converso inversa feita atravs da funo char *strlwr(char *s); od endo o armetro ser uma constante. d) Concatenando uma string a outra. A concatenao de uma cadeia de caracteres a uma outra cadeia feita atravs da funo char *strcat(char *s1, char *ss); que retorna a cadeia s1 acrescida dos caracter es de s2, que ode ser uma constante. Por exem lo, a sequncia de instrues char *Str ; Str = "Com uta"; strcat(Str, "dor"); armazena em Str a cadeia "Com utador". e) Fazendo c ia de uma string. Se s1 e s2 foram definidas como strings no se ode fa zer uma atribuio do ti o s1 = s2. Se retendemos armazenar o contedo de s2 em s1 de vemos utilizar a funo char *strc y(char *s1, char *s2); que faz uma c ia do contedo de s2 em s1, odendo s2 ser uma constante. f) Co iando arte de uma string. Pode -se co iar os n rimeiros caracteres de uma string atravs da funo char *strnc y(cha r *s1, char *s2, int n); que armazena em s1 os n rimeiros caracteres de s2, od endo este segundo armetro ser uma constante. necessrio observar que o caractere n ulo no armazenado, devendo isto ser feito elo rograma. g) Verificando se uma st ring subcadeia de outra string. Para se verificar se uma dada cadeia de caracteres est contida em outra cadeia, u tiliza-se a funo char *strstr(char *s1, char *s2); que retorna um onteiro ara a rimeira osio a artir da qual s2 ocorre em s1, retornando NULL se s2 no est contida em s1. Por ex em lo, a execuo do rograma #include <stdio.h> #include <string.h> main(void) {

char *Str1 = "Logica de Programacao", *Str2 = "grama", * ; = strstr(Str1, Str2 ); if ( != NULL) rintf("A \"ultima\" substring de %s que contem %s e: %s.\n", Str1, Str2, ); else rintf("%s nao esta contida em %s", Str2, Str1); } exibe na tela a afirmao: A "ultima" substring de Logica de Programacao que contem grama e gramacao. h) Convertendo uma string em nmeros Como veremos em exem los a seguir, muitas vez es refervel que um dado de entrada seja um vetor de caracteres, mesmo que a funo n ecessite realizar o eraes matemticas com ele. A converso de uma subcadeia de dgitos ara os ti os int, long ou float, res ectivamente, feita atravs das funes int atoi(c har *s); long atol(char *s); double atof(char *s); cujos rotti os esto no arquivo stdlib.h. Estas funes retornam o nmero (no formato res ectivo) corres ondente rim eira (da esquerda ara direita) subcadeia de s que ode ser convertida , retorna ndo 0 (zero) se o rimeiro caractere de s no for um dgito ou um dos caracteres + e (se o rimeiro caractere for + ou -, ara que haja alguma converso o segundo dev e ser um dgito).

8.3 Exem los Parte VI 1. A funo a seguir exclui uma dada quantidade n de caracteres a artir de uma osio dada . Para conseguir excluir os n caracteres, "trazemos" a substring formada elos ltimos caracteres que no sero excludos mais o caractere nulo ara a osio . Nat ralmente, se o nmero de caracteres a serem excludos for maior do que o dis onvel, t odos os caracteres a artir de sero excludos. Isto obtido atravs da funo strnc y() #include <stdio.h> #include <string.h> void DeletaCaracteres(char *s, int n, in t ) { int i, Com ; char *Aux; Com = strlen(s); if ( + n <= Com ) { i = ; whi le (i <= Com - n) { s[i] = s[i + n]; i = i + 1; } } else s[ ] = '\0'; } 2. A rx ima funo insere uma cadeia s1 numa cadeia s2 a artir de uma osio dada. void Inse re(char *s1, char *s2, int ) { int i, c1, c2;

char a[20]; c1 = strlen(s1); c2 = strlen(s2); for (i = 0; i < c1 + c2 ; i++) if (i < ) a[i] = s1[i]; else if (i < + c2) a[i] = s2[i - ]; else a[i] = s1[i c2]; a[i] = '\0'; strc y(s1, a); } 3. A funo strstr() comentada acima verifica se uma string s1 est contida numa string s2 mas no retorna a osio a artir da qual s2 ocorre em s1. A funo abaixo resolve esta questo atravs da diferena dos com rimentos d e s1 e da cadeia que a chamada strstr(s1, s2) retorna. int Pos(char *s1, char *s 2) { char *Aux; Aux = strstr(s1, s2); if (Aux != NULL) return(strlen(s1) - strle n(Aux)); else return (-1); } 4. Com a funo strnc y() ode-se co iar os n rimeiros caracteres de uma string. Considerando que um onteiro de caracteres armazena o endereo da osio de memria do rimeiro caractere da string, que as osies de memria e armazenam as com onentes de um vetor so contguas e que cada varivel do ti o char ocu a um byte, se s um onteiro do ti o char e um inteiro, s + ser um onteir o que a ontar ara o caractere de ordem . Assim, strnc y(s1, s2 + , n) armazena r em s1 os n caracteres de s2 a artir da osio . 5. A rxima funo converte uma data dada (como uma cadeia de caracteres) no formato americano mm/dd/aaaa ara o form ato brasileiro dd/mm/aaaa. O algoritmo usa a funo strnc y() (com a observao do exem lo anterior) ara extrair o dia, o ms e o ano e a funo strcat() ara concatenar na ordem retendida. void ConverteData(char *s) { char *Dia, *Mes, *Ano; strnc y(Me s, s, 3); Mes[3] = '\0'; strnc y(Dia, s + 3, 3); Dia[3] = '\0'; strnc y(Ano, s + 6, 4); Ano[4] = '\0'; strcat(Dia, Mes); strcat(Dia, Ano); strc y(s, Dia); } 6. Um rograma que mani ule datas deve ossuir uma funo que verifique se a data dada era vlida. Isto no ocorreria se o valor do ms fosse maior que 12 ou que, or exem l o, se o ms fosse junho e o dia fosse 31. int VerificaData(char s[11]) {

int i, d, m, a, Verifica; char Dia[3], Mes[3], Ano[5]; strnc y(Dia, s, 2); Dia[3 ] = '\0'; strnc y(Mes, s + 3, 2); Mes[3] = '\0'; strcn y(Ano, s + 6, 4); Ano[4] = '\0'; d = atoi(Dia); m = atoi(Mes); a = atoi(Ano); Verifica = 1; if ((m <= 12) && (m >= 1) && (d >= 1) && (d <= 31)) switch(m) { case 2: if (((a % 4 == 0) && (a % 100 != 0)) (a % 400 == 0)) if (d > 29) Verifica = 0; else; else if (d > 28) Verifica = 0; break; case 4: case 6: case 9: case 11: if (d > 30) Verifica = 0; break; } else Verifica = 0; return(Verifica); } Vale observar que os comando s Verifica = 0 oderiam ser substitudos or return(0). Neste caso, o ltimo comando seria return(1). 7. Os com iladores C ignoram es aos em branco digitados num ro grama. Uma maneira de se tornar isto ossvel , antes da com ilao, eliminar todos os es aos em branco "su rfluos", ou seja, deixar duas alavras sem re se aradas or u m nico es ao em branco. A funo abaixo, utilizando a funo DeletaCaracteres(), realiza al ao. void ExcluiBrancosSu erfluos(char *s) { int i, NumBrancos; i = 0; while (s[i] != '\0') { NumBrancos = 0; while (s[i] = = ' ') { NumBrancos = NumBrancos + 1; i = i + 1; } if (NumBrancos > 1) { i = i NumBrancos; DeletaCaracteres(s, NumBrancos - 1, i); }

i = i + 1; } } 8. A questo a seguir bem interessante. Trata-se de um rograma que determine o dgito verificador de um nmero de uma conta corrente, de um nmero de ma trcula de um estudante de uma escola, etc. O dgito verificador serve ara a reveno de ossveis erros de digitao. Por exem lo, se a matrcula 302457 fosse digitada erron eamente como 39245-7, o erro seria detectado, ois o dgito verificador da conta 3 9245 seria 6 e no 7. Existem vrios mtodos ara a determinao do dgito verificador. Um eles dado elo seguinte algoritmo: 1. Multi lica-se os nmeros corres ondentes aos dgitos da conta, da direita ara es querda, or 2, or 3, etc.. 2. Soma-se os rodutos obtidos no item 1. 3. Determina-se o resto da diviso da so ma obtida no item 2 or 11. 4. Subtrai-se de 11 o resto obtido no item 3 5. Se o valor obtido no item 4 for 10 ou 11 o dgito verificado igual a zero; seno, o dgito o valor obtido no item referido. Por exem lo, se o nmero da conta for 30245, tem os 1. 5x2 = 10, 4x3 = 12, 2x4 = 8, 0x5 = 0, 3x6 = 18 2. 10 + 12 + 8 + 0 + 18 = 4 8 3. Resto(48, 11) = 4 4. 11 - 4 = 7 5. Dgito verificador = 7. A funo abaixo im lem enta este algoritmo. Observe que foi utilizado molde ara converter caracteres e m inteiros e vice-versa. int ArmazenaDigitos(char *s, int *v) { int i, Com ; Com = strlen(s); for (i = 0; i < Com ; i = i + 1) v[i] = (int) ( s[i] - '0'); return(i); } char CalculaDigito(char *s) { char c; int t, i, j, Dig ito, *v; t = ArmazenaDigitos(s, v); Digito = 0; j = 2; for (i = t - 1; i >= 0; i = i - 1, j = j + 1) Digito = Digito + v[i]*j; Digito = Digito % 11; Digito = 11 - Digito; if ((Digito == 10) (Digito == 11)) Digito = 0; c = (char) Digito + '0'; return (c); } 8.4 Exerccios ro ostos 1. Uma alavra alndroma se ela no se altera quando lida da direita ara esquerda. Por exem lo,

raiar alndroma. Escreva um rograma que verifique se uma alavra dada alndroma. 2. Um dos recursos dis onibilizados elos editores de texto mais modernos a dete rminao do nmero de alavras de um texto. Escreva um rograma que determine o nmero d e alavras de um texto dado. 3. O exerccio 21 do ca tulo 6 solicitava um rograma que convertesse um nmero dado no sistema decimal ara o sistema binrio. Pela limit ao do sistema em tratar nmeros inteiros, uma soluo que tratasse a converso como sendo do ti o long seria limitada. Escreva um rograma ara a converso citada, tratando o valor em binrio como uma cadeia de caracteres. 4. Escreva um rograma que conv erta um nmero do sistema binrio, dado como uma cadeia de zeros e uns, ara o siste ma decimal de numerao. 5. Reescreva a funo a resentada no exem lo 8 deste ca tulo de tal modo que ele ossa, alm de gerar dgitos verificadores, verificar se uma conta dada (incluindo o dgito verificador) foi digitada incorretamente, incorreo esta det ectada elo dgito verificador. 6. Os editores de texto ossuem um recurso que er mite o usurio substituir uma sub-cadeia de um texto or outra cadeia de caractere s. Escreva um rograma que realize esta ao numa frase dada. 7. As com anhias de tr ans ortes areos costumam re resentar os nomes dos assageiros no formato ltimo sob renome/nome. Por exem lo, o assageiro Carlos Drumond de Andrade seria indicado or Andrade/Carlos. Escreva um rograma que receba um nome e o escreva no format o acima. 8. As normas ara a exibio da bibliografia de um artigo cientfico, de uma monografia, de um livro texto, etc., exigem que o nome do autor seja escrito no formato ltimo sobrenome, sequncia das rimeiras letras do nome e dos demais sobren omes, seguidas de onto final. Por exem lo, Antnio Carlos Jobim seria referido o r Jobim, A. C.. Escreva um rograma que receba um nome e o escreva no formato de bibliografia. 9. muito comum que os ttulos de documentos como avisos, declaraes, a testados, etc., a aream em letras maiusculas se aradas or um es ao em branco. Esc reva uma funo que receba uma alavra e a retorne no formato acima. 10. Escreva uma funo que gere logins ara usurios de um sistema de com utao baseado na seguinte regr a: o login com osto elas letras iniciais do nome do usurio. Observao Pro ostas de solues dos exerccios ro ostos odem ser solicitadas atravs de mensagem eletrnica ar a jaime@ccen.ufal.br com assunto RESPOSTAS LIVRO C, anexando o formulrio abaixo d evidamente reenchido. Nome 1 2 Categoria1 Instituio2 Curso2 Cidade/Estado Categoria: docente, estudante, autodidata Se docente ou estudante

9 Estruturas e Arquivos 9.1 O que so estruturas Um vetor ca az armazenar diversos valores, com a ressalva de que todos sejam de um mesmo ti o de dado. Um rograma que gerencie os recursos humanos de uma em re sa mani ula dados de ti os diferentes relativos a cada um dos funcionrios. Por ex em lo, ara cada funcionrio deve-se ter sua matrcula, seu nome, seu endereo, o carg o que ele ocu a, o nmero de seus de endentes, o seu salrio, a data de admisso, etc. Observe que, nome, matrcula, endereo, data de admisso e cargo que ele ocu a odem ser tratados com variveis do ti o string, orm, como eventualmente haver necessidad e de se efetuar o eraes aritmticas com eles, o nmero de de endentes deve ser tratado como do ti o int e valor do salrio, do ti o float. A utilizao de uma varivel sim le s ara cada um destes elementos, im licaria, como so vrios funcionrios, a necessida de de vrios vetores, o que oderia atra alhar a legibilidade e a manuteno do rogra ma, alem de dificultar a ossibilidade de armazenamento dos dados em disco, conf orme veremos numa seo osterior. Uma estrutura um conjunto de variveis, denominadas cam os ou membros, que odem ser de ti os diferentes. comum se associar um iden tificador a uma estrutura, chamado etiqueta da estrutura, ara que se ossa defi nir uma varivel deste ti o. A definio de uma estrutura feita com a seguinte sintaxe : struct TEstrutura { Ti o de dado Identificador do cam o 1; Ti o de dado Identi ficador do cam o 2; ... Ti o de dado Identificador do cam o n; }; onde, ara cad a cam o, Ti o de dado ode ser qualquer ti o, at mesmo uma estrutura. Se esta dec larao for feita fora de qualquer funo, a estrutura TEstrutura ser global e qualquer f uno do rograma ode declarar uma varivel ca az de armazenar valores de acordo com os ti os de dados dos cam os, isto sendo feito a artir de uma declarao do ti o st ruct TEstrutura Identificador; Por exem lo, ara o rograma do exem lo acima od eramos definir as estruturas struct TEndereco { char Rua[40]; char Numero[5]; cha r Bairro[10]; char Ce [9]; }; struct TEstrutura { char Matricula[11]; char Nome[ 40]; struct TEndereco Endereco; int NumDe endentes; float Salario; char Cargo[8] ; }; e ento uma funo oderia ter uma varivel declarada da seguinte forma: struct TEs trutura Registro;

Na verdade, ao se definir struct TEstrutura est se definindo um novo ti o de dado e isto justifica a definio de uma varivel, no caso Registro, do ti o de dado struc t TEstrutura. A linguagem C oferece uma outra forma de se definir um novo ti o d e dado. Trata-se da declarao ty edef que oderia ser utilizado ara se definir a e strutura acima da seguinte forma: ty edef struct { char Matricula[11]; char Nome [40]; struct TEndereco Endereco; int NumDe endentes; float Salario; char Cargo[8 ]; } TEstrutura; Neste caso, a declarao de uma varivel do ti o TEstrutura seria fei ta sem a referncia ao ti o struct: TEstrutura Registro; A referncia a um cam o ar ticular da estrutura se faz com a a osio do identificador da varivel estrutura e o identificador do cam o se arados or um onto. No exem lo anterior oderamos ter comandos do ti o Registro.Salario = 4500.00; scanf("%s", Registro.Matricula); ge ts((Registro.Endereco).Rua); sendo os arnteses de (Registro.Endereco).Rua no obri gatrios. 9.2 Exem los Parte VII 1. Vejamos um rograma ara controlar as vendas de uma loja, no sentido de, ao f inal do dia, seja exibida uma lista relacionando todos os rodutos vendidos e os vendedores res ectivos #include <string.h> #include <conio.h> #include <stdio.h > ty edef struct { char Prod[20]; char Vend[4]; float Preco; } TVenda; void LeDa dos(TVenda v[100], int &t) { int i = 0; uts("Digite roduto vendedor reo ( / en cerrar digite 0 ara o roduto"); uts(Produto); scanf("%s", v[i].Prod); while (st rcm (v[i].Prod, "0") != 0) { fflush(stdin); uts(Vendedor); scanf("%s", v[i].Vend) ; uts(Preo); scanf("%f", &v[i].Preco); i++;

fflush(stdin); uts(Produto); scanf("%s", v[i].Prod); } t = i - 1; } void ExibeDad os(TVenda v[100], int t) { int i; for (i = 0; i <= t; i++) rintf("%s %s %.2f \n ", v[i].Prod, v[i].Vend, v[i].Preco); } main() { TVenda w[100]; int q; LeDados(w , q); ExibeDados(w, q); getch(); } 2. Imagine que tenha sido realizada uma esqu isa com 20 essoas a res eito de salrio, idade, nmero de filhos e sexo. O rograma abaixo recebe os dados coletados na esquisa e fornece a mdia salarial, a mdia da s idades e o nmero de mulheres cujo salrio maior R$ 500,00. #include <string.h> #i nclude <conio.h> #include <stdio.h> #include <stdlib.h> ty edef struct { int Sal ario, Idade, NumFilhos; char Sexo; } TDados; /*Recebe os dados da coleta e os ar mazena num vetor de registros&/ void LeDados(TDados v[20], int &i) { for (i = 0; i < 20; i++) { rintf("Salario: "); scanf("%d", &v[i].Salario); rintf("Idade: "); scanf("%d", &v[i].Idade); rintf("Numero de filhos: "); scanf("%d", &v[i].Nu mFilhos); fflush(stdin); rintf("Sexo: "); scanf("%d", &v[i].Sexo); } } /*Determ ina os indicadores retendidos void Indicadores(TDados v[20], int t, int &MedSal , int &MedIdade, int &NumMulheres, int &MaiorSal) { int i, SomaIdade = 0, SomaSa l = 0; NumMulheres = 0, MaiorSal = 0; for (i = 0; i < t; i++) { SomaSal = SomaSa l + v[i].Salario;

SomaIdade = SomaIdade + v[i].Idade; if (v[i].Sexo == 'F' && v[i].Salario > 500) NumMulheres++; if (v[i].Salario > MaiorSal) MaiorSal = v[i].Salario; } MedIdade = SomaIdade/t; MedSal = SomaSal/t; } main() { TDados w[20]; int q; int MediaSal, MediaIdade, Mulheres, MaiorSalario; clrscr(); LeDados(w, q); clrscr(); ExibeDad os(w, q); Indicadores(w, q, MediaSal, MediaIdade, Mulheres, MaiorSalario); rint f("\nMedia Salarial: %d\nMediaIdade: %d\nNumero de mulheres com salarios su erio res a R$ 500,00: %d\nMaior Sal rio: %d\n", MediaSal, MediaIdade, Mulheres, Maior Salario); getch(); }

9.3 O que so arquivos At o momento, os dados mani ulados elos nossos rogramas (dados de entrada, dado s gerados elo rograma e resultados do rocessamento) foram armazenados na memri a do com utador que, como j foi dito, uma memria voltil, no sentido de que todas as informaes nela armazenadas so erdidas quando a execuo do rograma , or qualquer mo ivo, encerrada. evidente que um rograma que gerencia os recursos humanos de uma em resa no ode mani ular os dados relativos aos funcionrios a enas na memria do c om utador. Isto im licaria, or exem lo, a necessidade de que fossem digitados t odos os dados em todas as execues do rograma. evidente que os dados relativos a c ada um dos funcionrios da em resa devem estar armazenados, de forma ermanente, e m um disco, de modo que o rograma que gerencia os recursos humanos ossa acess-l os em execues distintas. Dados e informaes reunidos e armazenados num disco constitu em um arquivo e a linguagem C ermite que se mani ule arquivos em discos, fornec endo recursos ara a realizao das o eraes bsicas que odem ser neles executadas: cria de um arquivo, alterao dos dados de um arquivo, excluso de dados de uma arquivo, in cluso de novos dados no arquivo, exibio (na tela ou em formato im resso) do contedo de uma arquivo, etc..

9.4 Arquivos de registros (Arquivos binrios) Os arquivos de uso mais comum na rtica de rogramao em C so os arquivos que armazen am dados oriundos de estruturas. Por exem lo, um sistema que gerencie uma locado ra de fitas deve mani ular um arquivo que armazene ara cada fita, um cdigo, o ttu lo do filme, o tema, a data de aquisio, o reo de custo, o valor da locao, etc. No mo mento da entrada, estes dados odem ser armazenados numa estrutura ara serem, e m seguida, armazenados num arquivo. Um conjunto de dados relativo a uma fita (ne ste exem lo) chamado registro e um arquivo em que um conjunto de registros est ar mazenado chamado arquivo de registros. Nesse caso, os dados so gravados em format o anlogo ao formato utilizado ara armazenamento em memria. Por esta razo, estes ar quivos tambm so chamados arquivos binrios. Uma grande arte das o eraes que so feitas em arquivos requer a verificao de que o registro que

se retende mani ular est armazenado no arquivo. Isto exige que os registros oss uam um cam o cujos valores sejam distintos entre si, sendo o valor deste cam o u m identificador do referido registro. Esta a funo de cam os do ti o CPF, matrculas, lacas de veculos, etc.. Um cam o identificador dos registros de um arquivo cham ado chave. Criando um arquivo de registros Um arquivo criado atravs da funo fo en(), que ossui dois armetros do ti o string e retorna um onteiro ara uma estrutura r-definida FILE (um onteiro que a onta ara uma estrutura FILE chamado onteiro de arquivo). O rimeiro dos armetros de fo en() fixa o nome com o qual o arquivo ser gravado no disco e o segundo armetr o a string "wb" que indica o formato binrio ara o arquivo que se est criando. Se, or alguma razo, o arquivo no for criado, a funo fo en() retorna o onteiro NULL. P or exem lo, o rograma abaixo, cria, no disco da unidade A, um arquivo denominad o Teste.arq. #include <stdio.h> FILE *CriaArquivo(char s[12]) { FILE * ; = fo en(s, "wb"); return( ); } main() { FILE *PontArquivo; PontArquivo = CriaArquivo( "A:\Teste.arq"); if (PontArquivo != NULL) rintf("Arquivo Teste.arq criado como sucesso"); else rintf("O arquivo Teste.arq no foi criado"); } A funo fo en(), alm d e criar um arquivo gravado no disco associa, atravs do que ela retorna, um ontei ro ara o arquivo referido. Este onteiro utilizado ara se referenciar o tal ar quivo no restante do rograma e chamado fluxo. o caso do onteiro de arquivo Pon tArquivo do exem lo anterior. Qualquer referncia a ele ser uma referncia ao arquivo Teste.arq. A criao de um arquivo com a ativao de fo en(NomeArquivo, "wb") deve ser solicitada com cautela. Se o arquivo de nome NomeArquivo existir, a chamada refe rida "a agar" todo o seu contedo. O ti o de cautela necessria veremos a seguir.

Gravando registros em um arquivo O rograma anterior, a enas cria o arquivo no disco no gravando nenhum registro. Se, a s a sua execuo, rocurarmos com o Windows Ex lorer o arquivo Teste.arq, encon tr-lo-emos com a indicao de que seu contedo tem zero bytes. Ou seja um arquivo vazio . natural que se crie um arquivo ara gravar registros e isto ode ser feito qua ndo da sua criao. A gravao de registros em um arquivo feito atravs da funo fwrite( ossui quatro armetros: 1. Um onteiro r ara uma varivel do ti o void que receb er o endereo da varivel do ti o estrutura que contm os dados que se quer armazenar; 2. Um inteiro n que receber o tamanho, em bytes, do registro a ser armazenado; 3. Um inteiro q que receber o nmero de registros que sero armazenados; 4. Um onteiro de arquivo que receber o fluxo associado atravs da funo fo en() ao arquivo de dis co onde os dados sero armazenados. Para se criar um arquivo de registros com a es trutura TRegistro definida na seo anterior e, logo em seguida, gravar registros no arquivo, teramos o seguinte rograma.

#include <stdio.h> struct TRegistro { char Mat[4]; char Nome[40]; float SalarioB ruto; }; /*Funo que cria um arquivo em disco, deixando-o a to a armazenar dados */ FILE *CriaArquivo(char s[12]) { FILE * ; = fo en(s, "wb"); return( ); } /*Funo que grava dados armazenados numa estrutura em um arquivo*/ void GravaRegistros(c har s[12]) { FILE * ; struct TRegistro r; rintf("Matricula ( ara encerrar, digi te matricula 0): "); fflush(stdin); gets(r.Mat); while ((r.Mat)[0] != '0') { ri ntf("Nome: "); fflush(stdin); gets(r.Nome); rintf("Salario bruto: "); scanf("%f ", &r.SalBruto); fwrite(&r, sizeof(r), 1, ); rintf("Matricula ( ara encerrar, digite matricula 0): "); fflush(stdin); gets(r. Mat); } fclose( ); } main() { FI LE *PontArquivo; char NomeArq[12]; rintf("Digite o nome do arquivo"); gets(Nome Arq); PontArquivo = CriaArquivo(NomeArq); if (PontArquivo != NULL) GravaRegistro s(NomeArq); else rintf("O arquivo %s nao ode ser criado \n", NomeArq); } A funo fclose() "fecha" um arquivo ara que o sistema o eracional ossa atualizar a tab ela do diretrio de arquivos. Observe que esta funo tem um armetro que receber o flux o associado ao arquivo que se retende fechar. necessrio que todo arquivo "aberto " seja fechado antes do encerramento da execuo do rograma. Exibindo o contedo de um arquivo

Para se ter acesso ao contedo de um arquivo necessrio que este contedo seja transfe rido ara memria do com utador ara, em seguida, ser exibido na tela ela funo rin tf() ou im resso or uma im ressora atravs da funo f rintf() (veremos isto numa seo s eguinte). A transferncia do contedo de um arquivo ara memria ode ser feita regist ro a registro, armazenando cada um deles em uma estrutura, ou atravs de um conjun to de registros, armazenando-o num vetor de estruturas. Aqui o taremos ela rim eira alternativa. A transferncia de registros de um arquivo ara a memria feita at ravs da funo fread() que, como a funo fwrite(), ossui quatro armetros: 1. Um ontei o ara uma varivel do ti o void que receber o endereo da varivel que armazenar os dad os contidos no registro; 2. Um inteiro que receber o tamanho, em bytes, da estrut ura que armazenar o registro na memria; 3. Um inteiro que receber o nmero de registr os que sero transferidos ara a memria (com a o o aqui escolhida este armetro sem re ser igual a 1); 4. Um onteiro de arquivo que receber o fluxo associado, atravs da funo fo en(), ao arquivo de disco que contm os registros. Para que seja ossvel a a licao da funo fread() necessrio que o arquivo esteja "aberto ara leitura", o que ito tambm atravs da funo fo en() agora com segundo armetro "rb". Quando feita uma c amada da funo fo en() com os argumentos Nome do Arquivo e "rb", o rimeiro registr o do arquivo fica dis onvel ara leitura (registramos este fato dizendo que o on teiro de leitura e gravao a onta ara o rimeiro registro). Considerando-se que a s a execuo da funo fread() o onteiro de leitura e gravao avana automaticamente ara rximo registro, ode-se ercorrer todo o arquivo at atingir o seu final, que forne cido ela funo feof(). Esta funo tem como armetro um onteiro de arquivo e retorna u m nmero diferente de zero quando o onteiro de leitura e gravao a onta ara o final do arquivo. Por exem lo, ode-se exibir na tela o contedo do arquivo gerado acim a atravs da seguinte funo. /*Funo que exibe na tela o contedo de um arquivo */ void E ibeArquivo(char s[12]) { FILE * ; struct TRegistro r; = fo en(s, "rb"); fread( &r, sizeof(r), 1, ); while (feof( ) == 0) /*Ou, o que o mais utilizado, while ( !feof( ))*/ { rintf("%s \b %s \b %f \n", r.Mat, r.Nome, r.SalarioBruto); fread( &r, sizeof(r), 1, ); } fclose( ); }

Verificando a existncia de um arquivo A ativao de fo en() no modo "rb" (o segundo armetro de fo en() chamado modo de abe rtura do arquivo) ermite que se escreva uma funo ara verificar a existncia de um arquivo, que ser til ara evitar uma ativao "desastrada" de fo en(), j que, como diss emos acima, a ativao desta funo no modo "wb" a aga todo o contedo do arquivo que oss uir o nome assado ara o rimeiro armetro desta funo. Isto im lica a necessidade de que se tenha cuidado na abertura de um arquivo no modo "wb", ois se for ass ado um nome de um arquivo que j existe todo o seu contedo ser erdido. rudente, o rtanto, que a abertura de um arquivo no modo aqui discutido seja recedida de um a funo que verifique se um arquivo com o nome escolhido j existe. Uma funo com este o bjetivo bastante sim les, ois a funo fo en() retorna NULL se for ativada no modo "rb" com o arquivo que no existe. int ExisteArquivo(char s[12])

{ FILE * ; = fo en(s, "rb"); if ( == NULL) return(0); else { fclose( ); retur n(1); } } Assim a funo CriaArquivo() definida anteriormente deveria ser escrita da seguinte forma: FILE *CriaArquivo(char s[12]) { FILE * ; = fo en(s, "rb"); if ( == NULL) { = fo en(s, "wb"); return( ); } else rintf("\a Arquivo %s j exis te!"); }

Localizando um registro num arquivo Uma o erao muito comum em arquivos a verificao de que um determinado registro est ne e armazenado. Esta o erao normalmente (como j foi dito no ca tulo 7) chamada consult a, esquisa ou busca e deve ser feita de acordo com o valor da chave do registro ou de um outro cam o que, relativamente, identifique o registro. No exem lo que estamos discutindo, a consulta ode ser feita elo cam o Mat (de matrcula) ou e lo cam o Nome. Em geral, a consulta se rocessa com a localizao do registro, a con sequente exibio do seu contedo e o retorno da osio que ele ocu a no arquivo. A local izao do registro ode ser feita, abrindo-o com fo en() e o ercorrendo at que o val or da chave seja encontrado; a exibio do seu contedo ode ser feita atravs das funes read() e f rintf(), e a osio que ele ocu a no arquivo fornecida or uma das funes f get os() e ftell() que ossuem os rotti os int fget os(FILE * , f os_t * os); lo ng ftell(FILE * ); onde, na rimeira, f os_t um ti o de dado r-definido. Nas dua s funes, receber o onteiro associado ao arquivo onde est se realizando a esquisa ; a osio do registro esquisado (dada ela ordem do ltimo byte ocu ado elo ltimo c am o deste registro) armazenada na varivel cujo endereo for assado ara o armetro os de fget os() ou ser retornado ela funo ftell(). Como em vetores, o rimeiro b yte ocu ado elo rimeiro cam o do rimeiro registro o de ordem zero. /*Funo que v erifica se um registro com matricula dada ertence ao arquivo, retornando sua o sio no arquivo*/ int ConsultaRegistro(char s[12], char s1[12]) { FILE * ; int Acho u = 0; struct TRegistro r; f os_t Byte;

= fo en(s1, "rb"); fread(&r, sizeof(r), 1, ); while (!feof( ) && Achou == 0) if (strcm (s, r.Mat) == 0) { fget os( , &Byte); Achou = 1; } else fread(&r, size of(r), 1, ); if (Achou == 0) return (-1); else return(Byte); } Como no nosso ex em lo o tamanho da estrutura de 48 bytes (4 bytes ara o cam o Mat, 40 ara o ca m o Nome e 4 ara o cam o SalarioBruto), se o registro esquisado for o rimeiro a funo retornar 48, se o registro esquisado for o segundo, a funo retornar retorna 6, se for o terceiro, a funo retornar 144 e assim or diante. Se o registro no estiv er no arquivo, a funo retornar 1. Quando o registro encontrado, seu contedo est arm nado na estrutura r. Assim, ara exibir o contedo do registro, basta no comando i f (strcm (s, r.Mat) == 0) incluir o comando rintf("Matricula: %s \n Nome: %s \n Salario: %f \n", r.Mat, r.Nome, r.SalBruto); Para escrever a funo acima com a funo ftell() bastaria se substituir os comando fget os( , &Byte) elo comando Byte = ftell( ). Considerando que a instruo return() interrom e a execuo de uma funo, a fun ima oderia rescindir da varivel Achou: int ConsultaRegistro1(char s[12], char s 1[12]) { FILE * ; struct TRegistro r; f os_t Byte; = fo en(s1, "rb"); fread(&r , sizeof(r), 1, ); while (!feof( )) if (strcm (s, r.Mat) == 0) { fget os( , &By te); return(Byte); } else fread(&r, sizeof(r), 1, ); return (-1); } O tamos el a rimeira verso elo fato de que existem linguagens que no ossuem instrues do ti o return() e, nestas linguagens, teramos de escrever a funo como na verso inicial. Va le observar que as funes ConsultaRegistro() acima utilizam a esquisa sequencial. Se os registros dos arquivos estiverem ordenados elo cam o Mat oderamos ter uti lizado a esquisa binria, que, como estudado no ca tulo 7, bem mais eficiente. Alterando o contedo de um registro s vezes, h necessidade de que os dados de um registro sejam alterados. No arquivo que estamos

utilizando como exem lo isto oderia ocorrer no caso de uma romoo de um funcionrio que im licasse um aumento no seu salrio bruto ou no caso de uma funcionria que al terou o seu nome em funo de um casamento. Uma funo ara alterar os dados de um regis tro deve, inicialmente, abrir o arquivo ara leitura e gravao, o que feito atravs d a funo fo en() no modo "rb+". Feito isto, a funo deve receber o valor da chave do re gistro e com este valor chamar a funo ConsultaRegistro() definida acima ara obter a osio do registro retendido. Tendo esta osio, deve osicionar o onteiro de lei tura e gravao naquele registro e realizar as alteraes que so desejadas. Para osicion ar o onteiro de leitura e gravao num determinado registro utiliza-se a funo fset os () cujo rotti o int fset os(FILE * , f os_t * os);. Numa ativao desta funo, o arm o recebe o onteiro associado ao arquivo e os recebe a osio do registro, obtid o ela funo fget os() ou ela funo ftell(). No exem lo que estamos discutindo, odem os alterar o cam o Nome de um registro de cam o Mat dado utilizando a seguinte f uno. /*Funo que altera o nome de um registro, dada a matrcula */ void AlteraRegistro( char s[4], char s1[12]) { char c; struct TRegistro r; f os_t Byte; int Tam; FILE * ; Tam = sizeof(r); Byte = ConsultaRegistro(s, s1); if (Byte != -1) { Byte = B yte Tam; = fo en(s1, "rb+"); fset os( , &Byte); fread(&r, Tam, 1, ); rintf(" Nome atual: %s \n Altera (S/N)? ", r.Nome); fflush(stdin); scanf("%c", &c); if ( tou er(c) == 'S') { rintf("\Digite o novo nome: \n"); gets(r.Nome); fset os( , &Byte); fwrite(&r, Tam, 1, ); } } else rintf("\n Registro nao encontrado \n") ; fclose( ); } Observe que, ao contrrio das funes anteriores, o tamos or armazenar o valor de sizeof(r) na varivel Tam, ara evitar vrias chamadas dessa funo. Observe tambm que o comando Byte = Byte Tam osiciona o onteiro no incio do registro que se retende alterar. Outra funo que osiciona o onteiro de leitura e gravao num re gistro de osio conhecida a funo fseek() que tem o seguinte rotti o: int fseek(FILE * , long os, int orig) A, receber o fluxo associado ao arquivo e os indicar a n ova osio do onteiro, a artir da osio dada elo valor assado ara orig. O sistem a ossui trs constantes r-definidas, SEEK_SET, SEEK_CUR e SEEK_END que odem ser assados ara o armetro orig. A rimeira toma como origem o

registro zero do arquivo; a segunda, o registro a ontado elo onteiro de leitur a e gravao (registro corrente); a terceira, o final do arquivo. No caso da osio do registro ser obtida or fget os() ou or ftell(), o valor que deve ser assado ara orig SEEK_SET. Desta forma, ara se escrever a funo AlteraRegistro() escrita a cima utilizando-se a funo fseek() basta substituir os comandos fset os( , &Byte) elo comando fseek( , Byte, SEEK_SET). A constante SEEK_END, a funo fseek() e a funo ftell() ermitem determinar o tamanho, em bytes, de um arquivo. Basta osicionar o onteiro de leitura e gravao no final do arquivo atravs de fseek( , 0, SEEK_END) e obter a osio do onteiro atravs de ftell( ). int TamanhoArquivo(char *s) { FILE * ; int Tamanho; = fo en(s, "rt"); fseek( , 0, SEEK_END); Tamanho = ftell( ); fclose( ); return(Tamanho); } Com esta funo ossvel se determinar o nmero de regist ros de um arquivo. Basta dividir o tamanho do arquivo elo tamanho de cada regis tro: int NumRegistros(char *s) { FILE * ; struct TRegistro r; = fo en(s, "rt") ; return(TamanhoArquivo(s)/sizeof(r)); fclose( ); } Vale observar que, da mesma forma que a chamada de fseek( , 0, SEEK_END) osiciona o onteiro de leitura e g ravao no final do arquivo, fseek( , 0, SEEK_SET) osiciona o tal onteiro no incio do arquivo (existe outra forma de a ontar o onteiro de leitura e gravao ara o inc io do arquivo: rewind( )). Incluindo novos registros num arquivo A incluso de novos registros em um arquivo feita de forma bastante sim les, ois a funo fo en() ativada no modo "ab+" abre um arquivo e ermite que novos registros sejam nele gravados. Naturalmente, a incluso de um novo registro deve ser reced ida da verificao de que o tal registro j est armazenado no arquivo, o que im ediria uma nova incluso. Temos a seguinte sugesto ara atingir o objetivo aqui ro osto: /* Funo que inclui um novo registro num arquivo */ void IncluiRegistro(struct TReg istro r, char s[12]) { char c; long Byte; int Tam; FILE * ; Tam = sizeof(r); Byt e = ConsultaRegistro(r.Mat, s); if (Byte == -1) { = fo en(s, "ab+"); fwrite(&r , Tam, 1, );

Excluindo um registro de um arquivo Outra o erao muito utilizada em arquivos a excluso de um registro. No nosso exem lo , esta o erao seria necessria, or exem lo, na ocasio de um edido de demisso de um f uncionrio. Uma ossvel soluo , a s localizar o registro, gravar todos os outros regis ros num arquivo auxiliar, Tem , excluir do disco o arquivo original e renomear o arquivo Tem com o nome do arquivo original. A maioria dos com iladores C exclu em um arquivo atravs da funo remove() que ossui um armetro do ti o vetor de caract eres ara receber o nome do arquivo a ser removido. Para renomear um arquivo, os com iladores C ossuem a funo rename() que ossui dois armetros do ti o vetor de caracteres, devendo o rimeiro receber o nome atual do arquivo e o segundo receb er o novo nome que se retende. Dentro do exem lo que estamos estudando, a funo ab aixo recebendo o valor do cam o r.Mat e o nome do arquivo, exclui, se a matrcula dada for uma matrcula cadastrada, o registro corres ondente. /*Funo que exclui um r egistro de matrcula dada */ void ExcluiRegistro(char s[4], char s1[12]) { struct TRegistro r; char c; long Byte; int Tam, Reg; FILE * , *t; Tam = sizeof(r); Byte = ConsultaRegistro(s, s1); if (Byte != -1) { = fo en(s1, "rb"); Byte = Byte T am; fset os( , &Byte); fread(&r, Tam, 1, ); rintf("Matricula: %s \b Nome: %s \ n", r.Mat, r.Nome); rintf("Exclui este registro (S/N)? "); fflush(stdin); scanf ("%c", &c); if (tou er(c) == 'S') { t = fo en("Tem ", "wb"); rewind( ); /*Prime iro registro do arquivo*/ Reg = 0; fread(&r, Tam, 1, ); while (!feof( )) { if ( Reg != Byte) fwrite(&r, Tam, 1, t); Reg = Reg + Tam; fread(&r, Tam, 1, ); } fcl ose( ); fclose(t);

} else

rintf("\n Registro ja cadastrado \n"); fclose( ); }

remove(s1); rename("Tem ", s1); } } else rintf("\n Registro nao encontrado \n") ; } 9.5 Arquivo texto Outra forma de arquivo que os com iladores C mani ulam so os chamados arquivos te xtos. Nestes arquivos, tambm criados atravs da funo fo en(), agora no modo "wt", cad eias de caracteres odem ser armazenadas byte a byte, atravs do cdigo ASCII de cad a caractere. A gravao de texto em um arquivo texto ode ser feita atravs da funo f ri ntf() que, alm dos armetros da funo rintf(), exige um rimeiro armetro do ti o flu xo que indicar o arquivo onde o texto ser gravado. Por exem lo, o rograma abaixo cria um arquivo Teste.txt e grava nele a frase Isto um teste. #include <stdio.h> main() { FILE *PontArquivo; PontArquivo = fo en("Teste.txt", "wt"); f rintf(Pon tArquivo, "Isto um teste"); fclose(PontArquivo); } A s a execuo deste rograma, qua lquer rocessador de texto que edite textos em ASCII (inclusive o Bloco de Notas do Windows) ode abrir o arquivo Teste.txt, sendo o seu contedo absolutamente le gvel. Na verdade, ossvel gravar contedos de variveis e resultados de rocessamentos em arquivos utilizando-se a funo f rintf(). Nestes casos, so utilizados os cdigos d e es ecificao de formato da funo rintf(). Por exem lo, ara se armazenar no arquivo Teste.txt uma tabela de razes quadradas dos cem rimeiros inteiros ositivos bas ta se executar o seguinte rograma: #include <stdio.h> #include <math.h> main() { int i; float r; FILE *PontArquivo; PontArquivo = fo en("Teste.txt", "wt"); for (i = 1; i <= 100; i++) { r = sqrt(i); f rintf(PontArquivo, "%d %f \n", i, r); } fclose(PontArquivo); } A funo rintf() , de fato, um caso articular da funo f rintf () cujo rimeiro armetro o fluxo r-definido stdout. O fluxo stdout, que omitido em rintf(), a onta ara um arquivo que faz referncia ao dis ositivo adro de sada, em geral a tela do monitor. Ou seja, rintf() "grava" a sada na tela, enquanto f rintf() grava a sada no arquivo associado ao fluxo assado ara ela. Por exem lo , os comandos rintf("Estou a rendendo a rogramar em C") e f rintf(stdout, "Est ou a rendendo a rogramar em C") executam aes idnticas: exibem na tela a frase Esto u a rendendo a rogramar em C. Um outro fluxo r-definido std rn que a onta ara um arquivo que gerencia a relao entre o

sistema e a im ressora conectada ao com utador. Por exem lo, o rograma #include <stdio.h> main() { int i; for (i = 0; i < 10; i++) f rintf(std rn, "Estou a ren dendo a rogramar em C \n"); } im rime, atravs da im ressora conectada ao com uta dor, dez vezes a frase Estou a rendendo a rogramar em C, uma vez em cada linha. Um terceiro fluxo r-definido stdin que a onta ara um arquivo que administra a relao do sistema com o dis ositivo de entrada adro, em geral o teclado. Isto ex li ca a chamada de fflush(stdin) comentada no ca tulo 5.

Exibindo um arquivo texto A biblioteca da linguagem C dis e de uma funo ca az de "ler" uma linha de um arquiv o texto, armazenando-a num onteiro de caracteres. Trata-se da funo de rotti o cha r *fgets(char *s, int n, FILE * ); que l uma quantidade x de caracteres do arquiv o associado a e os armazena em s, como uma string. A quantidade de caracteres x inferior ou igual a n, sendo inferior quando uma marca de fim de linha atingid a, ou seja, quando o caractere indicado or \n encontrado. Quando o fim de arqui vo alcanado, a funo retorna NULL. Com fgets() ossvel exibir o contedo de um arqui texto com a seguinte funo: #include <stdio.h> void ExibeArquivoTexto(char *s) { FI LE * ; char *Linha, *Fim; = fo en(s, "rt"); Fim = fgets(Linha, 80, ); while ( Fim != NULL) { rintf("%s", Linha); Fim = fgets(Linha, 80, ); } } Se este arqui vo adicionado da funo main() { char *NomeArq; uts("Digite o nome do arquivo"); sc anf("%s", NomeArq); ExibeArquivoTexto(NomeArq); } for gravado com o nome ExibTex t.c, sua execuo ara a entrada exibtext.c exibe o seu r rio contedo. Utilizando um arquivo texto como entrada de dados

ossvel utilizar um arquivo texto ara obter a entrada de um rograma. Imaginemos que o arquivo texto card.txt contivesse o card io da lanchonete referida num exe m lo do ca tulo 4. Ou seja, su onhamos que o contedo do arquivo card.txt fosse o s eguinte: 101 Refrigerante 1.20 102 Suco 1.00 103 Sanduche 2.50 104 Salgado 1.00 1 05 Torta 2.00 O rograma abaixo l este arquivo e armazena num vetor de estruturas ermitindo o gerenciamento dos edidos dos clientes. #include <math.h> #include <conio.h> #include <stdio.h> #include <string.h> ty edef struct { int Cod; char Prod[30]; float Preco; }TItem; ty edef struct { int Cod; int Quant; }TPedido; T Item Carda io[100]; TPedido Pedido[100]; /*Funo ara se arar os com onentes do card i o*/ void ProcessaItem(char *s, int &Codigo, char *Produto, float &Pr) { char a[1 0]; int c = strlen(s); Codigo = atoi(s); strnc y(Produto, s + 4, c-9); strnc y(a , s + c - 5, 4); Pr = atof(a); } /*Funcao ara ler o card io do arquivo texto*/ i nt LerCarda io(char *s) { FILE * ; int i = 0; char *Item, *FimDeLinha; = fo en (s, "rt"); FimDeLinha = fgets(Item, 80, ); while (FimDeLinha != NULL) { Process aItem(Item, Carda io[i].Cod, Carda io[i].Prod, Carda io[i].Preco); i++; FimDeLin ha = fgets(Item, 80, ); } return i; }

/*Funo ara exibir o card io*/ void ExibeCarda io(TItem v[100], int t) { int i; ri ntf("COD ESPECIFICACAO PRECO\n"); for (i = 0; i < t; i++) rintf("%d %-20s %.2f\ n", v[i].Cod, v[i].Prod, v[i].Preco); } /* Funcao ara exibir edido*/ void Exib ePedidos(int n) { int i, Ind; rintf("COD ESPECIFICACAO QUANT PRECO\n"); for(i=0 ; i<n; i++) { Ind = Pedido[i].Cod - 101; rintf("%3d %-30s %5d R$ %.2f\n",Pedido [i].Cod, Carda io[Ind].Prod, Pedido[i].Quant, Carda io[Ind].Preco*Pedido[i].Quan t); } } void main() { int i, NumItens; float Total; clrscr(); NumItens = LerCard a io("card.txt"); ExibeCarda io(Carda io, NumItens); Total = 0; i = 0; uts("Dig ite o codigo do roduto desejado (0 ara encerrar):"); scanf("%d",&Pedido[i].Cod ); while(Pedido[i].Cod != 0) { if( (Pedido[i].Cod > 100) &&(Pedido[i].Cod < 106) ) { uts("Digite a quantidade:"); scanf("%d",&Pedido[i].Quant); Total = Total + Pedido[i].Quant * Carda io[Pedido[i].Cod - 101].Preco; i++; } else { uts("Erro ! O cdigo informado no est cadastrado!"); uts(Digite uma tecla ara continuar); getc h(); } uts("Digite o codigo do roduto desejado (0 ara encerrar):"); scanf("%d ",&Pedido[i].Cod); } uts("\nTotal dos edidos:"); ExibePedidos(i); rintf("\nVa lor total dos edidos: R$ %.2f", Total); getch(); }

9.6 Exerccios ro ostos 1. Escreva uma funo main() que, atravs de um menu de o es, utilize as funes estudada este ca tulo e que, ortanto, seja ca az de a) criar e gravar dados num arquivo d e registros; b) exibir o contedo de um arquivo; c) alterar dados de um registro d e um arquivo; d) incluir novos registros em um arquivo; e) excluir um registro d e um arquivo. 2. Escreva uma funo que rena dois arquivos de registros de mesma estr utura em um terceiro arquivo. 3. Escreva um rograma que, dado um arquivo cujos registros ossuem os cam os Nome (do ti o vetor de strings) e Salario (do ti o f loat), gere um arquivo dos registros cujo cam o Salario maior que 5.000,00. 4. E screva uma funo que inclua um registro dado num arquivo de registros ordenado or um cam o Mat de modo que o arquivo se mantenha ordenado, sem utilizar um arquivo auxiliar. 5. Escreva um rograma que, dados dois arquivos ordenados or um cam o Mat, gere um terceiro arquivo tambm ordenado. 6. Escreva um rograma que dados dois arquivos cujos registros tm os cam os char C f[12] e char Nome[40] gere um a rquivo contendo os registros que ertencem aos dois arquivos. 7. Escreva uma funo que troque as osies de dois registros de um arquivo. 8. Escreva uma funo que ordene um arquivo, cujos registros tm os cam os char C f[12] e char Nome[40], em relao ao cam o C f. 9. Escreva uma funo que exclua os comentrios de um rograma da linguage m C. 10. Para uma esquisa relativa aos hbitos de estudo dos alunos do Curso de C incia da Com utao da Universidade Federal de Alagoas, foi idealizado um sistema bas eado numa estrutura TDados, com os cam os char Nome[40]; char Sexo; int NumHoras ;, onde Nome e Sexo tm finalidades bvias (Sexo recebe F ou M) e NumHoras recebe o nmero de horas dirias de estudo do esquisado. x) Escreva uma funo que armazene os d ados coletados (quantidade de alunos esquisados no conhecido a riori) num vetor de estruturas. y) Escreva uma funo que retorne os nomes dos/as alunos/as que dedi cam mais horas dirias ao estudo. 11. Imagine que o arquivo texto Notas.txt contm a s notas finais dos alunos da disci lina Programao 1do Curso de Cincia da Com utao da UFAL como abaixo Gisele Bachen 9.9 Juliana Raes 9.8 Ana Paula Ardsia 9.0 Rodrigo Sentouro 5.5 ... no qual a coluna dos nomes est alinhada esquerda, as notas tm sem re uma casa decimal, odendo ter ocorrido nota 10.0, e no h es aos em branco a s ca da nota. Escreva uma funo que receba o nome do arquivo e retorne as mdias das notas . Observao Pro ostas de solues dos exerccios ro ostos odem ser solicitadas atravs d mensagem eletrnica ara jaime@ccen.ufal.br com assunto RESPOSTAS LIVRO C, anexan do o formulrio abaixo devidamente reenchido. Nome 1 2 Categoria1 Instituio2 Curso2 Cidade/Estado Categoria: docente, estudante, autodidata Se docente ou estudante

10 Noes bsicas de alocao dinmica de memria 10.1 O que alocao dinmica At agora, os rogramas utilizavam a memria do com utador estaticamente: todas as osies de memria eram reservadas ara as variveis no incio da execuo do rograma ou d uno e, mesmo que no estivessem sendo mais utilizadas, continuavam reservadas ara a s mesmas variveis at a concluso da execuo do rograma ou da funo. Um vetor global do o float com dez mil com onentes, or exem lo, ocu ar quarenta mil bytes de memria d urante toda a execuo do rograma. Naturalmente, isto ode, em grandes rogramas, s obrecarregar ou, at mesmo, esgotar a memria dis onvel. No rimeiro caso, h uma degra dao na eficincia do rograma; no segundo caso a execuo do rograma ode ser inviabili zada. Os com iladores C ermitem a alocao dinmica da memria de tal modo que osies de memria sejam reservadas ara variveis no instante em que sejam necessrias e sejam l iberadas (as osies de memria) ara o sistema nos instantes em que no estejam sendo utilizadas. A alocao dinmica de memria ode ser feita atravs das funes malloc(), cal () e realloc() cujos rotti os se encontram no arquivo alloc.h e so os seguintes v oid *malloc(size_t Tam); void *calloc(size_t NumItens, size_t Tam); void *reallo c(void *Bloco, size_t Tam); A, size_t um ti o de dado r-definido, definido tambm n o arquivo alloc.h, Tam o nmero de bytes que se retende alocar dinamicamente, Num Itens a quantidade de itens de Tam bytes que se retende alocar e Bloco um onte iro que contm o endereo da varivel cuja memria se retende ex andir em Tam bytes. A funo malloc() retorna um onteiro ara um bloco de Tam bytes at ento dis onvel, a fun calloc() retorna um onteiro ara um es ao de memria at ento dis onvel ca az de armaz enar NumItens objetos, cada um deles com Tam bytes e a funo realloc() retorna um onteiro ara um bloco de memria com quantidade de bytes igual soma algbrica da qua ntidade de bytes a ontada or Bloco e Tam, odendo Tam ser negativo. Caso a quan tidade de bytes retendida no esteja dis onvel, as funes acima retornam NULL. Como o s onteiros retornados so ambos do ti o void, eles devem ser moldados ara odere m receber endereos de qualquer ti o de varivel. Por exem lo, o rograma #include < stdio.h> #include <alloc.h> main() { int *v, t; v = (int *)malloc(80); if (v == NULL) rintf("Memoria nao dis onivel"); else { for (t = 0; t <= 40; t = t + 1) v [t] = t*t; for (t = 0; t <= 40; t = t + 1) rintf("%d ", v[t]); free(v); } } arm azena os quadrados dos quarenta rimeiros nmeros inteiros num vetor criado dinami camente. A funo free() libera ara o sistema a quantidade de memria alocada ara o seu argumento or uma das funes malloc(), calloc() ou realloc(). Naturalmente, o l eitor ode estar ensando que o rograma acima no teria muita vantagem em

relao ao rograma abaixo, onde o vetor v criado estaticamente, #include <stdio.h> main() { int v[40], t; for (t = 0; v <= 40; t = t + 1) v[t] = t * t; for (t = 0; v <= 40; t = t + 1) rintf("%d ", v[t]) } De fato, os dois rogramas durante su as execues utilizam oitenta bytes de memria. Haver diferena se estes rogramas fizere m arte de um rograma maior. Neste caso, o rimeiro utiliza oitenta bytes a ena s at a execuo do comando free(), enquanto que o segundo utiliza os oitenta bytes du rante toda execuo do rograma. Naturalmente, tambm, o leitor ode estar se ergunta ndo qual a vantagem do rimeiro dos rogramas acima em relao ao rograma #include <stdio.h> main() { int *v, t; for (t = 0; v <= 40; t = t + 1) v[t] = t * t; for (t = 0; v <= 40; t = t + 1) rintf("%d ", v[t]) } no qual o "tamanho" de v no foi fixado e ortanto no h "des erdcio" de memria. O que ocorre que no rimeiro se no h uver memria dis onvel, o vetor v no "criado", cabendo ao rogramador ajustar o rog rama ara esta hi tese.

10.2 Armazenando dinamicamente um olinmio A funo realloc() aumenta a eficincia de utilizao de memria elo fato de que a quantid de de memria alocada ara um vetor ode crescer medida da necessidade. Para exem lificar, imagine a funo abaixo que "l um olinmio" (x). Como se sabe, um olinmio ( x) = a 0xn + a1xn-1 + ... + an-1x + an identificado elo seu grau e elos valore s de seus coeficientes. Se se retende que o grau no seja dado de entrada, a ques to a mesma que ocorre quando se trabalha com uma relao de nmeros: no se sabe a quant dade deles e, ortanto, no se ode recisar o tamanho do vetor necessrio. Uma soluo utilizar a funo malloc() ara inicializar um onteiro e, medida que os coeficiente s so digitados, utilizar a funo realloc() ara ex andir a memria necessria. #include <stdio.h> #include <alloc.h> #include <string.h> #include <stdlib.h> int LePolin omio(int * ) { char *Coef; int i; rintf("Digite os coeficientes ('fim' ara enc errar)\n"); i = 1; do { = (int *)realloc( , 2*i);

gets(Coef); if (strcm (Coef, "fim") != 0) { [i - 1] = atof(Coef); i = i + 1; } } while (strcm (Coef, "fim") != 0); free( ); return (i - 1); } A "inicializao de " deve ocorrer antes da chamada da funo. Por exem lo, na funo main() atravs do ontei ro declarado nesta funo e que ser assado ara a funo LePolinomio(). main() { int *Po li; int Grau; Poli = (int *)malloc(2); Grau = LePolinomio(Poli); ... } Observe q ue o tamos or dar entrada nos coeficientes como strings. Esta o o foi feita ara que udssemos usar "fim" como flag, j que a utilizao de qualquer nmero com esta final idade fica com licada j que qualquer nmero ode ser um coeficiente de um olinmio. 10.3 Listas Para mais um exem lo de alocao dinmica, a resentaremos um ti o de dado chamado list a sim lesmente encadeada. Este ti o de dado ode ser definido como uma sequncia d e elementos ligados atravs de onteiros com um nmero mximo de elementos no fixado a riori. Usualmente, cada elemento da lista uma estrutura, com um cam o contendo um onteiro e os demais cam os contendo os dados que o rograma vai mani ular. A ssocia-se um onteiro ao rimeiro elemento e o cam o do ti o onteiro do ltimo el emento da lista tem valor NULL. O onteiro que a onta ara o rimeiro elemento d a lista indica o seu incio e o valor do onteiro da ltima estrutura da lista ser N ULL indicar o seu final. Para as funes que vamos a resentar (criao de uma lista de in teiros, exibio e remoo de um elemento desta lista) necessitamos definir a seguinte e strutura: struct TElemento { int Valor; struct TElemento * ; }; Observe que na d efinio de uma estrutura ossvel se definir um cam o de ti o idntico ao da estrutura. Este cam o definir um onteiro que a onta ara o elemento seguinte da lista e o cam o Valor armazenar o inteiro. Necessitamos tambm de duas variveis globais: struc t TElemento *Inicio, *Prox; a varivel Inicio ara a ontar ara o inicio da lista e Prox ara a ontar ara o rximo elemento. necessrio observar que o onteiro Inic io a onta ara o ltimo elemento que foi inserido na lista, enquanto que o cam o * do rimeiro elemento da lista igual a NULL. Para criar a lista fazemos Inicio receber NULL e, dentro de uma estrutura de re etio, alocamos memria ara o onteiro Prox, damos entrada em Prox.Valor e fazemos o cam o de Prox receber Inicio e

Inicio receber Prox ara que este onteiro a onte sem re ara o ltimo elemento a dar entrada. Temos a seguinte funo: void CriaLista() { Inicio = NULL; rintf("Digi te os numeros (-1 ara encerrar)\n"); do { Prox = (struct TElemento *)malloc(5); scanf("%d",&(*Prox).Valor); if ((*Prox).Valor != -1) { (*Prox). = Inicio; Inic io = Prox; } } while ((*Prox).Valor != -1); } Para exibir a lista (ou realizar n ela qualquer rocessamento), basta ercorr-la desde seu incio (Prox = Inicio) at o seu final ((*Prox). = NULL). void ExibeLista() { Prox = Inicio; while (Prox != NULL) { rintf("%d ", (*Prox).Valor); Prox = (*Prox). ; } rintf("\n"); } Para d eletar um elemento da lista necessrio que, quando ele for localizado, se armazene o onteiro do elemento anterior a ele e o onteiro que a onta ara ele. Se o el emento a ser deletado for o rimeiro, basta fazer Inicio a ontar ara o segundo elemento; se o elemento a ser excludo for outro elemento, basta fazer o onteiro do elemento anterior ara o elemento seguinte e devolver ao sistema a osio de memr ia ocu ada elo elemento a ser excludo. void Deleta(int n) { struct TElemento *An t; Prox = Inicio; Ant = Inicio; while ((Prox != NULL) && ((*Prox).Valor != n)) { Ant = Prox; Prox = (*Prox). ; } if (Prox != NULL) { if ((Ant == Inicio) && (Pro x == Inicio)) Inicio = (*Prox). ; else (*Ant). = (*Prox). ; free(Prox); } else rintf("Elemento nao esta lista \n");

10.4 Exerccios ro ostos 1. Escreva uma funo que calcule a mdia de uma relao de nmeros armazenada numa lista c iada ela funo CriaLista() acima. 2. Escreva uma funo que insira um elemento numa li sta ordenada de modo que a lista ermanea ordenada. Observao Pro ostas de solues dos exerccios ro ostos odem ser solicitadas atravs de ensagem eletrnica ara jaime@ccen.ufal.br com assunto RESPOSTAS LIVRO C, anexando o formulrio abaixo devidamente reenchido. Nome 1 2 Categoria1 Instituio2 Curso2 Cidade/Estado Categoria: docente, estudante, autodidata Se docente ou estudante

Bibliografia Dijkstra, E. W., A Disci line of Programiming. Prentice-Hall. New Jersey, 1975. Almeida, Eliana S. de et al.. AMBAP: Um Ambiente de A oio ao A rendizado de Prog ramao. Anais do Congresso da Sociedade Brasileira de Com utao, 2002, Florian olis. Ev aristo, J. e Cres o, S, A rendendo a Programar Programando numa Linguagem Algortm ica Executvel (ILA). Book Ex ress, Rio de Janeiro, 2000. Evaristo, J., A rendendo a Programar Programando em Linguagem C. Book Ex ress, Rio de Janeiro, 2001. Eva risto, J., Perdigo, E., Introduo `a lgebra Abstrata. Editora da Universidade Federal de Alagoas (EDUFAL). Alagoas, 2002. Evaristo, J., Programando com Pascal. Segun da Edio, Book Ex ress, Rio de Janeiro, 2004. Knuth, D. E., The Art of Com uter Pro gramming, volume 2, Seminumerical Algorithms AddisonWesley Publishing Com any. U SA, 1988. Kowaltowski, T. & Lucchesi, C., Conceitos Fundamentais e Teoria da Com utao. Anais do II WEI. Minas Gerais, 1994 Norton, P., Introduo Informtica. Makron B oks. S Paulo, 1996. Rangel, J. L., Os Programas de Graduao em Linguagens de Progra mao. Anais do IIWEI. Minas Gerais, 1994. Szwarcfiter, J. L. & Markenzon, Estrutura s de Dados e seus Algoritmos. LTC Editora. Rio de Janeiro, 1994. Wirth, N., Algo rithms & Data Structures. Prentice-Hall. New-Jersey, 1986.

ndice remissivo A Algoritmo de Euclides..................................... 61 Alocao dinmica da m emria....................132 Am litude........................................... ............. 96 A ontadores.................................................... . 72 Argumentos......................................................65 Arquivo binrio..............................................117 Arquivo de registros..... ..................................117 Ativao de uma funo............................ ...... 65 B Binary digit........................................................ 4 Bit.......................................................................4 B ubbleSort..................................................... 102 Busca........ ........................................................99 Byte................. ................................................... 5 C Cadeia de caracteres.... ...................................104 Cam os................................... ....................... 113 Caractere nulo...................................... .......... 104 Central rocessing unit...................................... 4 C har..................................................................18 Chave... .......................................................... 117 Cdigo ASCII....... ............................................. 5 Cdigos de converso................ ...................... 23 Cdigos es eciais....................................... ......27 Comando de atribuio.................................... 28 Comando de sel eo........................................ 36 Comando do while.................... ....................... 56 Comando for.......................................... .......... 50 Comando if...................................................... 3 6 Comando if else............................................... 37 Comando swit ch.............................................. 44 Comando while............... ................................. 53 Comentrios.................................. ................... 41 Com iladores............................................. ...... 13 Com onentes de um vetor............................... 84 Condio de esca e..........................................76 Constante........................ ................................. 18 Consulta................................... ........................ 99 D Decom osio em fatores rimos..............64, 97 Des vio mdio................................................... 87 Desvio adro....... ........................................... 96 Diagonal rinci al............... .............................93 Dgito verificador................................ ...........110 Divisor r rio.................................................52 Double..............................................................18 E Endentao. ......................................................38 Endereo de uma varivel... .............................72 Estrutura....................................... ..................113 Estrutura de deciso........................................ . 36 Estrutura de seleo......................................... 36 Ex resso de rec orrncia................................. 76 Ex resses lgicas....................... .................... 20 F Fatorial.............................................. ............... 75 FILE......................................................... ...... 117 Float................................................................ . 18 Fluxo.............................................................. 118 Funo atof.................................................... 107 Funo atoi............ .........................................107 Funo atol............................ .........................107 Funo calloc.......................................... ....... 132 Funo fclose................................................. 119 Funo fe of.................................................... 120 Funo fget os........... .................................... 121 Funo fo en............................... ...................117 Funo fread................................................. . 119 Funo free.................................................... 133 Funo fseek.. ................................................ 123 Funo fset os................. .............................. 122 Funo ftell..................................... ............... 121 Funo fwrite................................................. 1 18 Funo main.....................................................67 Funo malloc..... ...........................................132 Funo rintf........................ ............................23 Funo realloc....................................... .........132 Funo scanf.................................................... 22 Funo

strcat.................................................. 106 Funo strcm .......... ......................................106 Funo strc y............................. .................... 106 Funo strlen.............................................. ....105 Funo strlwr................................................. 106 Funo strnc y............................................... 106 Funo strstr.................. .................................107 Funo stru r.................................. ............... 106

G Gets................................................................ 105 H Har dware..........................................................15 I Identificado r.....................................................17 InsertSor.............. ...........................................103 Int.............................. ....................................... 18 Inter retadores...................... ........................... 13 L Laos............................................ .................... 50 Linguagem de alto nvel.................................. 13 Linguagem de mquina......................................4 Long............... .................................................. 18 M Matriz identidade de ord em n.......................... 93 Matriz quadrada............................... ................ 93 Mximo divisor comum...................................61 Memb ros........................................................ 113 Memria........... ..................................................4 Mnimo mlti lo comum........... ...................... 62 Modularizao de um rograma...................... 67 Mdulo .............................................................19 Multi licidade.. ................................................ 64 N Norma de um vetor......... ................................. 96 Notao cientfica............................... ............. 19 NULL........................................................... ....73 Nmero rimo..................................................54 O O erador condicional ternrio......................... 38 O erador de endereo.............. .................. 22, 72 O eradores lgicos...................................... .... 20 O eradores relacionais.....................................20 P Parmetros ....................................................... 65 Passagem de armetro or valor.................... 68 Pesquisa........................................ ................... 99 Pesquisa binria........................................... .. 100 Pesquisa sequencial..........................................99 Pilha de memria............................................. 76 Ponteiro de arqui vo........................................ 117 Ponteiros........................ .................................. 72 Produto escalar........................... ......................96 Programa fonte......................................... ........13 Programa objeto............................................... 13 Pro tti o de uma funo.................................. 65 R Recursividade............. ......................................75 Registro............................... ........................... 117 Resoluo de roblemas.............................. ...... 6 Return...............................................................65 Rewind........................................................... 124 S SEEK_CU R................................................... 123 SEEK_END............... .................................... 123 SEEK_SET............................... ..................... 123 SelectSort............................................ ........... 101 Semnticade um comando............................... 14 Sequncia d e Fibbonaci................................... 64 Srie harmnica................... ............................ 64 Sintaxe de um comando........................... ........ 14 Sistema binrio de numerao........................... 5 Sistema o eracio nal......................................... 14 Sizeof.......................... ..................................... 84 Software............................... ............................ 15 Soluo iterativa................................... ........... 77 Static........................................................... ..... 80 Stdou.............................................................. 126 Std rn.............................................................127 String.. ............................................................104 T Ti o de dado.. .................................................. 17 Torre de Hani.............. ................................... 78 Trao...................................... .......................... 93 Ty edef........................................... ............... 114 U Unidade de entrada........................................ .... 4 Unidade de rocessamento centra......................4 Unidade de sada.... ............................................ 4 V Variveis automticas.............. ........................ 80 Variveis dinmicas..................................... .... 80 Variveis estticas............................................80

Variveis locais..........................................65, 80 Variveis sim les.. ........................................... 17 Varivel global.................... .............................80 Vetores............................................................. 84 Void.... ............................................................. 67

Potrebbero piacerti anche