Escolar Documentos
Profissional Documentos
Cultura Documentos
Progiv2 PDF
Progiv2 PDF
2011
S UMRIO
1.1
Pr-histria . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . .
1.2
Sculo XX . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . .
1.2.1
Computadores Eletromecnicos . . . . . . . . . . . . . . . . . . . . . . . .
1.2.2
Computadores Eletrnicos . . . . . . . . . . . . . . . . . . . . . . . . . . .
2 Introduo computao
21
2.1
Contextualizao . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . .
21
2.2
22
2.3
Algoritmos e programas . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . .
24
2.3.1
26
2.3.2
27
2.3.3
Algoritmos e computadores . . . . . . . . . . . . . . . . . . . . . . . . . . .
28
3 Dicas iniciais
31
3.1
31
3.2
Compilador . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . .
36
3.3
Emacs . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . .
37
4 Primeiros programas
41
4.1
Digitando . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . .
41
4.2
Compilando e executando . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . .
41
4.3
42
4.4
Prximo programa . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . .
43
4.5
Documentao . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . .
44
4.6
Entrada e sada . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . .
45
5 Estruturas condicionais
49
i
5.1
49
5.2
50
5.2.1
51
52
5.3.1
56
5.3
59
6.1
Motivao . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . .
59
6.2
60
63
7.1
Expresses aritmticas . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . .
63
7.2
Expresses relacionais . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . .
64
7.3
Expresses lgicas . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . .
65
73
8.1
73
8.2
75
79
9.1
79
9.2
Expresses aritmticas . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . .
81
10 Caracteres
89
89
91
93
95
95
12 Vetores
113
. . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 116
125
133
143
151
163
181
iii
187
193
199
209
23 Depurao de programas
229
249
AULA
B REVE
HISTRIA DA COMPUTAO
Nesta aula abordaremos uma pequena histria da computao. Sabemos, no entanto, que
esta na verdade uma tentativa e que fatos histricos relevantes podem ter sido excludos involuntariamente. Continuaremos a trabalhar no sentido de produzir um texto cada vez mais
amplo e completo, buscando informaes em outras fontes que, por descuido ou desconhecimento, infelizmente ainda no foram consultadas.
Este texto baseado principalmente nas pginas da Rede Mundial de Computadores [1, 2,
3, 4, 5] e nos livros de Philippe Breton [6] e Russel Shackelford [7].
1.1 Pr-histria
Desde muito tempo, possvel notar que o ser humano vem realizando clculos complexos
para solucionar seus mais diversos problemas. Um dos primeiros e mais notveis exemplos que
temos registro a descoberta do nmero real que representa a relao entre o comprimento da
circunferncia de um crculo e o comprimento de seu raio. A mais antiga evidncia do uso
consciente de uma aproximao precisa para esse nmero, com valor 3 + 17 , foi descoberta nos
projetos das pirmides da poca do Reino Antigo no Egito, datando assim do ano de 2630 a.C. a
2468 a.C. As mais antigas evidncias textuais do clculo de aproximaes desse nmero datam
de 1900 a.C., realizadas pelos gemetras egpcios, babilnios, hindus e gregos. A letra grega
at hoje usada como a representao desse nmero.
Alm disso, a histria do pensamento humano marcada, desde o princpio, pelos registros
de tentativas de sistematizao e estruturao do mesmo. A lgica1 uma cincia filosficomatemtica descrita geralmente por um conjunto de regras que procura sistematizar o pensamento. A lgica enxerga o pensamento como a manifestao do conhecimento, que por sua vez
visto como a busca da verdade, e, para que essa meta seja atingida, estabelece regras a serem
seguidas, chamadas de regras do pensar corretamente. Apesar de muitos povos antigos terem usado sofisticados sistemas de raciocnio, somente na China, ndia e Grcia os mtodos de
raciocnio tiveram um desenvolvimento sustentvel e possvel que a lgica tenha emergido
nesses trs pases por volta do sculo IV a.C. A lgica moderna descende da lgica clssica,
tambm conhecida como lgica aristotlica, desenvolvida por Aristteles2. A lgica moderna
baseada na lgica clssica e usada extensivamente em diversas reas do conhecimento, em
especial na Cincia da Computao. At os dias de hoje, programas e computadores so projetados com base nessa estruturao do pensamento chamada lgica.
1
Do grego clssico o, ou logos, que significa palavra, pensamento, idia, argumento, relato, razo lgica ou
princpio lgico.
2
Aristotles ( a.C. a.C.), nascido na Grcia, filsofo, aluno de Plato, mestre de Alexandre, o Grande.
B REVE
HISTRIA DA COMPUTAO
Do mesmo modo, quando comeou a realizar tarefas mecnicas para sua comodidade e
bem estar, o ser humano predominantemente as mulheres tinha de realizar, hora aps hora,
dia aps dia, todos os clculos repetitivos em tarefas das cincias, do comrcio e da indstria.
Tabelas e mais tabelas eram preenchidas com os resultados desses clculos, para que no fossem sempre refeitos. No entanto, erros nesses clculos eram freqentes devido, em especial, ao
tdio e desconcentrao. Alm disso, esses clculos no eram realizados de forma rpida. Assim, muitos inventores tentaram por centenas de anos construir mquinas que nos ajudassem
a realizar essas tarefas.
O baco3 provavelmente o mais antigo instrumento conhecido de auxlio ao ser humano em clculos matemticos. O baco mais antigo foi descoberto
na Babilnia, hoje conhecida como Iraque, e data do
ano de 300 a.C. Seu valor est baseado especialmente
no fato de auxiliar a memria humana durante as operaes aritmticas mais bsicas. Algum bem treinado
no uso de um baco pode executar adies e subtraes com a mesma velocidade de quem usa uma calculadora eletrnica. No entanto, as duas outras operaes bsicas so realizadas de forma bem mais lenta.
Esse instrumento ainda consideravelmente utilizado
em certos pases do Oriente.
Abacus uma palavra em latim que tem sua origem nas palavras gregas abax ou abakon, que quer dizer tabela e
que, por sua vez, tem sua origem possivelmente na palavra semtica abq, que significa areia (do livro The Universal
History of Numbers de Georges Ifrah, Wiley Press 2000).
4
a al-Khwarizm ( ), nascido na Prsia, matemtico, astrnomo e
Abu Abdalla Muh.ammad ibn Mus
gegrafo.
FACOM
UFMS
1.1 P R - HISTRIA
Ainda sobre os primeiros dispositivos de auxlio nas atividades humanas, o primeiro relgio de bolso foi criado por Peter Henlein5 por volta de 1504. No ano de 1600, William Gilbert6
ficou conhecido por suas investigaes em magnetismo e eletricidade, tendo cunhado o termo
eletricidade a partir da palavra grega elecktra. John Napier7 , em seu trabalho Mirifici Logarithmorum Canonis Descriptio de 1614, inventou o logaritmo, uma ferramenta que permitia
que multiplicaes fossem realizadas via adies e divises via subtraes. A mgica consistia na consulta do logaritmo de cada operando, obtido de uma tabela impressa. A inveno de
John Napier deu origem rgua de clculo, instrumento de preciso construdo inicialmente na
Inglaterra em 1622 por William Oughtred8 e utilizado nos projetos Mercury, Gemini e Apollo
da NASA, que levaram o homem lua.
FACOM
UFMS
B REVE
HISTRIA DA COMPUTAO
Joseph Jacquard17 criou, em 1801, um tear que podia tecer a partir de um padro lido automaticamente de cartes de madeira perfurados e conectados por cordes. Descendentes desses
cartes perfurados so utilizados at hoje em algumas aplicaes. A inveno de Jacquard
incrementou a produtividade de tecidos da poca, mas, em contrapartida, gerou grande desemprego de operrios da indstria txtil.
FACOM
UFMS
1.2 S CULO XX
Em 1890 o governo norte-americano tinha grande urgncia de realizar o censo da populao dos
Estados Unidos e a previso era de que, da maneira como tinha sido realizado o ltimo, o censo
de 1890 levaria cerca de 7 anos e meio at ser finalizado. Um prmio foi ento anunciado para o inventor que ajudasse a automatizar o censo de 1890.
O prmio foi vencido por Herman Hollerith25 , que
props a Mesa de Hollerith26 , uma mquina que
consistia de um leitor de cartes perfurados que
era sensvel a pequenos buracos realizados nesses
cartes, um mecanismo de engrenagens que podia
contar e um grande expositor de indicadores para
mostrar os resultados da computao. Essa mquina foi projetada com sucesso e o censo de 1890
terminou em somente 3 anos. A partir da Hollerith
fundou uma empresa chamada TABULATING M A CHINE C OMPANY . Em 1911 sua empresa se une a
outras duas e se torna a C OMPUTING TABULATING
R ECORDING C ORPORATION CTR. Sob a presidncia de Thomas Watson27 , a empresa foi renomeada
I NTERNATIONAL B USINESS M ACHINES IBM em
1924.
1.2 Sculo XX
A exploso dos computadores ocorreu no sculo XX. At a metade desse sculo, computadores eletromecnicos e os primeiros computadores totalmente eletrnicos foram projetados
com fins militares, para realizar clculos balsticos e decifrar cdigos dos inimigos. Eminentes cientistas, que deram origem a quase tudo do que chamamos de Cincia da Computao,
estiveram envolvidos nesses projetos. A partir da segunda metade do sculo, a exploso dos
computadores eletrnicos se deu, quando o computador pessoal passou a fazer parte de nosso
dia a dia.
26
FACOM
UFMS
B REVE
HISTRIA DA COMPUTAO
Karel Capek
( ), nascido no Imprio Austro-Hngaro, hoje Repblica Tcheca, escritor.
Konrad Zuse ( ), nascido na Alemanha, engenheiro e pioneiro da computao.
30
espantoso observar que aps 45 anos da fabricao do Mark I, um computador podia realizar uma operao
de adio em 1/109 de segundo.
29
FACOM
UFMS
1.2 S CULO XX
Uma das primeiras pessoas a programar o Mark I foi uma mulher, Grace Hopper31, que em
1953 inventou a primeira linguagem de programao de alto nvel chamada Flow-matic, vindo
a se tornar posteriormente a linguagem COBOL. Uma linguagem de programao de alto nvel projetada com o objetivo de ser mais compreensvel ao ser humano, diferentemente da
linguagem binria, de baixo nvel, compreendida pelo computador. No entanto, uma linguagem de alto nvel necessita de um programa chamado compilador que traduz um programa
em linguagem de alto nvel para um programa em linguagem de baixo nvel, de modo que o
Mark I pudesse execut-lo. Portanto, Grace Hopper tambm construiu o primeiro compilador
conhecido.
Grace Murray Hopper ( ), nascida nos Estados Unidos, cientista da computao e oficial da Marinha
dos Estados Unidos.
32
Alan Mathison Turing ( ), nascido na Inglaterra, matemtico, lgico e criptoanalista.
33
Esta afirmao chamada Tese de Church-Turing. Uma linguagem de programao ou um computador abstrato Turing-completo se satisfaz essa tese. Alonzo Church, um influente matemtico e lgico norte-americano,
foi seu orientador de doutorado.
34
David Hilbert ( ), nascido na Alemanha, reconhecido como um dos mais influentes matemticos
dos sculos XIX e XX.
35
Kurt Gdel ( ), nascido no Imprio Austro-Hngaro, lgico, matemtico e filsofo.
FACOM
UFMS
B REVE
HISTRIA DA COMPUTAO
De 1940 a 1960
O ttulo de primeiro computador digital de propsito geral e totalmente eletrnico em
geral dado ao ENIAC (Electronic Numerical Integrator and Calculator). Esse computador foi construdo na Universidade da Pensilvnia entre 1943 e 1945 pelos professores John Mauchly40 e
John Eckert41 obtendo financiamento do departamento de guerra com a promessa de construir
uma mquina que substituiria todos os computadores existentes, em particular as mulheres
que calculavam as tabelas balsticas para as armas da artilharia pesada do exrcito. O ENIAC
ocupava uma sala de 6 por 12 metros, pesava 30 toneladas e usava mais de 18 mil tubos a
vcuo, que eram muito pouco confiveis e aqueciam demasiadamente.
Apesar de suas 18 mil vlvulas, o ENIAC podia armazenar apenas 20 nmeros por vez.
No entanto, graas eliminao de engrenagens, era muito mais rpido que o Mark I. Por
exemplo, enquanto uma multiplicao no Mark I levava 6 segundos, no ENIAC levava 2,8
milsimos de segundo. A velocidade do relgio interno do ENIAC era de 100 mil ciclos por
segundo42. Financiado pelo exrcito dos Estados Unidos, o ENIAC tinha como principal tarefa
36
37
38
39
40
41
42
FACOM
UFMS
1.2 S CULO XX
FACOM
UFMS
10
B REVE
HISTRIA DA COMPUTAO
UFMS
1.2 S CULO XX
11
Jack St. Clair Kilby ( ), nascido nos Estados Unidos, engenheiro eltrico. Ganhador do Prmio Nobel
de Fsica em 2000 por sua contribuio na inveno do circuito integrado.
46
Robert Noyce ( ), nascido nos Estados Unidos, fsico. Tambm conhecido como o Mestre do Vale
do Silcio.
47
Douglas C. Engelbart (), nascido nos Estados Unidos, engenheiro eltrico e inventor.
48
Do ingls American Standard Code for Information Interchange ASCII.
49
Disquete ou disco flexvel, do ingls floppy disk.
50
Gordon Earle Moore (), nascido nos Estados Unidos, qumico e fsico.
51
A afirmao original de Gordon Moore pode ser encontrada no artigo intitulado Cramming more components
onto integrated circuits da Electronics Magazine, nmero 19, de abril de 1965.
FACOM
UFMS
12
B REVE
HISTRIA DA COMPUTAO
FACOM
UFMS
1.2 S CULO XX
13
FACOM
UFMS
14
B REVE
HISTRIA DA COMPUTAO
Donald Ervin Knuth (), nascido nos Estados Unidos, cientista da computao, Professor Emrito de Arte
de Programao de Computadores da Universidade de Stanford.
63
Stephen Arthur Cook (), nascido nos Estados Unidos, matemtico e cientista da computao, University
Professor da Universidade de Toronto.
64
Leonid Anatolievich Levin (), nascido na Ucrnia, cientista da computao.
65
Este problema tem um prmio estabelecido de 1 milho de dlares para o(s) pesquisador(es) que o solucionaFACOM
UFMS
1.2 S CULO XX
15
UFMS
16
B REVE
HISTRIA DA COMPUTAO
Windows 2.0 disponibilizado. Nessa poca a A PPLE trava uma batalha judicial por cpia de
direitos autorais do sistema operacional do MacIntosh contra a M ICROSOFT, pelo sistema operacional Windows 2.03 de 1988, e a H EWLETT-PACKARD, pelo sistema operacional NewWave
de 1989.
Em 1990 Tim Berners-Lee67 prope um sistema de hipertexto que o primeiro impulso da
Rede Mundial de Computadores68 . O primeiro provedor comercial de linha discada da Internet
torna-se ativo em 1991, quando a WWW disponibilizada para o pblico em geral como uma
ferramenta de busca.
Richard Stallman69 , em 1985, escreve o Manifesto GNU
que apresenta sua motivao para desenvolver o sistema
operacional GNU, o primeiro projeto de software livre proposto. Desde meados dos anos 90, Stallman tem gastado
muito de seu tempo como um ativista poltico defendendo
o software livre, bem como fazendo campanha contra patentes de software e a expanso das leis de direitos autorais. Os mais destacados programas desenvolvidos por
Stallman so o GNU Emacs, o GNU Compiler Collection
(gcc) e o GNU Debugger (gdb). Inspirado pelo Minix, um
sistema operacional baseado no Unix voltado para o ensino,
Linus Torvalds70 projetou em 1991 um sistema operacional
para computadores pessoais chamado Linux. O Linux um
exemplo de destaque do que chamamos de software livre e
de desenvolvimento de cdigo aberto. Seu cdigo fonte, escrito na linguagem C, disponibilizado para qualquer pessoa usar, modificar e redistribuir livremente.
O sistema operacional MS-DOS teve seu fim na dcada de 90, em sua ltima verso comercial 6.22, tendo sido completamente substitudo pelo bem sucedido Windows. A verso
3.0 do Windows vendeu 3 milhes de cpias em 1990. Em 1992, a verso 3.1 vendeu 1 milho
de cpias em apenas 2 meses depois de seu lanamento. J em 1997, aps o lanamento do
Windows 95 em 1995, Bill Gates reconhecido como o homem mais rico do mundo. Nessa
poca de exploso do uso dos sistemas operacionais da M ICROSOFT, os vrus de computador passaram a infestar cada vez mais computadores e a impor perdas cada vez maiores de
tempo, de recursos e de dinheiro s pessoas e empresas que os utilizavam. Um dos primeiros
e mais famosos vrus de computador o Monkey Virus, um vrus de setor de boot descoberto
no Canad em 1991, que se espalhou muito rapidamente pelos Estados Unidos, Inglaterra e
Austrlia. Seguiu-se ao Windows 95 o Windows 98 em 1998 e o Windows ME em 2000.
A Rede Mundial de Computadores e a Internet tambm mostram um desenvolvimento
destacado nessa poca. O ano de 1993 registra um crescimento espantoso da Internet e 50
servidores WWW j so conhecidos at aquele momento. Em 1994, os estudantes de doutorado em engenharia eltrica da Universidade de Stanford Jerry Yang71 e David Filo72 fundam
a Yahoo!, uma empresa de servios de Internet que engloba um portal de Internet, uma ferra67
68
69
70
71
72
FACOM
UFMS
1.2 S CULO XX
17
menta de busca na Internet, servio de e-mail, entre outros. A Yahoo! obtm grande sucesso
entre usurios e em outubro de 2005 sua rede de servios espalhada pelo mundo recebe em
mdia 3,4 bilhes de visitas por dia. Em 1994, o World Wide Web Consortium W3C fundado
por Tim Berners-Lee para auxlio no desenvolvimento de protocolos comuns para avaliao da
Rede Mundial de Computadores. O Wiki foi criado em 1995 pelo Repositrio Padro de Portland, nos Estados Unidos, e um banco de dados aberto edio, permitindo que qualquer
usurio possa atualizar e adicionar informao, criar novas pginas, etc., na Internet. Nesse
mesmo ano, a S UN M ICROSYSTEMS lana a linguagem de programao orientada a objetos
Java, amplamente utilizada hoje em dia para criar aplicaes para a Internet. Os rudimentos
da ferramenta de busca Google so desenvolvidos em 1996 como um projeto de pesquisa dos
alunos de doutorado Larry Page73 e Sergey Brin74 da Universidade de Stanford. Em 1998 a
pgina do Google disponibilizada na Internet e, atualmente, a ferramenta de busca mais
utilizada na rede. A WebTV tambm disponibilizada em 1996 possibilitando aos usurios
navegar pela Internet a partir de sua TV.
Com relao aos dispositivos eletrnicos, o Barramento Serial Universal USB75 padronizado em 1995 pela I NTEL, C OMPAQ, M ICROSOFT, entre outras. O USB um barramento externo
padronizado que permite transferncia de dados e capaz de suportar at 127 dispositivos perifricos. Em 1997 o mercado comea a vender uma nova mdia de armazenamento tico de
dados, o Disco Verstil Digital DVD76 , com as mesmas dimenses do CD, mas codificado
em um formato diferente com densidade muito mais alta, o que permite maior capacidade de
armazenamento. Os DVDs so muito utilizados para armazenar filmes com alta qualidade de
som e vdeo. Em 1998 o primeiro tocador de MP3, chamado de MPMan, vendido no Japo
pela empresa S AEHAN. A dcada de 90 tambm marcada pela unio, compra e venda de diversas empresas de computadores. A indstria de jogos para computadores pessoais tambm
teve seu crescimento acentuado nessa poca.
Os processadores tambm foram vendidos como nunca nos anos 90. A I NTEL lana em 1993 o
sucessor do INTEL 486, conhecido como Pentium,
ou Pentium I, de 32 bits, 60 MHz e 3,1 milhes de
transistores em sua verso bsica. A partir de 1997,
a I NTEL lana seus processadores seguidamente,
ano aps ano. Em 1997 anuncia a venda dos processadores Pentium MMX e Pentium II. O Celeron
produzido a partir de 1998 e em 1999, a I NTEL
anuncia o incio da produo do Pentium III. O
Pentium IV produzido a partir de 2000 e um
processador de 32 bits, 1,4 GHz e 42 milhes de
transistores. A AMD j produzia microprocessadores desde a dcada de 70, mas entrou em forte
concorrncia com a I NTEL a partir dessa poca,
com o lanamento do K5 em 1995, concorrente do
Pentium I, de 32 bits, 75 MHz e 4,3 milhes de transistores em sua primeira verso. Seguiu-se ao K5
73
Lawrence Edward Page (), nascido nos Estados Unidos, engenheiro da computao e empresrio.
Sergey Brin (), nascido na Rssia, matemtico, cientista da computao e empresrio.
75
Do ingls Universal Serial Bus.
76
Do ingls Digital Versatile Disc.
74
FACOM
UFMS
18
B REVE
HISTRIA DA COMPUTAO
o K6 em 1997, de 32 bits, 66 MHZ e 8,8 milhes de transistores, e a srie K7 de 1999, que engloba os processadores Athlon e Duron. A partir da dcada de 90, uma fatia considervel das
fbricas produz computadores pessoais com processadores da I NTEL ou da AMD. No incio da
dcada de 90, A PPLE, IBM e M OTOROLA se unem para projetar o processador PowerPC de 32
bits que equipou o PowerMac da A PPLE a partir de 1994. A aceitao desse novo computador
no foi como o esperado e, aps um perodo de baixas, a A PPLE ressurge em 1998 com o iMac,
um computador pessoal com projeto visual arrojado e com a filosofia do tudo-em-um-s. A
dcada de 90 marcada pela facilidade de acesso aos computadores pessoais, j que muitos
deles passam a ser vendidos por menos que 1.000 dlares.
De 2000 at hoje
O ano de 2000 inicia receoso para governos e empresas pelo medo das conseqncias potencialmente desastrosas da virada do sculo nos sistemas computacionais, o que se chamou na
poca de Bug do Milnio. Alm disso, o juiz Thomas Penfield anuncia a diviso do imprio
M ICROSOFT em duas companhias com Bill Gates deixando o cargo de Executivo-Chefe.
A M ICROSOFT lana o Windows XP em 2001, o Windows Vista, em janeiro de 2007 e recentemente o Windows 7 em 2009. A A PPLE disponibiliza o MacOS X 10.0 em 2001 e seguidas novas atualizaes at 2009, com o MAC OS X 10.6. O Linux tem maior penetrao e
aceitao dos usurios de computadores pessoais e diversas distribuies so disponibilizadas
como Ubuntu, Mandriva Linux, Fedora Core e SUSE Linux. Estas distribuies e os projetos
comunitrios Debian e Gentoo, montam e testam os programas antes de disponibilizar sua
distribuio. Atualmente, existem centenas de projetos de distribuio Linux em ativo desenvolvimento, constantemente revisando e melhorando suas respectivas distribuies.
Em 2001 a D ELL passa a ser a maior fabricante de computadores pessoais do mundo. Em
2002, uma empresa de consultoria norte-americana faz uma estimativa que at aquele ano
aproximadamente 1 bilho de computadores pessoais tinham sido vendidos no mundo inteiro
desde sua consolidao.
A I NTEL tem investido mais recentemente sua produo em processadores de 64 bits
com ncleos mltiplos, como por exemplo
o Xeon de 2004, o Pentium D de 2005, o
INTEL Core 2 Duo e o INTEL Core 2 Quad
de 2008. A AMD produz os processadores de
64 bits Duron em 2000 e o Sempron em 2004,
ambos da srie K7, e o Opteron em 2003 da
srie K8, este ltimo um processador de dois
ncleos, para competir com os processadores de mltiplos ncleos, como o Xeon da I N TEL. Em seguida, lana a srie K10 chamada
Phenom, com 2, 3 e 4 ncleos. A A PPLE, que
vinha utilizando o processador PowerPC em
sua linha de iMacs, anuncia que a partir de
2006 comear a usar os processadores da
I NTEL. A verso de 2006 do iMac usa o
processador INTEL Core 2 Duo. Na lista dos
FACOM
UFMS
1.2 S CULO XX
19
500 supercomputadores mais rpidos do mundo, a TOP500, de novembro de 2009, h um amplo domnio de mais de 80% de uso de processadores com ncleos mltiplos da INTEL nesses
computadores. Tambm interessante notar que esses supercomputadores usam alguma distribuio do sistema operacional Linux em mais de 82% deles, sendo que 99% usam um sistema
operacional baseado no Unix, como o Linux, e apenas 1% usam um sistema operacional baseado no Windows.
Figura 1.19: Cray XT5-HE Opteron Six Core 2.6 GHz, o computador mais rpido do mundo
na lista TOP500 de 2009, instalado no Oak Ridge National Laboratory. Usa o processador AMD
x86_64 Opteron Six Core 2600 MHz de 10,4 GFlops e o sistema operacional Linux.
Alguns modelos de computadores experimentais e inovadores tm sido propostos, com tentativas de implementaes. O computador baseado em DNA, tambm conhecido como computador molecular, o computador qumico e o computador quntico so exemplos de propostas recentes e promissoras.
UFMS
20
B REVE
HISTRIA DA COMPUTAO
Exerccios
1.1 Visite a pgina do Computer History Museum, que contm uma enorme quantidade de
informaes sobre esses dispositivos.
1.2 Escolha um ou dois personagens da pr-histria da computao e leia os verbetes sobre
esses personagens na Wikipedia.
1.3 Leia os verbetes associados s duas mulheres que tm papel importante na Histria da
Computao: Augusta Ada Byron e Grace Murray Hopper.
1.4 Leia o verbete sobre Alan Mathison Turing, o Pai da Cincia da Computao, na Wikipedia. Aproveite para ler o pedido formal de desculpas feito em 2009 pelo Primeiroministro da Inglaterra, Gordon Brown, e para vasculhar a pgina com as festividades do
centenrio de seu nascimento em 2012.
1.5 Leia uma apresentao simples e motivadora do problema P versus NP na pgina do Clay
Mathematics Institute.
1.6 Leia o verbete Cook-Levin Theorem na Wikipedia e tente entender informalmente o que ele
realmente quer dizer.
1.7 Visite a pgina GNU Operating System e leia o verbete GNU na Wikipedia e veja como este
sistema vem se desenvolvendo ao longo do tempo.
1.8 Visite as pginas Free Software Foundation, Fundao Software Livre Amrica Latina e o
portal de software livre (Portal: Free Software) da Wikipedia. Procure saber quais projetos
mantidos por esta fundao mais lhe interessou.
1.9 Leia o verbete Linux na Wikipedia, o sistema operacional que usamos na universidade.
1.10 Visite a pgina TOP500 para obter informaes dos computadores mais rpidos hoje existentes.
FACOM
UFMS
AULA
I NTRODUO
COMPUTAO
Na aula 1 vimos um pequeno histrico sobre a Computao. Nesta aula, vamos mencionar
brevemente como essas mquinas so organizadas internamente alm de invertigarmos o conceito de algoritmo e programa. Como veremos, John von Neumann foi o responsvel, em 1945,
pelo desenvolvimento de um modelo1 de computador que sobrevive at hoje.
Este texto baseado principalmente nas referncias [8, 9, 10].
2.1 Contextualizao
As primeiras mquinas computacionais projetadas tinham programas fixos. Assim, realizavam apenas aquelas tarefas para as quais foram concebidas. Modificar o programa de uma
dessas mquinas significava reestruturar toda a mquina internamente. Mesmo para computadores como o ENIAC, programar e reprogramar era um processo geralmente laborioso, com
uma quantidade enorme de rearranjo de fiao e de cabos de conexo. Dessa forma, podemos
destacar que a programao dos computadores que foram projetados antes do EDVAC tinha
uma caracterstica curiosa e comum: a programao por meios externos. Ou seja, os programadores, para que essas mquinas executassem seus programas, deviam usar cartes perfurados,
fitas perfuradas, cabos de conexo, entre outros. A pequena disponibilidade de memria para
armazenamento de dados e resultados intermedirios de processamento tambm representava
uma outra dificuldade complicadora importante.
Em 1936, Alan Turing publicou um trabalho [11]2 que descrevia um computador universal
terico, conhecido hoje como mquina universal de Turing. Esse computador tinha capacidade
infinita de armazenamento, onde se poderia armazenar dados e instrues. O termo usado foi o
de computador com armazenamento de programas3 . Sobre esse mesmo conceito, o engenheiro
alemo Konrad Zuse, que projetou a famlia Z de computadores, escreveu um trabalho [12]4
independentemente em 1936. Tambm de forma independente, John Presper Eckert e John
Mauchly, que projetaram o ENIAC na Universidade da Pensilvnia, propuseram um trabalho
em 1943, conforme meno em [13], sobre o conceito de computadores com armazenamento de
programas. Em 1944, no projeto do novo computador EDVAC, John Eckert deixou registrado
que sua equipe estava propondo uma forma inovadora de armazenamento de dados e programas em um dispositivo de memria enderevel, feito de mercrio, conhecido como linhas de
atraso. John von Neumann, tendo trabalhado com a equipe que construiu o ENIAC, juntou1
21
22
I NTRODUO
COMPUTAO
se tambm s discusses do projeto desse novo computador e ficou responsvel por redigir o
documento com a descrio dessas idias. Com a publicao desse trabalho [14]5 , divulgado
contendo apenas seu nome, essa organizao interna de um computador passou a ser conhecida como arquitetura de von Neumann, apesar de Turing, Zuse, Eckert e Mauchly terem
contribudo ou j apresentado idias semelhantes. Esse trabalho obteve grande circulao no
meio acadmico e seu sucesso como proposta de implementao de um novo computador foi
imediato. At nossos dias, essa organizao ainda usada nos projetos de computadores mais
conhecidos.
1111111111111111
0000000000000000
0000000000000000
1111111111111111
0000000000000000
1111111111111111
0000000000000000
1111111111111111
memria
0000000000000000
1111111111111111
0000000000000000
1111111111111111
0000000000000000
1111111111111111
11111111
00000000
00000000UCP
11111111
00000000
11111111
000
111
00
11
00000000
11111111
000
111
00
11
00000000
11111111
UC
ULA
000
111
00
11
00000000
11111111
000
111
00
11
00000000
11111111
00000000
11111111
00000000
11111111
1111
0000
0000
1111
0000
1111
0000
1111
entrada
0000
1111
0000
1111
0000
1111
0000
1111
11111
00000
00000
11111
00000
11111
00000
11111
sada
00000
11111
00000
11111
00000
11111
00000
11111
FACOM
UFMS
2.2 A RQUITETURA
DE VON
N EUMANN
23
ou de muito poucos, circuitos integrados. Diversos fabricantes disponibilizam microprocessadores no mercado, como os Core 2 Duo e Core 2 Quad da Intel e os Phenom X3 triple-core e
Phenom X4 quad-core da AMD.
A unidade central de processamento composta tambm pela unidade lgico-aritmtica
(ULA) e pela unidade de controle (UC). A ULA executa dois tipos de operaes: (i) operaes
aritmticas, como adies e subtraes, e (ii) operaes lgicas ou de comparao, como por
exemplo a verificao se um nmero maior ou igual a outro nmero. A UC coordena as
tarefas da UCP.
A memria de um computador pode ser vista como uma lista linear de compartimentos ou
clulas. Cada compartimento tem um identificador ou endereo numrico e pode armazenar
uma certa quantidade pequena de informao. A informao armazenada em um compartimento de memria pode ser uma instruo de um programa ou um dado, uma informao
que deve ser processada atravs das instrues. H dois tipos distintos de memria: (i) memrias volteis e (ii) memrias no volteis. As memrias do primeiro tipo necessitam de
uma fonte de energia para que seu contedo seja mantido. As memrias que permitem acesso
aleatrio7 aos seus compartimentos so, em geral, memrias volteis. Esses dispositivos permitem acesso rpido informao armazenada, mas so muito mais caros que os dispositivos
no volteis de memria. O que em geral chamamos de memria principal de um computador um dispositivo de memria voltil, pois quando desligamos o computador, todas as
informaes armazenadas em seus compartimentos so perdidas. Os dispositivos de armazenamento de informaes no volteis so aqueles que, ao contrrio dos primeiros, podem reter
a informao armazenada mesmo sem uma fonte de energia conectada. Como exemplo desses
dispositivos, podemos listar os discos rgidos, discos ticos, fitas magnticas, memrias do tipo
flash, memrias hologrficas, entre outros. Pela forma como em geral so implementados, esses
dispositivos no permitem que as informaes sejam acessadas rapidamente em um compartimento qualquer, o que acarreta um tempo maior para busca e recuperao das informaes.
No entanto, o custo de produo de tais dispositivos inferior ao custo dos dispositivos de
memrias volteis.
Se enxergarmos um computador como uma caixa-preta que alimentamos com informaes
e colhemos resultados dessas informaes processadas, podemos associar os seus dispositivos de entrada e sada como aqueles que fazem a comunicao do computador com o mundo
externo. O mundo externo pode ser composto por pessoas ou mesmo outros computadores.
Teclados, mouses, microfones, cmeras, entre outros, so dispositivos comuns de entrada. Monitores e impressoras so dispositivos de sada. Placas de rede so dispositivos tanto de entrada
como de sada de informaes.
Um computador funciona ento como uma mquina que, a cada passo, carrega uma instruo e dados da memria, executa essa instruo sobre esses dados e armazena os resultados
desse processamento em sua memria. Ento o processo se repete, isto , o computador novamente carrega uma prxima instruo e novos dados da memria, executa essa instruo sobre
os dados e grava os resultados desse processamento em sua memria. Enquanto existirem instrues a serem executadas em um programa, esse processo se repete. Todo computador tem
um sinal de relgio8 que marca esse passo mencionado, que mais conhecido como ciclo do relgio. Dessa forma, o sinal de relgio de um computador usado para coordenar e sincronizar
as suas aes.
7
8
FACOM
UFMS
24
I NTRODUO
COMPUTAO
Uma outra representao a arquitetura de von Neumann, mais prxima ao que conhecemos
como um computador pessoal, pode ser vista na figura 2.2.
impressora
mouse
1111
0000
0000
1111
0000
1111
portas
0000
1111
0000
1111
teclado
1111
0000
0000
1111
UCP
0000
1111
0000
1111
1111
0000
0000
1111
memria
0000
1111
0000
1111
1
0
0
1
0
1
0
1
0
1
0
1
0
1
0
1
0
1
0
1
0
1
0
1
0
1
0
1
0
1
0
1
0
1
0
1
0
1
0
1
0
1
0
1
0
1
0
1
0
1
0
1
0
1
0
1
0
1
0
1
0
1
0
1
0
1
0
1
0
1
0
1
1
0
0
1
0
1
0
1
0
1
0
1
0
1
0
1
0
1
0
1
0
1
0
1
0
1
0
1
0
1
0
1
0
1
0
1
0
1
0
1
0
1
0
1
0
1
0
1
0
1
0
1
0
1
0
1
0
1
0
1
0
1
0
1
0
1
0
1
0
1
0
1
0
1
0
1
0
1
0
1
0
1
0
1
0
1
0
1
0
1
0
1
0
1
0
1
0
1
0
1
0
1
0
1
0
1
0
1
0
1
0
1
0
1
0
1
0
1
0
1
0
1
0
1
0
1
0
1
0
1
0
1
0
1
0
1
0
1
0
1
0
1
0
1
0
1
0
1
0
1
0
1
0
1
0
1
0
1
0
1
0
1
0
1
0
1
0
1
0
1
0
1
0
1
0
1
0
1
0
1
0
1
0
1
0
1
0
1
0
1
0
1
0
1
0
1
0
1
0
1
0
1
0
1
0
1
0
1
0
1
0
1
0
1
0
1
1111
0000
0000
1111
placa
0000
1111
0000
1111
de disco
0000
1111
disco
rgido
DVD-RW
1111
0000
placa
0000
1111
0000
1111
grfica
0000
1111
monitor
1111
0000
placa
0000
1111
0000
1111
de som
0000
1111
caixas
de som
1111
0000
placa
0000
1111
0000
1111
de rede
0000
1111
internet
barramento
FACOM
UFMS
2.3 A LGORITMOS
E PROGRAMAS
25
PASSO
3 Se r igual a zero ento o mximo divisor comum igual a b e a execuo das instrues encerra aqui. Caso contrrio, siga para a prxima instruo.
PASSO
PASSO
PASSO
FACOM
UFMS
26
I NTRODUO
COMPUTAO
Um outro exemplo de instruo que no pode fazer parte de um algoritmo Escreva todos
os nmeros mpares. Neste caso, temos uma instruo que no pode ser executada porque
a execuo nunca terminar, apesar de sabermos exatamente como determinar os nmeros
mpares. Observe que se modificssemos a instruo para Escreva todos os nmeros mpares
menores do que 100, ela poderia, perfeitamente, fazer parte de um algoritmo.
Um problema para o qual existe uma soluo na forma de algoritmo dito um problema
algortmico. O problema de encontrar o mximo divisor comum de dois nmeros naturais
quaisquer , portanto, um problema algortmico. Problemas algortmicos, em geral, possuem
muitas ocorrncias. Por exemplo, para o problema de encontrar o mximo divisor comum de
dois nmeros naturais, cada ocorrncia uma dupla distinta de nmeros naturais cujo mximo
divisor comum queremos encontrar. Um algoritmo dito correto quando ele sempre termina e
produz a resposta correta para todas as ocorrncias de um dado problema.
Algoritmo, ento, pode ser imaginado como a especificao de um processo mecnico
que, quando executado, leva-nos soluo de algum problema. Embora o termo algoritmo
esteja relacionado intimamente com Computao, algoritmos tm sido parte de nossas vidas
desde a primeira vez que uma pessoa explicou para outra como fazer alguma coisa. As pessoas utilizam algoritmos quando seguem receitas culinrias ou instrues para programar um
tocador de msicas. Entretanto, nem todo algoritmo pode ser executado por um computador.
Um computador pode executar apenas aqueles algoritmos cujas instrues envolvam tarefas
que ele possa entender e executar. Este no o caso, por exemplo, de instrues como corte o
fil em cubos e ligue o tocador de msica.
Computadores executam algoritmos que manipulam apenas dados e no coisas fsicas, tais
como fil e tocador de msica. A execuo de um algoritmo por um computador denominada
processamento de dados e consiste de trs partes: uma entrada, um processo ou processamento
e uma sada. A entrada um conjunto de informaes que requisitada para que as instrues
do algoritmo possam ser executadas. O processamento a seqncia de instrues que compe
o algoritmo. E a sada o resultado obtido com a execuo do processo para a entrada fornecida. Por exemplo, a entrada e a sada para uma computao do algoritmo para o problema
de encontrar o mximo divisor comum de dois nmeros naturais so, respectivamente, dois
nmeros naturais e o mximo divisor comum entre eles.
Quando escrevemos algoritmos para serem executados por computador, temos de fazer
algumas suposies sobre o modelo de computao entradaprocessamentosada. A primeira
delas que, a fim de realizar qualquer computao, o algoritmo deve possuir um meio de
obter os dados da entrada. Esta tarefa conhecida como leitura da entrada. A segunda, que o
algoritmo deve possuir um meio de revelar o resultado da computao. Isto conhecido como
escrita dos dados da sada. Todo e qualquer computador possui dispositivos atravs dos quais
a leitura e a escrita de dados so realizadas.
UFMS
2.3 A LGORITMOS
E PROGRAMAS
27
FACOM
UFMS
28
I NTRODUO
COMPUTAO
O processo de abstrao pode ser visto como constando de nveis. Isto diz respeito ao grau
de simplificao de uma abstrao. Por exemplo, se a planta de uma casa entregue a um
experiente mestre-de-obras sem meno de, por exemplo, como fazer uma mistura ideal de
cimento para fundao, provavelmente, isso no ser um problema para ele. Entretanto, se a
mesma planta da casa for entregue a um advogado, ele certamente no saber construir a casa.
Isso quer dizer que a planta da casa dada ao advogado deveria conter maiores detalhes do
processo de construo da casa do que aquela dada para o mestre-de-obras. Aqui, a planta da
casa uma abstrao e o nvel de detalhe da planta proporcional ao nvel de simplificao da
abstrao.
Algoritmos bem projetados so organizados em nveis de abstrao, pois um mesmo algoritmo deve ser entendido por pessoas com diferentes graus de conhecimento. Quando um
algoritmo est assim projetado, as instrues esto organizadas de tal forma que podemos entender o algoritmo sem, contudo, ter de entender os detalhes de todas as instrues de uma s
vez. Para tal, o processo de construo de algoritmos conta com ferramentas, tais como mdulos, que agrupam instrues que realizam uma determinada tarefa no algoritmo, independente
das demais, tal como fazer a leitura da entrada, dispensando-nos de entender o detalhe de cada
instruo separadamente, mas sim fornecendo-nos uma viso da funcionalidade do grupo de
instrues.
UFMS
2.3 A LGORITMOS
29
E PROGRAMAS
UFMS
30
I NTRODUO
COMPUTAO
111111
000000
000000
111111
000000
111111
000000
111111
algoritmo
000000
111111
000000
111111
000000
111111
0
1
0
1
0
1
0 programao
1
0
1
0
1
000000
111111
programa na
000000
111111
000000
111111
linguagem
000000
111111
X
000000
111111
0
1
000000
111111
0
1
0
1
0
1
0 compilao
1
0
1
0
1
000000
111111
000000
111111
programa
000000
111111
assembly
000000
111111
000000
111111
000000
111111
0
1
0
1
0
1
montagem
0
1
0
1
000000
111111
0
1
000000
111111
programa
em
000000
111111
000000
111111
linguagem
000000
111111
de mquina
000000
111111
000000
111111
Figura 2.3: Passos desde a concepo de um algoritmo at o programa executvel por um
computador.
Exerccios
2.1 Leia o verbete Computer na Wikipedia, que traz muitas informaes sobre essas mquinas.
2.2 Leia o verbete von Neumann architecture na Wikipedia, sobre o modelo de organizao
interna de computadores mais conhecido.
2.3 D uma olhada no trabalho de John von Neumann na referncia [14]13 , sobre a arquitetura de von Neumann.
2.4 D uma olhada no trabalho de Alan Turing na referncia [11]14 com a descrio da mquina de Turing.
2.5 Visite a pgina sobre a vida e o trabalho de Konrad Zuse.
2.6 Sobre a linguagem de programao que adotaremos neste curso, visite as pginas
C History e C Programming Language e leia o verbete C (programming language) na Wikipedia.
13
14
FACOM
UFMS
AULA
D ICAS
INICIAIS
Nesta aula aprenderemos dicas importantes sobre as ferramentas que mais usaremos durante o desenvolvimento da parte prtica da disciplina. Em particular, veremos a definio de
uma interface do sistema operacional (shell ou Unix shell) e aprenderemos a usar alguns dentre
os tantos comandos disponveis para essa interface, aprenderemos alguns comandos e funes
do ambiente de trabalho GNU/Emacs e aprenderemos a usar o compilador da linguagem C da
coleo de compiladores GNU, o GCC .
32
D ICAS
INICIAIS
Isso posto, um dos programas mais comuns disponveis para os usurios do sistema operacional GNU/Linux chamado de terminal, como uma abreviao de terminal de linhas de
comando, que nada mais que uma interface entre o usurio e o sistema operacional. Para
disparar esse programa no gerenciador de janelas GNOME, selecione a opo Aplicaes do
menu principal, depois a opo Acessrios no sub-menu e, em seguida, a opo Terminal.
Um exemplo de uma janela de terminal de linhas de comando do GNOME apresentado na
figura 3.1.
Figura 3.1: Uma interface, ou janela, de linhas de comandos do sistema de janelas GNOME,
chamada no computador Homer pelo usurio fhvm. Esses nomes compem o sinal de pronto
do sistema.
Uma janela de linha de comandos possibilita a interao entre o usurio e o computador,
intermediada pelo sistema operacional, onde o primeiro solicita tarefas diretamente ao outro e,
depois de executadas, recebe seus resultados. Daqui por diante, veremos alguns dos comandos
e utilitrios que sero mais usados durante o decorrer da disciplina. Alguns deles apresentam,
at certo ponto, algum grau de dificuldade de compreenso neste momento. Todavia, importante ressaltar que todos esses comandos e utilitrios sero muito teis a partir de momentos
oportunos, como veremos.
A seguir, apresentamos a tabela 3.1 contendo os principais comandos e utilitrios do sistema operacional, com suas descries breves, os quais mais usaremos no desenvolvimento da
disciplina de Algoritmos e Programao I (e II). Esta tabela apenas um guia de referncia rpida e, apesar da maioria dos comandos e utilitrios serem intuitivos e muito fceis de usar, a
descrio breve contida na tabela infelizmente no nos ensina de fato como fazer uso correto de
cada um deles. Tambm no mostra todas as opes de execuo que em geral todo comando
ou utilitrio possui.
FACOM
UFMS
3.1 I NTERFACE
DO SISTEMA OPERACIONAL
33
Dessa forma, para aprender gradativa e corretamente a usar os comandos e utilitrios apresentados na tabela 3.1 necessrio: (i) fazer os exerccios ao final desta aula; (ii) usar com
freqncia o utilitrio man ou info , que so interfaces para o manual de referncia dos comandos e ferramentas do sistema1 . Por exemplo, podemos digitar:
ou
prompt$ ls *.c
prompt$ ls ???.c
Esses manuais tambm podem ser encontrados em pginas da internet, como Manpages e SS64.com.
FACOM
UFMS
34
D ICAS
INICIAIS
Comando
Descrio
cat arq
cd dir
cmp arq1 arq2
cp arq1 arq2
cp arq(s) dir
date
diff arq1 arq2
echo args
enscript arq
fmt arq
gprof arq
indent arq
info cmd
ls arq(s)
ls dir
man cmd
mkdir dir(s)
mv arq1 arq2
mv arq(s) dir
pwd
pr arq
rm arq(s)
rmdir dir(s)
sort arq(s)
wc arq(s)
who
prompt$ ls *[abc]
o argumento *[abc] representa todos os arquivos do diretrio cujos nomes terminam com o
caractere a , b ou c .
Um intervalo de caracteres pode ser obtido no interior dos colchetes se o caractere -
usado. Por exemplo:
FACOM
UFMS
3.1 I NTERFACE
DO SISTEMA OPERACIONAL
35
prompt$ ls *[a-z]
onde o argumento representa os nomes dos arquivos que terminam com uma das 26 letras do
alfabeto.
Por fim, importante destacar que muitos comandos do sistema operacional recebem informaes de entrada a partir do terminal e tambm enviam as informaes resultantes de sada
para o terminal de comandos. Um comando em geral l as informaes de entrada de um local chamado de entrada padro, que pr-definido como o terminal de linha de comandos, e
escreve sua sada em um local chamado de sada padro, que tambm pr-definido como o
terminal de linhas de comando.
Por exemplo, o comando sort pode ordenar nomes fornecidos linha a linha por um usurio no terminal de comandos, ordenar esses nomes lexicograficamente e apresentar o resultado
no terminal de linha de comandos:
prompt$ sort
Zenaide
Carlos
Giovana
Amanda
Ctrl-d
Amanda
Carlos
Giovana
Zenaide
prompt$
Se dispomos os caracteres > arq ao final de qualquer comando ou utilitrio que normalmente envia sua sada para a sada padro, ou seja, para o terminal de linha de comandos,
o sada desse comando ser escrita para o arquivo com nome arq ao invs do terminal. Por
exemplo, a seqncia a seguir:
Ctrl-d
prompt$
faz com que quatro nomes digitados pelo usurio sejam ordenados e, em seguida, armazenados
no arquivo nomes.txt .
Assim como a sada pode ser redirecionada para um arquivo, a entrada tambm pode ser
redirecionada a partir de um arquivo. Se, por exemplo, existe um arquivo temp.txt contendo
diversos nomes apresentados linha a linha, ento o comando a seguir:
FACOM
UFMS
36
D ICAS
INICIAIS
faz com que todos os nomes contidos no arquivo temp.txt sejam ordenados lexicograficamente e posteriormente apresentados seguida na sada padro, isto , na janela do terminal de
linha de comandos.
Podemos ainda redirecionar a entrada e a sada de um comando concomitantemente. Por
exemplo, o comando:
recebe, pelo redirecionamento da entrada, os nomes contidos no arquivo temp.txt , ordenaos lexicograficamente e os armazena em um novo arquivo chamado nomes.txt , devido ao
redirecionamento da sada.
Dessa forma, temos que os smbolos < e > so os smbolos de redirecionamento de entrada e sada, respectivamente.
3.2 Compilador
A coleo de compiladores GNU (GCC ) , na verdade, um arcabouo de compiladores para
diversas linguagens de programao. Esse sistema foi desenvolvido pelo Projeto GNU e, por
ter sido adotado como o compilador oficial do sistema operacional GNU, tambm foi adotado
como compilador padro por muitos dos sistemas operacionais derivados do Unix, tais como
o GNU/Linux, a famlia BSD e o Mac OS X. Alm disso, o GCC tem sido traduzido para uma
grande variedade de arquiteturas.
Richard Stallman desenvolveu a primeira verso do GCC em 1987, como uma extenso de
um compilador j existente da linguagem C. Por isso, naquela poca o compilador era conhecido como GNU C Compiler. No mesmo ano, o compilador foi estendido para tambm compilar
programas na linguagem C++. Depois disso, outras extenses foram incorporadas, como Fortran, Pascal, Objective C, Java e Ada, entre outras. A Fundao para o Software Livre distribui
o GCC sob a Licena Geral Pblica (GNU GPL GNU General Public License). O GCC um
software livre.
Um compilador faz o trabalho de traduzir um programa na linguagem C, ou de outra linguagem de alto nvel qualquer, para um programa em uma linguagem intermediria, que ainda
ser traduzido, ou ligado, para um programa em uma linguagem de mquina. Dessa forma,
um argumento bvio que devemos fornecer ao GCC o nome do arquivo que contm um programa na linguagem C. Alm disso, podemos informar ao compilador um nome que ser atribudo ao programa executvel resultante da compilao e ligao. H tambm diversas opes
disponveis para realizar uma compilao personalizada de um programa e que podem ser
informadas no processo de compilao.
Ento, o formato geral de compilao de um programa dado a seguir:
FACOM
UFMS
3.3 E MACS
37
onde gcc o programa compilador, programa.c um arquivo com extenso .c que contm
um programa fonte na linguagem C, -o uma opo do compilador que permite fornecer um
nome ao programa executvel resultante do processo ( executvel ), -Wall uma opo que
solicita que o compilador mostre qualquer mensagem de erro que ocorra durante a compilao,
-ansi uma opo que fora o programa fonte a estar escrito de acordo com o padro ANSI
da linguagem C e -pedantic uma opo que deixa o compilador muito sensvel a qualquer
possvel erro no programa fonte.
No momento, ainda no escrevemos um programa na linguagem C e, por isso, no conseguimos testar o compilador de forma satisfatria. Esta seo ento apenas um guia de
referncia rpida que ser muito usada daqui por diante.
3.3 Emacs
Em geral, usamos a palavra Emacs para mencionar um editor/processador de textos, mas
Emacs , na verdade, o nome de uma classe de editores/processadores que se caracteriza especialmente pela sua extensibilidade. O Emacs tem mais de 1.000 comandos de edio, mais do
que qualquer outro editor existente, e ainda permite que um usurio combine esses comandos
em macros para automatizao de tarefas. A primeira verso do Emacs foi escrita em 1976
por Richard Stallman. A verso mais popular do Emacs o GNU/Emacs, uma parte do Projeto GNU. O GNU/Emacs um editor extensvel, configurvel, auto-documentado e de tempo
real. A maior parte do editor escrita na linguagem Emacs Lisp, um dialeto da linguagem de
programao funcional Lisp.
O Emacs considerado por muitos especialistas da rea como o editor/processador de
textos mais poderoso existente nos dias de hoje. Sua base em Lisp permite que se torne configurvel a ponto de se transformar em uma ferramenta de trabalho completa para escritores,
analistas e programadores.
Em modo de edio, o Emacs comporta-se como um editor de texto normal, onde o pressionamento de um caractere alfanumrico no teclado provoca a insero do caractere correspondente no texto, as setas movimentam o ponto ou cursor de edio, a tecla Backspace remove
um caractere, a tecla Insert troca o modo de insero para substituio ou vice-versa, etc. Comandos podem ser acionados atravs do pressionamento de uma combinao de teclas, pressionando a tecla Ctrl e/ou o Meta/Alt juntamente com uma tecla normal. Todo comando
de edio de fato uma chamada de uma funo no ambiente Emacs Lisp. Alguns comandos
bsicos so mostrados na tabela 3.2. Observe que a tecla Ctrl representada por C e a tecla
Alt por M . Um manual de referncia rpida est disponvel na bibliografia complementar na
pgina da disciplina.
Para carregar o Emacs, podemos usar o menu principal do GNOME e escolher a opo Aplicaes, escolhendo em seguida a opo Acessrios e ento a opo Emacs. Ou ento, de uma
linha de comandos, podemos usar:
UFMS
38
D ICAS
INICIAIS
Descrio
minimiza a janela do Emacs
finaliza a execuo do Emacs
carrega um arquivo no Emacs
salva o arquivo atual no disco
insere o contedo de um outro arquivo no arquivo atual
salva o contedo do arquivo em um outro arquivo especificado
carrega o manual do Emacs
mostra um tutorial do Emacs
aborta o comando parcialmente informado
busca uma cadeia de caracteres a partir do cursor
busca uma cadeia de caracteres antes do cursor
interativamente, substitui uma cadeia de caracteres
Exerccios
3.1 Abra um terminal. A partir de seu diretrio inicial, chamado de home pelo sistema operacional, faa as seguintes tarefas:
crie trs diretrios com os seguintes nomes: algprogi, ftc e temp;
usando o comando cat e o smbolo de redirecionamento de sada > , crie um arquivo com nome agenda.txt, que contm linha a linha, nome e telefone de pessoas.
Adicione pelo menos 10 nomes nesse arquivo;
copie o arquivo agenda.txt para os diretrios algprogi e temp;
Veja tambm o carto de referncia do Emacs na seo de bibliografia complementar da disciplina no Moodle.
FACOM
UFMS
3.3 E MACS
39
neste diretrio, liste todos os arquivos que terminam com a seqncia de caracteres
txt;
repita os trs ltimos comandos, usando no entanto o comando echo ;
liste todos os arquivos contidos neste diretrio, mas redirecione a sada do comando
para um arquivo de nome lista;
execute o comando ls [afl]* e verifique a sada;
FACOM
UFMS
40
FACOM
D ICAS
INICIAIS
UFMS
AULA
P RIMEIROS
PROGRAMAS
4.1 Digitando
Abra o seu Emacs, pressione C-x C-f , digite em seguida um nome para seu primeiro
programa, como por exemplo primeiro.c, e ento digite o seguinte cdigo.
Programa 4.1: Primeiro programa.
#include <stdio.h>
int main(void)
{
printf("Programar bacana!\n");
return 0;
}
Depois de ter digitado o programa, pressione as teclas C-x C-s para salv-lo em um diretrio adequado da sua rea de trabalho. Na linguagem C, letras minsculas e maisculas so
diferentes. Alm disso, em programas na linguagem C no h distino de onde voc inicia a
digitao das suas linhas e, assim, usamos essa caracterstica a nosso favor, adicionando espaos em algumas linhas do programa para facilitar sua leitura. Essa adio de espaos em uma
linha chamada indentao ou tabulao. No Emacs, voc pode usar a tecla Tab para adicionar indentaes de forma adequada. Veremos que a indentao uma prtica de programao
muito importante.
41
42
P RIMEIROS
PROGRAMAS
Depois disso, o programa executvel a.out estar disponvel para execuo no mesmo
diretrio. Assim, s digitar a.out (ou ./a.out) para ver o resultado da execuo:
prompt$ ./a.out
Programar bacana!
prompt$
O nome a.out um nome padro que o compilador gcc d aos arquivos executveis resultantes de uma compilao. Em geral, atribumos um nome mais significativo a um programa
executvel, como por exemplo o mesmo nome do programa na linguagem C, mas sem a sua
extenso. No exemplo acima, o programa executvel associado tem o nome primeiro. O compilador gcc pode gerar um executvel dessa forma como segue:
#include <stdio.h>
ser muito provavelmente includa em todo programa que voc far na linguagem C. Essa
linha fornece informaes ao compilador sobre a funo de sada de dados de nome printf ,
que usada depois no programa.
A segunda linha do programa
int main(void)
informa ao compilador onde o programa inicia de fato. Em particular, essa linha indica que
main , do ingls principal, o incio do programa principal e, mais que isso, que esse trecho do
programa na verdade uma funo da linguagem C que no recebe valores de entrada ( void )
e devolve um valor do tipo inteiro ( int ). Esses conceitos de funo, parmetros de uma
funo e valor de sada sero elucidados oportunamente. Por enquanto, devemos memorizar
que essa linha indica o incio de nosso programa.
A prxima linha contm o smbolo abre-chave { que estabelece o incio do corpo do programa. Em seguida, a prxima linha contm uma chamada funo printf :
printf("Programar bacana!\n");
FACOM
UFMS
4.4 P RXIMO
43
PROGRAMA
return 0;
UFMS
44
P RIMEIROS
PROGRAMAS
sulta o contedo das variveis num1 e num2 , realiza a operao de adio com os dois valores
obtidos dessas variveis e, aps isso, atribui o resultado varivel soma . No nosso exemplo,
o resultado da expresso aritmtica 25 + 30, ou seja, o valor 55, ser atribudo varivel soma .
A linha seguinte contm uma chamada funo printf , mas agora com quatro argumentos:
o primeiro agora uma cadeia de caracteres de formatao, contendo no apenas caracteres a
serem impressos na sada, mas smbolos especiais, iniciados com % , conhecidos como conversores de tipo da linguagem C. Neste caso, os smbolos %d permitem que um nmero inteiro
seja mostrado na sada. Note que trs conversores %d esto contidos na cadeia de caracteres
de formatao e, a cada um deles est associado uma das variveis num1 , num2 e soma , na
ordem em que aparecem. Essas variveis so os argumentos restantes da funo printf .
4.5 Documentao
Uma boa documentao de um programa, conforme [15], significa inserir comentrios apropriados no cdigo de modo a explicar o que cada uma das funes que compem o programa
faz. A documentao de uma funo um pequeno manual que d instrues precisas e completas sobre o uso da funo.
Comentrios so introduzidos em programas com o objetivo de document-los e de incrementar a sua legibilidade. O(a) programador(a) responsvel por manter seus cdigos legveis
e bem documentados para que, no futuro, possa retom-los e compreend-los sem muito esforo e sem desperdcio de tempo. Na linguagem C padro, os comentrios so envolvidos
pelos smbolos /* e */ . Um comentrio completamente ignorado quando encontrado pelo
compilador e, portanto, no faz diferena alguma no programa executvel resultante.
Vejamos o programa 4.3, que nada mais que a codificao do programa 4.2 com uma
documentao do programa principal.
Programa 4.3: Segundo programa.
#include <stdio.h>
/* Este programa faz a adio de dois nmeros inteiros
fixos e mostra o resultado da operao na sada. */
int main(void)
{
int num1, num2, soma;
num1 = 25;
num2 = 30;
soma = num1 + num2;
printf("A soma de %d e %d %d\n", num1, num2, soma);
return 0;
}
Ainda conforme [15], uma boa documentao no se preocupa em explicar como uma funo faz o que faz, mas sim o que ela faz de fato, informando quais so os valores de entrada da
funo, quais so os valores de sada e quais as relaes que esses valores que entram e saem
da funo e as transformaes pela funo realizadas.
FACOM
UFMS
4.6 E NTRADA
45
E SADA
Vamos olhar mais de perto este programa. Observe que, pela primeira vez, usamos a funo
scanf que, como mencionamos acima, uma funo da linguagem C responsvel pela leitura
de dados.
Desconsiderando o esqueleto do programa, a primeira linha a ser notada a declarao de
variveis:
int num1, num2, soma;
Estamos, com esta linha do programa, reservando trs compartimentos de memria que podero ser utilizados para armazenamento de nmeros inteiros, cujos nomes so num1 , num2
e soma . Os contedos desses compartimentos de memria podem variar durante a execuo
do programa. De fato, no momento da declarao, os compartimentos associados aos nomes
num1 , num2 e soma j contm, cada um, algum valor que desconhecido e que referenciamos
como lixo.
Em seguida, h duas chamadas de funes para escrita e leitura:
UFMS
46
P RIMEIROS
PROGRAMAS
A funo para escrita de dados printf j bem conhecida, vista nesta e nas aulas anteriores. A funo de leitura scanf tem dois argumentos: uma cadeia de caracteres de formatao "%d" e uma varivel num1 correspondente a este formato. Diferentemente da funo
printf , uma varivel do tipo inteiro que um argumento da funo scanf deve sempre vir
precedida com o smbolo & . Na instruo acima, a cadeia de caracteres de formatao "%d"
indica que o valor informado pelo usurio ser convertido para um inteiro. Ainda, este valor
ser ento armazenado na varivel do tipo inteiro num1 . Observe, mais uma vez, que esta
varivel precedida por um & .
A prxima seqncia de instrues equivalente e solicita ao usurio do programa a entrada de um outro nmero, que ser armazenado na varivel num2 :
Aqui temos uma instruo/comando de atribuio da linguagem C, definida pelo smbolo/operador = . Uma instruo de atribuio tem uma sintaxe bem definida: do lado esquerdo do smbolo de atribuio = h sempre uma varivel; do lado direito h uma constante,
uma varivel ou uma expresso do mesmo tipo da varivel esquerda. Esta instruo funciona da seguinte forma: avalia a expresso do lado direito do smbolo de atribuio e atribui o
resultado desta avaliao para a varivel do lado esquerdo. Em nosso exemplo, o lado direito
uma expresso aritmtica de adio, que soma os contedos das variveis do tipo inteiro num1
e num2 . O resultado da avaliao dessa expresso um nmero inteiro que ser atribudo
varivel soma , do lado esquerdo do smbolo de atribuio. O lado direito de uma instruo
de atribuio pode conter expresses aritmticas to complicadas quanto quiseremos. O lado
esquerdo, ao contrrio, sempre descrito por uma nica varivel.
Por fim, a chamada funo
mostra, alm dos valores das duas parcelas num1 e num2 , o resultado dessa soma armazenado
na varivel soma .
Veremos agora um segundo exemplo usando as funes de entrada e sada que acabamos
de aprender. Este segundo exemplo muito semelhante ao exemplo anterior. A diferena est
apenas no formato da expresso aritmtica: no primeiro exemplo, uma adio realizada; neste
segundo exemplo, uma multiplicao realizada. O operador aritmtico de multiplicao o
smbolo * . Ento, informe, compile e execute o seguinte programa 4.5.
FACOM
UFMS
4.6 E NTRADA
47
E SADA
Exerccios
4.1 Escreva uma programa na linguagem C que escreva a seguinte mensagem na sada padro:
a)
b)
c)
d)
e)
UFMS
48
P RIMEIROS
PROGRAMAS
resultado);
4.5 Escreva um programa que leia trs nmeros inteiros a, b e c, calcule a b + c e mostre o
resultado na sada padro para o usurio.
4.6 Escreva um programa que leia um nmero inteiro e mostre o seu quadrado e seu cubo.
Por exemplo, se o nmero de entrada 3, a sada deve ser 9 e 27.
4.7 Escreva um programa que leia trs nmeros inteiros e mostre como resultado a soma
desses trs nmeros e tambm a multiplicao desses trs nmeros.
4.8 Escreva um programa que leia um nmero inteiro e mostre o resultado da quociente
(inteiro) da diviso desse nmero por 2 e por 3.
FACOM
UFMS
AULA
E STRUTURAS
CONDICIONAIS
50
E STRUTURAS
CONDICIONAIS
para m, n > 1. Como nas estruturas condicionais simples, se m = 1 ou n = 1, os smbolos delimitadores de bloco { e } so opcionais. A linguagem C tem como regra sempre envolver um
bloco de instrues com os delimitadores { e } . Exceo se faz quando o bloco de instrues
contm uma nica instruo: neste caso, a incluso dos delimitadores opcional.
Uma deciso tomada de acordo com a avaliao da condio, que uma expresso lgica:
caso o resultado dessa avaliao seja verdadeiro, o primeiro bloco de instrues ser executado
e, ao trmino desse bloco, a instruo da prxima linha aps a estrutura condicional composta
ser executada. Caso contrrio, isto , se o resultado da avaliao da expresso lgica falso,
FACOM
UFMS
5.2 E STRUTURA
51
CONDICIONAL COMPOSTA
o segundo bloco de instrues, logo aps a palavra-chave else , ser executado. Ao final da
execuo das instrues desse bloco, a instruo da prxima linha aps a estrutura condicional
composta ser executada. Veja um exemplo no programa 5.2.
Programa 5.2: Estrutura condicional if-else.
#include <stdio.h>
/* Recebe um nmero inteiro e emite uma mensagem de acordo com esse nmero */
int main(void)
{
int idade;
printf("Quantos anos voc tem? ");
scanf("%d", &idade);
if (idade < 30)
printf("Puxa! Voc bem jovem!\n");
else
printf("Puxa! Voc j velhinho!\n");
printf("At breve!\n");
return 0;
}
FACOM
UFMS
52
E STRUTURAS
CONDICIONAIS
soma
num1
i
soma_total
_sistema
A3x3
frao
1
FACOM
UFMS
5.3 R EVISO
DE NMEROS INTEIROS
53
preo$
soma total
4quant
int
ou
int
int
int
int
int
int
i;
num1;
num2;
soma;
produto;
aux;
TotalDeDinheiroQueTenho = TotalDoDinheiroQueGuardeiAnoPassado +
TotalDeDinheiroQueGuardeiEsteAno - TotalDeImpostosEmReais;
FACOM
UFMS
54
E STRUTURAS
CONDICIONAIS
Em um programa na linguagem C, os nmeros inteiros que ocorrem em algumas expresses so conhecidos como constantes numricas, ou simplesmente constantes. Por exemplo,
o nmero 37 representa um valor inteiro constante. Expresses aritmticas que se constituem
apenas de constantes numricas e de operadores so chamadas de expresses aritmticas constantes. Por exemplo,
781 + 553 - 12 * 44
#define NUMERADOR 4
#define MIN -10000
#define MAX 100
FACOM
UFMS
5.3 R EVISO
DE NMEROS INTEIROS
55
UFMS
56
E STRUTURAS
CONDICIONAIS
x + y * z
dado primeiro pela avaliao da multiplicao e depois pela avaliao da adio. Parnteses
so utilizados para modificar a ordem das operaes. Por exemplo,
(x + y) * z
Descrio
Multiplicao, quociente da diviso e resto da diviso
Adio e subtrao
Precedncia
1 (mxima)
2 (mnima)
int i;
UFMS
5.3 R EVISO
57
DE NMEROS INTEIROS
ou
2147483648, . . . , 1, 0, 1, . . . , 2147483647 .
Cada seqncia de 32 bits que comea com 0 representa um int no-negativo em notao
binria. Cada seqncia de 32 bits que comea com 1 representa o inteiro negativo k 232 ,
onde k o valor da seqncia em notao binria. Esta representao de nmeros inteiros
negativos
de complemento-de-dois. Nmeros inteiros que estejam fora do intevalo
31 31 chamada
2 , 2 1 so representados mdulo 232 .
Ressaltamos ainda que todos os valores acima podem ser obtidos usando frmulas gerais
em funo do nmero de bytes consecutivos usados para representar um int .
Exerccios
5.1 Escreva um programa que receba a temperatura ambiente em graus Clsius e mostre uma
mensagem para o usurio informando se a temperatura est muito quente. Considere
como temperatura limite o valor de 30 graus Clsius.
Programa 5.5: Soluo do exerccio 5.1.
#include <stdio.h>
/* Recebe um nmero inteiro que representa uma
temperatura e imprime uma mensagem de aviso */
int main(void)
{
int temperatura;
printf("Informe uma temperatura (em graus Celsius):"));
scanf("%d", &temperatura);
if (temperatura > 30)
printf("Hoje um dia bem quente!\n");
else
printf("Hoje no um dia to quente.\n");
return 0;
}
UFMS
58
E STRUTURAS
CONDICIONAIS
Por exemplo, suponha que usamos i = 256 dias para alguma atividade e queremos saber
qual o total de dias m que devemos ter de forma que esse nmero seja divisvel por j = 7,
para termos uma idia do nmero de semanas que usaremos na atividade. Ento, pela
frmula acima, temos que
m = 256 + 7 256 mod 7
= 256 + 7 4
= 259 .
Escreva um programa que receba dois nmeros inteiros positivos i e j e devolva o menor
inteiro m maior que i e mltiplo de j.
5.4 Escreva um programa que receba um nmero inteiro a e verifique se a par ou mpar.
5.5 Escreva um programa que receba um nmero inteiro a e verifique se a positivo, negativo
ou igual a 0.
5.6 Escreva um programa que receba trs valores, armazenando-os nas variveis x, y e z, e ordene esses valores de modo que, ao final, o menor valor esteja armazenado na varivel x,
o valor intermedirio esteja armazenado na varivel y e o maior valor esteja armazenado
na varivel z.
FACOM
UFMS
AULA
E STRUTURA
DE REPETIO
while
As estruturas de repetio so, juntamente com a estrutura seqencial e as estruturas condicionais que vimos nas aulas passadas, elementos fundamentais em algoritmos e programao.
So essas trs estruturas bsicas que permitem que um(a) desenvolvedor(a)/programador(a)
consiga resolver centenas e centenas de problemas de maneira efetiva. De posse apenas das estruturas seqencial e condicional, um(a) programador(a) fica muito restrito soluo de uma
pequena parcela de problemas. Assim, nesta aula motivaremos o estudo das estruturas de
repetio e apresentaremos a estrutura de repetio while da linguagem C.
Esta aula baseada em [16, 9].
6.1 Motivao
Suponha que algum queira escrever um programa para imprimir os dez primeiros nmeros inteiros positivos. Este problema, apesar de muito simples e pouco til primeira vista,
motiva a introduo das estruturas de repetio, como veremos adiante. Com o que aprendemos at o momento, bem fcil escrever um programa como esse.
#include <stdio.h>
/* Escreve os 10 primeiros nmeros inteiros positivos na sada */
int main(void)
{
printf("1\n");
printf("2\n");
printf("3\n");
printf("4\n");
printf("5\n");
printf("6\n");
printf("7\n");
printf("8\n");
printf("9\n");
printf("10\n");
return 0;
}
59
60
E STRUTURA
DE REPETIO
while
Alm de bem simples, o programa acima est correto, isto , realiza corretamente o propsito de imprimir os dez primeiros nmeros inteiros positivos na sada. Mas e se quisssemos, por exemplo, imprimir os 1000 primeiros nmeros inteiros positivos? Um programa
semelhante ao que acabamos de apresentar ficaria um pouco mais complicado e montono de
escrever, j que teria muitas e muitas linhas de cdigo.
Uma das propriedades fundamentais dos computadores, talvez a que mais nos auxilia,
que eles possuem a capacidade de executar repetitivamente um conjunto de instrues. Essa
capacidade de repetio permite que um(a) desenvolvedor(a)/programador(a) escreva algoritmos e programas mais concisos, contendo processos repetitivos que poderiam necessitar de
centenas ou milhares de linhas se no fossem assim descritos. Na linguagem C podemos ter
trs estruturas de repetio diferentes. A seguir veremos a estrutura de repetio while , mais
simples, mais didtica, mais ilustrativa e provavelmente a mais usada estrutura de repetio
da linguagem C.
while (condio) {
instruo1 ;
instruo2 ;
.
.
.
instruon ;
}
onde while uma palavra-chave da linguagem C, condio uma expresso lgica envolvida por parnteses que avaliada e possui o valor verdadeiro ou falso, instruo1 a
instruon fazem parte do bloco de instrues da estrutura de repetio while com as chaves { e } delimitando esse bloco de instrues. Do mesmo modo como vimos nas estruturas
condicionais, se o bloco de instrues associado estrutura de repetio while tem uma nica
instruo, esses delimitadores so opcionais.
A estrutura de repetio while funciona da seguinte forma. Quando um programa encontra a palavra-chave while , a expresso descrita na condio avaliada. Se o resultado
da avaliao dessa expresso verdadeiro, o programa desvia seu fluxo de execuo para o
bloco de instrues interno estrutura de repetio. Ento, as instrues so executadas uma
a uma at a ltima delas. Quando o programa atinge o final do bloco de instrues, o fluxo
de execuo desviado para a linha que contm a palavra-chave while e a expresso novamente avaliada. Se o resultado verdadeiro, as instrues so todas executadas novamente e
o processo se repete. Caso contrrio, isto , se o resultado da avaliao da expresso falso, o
fluxo de execuo do programa desviado para a primeira instruo aps o bloco de instrues
envolvido por chaves.
Veja o programa 6.1 para um exemplo de uso da estrutura de repetio while .
FACOM
UFMS
6.2 E STRUTURA
DE REPETIO
while
61
Exerccios
6.1 Dado um inteiro positivo n, somar os n primeiros inteiros positivos.
Programa 6.2: Programa para o exerccio 6.1.
#include <stdio.h>
/* Recebe um nmero inteiro n > 0 e mostra a soma dos n primeiros nmeros inteiros positivos */
int main(void)
{
int n, numero, soma;
printf("Informe n: ");
scanf("%d", &n);
soma = 0;
numero = 1;
while (numero <= n) {
soma = soma + numero;
numero = numero + 1;
}
printf("Soma dos %d primeiros inteiros %d\n", n, soma);
return 0;
}
UFMS
62
E STRUTURA
DE REPETIO
while
FACOM
UFMS
AULA
E XPRESSES
COM INTEIROS
Nesta aula veremos expresses aritmticas, relacionais e lgicas com nmeros inteiros. Em
aulas anteriores j tomamos contato com essas expresses, mas pretendemos formaliz-las
aqui. A compreenso destas expresses com nmeros inteiros fundamental para que possamos escrever programas mais eficientes e poderosos e tambm porque podemos estender
esse entendimento a outros tipos de variveis. Importante destacar que a linguagem C no tem
um tipo lgico primitivo, que ento simulado atravs do tipo inteiro, como veremos.
Esta aula baseada nas referncias [15, 16].
64
E XPRESSES
COM INTEIROS
Suponha ainda que as seguintes atribuies de valores constantes tenham sido executadas sobre essas variveis:
x = 1;
y = 2;
a = 5;
soma = 100;
parcela = 134;
2 * x * x + 5 * -x - +4
soma + parcela % 3
4 * 1002 - 4412 % 11 * -2 + a
(((204 / (3 + x)) * y) - ((y % x) + soma))
De acordo com os valores das inicializaes das variveis envolvidas e o resultado da avaliao
das prprias expresses, a avaliao de cada uma das linhas acima tem valores 7, 102, 4037 e
202, respectivamente.
A tabela abaixo, contendo as prioridades dos operadores aritmticos unrios e binrios, j
foi exibida em parte na aula 5.
Operadores
+ * / %
+ -
Tipo
unrios
binrios
binrios
Descrio
constante positiva, troca de sinal
produto, quociente da diviso e resto da diviso
adio e subtrao
Precedncia
1 (mxima)
2
3 (mnima)
UFMS
7.3 E XPRESSES
65
LGICAS
Operador
==
!=
<
>
<=
>=
Descrio
igual a
diferente de
menor que
maior que
menor que ou igual a
maior que ou igual a
int a, b, c;
a = 2;
b = 3;
c = 4;
a
a
b
b
== 2
> b + c
+ c <= 5 - a
!= 3
UFMS
66
E XPRESSES
COM INTEIROS
uma relao, uma varivel do tipo inteiro ou uma constante do tipo inteiro. Uma expresso
condicional ou lgica, ou ainda booleana formada por uma ou mais proposies. Neste
ltimo caso, relacionamos as proposies atravs de operadores lgicos. Os operadores lgicos
da linguagem C utilizados como conectivos nas expresses lgicas so apresentados a seguir.
Operador
&&
||
!
Descrio
conjuno
disjuno
negao
Duas proposies p e q podem ser combinadas pelo conectivo && para formar uma nica
proposio denominada conjuno das proposies originais: p && q e lemos p e q . O
resultado da avaliao da conjuno de duas proposies verdadeiro se e somente se ambas
as proposies tm valor verdadeiro, como mostra a tabela a seguir.
p
p && q
1
1
0
0
1
0
1
0
1
0
0
0
Duas proposies p e q podem ser combinadas pelo conectivo || para formar uma nica
proposio denominada disjuno das proposies originais: p || q e lemos p ou q ,
com sentido de e/ou. O resultado da avaliao da disjuno de duas proposies verdadeiro
se pelo menos uma das proposies tem valor verdadeiro, como mostra a tabela a seguir.
p
p || q
1
1
0
0
1
0
1
0
1
1
1
0
Dada uma proposio p , uma outra proposio, chamada negao de p , pode ser obtida
atravs da insero do smbolo ! antes da proposio: !p e lemos no p . Se a proposio
p tem valor verdadeiro, ento !p tem valor falso e se p tem valor falso, ento a proposio
!p tem valor verdadeiro, como mostra a tabela a seguir.
p
!p
1
0
0
1
Exemplos de expresses lgicas so mostrados a seguir. Inicialmente, suponha que declaramos as variveis do tipo inteiro a seguir:
int a, b, c, x;
UFMS
7.3 E XPRESSES
a
b
c
x
=
=
=
=
67
LGICAS
2;
3;
4;
1;
5
a
!x
a == 2 && a < b + c
b + c >= 5 - a || b != 3
a + b > c || 2 * x == b && 4 < x
a == 2 && a + x > b + c
2 == 2 && 3 > 3 + 4
2 == 2 && 3 > 7
1 && 0
1
A tabela abaixo ilustra a prioridade de todos os operadores aritmticos, relacionais e lgicos, unrios e binrios, vistos at aqui.
Operador
+ * / %
+ == != >= <= > <
!
&&
||
Tipo
unrios
binrios
binrios
binrios
unrio
binrio
binrio
Precedncia
1 (mxima)
2
3
4
5
6
7 (mnima)
UFMS
68
E XPRESSES
COM INTEIROS
Observe que, como o operador lgico de conjuno && tem prioridade sobre o operador
lgico de disjuno || , o resultado da expresso acima verdadeiro. Se tivssemos realizado a
disjuno primeiramente, como poderamos intuitivamente supor devido ao posicionamento
mais esquerda do operador de disjuno, o resultado da expresso seria diferente.
Exerccios
Alguns exerccios desta aula ensinam um importante truque de programao que , na verdade, o uso de uma varivel que simula um tipo lgico e que indica que algo ocorreu durante
a execuo do programa. Essa varivel chamada de indicadora de passagem.
FACOM
UFMS
7.3 E XPRESSES
69
LGICAS
Programa 7.2: Soluo para o exerccio 7.1 usando uma varivel indicadora de passagem.
#include <stdio.h>
/* Recebe um inteiro positivo p e verifica se p primo */
int main(void)
{
int p, divisor, primo;
printf("Informe um nmero: ");
scanf("%d", &p);
divisor = 2;
primo = 1;
while (divisor <= p/2 && primo == 1) {
if (p % divisor == 0)
primo = 0;
else
divisor = divisor + 1;
}
if (primo == 1)
printf("%d primo\n", p);
else
printf("%d no primo\n", p);
return 0;
}
FACOM
UFMS
70
E XPRESSES
COM INTEIROS
7.2 Dado um nmero inteiro positivo n e uma seqncia de n nmeros inteiros, verificar se a
seqncia est em ordem crescente.
7.3 Dados um nmero inteiro n > 0 e um dgito d, com 0 6 d 6 9, determinar quantas vezes
o dgito d ocorre no nmero n.
7.4 Dado um nmero inteiro positivo n, verificar se este nmero contm dois dgitos consecutivos iguais.
7.5 Dado um nmero inteiro positivo n, verificar se o primeiro e o ltimo dgito deste nmero
so iguais.
7.6 Dado um nmero inteiro positivo n e dois nmeros naturais no nulos i e j, imprimir em
ordem crescente os n primeiros naturais que so mltiplos de i ou de j ou de ambos.
Exemplo:
Para n = 6, i = 2 e j = 3 a sada dever ser 0, 2, 3, 4, 6, 8.
7.7 Dizemos que um nmero natural triangular se produto de trs nmeros naturais
consecutivos.
Exemplo:
120 triangular, pois 4 5 6 = 120.
Dado n natural, verificar se n triangular.
7.8 Dados dois nmeros inteiros positivos, determinar o mximo divisor comum entre eles
utilizando o algoritmo de Euclides.
Exemplo:
24
9
1
15
6
1
9
3
1
6
0
2
3
= mdc(24,15)
7.9 Dados dois nmeros inteiros positivos a e b, representando a frao a/b, escreva um programa que reduz a/b para uma frao irredutvel.
Exemplo:
Se a entrada 9/12 a sada tem de ser 3/4.
7.10 Dados a quantidade de dias de um ms e o dia da semana em que o ms comea, escreva
um programa que imprima os dias do ms por semana, linha a linha. Considere o dia
da semana 1 como domingo, 2 como segunda-feira, e assim por diante, at o dia 7 como
sbado.
Exemplo:
Se a entrada 31 e 3 ento a sada deve ser
6
13
20
27
FACOM
7
14
21
28
1
8
15
22
29
2
9
16
23
30
3
10
17
24
31
4
11
18
25
5
12
19
26
UFMS
7.3 E XPRESSES
LGICAS
71
7.11 Dados um nmero inteiro n e n seqncias de nmeros inteiros, cada qual terminada por
0, determinar a soma dos nmeros pares de cada seqncia.
7.12 Dados um nmero inteiro n > 0 e uma seqncia de n nmeros inteiros positivos determinar o fatorial de cada nmero da seqncia.
7.13 Dados n nmeros inteiros positivos, calcular a soma dos que so primos.
7.14 Dado um nmero inteiro positivo n, determinar todos os inteiros entre 1 e n que so
comprimento de hipotenusa de um tringulo retngulo com catetos inteiros.
7.15 Dados dois naturais m e n, determinar, entre todos os pares de nmeros naturais (x, y)
tais que x 6 m e y 6 n, um par para o qual o valor da expresso xy x2 + y seja mximo
e calcular tambm esse mximo.
7.16 Sabe-se que um nmero da forma n3 igual soma de n nmeros mpares consecutivos.
Exemplo:
13
23
33
43
..
.
=1
=3+5
= 7 + 9 + 11
= 13 + 15 + 17 + 19
FACOM
UFMS
72
FACOM
E XPRESSES
COM INTEIROS
UFMS
AULA
O UTRAS
ESTRUTURAS DE REPETIO
74
O UTRAS
ESTRUTURAS DE REPETIO
int cont;
cont = 1;
printf("cont vale %d\n", ++cont);
printf("cont vale %d\n", cont);
imprime cont vale 2 e cont vale 2 em duas linhas consecutivas na sada. Por outro lado,
o trecho de cdigo abaixo:
int cont;
cont = 1;
printf("cont vale %d\n", cont++);
printf("cont vale %d\n", cont);
UFMS
8.2 E STRUTURA
DE REPETIO
do-while
75
UFMS
76
O UTRAS
ESTRUTURAS DE REPETIO
O programa 8.3 muito semelhante aos demais programas que vimos construindo at o momento. A principal e mais significativa diferena o uso da estrutura de repetio do-while .
Quando o programa encontra essa estrutura pela primeira vez, com uma linha contendo a
palavra-chave do , o fluxo de execuo segue para a primeira instruo do bloco de instrues
dessa estrutura, envolvido por chaves. As instrues desse bloco so ento executados uma a
uma, at o fim do bloco. Logo em seguida, aps o fim do bloco com o caractere } , encontramos
a palavra-chave while e, depois, entre parnteses, uma expresso lgica. Se o resultado da
avaliao dessa expresso lgica for verdadeiro, ento o fluxo de execuo do programa desviado para a primeira instruo do bloco de instrues desta estrutura de repetio e todas as
instrues so executadas novamente. Caso contrrio, se o resultado da avaliao da expresso
lgica falso, o fluxo de execuo desviado para a prxima instruo aps a linha contendo
o final do bloco de execuo desta estrutura de repetio.
Note ainda que o teste de continuidade desta estrutura de repetio realizado sempre no
final, aps todas as instrues de seu bloco interno de instrues terem sido executadas. Isso
significa que esse bloco de instrues ser executado ao menos uma vez. Neste sentido, esta
estrutura de repetio do-while difere das outras estruturas de repetio while e for que
vimos anteriormente, j que nesses dois ltimos casos o resultado da avaliao da expresso
lgica associada a essas estruturas pode fazer com que seus blocos de instrues respectivos
no sejam executados nem mesmo uma nica vez.
Exerccios
8.1 Qualquer nmero natural de quatro algarismos pode ser dividido em duas dezenas formadas pelos seus dois primeiros e dois ltimos dgitos.
Exemplos:
FACOM
UFMS
8.2 E STRUTURA
DE REPETIO
do-while
77
1297: 12 e 97.
5314: 53 e 14.
Escreva um programa que imprima todos os nmeros de quatro algarismos cuja raiz
quadrada seja a soma das dezenas formadas pela diviso acima.
Exemplo:
9801 = 99 = 98 + 01.
Portanto, 9801 um dos nmeros a ser impresso.
Programa 8.4: Soluo do exerccio 8.1.
#include <stdio.h>
/* Imprime os nmeros inteiros positivos de 4 dgitos cuja raiz quadrada igual soma dos seus dois primeiros e dois ltimos dgitos */
int main(void)
{
int numero, DD, dd;
for (numero = 1000; numero <= 9999; numero++) {
DD = numero / 100;
dd = numero % 100;
if ( (DD + dd) * (DD + dd) == numero )
printf("%d\n", numero);
}
return 0;
}
8.2 Dado um nmero inteiro no-negativo n, escreva um programa que determine quantos
dgitos o nmero n possui.
Programa 8.5: Soluo do exerccio 8.8.
/* Recebe um inteiro e imprime a quantidade de dgitos que possui */
#include <stdio.h>
int main(void)
{
int n, digitos;
printf("Informe n: ");
scanf("%d", n);
do {
n = n / 10;
digitos++;
} while (n > 0);
printf("O nmero tem %d dgitos\n", digitos);
return 0;
}
FACOM
UFMS
78
O UTRAS
ESTRUTURAS DE REPETIO
8.3 Dado um nmero natural na base binria, transform-lo para a base decimal.
Exemplo:
Dado 10010 a sada ser 18, pois 1 24 + 0 23 + 0 22 + 1 21 + 0 20 = 18.
8.4 Dado um nmero natural na base decimal, transform-lo para a base binria.
Exemplo:
Dado 18 a sada dever ser 10010.
8.5 Dado um nmero inteiro positivo n que no contm um dgito 0, imprimi-lo na ordem
inversa de seus dgitos.
Exemplo:
Dado 26578 a sada dever ser 87562.
8.6 Dizemos que um nmero natural n com pelo menos 2 algarismos palndromo se
o primeiro algarismo de n igual ao seu ltimo algarismo;
o segundo algarismo de n igual ao se penltimo algarismo;
e assim sucessivamente.
Exemplos:
567765 palndromo;
32423 palndromo;
567675 no palndromo.
Dado um nmero natural n, n > 10, verificar se n palndromo.
8.7 Dados um nmero inteiro n > 0 e uma seqncia de n nmeros inteiros, determinar
quantos segmentos de nmeros iguais consecutivos compem essa seqncia.
Exemplo:
z}|{ z }| { z }| { z}|{
Para n = 9, a seqncia 5 , 2, 2, 4, 4, 4, 4, 1, 1 formada por 4 segmentos
de nmeros iguais.
8.8 Dados um nmero inteiro n > 0 e uma seqncia de n nmeros inteiros, determinar o
comprimento de um segmento crescente de comprimento mximo.
Exemplos:
z }| {
Na seqncia 5, 10, 6, 2, 4, 7, 9, 8, 3 o comprimento do segmento crescente mximo 4.
Na seqncia 10, 8, 7, 5, 2 o comprimento do segmento crescente mximo 1.
FACOM
UFMS
AULA
N MEROS
float x, y;
double arco;
80
N MEROS
Maior valor
3.40282 1038
1.79769 10308
Preciso
6 dgitos
15 dgitos
O padro IEEE 754 estabelece dois formatos primrios para nmeros de ponto flutuante:
o formato de preciso simples, com 32 bits, e o formato de preciso dupla, com 64 bits. Os
nmeros de ponto flutuante so armazenados no formato de notao cientfica, composto por
trs partes: um sinal, um expoente e uma frao. O nmero de bits reservado para representar o
expoente determina quo grande o nmero pode ser, enquanto que o nmero de bits da frao
determina sua preciso.
Um exemplo de um programa que usa constantes e variveis do tipo float apresentado
no programa 9.1. Neste programa, uma seqncia de cem nmeros do tipo ponto flutuante
informada pelo usurio. Em seguida, a mdia aritmtica desses nmeros calculada e, por fim,
mostrada na sada padro.
Programa 9.1: Calcula a mdia de 100 nmeros do tipo ponto flutuante.
#include <stdio.h>
/* Recebe uma seqncia de 100 nmeros reais e mostra a mdia desses nmeros */
int main(void)
{
int i;
float numero, soma, media;
soma = 0.0;
for (i = 1; i <= 100; i++) {
printf("Informe um nmero: ");
scanf("%f", &numero);
soma = soma + numero;
}
media = soma / 100;
printf("A mdia dos 100 nmeros %f\n", media);
return 0;
}
Instituto de Engenheiros Eltricos e Eletrnicos, do ingls Institute of Electrical and Eletronics Engineers (IEEE).
FACOM
UFMS
9.2 E XPRESSES
ARITMTICAS
81
i2);
f2);
f2);
f2);
i2
f2
f2
f2
=
=
=
=
1
1.000000
1.900000
1.005000
UFMS
82
N MEROS
Suponha, no entanto, que um programa semelhante, o programa 9.3, tenha sido desenvolvido, compilado e executado.
Programa 9.3: Operaes e tipos inteiro e de ponto flutuante.
#include <stdio.h>
int main(void)
{
int i1, i2;
float f1;
i1 = 3;
i2 = 2;
f1 = i1 / i2;
printf("f1 = %f\n", f1);
return 0;
}
f1 = 1.000000
Mas e se quisssemos que a diviso i1/ i2 tenha como resultado um valor do tipo ponto
flutuante? Neste caso, devemos usar um operador unrio chamado operador conversor de
tipo, do ingls type cast operator, sobre alguma das variveis da expresso. No caso acima,
poderamos usar qualquer uma das atribuies abaixo:
f1 = 1.500000
UFMS
9.2 E XPRESSES
ARITMTICAS
83
i1
i2
i3
i4
=
=
=
=
7
6
10
10
UFMS
84
N MEROS
Exerccios
9.1 Uma pessoa aplicou um capital de x reais a juros mensais de y% durante 1 ano. Determinar o montante de cada ms durante este perodo.
9.2 Os pontos (x, y) que pertencem figura H (veja a figura 9.1) so tais que x > 0, y > 0 e
x2 + y 2 6 1. Dados n pontos reais (x, y), verifique se cada ponto pertence ou no a H.
FACOM
UFMS
9.2 E XPRESSES
85
ARITMTICAS
1111111111
0000000000
0000000000
1111111111
0000000000
1111111111
0000000000
1111111111
0000000000
1111111111
H
0000000000
1111111111
0000000000
1111111111
0000000000
1111111111
0000000000x
1111111111
Dado um nmero inteiro n > 0, leia uma seqncia de n pontos reais (x, y) e verifique se
cada ponto pertence ou no ao conjunto H, contando o nmero de pontos da seqncia
que pertencem a H.
9.4 Dado um natural n, determine o nmero harmnico Hn definido por
n
X
1
.
Hn =
k
k=1
9.5 Para n > 0 alunos de uma determinada turma so dadas 3 notas de provas. Calcular a
mdia aritmtica das provas de cada aluno, a mdia da classe, o nmero de aprovados e
o nmero de reprovados, onde o critrio de aprovao mdia > 5.0.
9.6 Dados nmeros reais a, b e c, calcular as razes de uma equao do 2o grau da forma
ax2 + bx + c = 0. Imprimir a soluo em uma das seguintes formas:
FACOM
UFMS
86
N MEROS
a.
DUPLA
raiz
b.
REAIS DISTINTAS
raiz 1
raiz 2
c.
COMPLEXAS
parte real
parte imaginria
1 1 1
1
1
+ + ... +
2 3 4
9999 10000
4 4 4 4
4
+ +
+ ...
3 5 7 9 11
Escreva um algoritmo que calcule e imprima o valor de atravs da srie acima, com
preciso de 4 casas decimais. Para obter a preciso desejada, adicionar apenas os termos
cujo valor absoluto seja maior ou igual a 0.0001.
9.10 Dado um nmero real x tal que 0 6 x 6 1, calcular uma aproximao do arco tangente
de x em radianos atravs da srie infinita:
arctan x = x
x3 x5 x7
+
+ ...
3
5
7
x1 x2 x3
+
+
+ ...
1!
2!
3!
k
Dados dois nmeros reais x e , calcular o valor de ex incluindo todos os termos Tk = xk! ,
com k > 0, at que Tk < . Mostre na sada o valor computado e o nmero total de termos
usados na srie.
9.12 Dados x real e n natural, calcular uma aproximao para cos x, onde x dado em radianos, atravs dos n primeiros termos da seguinte srie:
cos x = 1
x2k
x2 x4 x6
+
+ . . . + (1)k
+ ...
2!
4!
6!
(2k)!
UFMS
9.2 E XPRESSES
87
ARITMTICAS
9.13 Dados x e reais, > 0, calcular uma aproximao para sen x, onde x dado em radianos,
atravs da seguinte srie infinita
sen x =
x
x3 x5
x2k+1
+
. . . + (1)k
+ ...
1!
3!
5!
(2k + 1)!
FACOM
x2k+1
(2k+1)! ,
UFMS
88
FACOM
N MEROS
UFMS
AULA
10
C ARACTERES
Nesta aula vamos estudar um novo tipo primitivo de dados, o tipo caractere. O tipo caractere um tipo primitivo que podemos trabalhar com um conjunto pequeno e previsvel de
valores. Na linguagem C existem dois tipos de caracteres: caractere com sinal e caractere sem
sinal. Esses dois tipos so apenas interpretaes diferentes do conjunto de todas as seqncias
de 8 bits, sendo que essa diferena irrelevante na prtica. O estudo dos caracteres ser estendido, mais til e melhor compreendido na aula 13, quando veremos as cadeias de caracteres.
Esta aula baseada especialmente nas referncias [15, 16].
89
90
C ARACTERES
Dos 128 caracteres padronizados da tabela ASCII e de seus smbolos grficos correspondentes, 33 deles so no-imprimveis e os restantes 95 so imprimveis. Os caracteres noimprimveis so caracteres de controle, criados nos primrdios da computao, quando se usavam mquinas teletipo e fitas de papel perfurado, sendo que atualmente grande parte deles
esto obsoletos. Na tabela a seguir, apresentamos alguns desses caracteres no-imprimveis.
Muitos deles no so mostrados por opo ou por terem cado em desuso.
Bin
0000 0000
0000 0111
0000 1001
0000 1010
0000 1011
0000 1100
0000 1101
0111 1111
Dec
00
07
09
10
11
12
13
127
Significado
Nulo
Campainha
Tabulao horizontal
Mudana de linha
Tabulao vertical
Quebra de pgina
Retorno do carro/cursor
Delete
Dec
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
Sim
!
"
#
$
%
&
(
)
*
+
,
.
/
0
1
2
3
4
5
6
7
8
9
:
;
<
=
>
?
Bin
0100 0000
0100 0001
0100 0010
0100 0011
0100 0100
0100 0101
0100 0110
0100 0111
0100 1000
0100 1001
0100 1010
0100 1011
0100 1100
0100 1101
0100 1110
0100 1111
0101 0000
0101 0001
0101 0010
0101 0011
0101 0100
0101 0101
0101 0110
0101 0111
0101 1000
0101 1001
0101 1010
0101 1011
0101 1100
0101 1101
0101 1110
0101 1111
Dec
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
Sim
@
A
B
C
D
E
F
G
H
I
J
K
L
M
N
O
P
Q
R
S
T
U
V
W
X
Y
Z
[
\
]
^
_
Bin
0110 0000
0110 0001
0110 0010
0110 0011
0110 0100
0110 0101
0110 0110
0110 0111
0110 1000
0110 1001
0110 1010
0110 1011
0110 1100
0110 1101
0110 1110
0110 1111
0111 0000
0111 0001
0111 0010
0111 0011
0111 0100
0111 0101
0111 0110
0111 0111
0111 1000
0111 1001
0111 1010
0111 1011
0111 1100
0111 1101
0111 1110
Dec
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
Sim
a
b
c
d
e
f
g
h
i
j
k
l
m
n
o
p
q
r
s
t
u
v
w
x
y
z
{
|
}
~
UFMS
10.2 C ONSTANTES
E VARIVEIS
91
Os caracteres com sinal, quando dispostos em ordem crescente, apresentam-se de tal forma
que as letras acentuadas precedem as no-acentuadas. Os caracteres sem sinal, ao contrrio, em
ordem crescente apresentam-se de forma que as letras no-acentuadas precedem as acentuadas.
Essa a nica diferena entre caracteres com e sem sinal.
char c, d, e;
unsigned char f, g, h;
c = 122;
d = 59;
e = 51;
Mais comum e confortavelmente, podemos especificar uma constante do tipo caractere atravs da representao grfica de um caractere, envolvendo-o por aspas simples. Por exemplo,
z , ; e 3 so exemplos de constantes do tipo caractere. Assim, bem mais cmodo
fazer as atribuies
c = z;
d = ;;
e = 3;
UFMS
92
C ARACTERES
caractere
0
9
10
11
12
13
32
55
92
97
constante
\0
\t
\n
\v
\f
\r
7
\\
a
smbolo grfico
caractere nulo
tabulao horizontal
mudana de linha
tabulao vertical
quebra de pgina
retorno do carro/cursor
espao
7
\
a
Na linguagem C, um branco (do ingls whitespace) definido como sendo um caractere que
uma tabulao horizontal, uma mudana de linha, uma tabulao vertical, uma quebra de
pgina, um retorno de carro/cursor e um espao. Ou seja, os caracteres 9, 10, 11, 12, 13 e 32
so brancos e as constantes correspondentes so \t , \n , \v , \f , \r e .
A funo scanf trata todos os brancos como se fossem , assim como outras funes da
linguagem C tambm o fazem.
Para imprimir um caractere na sada padro com a funo printf devemos usar o especificador de converso de tipo caractere %c na seqncia de caracteres de formatao. Para ler
um caractere a partir da entrada padro com a funo scanf tambm devemos usar o mesmo
especificador de converso de tipo caractere %c na seqncia de caracteres de formatao. Um
exemplo de uso do tipo bsico caractere mostrado no programa 10.1.
Programa 10.1: Um programa usando o tipo char .
#include <stdio.h>
int main(void)
{
char c;
c = a;
printf("%c\n", c);
c = 97;
printf("%c\n", c);
printf("Informe um caractere: ");
scanf("%c", &c);
printf("%c = %d\n", c, c);
return 0;
}
Como vimos at aqui nesta seo, por enquanto no h muita utilidade para constantes
e variveis do tipo caractere. Mas em breve iremos us-las para construir um tipo de dados
muito importante chamado de cadeia de caracteres.
FACOM
UFMS
10.3 E XPRESSES
COM CARACTERES
93
unsigned char x, y, z;
x = 240;
y = 65;
z = x + y;
Na ltima linha o resultado da expresso x + y 305 . No entanto, atribuies de nmeros inteiros a variveis do tipo caractere so feitas mdulo 256. Por isso, a varivel z acima
receber o valor 49 .
Do mesmo modo, aps a execuo do trecho de cdigo a seguir:
unsigned char x;
char c;
x = 256;
c = 136;
.
.
.
char c;
c = a;
if (a <= c && c <= z)
c = c - ;
printf("%c = %d\n", c, c);
if (65 <= c && c <= 122)
c = c + a;
printf("%c = %d\n", c, c);
.
.
.
Tente verificar a sada gerada pelas duas chamadas da funo printf no trecho de cdigo
acima.
FACOM
UFMS
94
C ARACTERES
Exerccios
10.1 Verifique se o programa 10.2 est correto.
Programa 10.2: O que faz este programa?
#include <stdio.h>
int main(void)
{
char c;
for (c = 0; c < 128; c++)
printf(".");
printf("\ntchau!\n");
return 0;
}
10.2 Escreva um programa que imprima todas as letras minsculas e todas as letras maisculas do alfabeto.
10.3 Escreva um programa que traduz um nmero de telefone alfabtico de 8 dgitos em um
nmero de telefone na forma numrica. Suponha que a entrada sempre dada em caracteres maisculos.
Exemplo:
Se a entrada URGENCIA a sada deve ser 87436242 .
1111FOGO a sada deve ser 11113646 .
Se a entrada
Se voc no possui um telefone, ento as letras que correspondem s teclas so as seguintes: 2=ABC, 3=DEF, 4=GHI, 5=JKL, 6=MNO, 7=PQRS, 8=TUV e 9=WXYZ.
10.4 Scrabble um jogo de palavras em que os jogadores formam palavras usando pequenos
quadrados que contm uma letra e um valor. O valor varia de uma letra para outra, baseado na sua raridade. Os valores so os seguintes: AEILNORSTU=1, DG=2, BCMP=3,
FHVWY=4, K=5, JX=8 e QZ=10.
Escreva um programa que receba uma palavra e compute o seu valor, somando os valores de suas letras. Seu programa no deve fazer distino entre letras maisculas e
minsculas.
Exemplo:
Se a palavra de entrada programa a sada tem de ser 13 .
10.5 Escreva um programa que receba dois nmeros inteiros a e b e um caractere op, tal que
op pode ser um dos cinco operadores aritmticos disponveis na linguagem C ( + , - , * ,
/ , % ), realize a operao a op b e mostre o resultado na sada.
FACOM
UFMS
AULA
T IPOS
11
PRIMITIVOS DE DADOS
Como vimos at esta aula, a linguagem C suporta fundamentalmente dois tipos de dados
numricos: tipos inteiros e tipos com ponto flutuante. Valores do tipo inteiro so nmeros
inteiros em um dado intervalo finito e valores do tipo ponto flutuante so tambm dados em
um intervalo finito e podem ter uma parte fracionria. Alm desses, o tipo caractere tambm
suportado pela linguagem e um valor do tipo caractere tambm um nmero inteiro em um
intervalo finito mais restrito que o dos tipos inteiros.
Nesta aula faremos uma reviso dos tipos primitivos de dados da linguagem C e veremos os
especificadores desses tipos, seus especificadores de converso para entrada e sada de dados,
as converses entre valores de tipos distintos, alm de definir nossos prprios tipos. Esta aula
uma reviso das aulas sobre o tipo inteiro (aula 7), o tipo ponto flutuante (aula 9) e o tipo
carctere, que vimos em conjunto com nas aulas tericas da disciplina. tambm uma extenso
desses conceitos, podendo ser usada como uma referncia para tipos primitivos de dados.
As referncias usadas nesta aula so [15, 16].
96
T IPOS
PRIMITIVOS DE DADOS
short int
unsigned short int
int
unsigned int
long int
unsigned long int
Qualquer outra combinao de especificadores na declarao de uma varivel equivalente a uma das combinaes acima. A ordem que os especificadores ocorrem no tem
influncia sobre o resultado final: declaraes feitas com unsigned short int ou com
short unsigned int tm o mesmo resultado. Quando no estritamente necessrio, a
linguagem C permite que a palavra reservada int seja omitida, como por exemplo em
unsigned short e long .
O intervalo de valores representado por cada um dos seis tipos inteiros varia de uma mquina para outra. Os compiladores, entretanto, devem obedecer algumas regras fundamentais.
Em especial, o padro especifica que o tipo int no seja menor que o tipo short int e que
long int no seja menor que int .
As mquinas mais atuais so de 64 bits e a tabela abaixo mostra os intervalos de cada um
dos possveis tipos inteiros. A principal diferena entre mquinas de 32 e de 64 bits est no
tipo long int . Em mquinas de 32 bits, o tipo long int e o tipo int so equivalentes. Em
mquinas de 64 bits, h diferenciao entre esses dois tipos, como apresentado abaixo.
Tipo
short int
unsigned short int
int
unsigned int
long int
unsigned long int
Menor valor
32.768
0
2.147.483.648
0
9.223.372.036.854.775.808
0
Maior valor
32.767
65.535
2.147.483.647
4.294.967.294
9.223.372.036.854.775.807
18.446.744.073.709.551.615
Constantes numricas, como vimos, so nmeros que ocorrem no cdigo dos programas,
em especial em expresses aritmticas. As constantes, assim como as variveis, podem ser
nmeros inteiros ou nmeros com ponto flutuante.
Na linguagem C, as constantes numricas do tipo inteiro podem ser descritas em decimal
ou base 10, octal ou base 8 ou ainda hexadecimal ou base 16. Constantes decimais contm
dgitos de 0 (zero) a 9 (nove), mas no devem iniciar com 0 (zero). Exemplos de constantes
decimais so mostrados a seguir:
75
-264
32767
Constantes octais contm somente dgitos entre 0 (zero) e 7 (sete) e devem comear necessariamente com o dgito 0 (zero). Exemplos de constantes octais so mostrados a seguir:
075
FACOM
0367
07777
UFMS
11.1 T IPOS
97
INTEIROS
E constantes hexadecimais contm dgitos entre 0 (zero) e 9 (nove) e letras entre a e f, e sempre
devem iniciar com os caracteres 0x. As letras podem ser maisculas ou minsculas. Exemplos
de constantes hexadecimais so mostrados a seguir:
0xf
0x8aff
0X12Acf
importante destacar que a descrio de constantes como nmeros na base octal e hexadecimal apenas uma forma alternativa de escrever nmeros que no tem efeito na forma como
so armazenados na memria, j que sempre so armazenados na base binria. Alm disso,
essas notaes so mais usadas quando trabalhamos com programas de baixo nvel.
No h necessidade de se convencionar uma nica notao para escrever constantes e podemos trocar de uma notao para outra a qualquer momento. Na verdade, podemos inclusive
misturar essas notaes em expresses aritmticas como a seguir:
22L
055l
0xffffL
Para indicar que uma constante do tipo inteiro no tem sinal, devemos adicionar a letra
U ou u ao final da constante. Por exemplo, as constantes apresentadas abaixo so do tipo
unsigned int :
22u
072U
0xa09DU
Podemos indicar que uma constante um nmero inteiro grande e sem sinal usando uma
combinao das letras acima, em qualquer ordem. Por exemplo, as constantes abaixo so do
tipo unsigned long int :
FACOM
UFMS
98
T IPOS
22ul
07777UL
PRIMITIVOS DE DADOS
0xFFFFAALU
A funo printf usada para imprimir, entre outros, nmeros inteiros. Relembrando, a
funo printf tem o seguinte formato:
printf(cadeia, expresso 1, expresso 2, . . .);
Especificador de converso
%hd ou %hi
%hu
%d ou %i
%u
%ld ou %li
%lu
%[flags][comprimento][.preciso][hl]conversor
Os campos opcionais so mostrados entre colchetes. Ou seja, apenas conversor obrigatrio, que chamamos de especificador de converso. A tabela a seguir mostra os possveis
flags para um especificador de converso de uma cadeia de caracteres de formatao da funo
printf .
Flag
+
espaos
0
FACOM
Significado
Valor alinhado esquerda
Valor precedido por + ou Valor positivo precedido por espaos
Nmero preenchido com zeros esquerda
UFMS
11.1 T IPOS
INTEIROS
99
=
=
=
=
=
=
159;
630u;
-991023;
98979U;
8393202L;
34268298UL;
Assim como para a funo printf , outras opes de formatao tambm esto disponveis
para a funo scanf , mais que aquelas vistas at esta aula. Neste caso tambm vale o conceito
de especificadores de converso. Quando uma funo scanf executada, especificadores de
converso so procurados na cadeia de caracteres de formatao (de leitura), aps o smbolo
usual % .
Os especificadores de converso h e l podem ser usados em uma cadeia de caracteres de
formatao de leitura, juntamente com a chamada da funo scanf , com o mesmo sentido que
na cadeia de caracteres de formatao de escrita, na funo printf , isto , para indicar que a
leitura ser feita como um nmero inteiro curto ou longo, respectivamente. Um comprimento
tambm pode ser usado, indicando o comprimento mximo do valor a ser armazenado na
varivel correspondente.
FACOM
UFMS
100
T IPOS
Especificador
PRIMITIVOS DE DADOS
Significado
valor a ser lido expresso em notao decimal; o argumento correspondente do tipo
int, a menos que os modificadores de converso h ou l tenham sido usados, casos
em que o valor ser short int ou long int, respectivamente
valor a ser lido expresso na notao octal e pode opcionalmente ser precedido por 0;
o argumento correspondente um int, a menos que os modificadores de converso
h ou l tenham sido usados, casos em que short int ou long int,
respectivamente
valor a ser lido expresso na notao hexadecimal e pode opcionalmente ser precedido
por 0x ou 0X; o argumento correspondente um unsigned int, a menos que os
modificadores de converso h ou l tenham sido usados, casos em que short int
ou long int, respectivamente
A funo scanf executada primeiro esperando por um valor a ser informado pelo usurio e, depois, formatando este valor atravs do uso da cadeia de caracteres de formatao e do
especificador de converso.
A funo scanf finaliza uma leitura sempre que o usurio informa um branco, que o
caractere 32 (espao ou ), o caractere 9 (tabulao horizontal ou \t ), o caractere 10
(tabulao vertical ou \v ), o caractere 11 (retorno de carro/cursor ou \r ), o caractere 12
(mudana de linha ou \n ) ou o caractere 13 (avano de pgina ou \f ). Nesse sentido,
considere uma entrada como no trecho de cdigo abaixo:
prompt$ ./a.out
4 7
ou
prompt$ ./a.out
4
7
ou ainda
prompt$ ./a.out
4
7
FACOM
UFMS
11.2 N MEROS
101
O tipo float usado quando a necessidade de preciso no crtica. O tipo double fornece maior preciso, suficiente para a maioria dos problemas. E o tipo long double fornece
a maior preciso possvel e raramente usado.
A linguagem C no estabelece padro para a preciso dos tipos com ponto flutuante, j
que diferentes computadores podem armazenar nmeros com ponto flutuante de formas diferentes. Os computadores mais recentes seguem, em geral, as especificaes do Padro 754 da
IEEE. A tabela abaixo, mostrada na aula 9, mostra as caractersticas dos tipos numricos com
ponto flutuante quando implementados sob esse padro.
Tipo
float
double
Maior valor
3.40282 1038
1.79769 10308
Preciso
6 dgitos
15 dgitos
Constantes com ponto flutuante podem ser descritas de diversas formas. Por exemplo, as
constantes abaixo so formas vlidas de escrever o nmero 391,0:
391.0
391.
391.0e0
391E0
3.91e+2
.391e3
3910.e-1
Uma constante com ponto flutuante deve conter um ponto decimal e/ou um expoente,
que uma potncia de 10 pela qual o valor multiplicado. Se um expoente dado, deve vir
precedido da letra e ou E . Opcionalmente, um sinal + ou - pode ocorrer logo aps a letra.
Por padro, constantes com ponto flutuante so armazenadas como nmeros de ponto flutuante de preciso dupla. Isso significa que, quando um compilador C encontra em um programa uma constante 391.0 , por exemplo, ele armazena esse nmero na memria no mesmo
formato de uma varivel do tipo double . Se for necessrio, podemos forar o compilador a
armazenar uma constante com ponto flutuante no formato float ou long double . Para indicar preciso simples basta adicionar a letra f ou F ao final da constante, como por exemplo
391.0f . Para indicar preciso estendida necessrio adicionar a letra l ou L ao final da
constante, como por exemplo 391.0L .
FACOM
UFMS
102
T IPOS
PRIMITIVOS DE DADOS
converso para nmeros com ponto flutuante parecido com aquele descrito na seo anterior,
como podemos observar abaixo:
%[flags][comprimento][.preciso][lL]conversor
O especificador de converso %e mostra/solicita um nmero com ponto flutuante no formato exponencial ou notao cientfica. A preciso indica quantos dgitos aps o ponto sero
mostrados/solicitados ao usurio, onde o padro 6. O especificador de converso %f mostra/solicita um nmero com ponto flutuante no formato com casas decimais fixas, sem expoente. A preciso indica o mesmo que para %e . E o especificador de converso %g mostra o
nmero com ponto flutuante no formato exponencial ou com casas decimais fixas, dependendo
de seu tamanho. Diferentemente dos especificadores anteriores, a preciso neste caso indica o
nmero mximo de dgitos significativos a ser mostrado/solicitado.
Ateno deve ser dispensada com pequenas diferenas na escrita e na leitura de nmeros
com ponto flutuante de preciso dupla e estendida. Quando da leitura de um valor do tipo
double necessrio colocar a letra l precedendo e , f ou g . Esse procedimento necessrio apenas na leitura e no na escrita. Quando da leitura de um valor do tipo long double
necessrio colocar a letra L precedendo e , f ou g .
11.3 Caracteres
Como mencionamos quando discutimos caracteres nas nossas aulas tericas e prticas, na
linguagem C cada caractere armazenado em um nico byte na memria do computador.
Assim, um caractere sem sinal um nmero do conjunto {0, . . . , 255} e um caractere com sinal
um nmero do conjunto {128, . . . , 1, 0, 1, . . . , 127}. Ou seja, um caractere uma seqncia
de 8 bits, dentre as 256 seqncias de 8 bits possveis. A impresso de um caractere na sada
padro a sua representao como um smbolo grfico. Por exemplo, o smbolo grfico do
caractere 97 a . Alguns caracteres tm representaes grficas especiais, como o caractere
10 que representado por uma mudana de linha.
Uma varivel do tipo caractere (com sinal) pode ser declarada na linguagem C com a palavra reservada char . Uma varivel do tipo caractere sem sinal pode ser declarada com a
mesma palavra reservada char , mas com o especificador de tipo unsigned a precedendo:
char c, d, e;
unsigned char f, g, h;
Uma constante do tipo caractere sem sinal um nmero no intervalo de 0 a 255 e uma
constante do tipo caractere com sinal uma constante no intervalo de 128 a 127. Por exemplo,
para as variveis c , d e e declaradas acima, podemos fazer
FACOM
UFMS
11.3 C ARACTERES
103
c = 122;
d = 59;
e = 51;
Mais comum e confortavelmente, podemos especificar uma constante do tipo caractere atravs da representao grfica de um caractere, envolvendo-o por aspas simples. Por exemplo,
z , ; e 3 so exemplos de constantes do tipo caractere. Assim, bem mais cmodo
fazer as atribuies
c = z;
d = ;;
e = 3;
constante
\0
\t
\n
\v
\f
\r
7
\\
a
smbolo grfico
caractere nulo
tabulao horizontal
mudana de linha
tabulao vertical
quebra de pgina
retorno do carro/cursor
espao
7
\
a
Na linguagem C, um branco (do ingls whitespace) definido como sendo um caractere que
uma tabulao horizontal, uma mudana de linha, uma tabulao vertical, uma quebra de
pgina, um retorno de carro/cursor ou um espao. Ou seja, os caracteres 9, 10, 11, 12, 13 e 32
so brancos e as constantes correspondentes so \t , \n , \v , \f , \r e . A
funo scanf trata todos os brancos como se fossem , assim como outras funes tambm
o fazem.
O especificador de converso %c permite que as funes scanf e printf possam ler ou
escrever um nico caractere. importante reiterar que a funo scanf no salta caracteres
brancos antes de ler um caractere. Se o prximo caractere a ser lido foi digitado como um
espao ou uma mudana de linha, ento a varivel correspondente conter um espao ou uma
mudana de linha. Para forar a funo scanf desconsiderar espaos em branco antes da
leitura de um caractere, necessrio adicionar um espao na cadeia de caracteres de formatao
de leitura antes do especificador de formatao %c , como a seguir:
FACOM
UFMS
104
T IPOS
PRIMITIVOS DE DADOS
UFMS
11.3 C ARACTERES
105
prompt$ ./a.out
-10
2
0.33
27.8e3
Como, nesse caso, a leitura busca por nmeros, a funo ignora os brancos. Dessa forma, os
nmeros acima podem ser colocados todos em uma linha, separados por espaos, ou em vrias
linhas, como mostramos acima. A funo scanf enxerga a entrada acima como uma cadeia
de caracteres como abaixo:
-102
0.33 27.8e3
ento, a funo scanf salta o primeiro espao, associa %d com 2 , casa / e / , salta o espao
e associa %d com 33 . Por outro lado, se a entrada
2 / 33
a funo scanf salta o espao, associa %d com 2 , tenta casar o caractere / da cadeia de
da entrada e como esses caracteres no casam, a
caracteres de formatao com um espao
funo termina e o restante / 33 da entrada permanecer armazenado na memria at que
uma prxima chamada funo scanf seja realizada.
FACOM
UFMS
106
T IPOS
PRIMITIVOS DE DADOS
Por convenincia e simplicidade, muitas vezes preferimos usar funes mais simples de
entrada e sada de caracteres. As funes getchar e putchar so funes da biblioteca
padro de entrada e sada da linguagem C e so usadas exclusivamente com caracteres. A
funo getchar l um caractere da entrada e devolve esse caractere. A funo putchar
toma um caractere como parmetro e o exibe na sada. Dessa forma, se c uma varivel do
tipo char as linhas a seguir:
scanf("%c", &c);
printf("%c", c);
c = getchar();
putchar(c);
Observe que a funo getchar no tem parmetros de entrada, mas, por ser uma funo,
carrega os parnteses como sufixo. Alm disso, essa funo devolve um caractere, que pode
ser usado em uma expresso. Nas linhas acima, getchar usada em uma atribuio. Por
outro lado, a funo putchar tem como parmetro uma expresso do tipo caractere que, aps
avaliada, seu valor ser exibido na sada. A funo putchar no devolve qualquer valor.
UFMS
11.4 C ONVERSO
DE TIPOS
107
Veremos agora os dois primeiros casos, sendo que os dois ltimos sero vistos adiante.
As converses usuais em expresses so aplicadas aos operandos de todos os operadores binrios aritmticos, relacionais e lgicos. A linguagem C faz a converso dos operandos de
maneira que fiquem mais seguramente acomodados. Logo, o menor nmero de bits que mais
seguramente acomode os operandos ser usado nessa converso, se uma converso for de fato
necessria. As regras de converso de tipos podem ento ser divididas em dois tipos:
o tipo de pelo menos um dos operandos de ponto flutuante: se um dos operandos do tipo
long double , ento o outro operando ser convertido para o tipo long double . Caso
contrrio, se um dos operandos do tipo double , ento o outro operando ser convertido para o tipo double . Seno, um dos operandos do tipo float e o outro ser
convertido para esse mesmo tipo;
nenhum dos operandos do tipo ponto flutuante: primeiro, se qualquer um dos operandos
do tipo char ou short int , ser convertido para o tipo int ; depois, se um dos operandos do tipo unsigned long int , ento o outro operando ser convertido para o
tipo unsigned long int . Caso contrrio, se um dos operandos do tipo long int ,
ento o outro operando ser convertido para o tipo long int . Ainda, se um dos operandos do tipo unsigned int , ento o outro operando ser convertido para o tipo
unsigned int . Por fim, um dos operandos do tipo int e o outro ser convertido
para esse mesmo tipo.
importante alertar para um caso em que uma operao envolve um dos operandos com
sinal e o outro sem sinal. Pelas regras acima, o operando com sinal convertido para um operando sem sinal. Assim, se um dos operandos do tipo int e contm um nmero negativo e
o outro operando do tipo unsigned int e contm um nmero positivo, ento uma operao envolvendo esses dois operandos deve ser realizada cuidadosamente. Nesse caso, o valor
do tipo int ser promovido para o tipo unsigned int , mas a converso ser feita usando
a frmula k + 232 , onde k o valor com sinal. Esse problema uma das causas de erro mais
difceis de depurar. Veja o programa 11.3 para um exemplo bastante ilustrativo.
Programa 11.3: Dificuldade na converso de valores em expresses.
#include <stdio.h>
int main(void)
{
int i;
unsigned int j;
i = -1;
j = 1;
printf("i = %+d i = %u\n", i, (unsigned int) i);
printf("j = %+d j = %u\n", (int) j, j);
if (i < j)
printf("i < j\n");
else
printf("j < i\n");
return 0;
}
FACOM
UFMS
108
T IPOS
PRIMITIVOS DE DADOS
prompt$ ./a.out
i = -1
i = 4294967295
j = +1
j = 1
j < i
As converses implcitas da linguagem C so bastante convenientes, como pudemos perceber at aqui. No entanto, muitas vezes necessrio que o programador tenha maior controle
sobre as converses a serem realizadas, podendo assim realizar converses explcitas. Dessa
forma, a linguagem C possui operadores de converso de tipo, ou casts, que j tomamos contato especialmente na aula 9. Um operador de converso de tipo um operador unrio que
tem o seguinte formato geral:
(nome-do-tipo) expresso
onde nome-do-tipo o nome de qualquer tipo primitivo de dados que ser usado para converter o valor da expresso , aps sua avaliao.
Por exemplo, supondo que f e frac so variveis do tipo float , ento o trecho de
cdigo a seguir:
f = 123.4567f;
frac = f - (int) f;
far com que a varivel frac contenha apenas o valor da parte fracionria da varivel f .
UFMS
109
Na primeira linha, typedef uma palavra reservada da linguagem C, int o tipo primitivo de dados para nmeros inteiros com sinal e Logic o nome do novo tipo de dados
criado pelo(a) programador(a). Na segunda linha, ocorre a declarao de duas variveis do
tipo Logic : a varivel primo e a varivel crescente . O nome Logic desse novo tipo
foi descrito com a primeira letra maiscula, mas isso no uma obrigatoriedade. O novo tipo
Logic criado a partir de typedef faz com que o compilador o adicione a sua lista de tipos conhecidos. Isso significa que podemos, a partir de ento, declarar variveis com esse tipo novo,
us-lo como operador conversor de tipo, entre outras coisas. Observe ainda que o compilador
trata Logic como um sinnimo para int . Dessa forma, as variveis primo e crescente
so, na verdade, variveis do tipo int .
Como principais vantagens podemos dizer que definies de tipos em programas permitem
fazer com que um cdigo torne-se mais compreensvel, mais fcil de modificar e mais fcil de
transportar de uma arquitetura de computadores para outra.
sizeof (nome-do-tipo)
determina um valor que um inteiro sem sinal representando o nmero de bytes necessrios
para armazenar um valor do tipo dado por nome-do-tipo .
Veja o programa 11.4.
Programa 11.4: Exemplo do uso do operador unrio sizeof.
#include <stdio.h>
int main(void)
{
printf("Caracteres: %lu\n", sizeof(char));
printf("Inteiros:\n");
printf(" short: %lu\n", sizeof(short int));
printf(" int: %lu\n", sizeof(int));
printf(" long int: %lu\n", sizeof(long int));
printf("Nmeros de ponto flutuante:\n");
printf(" float: %lu\n", sizeof(float));
printf(" double: %lu\n", sizeof(double));
printf(" long double: %lu\n", sizeof(long double));
return 0;
}
FACOM
UFMS
110
T IPOS
PRIMITIVOS DE DADOS
Caracteres:
1
Inteiros:
short:
2
int:
4
long int:
8
Nmeros de ponto flutuante:
float:
4
double:
8
long double: 16
11.7 Exerccios
Exerccios para treinar os conceitos aprendidos nesta aula. Faa muitos testes com suas
entradas e sadas.
11.1 Dadas n triplas compostas por um smbolo de operao aritmtica (+, , ou /) e dois
nmeros reais, calcule o resultado ao efetuar a operao indicada para os dois nmeros.
Faremos esse exerccio usando a estrutura condicional switch , que compara uma expresso com uma seqncia de valores. Essa estrutura tem o seguinte formato:
UFMS
11.7 E XERCCIOS
111
Programa 11.5: Soluo do exerccio 11.1.
#include <stdio.h>
/* Recebe um operador aritmtico e dois operandos inteiros e
devolve o resultado da operao sobre os dois operandos */
int main(void)
{
char operador;
int n;
float op1, op2, result;
printf("Informe n: ");
scanf("%d", &n);
for ( ; n > 0; n--) {
printf("Informe a expresso (ex.: 5.3 * 3.1): ");
scanf("%f %c%f", &op1, &operador, &op2);
switch (operador) {
case +:
result = op1 + op2;
break;
case -:
result = op1 - op2;
break;
case *:
result = op1 * op2;
break;
case /:
result = op1 / op2;
break;
default:
break;
}
printf("%f %c %f = %f\n", op1, operador, op2, result);
}
return 0;
}
F1 = 1
F = 1
2
Fi = Fi1 + Fi2 , para i > 3.
Escreva um programa que dado n > 1 calcule e exiba Fn .
11.3 Os babilnios descreveram a mais de 4 mil anos um mtodo para calcular a raiz quadrada
de um nmero. Esse mtodo ficou posteriormente conhecido como mtodo de Newton.
Dado um nmero x, o mtodo parte de um chute inicial y para o valor da raiz quadrada
de x e sucessivamente encontra aproximaes desse valor calculando a mdia aritmtica
FACOM
UFMS
112
T IPOS
PRIMITIVOS DE DADOS
y
1
2
1.75
1.732143
1.732051
x/y
3
1.5
1.714286
1.731959
1.732051
(y + x/y)/2
2
1.75
1.732143
1.732051
1.732051
Escreva um programa que receba um nmero real positivo x e um nmero real e calcule
a raiz quadrada de x usando o mtodo de Newton, at que o valor absoluto da diferena
entre dois valores consecutivos de y seja menor que . Mostre tambm na sada a quantidade de passos realizados para obteno da raiz de x.
FACOM
UFMS
AULA
12
V ETORES
Os tipos primitivos de dados na linguagem C se caracterizam pelo fato que seus valores no
podem ser decompostos. Isso significa que um valor armazenado em uma varivel de um tipo
primitivo nico e no faz parte de uma composio de valores organizada de alguma maneira.
Tipos primitivos de dados tambm so de bsicos ou elementares. Por outro lado, se os valores
de um tipo de dados podem ser decompostos ou subdivididos em valores mais simples, ento
o tipo de dados chamado de complexo, composto ou estruturado. A organizao desses
valores e as relaes estabelecidas entre eles determinam o que conhecemos como estrutura de
dados. Nesta aula iniciaremos o estudo sobre variveis compostas, partindo de uma varivel
conhecida como varivel composta homognea unidimensional ou simplesmente vetor.
Esta aula inspirada nas referncias [16, 15].
12.1 Motivao
Como um exemplo da necessidade do uso da estrutura de dados conhecida como vetor,
considere o seguinte problema:
Dadas cinco notas de uma prova dos(as) estudantes de uma disciplina, calcular a
mdia das notas da prova e a quantidade de estudantes que obtiveram nota maior
que a mdia e a quantidade de estudantes que obtiveram nota menor que a mdia.
Uma tentativa natural e uma idia inicial para solucionar esse problema consiste no uso
de uma estrutura de repetio para acumular o valor das cinco notas informadas e o clculo
posterior da mdia destas cinco notas. Esses passos resolvem o problema inicial do clculo da
mdia das provas dos estudantes. Mas e a computao das quantidades de alunos que obtiveram nota maior e menor que a mdia j computada? Observe que aps lidas as cinco notas
e processadas para o clculo da mdia em uma estrutura de repetio, a tarefa de encontrar
as quantidades de estudantes que obtiveram nota superior e inferior mdia impossvel, j
que as notas dos estudantes no esto mais disponveis na memria. Isto , a menos que o(a)
programador(a) pea ao usurio para informar as notas dos(as) estudantes novamente, no h
como computar essas quantidades.
Apesar disso, ainda podemos resolver o problema usando uma estrutura seqencial em
que todas as cinco notas informadas pelo usurio ficam armazenadas na memria e assim podemos posteriormente computar as quantidades solicitadas consultando estes valores. Veja o
programa 12.1.
113
114
V ETORES
Programa 12.1: Mdia de 5 notas.
#include <stdio.h>
/* Recebe 5 notas (nmeros reais), calcula a mdia desses valores e mostra
essa mdia e quantos dos valores so superiores e inferiores mdia */
int main(void)
{
int menor, maior;
float nota1, nota2, nota3, nota4, nota5, media;
printf("Informe as notas dos alunos: ");
scanf("%f%f%f%f%f", nota1, nota2, nota3, nota4, nota5);
media = (nota1 + nota2 + nota3 + nota4 + nota5) / 5;
printf("Media das provas: %f\n", media);
menor = 0;
if (nota1 < media)
menor = menor +
if (nota2 < media)
menor = menor +
if (nota3 < media)
menor = menor +
if (nota4 < media)
menor = menor +
if (nota5 < media)
menor = menor +
maior = 0;
if (nota1 > media)
maior = maior +
if (nota2 > media)
maior = maior +
if (nota3 > media)
maior = maior +
if (nota4 > media)
maior = maior +
if (nota5 > media)
maior = maior +
1;
1;
1;
1;
1;
1;
1;
1;
1;
1;
A soluo que apresentamos no programa 12.1 uma soluo correta para o problema.
Isto , dadas as cinco notas dos(as) estudantes em uma prova, o programa computa as sadas
que esperamos, ou seja, as quantidades de estudantes com nota inferior e superior mdia
da prova. No entanto, o que aconteceria se a sala de aula tivesse mais estudantes, como por
exemplo 100? Ou 1000 estudantes? Certamente, as estruturas seqencial e condicional no
seriam apropriadas para resolver esse problema, j que o(a) programador(a) teria de digitar
centenas ou milhares de linhas repetitivas, incorrendo inclusive na possibilidade de propagao de erros e na dificuldade de encontr-los. E assim como esse, outros problemas no podem
ser resolvidos sem uma extenso na maneira de armazenar e manipular as entradas de dados.
FACOM
UFMS
12.2 D EFINIO
115
12.2 Definio
Uma varivel composta homognea unidimensional, ou simplesmente um vetor, uma
estrutura de armazenamento de dados que se dispe de forma linear na memria e usada
para armazenar valores de um mesmo tipo. Um vetor ento uma lista de clulas na memria de tamanho fixo cujos contedos so do mesmo tipo primitivo. Cada uma dessas clulas
armazena um, e apenas um, valor. Cada clula do vetor tem um endereo ou ndice atravs
do qual podemos referenci-la. O termo varivel composta homognea unidimensional bem
explcito e significa que temos uma: (i) varivel, cujos valores podem ser modificados durante
a execuo de um programa; (ii) composta, j que h um conjunto de valores armazenado na
varivel; (iii) homognea, pois os valores armazenados na varivel composta so todos de um
mesmo tipo primitivo; e (iv) unidimensional, porque a estrutura de armazenamento na varivel
composta homognea linear. No entanto, pela facilidade, usamos o termo vetor com o mesmo
significado.
A forma geral de declarao de um vetor na linguagem C dada a seguir:
tipo identificador[dimenso];
onde:
tipo um tipo de dados conhecido ou definido pelo(a) programador(a);
identificador o nome do vetor, fornecido pelo(a) programador(a); e
dimenso a quantidade de clulas a serem disponibilizadas para uso no vetor.
Por exemplo, a declarao a seguir
float nota[100];
faz com que 100 clulas contguas de memria sejam reservadas, cada uma delas podendo
armazenar nmeros de ponto flutuante do tipo float . A referncia a cada uma dessas clulas
realizada pelo identificador do vetor nota e por um ndice. Na figura 12.1 mostramos o
efeito da declarao do vetor nota na memria de um computador.
0
98
99
memria
nota
UFMS
116
V ETORES
sexto elemento do vetor nota . Podemos, tambm, usar uma varivel do tipo inteiro como
ndice de um vetor ou ainda uma expresso aritmtica do tipo inteiro. Por exemplo, nota[i]
acessa a (i + 1)-sima clula do vetor nota . Ou ainda, podemos fazer nota[2*i+j] para
acessar a posio de ndice 2i + j + 1 do vetor nota . O compilador da linguagem C no
verifica de antemo se os limites dos ndices de um vetor esto corretos, trabalho que deve ser
realizado pelo(a) programador(a).
Um erro comum, aparentemente inocente, mas que pode ter causas desastrosas, mostrado
no trecho de cdigo abaixo:
int A[10], i;
for (i = 1; i <= 10; i++)
A[i] = 0;
Alguns compiladores podem fazer com que a estrutura de repetio for acima seja executada infinitamente. Isso porque quando a varivel i atinge o valor 10 , o programa armazena
o valor 0 em A[10] . Observe, no entanto, que A[10] no existe e assim 0 armazenado
no compartimento de memria que sucede A[9] . Se a varivel i ocorre na memria logo
aps A[9] , como bem provvel, ento i receber o valor 0 fazendo com que o lao inicie
novamente.
char c = a;
int num, soma = 0;
float produto = 1.0, resultado;
UFMS
12.4 E XEMPLO
COM VETORES
117
UFMS
118
V ETORES
Programa 12.2: Soluo do problema proposto na seo 12.1 usando um vetor.
#include <stdio.h>
/* Recebe 5 notas (nmeros reais), calcula a mdia desses valores e mostra
essa mdia e quantos dos valores so superiores e inferiores mdia */
int main(void)
{
int i, menor, maior;
float nota[5], soma, media;
for (i = 0; i < 5; i++) {
printf("Informe a nota do(a) estudante %d: ", i+1);
scanf("%f", ¬a[i]);
}
soma = 0.0;
for (i = 0; i < 5; i++)
soma = soma + nota[i];
media = soma / 5;
menor = 0;
maior = 0;
for (i = 0; i < 5; i++) {
if (nota[i] < media)
menor++;
if (nota[i] > media)
maior++;
}
printf("\nMedia das provas: %2.2f\n", media);
printf("Quantidade de alunos com nota inferior mdia: %d\n", menor);
printf("Quantidade de alunos com nota superior mdia: %d\n", maior);
return 0;
}
UFMS
12.5 M ACROS
PARA CONSTANTES
119
#define
#define
#define
#define
CARAC
NUMERADOR
MIN
TAXA
a
4
-10000
0.01567
O uso de macros com vetores bastante til porque, como j vimos, um vetor faz alocao esttica da memria, o que significa que em sua declarao ocorre uma reserva prvia
de um nmero fixo de compartimentos de memria. Por ser uma alocao esttica, no h
possibilidade de aumento ou diminuio dessa quantidade aps a execuo da linha de cdigo contendo a declarao do vetor. O programa 12.2 pode ser ainda modificado como no
programa 12.4 com a incluso de uma macro que indica a quantidade de notas a serem processadas.
A macro MAX usada quatro vezes no programa 12.4: na declarao do vetor nota , nas
expresses relacionais das duas estruturas de repetio for e no clculo da mdia. A vantagem de se usar uma macro que, caso seja necessrio modificar a quantidade de notas do
programa por novas exigncias do usurio, isso pode ser feito rpida e facilmente em uma
nica linha do cdigo, onde ocorre a definio da macro.
FACOM
UFMS
120
V ETORES
Programa 12.4: Soluo do problema proposto na seo 12.1 usando uma macro e um vetor.
#include <stdio.h>
#define MAX 5
/* Recebe 5 notas (nmeros reais), calcula a mdia desses valores e mostra
essa mdia e quantos dos valores so superiores e inferiores mdia */
int main(void)
{
int i, menor, maior;
float nota[MAX], soma, media;
for (i = 0; i < MAX; i++) {
printf("Informe a nota do(a) estudante %d: ", i+1);
scanf("%f", ¬a[i]);
}
soma = 0.0;
for (i = 0; i < MAX; i++)
soma = soma + nota[i];
media = soma / MAX;
menor = 0;
maior = 0;
for (i = 0; i < MAX; i++) {
if (nota[i] < media)
menor++;
if (nota[i] > media)
maior++;
}
printf("\nMedia das provas: %2.2f\n", media);
printf("Quantidade com nota inferior mdia: %d\n", menor);
printf("Quantidade com nota superior mdia: %d\n", maior);
return 0;
}
Exerccios
12.1 Dada uma seqncia de n nmeros inteiros, com 1 6 n 6 100, imprimi-la em ordem
inversa de leitura.
12.2 Uma prova consta de 30 questes, cada uma com cinco alternativas identificadas pelas
letras A, B, C, D e E. Dado o carto gabarito da prova e o carto de respostas de n estudantes, com 1 6 n 6 100, computar o nmero de acertos de cada um dos estudantes.
12.3 Tentando descobrir se um dado era viciado, um dono de cassino o lanou n vezes. Dados
os n resultados dos lanamentos, determinar o nmero de ocorrncias de cada face.
12.4 Um jogador viciado de cassino deseja fazer um levantamento estatstico simples sobre
uma roleta. Para isso, ele fez n lanamentos nesta roleta. Sabendo que uma roleta contm
FACOM
UFMS
12.5 M ACROS
121
PARA CONSTANTES
37 nmeros (de 0 a 36), calcular a freqncia de cada nmero desta roleta nos n lanamentos realizados.
12.5 Dados dois vetores x e y, ambos com n elementos, 1 6 n 6 100, determinar o produto
escalar desses vetores.
12.6 Calcule o valor do polinmio p(x) = a0 + a1 x + . . . + an xn em k pontos distintos. So
dados os valores de n (grau do polinmio), com 1 6 n 6 100, de a0 , a1 , . . . an (coeficientes
reais do polinmio), de k e dos pontos x1 , x2 , . . . , xk .
12.7 Dado o polinmio p(x) = a0 + a1 x + . . . an xn , isto , os valores de n e de a0 , a1 , . . . , an ,
com 1 6 n 6 100 determine os coeficientes reais da primeira derivada de p(x).
12.8 Dados dois polinmios reais
p(x) = a0 + a1 x + . . . + an xn
q(x) = b0 + b1 x + . . . + bm xm
FACOM
+
1
8
3
1
2
3
6
4
7
1
3
5
8
4
2
6
2
3
5
5
3
8
1
7
8
UFMS
122
V ETORES
12.10 Dados dois nmeros naturais m e n, com 1 6 m, n 6 100, e duas seqncias ordenadas
com m e n nmeros inteiros, obter uma nica seqncia ordenada contendo todos os
elementos das seqncias originais sem repetio.
12.11 Dada uma seqncia de n nmeros inteiros, com 1 6 n 6 100, imprimi-la em ordem
crescente de seus valores.
12.12 Dizemos que uma seqncia de n elementos, com n par, balanceada se as seguintes
somas so todas iguais:
a soma do maior elemento com o menor elemento;
a soma do segundo maior elemento com o segundo menor elemento;
a soma do terceiro maior elemento com o terceiro menor elemento;
e assim por diante . . .
Exemplo:
2 12 3 6 16 15 uma seqncia balanceada, pois 16 + 2 = 15 + 3 = 12 + 6.
Dados n (n par e 0 6 n 6 100) e uma seqncia de n nmeros inteiros, verificar se essa
seqncia balanceada.
12.13 Dada uma seqncia x1 , x2 , . . . , xk de nmeros inteiros, com 1 6 k 6 100, verifique se
existem dois segmentos consecutivos iguais nesta seqncia, isto , se existem i e m tais
que
xi , xi+1 , . . . , xi+m1 = xi+m , xi+m+1 , . . . , xi+2m1 .
Imprima, caso existam, os valores de i e m.
Exemplo:
Na seqncia 7, 9, 5, 4, 5, 4, 8, 6 existem i = 3 e m = 2.
12.14 Dadas duas seqncias de caracteres (uma contendo uma frase e outra contendo uma
palavra), determine o nmero de vezes que a palavra ocorre na frase. Considere que
essas seqncias tm no mximo 100 caracteres cada uma.
Exemplo:
Para a palavra ANA e a frase:
ANA E MARIANA GOSTAM DE BANANA.
Temos que a palavra ocorre 4 vezes na frase.
12.15 So dadas as coordenadas reais x e y de um ponto, um nmero natural n e as coordenadas
reais de n pontos, com 1 6 n 6 100. Deseja-se calcular e imprimir sem repetio os
raios das circunferncias centradas no ponto (x, y) que passem por pelo menos um dos n
pontos dados.
Exemplo:
Pontos: (1.0, 1.2), (1.5, 2.0), (0.0, 2.0), (0.0, 0.5), (4.0, 2.0)
Nesse caso h trs circunferncias de raios 1.12, 2.01 e 3.162.
Observaes:
FACOM
UFMS
12.5 M ACROS
123
PARA CONSTANTES
p
(a c)2 + (b d)2 .
(b) Dois pontos esto na mesma circunferncia se esto mesma distncia do centro.
FACOM
UFMS
124
FACOM
V ETORES
UFMS
AULA
C ADEIAS
13
DE CARACTERES
Veremos nesta aula uma estrutura que possui tratamento especial na linguagem C: a cadeia
de caracteres. Esta estrutura similar a um vetor de caracteres, diferenciando-se apenas por
conter um caracter especial no final, aps o ltimo caracter vlido. Essa caracterstica evita, em
muitos casos, que tenhamos de manter uma varivel que contenha o comprimento do vetor
para saber o nmero de caracteres contidos nele. Outras caractersticas e diferenas importantes sero vistas a seguir.
Diversas funes que manipulam cadeias de caracteres esto disponveis na biblioteca
string.
13.1 Literais
Vimos tomando contato com cadeias de caracteres desde quando escrevemos nosso primeiro programa na linguagem C. Por exemplo, na sentena abaixo:
printf("Programar bacana!\n");
o nico argumento passado para a funo printf a cadeia de caracteres (de formatao)
"Programar bacana!\n" . As aspas duplas so usadas para delimitar uma constante do
tipo cadeia de caracteres, que pode conter qualquer combinao de letras, nmeros ou caracteres especiais que no sejam as aspas duplas. Mesmo assim, possvel inserir as aspas duplas
no interior de uma constante cadeia de caracteres, inserindo a seqncia \" nessa cadeia. Na
linguagem C, uma constante do tipo cadeia de caracter chamada de literal.
Quando estudamos o tipo de dados char , aprendemos que uma varivel deste tipo pode
conter apenas um nico caracter. Para atribuir um caracter a uma varivel, o caracter deve ser
envolvido por aspas simples. Dessa forma, o trecho de cdigo a seguir:
char sinal;
sinal = +;
125
126
C ADEIAS
DE CARACTERES
tem o efeito de atribuir o caractere cuja constante + para a varivel sinal . Alm disso,
aprendemos que existe uma distino entre as aspas simples e as aspas duplas, sendo que no
primeiro caso elas servem para definir constantes do tipo caracter e no segundo para definir
constantes do tipo cadeia de caracteres. Assim, o seguinte trecho de cdigo:
char sinal;
sinal = "+";
no est correto, j que que a varivel sinal foi declarada do tipo char , podendo conter um
nico caracter. Lembre-se que na linguagem C as aspas simples e as aspas duplas so usadas
para definir dois tipos de constantes diferentes.
Usamos literais especialmente quando chamamos as funes printf e scanf em um
programa, ou seja, quando descrevemos cadeias de caracteres de formatao. Essencialmente,
a linguagem C trata as literais como cadeias de caracteres. Quando o compilador da linguagem
C encontra uma literal com n caracteres em um programa, ele reserva n + 1 compartimentos de
memria para armazenar a cadeia de caracteres correspondente. Essa rea na memria conter
os caracteres da cadeia mais um caractere extra, o caractere nulo, que registra o final da cadeia.
O caractere nulo um byte cujos bits so todos 0 (zeros) e representado pela seqncia \0 .
importante destacar a diferena entre o caractere nulo e o caractere zero: o primeiro um
caractere no-imprimvel, tem valor decimal 0 e constante \0 ; o segundo um caractere
imprimvel, tem valor 48, smbolo grfico 0 e constante 0 .
A literal "abc" armazenada como um vetor de quatro caracteres na memria, como
mostra a figura 13.1.
a
\0
UFMS
13.3 C ADEIAS
DE CARACTERES
127
Para ler, por exemplo, o contedo da varivel palavra , produzimos o seguinte trecho de
programa:
Para imprimir o contedo dessa mesma varivel palavra , devemos escrever um trecho de
programa da seguinte forma:
printf("Palavra: ");
for (i = 0; i < m; i++)
printf("%c", palavra[i]);
printf("\n");
Note que sempre necessitamos de uma varivel adicional para controlar o comprimento
de um vetor de caracteres quando da sua leitura. A varivel m faz esse papel no primeiro
trecho de programa acima. Alm disso, tanto para leitura como para escrita de um vetor de
caracteres, precisamos de uma estrutura de repetio para processar os caracteres um a um.
Com as cadeias de caracteres, evitamos esta sobrecarga de trabalho para o programador, como
veremos daqui por diante.
UFMS
128
C ADEIAS
DE CARACTERES
#define MAX 50
char cadeia[MAX+1];
Na declarao de uma varivel que pode armazenar uma cadeia de caracteres, sempre devemos reservar um compartimento a mais para que o caractere nulo possa ser armazenado.
Como diversas funes da linguagem C supem que as cadeias de caracteres so terminadas
com o caractere nulo, se isso no ocorre em algum caso, o comportamento do programa passa
a ser imprevisvel.
A declarao de um vetor de caracteres com dimenso MAX+1 no quer dizer que ele sempre conter uma cadeia de caracteres com MAX caracteres. O comprimento de uma cadeia de
caracteres depende da posio do caractere nulo na cadeia, no do comprimento do vetor onde
a cadeia est armazenada.
Como em qualquer vetor, uma cadeia de caracteres tambm pode ser declarada e inicializada simultaneamente. Por exemplo,
printf("%s\n", palavra);
FACOM
UFMS
13.3 C ADEIAS
DE CARACTERES
129
pode ser usada para mostrar o contedo completo da cadeia de caracteres palavra na sada
padro. Quando a funo printf encontra o especificador de converso %s , supe que o
argumento correspondente uma cadeia de caracteres, isto , um vetor de caracteres terminado
por um caractere nulo.
Podemos tambm usar a mesma cadeia de caracteres de formatao "%s" para leitura de
uma cadeia de caracteres. A funo scanf pode ser usada com o especificador de converso
%s para ler uma cadeia de caracteres at que a leitura de um branco seja realizada. Assim, a
chamada da funo scanf abaixo:
scanf("%s", palavra);
tem o efeito de ler uma cadeia de caracteres digitada pelo usurio e de armazen-la no vetor
de caracteres palavra .
muito importante ressaltar que, ao contrrio das chamadas anteriores da funo scanf ,
no caso de leitura de cadeias de caracteres, o smbolo & no adicionado como prefixo do
identificador da varivel. Veremos o porqu disto quando estudarmos apontadores.
Se na execuo da funo scanf anterior um(a) usurio(a) digita os caracteres abcdefg , a
cadeia de caracteres "abcdefg" armazenada no vetor palavra . Se, diferentemente, um(a)
usurio(a) digita os caracteres Campo Grande , ento apenas a cadeia de caracteres "Campo"
armazenada no vetor palavra , devido ao branco ( ). Os caracteres restantes da cadeia digitada ficaro disponveis no buffer de entrada at que uma prxima chamada funo scanf
seja realizada.
Para evitar os brancos na leitura de uma cadeia de caracteres, usamos o especificador de
converso %[...] , que tambm usado na leitura de cadeias de caracteres, delimitando, dentro dos colchetes, quais so os caracteres permitidos em uma leitura. Qualquer outro caractere
diferente dos especificados dentro dos colchetes finalizam a leitura. Alm disso, podemos inverter essas permisses, indicando o caractere ^ como o primeiro caractere dentro dos colchetes. Por exemplo,
FACOM
UFMS
130
C ADEIAS
DE CARACTERES
scanf("%[^\n]", palavra);
realiza a leitura de uma cadeia de caracteres, armazenando seu contedo no vetor de caracteres palavra . O caracter que finaliza a leitura o \n . Qualquer outro caracter ser lido e
armazenado no vetor palavra .
muito importante destacar que a funo scanf termina automaticamente uma cadeia de
caracteres que lida com o especificador de converso "%s" ou "%[...]" com um caracter
nulo, fazendo assim que o vetor de caracteres se torne de fato uma cadeia de caracteres aps
sua leitura.
Veja um exemplo simples do uso dos conceitos de entrada e sada de cadeias de caracteres
no programa 13.2.
Programa 13.2: Entrada e sada de uma cadeia de caracteres.
#include <stdio.h>
#define MAX 20
/* Recebe uma palavra com at MAX caracteres e imprime seu comprimento */
int main(void)
{
char palavra[MAX];
int n;
printf("Informe uma palavra (com at %d caracteres): ", MAX);
scanf("%s", palavra);
n = 0;
while (palavra[n] != \0)
n++;
printf("A palavra [%s] tem %d caracteres\n", palavra, n);
return 0;
}
Exerccios
13.1 Dada uma frase com no mximo 100 caracteres, determinar quantos caracteres espao a
frase contm.
13.2 Dada uma cadeia de caracteres com no mximo 100 caracteres, contar a quantidade de
letras minsculas, letras maisculas, dgitos, espaos e smbolos de pontuao que essa
cadeia possui.
13.3 Dadas duas cadeias de caracteres cadeia1 e cadeia2 , concatenar cadeia2 no final
de cadeia1 , colocando o caracter nulo no final da cadeia resultante. A cadeia resultante
a ser mostrada deve estar armazenada em cadeia1 . Suponha que as cadeias sejam
informadas com no mximo 100 caracteres.
FACOM
UFMS
13.3 C ADEIAS
DE CARACTERES
131
13.4 Dada uma cadeia de caracter cadeia com no mximo 100 caracteres e um caractere c ,
buscar a primeira ocorrncia de c em cadeia . Se c ocorre em cadeia , mostrar a
posio da primeira ocorrncia; caso contrrio, mostrar o valor -1 .
13.5 Dadas duas cadeias de caracteres cadeia1 e cadeia2 , cada uma com no mximo 100
caracteres, compar-las e devolver um valor menor que zero se cadeia1 lexicograficamente menor que cadeia2 , o valor zero se cadeia1 igual ou tem o mesmo contedo
que cadeia2 , ou um valor maior que zero se cadeia1 lexicograficamente maior que
cadeia2 .
13.6 Dadas duas seqncias de caracteres (uma contendo uma frase e outra contendo uma
palavra), determine o nmero de vezes que a palavra ocorre na frase. Considere que
essas seqncias tm no mximo 100 caracteres cada uma.
Exemplo:
Para a palavra ANA e a frase:
ANA E MARIANA GOSTAM DE BANANA.
Temos que a palavra ocorre 4 vezes na frase.
FACOM
UFMS
132
FACOM
C ADEIAS
DE CARACTERES
UFMS
AULA
14
M ATRIZES
Na aula 12, tivemos contato com vetores ou variveis compostas homogneas unidimensionais. No entanto, uma varivel composta homognea pode ter qualquer nmero de dimenses. A partir desta aula, aprenderemos a trabalhar com as estruturas denominadas de
matrizes ou variveis compostas homogneas bidimensionais. Do mesmo modo como vimos
com os vetores, as matrizes so variveis porque podem ter os valores de suas clulas alterados
durante a execuo do algoritmo/programa, compostas porque representam a composio de
um conjunto de valores indivisveis, homogneas porque esses valores so de um mesmo tipo
de dados e bidimensionais porque, ao contrrio dos vetores que so lineares ou tm uma nica
dimenso, estas estruturas tm duas dimenses. A extenso de variveis compostas homogneas para trs ou mais dimenses simples e imediata, como veremos posteriormente. Nesta
aula, que tem como referncias os livros [15, 16], aprenderemos a declarar matrizes, a declarar
e inicializar simultaneamente as matrizes e tambm a usar matrizes para solucionar problemas.
tipo identificador[dimenso1][dimenso2];
133
134
M ATRIZES
onde tipo um dos tipos de dados da linguagem C ou um tipo definido pelo(a) programador(a), identificador o nome da varivel matriz fornecido pelo(a) programador(a) e
dimenso1 e dimenso2 determinam a quantidade de linhas e colunas, respectivamente, a
serem disponibilizadas para uso na matriz. Por exemplo, a declarao a seguir:
int A[20][30];
faz com que 600 clulas de memria sejam reservadas, cada uma delas podendo armazenar
valores do tipo int . A referncia a cada uma dessas clulas realizada pelo identificador da
matriz A e por dois ndices, o primeiro que determina a linha e o segundo que determina a
coluna da matriz. Veja a figura 14.1.
0
28
29
0
1
2
18
19
memria
A[0][0]
linha 1
A[0][29] A[1][0]
linha 19
A[1][29]
A[19][0]
A[19][29]
UFMS
14.2 D ECLARAO
E INICIALIZAO SIMULTNEAS
135
1,
2,
2,
7,
1,
0,
2,
9,
0,
1,
1,
6,
0,
5,
1,
2,
0,
7,
2,
1,
2},
1},
1},
0} };
Na declarao e inicializao acima, cada inicializador fornece valores para uma linha da matriz. A linguagem C possui algumas pequenas regras para declarar e inicializar matrizes ou
variveis compostas homogneas de qualquer dimenso:
se um inicializador no grande o suficiente para inicializar um varivel composta homognea, ento o restante dos elementos sero inicializados com 0 (zero). Por exemplo,
inicializa as duas primeiras linhas da matriz A . As duas ltimas linhas sero inicializadas com 0 (zero);
se um inicializador mais interno no longo o suficiente para inicializar uma linha, ento
o restante dos elementos na linha inicializado com 0 (zero). Por exemplo,
1,
2,
2,
7,
1},
0, 1, 5, 7, 1},
2, 1, 1, 2},
9, 6, 2, 1, 0} };
as chaves internas, que determinam as inicializaes das linhas, podem ser omitidas.
Neste caso, uma vez que o compilador tenha lido elementos suficientes para preencher
uma linha, ele o faz e inicia o preenchimento da prxima linha. Por exemplo,
FACOM
1,
2,
2,
7,
1,
0,
2,
9,
0,
1,
1,
6,
0,
5,
1,
2,
0,
7,
2,
1,
2,
1,
1,
0};
UFMS
136
M ATRIZES
14.3 Exemplo
Apresentamos a seguir o programa 14.1, que resolve o seguinte problema:
Dada uma matriz real B, de 5 linhas e 10 colunas, calcule o somatrio dos elementos
da oitava coluna e que calcule o somatrio da terceira linha.
Programa 14.1: Exemplo de um programa que usa uma matriz.
#include <stdio.h>
/* Dada uma matriz de nmeros reais de dimenso 5 x 10, mostra
a soma da sua oitava coluna e da sua terceira linha */
int main(void)
{
int i, j;
float soma_c8, soma_l3, B[5][10];
for (i = 0; i < 5; i++)
for (j = 0; j < 10; j++) {
printf("Informe B[%d][%d]: ", i, j);
scanf("%f", B[i][j]);
}
soma_c8 = 0.0;
for (i = 0; i < 4; i++)
soma_c8 = soma_c8 + B[i][7];
printf("Valor da soma da oitava coluna %f\n", soma_c8);
soma_l3 = 0.0;
for (j = 0; j < 10; j++)
soma_l3 = soma_l3 + B[2][j];
printf("Valor da soma da terceira linha %f\n", soma_l3);
return 0;
}
Exerccios
14.1 Dadas duas matrizes de nmeros inteiros A e B, de dimenses mn, com 1 6 m, n 6 100,
fazer um programa que calcule a matriz Cmn = A + B.
14.2 Faa um programa que, dada uma matriz de nmeros reais Amn , determine At . Suponha que 1 6 m, n 6 100.
14.3 Dada uma matriz de nmeros reais A com m linhas e n colunas, 1 6 m, n 6 100, e um
vetor de nmeros reais v com n elementos, determinar o produto de A por v.
14.4 Um vetor de nmeros reais x com n elementos apresentado como resultado de um
sistema de equaes lineares Ax = b, cujos coeficientes so representados em uma matriz
de nmeros reais Amn e o lados direitos das equaes em um vetor de nmeros reais
b de m elementos. Dados A, x e b, verificar se o vetor x realmente soluo do sistema
Ax = b, supondo que 1 6 m, n 6 100.
FACOM
UFMS
14.3 E XEMPLO
137
Programa 14.2: Soluo do exerccio 14.1.
#include <stdio.h>
#define MAX 100
/* Dadas duas matrizes de nmeros inteiros de dimenses m n,
calcula a matriz soma dessas matrizes, mostrando-a na sada */
int main(void)
{
int m, n, i, j, A[MAX][MAX], B[MAX][MAX], C[MAX][MAX];
printf("Informe as dimenses (m, n) das matrizes: ");
scanf("%d%d", &m, &n);
for (i = 0; i < m; i++)
for (j = 0; j < n; j++) {
printf("Informe A[%2d][%2d]: ", i, j);
scanf("%d", &A[i][j]);
}
for (i = 0; i < m; i++)
for (j = 0; j < n; j++) {
printf("Informe B[%2d][%2d]: ", i, j);
scanf("%d", &B[i][j]);
}
for (i = 0; i < m; i++)
for (j = 0; j < n; j++)
C[i][j] = A[i][j] + B[i][j];
for (i = 0; i < m; i++) {
for (j = 0; j < n; j++)
printf("%2d ", C[i][j]);
printf("\n");
}
return 0;
}
14.5 Dadas duas matrizes de nmeros reais Amn e Bnp , com 1 6 m, n, p 6 100, calcular o
produto de A por B.
14.6 Dada uma matriz de nmeros inteiros Amn , com 1 6 m, n 6 100, imprimir o nmero de
linhas e o nmero de colunas nulas da matriz.
Exemplo:
Se a matriz A tem m = 4 linhas, n = 4 colunas e contedo
1 0 2 3
4 0 5 6
0 0 0 0
0 0 0 0
ento A tem 2 linhas nulas e 1 coluna nula.
FACOM
UFMS
138
M ATRIZES
14.7 Dizemos que uma matriz de nmeros inteiros Ann uma matriz de permutao se em
cada linha e em cada coluna houver n 1 elementos nulos e um nico elemento 1.
Exemplo:
0 1 0 0
0 0 1 0
1 0 0 0 .
0 0 0 1
Observe que
2 1 0
1
2 0
0
0 1
no de permutao.
Dada uma matriz de nmeros inteiros Ann , com 1 6 n 6 100, verificar se A de permutao.
14.8 Dada uma matriz de nmeros reais Amn , com 1 6 m, n 6 100, verificar se existem
elementos repetidos em A.
14.9 Dizemos que uma matriz quadrada de nmeros inteiros distintos um quadrado mgico1 se a soma dos elementos de cada linha, a soma dos elementos de cada coluna e a
soma dos elementos da diagonal principal e secundria so todas iguais.
Exemplo:
A matriz
8 0 7
4 5 6
3 10 2
um quadrado mgico.
Dada uma matriz quadrada de nmeros inteiros Ann , com 1 6 n 6 100, verificar se A
um quadrado mgico.
14.10
1
2
3
4
5
1
3
6
10
1
4
10
1
5
O primeiro registro conhecido de um quadrado mgico vem da China e data do ano de 650 a.c.
Descoberto em 1654 pelo matemtico francs Blaise Pascal.
FACOM
UFMS
14.3 E XEMPLO
139
14.11 Um jogo de palavras cruzadas pode ser representado por uma matriz Amn onde cada
posio da matriz corresponde a um quadrado do jogo, sendo que 0 indica um quadrado
branco e 1 indica um quadrado preto. Indicar em uma dada matriz Amn de 0 e 1,
com 1 6 m, n 6 100, as posies que so incio de palavras horizontais e/ou verticais nos
quadrados correspondentes (substituindo os zeros), considerando que uma palavra deve
ter pelo menos duas letras. Para isso, numere consecutivamente tais posies.
Exemplo:
Dada a matriz
0 1
0 1 1
0 1
0
0
0
0
0 1
0
0
0
0
0
1
1
0
0
1
0
1
0
0
0
0 1
0
0
0
0 1
0
0
0 1 1
1 1
2 1 1
3 1
4
5
6
0
0 1
7
0
0
8
0
1
1
9
0
1
0
1 10
0 11
0 1 12
0
13
0 1 14
0
0 1 1
14.12 Os elementos aij de uma matriz de nmeros inteiros Ann representam os custos de transporte da cidade i para a cidade j. Dados uma matriz Ann , com 1 6 n 6 100, um nmero
inteiro m > 0 representando a quantidade de itinerrios, um nmero k representando o
nmero de cidades em cada um dos itinerrios, calcular o custo total para cada itinerrio.
Exemplo:
Dado
4
5
A=
2
7
1
2
1
1
2
3
1 400
3
8
2
5
FACOM
UFMS
140
M ATRIZES
a
q
b
p
o
h
z
o
t
q
r
m
c
y
m
f
c
j
l
b
s
b
o
u
t
s
m
x
j
a
a
j
z
s
o
q
a
u
a
a
g
o
c
g
y
r
d
l
g
z
o
v
u
q
d
h
l
o
m
c
u
j
r
n
a
y
b
c
o
a
a
k
d
l
a
e
t
s
m
t
k
e
y
a
k
l
w
t
d
c
o
a
e
p
s
z
h
c
e
q
k
z
r
w
u
h
l
g
amora
14.14 Considere n cidades numeradas de 0 a n 1 que esto interligadas por uma srie de
estradas de mo nica, com 1 6 n 6 100. As ligaes entre as cidades so representadas
pelos elementos de uma matriz quadrada Ann , cujos elementos aij assumem o valor 1 ou
0, conforme exista ou no estrada direta que saia da cidade i e chegue cidade j. Assim,
os elementos da coluna j indicam as estradas que chegam cidade j. Por conveno
aii = 1.
A figura abaixo mostra um exemplo para n = 4.
A 0
UFMS
14.3 E XEMPLO
141
FACOM
UFMS
142
FACOM
M ATRIZES
UFMS
AULA
15
R EGISTROS
Nas aulas 12 e 14 aprendemos a trabalhar com variveis compostas homogneas unidimensionais e bidimensionais ou os vetores e as matrizes , que permitem que um programador
agrupe valores de um mesmo tipo em uma nica entidade lgica. Como mencionamos antes,
a dimenso de uma varivel composta homognea no fica necessariamente restrita a uma ou
duas. Isto , tambm podemos declarar e usar variveis compostas homogneas com trs ou
mais dimenses. Importante relembrar tambm que, para referenciar um elemento em uma
varivel composta homognea so necessrios o seu identificador e um ou mais ndices.
A linguagem C dispe tambm de uma outra forma para agrupamento de dados, chamada
varivel composta heterognea, registro ou estrutura1 . Nelas, diferentemente do que nas variveis compostas homogneas, podemos armazenar sob uma mesma entidade lgica valores de
tipos diferentes. Alm disso, ao invs de ndices ou endereos usados nas variveis compostas
homogneas para acesso a um valor, especificamos o nome de um campo para selecionar um
campo particular do registro. Os registros so os objetos de estudo desta aula, que inspirada
nas referncias [15, 16].
15.1 Definio
Uma varivel composta heterognea ou registro uma estrutura onde podemos armazenar valores de tipos diferentes sob uma mesma entidade lgica. Cada um desses possveis
valores armazenado em um compartimento do registro denominado campo do registro, ou
simplesmente campo. Um registro composto pelo seu identificador e pelos seus campos.
Suponha que queremos trabalhar com um agrupamento de valores que representam uma
determinada mercadoria de uma loja, cujas informaes relevantes so o cdigo do produto e
seu valor. Na linguagem C, podemos ento declarar um registro com identificador produto
da seguinte forma:
struct {
int codigo;
int quant;
float valor;
} produto;
1
struct e member (of a structure) so jarges comuns na linguagem C. A traduo literal dessas palavras pode nos
confundir com outros termos j usados durante o curso. Por isso, escolhemos registro e campo (do registro) como
tradues para o portugus.
143
144
R EGISTROS
valor
struct {
.
.
.
bloco de declaraes
.
.
.
} identificador;
Podemos declarar outras variveis do tipo registro com os mesmos campos da varivel
produto , declarada acima, da seguinte forma:
struct {
int codigo;
int quant;
float valor;
} produto, estoque, baixa;
struct {
char sala, turma;
int horas_inicio, minutos_inicio, horas_fim, minutos_fim;
float largura, comprimento;
} aula;
FACOM
UFMS
15.1 D EFINIO
145
declara um registro com identificador aula com seis campos, dois campos do tipo char ,
quatro outros campos do tipo int e dois campos do tipo float . Apesar dessa declarao
estar correta e de economizar algumas linhas de cdigo, sempre optamos pela declarao dos
campos separadamente, linha a linha, para que os campos fiquem bem destacados e, assim,
facilitem sua identificao rpida no cdigo. Dessa forma, em geral optamos pela seguinte
declarao do registro aula :
struct {
char sala;
char turma;
int horas_inicio;
int minutos_inicio;
int horas_fim;
int minutos_fim;
float largura;
float comprimento;
} aula;
Observe acima que, quando referenciamos um campo de uma varivel do tipo registro, no
so permitidos espaos entre o identificador do registro, o operador ponto e o identificador
do campo.
Tambm podemos usar o valor de um campo de um registro em quaisquer expresses. Por
exemplo, a expresso relacional abaixo correta:
Declaraes de registros diferentes podem conter campos com mesmo identificador. Por
exemplo,
FACOM
UFMS
146
R EGISTROS
struct {
char tipo;
char fatorRH;
int idade;
float altura;
} coleta;
struct {
char codigo;
int tipo;
int idade;
} certidao;
so declaraes vlidas na linguagem C. O acesso aos campos dessas variveis se diferencia justamente pelo identificador dos registros. Isto , a partir das declaraes dos registros coleta
e certidao , as atribuies abaixo esto corretas:
coleta.tipo = O;
certidao.tipo = 0;
coleta.idade = 29;
certidao.idade = coleta.idade + 2;
struct {
int codigo;
int quant;
float valor;
} produto = {1, 5, 34.5};
Neste caso, o campo codigo inicializado com o valor 1 , o campo quant inicializado
com o valor 5 e o campo valor com 34.5 . Como mencionado, as regras de declarao e
inicializao simultneas para registros so equivalentes quelas para vetores. Assim,
struct {
int codigo;
int quant;
float valor;
} produto = {0};
far a inicializao dos campos codigo e quant com 0 e do campo valor com 0.0 .
FACOM
UFMS
15.3 O PERAES
SOBRE REGISTROS
147
Variveis compostas heterogneas possuem uma caracterstica importante, que no observada em variveis compostas homogneas.
Lembre-se que quando queremos copiar o contedo completo de todos os compartimentos
de uma varivel composta homognea para os compartimentos respectivos de outra varivel
composta homognea, necessrio realizar a cpia elemento a elemento, escrevendo uma ou
mais estruturas de repetio para que essa cpia seja efetuada com sucesso. Isto , se A e B
so, por exemplo, vetores de um mesmo tipo de dados e mesma dimenso, errado tentar
fazer uma atribuio como abaixo:
A = B;
Por outro lado, quando tratamos de registros, podemos fazer uma atribuio direta e realizar a cpia de todos os seus campos nessa nica atribuio. O trecho de cdigo a seguir mostra
um exemplo com a declarao de dois registros com mesmos campos, a atribuio de valores
ao primeiro registro e uma cpia completa de todos os campos do primeiro registro para o
segundo:
.
.
.
struct {
char tipo;
int codigo;
int quant;
float valor;
} mercadoria1, mercadoria2;
.
.
.
mercadoria1.tipo = A;
mercadoria1.codigo = 10029;
mercadoria1.quant = 62;
mercadoria1.valor = 10.32 * TAXA + 0.53;
.
.
.
mercadoria2 = mercadoria1;
.
.
.
FACOM
UFMS
148
R EGISTROS
15.4 Exemplo
O programa 15.1 a seguir recebe um horrio no formato de horas, minutos e segundos, com
as horas no intervalo de 0 a 23, e atualiza este horrio em um segundo.
Programa 15.1: Atualiza o horrio em 1 segundo
#include <stdio.h>
/* Recebe um horrio no formato hh:mm:ss e o atualiza
em 1 segundo, mostrando o novo horrio na sada */
int main(void)
{
struct {
int hh;
int mm;
int ss;
} agora, prox;
printf("Informe o horrio atual (hh:mm:ss): ");
scanf("%d:%d:%d", agora.hh, agora.mm, agora.ss);
prox = agora;
prox.ss = prox.ss + 1;
if (prox.ss == 60) {
prox.ss = 0;
prox.mm = prox.mm + 1;
if (prox.mm == 60) {
prox.mm = 0;
prox.hh = prox.hh + 1;
if (prox.hh == 24)
prox.hh = 0;
}
}
printf("Prximo horrio %d:%d:%d\n", prox.hh, prox.mm, prox.ss);
return 0;
}
Exerccios
15.1 Dada uma data no formato dd/mm/aaaa, escreva um programa que mostre a prxima
data, isto , a data que representa o dia seguinte data fornecida.
Observao: No esquea dos anos bissextos. Lembre-se que um ano bissexto se divisvel por 400 ou, em caso negativo, se divisvel por 4 mas no por 100.
15.2 Dados dois horrios de um mesmo dia expressos no formato hh:mm:ss, calcule o tempo
decorrido entre estes dois horrios, apresentando o resultado no mesmo formato.
FACOM
UFMS
15.4 E XEMPLO
149
Programa 15.2: Soluo do exerccio 15.1.
#include <stdio.h>
/* Recebe uma data no formato dd:mm:aaaa e a atualiza em 1 dia, mostrando a nova data na sada */
int main(void)
{
struct {
int dia;
int mes;
int ano;
} data, prox;
printf("Informe uma data (dd/mm/aa): ");
scanf("%d/%d/%d", &data.dia, &data.mes, &data.ano);
prox = data;
prox.dia++;
if (prox.dia > 31 ||
(prox.dia == 31 && (prox.mes == 4 || prox.mes == 6 ||
prox.mes == 9 || prox.mes == 11)) ||
(prox.dia == 30 && prox.mes == 2) ||
(prox.dia == 29 && prox.mes == 2 && (prox.ano % 400 != 0 &&
(prox.ano % 100 == 0 || prox.ano % 4 != 0)))) {
prox.dia = 1;
prox.mes++;
if (prox.mes > 12) {
prox.mes = 1;
prox.ano++;
}
}
printf("%02d/%02d/%02d\n", prox.dia, prox.mes, prox.ano);
return 0;
}
15.3 Dadas duas datas, calcule o nmero de dias decorridos entre estas duas datas.
Uma maneira provavelmente mais simples de computar essa diferena usar a frmula 15.1 para calcular um nmero de dias N baseado em uma data:
1461 f (ano, ms)
153 g(ms)
N=
+
+ dia
(15.1)
4
5
onde
f (ano, ms) =
e
g(ms) =
ano 1, se ms 6 2 ,
ano,
caso contrrio
ms + 13, se ms 6 2 ,
ms + 1, caso contrrio .
Podemos calcular o valor N1 para a primeira data informada, o valor N2 para a segunda
data informada e a diferena N2 N1 o nmero de dias decorridos entre estas duas
datas informadas.
FACOM
UFMS
150
R EGISTROS
FACOM
UFMS
AULA
V ETORES ,
16
MATRIZES E REGISTROS
Nesta aula, vamos trabalhar com uma extenso natural do uso de registros, declarando e
usando variveis compostas homogneas de registros como, por exemplo, vetores de registros
ou matrizes de registros. Por outro lado, estudaremos tambm registros contendo variveis
compostas homogneas como campos. Veremos que combinaes dessas declaraes tambm
podem ser usadas de modo a representar e organizar os dados na memria para soluo de problemas. Alm disso, veremos ainda registros cujos campos podem ser variveis no somente de
tipos primitivos, de tipos definidos pelo usurio, ou ainda variveis compostas homogneas,
mas tambm de variveis compostas heterogneas ou registros. O conjunto dessas combinaes de variveis que acabamos de mencionar fornece ao() programador(a) uma liberdade e
flexibilidade na declarao de qualquer estrutura para armazenamento de informaes que lhe
seja necessria na soluo de um problema computacional, especialmente daqueles problemas
mais complexos.
Esta aula baseada nas referncias [16, 15].
struct {
int horas;
int minutos;
int segundos;
} cronometro[10];
ou ainda declarar, por exemplo, uma matriz com identificador agenda como abaixo:
151
152
V ETORES ,
MATRIZES E REGISTROS
struct {
int horas;
int minutos;
int segundos;
} agenda[10][30];
struct {
int horas;
int minutos;
int segundos;
} cronometro[10], agenda[10][30];
A declarao do vetor cronometro tem um efeito na memria que pode ser ilustrado como
na figura 16.1.
cronometro
horas
minutos
segundos
cronometro[0].horas = 20;
cronometro[0].minutos = 39;
cronometro[0].segundos = 18;
FACOM
UFMS
16.1 VARIVEIS
153
Alm disso, como fizemos na aula 15, podemos fazer a atribuio direta de registros para
registros declarados da mesma maneira. Assim, por exemplo, se declaramos as variveis
cronometro e aux como abaixo:
struct {
int horas;
int minutos;
int segundos;
} cronometro[10], aux;
ento as atribuies a seguir so vlidas e realizam a troca dos contedos das posies i e j
do vetor de registros cronometro :
aux = cronometro[i];
cronometro[i] = cronometro[j];
cronometro[j] = aux;
cronometro[i] = cronometro[j];
ao invs de:
cronometro[i].horas = cronometro[j].horas;
cronometro[i].minutos = cronometro[j].minutos;
cronometro[i].segundos = cronometro[j].segundos;
As duas formas de atribuio acima esto corretas, apesar da primeira forma ser muito mais
prtica e direta.
Nesse contexto, considere o seguinte problema:
O programa 16.1 soluciona o problema acima usando o mtodo de ordenao das trocas
sucessivas ou mtodo da bolha.
FACOM
UFMS
154
V ETORES ,
MATRIZES E REGISTROS
FACOM
UFMS
16.2 R EGISTROS
155
struct {
int dias;
char nome[3];
} mes;
struct {
int dias,
char nome[3];
} mes, aux;
mes.dias = 31;
mes.nome[0] = J;
mes.nome[1] = a;
mes.nome[2] = n;
31
UFMS
156
V ETORES ,
MATRIZES E REGISTROS
importante salientar mais uma vez que as regras para cpias de registros permanecem as
mesmas, mesmo que um campo de um desses registros seja uma varivel composta. Assim, a
cpia abaixo perfeitamente vlida:
aux = mes;
FACOM
UFMS
16.3 R EGISTROS
157
CONTENDO REGISTROS
struct {
int rga;
char nome[51];
struct {
int dia;
int mes;
int ano;
} nascimento;
} estudante;
rga
nome
mes
ano
nasc
49
50
UFMS
158
V ETORES ,
MATRIZES E REGISTROS
estudante.rga = 200790111;
estudante.nome[0] = J;
estudante.nome[1] = o;
estudante.nome[2] = s;
estudante.nome[3] = e;
estudante.nome[4] = \0;
estudante.nasc.dia = 22;
estudante.nasc.mes = 2;
estudante.nasc.ano = 1988;
struct {
int rga;
char nome[51];
struct {
int dia;
int mes;
int ano;
} nascimento;
} estudante1, estudante2, aux;
aux = estudante1;
estudante1 = estudante2;
estudante2 = aux;
FACOM
UFMS
16.3 R EGISTROS
CONTENDO REGISTROS
159
FACOM
UFMS
160
V ETORES ,
MATRIZES E REGISTROS
Exerccios
16.1 Dadas n datas, com 1 6 n 6 100, e uma data de referncia d, verifique qual das n datas
mais prxima data d.
Programa 16.4: Soluo do exerccio 16.1.
#include <stdio.h>
#define MAX 100
/* Recebe um inteiro n, 1 6 n 6 100, n datas e uma data de referncia,
e verifica qual das n datas mais prxima da data de referncia */
int main(void)
{
int dif[MAX], menor;
struct {
int dia;
int mes;
int ano;
} d, data[MAX];
printf("Informe uma data de referncia (dd/mm/aa): ");
scanf("%d/%d/%d", &d.dia, &d.mes, &d.ano);
printf("Informe a quantidade de datas: ");
scanf("%d", &n);
for (i = 0; i < n; i++) {
printf("[%03d] Informe uma data (dd/mm/aa): ", i+1);
scanf("%d/%d/%d", &data[i].dia, &data[i].mes, &data[i].ano);
}
if (d.mes <= 2)
N1 = (1461*(d.ano-1))/4 + ((153*d.mes+13)/5) + d.dia;
else
N1 = (1461*d.ano)/4 + ((153*d.mes+1)/5) + d.dia;
for (i = 0; i < n; i++) {
if (data[i].mes <= 2)
N2 = (1461*(data[i].ano-1))/4+((153*data[i].mes+13)/5)+data[i].dia;
else
N2 = (1461*data[i].ano)/4 + ((153*data[i].mes+1)/5) + data[i].dia;
if (N1 >= N2)
dif[i] = N1 - N2;
else
dif[i] = N2 - N1;
}
menor = 0;
for (i = 1; i < n; i++)
if (dif[i] < dif[menor])
menor = i;
printf("Data mais prxima de %2d/%2d/%2d %2d/%2d/%d\n",
d.dia, d.mes, d.ano, data[menor].dia, data[menor].mes, data[menor].ano);
return 0;
}
FACOM
UFMS
16.3 R EGISTROS
CONTENDO REGISTROS
161
FACOM
UFMS
162
FACOM
V ETORES ,
MATRIZES E REGISTROS
UFMS
AULA
I NTRODUO
17
S FUNES
Se concordamos que uma grande tarefa pode ser solucionada atravs de sua diviso em
sub-tarefas e da combinao de suas solues parciais, ento podemos ter nosso trabalho facilitado focando na construo de solues para essas sub-tarefas. Em programao essas solues
menores so chamadas de mdulos de programao e fazem parte de todo processo de construo de programas para soluo de problemas reais.
Os mdulos so uma ferramenta da programao estruturada que fornecem ao() programador(a) um mecanismo para construir programas que so fceis de escrever, ler, compreender, corrigir, modificar e manter. Na linguagem C, essa caracterstica em um cdigo obtida
atravs do uso de funes. Na verdade, todos os programas que codificamos at o momento
de alguma forma j fizeram uso de funes. Por exemplo, scanf e printf so funes de
entrada e sada de dados da linguagem C que j usamos muitas e muitas vezes. Alm disso,
temos construdo nossas prprias funes main para solucionar todos os problemas vistos at
aqui. Apesar do termo funo vir da matemtica, uma funo da linguagem C nem sempre
se parece com uma funo matemtica, j que pode no ter argumentos nem computar um
valor. Cada funo na linguagem C pode ser vista como um pequeno programa com suas prprias declaraes de variveis e sentenas de programao. Alm de facilitar a compreenso
e a modificao de um programa e evitar a duplicao de cdigo usado mais que uma vez, as
funes podem ser usadas no s no programa para o qual foram projetadas, mas tambm em
outros programas.
Esta aula baseada nas referncias [16, 15].
163
164
I NTRODUO
S FUNES
m = media(x, y);
A sentena acima chama a funo media e ento salva o valor devolvido na varivel m .
FACOM
UFMS
17.1 N OES
INICIAIS
165
Vamos usar a funo media em no programa 17.1. Entre outras coisas, este programa
mostra que uma funo pode ser chamada tantas vezes quanto necessrio.
Observe que a definio da funo media vem antes da definio da funo main , j que
teramos problemas de compilao se fizssemos o contrrio.
Nem toda funo devolve um valor como a funo media faz. Por exemplo, uma funo
cujo trabalho enviar informaes para a sada muito provavelmente no devolve valor algum.
Para indicar que uma funo no tem valor devolvido, especificamos que seu valor devolvido
do tipo void , onde void um tipo sem valor. Considere o seguinte exemplo, que imprime
na sada uma mensagem uma certa quantidade de vezes:
UFMS
166
I NTRODUO
S FUNES
imprimeContador(i);
O programa 17.2 chama a funo imprimeContador 10 vezes em uma estrutura de repetio for .
10 e contando...
FACOM
UFMS
17.1 N OES
INICIAIS
167
A funo imprimeContador regressa para o ponto em que foi chamada, no corpo da estrutura de repetio for , imprimeContador chamada novamente e imprime a mensagem:
9 e contando...
Cada vez que imprimeContador chamada, o valor armazenado na varivel i diferente e, assim, imprimeContador imprimir 10 mensagens diferentes na sada.
importante salientar ainda que algumas funes podem tambm no ter parmetros.
Considere a funo imprimeMsg , que imprime uma mensagem cada vez que chamada:
A palavra reservada void entre parnteses aps o identificador da funo indica que
imprimeMsg no tem argumentos. Para chamar uma funo sem argumentos, devemos escrever o nome da funo seguido obrigatoriamente por parnteses, como mostramos abaixo:
imprimeMsg();
FACOM
UFMS
168
I NTRODUO
S FUNES
A execuo do programa 17.3 comea com a primeira sentena na funo main , que a
declarao da varivel i do tipo int . Ems eguida, uma estrutura de repetio faz com que
a funo imprimeMsg seja executada 10 vezes. Quando imprimeMsg comea sua execuo,
ela chama a funo printf para mostrar uma mensagem na sada. Quando printf termina
sua execuo, imprimeMsg termina sua execuo e volta para main .
tipo identificador(parmetros)
{
declarao de variveis
sentena1 ;
.
.
.
sentenan ;
}
FACOM
UFMS
17.2 D EFINIO
E CHAMADA DE FUNES
169
Se a funo no tem parmetros, a palavra reservada void deve ocorrer entre os parnteses.
Aps a interface, a funo contm um corpo, que uma seqncia de comandos da linguagem C envolvida por chaves. O corpo de uma funo pode incluir declaraes e sentenas. Por
exemplo, a funo media poderia ser escrita como abaixo:
A declarao de variveis de uma funo deve vir primeiro, antes de qualquer sentena do
corpo da funo. As variveis declaradas no corpo de uma funo pertencem exclusivamente
quela funo e no podem ser examinadas ou modificadas por outras funes.
Uma chamada de funo consiste de um identificador da funo seguido por uma lista de
argumentos entre parnteses. Por exemplo, abaixo temos trs chamadas de funes:
media(x, y)
imprimeContador(i)
imprimeMsg()
FACOM
UFMS
170
I NTRODUO
S FUNES
Uma chamada de uma funo com valor devolvido void sempre seguida por um ;
para torn-la uma sentena. Por exemplo:
imprimeContador(i);
imprimeMsg();
Por outro lado, uma chamada de uma funo com valor devolvido diferente de void produz um valor que pode ser armazenado em uma varivel ou usado em uma expresso aritmtica, relacional ou lgica. Por exemplo,
if (media(x, y) > 0)
printf("Mdia positiva\n");
printf("A mdia %g\n", media(x, y));
O valor devolvido por uma funo que devolve um valor diferente de void sempre pode
ser descartado, como podemos ver na chamada a seguir:
media(x, y);
Esta chamada funo media um exemplo de uma sentena que avalia uma expresso mas
descarta o resultado. Apesar de estranho na chamada funo media , ignorar o valor devolvido pode fazer sentido em alguns casos. Por exemplo, a funo printf sempre devolve o
nmero de caracteres impressos na sada. Dessa forma, aps a chamada abaixo, a varivel nc
ter o valor 19:
nc = printf("Programar bacana\n");
printf("Programar bacana\n");
Uma funo que devolve um valor diferente de void deve usar a sentena return para
especificar qual valor ser devolvido. A sentena return tem a seguinte forma geral:
return expresso;
UFMS
17.3 F INALIZAO
DE PROGRAMAS
171
return 0;
return estado;
return (a + b) / 2;
return a * a * a + 2 * a * a - 3 * a - 1;
Quando uma das sentenas acima executada, primeiramente a avaliao da expresso realizada e o valor obtido ento devolvido pela funo.
Se o tipo da expresso na sentena return diferente do tipo devolvido pela funo, a
expresso ser implicitamente convertida para o tipo da funo.
exit(0);
Como o argumento 0 no muito significativo, a linguagem C nos permite usar o argumento EXIT_SUCCESS , que tem o mesmo efeito:
FACOM
UFMS
172
I NTRODUO
S FUNES
exit(EXIT_SUCCESS);
exit(EXIT_FAILURE);
return expresso;
exit(expresso);
A diferena entre return e exit que exit causa o trmino de um programa independente do ponto em que se encontra essa chamada, isto , no considerando qual funo
chamou a funo exit . A sentena return causa o trmino de um programa apenas se
aparece na funo main . Alguns(mas) programadores(as) usam exit exclusivamente para
depurar programas. Depurao de programas um tpico importante para uma linguagem de
programao e teremos uma breve introduo ao assunto na aula 23.
17.4 Exemplo
Vamos resolver agora o seguinte problema:
Construa uma funo que receba dois inteiros positivos e devolva o mximo divisor
comum entre eles.
J resolvemos o problema de encontrar o mximo divisor comum entre dois nmeros inteiros positivos antes, usando o algoritmo de Euclides, mas com o uso de uma nica funo,
a funo ou programa principal. Agora, faremos uma funo que recebe esses dois nmeros e
devolve o mximo divisor comum. Uma possvel funo que soluciona o problema mostrada
a seguir.
FACOM
UFMS
17.4 E XEMPLO
173
Um exemplo de um programa principal que faz uma chamada funo mdc descrita acima
mostrado no programa 17.4.
FACOM
UFMS
174
I NTRODUO
S FUNES
#include <stdio.h>
/* Recebe trs valores reais e mostra a mdia aritmtica entre cada um dos 3 pares de nmeros fornecidos */
int main(void)
{
double x, y, z;
printf("Informe trs valores: ");
scanf("%lf%lf%lf", &x, &y, &z);
printf("Mdia de %g e %g %g\n", x, y, media(x, y));
printf("Mdia de %g e %g %g\n", x, z, media(x, z));
printf("Mdia de %g e %g %g\n", y, z, media(y, z));
return 0;
}
/* Recebe dois nmeros reais e devolve a mdia aritmtica entre eles */
double media(double a, double b)
{
return (a + b) / 2;
}
UFMS
17.5 D ECLARAO
175
DE FUNES
da funo cuja declarao completa ser dada posteriormente. A declarao de uma funo
composta exatamente pela primeira linha da definio de uma funo com um ponto e vrgula
adicionado no final:
tipo identificador(parmetros);
Desnecessrio dizer que a declarao de uma funo tem de ser consistente com a definio da mesma funo. A seguir mostramos como nosso programa ficaria com a adio da
declarao de media :
#include <stdio.h>
double media(double a, double b);
/* declarao */
/* Recebe trs valores reais e mostra a mdia aritmtica entre cada um dos 3 pares de nmeros fornecidos */
int main(void)
{
double x, y, z;
printf("Informe trs valores: ");
scanf("%lf%lf%lf", &x, &y, &z);
printf("Mdia de %g e %g %g\n", x, y, media(x, y));
printf("Mdia de %g e %g %g\n", x, z, media(x, z));
printf("Mdia de %g e %g %g\n", y, z, media(y, z));
return 0;
}
/* Recebe dois nmeros reais e devolve a mdia aritmtica entre eles */
double media(double a, double b)
/* definio */
{
return (a + b) / 2;
}
A declarao de uma funo tambm conhecida como prottipo da funo. Um prottipo de uma funo fornece ao compilador uma descrio completa de como chamar a funo:
quantos argumentos fornecer, de quais tipos esses argumentos devem ser e qual o tipo do resultado a ser devolvido.
Exerccios
17.1
FACOM
UFMS
176
I NTRODUO
S FUNES
que receba dois nmeros de ponto flutuante que representam a base e a altura de
um tringulo e compute e devolva a rea desse tringulo.
(b) Escreva um programa que receba uma seqncia de n pares de nmeros de ponto
flutuante, onde cada par representa a base e a altura de um tringulo, e calcule e
escreva, para cada par, a rea do tringulo correspondente. Use a funo descrita no
item (a).
Programa 17.5: Soluo do exerccio 17.1.
#include <stdio.h>
/* Recebe a base e a altura, dois nmeros reais,
e devolve a rea do tringulo correspondente */
double area_triangulo(double base, double altura)
{
return (base * altura) / 2;
}
/* Recebe um nmero inteiro n > 0 e uma seqncia
de n pares de nmeros reais, base e altura de
um tringulo, e mostra a rea de cada tringulo */
int main(void)
{
int i, n;
double b, a;
printf("Informe n: ");
scanf("%d", &n);
for (i = 0; i < n;
printf("Informe
scanf("%lf%lf",
printf("rea do
}
i++) {
a base e a altura do tringulo: ");
&b, &a);
tringulo: %g\n", area_triangulo(b, a));
return 0;
}
17.2
que receba dois nmeros inteiros positivos a e b e determine e devolva um valor que
representa o produto desses nmeros, usando o seguinte mtodo de multiplicao:
i. dividir, sucessivamente, o primeiro nmero por 2, at que se obtenha 1 como
quociente;
ii. em paralelo, dobrar, sucessivamente, o segundo nmero;
iii. somar os nmeros da segunda coluna que tenham um nmero mpar na primeira coluna; o total obtido o produto procurado.
Por exemplo, para os nmeros 9 e 6, temos que 9 6
FACOM
UFMS
17.5 D ECLARAO
9
4
2
1
177
DE FUNES
6
12
24
48
48
54
(b) Escreva um programa que leia n > 1 pares de nmeros e calcule os respectivos
produtos desses pares, usando a funo do item (a).
17.3 Para determinar o nmero de lmpadas necessrias para cada aposento de uma residncia, existem normas que fornecem o mnimo de potncia de iluminao exigida por metro
quadrado (m2 ) conforme o uso desse ambiente. Suponha que s temos lmpadas de 60
watts para uso.
Seja a seguinte tabela de informaes sobre possveis aposentos de uma residncia:
Utilizao
quarto
sala de TV
salas
cozinha
varandas
escritrio
banheiro
Classe
1
1
2
2
2
3
3
Potncia/m2 (W)
15
15
18
18
18
20
20
que receba dois nmeros inteiros positivos a e b e calcule e devolva o mximo divisor
comum entre eles.
FACOM
UFMS
178
I NTRODUO
S FUNES
(b) Usando a funo do item anterior, escreva um programa que receba n > 1 nmeros
inteiros positivos e calcule o mximo divisor comum entre todos eles.
17.5
que receba dois nmeros inteiros n e d, com 0 < d 6 9, devolva um valor que
representa o nmero de vezes que o dgito d ocorre no nmero n.
(b) Usando a funo do item anterior, escreva um programa que leia dois nmeros inteiros positivos a e b e responda se a permutao de b.
17.7
b
890
1234
245
2457
sufixo
sufixo
no sufixo
no sufixo
(b) Usando a funo do item anterior, escreva um programa que leia dois nmeros inteiros a e b e verifique se o menor deles subseqncia do outro.
Exemplo:
FACOM
UFMS
17.5 D ECLARAO
179
DE FUNES
a
567890
1234
235
b
678
2212345
236
b subseqncia de a
a subseqncia de b
um no subseqncia do outro
17.8 Uma seqncia de n nmeros inteiros no nulos dita m-alternante se constituda por
m segmentos: o primeiro com um elemento, o segundo com dois elementos e assim por
diante at o m-simo, com m elementos. Alm disso, os elementos de um mesmo segmento devem ser todos pares ou todos mpares e para cada segmento, se seus elementos
forem todos pares (mpares), os elementos do segmento seguinte devem ser todos mpares (pares).
Por exemplo:
A seqncia com n = 10 elementos: 8 3 7 2 10 4 5 13 9 11 4-alternante.
A seqncia com n = 3 elementos: 7 2 8 2-alternante.
(b) Usando a funo do item anterior, escreva um programa que, dados um inteiro n,
com n > 1, e uma seqncia de n nmeros inteiros, verifica se a seqncia malternante. O programa deve imprimir o valor de m ou exibir uma mensagem informando que a seqncia no alternante.
FACOM
UFMS
180
FACOM
I NTRODUO
S FUNES
UFMS
AULA
A RGUMENTOS
18
E PARMETROS DE
FUNES
Como vimos at aqui, a interface de uma funo define muito do que queremos saber sobre
ela: o tipo de valor que a funo devolve, seu identificador e seus parmetros. Isso implica na
conseqente elevao do nvel de abstrao dos nossos programas, j que podemos entender o
que um programa faz sem a necessidade de examinar os detalhes de suas funes. Caso alguns
detalhes sejam de nosso interesse, tambm h a vantagem de que sabemos onde examinlos. Nesta aula, baseada nas referncias [16, 15], focaremos nos argumentos e parmetros das
funes e no escopo de seus dados.
x = quadrado(num);
182
A RGUMENTOS
E PARMETROS DE FUNES
J os valores dos parmetros de entrada e sada so passados/devolvidos por um mecanismo chamado referncia. Nesse caso, temos uma varivel especificada na chamada da funo e um parmetro especificado na interface da funo que compartilham a mesma rea de
armazenamento na memria e isso significa que qualquer alterao realizada no contedo do
parmetro dentro da funo acarreta alterao no contedo da varivel que o argumento da
chamada. Vejamos um exemplo no programa 18.1.
Uma primeira observao importante sobre a interface da funo decompoe . Note que
os parmetros parte_int e parte_frac vem precedidos do smbolo * . Essa a forma
que definimos parmetros de entrada e sada na linguagem C. No corpo da funo decompoe ,
observe que os parmetros de entrada e sada so usados como de costume no corpo de uma
funo, isto , como vimos usando os parmetros de entrada. No entanto, os parmetros de
entrada e sada sempre devem vir precedidos pelo smbolo * no corpo de uma funo, como
mostrado acima. E por ltimo, a chamada da funo decompoe na funo main ligeiramente diferente. Observe que os argumentos a e b so precedidos pelo smbolo & , indicando
que as variveis a e b da funo main , de tipos inteiro e ponto flutuante respectivamente,
so passadas como parmetros de entrada e sada para a funo decompoe , ou seja, so passadas por referncia, e qualquer alterao realizada nos parmetros correspondentes da funo
refletiro nos argumentos da chamada.
FACOM
UFMS
18.2 E SCOPO
183
DE DADOS E DE FUNES
Exerccios
18.1
UFMS
184
A RGUMENTOS
E PARMETROS DE FUNES
18.2 Em um dado pas a moeda corrente possui apenas quatro cdulas de papel: $1, $5, $10 e
$20.
(a) Escreva uma funo com a seguinte interface:
void cedulas(int val, int *um, int *cin, int *dez, int *vin)
UFMS
18.2 E SCOPO
185
DE DADOS E DE FUNES
18.3 Dizemos que um nmero natural n palndromo se lido da esquerda para direita e da
direita para esquerda o mesmo nmero.
Exemplos:
567765 palndromo.
32423 palndromo.
567675 no palndromo.
(a) Escreva uma funo com a seguinte interface:
void quebra(int n, int *prim, int *ult, int *miolo)
que receba um nmero inteiro n > 0 e devolva trs nmeros inteiros: o primeiro
dgito de n, o ltimo dgito de n e um inteiro que represente o nmero n sem seu
primeiro e ltimo dgitos.
Exemplo:
valor inicial de n
732
14738
78
7
primeiro dgito
7
1
7
7
ltimo dgito
2
8
8
7
miolo de n
3
473
0
0
(b) Usando a funo do item (a), escreva um programa que receba um nmero inteiro
n > 0 e verifique se n palndromo. Suponha que n no contm o dgito 0.
18.4
que receba trs nmeros inteiros e devolva um nmero inteiro representando a soma
dos trs bits, e devolva tambm um outro valor do tipo inteiro representando o valor
do vai um.
(b) Escreva um programa que receba dois nmeros na base binria e, usando a funo
do item (a), calcule um nmero na base binria que a soma dos dois nmeros
dados.
FACOM
UFMS
186
FACOM
A RGUMENTOS
E PARMETROS DE FUNES
UFMS
AULA
F UNES
19
E VETORES
Nas aulas prticas e tericas vimos funes, argumentos de funes e passagem de parmetros para funes na linguagem C, onde trabalhamos apenas com argumentos de tipos bsicos.
Observe que chegamos a passar o valor de um elemento de um vetor como um argumento para
uma funo, por cpia e por referncia. Nesta aula veremos como realizar passagem de parmetros de tipos complexos, mais especificamente de parmetros que so variveis compostas
homogneas unidimensionais ou vetores. Esta aula baseada nas referncias [16, 15].
187
188
F UNES
E VETORES
Observe a interface da funo minimo do programa acima. Essa interface indica que a funo devolve um valor do tipo inteiro, tem identificador minimo e tem como seu argumento um
vetor contendo 10 elementos do tipo inteiro. Referncias feitas ao parmetro A , no interior da
funo minimo , acessam os elementos apropriados dentro do vetor que foi passado funo.
Para passar um vetor inteiro para uma funo necessrio apenas descrever o identificador
do vetor, sem qualquer referncia a ndices, na chamada da funo. Essa situao pode ser
visualizada na ltima linha do programa principal, na chamada da funo minimo(pontos) .
importante destacar tambm que a nica restrio de devoluo de uma funo relativa
s variveis compostas homogneas. De fato, um valor armazenado em uma varivel de qualquer tipo pode ser devolvido por uma funo, excluindo variveis compostas homogneas.
FACOM
UFMS
19.3 V ETORES
189
Perceba que a funo dobro do programa acima modifica os valores do vetor valor , uma
varivel local do programa principal que passada como parmetro para a funo dobro na
varivel vetor , uma varivel local da funo dobro . importante observar que, quando
usamos vetores como argumentos, uma funo que modifica o valor de um elemento do vetor, modifica tambm o vetor original que foi passado como parmetro para a funo. Esta
modificao tem efeito mesmo aps o trmino da execuo da funo.
Nesse sentido, podemos dizer que um vetor, uma matriz ou uma varivel composta homognea de qualquer dimenso sempre um parmetro de entrada e sada, isto , sempre
passado por referncia a uma funo.
No entanto, lembre-se que a modificao de elementos de um vetor em uma funo se
aplica somente quando o vetor completo passado como parmetro funo e no elementos
individuais do vetor. Esse ltimo caso j foi tratado em aulas anteriores.
Observe que a dimenso do parmetro vetor da funo dobro , que um vetor, foi omitida. A duas definies da funo dobro , nesta seo e na seo anterior, so equivalentes. No
entanto, a definio com a dimenso omitida permite que a funo dobro possa ser chamada
com vetores de quaisquer dimenses como argumentos.
Por exemplo, se temos dois vetores de inteiros A e B, com dimenses 50 e 200, respectivamente, a funo dobro pode ser chamada para computar o dobro de cada coordenada do
vetor A e, do mesmo modo, tambm pode se chamada para computar o dobro de cada coordenada do vetor B. Ou seja, a funo dobro pode ser chamada com vetores de dimenses
diferentes como parmetros.
dobro(A, 50);
dobro(B, 200);
FACOM
UFMS
190
F UNES
E VETORES
Exerccios
19.1
(b) Escreva um programa que receba dois vetores de nmeros inteiros U e W , com u e
w elementos respectivamente, 1 6 u, w 6 100, e verifique se os dois conjuntos so
iguais (U = W se e somente se U W e W U ). Use a funo do item (a).
Programa 19.3: Soluo do exerccio 19.1.
#include <stdio.h>
#define MAX
100
#define VERDADEIRO 1
#define FALSO
0
/* Recebe um vetor A com m nmeros inteiros e um vetor B com
n nmeros inteiros e verifica se A est contido em B */
int subconjunto(int A[MAX], int m, int B[MAX], int n)
{
int i, j, contido;
contido = VERDADEIRO;
for (i = 0; i < m && contido; i++) {
for (j = 0; j < n && B[j] != A[i]; j++)
;
if (j == n)
contido = FALSO;
}
return contido;
}
/* Recebe dois conjuntos de nmeros inteiros e verifica se so iguais */
int main(void)
{
int tamU, i, U[MAX], tamW, j, W[MAX];
scanf("%d", &tamU);
for (i = 0; i < tamU; i++)
scanf("%d", &U[i]);
scanf("%d", &tamW);
for (j = 0; j < tamW; j++)
scanf("%d", &W[j]);
if (subconjunto(U, tamU, W, tamW) && subconjunto(W, tamW, U, tamU))
printf("U == W\n");
else
printf("U != W\n");
return 0;
}
FACOM
UFMS
19.3 V ETORES
191
FACOM
UFMS
192
FACOM
F UNES
E VETORES
UFMS
AULA
F UNES
20
E MATRIZES
20.1 Matrizes
Um elemento de uma matriz pode ser passado como parmetro para uma funo assim
como fizemos com uma varivel de um tipo bsico ou como um elemento de um vetor. Ou
seja, a sentena
p = paridade(matriz[i][j]);
multiplica_escalar(A, escalar);
pode ser usada para chamar uma funo que multiplica cada elemento de uma matriz A pelo
valor armazenado na varivel escalar . Assim como com vetores, uma modificao realizada
no corpo de uma funo sobre qualquer elemento de uma matriz que um parmetro dessa
funo provoca uma modificao no argumento da chamada da funo, ou seja, na matriz que
foi passada funo durante sua chamada.
O programa 20.1 recebe uma matriz A44 de nmeros inteiros e um escalar e realiza o
produto da matriz por esse escalar.
193
194
F UNES
E MATRIZES
UFMS
20.2 M ATRIZES
195
Exerccios
20.1
FACOM
UFMS
196
F UNES
E MATRIZES
20.2 A k-sima potncia de uma matriz quadrada Ann , denotada por Ak , a matriz obtida a
partir da matriz A da seguinte forma:
k
}|
{
z
Ak = In A A A ,
que receba uma matriz I e uma dimenso n e preencha essa matriz com os valores
da matriz identidade de ordem n.
(b) Escreva uma funo com a seguinte interface:
void multMat(int C[MAX][MAX], int A[MAX][MAX], int B[MAX][MAX], int n)
1
2
4
3
2
3
1
4
3
4
2
1
4
1
3
2
UFMS
20.2 M ATRIZES
197
que receba como parmetros uma matriz Ann de nmeros inteiros e um ndice i, e
verifique se na linha i de A ocorrem todos os nmeros inteiros de 1 a n, devolvendo
1 em caso positivo e 0 caso contrrio.
(b) Escreva uma funo com a seguinte interface:
int coluna(int A[MAX][MAX], int n, int j)
que receba como parmetros uma matriz Ann de nmeros inteiros e um ndice j, e
verifique se na coluna j de A ocorrem todos os nmeros inteiros de 1 a n, devolvendo
1 em caso positivo e 0 caso contrrio.
(c) Usando as funes dos itens (a) e (b), escreva um programa que verifique se uma
dada matriz Ann de nmeros inteiros, com 1 6 n 6 100, um quadrado latino de
ordem n.
FACOM
UFMS
198
FACOM
F UNES
E MATRIZES
UFMS
AULA
F UNES
21
E REGISTROS
J vimos funes com parmetros de tipos bsicos e de tipos complexos, como vetores e
matrizes. Nesta aula, aprenderemos como comportam-se os registros no contexto das funes.
Como veremos, um registro, diferentemente das variveis compostas homogneas, comportase como uma varivel de um tipo bsico qualquer quando trabalhamos com funes. Ou seja,
um registro comporta-se como qualquer outra varivel excluindo as compostas homogneas,
isto , um registro sempre um argumento passado por cpia a uma funo. Se quisermos
que um registro seja um argumento passado por referncia a uma funo, devemos explicitamente indicar essa opo usando o smbolo & no argumento e o smbolo * no parmetro
correspondente, como fazemos com variveis de tipos primitivos.
Esta aula baseada nas referncias [16, 15].
struct cadastro {
int codigo;
char nome[MAX+1];
int fone;
};
199
200
F UNES
E REGISTROS
Observe que o caractere ponto e vrgula ( ; ) segue o caractere fecha chaves } . O ; deve
estar presente neste ponto para terminar a declarao da etiqueta do registro.
Uma vez que criamos a etiqueta cadastro , podemos us-la para declarar variveis:
Tambm, a declarao de uma etiqueta de um registro pode ser combinada com a declarao de variveis registros, como mostrado a seguir:
struct cadastro {
int codigo;
char nome[MAX+1];
int fone;
} ficha1, ficha2;
typedef struct {
int codigo;
char nome[MAX+1];
int fone;
} Cadastro;
Observe que o nome do tipo, Cadastro , deve ocorrer no final, no aps a palavra reservada struct . Alm disso, como Cadastro um nome de um tipo definido por typedef ,
no permitido escrever struct Cadastro . Todas as variveis do tipo Cadastro so compatveis, desconsiderando onde foram declaradas. Assim, a declarao de registros com essa
definio pode ser dada como abaixo:
FACOM
UFMS
21.2 R EGISTROS
201
Quando precisamos declarar um nome para um registro, podemos escolher entre declarar uma etiqueta de registro ou definir um tipo registro com a palavra reservada typedef .
Entretanto, em geral preferimos usar etiquetas de registros por diversos motivos que sero
justificados posteriormente.
x = raiz_quadrada(poligono.diagonal);
s = total_segundos(tempo);
pode ser usada para chamar a funo totalSegundos que provavelmente calcula o total de
segundos de uma medida de tempo armazenada no registro tempo .
Diferentemente das variveis compostas homogneas, uma modificao realizada em qualquer campo de um registro que um parmetro de uma funo no provoca uma modificao no contedo do campo correspondente que um argumento da funo. Nesse caso, a
princpio, um argumento que um registro em uma chamada de uma funo tem o mesmo
comportamento de um argumento que uma varivel de um tipo bsico qualquer, ou seja,
uma expresso que um argumento de uma chamada de uma funo e que, na verdade ou
contm um registro, de fato um parmetro de entrada da funo, passado por cpia. Dessa
forma, voltamos a repetir que somente as variveis compostas homogneas tm um comportamento deferenciado na linguagem C, no que ser refere a argumentos e parmetros de funes
neste caso especfico.
Um exemplo com uma chamada de uma funo contendo um registro como argumento
mostrado no programa 21.1.
FACOM
UFMS
202
F UNES
E REGISTROS
Programa 21.1: Um programa com uma funo com parmetro do tipo registro.
#include <stdio.h>
struct
int
int
int
};
marca {
hh;
mm;
ss;
Devemos destacar pontos importantes neste programa. O primeiro, e talvez o mais importante, a definio da etiqueta de registro marca . Em nenhuma outra oportunidade anterior
havamos desenvolvido um programa que continha uma declarao de uma etiqueta de registro. Observe ainda que a declarao da etiqueta marca do programa 21.1 foi feita fora dos
corpos das funes converte_segundos e main . Em todos os programas descritos at aqui,
no temos um exemplo de uma declarao de uma etiqueta de registro, ou mesmo uma declarao de uma varivel de qualquer tipo, fora do corpo de qualquer funo. A declarao
da etiqueta marca realizada dessa maneira se deve ao fato que a mesma usada nas funes
converte_segundos e main , obrigando que essa declarao seja realizada globalmente, ou
seja, fora do corpo de qualquer funo. Todas as outras declaraes que fizemos so declaraes locais, isto , esto localizadas no interior de alguma funo.
Os outros pontos de destaque do programa 21.1 so todos relativos ao argumento da chamada da funo converte_segundos e do parmetro da mesma, descrito em sua interface.
Note que essa funo tem como parmetro o registro tempo do tipo struct marca . O argumento da funo, na chamada dentro da funo main o registro horario de mesmo tipo
struct marca .
FACOM
UFMS
21.3 R EGISTROS
203
Finalmente, importante repetir que a passagem de um registro para uma funo feita
por cpia, ou seja, o parmetro correspondente um parmetro de entrada e, por isso, qualquer
alterao realizada em um ou mais campos do registro dentro da funo no afeta o contedo
dos campos do registro que um argumento na sua chamada. No exemplo acima no h
alteraes nos campos do registro tempo no corpo da funo converte_segundos , mas, caso
houvesse, isso no afetaria qualquer um dos campos do registro horario da funo main .
marca {
hh;
mm;
ss;
FACOM
UFMS
204
F UNES
E REGISTROS
Uma observao importante sobre o programa 21.2 a forma como um registro que um
parmetro passado por referncia apresentado no corpo da funo. Como o smbolo . que
seleciona um campo de um registro tem prioridade sobre o smbolo * , que indica que o parmetro foi passado por referncia, os parnteses envolvendo o o smbolo * e o identificador do
registro so essenciais para evitar erros. Dessa forma, uma expresso envolvendo, por exemplo, o campo ss do registro tempo , escrita como *tempo.ss , est incorreta e no realiza a
seleo do campo do registro que tencionamos.
Alternativamente, podemos usar os smbolos -> para indicar o acesso a um campo de um
registro que foi passado por referncia a uma funo. O uso desse smbolo simplifica bastante
a escrita do corpo das funes que tm parmetros formais que so registros passados por
referncia. Dessa forma, o programa 21.2 pode ser reescrito como o programa 21.3. Observe
que esses dois programas tm a mesma finalidade, isto , dada uma entrada, realizam o mesmo
processamento e devolvem as mesmas sadas.
Programa 21.3: Uso do smbolo -> para registros passados por referncia.
#include <stdio.h>
struct
int
int
int
};
marca {
hh;
mm;
ss;
FACOM
UFMS
21.4 F UNES
205
FACOM
UFMS
206
F UNES
E REGISTROS
marca {
hh;
mm;
ss;
FACOM
UFMS
21.4 F UNES
207
Exerccios
21.1
que receba uma data no formato dd/mm/aaaa e verifique se o ano bissexto, devolvendo 1 em caso positivo e 0 caso contrrio. Um ano bissexto se divisvel por 4 e
no por 100 ou divisvel por 400.
(b) Escreva uma funo com a seguinte interface:
int dias_mes(struct data d)
que receba uma data no formato dd/mm/aaaa e devolva a data que representa o dia
seguinte. Use as funes dos itens (a) e (b).
(d) Escreva um programa que receba uma data no formato dd/mm/aaaa e imprima a
data que representa o dia seguinte. Use as funes dos itens anteriores.
21.2 Reescreva a funo do item (c) do exerccio 21.1, de modo que a funo dia_seguinte
tenha o registro d como um parmetro de entrada e sada. Isto , a interface da funo
deve ser:
void dia_seguinte(struct data *d)
21.3
que receba duas medidas de tempo no formato hh:mm:ss e calcule o tempo decorrido entre essas duas medidas de tempo. Tenha cuidado com um par de medidas de
tempo que cruzam a meia noite.
(b) Escreva um programa que receba dois horrios no formato hh:mm:ss e calcule o
tempo decorrido entre esses dois horrios. Use a funo anterior.
FACOM
UFMS
208
FACOM
F UNES
E REGISTROS
UFMS
AULA
B IBLIOTECA
22
PADRO
Nas ltimas aulas aprendemos a construir nossas prprias funes. Os benefcios dessa
prtica so muitos, como percebemos. Entre eles, podemos destacar abstrao, organizao e reaproveitamento de cdigo, por exemplo. Felizmente, no sempre que precisamos de um trecho de cdigo que realiza um determinado processamento que temos necessariamente de programar esse trecho, construindo uma funo. A linguagem C fornece
uma biblioteca padro de funes que nos ajuda em muitas tarefas importantes, desde funes de entrada e sada de dados, manipulao de cadeias de caracteres at funes matemticas. Nesta aula, veremos algumas funes importantes, destacando que muitas outras
no sero cobertas aqui. Os interessados em mais informaes devem buscar a pgina do
guia de referncia da biblioteca da linguagem C. Nesta aula, cobrimos com algum detalhe os
arquivos que contm definies de macros, tipos e os prottipos das funes da biblioteca
padro de funes da linguagem C. Esses arquivos so tambm conhecidos como arquivoscabealhos e tm extenso .h, do ingls header.
Iniciamos com uma viso sobre os qualificadores de tipos existentes na linguagem C, fundamentais especialmente na declarao de parmetros sensveis alterao, tais como os vetores
e as matrizes, que so sempre parmetros por referncia. Em seguida, definimos arquivoscabealhos para, por fim, cobrir os arquivos-cabealhos da biblioteca padro da linguagem C.
Esta aula um guia de referncia da biblioteca padro da linguagem C, suas constantes, tipos
e funes principais. Algumas funes, por serem muito especficas, no foram listadas aqui.
A aula baseada nas referncias [17, 16].
210
B IBLIOTECA
PADRO
cria um objeto const do tipo int com identificador n cujo valor 10 . A declarao abaixo:
22.2 Arquivo-cabealho
A diretiva #include ordena o pr-processador a abrir um arquivo especificado e a inserir seu contedo no arquivo atual. Assim, se queremos que vrios arquivos de cdigo fonte
tenham acesso mesma informao, devemos colocar essa informao em um arquivo e ento usar a diretiva #include para trazer o contedo do arquivo em cada arquivo de cdigo
fonte. Arquivos que so includos dessa forma so chamados de arquivos-cabealhos, do ingls header files ou tambm include files. Por conveno, um arquivo como esse tem a extenso
.h .
A diretiva #include pode ser usada de duas formas. A primeira forma usada para
arquivos-cabealhos que pertencem biblioteca padro da linguagem C:
FACOM
UFMS
211
#include <arquivo.h>
A segunda forma usada para todos os outros arquivos-cabealhos, incluindo aqueles que
so escritos por programadores(as):
#include "arquivo.h"
A diferena entre as duas formas se d pela maneira como o compilador busca o arquivocabealho. Na primeira, o compilador busca o arquivo-cabealho no(s) diretrio(s) em que os
arquivos-cabealhos do sistema se encontram. Nos sistemas baseados no UNIX, como o LINUX,
os arquivos-cabealhos so mantidos usualmente no diretrio /usr/include . Na segunda
forma, a busca realizada no diretrio corrente e, em seguida, no(s) diretrio(s) em que os
arquivos-cabealhos do sistema se encontram.
Arquivos-cabealhos auxiliam no compartilhamento de definies de macros, de tipos e de
prottipos de funes por dois ou mais arquivos de cdigo fonte.
Abaixo apresentamos o arquivo-cabealho completo assert.h da biblioteca padro da
linguagem C.
FACOM
<assert.h>
UFMS
212
B IBLIOTECA
PADRO
#ifdef _ASSERT_H
# undef _ASSERT_H
# undef assert
# undef __ASSERT_VOID_CAST
# ifdef __USE_GNU
# undef assert_perror
# endif
#endif /* assert.h
*/
#define _ASSERT_H
1
#include <features.h>
#if defined __cplusplus && __GNUC_PREREQ (2,95)
# define __ASSERT_VOID_CAST static_cast<void>
#else
# define __ASSERT_VOID_CAST (void)
#endif
/* void assert (int expression);
If NDEBUG is defined, do nothing.
If not, and EXPRESSION is zero, print an error message and abort.
#ifdef NDEBUG
# define assert(expr)
(__ASSERT_VOID_CAST (0))
(__ASSERT_VOID_CAST (0))
FACOM
UFMS
DA BIBLIOTECA PADRO
213
__END_DECLS
#endif /* Not _ASSERT_H_DECLS */
# define assert(expr)
\
((expr)
\
? __ASSERT_VOID_CAST (0)
\
: __assert_fail (__STRING(expr), __FILE__, __LINE__,
__ASSERT_FUNCTION))
# ifdef __USE_GNU
# define assert_perror(errnum)
\
(!(errnum)
\
? __ASSERT_VOID_CAST (0)
\
: __assert_perror_fail ((errnum), __FILE__, __LINE__,
__ASSERT_FUNCTION))
# endif
/* Version 2.4 and later of GCC define a magical variable
__PRETTY_FUNCTION__ which contains the name of
the function currently being defined.
This is broken in G++ before version 2.6.
C9x has a similar variable called __func__, but prefer the GCC
one since it demangles C++ function names. */
# if defined __cplusplus ? __GNUC_PREREQ (2, 6) : __GNUC_PREREQ (2, 4)
#
define __ASSERT_FUNCTION
__PRETTY_FUNCTION__
# else
#
if defined __STDC_VERSION__ && __STDC_VERSION__ >= 199901L
#
define __ASSERT_FUNCTION
__func__
#
else
#
define __ASSERT_FUNCTION
((__const char *) 0)
#
endif
# endif
#endif /* NDEBUG. */
UFMS
214
B IBLIOTECA
PADRO
verificao nos programas. Se uma verificao falha, o programa termina sua execuo.
No exemplo de trecho de cdigo a seguir, a macro assert monitora o valor do ndice i do
vetor v. Se esse valor no est no intervalo especificado, o programa terminado.
FACOM
UFMS
DA BIBLIOTECA PADRO
215
int isgraph(int c)
22.3.3 Erros
A biblioteca de monitoramento de erros pode ser acessada por meio do arquivo-cabealho
errno.h. Algumas funes da biblioteca padro da linguagem C indicam ocorrncia de uma
falha atravs do armazenamento de um cdigo de erro, um nmero inteiro positivo, em
errno , uma varivel do tipo int declarada em errno.h. O trecho de cdigo a seguir mostra
o uso da varivel errno :
FACOM
UFMS
216
B IBLIOTECA
PADRO
errno = 0;
y = sqrt(x);
if (errno != 0)
exit(EXIT_FAILURE);
Nesse trecho de cdigo, observe que inicializamos a varivel errno declarada na biblioteca
errno.h. Se o valor dessa varivel diferente de zero aps a execuo da funo sqrt , isso
significa que um erro ocorreu em sua execuo, como por exemplo, quando o valor de x
negativo.
O valor armazenado na varivel errno , em geral, EDOM ou ERANGE , ambas macros
definidas em errno.h. Essas macros representam os dois tipos de erros que podem ocorrer
quando uma funo matemtica chamada: erro de domnio ou erro de intervalo, respectivamente. No exemplo acima, se x tem valor negativo, ento o valor de EDOM armazenado na
varivel errno . Por outro lado, se o valor devolvido por uma funo muito grande, ultrapassando a capacidade de representao do tipo do valor a ser devolvido pela funo, ento
o valor ERANGE armazenado em errno . Por exemplo, se 1000 argumento da funo exp,
ento isso provoca um erro de intervalo j que e1000 muito grande para ser representado por
um double .
22.3.5 Localizao
locale.h o arquivo-cabealho que contm as informaes da biblioteca de funes que
ajudam um programa a adaptar seu comportamento a um pas ou a uma regio geogrfica.
O comportamento especfico de um local inclui a forma como os nmeros so impressos, o
formato dos valores monetrios, o conjunto de caracteres e a aparncia da data e da hora.
Com a mudana de um local, um programa pode adaptar seu comportamento para uma
rea diferente do mundo. Mas essa mudana pode afetar muitas partes da biblioteca, algumas
das quais podemos preferir no alterar.
Constantes
Podemos usar uma das macros a seguir para especificar uma categoria:
FACOM
UFMS
217
DA BIBLIOTECA PADRO
LC_COLLATE
Funes
Duas funes so declaradas nesta biblioteca:
char *setlocale(int category, const char *locale)
Altera o local atual para uma nica categoria ou para todas. Se o primeiro argumento
uma das macros definidas na seo anterior, uma chamada a esta funo afeta apenas
uma categoria. Se o primeiro argumento LC_ALL , a chamada afeta todas as categorias.
A linguagem C padro define apenas dois valores para o segundo argumento: "C" e "".
O primeiro o padro e, por exemplo, o separador decimal um ponto. Se o segundo argumento especificado ento as funes da biblioteca comportam-se como local nativo
e permitem que o programa adapte seu comportamento para o ambiente local.
struct lconv *localeconv(void)
Devolve um apontador para um registro do tipo struct lconv. Os campos desse registro contm informaes detalhadas sobe o local atual.
22.3.6 Matemtica
A biblioteca matemtica da linguagem C pode ser acessada atravs do arquivo-cabealho
math.h, que contm os prottipos de diversas funes matemticas teis, agrupadas em fun-
UFMS
218
B IBLIOTECA
PADRO
Constantes
Uma nica macro definida neste arquivo-cabealho: HUGE_VAL . Essa macro indica que
o valor devolvido por uma funo muito grande para ser representado como um nmero de
preciso dupla. HUGE_VAL do tipo double e pode ser entendido como infinito.
Erros
Todas as funes da biblioteca matemtica da linguagem C manipulam erros de forma similar. No caso em que o argumento passado funo excede o intervalo permitido, ento a
varivel errno recebe o valor EDOM . O valor devolvido pela funo depende da mquina. No
caso do valor devolvido ser muito grande para ser representado como um nmero de preciso
dupla, ento a funo devolve a macro HUGE_VAL e atualiza a varivel errno para ERANGE .
Se o valor muito pequeno para ser representado como um nmero de preciso dupla, ento
a funo devolve zero. Nesse caso, se a varivel errno recebe ERANGE ou no uma deciso
dependente da mquina.
Funes trigonomtricas
Listamos abaixo as interfaces das funes trigonomtricas no arquivo-cabealho math.h,
acompanhadas de explicaes:
double cos(double x)
Devolve o arco-tangente em radianos de y/x baseado nos sinais de ambos os valores para
determinar o quadrante correto. O valor devolvido est no intervalo [/2, /2];
FACOM
UFMS
DA BIBLIOTECA PADRO
219
double cosh(double x)
Subdivide o nmero com ponto flutuante x nas partes inteira e fracionria. O valor devolvido pela funo a parte fracionria, depois do ponto decimal, e o parmetro de entrada
e sada inteiro contm a parte inteira de x;
double pow(double x, double y)
UFMS
220
B IBLIOTECA
PADRO
Outras funes
Listamos abaixo as interfaces de outras funes matemticas em math.h, acompanhadas de
explicaes:
double ceil(double x)
O tipo typedef jmp_buf definido nesta biblioteca. Uma varivel desse tipo armazena as
informaes atuais do ambiente, para uso posterior nas funes da biblioteca.
As duas funes desta biblioteca so listadas abaixo:
int setjmp(jmp_buf amb)
O ambiente armazenado na varivel amb por uma chamada prvia funo setjmp
recuperado. Uma salto ao ponto onde setjmp foi chamada realizado, e o contedo
armazenado em valor devolvido setjmp . Esse valor deve ser um nmero inteiro
diferente de zero.
FACOM
UFMS
DA BIBLIOTECA PADRO
221
Constantes e variveis
O tipo sig_atomic_t , na verdade um apelido para o tipo int , usado para declarao
de variveis que manipulam erros.
As macros com identificadores iniciando com SIG_ so usadas com a funo signal :
SIG_DFL
Sinal de erro;
SIG_IGN
Ignora sinal.
As macros com identificadores iniciando com SIG so usadas para representar um nmero
de sinal:
SIGABRT
Erro de ponto flutuante, causado por diviso por zero, operao no vlida, etc;
SIGILL
Operao ilegal;
SIGINT
Acesso no vlido a uma poro de memria, tal como violao de segmento ou violao
de memria;
SIGTERM
Requisio de trmino.
FACOM
UFMS
222
B IBLIOTECA
PADRO
Funes
void (*signal(int sinal, void (*func)(int)))(int)
Faz com que o sinal sinal seja gerado. O argumento sinal compatvel com as macros SIG .
UFMS
DA BIBLIOTECA PADRO
223
outros arquivos-cabealhos.
Constantes
Listamos abaixo as macros definidas em stdlib.h, acompanhadas de explicaes:
NULL
Valores usados pela funo exit para devolver o estado do trmino da execuo de um
programa;
RAND_MAX
UFMS
224
B IBLIOTECA
PADRO
UFMS
DA BIBLIOTECA PADRO
225
int abs(int x)
Concatena at n caracteres da cadeia de caracteres cadeia2 no final da cadeia de caracteres cadeia1 . O caractere nulo \0 da cadeia1 sobrescrito. O caractere nulo
sempre adicionado na cadeia1 . Devolve um apontador para a cadeia1 ;
int strcmp(const char *cadeia1, const char *cadeia2)
UFMS
226
B IBLIOTECA
PADRO
Procura o primeiro caractere na cadeia1 que corresponde a algum caractere especificado na cadeia2 . Se encontrado, um apontador para a localizao deste caractere
devolvido. Caso contrrio, o apontador para nulo devolvido;
char *strchr(const char *cadeia, int c)
Encontra a primeira seqncia de caracteres na cadeia1 que contm qualquer caracter da cadeia2 . Devolve o comprimento desta primeira seqncia de caracteres que
corresponde cadeia2 ;
size_t strcspn(const char *cadeia1, const char *cadeia2)
Encontra a primeira seqncia de caracteres na cadeia1 que no contm qualquer caracter da cadeia2 . Devolve o comprimento desta primeira seqncia de caracteres que
no corresponde cadeia2 ;
FACOM
UFMS
DA BIBLIOTECA PADRO
227
Exerccios
22.1
que receba um nmero real x e um nmero positivo real > 0, e calcule uma aproximao para cos x, onde x dado em radianos, atravs da seguinte srie:
cos x = 1
x2 x4 x6
x2k
+
+ . . . + (1)k
+ ...
2!
4!
6!
(2k)!
x2k
(2k)! ,
at que Tk < .
que receba um nmero real x e um nmero real > 0, e calcule uma aproximao
para sen x, onde x dado em radianos, atravs da seguinte srie:
sen x =
x2k+1
x3 x5
x
+
. . . + (1)k
+ ...
1!
3!
5!
(2k + 1)!
x2k+1
(2k+1)! ,
at que Tk < .
FACOM
UFMS
228
B IBLIOTECA
PADRO
que receba duas cadeias de caracteres palavra e frase e um inteiro pos e verifique se a cadeia de caracteres palavra ocorre na posio pos da cadeia de caracteres frase . Em caso positivo, a funo deve devolver 1. Em caso negativo, deve
devolver zero.
(b) Escreva um programa que receba duas cadeias de caracteres padrao e texto ,
com m e n caracteres respectivamente e m 6 n, e imprima o nmero de vezes que
padrao ocorre em texto .
Use todas as funes da biblioteca string que puder.
FACOM
UFMS
AULA
D EPURAO
23
DE PROGRAMAS
medida que temos resolvido problemas maiores e mais complexos, natural e conseqentemente nossos programas tm ganhado complexidade e extenso. Uso correto de estruturas
de programao, identificadores de variveis significativos, indentao, documentao, tudo
isso tem sido feito na tentativa de escrever programas corretamente. Ou seja, nosso desejo
sempre escrever programas eficientes, coesos e corretos.
Infelizmente, nem sempre isso possvel. Por falta de ateno, de experincia, de disciplina,
ou mesmo pela complexidade do problema que precisamos resolver, no incomum o desenvolvimento de um programa que contm erros. Nesta aula, aprenderemos a usar um poderoso
depurador de programas interativo, chamado GDB, como aliado na construo de programas
corretos. Veremos algumas de suas principais caractersticas, talvez as mais teis. Interessados(as) em mais informaes e caractersticas avanadas desta ferramenta devem consultar a
pgina e o manual da mesma.
Richard Matthew Stallman (), nascido nos Estados Unidos, fsico, ativista poltico e ativista de software.
229
230
D EPURAO
DE PROGRAMAS
GDB um software livre, protegido pela Licena Pblica Geral (GPL) da GNU . A GPL d a
seu usurio a liberdade para copiar ou adaptar um programa licenciado, mas qualquer pessoa
que faz uma cpia tambm deve ter a liberdade de modificar aquela cpia o que significa que
deve ter acesso ao cdigo fonte , e a liberdade de distribuir essas cpias. Empresas de software
tpicas usam o copyright para limitar a liberdade dos usurios; a Fundao para o Software Livre
(Free Software Foundation) usa a GPL para preservar essas liberdades. Fundamentalmente, a
Licena Pblica Geral (GPL) uma licena que diz que todas as pessoas tm essas liberdades e
que ningum pode restringi-las.
Para executar um programa com auxlio do depurador GDB, o programa fonte na linguagem C deve ser compilado com o compilador GCC usando a diretiva de compilao ou opo
-g . Essa diretiva de compilao faz com que o compilador adicione informaes extras no
programa executvel que sero usadas pelo GDB.
prompt$ gdb
GNU gdb 6.8-debian
Copyright (C) 2008 Free Software Foundation, Inc.
License GPLv3+: GNU GPL version 3 or later <http://gnu.org/licenses/gpl.html>
This is free software: you are free to change and redistribute it.
There is NO WARRANTY, to the extent permitted by law. Type "show copying"
and "show warranty" for details.
This GDB was configured as "x86_64-linux-gnu".
(gdb)
faz a chamada do depurador GDB com a carga do programa executvel consecutivos , que
foi previamente gerado pelo processo de compilao, usando o compilador GCC com a diretiva
de compilao -g .
FACOM
UFMS
23.3 S INTAXE
Para sair do
seguir:
GDB
231
(gdb) quit
prompt$
Usando o nome de uma das classes gerais de ajuda como um argumento do comando
help , podemos obter uma lista dos comandos desta classe. Por exemplo,
FACOM
UFMS
232
D EPURAO
DE PROGRAMAS
Tambm podemos usar o comando help diretamente com o nome de um comando que
queremos ajuda. Por exemplo,
GDB
run , que pode ser abreviado por r . Este programa executvel deve ter sido usado como um
parmetro na chamada do depurador ou ento deve ser carregado no GDB usando o comando
file ou exec-file .
UFMS
23.4 P ONTOS
233
DE PARADA
What
in main at consecutivos.c:9
in main at consecutivos.c:18
iguais
Muitas vezes, queremos eliminar um ponto de parada que j cumpriu o seu papel na depurao do programa e no queremos mais que o programa seja interrompido naquele ponto
previamente especificado. Podemos usar os comandos clear ou delete para remover um
ou mais pontos de parada de um programa. Os comandos clear e delete , com um argumento numrico, removem um ponto de parada especificado. Por exemplo, os comandos
clear 1 e delete 2 removem os pontos de parada identificados pelos nmeros 1 e 2, res-
FACOM
UFMS
234
D EPURAO
DE PROGRAMAS
UFMS
23.6 V ERIFICAO
DE DADOS
235
(gdb) l 1,40
1
#include <stdio.h>
2
3
/* Recebe um nmero inteiro positivo e verifica se
4
esse nmero tem dois dgitos consecutivos iguais */
5
int main(void)
6
{
7
int num, ant, prox, iguais;
8
9
printf("\nInforme um nmero: ");
10
scanf("%d", &num);
11
12
prox = num % 10;
13
iguais = 0;
14
while (num != 0 && !iguais) {
15
num = num / 10;
16
ant = prox;
17
prox = num % 10;
18
if (ant == prox)
19
iguais = 1;
20
}
21
22
if (iguais)
23
printf("Nmero tem dois dgitos consecutivos iguais\n");
24
else
25
printf("Nmero no tem dois dgitos consecutivos iguais\n");
26
27
return 0;
28
}
(gdb)
UFMS
236
D EPURAO
DE PROGRAMAS
Significado
list m,n
VARIVEIS E E XPRESSES
print expr
display expr
info display
delete display n
info locals
set var var = expr
Imprime expr
Adiciona expr lista de impresso automtica
Mostra a lista de impresso automtica
Remove a expresso de nmero n da lista de impresso automtica
Mostra o contedo de todas as variveis locais na funo corrente
Atribui expr para a varivel var
P ONTOS DE PARADA
break n
break n if expr
break func
watch expr
clear [n]
delete [n]
enable [n]
disable [n]
info break
E XECUO DO P ROGRAMA
file [prog]
info program
quit
A JUDA
help
help classe
help comando
exec-file [prog]
run
continue
step [n]
next [n]
FACOM
UFMS
23.9 E XEMPLOS
DE EXECUO
237
Esta uma relao dos comandos que aprendemos nesta aula, com uma explicao breve
sobre cada um. A inteno agrupar os comandos em um lugar s, para que a relao nos sirva
de referncia. Vale reiterar que o GDB possui muitos outros comandos interessantes, mas que
infelizmente no puderam ser cobertos neste texto. O(A) leitor(a) interessado(a) deve consultar
as referncias desta aula para mais informaes.
Iniciamos o processo compilando o programa 23.1 adequadamente e carregando o programa executvel gerado no GDB:
FACOM
UFMS
238
D EPURAO
DE PROGRAMAS
Para verificar se o programa foi de fato carregado na chamada do GDB, podemos usar o
comando list para ver seu cdigo fonte ou ento o comando info program , para visualizar
o estado do programa:
(gdb) l 1,14
1
#include <stdio.h>
2
3
/* Recebe um nmero inteiro positivo e verifica se
4
esse nmero tem dois dgitos consecutivos iguais */
5
int main(void)
6
{
7
int num, ant, prox, iguais;
8
9
printf("\nInforme um nmero: ");
10
scanf("%d", &num);
11
12
prox = num % 10;
13
iguais = 0;
14
while (num != 0 && !iguais) {
(gdb)
ou
(gdb) info program
The program being debugged is not being run.
(gdb)
(gdb) run
Starting program:
/ensino/disciplinas/api/2010/programas/consecutivos
FACOM
UFMS
23.9 E XEMPLOS
DE EXECUO
239
A execuo acima foi realizada dentro do GDB, sem a adio de qualquer ponto de parada.
Como o programa ainda continua carregado no GDB, podemos execut-lo quantas vezes quisermos. Antes de iniciar a prxima execuo, vamos adicionar alguns pontos de parada no
programa:
(gdb) break 9
Breakpoint 1 at 0x400575: file consecutivos.c, line 9.
(gdb)
(gdb) run
Starting program:
/ensino/disciplinas/api/programas/consecutivos
Observe que todas as variveis declaradas constam da relao apresentada pelo GDB e que seus
contedos so valores estranhos, j que nenhuma dessas variveis foi inicializada at a linha 9
do programa.
Vamos adicionar mais pontos de parada neste programa, um deles um breakpoint associado
a uma expresso lgica e o outro um watchpoint associado a uma varivel:
Agora, podemos visualizar todos os pontos de parada associados a este programa com o
comando info break :
FACOM
UFMS
240
D EPURAO
DE PROGRAMAS
What
in main at consecutivos.c:9
in main at consecutivos.c:18
iguais
(gdb) continue
Continuing.
Informe um nmero: 55123
Hardware watchpoint 3: iguais
Old value = 32767
New value = 0
0x00000000004005d3 in main () at consecutivos.c:13
13
iguais = 0;
(gdb)
(gdb) continue
Continuing.
Breakpoint 2, main () at consecutivos.c:18
18
if (ant == prox)
(gdb)
O GDB ento interrompeu a execuo do programa devido ao breakpoint 2, na linha 18 do programa. Neste ponto, deve ter ocorrido o evento em que os contedos das variveis ant e
prox coincidem. Para verificar se esse evento de fato ocorreu, podemos usar o comando
print para verificar os contedos dessas variveis:
FACOM
UFMS
23.9 E XEMPLOS
DE EXECUO
241
(gdb) continue
Continuing.
Hardware watchpoint 3: iguais
Old value = 0
New value = 1
main () at consecutivos.c:14
14
while (num != 0 && !iguais) {
(gdb)
Observe que o programa foi interrompido pelo watchpoint, j que o contedo da varivel
iguais foi modificado de 0 para 1 na linha 19 do programa. Assim, a prxima linha a ser
executada a linha 14, como mostrado pelo GDB.
Vamos dar uma olhada no contedo das variveis da funo main :
(gdb) continue
Continuing.
Nmero tem dois dgitos consecutivos iguais.
Watchpoint 3 deleted because the program has left the block in
which its expression is valid.
0x00007fd256015934 in exit () from /lib/libc.so.6
(gdb)
Mais uma anlise detalhada e mais alguns testes sobre o programa 23.1 nos permitem afirmar com alguma convico que este programa est correto e que soluciona o exerccio 7.3. O
fato novo que essa afirmao foi feita tambm com o GDB nos auxiliando. Para provar formalmente que o programa 23.1 est correto, devemos descrever algum invariante do processo
iterativo das linhas 14 at 20 do programa e ento provar por induo a sua validade. Essa
tcnica de demonstrao de correo vale para programas que possuem uma ou mais estruturas de repetio, como o caso do programa 23.1. Aprenderemos mais sobre demonstrao de
correo de programas e algoritmos em disciplinas posteriores do nosso curso.
No prximo exemplo vamos executar um programa sob o controle do GDB que no soluciona o problema associado, isto , contm algum erro que, primeira vista, no conseguimos
corrigir. O programa 23.2 se prope a implementar a ordenao por seleo.
FACOM
UFMS
242
D EPURAO
DE PROGRAMAS
Programa 23.2: Uma verso de um programa que deveria realizar a ordenao por seleo.
#include <stdio.h>
#define MAX 10
/* Recebe um nmero inteiro n > 0 e uma seqncia de n nmeros inteiros, e mostra essa seqncia em ordem crescente */
int main(void)
{
int i, j, n, menor, indice, aux, A[MAX];
scanf("%d", &n);
for (i = 0; i < n; i++)
scanf("%d", &A[i]);
for (i = 0; i < n-1; i++) {
menor = A[i];
indice = i;
for (j = n-1; j > i; j++) {
if (A[j] < menor) {
menor = A[j];
indice = j;
}
}
aux = A[i];
A[i] = A[indice];
A[indice] = aux;
}
for (i = 0; i < n; i++)
printf("%d ", A[i]);
printf("\n");
return 0;
}
prompt$ ./ord-selecao
8
7 5 4 1 8 6 2 3
Falha de segmentao
prompt$
Esse erro no nos d nenhuma dica de onde procur-lo. E se j nos debruamos sobre o
cdigo fonte e no conseguimos encontr-lo, a melhor idia usar um depurador para nos
ajudar. Neste exemplo, mostraremos o uso do GDB sem muitas interrupes no texto, a menos
que necessrias. Ento, segue uma depurao do programa 23.2.
FACOM
UFMS
23.9 E XEMPLOS
DE EXECUO
243
FACOM
UFMS
244
D EPURAO
DE PROGRAMAS
(gdb) continue
Continuing.
Hardware watchpoint 2: menor
Old value = 3
New value = -1075407768
main () at ord-selecao.c:21
21
indice = j;
3: i = 0
2: j = 9
1: A[j] = -1075407768
(gdb) c
Continuing.
Hardware watchpoint 2: menor
Old value = -1075407768
New value = -1208630704
main () at ord-selecao.c:21
21
indice = j;
3: i = 0
2: j = 15
1: A[j] = -1208630704
(gdb) step 100
Hardware watchpoint 2: menor
Old value = -1208630704
New value = -1210084267
main () at ord-selecao.c:21
21
indice = j;
3: i = 0
2: j = 18
1: A[j] = -1210084267
(gdb) set var j=-1
(gdb) set var i=n
(gdb) continue
Continuing.
7 5 4 1 8 6 2 3
Watchpoint 2 deleted because the program has left the block in
which its expression is valid.
0x00007fd256015934 in exit () from /lib/libc.so.6
(gdb)
FACOM
UFMS
23.9 E XEMPLOS
245
DE EXECUO
FACOM
UFMS
246
D EPURAO
(gdb)
45
(gdb)
48
(gdb)
44
45
46
47
48
49
50
(gdb)
DE PROGRAMAS
step
if (sufixo(x, y))
next
x = x / 10;
list 44,50
while (x >= y && !subseq)
if (sufixo(x, y))
subseq = VERDADEIRO;
else
x = x / 10;
if (subseq)
printf("%d S %d\n", a, b);
step
FACOM
UFMS
23.9 E XEMPLOS
DE EXECUO
247
(gdb) continue
Continuing.
Breakpoint 3, sufixo (a=5, b=0) at subsequencia.c:19
19
return suf;
(gdb) print suf
$3 = 1
(gdb) step
20
}
(gdb) step
Hardware watchpoint 2 deleted because the program has left the block
in which its expression is valid.
main () at subsequencia.c:46
46
subseq = VERDADEIRO;
(gdb) step
Breakpoint 1, main () at subsequencia.c:44
44
while (x >= y && !subseq)
(gdb) step
49
if (subseq)
(gdb) step
50
printf("%d S %d\n", a, b);
(gdb) step
567 S 55678
53
n-;
(gdb) step
29
while (n > 0) {
(gdb) step
55
return 0;
(gdb) step
56
}
(gdb) step
0x00007fdc477561a6 in __libc_start_main () from /lib/libc.so.6
(gdb)
FACOM
UFMS
248
D EPURAO
DE PROGRAMAS
FACOM
UFMS
AULA
24
P R - PROCESSADOR
O pr-processador um mdulo da linguagem C que edita um programa antes de sua compilao. uma ferramenta poderosa e que diferencia a linguagem C das demais linguagens de
programao do alto nvel. As diretivas #include e #define que usamos em aulas anteriores so manipuladas pelo pr-processador, assim como outras que veremos nesta aula. Apesar
de poderoso, o mal uso do pr-processador pode produzir programas praticamente ininteligveis e/ou com erros muito difceis de encontrar. Esta aula baseada na referncia [17].
24.1 Funcionamento
As diretivas de pr-processamento controlam o comportamento do pr-processador. Uma
diretiva do pr-processador um comando que inicia com o caractere # . At o momento,
vimos duas das diretivas do pr-processador da linguagem C: #include e #define . Revisaremos essas diretivas adiante.
A figura 24.1 ilustra o papel do pr-processador durante o processo de compilao.
programa em C
pr-processador
programa em C modificado
compilador
cdigo objeto
250
P R - PROCESSADOR
define
MAX
100
FACOM
\
\
\
UFMS
24.3 D EFINIES
251
DE MACROS
onde lista-de-troca uma seqncia qualquer de itens. Essa lista pode incluir identificadores, palavras reservadas, constantes numricas, constantes de caracteres, literais, operadores
e pontuao. Quando encontra uma definio de uma macro, o pr-processador toma nota
que o identificador representa a lista-de-troca . Sempre que identificador ocorre
posteriormente no arquivo, o pr-processador o substitui pela lista-de-troca .
Um erro freqente na definio de macros a incluso de smbolos extras, que conseqentemente faro parte da lista de troca. Abaixo so mostrados dois exemplos de erros como esse.
A traduo do trecho de cdigo acima realizada pelo pr-processador gera o seguinte trecho
de cdigo modificado, correspondente s duas ltima linhas:
UFMS
252
P R - PROCESSADOR
Podemos usar macros para dar nomes a valores numricos, caracteres e literais, como ilustrado abaixo:
#define
#define
#define
#define
#define
#define
COMPRIMENTO
VERDADEIRO
FALSO
PI
ENTER
ERRO
80
1
0
3.141592
\n
"Erro: memria insuficiente\n"
Usar a diretiva #define para criar nomes para constantes tem diversas vantagens, como
tornar os programas mais fceis de ler e de modificar, ajudar a evitar inconsistncias e erros
tipogrficos, permitir pequenas mudanas na sintaxe da linguagem, renomear tipos e controlar
a compilao condicional.
#include <arquivo.h>
A segunda forma usada para todos os outros arquivos-cabealhos, incluindo aqueles que
so escritos por programadores(as):
#include "arquivo.h"
A diferena entre as duas formas se d pela maneira como o compilador busca o arquivocabealho. Na primeira, o compilador busca o arquivo-cabealho no(s) diretrio(s) em que os
arquivos-cabealhos do sistema se encontram. Nos sistemas baseados no UNIX, como o LINUX,
os arquivos-cabealhos so mantidos usualmente no diretrio /usr/include . Na segunda
forma, a busca realizada no diretrio corrente e, em seguida, no(s) diretrio(s) em que os
arquivos-cabealhos do sistema se encontram.
Arquivos-cabealhos auxiliam no compartilhamento de definies de macros, de tipos e de
prottipos de funes por dois ou mais arquivos de cdigo fonte.
FACOM
UFMS
24.4 I NCLUSO
DE ARQUIVOS - CABEALHOS
253
PAR
IMPAR
Algoritmo
inicio
fim
escreva
leia
se
senao
enquanto
devolva
0
1
main
{
}
printf
scanf
if
else
while
return
FACOM
UFMS
254
P R - PROCESSADOR
#if expresso-constante
#define DEBUG 1
.
.
.
#if DEBUG
printf("Valor de i = %d\n", i);
printf("Valor de j = %d\n", j);
#endif
Durante o pr-processamento, a diretiva #if verifica o valor de DEBUG . Como seu valor diferente de zero, o pr-processador mantm as duas chamadas funo printf no
programa, mas as linhas contendo as diretivas #if e #endif sero eliminadas aps o prprocessamento. Se modificamos o valor de DEBUG para 0 (zero) e recompilamos o programa,
ento o pr-processador remove todas as 4 linhas do programa. importante notar que a diretiva #if trata identificadores no definidos como macros que tm o valor 0 (zero). Assim, se
esquecemos de definir DEBUG , o teste
#if DEBUG
UFMS
24.5 C OMPILAO
255
CONDICIONAL
#if !DEBUG
e
#ifndef identificador
Linhas a serem includas se o identificador no est definido como uma macro
#endif
As diretivas #elif e #else podem ser usadas em conjunto com as diretivas #if ,
#ifdef e #ifndef quando aninhamento de blocos so necessrios. O formato geral dessas
diretivas apresentado abaixo:
#elif expresso-constante
e
#else
#if expresso1
Linhas a serem includas se expresso1 diferente de zero
#elif expresso2
Linhas a serem includas se expresso2 diferente de zero
#else
Linhas a serem includas em caso contrrio
#endif
A compilao condicional, alm de auxiliar na depurao de programas, tambm tem outros usos como na construo de programas que podem executados em computadores diferentes, em sistemas operacionais diferentes, que podem ser compilados por compiladores diferentes, no suporte definies padronizadas de macros, entre outros.
FACOM
UFMS
256
P R - PROCESSADOR
#error mensagem
onde mensagem uma seqncia qualquer de caracteres. Um exemplo de uso dessa diretiva
apresentado no trecho de cdigo a seguir:
#ifdef LINUX
.
.
.
#else
#error Sistema operacional no especificado
#endif
Se o pr-processador encontra uma diretiva #error , isso sinal de que uma falha grave
ocorreu no programa e alguns compiladores terminam imediatamente a compilao.
A diretiva #line usada para alterar a forma como as linhas do programa so numeradas.
O formato geral dessa diretiva apresentado abaixo:
#line n
e
#line n "arquivo"
No primeiro formato, as linhas do programa so numeradas a partir do nmero n . No segundo, as linhas do programa no arquivo so numeradas a partir do nmero n . Muitos
compiladores usam essa informao quando precisam gerar mensagens de erro.
Por fim, a diretiva #pragma permite que uma diretiva seja criada pelo(a) programador(a).
O formato geral dessa diretiva dado abaixo:
#pragma diretiva
FACOM
UFMS
R EFERNCIAS B IBLIOGRFICAS
258
REFERNCIAS BIBLIOGRFICAS
[12] K. Zuse, Verfahren zur selbstttigen Durchfhrung von Rechnungen mit Hilfe von Rechenmaschinen. Patentanmeldung Z 23 139 GMD Nr. 005/021, 1936. 2.1
[13] H. Lukoff, From Dits to Bits... a Personal History of the Electronic Computer. Hawley
Books, 1979. 2.1
[14] J. von Neumann, First draft of a report on the EDVAC, tech. rep., Moore School of Electrical Engineering University of Pennsylvania, 1945. 2.1, 2.3
[15] P. Feofiloff, Algoritmos em linguagem C. Editora Campus/Elsevier, 2009. 4.5, 4.5, 5, 5.3.1,
7, 8, 9, 10, 11, 12, 13, 14, 15, 16, 17, 18, 19, 20, 21
[16] K. N. King, C Programming A Modern Approach. W. W. Norton & Company, Inc.,
2nd ed., 2008. 5, 6, 7, 8, 9, 10, 11, 12, 13, 14, 15, 16, 17, 18, 19, 20, 21, 22
[17] E. Huss, The C Library Reference Guide.
http://www.acm.uiuc.edu/webmonkeys/book/c_guide/, 1997.
ltimo acesso em 10 de maro de 2010. 22, 24
[18] S. A. Cook, The complexity of theorem-proving procedures, in Proceedings of the Third
Annual ACM Symposium on Theory of Computing, (Shaker Heights, Ohio, United States), pp. 151158, SIGACT: ACM Special Interest Group on Algorithms and Computation
Theory, ACM, 1971.
[19] B. W. Kernighan and R. Pike, The Practice of Programming. Addison-Wesley Professional,
1999.
[20] B. W. Kernighan and D. M. Ritchie, C Programming Language. Prentice Hall, 2nd ed.,
1988.
[21] D. E. Knuth, The Art of Computer Programming, vol. 17. Addison-Wesley, 3rd ed., 1997.
[22] S. G. Kochan, Unix Shell Programming. Sams Publishing, 3rd ed., 2003.
[23] K. A. Lambert, D. W. Nance, and T. L. Naps, Introduction to Computer Science with C++.
West Publishing Company, 1996.
[24] L. A. Levin, Universal sequential search problems, Problemy Peredachi Informatsii,
vol. 9, no. 3, pp. 115116, 1973.
[25] G. J. Pothering and T. L. Naps, Introduction to Data Structures and Algorithm Analysis
with C++. West Publishing Company, 1995.
[26] S. S. Skiena and M. Revilla, Programming Challenges. Springer, 2003.
[27] A. Tucker, A. P. Bernat, W. J. Bradley, R. D. Cupper, and G. W. Scragg, Fundamentals
of Computing I Logic, Problem Solving, Programs, and Computers C++ Edition.
McGraw-Hill, 1995.
[28] The past is the future at Bletchley Park.
http://news.bbc.co.uk/2/hi/technology/6895759.stm.
Mark Ward, Technology Correspondent, BBC News website, julho de 2007, ltimo acesso
em 10 de maro de 2010.
FACOM
UFMS