Anda di halaman 1dari 63

Aprenda a Programar

Uma Breve Introduo

Henrique Dias
Autor: Henrique Dias, henriquedias.com
Revisto por: Lus Soares, luissoares.com

Verso 2.1.0
Publicado a 26 de fevereiro de 2015
Com o apoio de: Pplware, pplware.com
ndice
Agradecimentos 6

0 Introduo 7
0.1 Qual o pblico-alvo deste livro . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 7
0.2 Como est estruturado o livro . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 7
0.3 Convenes . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 8
0.4 Sobre o revisor . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 8
0.5 Em caso de dvidas . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 8

1 Fundamentos 9
1.1 Linguagens de programao . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 9
1.2 Algoritmos . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 9
1.2.1 Fluxogramas . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 10
1.2.2 Pseudocdigo . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 10
1.3 Constantes e variveis . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 11
1.3.1 Constantes . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 12
1.3.2 Variveis . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 12
1.4 Paradigmas de programao . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 13
1.4.1 Paradigma imperativo . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 13
1.4.2 Paradigma procedimental . . . . . . . . . . . . . . . . . . . . . . . . . . . . 13
1.4.3 Paradigma estruturado . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 13
1.4.4 Paradigma declarativo . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 16
1.4.5 Paradigma funcional . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 17
1.4.6 Paradigma orientado a objetos . . . . . . . . . . . . . . . . . . . . . . . . . 17
1.5 A linguagem C . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 17
1.5.1 Caractersticas da linguagem C . . . . . . . . . . . . . . . . . . . . . . . . . 18
1.5.2 Ambiente de desenvolvimento . . . . . . . . . . . . . . . . . . . . . . . . . . 18
1.5.3 Hello World! . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 19
1.5.4 #include . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 20
1.5.5 Funo main . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 20
1.5.6 Funo printf . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 20
1.5.7 return . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 21
1.5.8 Comentrios . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 21

2 Dados 22
2.1 Variveis . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 22
2.2 Constantes . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 22
2.2.1 Constantes Definidas com #define . . . . . . . . . . . . . . . . . . . . . . 23
2.2.2 Constantes Declaradas com const . . . . . . . . . . . . . . . . . . . . . . . 23
2.3 Nmeros inteiros - int . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 24
2.3.1 Funo printf e nmeros inteiros . . . . . . . . . . . . . . . . . . . . . . . 24
NDICE 4

2.3.2 Modificadores short e long . . . . . . . . . . . . . . . . . . . . . . . . . . 24


2.3.3 Modificadores signed e unsigned . . . . . . . . . . . . . . . . . . . . . . 25
2.4 Nmeros reais - float e double . . . . . . . . . . . . . . . . . . . . . . . . . . . 26
2.4.1 Funo printf e nmeros reais . . . . . . . . . . . . . . . . . . . . . . . . 26
2.4.2 Notao Cientfica . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 27
2.5 Caracteres - char . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 27
2.5.1 Funo printf e caracteres . . . . . . . . . . . . . . . . . . . . . . . . . . 27

3 Operadores 28
3.1 Operadores aritmticos . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 28
3.2 Operadores de atribuio . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 28
3.3 Operadores relacionais . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 28
3.4 Operadores lgicos . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 29
3.4.1 Operador && . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 29
3.4.2 Operador || . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 30
3.4.3 Operador ! . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 30
3.4.4 Operadores de decremento e incremento . . . . . . . . . . . . . . . . . . . . 30

4 Controlo de Fluxo 33
4.1 Estrutura if/else . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 33
4.2 Estrutura while . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 34
4.3 Estrutura switch . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 35
4.4 Estrutura do/while . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 36
4.5 Estrutura for . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 37
4.6 Interrupo do fluxo . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 38
4.6.1 Terminar ciclo com break . . . . . . . . . . . . . . . . . . . . . . . . . . . 38
4.6.2 Terminar iterao com continue . . . . . . . . . . . . . . . . . . . . . . . 39

5 Funes e Procedimentos 40
5.1 Criao de funes . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 40
5.1.1 Argumentos e parmetros . . . . . . . . . . . . . . . . . . . . . . . . . . . . 41
5.1.2 Retorno de uma funo . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 41
5.2 Algumas funes teis . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 42
5.2.1 Funo puts . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 42
5.2.2 Funo scanf . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 42
5.2.3 Funo getchar . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 43
5.2.4 Limpeza do buffer . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 43
5.2.5 Funo rand . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 44

6 Arrays 46
6.1 Arrays unidimensionais . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 46
6.2 Arrays multidimensionais . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 46

7 Apontadores 48
7.1 Tamanho e endereo de uma varivel . . . . . . . . . . . . . . . . . . . . . . . . . . 48
7.2 Declarao de apontadores . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 49
NDICE 5

7.3 Inicializao de apontadores . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 49


7.4 Operaes com apontadores . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 51

8 Strings 53
8.1 Diferena entre string e char . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 53
8.2 Declarao e inicializao de strings . . . . . . . . . . . . . . . . . . . . . . . . . . 53
8.3 Como imprimir strings . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 54
8.3.1 Com a funo printf . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 54
8.3.2 Com a funo puts . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 54
8.4 Como ler strings . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 54
8.4.1 Com a funo scanf . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 54
8.4.2 Com a funo gets . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 55
8.4.3 Com a funo fgets . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 55

9 Anexos 58
9.1 Anexo I - Tabela ASCII . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 58
9.2 Anexo II - Converso Hexadecimal-Decimal . . . . . . . . . . . . . . . . . . . . . . 59
Agradecimentos
Em primeiro lugar, quero agradecer aos meus pais por estarem sempre presentem e me terem
apoiado imenso durante toda a minha vida.
Em segundo lugar, quero agradecer a toda a equipa do Pplware, pelo apoio dado. Agradeo
tambm comunidade do Pplware, que me ajudou, deu dicas, fez correes, sempre construtiva-
mente.
Finalmente, mas no menos importante, quero agradecer ao Lus Soares, por se ter oferecido a
rever este livro e me dado imensas dicas para o aprimorar.
Captulo
0
Introduo
Este livro pretende dar-lhe a conhecer os fundamentos bsicos e essenciais do mundo da pro-
gramao. No apenas ensinar-lhe a linguagem de programao x ou y, mas sim ensinar-lhe a
programar.
Programar no conhecer uma linguagem de programao. conhecer os fundamentos, a
lgica, que est na base de todas as linguagens de programao. Com isso, ser capaz de utilizar
qualquer linguagem de programao.

0.1 Qual o pblico-alvo deste livro


O pblico-alvo deste livro prende-se aos que querem iniciar a sua jornada no mundo da progra-
mao: independentemente de estarem a estudar ou serem apenas curiosos por esta rea. Neste
livro utilizada a linguagem de programao C de forma a mostrar os fundamentos bsicos da
programao. Fundamentos estes que so omnipresentes em todo o mundo da programao.
O captulo 7, sobre apontadores, poder, eventualmente, ser do interesse de algum que j
conhece algumas linguagens de programao, que j tem alguma habilidade, mas que est com
dificuldade nessa parte.

0.2 Como est estruturado o livro


Este livro foi baseado nos artigos da saga Introduo Programao do Pplware1 . No apenas
a compilao de todos os artigos, mas tambm a sua evoluo. Tudo foi remodelado, revisto e
melhorado.
A estrutura deste livro foi feita de forma a que a aprendizagem seja gradual e lhe d uma viso
sobre aquilo que ir encontrar em (quase) todas as linguagens de programao existentes. Ora
veja como est estruturado.
Captulo 1: Fundamentos - No primeiro captulo sero abordados fundamentos essen-
ciais sobre o mundo da programao: o que uma linguagem de programao, para que
serve, como est estruturada, o que precisar utilizar, etc;
Captulo 2: Dados - Tal como o nome sugere, o tema a abordar so os dados e vrias
coisas relacionadas com eles. So abordados os vrios tipos de dados existentes, tal como a
utilizao de variveis e constantes em C;
Captulo 3: Operadores - No mundo da programao os dados devem ser modelados,
moldados, alterados. com os operadores abordados neste captulo que tudo isso pode ser
feito. Os operadores abordados existem na maioria das linguagens de programao;
Captulo 4: Controlo de Fluxo - A ordem lgica das aes a tomar pode ser diferente
em diversas situaes. Neste captulo aprender a alterar e a modificar a ordem das aes
com base em condies;
Captulo 5: Funes e Procedimentos - No quinto captulo sero abordadas duas
1 Consultar pplware.com
0.3 Convenes 8

coisas importantssimas na programao: as funes e procedimentos. Com elas ir poupar


espao e ainda reutilizar cdigo;
Captulo 6: Arrays - Neste captulo abordada uma estrutura de dados extremamente
importante, os arrays, que esto presentes em quase todas as linguagens de programao;
Captulo 7: Strings - No stimo captulo sero abordadas as strings, ou seja, sequncias
de caracteres. So muito importantes, principalmente quando precisa de armazenar texto;
Captulo 8: Apontadores - Neste captulo, sobre apontadores, ir abordar algo omni-
presente, mas que utilizado massivamente em apenas algumas linguagens, como C. Pode
ser um captulo interessante para quem j tem bases nalguma linguagem de programao,
mas que gostava de aprender mais sobre apontadores;
Captulo 9: Desafios - No nono captulo temos alguns desafios para si; desafios estes
que englobam tudo o que j foi abordado anteriormente e at algo mais;
Captulo 10: Anexos - No ltimo captulo encontram-se os anexos que so mencionados
ao longo do livro.

0.3 Convenes
Ao longo do livro so apresentados endereos de websites para que os possa visitar. Todos esto
dotados de hiperligao de forma a que o seu acesso seja fcil. Alm disso, as partes http:// e
www. foram omitidas de todos os endereos, tal como a barra que por vezes aparece no final. O
endereo http://www.wikipedia.org/ ser mostrado como wikipedia.org.
A linguagem de programao C ser a utilizada para ilustrar os fundamentos sobre a progra-
mao. Por vezes um conjunto de pessoas rene-se em redor desta linguagem e lana uma reviso
da mesma, ou seja, novas formas de fazer algo, melhorias. Atualmente so utilizadas, maiorita-
riamente, trs revises: a C89, C99 e a C11. Tendo em conta que a C11 a mais recente e a
que permite ter um cdigo mais elegante e legvel, ser aquela que vai estar na base de todos os
exemplos ao longo do livro.

0.4 Sobre o revisor


O Lus Soares2 estudou Licenciatura e Mestrado em Engenharia Informtica e de Computadores
no Instituto Superior Tcnico. Trabalha, h vrios anos, no mbito de aplicaes web com as mais
diversas tecnologias. Atualmente trabalha na Media Capital numa posio de Desenvolvedor e
Arquiteto de Software.

0.5 Em caso de dvidas


Caso tenha alguma dvida, poder utilizar algum dos artigos da saga Introduo Programao
no Pplware ou enviar-me um mail para hacdias@gmail.com.

2 Consultar: luissoares.com
Captulo
1
Fundamentos
O objetivo deste primeiro captulo mostrar-lhe os fundamentos essenciais sobre o mundo da
programao. Comearemos por utilizar pseudocdigo (conceito explicado frente), avanando
gradualmente at chegar linguagem pretendida: a Linguagem C.

1.1 Linguagens de programao


semelhana de uma linguagem humana, uma linguagem de programao permite-nos comunicar,
no com Humanos, mas com computadores ou qualquer outro sistema computorizado. Linguagens
de programao so constitudas por uma gramtica que contm todas as regras sintticas uti-
lizadas. Atravs da utilizao dessas regras, podemos comunicar instrues a um computador, ou
seja, instruir-lhe a fazer algo. assim que os programas so criados.

Definio 1. Regras sintticas consistem num conjunto de normas a seguir que indicam como se
deve estruturar o cdigo, ou seja, como se deve construir o cdigo.

Existem inmeras linguagens de programao: algumas de propsito geral, ou seja, sem ter
uma finalidade especfica. Por outro lado, existem outras criadas para um domnio especfico. A
linguagem de programao C um exemplo de uma linguagem de programao de propsito geral.
Por outro lado a Wolfram Language 1 , uma linguagem de domnio especfico, multi-paradigma
(abordado mais frente) e dedicada Matemtica.

1.2 Algoritmos
importante compreender alguns conceitos bsicos que sero fundamentais na sua jornada no
mundo da programao. Assim, vai comear por entender o que so algoritmos visto que vai
estar sempre em contacto com eles.

Definio 2. Algoritmos so quaisquer sequncias de instrues finitas e bem definidas que podem
ser executadas por computadores, autmatos ou at mesmo humanos.

Na Figura 1.1 pode visualizar todo o processo da confeo de um bolo onde o algoritmo a re-
ceita uma sequncia de instrues bem definida e finita que executada pelo(a) cozinheiro(a).
Os algoritmos podem ser representados de diversas formas. Aqui so abordadas duas delas:
os fluxogramas e o pseudocdigo. Estas representaes dos algoritmos so essenciais antes destes
serem escritos em cdigo; ir-se- poupar tempo visto que so reduzidos os possveis erros durante
o desenvolvimento.
Nem sempre so precisos os dois tipos de representao de algoritmos. Por vezes basta um. Isso
algo que depende do fluxo e mtodos de trabalho de cada pessoa. Os fluxogramas e pseudocdigo
so algo universal, que no se compromete com uma determinada linguagem de programao.
1 Consultar wolfram.com/language
1.2 Algoritmos 10

Figura 1.1: Confeo de um bolo

1.2.1 Fluxogramas
Vejamos ento a primeira forma de representar algoritmos, os fluxogramas.

Definio 3. Um fluxograma uma representao grfica de um algoritmo que utiliza smbolos de


forma a demonstrar os processos neste realizado.

Existem vrias vantagens na criao de fluxogramas como, por exemplo, a sua facilidade de
criar, a facilidade na partilha e ajuda a criar modelos mentais.
Um fluxograma pode fazer uso de muitos smbolos. No entanto, apenas iremos necessitar dos
bsicos para ter uma boa compreenso de como funcionam os fluxogramas. Pode visualizar estes
smbolos na Figura 1.2.

Figura 1.2: Smbolos primrios dos fluxogramas

Na Figura 1.3 pode visualizar um fluxograma, baseado no processo de confeo de um bolo.

1.2.2 Pseudocdigo
Uma forma mais aproximada do cdigo final a utilizao de pseudocdigo. Sendo assim, sucede
a criao dos fluxogramas.

Definio 4. Pseudocdigo uma forma de representao de algoritmos que se assemelha a lingua-


gens de programao mas que utiliza a lngua nativa do utilizador de forma a ser facilmente entendida
por quem no tem quaisquer conhecimentos da sintaxe de uma linguagem de programao.

Os programadores cuja lngua nativa portugus, costumam referir-se ao pseudocdigo como


Portugol, tambm conhecido por Portugus Estruturado. O seguinte trecho de Portugol repre-
senta o algoritmo anteriormente representado com um fluxograma, a confeo de uma receita:
1.3 Constantes e variveis 11

1 inicio
2 variavel caracter receita "A minha receita"
3
4 se tenhoIngredientes(receita) == verdadeiro entao
5 fazerBolo()
6 senao
7 comprarIngredientes()
8 fazerBolo()
9 fimse
10 fim

Como pode verificar, o algoritmo acima, em Portugol, extremamente simples de compreender.


De momento, peo-lhe que entenda as expresses que terminam com () como se fossem comandos.

Definio 5. Um comando uma ordem ou instruo dada a um computador ou qualquer outra


mquina automatizada.

Figura 1.3: Fluxograma Confeo de um bolo

1.3 Constantes e variveis


Na quarta linha do trecho de cdigo que visualizou em 1.2.2, pde encontrar o seguinte cdigo:
1 variavel caracter receita "A minha receita"

Esse trecho de cdigo declara uma varivel do tipo caracter, que se chama receita, com o
valor A minha receita.
Definio 6. A declarao de variveis, ou constantes, consiste no processo em que o compilador
"avisado"da sua existncia para que, de cada vez se menciona o nome da varivel/constante, esta
seja utilizada.

Por exemplo, quando declaramos a varivel receita, estamos a reservar um endereo da me-
mria RAM para alocar um valor. Neste caso, o valor foi atribudo no momento da sua declarao
utilizando o operador (sem aspas).
1.3 Constantes e variveis 12

A partir do momento declaramos uma varivel ou constante, o endereo da memria RAM que
foi reservado estar disponvel atravs do seu nome. Sempre que for referenciado receita no
cdigo, o valor da varivel ser retornado.

1.3.1 Constantes
Comecemos por abordar as constantes.
Definio 7. Constantes permitem armazenar valores imutveis, ou seja, que no podem ser alte-
rados ao longo da execuo de um programa.

Ora veja o seguinte exemplo:


1 constante caracter EMPRESA "Pplware"
2 EMPRESA "A Minha Empresa"

Na primeira linha, a constante EMPRESA, do tipo carcter, declarada e -lhe atribudo o valor
Pplware. De seguida, na segunda linha, existe uma tentativa de alterar o seu valor da constante.
Esta tentativa ir falhar, causando um erro visto que o valor de uma constante no pode ser
alterado aps a sua atribuio.

Nomenclatura
Convencionalmente, o nome das constantes escrito com letras maisculas para haver uma
melhor distino no cdigo-fonte. Esta conveno no obrigatria e no ir causar quaisquer
erros durante a execuo de um programa. Seguir esta conveno apenas torna mais clara
a distino entre variveis e constantes dentro do cdigo-fonte facilitando tanto a si, como
programador, como a outros programadores que vejam o cdigo do seu programa.

1.3.2 Variveis
Por outro lado, existem as variveis.
Definio 8. Variveis, ao contrrio das constantes, permitem o armazenamento de valores que
podem ser alterados durante a execuo de um programa. Geralmente so utilizadas para manter
estados de algo e so fundamentais na programao.

Abaixo encontra um exemplo:


1 variavel caracter temaDaSecao "Constantes"
2 temaDaSecao "Variveis"

Na primeira linha declarada uma varivel do tipo carcter, com nome temaDaSecao e valor
Constantes. Seguidamente, o seu valor alterado para Variveis no causando nenhum erro,
pois o valor das variveis pode ser alterado ao longo da execuo de um programa.

Regras de nomeao

Existem diversas regras que tm de ser seguidas no momento da declarao de uma varivel para
que no seja causado nenhum erro.
O nome das variveis e constantes:
No pode comear com nmeros (ex.: 9comida no permitido, comida9 vlido);
No pode ser igual a uma palavra reservada (ex.: if no permitido, mas maria permi-
tido);
No pode conter espaos (ex.: a minha var no permitido, porm aMinhaVar vlido);
No pode conter caracteres especiais (existem excees em diversas linguagens).

Definio 9. Palavras reservadas so aquelas que constam na gramtica da linguagem de pro-


gramao. Tendo em conta que a palavra se um comando do Portugol, no podemos declarar
1.4 Paradigmas de programao 13

nenhuma varivel ou constante com esse nome. Se isso for feito, ser gerado um erro.

As variveis e constantes podem ser de diversos tipos. Os tipos de dados existentes variam de
linguagem para linguagem. Mais frente iro ser abordados os tipos de dados na linguagem C.

Nomenclatura
As variveis, ao contrrio das constantes, no so totalmente escritas em letras maisculas.
Convencionalmente, a variao lowerCamelCase (pertencente ao padro CamelCase) seguida
na maioria das linguagens de programao. Este padro ser utilizado visto que a maioria das
linguagens de programao adotam-no, tal como a linguagem C.

1.4 Paradigmas de programao


Todas as linguagens de programao tm caractersticas que as distinguem de outras. O(s) para-
digma(s) de programao que ela segue so fundamentais.

Definio 10. Paradigmas de programao so modelos ou padres da forma de estruturar o


nosso cdigo. Existem muitos.

Nesta seco apenas so abordados 6 paradigmas de programao, os mais conhecidos e utili-


zados. As que adotam mais do que um paradigma chamam-se multi-paradigma.

1.4.1 Paradigma imperativo


O primeiro paradigma abordado o paradigma imperativo. Este concentra-se num estado (que
so as variveis) e em aes (comandos) que modelam (alteram) esse estado.
Este paradigma pode ser comparado ao modo imperativo da linguagem humana visto que
criado para ordenar a realizao de aes (como por exemplo, fazer algo, recortar, analisar,
apagar...).
Alguns exemplos de linguagens de programao imperativas so, por exemplo: C, Java, C#,
Pascal.

1.4.2 Paradigma procedimental


Com o paradigma procedimental, trechos de cdigo podem ser reutilizados sem a necessidade de o
copiar para diversos locais atravs da utilizao de funes e procedimentos (que sero abordados
mais a frente).
A maioria das linguagens de programao adotam este paradigma.

1.4.3 Paradigma estruturado


Nas linguagens de programao em que o paradigma estruturado seguido, o cdigo-fonte de uma
aplicao pode ser reduzido em apenas trs estruturas: sequncia, deciso e iterao (repetio).

Sequncia

Nesta primeira estrutura, as tarefas so executadas de forma linear, ou seja, uma aps a outra.
Abaixo encontra um pequeno exemplo.
1 Acordar;
2 Vestir;
3 Tomar o pequeno-almoco;
4 Ir trabalhar;

Este um exemplo de uma sequncia onde so realizadas as aes normais do dia-a-dia de um


indivduo que est empregado.
1.4 Paradigmas de programao 14

Figura 1.4: Fluxograma de uma sequncia

Na maioria das linguagens de programao, os comandos/aes terminam com ponto e vrgula


pois estas permitem que os comandos sejam colocados em linha da seguinte forma:
1 Acordar; Vestir; Tomar o pequeno-almoco; Ir trabalhar;

A utilizao do ponto e vrgula normalmente obrigatria quando existe mais do que uma
instruo numa s linha. Existem linguagens de programao que s obrigam a utilizao de ponto
e vrgula nestes casos (JavaScript, por exemplo). Porm, existem outras, como C, Java e C# que
obrigam a utilizao de ponto e vrgula no final de todas as instrues.

Deciso

Neste tipo de estrutura, existe um trecho de cdigo que executado ou no dependendo do resultado
de um teste lgico, tambm conhecido por predicado. Abaixo encontra diversos exemplos para esta
estrutura.
O exemplo abaixo descreve a condio/deciso Se acordar, vou trabalhar. Caso contrrio, no
vou trabalhar (em pseudocdigo).
1 if "Acordar" then
2 "Trabalhar"
3 else
4 "No trabalhar"
5 endif

Novos Termos:
if se
then ento
else caso contrrio
endif fim do se
O pseudocdigo acima j no est em portugus; j no Portugol. O que encontra acima j
se assemelha ao que ir visualizar nas linguagens de programao.
1.4 Paradigmas de programao 15

Retornando novamente ao trecho de cdigo escrito acima, repare que Trabalhar s ser
executado se e apenas se o indivduo Acordar. Caso contrrio, o trecho No trabalhar ser
executado.

Figura 1.5: Exemplo de uma deciso em fluxograma

Agora veja o seguinte exemplo em que a condio Di-me a cabea. Se doer muito pouco, vou
trabalhar. Se doer pouco, tomo um comprimido e vou trabalhar. Se doer muito, vou ao mdico e
falto ao trabalho executada.
1 case "Dor de cabeca"
2 when "muito pouco" then "trabalhar"
3 when "pouco" then "tomar comprimido"; "trabalhar"
4 when "muito" then "ir ao mdico"; "no trabalhar"

Novos Termos:
case caso
when quando
else if caso contrrio se

Figura 1.6: O que farei se me doer a cabea


1.4 Paradigmas de programao 16

Este mais um exemplo mas utilizando diferentes comandos. Este trecho poderia ser tambm
escrito atravs de primitivas if/else da seguinte forma (ver Figura 1.6):
1 if "Dor de cabeca"
2 if "muito pouco" then
3 "trabalhar";
4 else if "pouco" then
5 "tomar comprimido";
6 "trabalhar";
7 else if "muito" then
8 "ir ao mdico";
9 "no trabalhar";
10 endif
11 endif

Iterao

Neste tipo de estrutura, tambm conhecido como repetio, um trecho de cdigo repetido um
nmero finito de vezes dependendo do resultado de um teste lgico.
Abaixo encontra a repetio no saio de casa enquanto no estiver vestido em pseudocdigo:
1 do {
2 "no sair de casa";
3 } while ( "no estou vestido" )

Novo termo:
do fazer
Ou seja, o cdigo acima pode ser lido da seguinte forma: fazer no sair de casa enquanto
no estou vestido. De forma generalizada, fazer x enquanto y.
Agora veja o retrato da repetio enquanto durmo, no me visto em pseudocdigo:
1 while ( durmo )
2 naoMeVisto();

Ou seja, enquanto acontece algo, fao outra coisa.


Visualize agora o cdigo correspondente ao lavar os dentes 20 vezes.
1 for ( i = 0; i++; i < 20 )
2 lavarOsDentes();

Ou seja, enquanto no acontece qualquer coisa, fao qualquer coisa.


Mais um exemplo, mas referente expresso Para cada dente, lavo-o muito bem.
1 for each dente in boca
2 lavarMuitoBem();

Novos Termos:
each cada
in em
Ou seja, para cada item do conjunto, fazer qualquer coisa.

1.4.4 Paradigma declarativo


O Paradigma Declarativo contrasta com o Imperativo pois capaz de expressar a lgica sem
descrever como o fluxo de comandos funciona, ou seja, apenas diz ao computador o que fazer e
no como fazer.
Um excelente exemplo de uma linguagem que utiliza este paradigma Prolog, muito utilizado
na rea de inteligncia artificial.
1.5 A linguagem C 17

1.4.5 Paradigma funcional


O Paradigma Funcional engloba todas as linguagens de programao que utilizam funes ma-
temticas e evita estados. Estas linguagens de programao so muito utilizadas no campo da
matemtica.
Algumas linguagens que seguem o paradigma funcional so, por exemplo, Matlab, Wolfram
Language, B.

1.4.6 Paradigma orientado a objetos


A Programao Orientada a Objetos permite a criao de objetos com base em classes. Estes
objetos so instncias dessas classes e possuem todos os atributos e funes presentes nas classes
em questo.
Este paradigma muito extenso e tem muita informao que mais frente ir ser abordada.
Atualmente existem muitas linguagens que utilizam este paradigma (Java, C++, C#, PHP, por
exemplo).

Os paradigmas de programao no se limitam aos 6 (seis) apresentados pois existem inmeros


outros. Estes so apenas os paradigmas de programao mais abrangentes. Existem paradigmas
baseados noutros paradigmas, outros que contrastam com outros, etc.

1.5 A linguagem C
Os anos de 1969 a 1973 foram de extremo entusiasmo dentro da AT&T Bell Labs porque foi quando
a linguagem de programao C foi maioritariamente desenvolvida.
O principal desenvolvedor desta linguagem foi Dennis Ritchie que descreveu o ano de 1972
como o mais produtivo e criativo.

Figura 1.7: Dennis Ritchie

A linguagem desenvolvida por Ritchie chama-se C porque esta linguagem baseou-se imenso
numa outra linguagem de programao chamada B, tendo C diversas caractersticas em comum
com B.
Inicialmente, esta linguagem de programao, C, tinha como principal finalidade o desenvolvi-
mento do Unix, que j havia sido escrito em Assembly - uma outra linguagem de programao.
1.5 A linguagem C 18

A verso mais recente de C C11 e foi lanada a dezembro de 2011. Esta linguagem foi uma das
influncias de muitas das linguagens de programao que atualmente so muito utilizadas. Entre
muitas outras, C influenciou AWK, BitC, C++, C#, C Shell, D, Euphoria, Go, Java, JavaScript,
Limbo, Logic Basic, Objective-C, Perl e PHP. Isto no significa que estas linguagens no
tenham sido influenciadas por outras.
Ns iremos comear por abordar C porque uma linguagem me, que influenciou muitas
outras. Por ser uma linguagem de baixo nvel, pode ter um contacto mais prximo com o hardware.

1.5.1 Caractersticas da linguagem C


Como abordmos anteriormente, os paradigmas de programao so muito importantes e influen-
ciam a forma como devemos escrever.
C uma linguagem de programao, em relao aos paradigmas, estruturada, imperativa e
procedimental. Outras caractersticas desta linguagem so o facto de ser padronizada pela ISO
e de propsito geral.

Linguagem de programao compilada

Linguagens de Programao Compiladas so aquelas que passam pelo processo de compilao, ou


seja, onde o seu cdigo fonte diretamente transformado na linguagem da mquina por via de um
compilador.

Definio 11. Cdigo fonte um conjunto de instrues lgicas, escritas de acordo com uma
linguagem de programao existente.

Figura 1.8: Linguagem C

Aprendendo a linguagem C, fica preparado para se iniciar com muitas outras linguagens de
programao pois tem uma sintaxe muito utilizada e, alm disso, sabe a lgica.

1.5.2 Ambiente de desenvolvimento


Para comear a desenvolver programas, necessita ter um ambiente de desenvolvimento, preparado
com as diversas ferramentas necessrias.

Instalao de um compilador

Definio 12. Um compilador a ferramenta que transforma o cdigo-fonte na linguagem da


mquina atravs do processo de compilao.

O compilador que iremos utilizar denomina-se GCC (GNU Compiler Collection). Este compi-
lador de fcil instalao e utilizao.
1.5 A linguagem C 19

Debian e derivadas

A instalao deste compilador na distribuio Linux Debian ou derivadas, como por exemplo,
Ubuntu, bastante simples. No terminal, execute os seguintes comandos:
> sudo apt-get update && apt-get upgrade
> sudo apt-get install build-essential

Depois desses dois comandos dever ter instalado o compilador GCC, entre outras ferramentas.
Para verificar se o GCC ficou instalado corretamente execute, o seguinte comando:
> gcc -v

Este comando dever retornar a verso atualmente instalada do GCC.

Outras distribuies Linux

Para outras distribuies Linux recomendvel seguir as instrues encontradas na pgina oficial
do projeto GCC2 .

Windows

No sistema operativo da Microsoft, o GCC pode ser instalado recorrendo a projetos como o MinGW
ou o Cygwin. Recomendo o primeiro3 .

OS X

No sistema operativo da Apple, o GCC costuma vir com o Xcode, um IDE multi-linguagem criado
pela Apple, podendo tudo isto ser instalado atravs do terminal com o seguinte comando:
> xcode-select --install

Pode verificar a verso instalada do GCC nos dois ltimos sistemas operativos recorrendo ao
comando anteriormente mencionado.
Um IDE um Ambiente de Desenvolvimento Integrado, do ingls Integrated Development
Environment. um programa de computador que rene diversas ferramentas para apoiar no
desenvolvimento de software.

Editor de texto

Alm do compilador, ir tambm precisar de um editor de texto. Qualquer editor de texto funciona,
mas recomendo um que suporte a sintaxe da linguagem C.
Existem vrios editores de texto que pode utilizar. Aqui deixamos algumas recomendaes:
Windows Notepad++, Atom, Sublime Text;
Linux Gedit, Atom, Sublime Text (algumas distribuies), Vim;
OS X TextWrangler, Sublime Text, Atom.

1.5.3 Hello World!


Como seria o mundo da programao sem o famoso Hello World? uma tradio o primeiro
programa criado por algum imprimir a mensagem Hello World no ecr.
Crie um ficheiro, onde queira, com o nome HelloWorld.c. Tenha em ateno extenso do
ficheiro que tem que ser .c, ou seja, da linguagem C.
Abra esse mesmo ficheiro com um editor de texto, copie e cole o seguinte texto e ento guarde
2 Ver gcc.gnu.org
3 Download em mingw.org/download
1.5 A linguagem C 20

as alteraes.
1 #include <stdio.h>
2 #include <stdlib.h>
3
4 int main() {
5 printf("Hello World!\n");
6 return 0;
7 }

Este trecho de cdigo ir imprimir no ecr a mensagem Hello World!. Para executarmos este
comando, dever abrir a Linha de Comandos/Terminal e navegar at ao local onde guardou o
ficheiro. Depois, execute o seguinte comando:
> gcc HelloWorld.c -o HelloWorld

Onde HelloWorld.c o ficheiro de entrada e HelloWorld o ficheiro de sada. A extenso do


ficheiro produzido dever ser diferente consoante o sistema operativo.
No meu caso, como estou a utilizar o Windows, foi criado um ficheiro .exe. Agora, para
executar o seu ficheiro, basta o executar atravs da linha de comandos:
> HelloWorld

Dever receber uma mensagem na Linha de Comandos a dizer Hello World.

1.5.4 #include
A primeira linha do trecho acima no C mas sim uma indicao para o compilador.

C uma linguagem utilizada em locais que necessitam de alta velocidade, como o kernel -
ncleo - do Linux, pois esta tem essa capacidade.
Devido alta velocidade que pode ser proporcionada por esta linguagem, C no est
preparado, por omisso, para todos os tipos de tarefas. Assim, precisamos de inclu-las para
ter disponveis mais funes.

A linguagem C no vem empacotada de funes por padro e necessrio inclu-las. Para


as incluir, utilizamos a diretiva #include que diz ao compilador que precisa de incluir ficheiros
ponto H (.h) que so ficheiros do tipo header. Nesta caso adicionmos o ficheiro stdio.h que
quer dizer standard input/output, ou seja, sistema padro de entrada e sada.

1.5.5 Funo main


Todos os programas C tm que ter, obrigatoriamente, uma funo main que ser automaticamente
executada. Esta funo o ponto de partida para criar um programa. o seu cerne.
Voltaremos a falar sobre este tema e da sua importncia.

1.5.6 Funo printf


Este um comando/funo que est contido no ficheiro stdio.h. Caso no incluamos o ficheiro,
ser gerado erro. Esta funo significa print formatted, ou seja, escrita de dados formatados.
Esta funo aceita vrios parmetros; permite-nos enviar vrias coisas que iro ser processadas
por ela. De momento, apenas iremos falar do primeiro argumento.
O primeiro argumento uma string, ou seja, um conjunto de caracteres. Este conjunto de
caracteres deve ser colocado dentro de aspas.
Neste caso escrevemos Hello World!\n! o que quer dizer que ser imprimido Hello World!
na janela. E o que faz \n? Simples, um carcter especial que imprime uma nova linha. Chama-se
new line.
A \ serve para inserir caracteres especiais.
1.5 A linguagem C 21

%% Por cento
\t Tab
\r Carriage Return (coloca o cursor no incio da linha)
\a e \7 Alguns sons

Tabela 1.1: Alguns caracteres especiais em C

1.5.7 return
Como referi acima, a funo main ir, neste caso, retornar um nmero inteiro. aqui que o
comando return, que quer dizer retorno, entra. Este retorna o nmero 0 que o binrio para
falso.
De momento, ainda no temos muito a acrescentar sobre esta diretiva mas mais frente iremos
falar de novo sobre ele quando abordarmos funes e procedimentos.

1.5.8 Comentrios
Os comentrios, em programao, so colocados para auxiliar ou dar mais informaes sobre al-
guma parte ou trecho do cdigo. Os comentrios so completamente ignorados pelo compilador.
Os comentrios que iniciam por // comeam nesse local e prolongam-se at ao final da linha
em questo. Os blocos de comentrios maiores comeam por /* e terminam com */ e tudo o
que est contido entre eles um comentrio.
Estes no devem ser utilizados para coisas bvias como, por exemplo, aqui somam-se as va-
riveis a e b. Devem-se utilizar os comentrios de dupla barra em variveis e constantes (ou para
comentrios curtos). Para comentar algo mais longo como funes ou classes, dever ser utilizada
a estrutura */.
1 #include <stdio.h>
2
3 int main() {
4 int n = 1; //At ao final da linha um comentrio.
5
6 /*
7 TUDO ISTO um comentrio
8 */
9 }

Em C, o tipo de comentrios mais utilizado aquele que comea por /*, independentemente
do tamanho do comentrio.
Captulo
2
Dados
No captulo 1 foi referida a existncia de diversos tipos de dados, que podem variar de linguagem
para linguagem e tambm a existncia de variveis e constantes.

Definio 13. Os tipos de dados constituem uma variedade de valores e de operaes que uma
varivel pode suportar. So necessrios para indicar ao compilador (ou interpretador) as converses
necessrias para obter os dados da memria.

Os tipos de dados subdividem-se ainda em dois grupos: os tipos primitivos e os tipos compostos.

Definio 14. Tipos primitivos, nativos ou bsicos so aqueles que so fornecidos por uma lin-
guagem de programao como um bloco de construo bsico.

Definio 15. Tipos compostos so aqueles que podem ser construdos numa linguagem de progra-
mao atravs de tipos de dados primitivos e compostos. A este processo denomina-se composio.

2.1 Variveis
No captulo 1 foi abordada a existncia de variveis e constantes que permitem armazenar dados.
Nesta seco explicado como se devem declarar as variveis na linguagem de programao que
ser utilizada ao longo do resto do livro, a linguagem C.
Relembro que variveis permitem o armazenamento de valores que podem ser alterados durante
a execuo de um programa. A declarao de variveis em C bastante simples:
1 tipo_de_dados nome_da_variavel;

Onde:
tipo_de_dados corresponde ao tipo de dados que a varivel vai armazenar;
nome_da_variavel corresponde ao nome que a varivel vai tomar, sua identificao.
Imagine que quer criar uma varivel chamada idade do tipo inteiro. Bastaria proceder da
seguinte forma:
1 int idade;

2.2 Constantes
Em C, tal como noutras linguagens de programao, existem as constantes. Relembro que cons-
tantes permitem armazenar valores imutveis durante a execuo de um programa.
Existem diversas formas de declarar constantes em C. Iremos abordar as duas mais utilizadas:
as constantes declaradas e as constantes definidas.
2.2 Constantes 23

2.2.1 Constantes Definidas com #define


Chamam-se Constantes Definidas quelas que so declaradas no cabealho de um ficheiro. Estas
so interpretadas pelo pr-processador que proceder substituio da constante em todo o cdigo
pelo respetivo valor. A principal vantagem deste tipo de constantes que so sempre globais. Ora
veja como se define:
1 #define identificador valor

Onde:
identificador corresponde ao nome da constante que, convencionalmente, escrito em
maisculas e com underscore (_) a separar palavras;
valor corresponde ao valor que a constante armazena.
Imagine que, por exemplo, precisa de uma constante que armazene o valor do e que depois
se calcule o permetro de um crculo. Poderia proceder da seguinte forma:
1 #include <stdio.h>
2 #define PI 3.14159
3
4 int main (){
5
6 double r = 5.0;
7 double circle;
8
9 circle = 2 * PI * r;
10 printf("%f\n", circle);
11 return 0;
12 }

O que acontece quando definida uma constante atravs da diretiva #define que quando
o pr-compilador l a definio da constante, substitui todas as ocorrncias no cdigo daquela
constante pelo seu valor, literalmente.

Pode utilizar a biblioteca math.h que tem a constante M_PI com o valor do pi.

2.2.2 Constantes Declaradas com const


As Constantes Declaradas, ao contrrio das Constantes Definidas so, tal como o prprio nome
indica, declaradas no cdigo, em linguagem C. A declarao destas constantes extremamente
semelhante declarao das variveis. Apenas temos que escrever const antes do tipo de dados.
Ora veja como se declara uma constante:
1 const tipo nome = valor;

Onde:
tipo corresponde o tipo de dados que a constante vai conter;
nome corresponde ao nome da constante;
valor corresponde ao contedo da constante.
Se tentar alterar o valor de uma constante durante a execuo de um programa ir obter um
erro. Analise ento o seguinte excerto de cdigo:
1 #include <stdio.h>
2 #include <math.h>
3
4 int main() {
5 const double goldenRatio = (1 + sqrt(5)) / 2;
6
7 goldenRatio = 9; // erro. A constante no pode ser alterada.
8
9 double zero = (goldenRatio * goldenRatio) - goldenRatio - 1;
10 printf("%f", zero);
11 return 0;
12 }
2.3 Nmeros inteiros - int 24

Existem vantagens ao utilizar cada uma destas formas de declarar constantes. As constantes
declaradas podem ser locais ou globais porm as definidas so sempre globais.

Definio 16. Uma constante/varivel local uma constante/varivel que est restrita a uma de-
terminada funo e s pode ser utilizada na funo em que declarada.

2.3 Nmeros inteiros - int


Comecemos por abordar o tipo int. Esta abreviatura quer dizer integer number, ou seja, nmero
inteiro (exemplos: 4500, 5, -250). Em C, pode-se definir o intervalo em que se situam os nmeros
de cada varivel do tipo int.

Definio 17. Inicializao de variveis consiste em dar o primeiro valor a uma varivel no
cdigo. Uma varivel no tem que ser obrigatoriamente inicializada no cdigo. Pode-se, por exemplo,
declarar uma varivel e dar-lhe o valor de uma leitura em que o utilizador introduz os dados, sendo
a varivel inicializada com os dados inseridos pelo utilizador.

No seguinte exemplo pode visualizar como se declara uma varivel, ou seja, como se reserva um
endereo da memria RAM, do tipo int com o nome a. Seguidamente inicializada com o valor
20 e imprimida recorrendo funo printf.
1 #include <stdio.h>
2
3 int main() {
4
5 int a;
6 a = 20;
7
8 printf("Guardei o nmero %d.", a);
9 return 0;
10 }

Antes de continuar, deve ter reparado que foi utilizado um %d dentro do primeiro parmetro.
Este substitudo pelo valor da varivel a quando impresso no ecr.

2.3.1 Funo printf e nmeros inteiros


Utiliza-se %d quando se quer imprimir o valor de uma varivel dentro de uma frase. A varivel
deve ser colocada nos parmetros seguintes, por ordem de ocorrncia. Por exemplo:
1 #include <stdio.h>
2
3 int main() {
4 int a, b;
5 a = 20;
6 b = 100;
7
8 /* imprime: O primeiro nmero : 20 */
9 printf("O primeiro nmero : %d.\n", a);
10 /* imprime: O segundo nmero : 100 */
11 printf("O segundo nmero : %d.\n", b);
12 /* imprime: O primeiro e segundo nmeros so 20 e 100 */
13 printf("O primeiro e segundo nmeros so %d e %d.\n", a, b);
14
15 return 0;
16 }

2.3.2 Modificadores short e long


Este tipo de variveis ocupa, normalmente, entre 2 a 4 bytes na memria de um computador. E
se quiser utilizar uma varivel para um nmero pequeno? No poderei gastar menos recursos? E
se acontecer o contrrio e precisar de um nmero maior?
2.3 Nmeros inteiros - int 25

Bit (Binary Digit) a menor unidade de informao que pode ser armazenada ou transmitida.
Um bit s pode assumir dois valores: 0 e 1, ou seja, o cdigo binrio. Os bits so representados
por B minsculo.
Byte (Binary Term) um tipo de dados de computao. Normalmente utilizado para
especificar a quantidade de memria ou capacidade de armazenamento de algo. representado
por um B maisculo. Geralmente:
1 Byte = 8 bits (Octeto)
1/2 Byte = 4 bits (Semiocteto)
Existem os Prefixos Binrios (IEC) que so nomes/smbolos utilizados para medidas
indicando a multiplicao da unidade, neste caso byte, por potncias de base dois. Como por
exemplo os megabibytes (MiB) que equivale a dois elevado a vinte bytes.
Por outro lado, existem os prefixos do Sistema Internacional de Unidades (SI), que
so os mais comuns, que correspondem na unidade multiplicada por potncias de base dez.
Como por exemplo os megabytes (MB) que correspondem a dez elevado a seis.

Nestas situaes, pode-se utilizar modificadores.


Definio 18. Um modificador consiste numa palavra-chave, numa keyword, que se coloca antes
de um elemento de forma a modificar uma propriedade do mesmo.

Para alterar a capacidade de armazenamento, ou seja, o nmero de bytes ocupado por uma
varivel do tipo int, podem-se utilizar os modificadores short e long. Estes permitem-nos criar
variveis que ocupem um maior ou menor nmero de bytes, respetivamente.
Uma varivel do tipo int, ao assumir um nmero de bytes diferentes, tambm est a alterar a
sua capacidade de armazenamento. Assim, temos os seguintes valores:
1 byte armazena de -128 a +127
2 bytes armazenam de -32 768 a +32 767
4 bytes armazenam de -2 147 483 648 a +2 147 483 647
8 bytes armazenam de -9 223 372 036 854 775 808 a +9 223 372 036 854 775 807
A utilizao destes modificadores feita da seguinte forma:
1 short int nomeDaVariavel = 20; // ou "long"

Funo sizeof

O nmero de bytes atribudo utilizando um destes modificadores pode depender do computador


onde o cdigo est a ser executado. Este problema depende da linguagem. Existem linguagens
de programao cuja capacidade de cada tipo de varivel igual em todas as mquinas.
Para descobrirmos qual o tamanho de bytes que utiliza o seu sistema, basta recorrer funo
sizeof da seguinte forma:
1 #include <stdio.h>
2
3 int main() {
4 printf("int : %d bytes\n", sizeof(int) );
5 printf("short int: %d bytes\n", sizeof(short) );
6 printf("long int: %d bytes\n", sizeof(long) );
7 return 0;
8 }

No computador que estou a utilizar, por exemplo, short refere-se a 2 bytes, long a 8 bytes e
o tamanho padro de int 4 bytes.

2.3.3 Modificadores signed e unsigned


Como sabe, os nmeros inteiros podem assumir forma positiva e negativa. Por vezes, na progra-
mao, os nmeros negativos podem atrapalhar (ou ento ajudar), dependendo do caso.
2.4 Nmeros reais - float e double 26

Para termos controlo sobre a positividade ou negatividade de um nmero, podemos atri-


buir os modificadores signed e unsigned. Para que uma varivel possa conter tanto nmeros
positivos como negativos, devemos utilizar o modificador signed. Caso queira que o nmero seja
apenas positivo, incluindo 0, utilize unsigned.
Tendo em conta que variveis marcadas com o modificador unsigned no podem conter n-
meros negativos, podem conter um intervalo de nmeros positivos superior ao regular. Imaginando
que uma varivel int suporta nmeros entre -32 768 e 32 767; a mesma varivel com o modificador
unsigned ir suportar nmeros entre 0 e 65 535.

2.4 Nmeros reais - float e double


Alm dos nmeros inteiros, existem outros tipos de dados que nos permitem armazenar nmeros
que, ao invs de serem inteiros, so decimais (por exemplo 1,3; 5,540; etc).
Existem dois tipos de dados que nos permitem armazenar valores do tipo decimal/real, ou seja,
que tm casas decimais. Estes tipos so float e double. Devem ser utilizados da seguinte forma:
1 float pi = 3.14;
2 double pi = 3.14159265359;

Como pode ter reparado, em C (e na maioria das linguagens de programao), no se utiliza a


vrgula, mas sim um ponto para separar a parte inteira da decimal.
A diferena entre float e double que o segundo ocupa mais memria que o primeiro, logo
consegue armazenar nmeros de maior dimenso.
Normalmente, o tipo float ocupa 4 bytes de memria RAM enquanto o segundo tipo, double,
ocupa 8 bytes de memria. Mais uma vez, relembro que estes valores podem alterar de mquina
para mquina.
Para quem precise de fazer clculos mais precisos, o tipo de dados double o mais aconselhado
pois o que permite uma maior extenso do valor.

2.4.1 Funo printf e nmeros reais


Recorrendo funo printf abordada na seco 1.5.7, utiliza-se %f para se imprimir o valor de
uma varivel dos tipos float e double. A varivel deve ser colocada nos parmetros seguintes,
por ordem de ocorrncia. Por exemplo:
1 #include <stdio.h>
2
3 int main() {
4 float piMinor = 3.14;
5 double piMajor = 3.14159265359;
6
7 // imprime: Pi pode ser 3.140000 mas, de forma mais exata, 3.141593
8 printf("Pi pode ser %f mas, de forma mais exata, %f.", piMinor, piMajor);
9
10 return 0;
11 }

Pode visualizar que, quando se utiliza %f, utilizado um nmero especfico de casas decimais.
Caso o nmero de casas decimais seja mais pequeno do que o da varivel original, o nmero
arredondado.
Pode definir o nmero de casas decimais que quer que sejam apresentadas da seguinte forma:
%.{nmeroDeCasasDecimais}f. Veja o seguinte exemplo, baseado no anterior:
1 #include <stdio.h>
2
3 int main() {
4 float piMinor = 3.14;
5 double piMajor = 3.14159265359;
6
7 // imprime: Pi pode ser 3.14 mas, de forma mais exata, 3.14159265359.
2.5 Caracteres - char 27

8 printf("Pi pode ser \%.2f mas, de forma mais exata, \%.11f.", piMinor, piMajor);
9
10 return 0;
11 }

2.4.2 Notao Cientfica


Relembre o conceito de notao cientfica1 , ou seja, nmeros no formato n 10s , ou seja, n vezes
dez elevado a s. Podemos utilizar notao cientfica nas variveis do tipo float e double. Veja o
seguinte exemplo:
1 #include <stdio.h>
2
3 int main() {
4 float num = 24E-5; // 24 x 10 elevado a -5
5 printf("\%f\n", num); // imprime: 0.000240
6
7 num = 2.45E5; //2.45 x 10^5
8 printf("\%.0f", num); // imprime: 245000
9
10 return 0;
11 }

2.5 Caracteres - char


O tipo char um gnero de dados que nos permite armazenar um nico carcter. declarado da
seguinte forma:
1 char letra = 'P';

Como pode visualizar, a varivel letra agora contm o carcter P. Pode, ao invs de utilizar
este tipo de notao, utilizar nmeros hexadecimais, octais e decimais. Em C pode-se utilizar
ASCII.
Definio 19. ASCII (do ingls American Standard Code for Information Interchange; em por-
tugus "Cdigo Padro Americano para o Intercmbio de Informao") um conjunto de cdigos
binrios que codificam 95 sinais grficos e 33 sinais de controlo. Dentro desses sinais esto includos
o nosso alfabeto, sinais de pontuao e sinais matemticos. No Anexo I encontra uma tabela ASCII
com caracteres que podem ser utilizados em C.

2.5.1 Funo printf e caracteres


Utiliza-se %c quando se quer imprimir o valor de uma varivel dos tipo char dentro de uma frase.
A varivel deve ser colocada nos parmetros seguintes, por ordem de ocorrncia. Exemplo:
1 #include <stdio.h>
2
3 int main() {
4 char letra = 'P';
5
6 printf("O nome Pplware comea por %c.", letra);
7 return 0;
8 }

1 Ler pt.wikipedia.org/wiki/Notao_cientfica
Captulo
3
Operadores
Neste captulo so abordados os operadores, que so deveras importantes na modificao dos valores
de variveis.
Definio 20. Operadores so smbolos para efetuar determinadas aes sobre variveis. Na pro-
gramao existem diversos tipos de operadores como, por exemplo, para efetuar operaes aritmticas.

Alguns dos operadores tambm existem em outras reas do conhecimento como matemtica,
por exemplo.

3.1 Operadores aritmticos


Os operadores aritmticos so, tal como o prprio nome indica, utilizados para efetuar operaes
aritmticas, ou seja, operaes matemticas como somas, subtraes, multiplicaes, entre outras.

Nome Smbolo Exemplo


Soma + 5+4=9
Subtrao - 154 - 10 = 144
Multiplicao * 5,55 * 10 = 55,5
Diviso / 40 / 2 = 20
1500 %
Resto inteiro de uma diviso %
11 = 4

Tabela 3.1: Operadores aritmticos

3.2 Operadores de atribuio


Os operadores de atribuio servem para atribuir um determinado valor a uma varivel ou cons-
tante. Existem vrios operadores de atribuio e muitos deles funcionam como abreviatura para
operaes aritmticas. Estes operadores so syntactic sugar 1 , ou seja, tm uma sintaxe elegante
de forma a serem facilmente entendidos pelos seres humanos.

3.3 Operadores relacionais


Pode avanar esta e as seces mais frente por agora. Mais tarde ser-lhe- indicado para
aqui voltar. Consultar captulo 4.

Estes operadores (relacionais) permitem-nos estabelecer relaes de comparao entre diversas


variveis.
1 Consulte en.wikipedia.org/wiki/Syntactic_sugar
3.4 Operadores lgicos 29

Nome Smbolo Exemplo Valor de var


Atribuio = var = 20 20
Adio e atribuio += (var = var + n) var += 5 25
Subtrao e atribuio -= (var = var - n) var -= 10 15
Multiplicao e atribuio *= (var = var * n) var *= 4 60
Diviso e atribuio /= (var = var / n) var /= 5 12
Resto inteiro e atribuio %= (var = var % n var %= 5 2

Tabela 3.2: Operadores de atribuio

Nome Smbolo Exemplo


x == y retorna 1 se x for igual a y e
Igualdade ==
0 se tiverem valores diferentes
x != y retorna 1 se x for diferente de y
Diferente !=
ou 0 se x for igual a y
Maior > x >40
Maior ou Igual >= y >= 25
Menor < y <20
Menor ou Igual <= x <= y

Tabela 3.3: Operadores relacionais

3.4 Operadores lgicos


Os operadores lgicos so normalmente utilizados em testes lgicos quando necessrio incluir
mais do que uma condio para que algo acontea. Existem trs operadores lgicos que aqui so
abordados: &&, || e !. Estes operadores tambm so syntactic sugar.

Nome Operador
Operador e &&
Operador ou ||
Negao !

Tabela 3.4: Operadores lgicos

3.4.1 Operador &&


Na programao, o operador && tem como funo a conjugao de condies, ou seja, funciona
da mesma forma que um e na Lngua Portuguesa. Com este elemento, para que algo seja
considerado verdadeiro, todos os elementos tm que o ser. Veja alguns exemplos em que este
operador utilizado para agregar condies:
1 #include <stdio.h>
2
3 int main() {
4 int a;
5 a = 4;
6
7 if (a > 0 && a <= 10) {
8 printf("O nmero %d est entre 1 e 10.", num1);
9 }
10
11 return 0;
12 }

A condio acima pode ser transcrita para uma linguagem lgica da seguinte forma: Se a for
maior que 0 e menor ou igual a 10, ento o cdigo executado.
3.4 Operadores lgicos 30

Este operador pode ser utilizado mais do que uma vez no interior de um teste condies pois
podemos intersetar duas ou mais condies, bastando apenas adicionar && e a outra condio a
ser adicionada.

3.4.2 Operador ||
semelhana do operador anterior, o operador || tambm tem uma funo que pode ser comparada
a uma pequena palavra do Portugus: palavra ou. Com este elemento, para que algo seja
considerado verdadeiro, basta que um elemento o seja.
Com este operador, podemos executar um trecho de cdigo que satisfaz uma das vrias
condies existentes. Por exemplo:
1 #include <stdio.h>
2
3 int main() {
4 int a;
5 a = 3;
6
7 if (a == 3 || a == 5) {
8 printf("O nmero 3 ou 5.\n");
9 }
10
11 return 0;
12 }

Numa linguagem puramente lgica, podemos converter a condio anterior para o seguinte: Se
a for 3 ou 5, ento a linha 8 executada.

3.4.3 Operador !
O operador ! utilizado para indicar a negao, ou numa linguagem corrente, o contrrio de.
Quando utilizado juntamente com uma condio, quer dizer que o cdigo que est condicionado
depende se a negao da condio satisfeita, tal como o antnimo de uma palavra. Ora veja o
seguinte exemplo:
1 #include <stdio.h>
2
3 int main() {
4 int a;
5 a = 0;
6
7 if (!a) {
8 printf("A varivel 0.\n");
9 }
10
11 return 0;
12 }

Relembrando que o nmero 0 considerado o binrio para falso e que, qualquer nmero diferente
de 0 , na linguagem C, considerado como verdadeiro, a condio acima pode ser traduzida para:
Se a no for diferente de 0, ento executa o cdigo.

3.4.4 Operadores de decremento e incremento


Os operadores de incremento e decremento so dois operadores essenciais na vida de qualquer
programador. Imagine que necessita de contar um nmero cujo qual nem o programador sabe o
fim. Vai adicionar/subtrair valor a valor? No, no necessrio.
1 #include <stdio.h>
2
3 int main() {
4 int num;
5
6 num = 1;
3.4 Operadores lgicos 31

7 printf("O nmero %d\n", num);


8
9 num = num + 1;
10 printf("O nmero %d\n", num);
11
12 num += 1;
13 printf("O nmero %d\n", num);
14
15 return 0;
16 }

O cdigo acima imprime a frase O nmero x, onde x corresponde ao valor da varivel num
nesse momento. Este algoritmo faz com que a varivel inicialmente tenha um valor de 1, passando
por 2, chegando finalmente a 3. As linhas num = num + 1 e num += 1 so equivalentes.
Existe outra forma mais simples para adicionar/subtrair um valor a uma varivel: atravs dos
operadores ++ e -. Veja como ficaria o cdigo anterior com estes operadores:
1 #include <stdio.h>
2
3 int main() {
4 int num;
5
6 num = 1;
7 printf("O nmero %d\n", num);
8
9 num++;
10 printf("O nmero %d\n", num);
11
12 num++;
13 printf("O nmero %d\n", num);
14
15 return 0;
16 }

Este ltimo trecho de cdigo ir imprimir o mesmo que o cdigo anterior. Agora, a diferena
aparenta no ser imensa, porm estes operadores sero extremamente teis em testes lgicos/de
repetio.
Para remover uma unidade bastaria colocar - ao invs de ++. Ento podemos concluir que este
operador torna o incremento/decremento mais rpido, mas s funciona quando o assunto uma
unidade. Veja o seguinte exemplo:
1 #include <stdio.h>
2
3 int main() {
4 int num;
5
6 num = 1;
7 printf("O nmero %d\n", num);
8
9 num--;
10 printf("O nmero %d\n", num);
11
12 return 0;
13 }

Posio do operador

Estes operadores podem ocupar duas posies: antes ou depois do nome da varivel, ou seja,
posso colocar tanto num++ como ++num. Quando so utilizados isoladamente, no existe
nenhuma diferena. Porm, quando estamos a efetuar uma atribuio, existem diferenas.
Analise o seguinte exemplo:
1 #include <stdio.h>
2
3.4 Operadores lgicos 32

3 int main() {
4 int a, b, c;
5
6 a = 0;
7 b = a++;
8 c = ++a;
9
10 printf("A: %d, B: %d, C: %d", a, b, c);
11
12 return 0;
13 }

Em primeiro lugar, so declaradas trs variveis: a, b e c. Seguidamente, atribudo o


valor 0 primeira varivel. Quando o valor a++ atribudo varivel b, esta fica com valor
0 ou 1? E o que acontece com a varivel a? A varivel b ir assumir o valor 0, e um valor
incrementado a a ficando esta com o valor 1, ou seja, b = a++ um atalho para o seguinte:

1 b = a;
2 a++;

Depois desta atribuio, atribuda varivel c, o valor ++a, ou seja, primeiro


incrementado o valor da varivel a e s depois que o valor de esta atribudo varivel c.
Ento, isto um atalho para o seguinte:

1 ++a;
2 c = a;
Captulo
4
Controlo de Fluxo
Este quarto captulo tem como objetivo mostrar-lhe as formas de controlar o fluxo de uma aplicao,
de um algoritmo, de um programa.

Definio 21. Controlo de Fluxo refere-se ao controlo que se tem sobre a ordem de comandos a
serem executados no decorrer de um programa.

Ao controlar o fluxo pode-se direcionar o utilizador para as aes que este escolheu e executar
apenas trechos de cdigo dependendo de uma determinada condio, controlando a ordem pela
qual os comandos so executados.
Existem diversas estruturas que nos permitem controlar o fluxo de uma aplicao. A maioria
das que so aqui abordadas so transversais maioria das linguagens de programao existentes.
Antes de continuar aconselhamos a que reveja os operadores relacionais e lgicos no captulo
3.

4.1 Estrutura if/else


A primeira estrutura a abordar a conhecida if else o que, numa traduo literal para Portu-
gus, quer dizer se caso contrrio. Com esta estrutura, um determinado trecho de cdigo pode
ser executado dependendo do resultado de um teste lgico.

Definio 22. Um teste lgico consiste na determinao da verdade ou falsidade de uma condio.

Sintaxe

1 if (condio) {
2 // cdigo a executar caso a condio seja verificada
3 } else {
4 // caso contrrio, isto executado.
5 }

Exemplo

Imagine que necessita criar um pequeno programa que deve imprimir se o valor de uma varivel
maior, menor ou igual a 50. Como ir proceder? A criao deste algoritmo deveras simples,
bastando inicializar a varivel e efetuar um teste lgico. Veja ento como este problema poderia
ser resolvido:
1 #include <stdio.h>
2
3 int main() {
4 int n = 25;
5
6 if (n >= 50) {
7 printf("O valor %d maior ou igual a 50.", n);
8 } else {
4.2 Estrutura while 34

9 printf("O valor %d menor que 50.", n);


10 }
11
12 return 0;
13 }

Se executar o trecho de cdigo anterior, a mensagem O valor 25 menor que 50. ser
imprimida, pois no se verificou a condio n >= 50, executando-se o cdigo dentro do bloco
else.
Imagine agora que precisa verificar as seguintes trs condies:
maior que 50?
igual a 50?
menor que 50?
O caminho mais bvio seria o seguinte:
1 if (n > 50) {
2 printf("O valor %d maior que 50.\n", n);
3 }
4
5 if (n < 50) {
6 printf("O valor %d menor que 50.\n", n);
7 }
8
9 if (n == 50) {
10 printf("A varivel igual a 50.\n");
11 }

O algoritmo acima um pouco repetitivo e extenso; pode ser simplificado ao ser agregado em
apenas um teste sequencial como seguinte:
1 if (n == 50) {
2 printf("A varivel igual a 50.\n"); //A
3 } else if (n < 50) {
4 printf("O valor %d menor que 50.\n", n); //B
5 } else {
6 printf("O valor %d maior que 50.\n", n); //C
7 }

Podemos traduzir o cdigo anterior para uma linguagem corrente da seguinte forma: Se n
for igual a 50; ento faz A, ou se n for menor que 50 faz B; caso contrrio
faz C.

4.2 Estrutura while


Outra estrutura para controlar o fluxo que muito importante a estrutura while, que em
Portugus significa enquanto. Esta estrutura permite repetir um determinado trecho de cdigo
enquanto uma condio for verdadeira.

Sintaxe

1 while(condio) {
2 //Algo acontece
3 }

Ora vejamos um exemplo: precisa imprimir todos os nmeros entre 0 e 100 (inclusive). Para
isso no necessrio utilizar o comando printf 101 vezes, bastando utilizar a repetio while.
Ora veja:
1 #include <stdio.h>
2
3 int main() {
4 int num = 0;
5
4.3 Estrutura switch 35

6 while(num <= 100) {


7 num++;
8 printf("%d\n", num);
9 }
10
11 return 0;
12 }

Pode-se traduzir o trecho anterior para uma linguagem corrente da seguinte forma: Enquanto
num for menor ou igual a 100, imprime a varivel num e incrementa-lhe um
valor.

4.3 Estrutura switch


A estrutura switch est presente na maioria das linguagens de programao, que numa traduo
literal para Portugus significa interruptor. Esta estrutura deveras til quando temos que
executar uma ao dependendo do valor de uma varivel.
A estrutura de controlo switch pode ser utilizada como forma de abreviar um teste lgico if
else longo.

Sintaxe

1 switch(variavel) {
2 case "valorUm":
3 //Cdigo da operao
4 break;
5 case "valorDois":
6 //Cdigo da operao
7 break;
8
9 //...
10
11 default:
12 //Cdigo executado caso no seja nenhuma das opes anteriores
13 break;
14 }

Imagine que tem que pedir ao utilizador um valor e que vai executar uma ao dependendo
o valor que o utilizador escolheu. Esse menu tem 5 opes. Poderia resolver este problema da
seguinte forma:
1 #include <stdio.h>
2
3 int main() {
4 int opcao;
5
6 printf("Insira a opo:\n");
7 scanf("%d", &opcao);
8
9 switch(opcao) {
10 case 1:
11 printf("Escolheu a opo 1");
12 break;
13 case 2:
14 printf("Escolheu a opo 2");
15 break;
16 case 3:
17 printf("Escolheu a opo 3");
18 break;
19 case 4:
20 printf("Escolheu a opo 4");
21 break;
22 case 5:
23 printf("Escolheu a opo 5");
24 break;
25 default:
4.4 Estrutura do/while 36

26 printf("Opo inexistente.");
27 break;
28 }
29
30 return 0;
31 }

O cdigo acima faz: em primeiro lugar, tudo depende do valor da varivel opcao. Caso seja
1, ser imprimida a mensagem Escolheu a opo 1 e por a a diante. Caso a opo inserida
no exista no cdigo, o cdigo contido em default ir ser executado.
Mais frente iremos falar mais sobre o break. Por agora no lhe d muita importncia, mas
coloque-o sempre.
O algoritmo anteriormente reproduzido pode tambm tomar a forma de uma sequncia de if
else, embora com uma menor legibilidade. Ora veja:
1 #include <stdio.h>
2
3 int main() {
4 int option;
5
6 printf("Insira a opo:\n");
7 scanf("%d", &option);
8
9 if (option == 1) {
10 printf("Escolheu a opo 1");
11 } else if (option == 2) {
12 printf("Escolheu a opo 2");
13 } else if (option == 3) {
14 printf("Escolheu a opo 3");
15 } else if (option == 4) {
16 printf("Escolheu a opo 4");
17 } else if (option == 5) {
18 printf("Escolheu a opo 5");
19 } else {
20 printf("Opo inexistente.");
21 }
22
23 return 0;
24 }

4.4 Estrutura do/while


Outra forma de controlar o fluxo a abordar a estrutura do while, que tem um nome semelhante
j abordada while. A diferena existente entre essas duas estruturas pequena, mas importante.
Ao contrrio do que acontece na estrutura while, no do while, o cdigo executado pri-
meiro e s depois que a condio testada. Se a condio for verdadeira, o cdigo executado
novamente. Podemos concluir que esta estrutura obriga o cdigo a ser executado pelo menos
uma vez.

Sintaxe

1 do
2 {
3 //cdigo a ser repetido
4 } while (condio);

Imagine agora que precisa criar uma pequena calculadora (ainda em linha de comandos) que
receba dois nmero e que, posteriormente, efetua uma soma, subtrao, multiplicao ou diviso.
Esta calculadora, aps cada clculo dever pedir ao utilizador para inserir se quer continuar a
realizar clculos ou no. Poderamos proceder da seguinte forma:
1 #include <stdio.h>
2
3 int main() {
4.5 Estrutura for 37

4 int calcular;
5
6 do {
7
8 char operacao;
9 float num1,
10 num2;
11
12 // limpeza do buffer. ou __fpurge(stdin); em linux
13 fflush(stdin);
14
15 printf("Escolha a operao [+ - * / ]: ");
16 scanf("%c", &operacao);
17
18 printf("Insira o primeiro nmero: ");
19 scanf("%f", &num1);
20
21 printf("Insira o segundo nmero: ");
22 scanf("%f", &num2);
23
24 switch(operacao) {
25 case '+':
26 printf("%.2f + %.2f = %.2f\n", num1, num2, num1 + num2);
27 break;
28 case '-':
29 printf("%.2f - %.2f = %.2f\n", num1, num2, num1 - num2);
30 break;
31 case '*':
32 printf("%.2f * %.2f = %.2f\n", num1, num2, num1 * num2);
33 break;
34 case '/':
35 printf("%.2f / %.2f = %.2f\n", num1, num2, num1 / num2);
36 break;
37 default:
38 printf("Digitou uma operao invlida.\n");
39 break;
40 }
41
42 printf("Insira 0 para sair ou 1 para continuar: ");
43 scanf("%d", &calcular);
44
45 /* Verifica-se o valor da varivel calcular. Se for 0 considerado falso
46 e o cdigo no executado mais vez nenhuma. Caso seja um nmero diferente
47 de 0, a condio retornar um valor que representa true (todos os nmeros
48 exceto 0) e continuar-se- a executar o cdigo. */
49 } while (calcular);
50
51 return 0;
52
53 }

4.5 Estrutura for


A ltima estrutura de controlo de fluxo a abordar, mas no o menos importante, a estrutura
for. Esta estrutura loop um pouco mais complexa que as anteriores, mas muito til e permite
reutilizar cdigo.

Definio 23. O termo ingls loop refere-se a todas as estruturas que efetuam repetio: while,
do while e for.

Sintaxe

1 for(inicio_do_loop ; condio ; termino_de_cada_iterao) {


2 //cdigo a ser executado
3 }

Onde:
4.6 Interrupo do fluxo 38

inicio_do_loop uma ao que executada no incio do ciclo das repeties;


condio a condio para que o cdigo seja executado;
termino_de_cada_iterao uma ao a executar no final de cada iterao.
Imagine agora que precisa de imprimir todos os nmeros pares de 0 a 1000. Para isso poderia
recorrer estrutura while e a uma condio if da seguinte forma:
1 #include <stdio.h>
2
3 int main() {
4 int num = 0;
5
6 while (num <= 1000) {
7 if (num % 2 = 0) {
8 printf("%d\n", num);
9 }
10
11 num++;
12 }
13
14 return 0;
15 }

Utilizando a estrutura for, o algoritmo acima poderia ser reduzido ao seguinte:


1 #include <stdio.h>
2
3 int main() {
4 for(int num = 0; num <= 1000; num++) {
5 if (num % 2 = 0) {
6 printf("%d\n", num);
7 }
8 }
9
10 return 0;
11 }

4.6 Interrupo do fluxo


As estruturas de controlo de fluxo so muito importantes, mas aprender como se as interrompe
tambm o . Por vezes necessrio interromper uma determinada repetio dependendo de um
teste lgico interno repetio.

4.6.1 Terminar ciclo com break


O break permite que interrompamos o fluxo em loops e na estrutura switch. Se no colocarmos
este comando no final de cada caso da estrutura switch, o cdigo continuaria a ser executado,
incluindo as restantes opes.
Imagine que por algum motivo precisa encontrar o primeiro nmero divisvel por 17, 18 e 20
entre 1 e 1000000. Iria, provavelmente, utilizar a estrutura for para percorrer todos estes nmeros.
Veja como poderamos fazer:
1 #include <stdio.h>
2
3 int main() {
4 int num = 0;
5
6 for (int count = 1; count <= 1000000; count++) {
7 if(num == 0) {
8 if((count % 17 == 0) && (count % 18 == 0) && (count % 20 == 0)) {
9 num = count;
10 }
11 }
12 }
13
4.6 Interrupo do fluxo 39

14 printf("O nmero divisvel por 17, 18 e 20 entre 1 e 1000000 : %d", num);


15 return 0;
16 }

Depois de encontrar o nmero em questo, que 3060, necessrio continuar a executar o


loop? Seriam executadas mais 996940 iteraes (repeties). Tal no necessrio e podemos
poupar os recursos consumidos, parando o ciclo de repeties. Ora veja:
1 #include <stdio.h>
2
3 int main() {
4 int num = 0;
5
6 for (int count = 1; count <= 1000000; count++) {
7 if(num == 0 && (count%17==0) && (count%18==0) && (count%20==0)) {
8 num = count;
9 break;
10 }
11 }
12
13 printf("O nmero divisvel por 17, 18 e 20 entre 1 e 1000000 : %d", num);
14 return 0;
15 }

4.6.2 Terminar iterao com continue


O comando continue parecido ao anterior s que, em vez de cancelar todo o ciclo de repeties,
salta para a prxima iterao, cancelando a atual.
Precisa de somar todos os nmeros inteiros entre 0 e 1000 que no so mltiplos de 2 nem de
3. Para o fazer, ir ter que saltar todas as somas em que o nmero atual mltiplo de 2 e 3. Veja
ento uma proposta de como poderia ficar:
1 #include <stdio.h>
2
3 int main() {
4 int sum = 0;
5
6 for (int count = 1; count <= 1000; count++) {
7 if(count%2 == 0 || count%3 == 0) {
8 continue;
9 }
10
11 sum += count;
12 }
13
14 printf("Soma %d", sum);
15 return 0;
16 }

O que acontece se percorrem todos os nmeros de 1 a 1000, e se for divisvel por 2 ou por
3, salto para o prximo nmero. Caso esta condio no se verifique, adiciono o nmero atual
soma.
Captulo
5
Funes e Procedimentos
Neste captulo abordada uma parte fundamental da programao funcional, ou seja, as funes
e procedimentos.

Definio 24. Uma funo um bloco de cdigo, que tal como o prprio nome indica, tem uma
funo prpria, ou seja, que serve para um finalidade especfica.

Definio 25. Procedimentos so blocos de cdigo que contm uma funo especfica. A diferena
entre funes e procedimentos que os procedimentos no retornam qualquer valor.

Ao invs de colocarmos um determinado trecho de cdigo diversas vezes, basta criarmos uma
funo com esse cdigo e de cada vez que for necessrio, precisamos apenas de invocar a funo.
As funes permitem-nos, por exemplo, reutilizar cdigo.

Definio 26. Invocar uma funo o nome que se d quando o nome de uma funo mencionado
no cdigo e esta chamada.

Durante os seus anos de programador ir criar milhares de funes para os mais diversos
propsitos. Ento recomendvel que v guardando as funes que utiliza porque futuramente
poder vir a precisar delas.
Existe uma funo que tem vindo a ser sempre utilizada: o main. a funo principal do
programa; aquela que executada automaticamente quando um programa iniciado.

5.1 Criao de funes


Ento, o primeiro passo a dar saber como se criam funes.

Sintaxe

1 tipo_dado_retorno nome_da_funcao(parametros) {
2 // contedo da funo
3 }

Onde:
tipo_dado_retorno corresponde ao tipo de dados que a funo vai devolver (retornar);
nome_da_funcao corresponde ao nome da funo em questo;
parametros corresponde aos parmetros da funo, algo que ser abordado mais frente.
Imagine que precisa de um procedimento que imprime a mensagem Hello World! no ecr.
Poderia fazer isso da seguinte forma:
1 #include <stdio.h>
2
3 int main() {
4 dizHello();
5.1 Criao de funes 41

5 return 0;
6 }
7
8 void dizHello() {
9 printf("Ol Mundo!\n");
10 }

A funo chama-se dizHello e no retorna nenhuns dados (void). O que est contido entre
chavetas o cdigo que executado quando o procedimento chamado.

5.1.1 Argumentos e parmetros


No exemplo acima possvel visualizar que tanto na invocao da funo, como na sua definio
foi colocado um par de parnteses sem nada. Isto acontece porque no existem parmetros.

Definio 27. Parmetros o conjunto de elementos que uma funo pode receber (input).

Imagine agora que necessita de uma funo que efetua uma soma: como enviamos os valores
para uma funo? Definindo o nome e o tipo de parmetros. Ora veja:
1 void soma(int n1, int n2) {
2 int soma = n1 + n2;
3 }

A funo representada no trecho acima, denominada soma, tem dois parmetros, o n1 e o n2,
ambos do tipo int. Para utilizar a funo, basta ento proceder do seguinte modo:
1 soma(4, 6);

Os nmeros 4 e 6 (que podiam ser quaisquer outros) so denominados argumentos. A funo


armazena os dois argumentos na varivel soma que apenas est disponvel dentro da funo, o
valor da soma entre os dois nmeros.
Definio 28. Argumento o nome dado a um valor que enviado para a funo.

5.1.2 Retorno de uma funo


Geralmente uma funo retorna um valor de forma a poder ser utilizado para outro fim. Para isso,
ao invs de colocarmos void na declarao da funo, devemos colocar qualquer outro tipo de
dados.
Imagine que quer que uma funo retorne o valor de uma soma entre dois nmeros. Poderia
proceder da seguinte forma:
1 int soma(int n1, int n2) {
2 return n1 + n2;
3 }

A funo acima retorna dados do tipo int e tem dois parmetros: o n1 e n2. Podemos aplicar
esta funo, por exemplo, no seguinte contexto, onde o programa efetua a soma de dois nmeros
dados pelo o utilizador.
1 #include <stdio.h>
2
3 int main() {
4 int a, b;
5
6 printf("Insira o primeiro nmero: ");
7 scanf("%d", &a);
8
9 printf("Insira o segundo nmero: ");
10 scanf("%d", &b);
11
12 printf("A soma %d", soma(a,b));
13 return 0;
14 }
15
5.2 Algumas funes teis 42

16 int soma(int n1, int n2) {


17 return n1 + n2;
18 }

5.2 Algumas funes teis


Aqui encontram-se algumas funes que so teis no seguimento deste livro. Algumas so relativas
entrada e sada de dados, ou seja, funes que podem receber dados inseridos pelo utilizador e
funes que permitem mostrar dados no ecr. Outras relativas matemtica. Ao longo do livro,
outras funes sero abordadas.

5.2.1 Funo puts


A funo puts serve simplesmente para imprimir texto no ecr. Ao contrrio da funo printf
no nos permite imprimir texto formatado.

Sintaxe

1 puts("frase");

Ao imprimir uma frase com esta funo, o carcter correspondente a uma nova linha sempre
adicionado ao final da mesma.
Imagine agora que precisa de imprimir uma mensagem que no contem nenhum valor varivel
e a mensagem era Bem-vindo ao programa XYZ!. Poderia faz-lo da seguinte forma:
1 puts("Bem-vindo ao programa XYZ!");

5.2.2 Funo scanf


A funo scanf permite-nos obter diversos tipos de dados do utilizador. A utilizao desta funo
semelhante da j conhecida funo printf; so como um espelho uma da outra. A scanf
reconhece o input e a printf formata o output.

Sintaxe

1 scanf(fraseFormatada, &variaveis...);

Onde:
fraseFormatada corresponde formatao do que ir ser imprimido com os espaos para
as variveis;
variaveis corresponde s variveis onde vo ser armazenados os valores obtidos por ordem
de ocorrncia. O nome da varivel deve ser sempre precedido por um &;
Imagine agora que vai criar um algoritmo que pea a idade ao utilizador e a imprima logo de
seguida. Poderia fazer isto da seguinte forma:
1 #include <stdio.h>
2
3 int main() {
4 int idade;
5
6 printf("Digite a sua idade: ");
7 scanf("%d", &idade);
8
9 printf("A sua idade %d", idade);
10 return 0;
11 }

Como pode verificar atravs da stima linha do trecho de cdigo anterior, o primeiro parmetro
da funo scanf deve ser uma string com o tipo de caracteres a ser inserido. Todos os parmetros
5.2 Algumas funes teis 43

seguintes devero ser o nome das variveis s quais se quer atribuir um valor, precedidos por &.
Ao se executar o trecho de cdigo anterior, a mensagem Digite a sua idade: ir aparecer
o ecr e o cursor ir posicionar-se logo aps essa frase aguardando que um valor seja inserido.
Deve-se inserir o valor e premir a tecla enter. Depois ser imprimida uma mensagem com a idade
inserida.
Relembro que pode utilizar as seguintes expresses para definir o tipo de dados a ser introduzido:
%d Nmeros inteiros (int);
%f Nmeros decimais (float e double);
%c Caracteres (char).
Podem-se pedir mais do que um valor com a funo scanf. Ora veja o seguinte exemplo:
1 #include <stdio.h>
2
3 int main()
4 {
5 int num1, num2;
6
7 printf("Digite dois nmeros: ");
8 scanf("%d %d", &num1, &num2);
9
10 printf("Os nmeros que digitou so %d e %d.", num1, num2);
11
12 return 0;
13 }

Assim, quando executar o cdigo acima, ter que escrever dois nmeros, separados por um
espao, tab ou enter.

5.2.3 Funo getchar


Existe uma forma simplicssima de pedir caracteres ao utilizador: utilizando a funo getchar.
Basta igualar uma varivel funo. Esta funo recomendvel quando se quer receber um nico
carcter numa linha.

Sintaxe

1 variavel = getchar();

No seguinte exemplo pedido para inserir a primeira letra do seu nome.


1 #include <stdio.h>
2
3 int main() {
4 printf("Insira a primeira letra do seu nome: ");
5 char letra = getchar();
6
7 printf("A primeira letra do seu nome %c.", letra);
8 return 0;
9 }

5.2.4 Limpeza do buffer


Quando se fala em entrada e sada de dados, deve-se ter em conta o buffer e a sua limpeza, pois
algo extremamente importante que pode fazer a diferena entre um programa que funciona e um
que no funciona.

Definio 29. Buffer o nome dado regio da memria de armazenamento fsica que utilizada
para armazenar temporariamente dados.

Ora analise o seguinte cdigo:


1 #include <stdio.h>
2
5.2 Algumas funes teis 44

3 int main()
4 {
5 char letra1, letra2;
6
7 printf("Insira a primeira letra do seu nome: ");
8 scanf("%c", &letra1);
9
10 printf("E agora a ltima: ");
11 scanf("%c", &letra2);
12
13 printf("O seu nome comea com \"%c\" e termina com \"%c\".", letra1, letra2);
14
15 return 0;
16 }

Ao olhar para o cdigo acima, provavelmente pensar que tudo ir correr como previsto:
executa-se o programa, digitam-se duas letras (X e Y, por exemplo) e depois imprimida
a mensagem O seu nome comea com X e termina com Y.. Infelizmente, no isso que acontece.
Se executar o algoritmo acima, ir inserir a primeira letra, clicar na tecla enter, mas depois o
programa ir chegar ao fim dizendo que o seu nome termina com a letra (em branco). Por que
que isto acontece? Quando a tecla enter premida, o programa submete a letra inserida, mas o
carcter correspondente tecla enter, \n, tambm fica na memria. Assim, quando pedido um
novo carcter, o que estava na memria automaticamente submetido.
Para que isso no acontea, basta limpar o buffer antes de pedir dados novamente ao utilizador.
No Windows pode ser utilizada a funo fflush e em sistemas operativos Linux a funo __-
fpurge. Ento, ficaria assim:
1 #include <stdio.h>
2
3 int main()
4 {
5 char letra1, letra2;
6
7 printf("Insira a primeira letra do seu nome: ");
8 scanf("%c",&letra1);
9
10 // stdin corresponde entrada teclado
11 fflush(stdin);
12 __fpurge(stdin);
13
14 printf("E agora a ltima: ");
15 scanf("%c",&letra2);
16
17 printf("O seu nome comea com \"%c\" e termina com \"%c\".", letra1, letra2);
18
19 return 0;
20 }

A utilizao deste tipo de funes no recomendvel, pois no uma conveno da linguagem


C. Ento pode tomar aes diferentes dependendo do compilador. O recomendvel utilizar
funes que no incluam lixo quando necessrio ler algo do utilizador.

5.2.5 Funo rand


Durante a sua jornada no mundo da programao ir precisar de gerar nmeros aleatrios para
os mais diversos fins. Em C podemos gerar nmeros aleatrios recorrendo funo rand. Para
poder utilizar esta funo deve-se incluir a biblioteca stdlib.h.

Sintaxe

1 int numero = rand();


5.2 Algumas funes teis 45

Imagine que precisa gerar um nmero aleatrio entre 1 e 10. Em primeiro lugar teria que obter
o resto da diviso de rand por 10 e somar 1. Ora veja:
1 int numero = (rand() % 10) + 1;

Se experimentar executar um algoritmo que contenha a linha de cdigo acima, ir verificar


que o nmero gerado sempre o mesmo, mas ningum quer que o nmero gerado seja sempre
o mesmo. Ento, temos que semear a semente que vai dar origem ao nmero. Para o fazer
deve-se recorrer funo srand.
A funo srand permite adicionar um nmero como ponto de partida de forma a gerar um
nmero aleatrio. Podemos, por exemplo, gerar um nmero baseado na hora e tempo atuais. Ora
veja um exemplo:
1 #include <stdio.h>
2 #include <stdlib.h>
3 #include <time.h>
4
5 int main() {
6 /* "semeia-se" utilizando o tempo atual num
7 tipo unsigned, ou seja, s com valores positivos */
8 srand((unsigned)time(NULL));
9 int numero = (rand() % 10) + 1;
10
11 printf("O nmero gerado %d.", numero);
12 return 0;
13 }

Agora, mesmo que execute o mesmo cdigo vrias vezes, ir verificar que o nmero gerado
diferente na maioria das vezes. No se esquea de incluir a biblioteca time.h para poder utilizar
a funo time().
Captulo
6
Arrays
At este ponto do livro, apenas tm sido abordadas variveis que contm um e apenas um valor.
Chegou a altura de falar de uma estrutura de dados muito importante no mundo da programao,
os arrays.

Definio 30. Arrays (tambm conhecidos por tabelas ou vetores) so estruturas de dados que
permitem armazenar mltiplos valores em posies bem definidas.

Os arrays so como matrizes/tabelas de dados onde cada dado se encontra localizado numa
determinada posio que pode ser acedida atravs de coordenadas, atravs de um ndice (por
exemplo, ndice 4 para a quarta posio). Existem os arrays unidimensionais e multidimensionais.

6.1 Arrays unidimensionais


Os arrays unidimensionais podem ser comparados a tabelas com uma nica coluna, mas com
diversas linhas. So o tipo mais simples de array. Eis a declarao geral de um array:
1 tipo nomeVariavel[numeroDeElementos];

Onde:
tipo corresponde ao tipo de dados que o array vai armazenar;
nomeVariavel corresponde ao nome do array;
numeroDeElementos corresponde ao nmero mximo de elementos que o array ir conter.
Os arrays so zero-index, ou seja, a primeira posio 0 e no 1. Para aceder ltima posio
de um array com 6 linhas, deve-se pedir o que est contido na posio 5. Ora veja um exemplo:
1 int idades[10]; // array de 10 elementos
2
3 idades[0] = 14; // atribuio correta
4 idades[4] = 12; // atribuio correta
5 idades[7] = 15; // atribuio correta
6 idades[10] = 20; // atribuio incorreta (tamanho mximo do array ultrapassado)

No exemplo anterior, a ltima declarao est errada porque o ndice mximo do array foi
ultrapassado, ou seja, tentou-se aceder a uma posio inexistente. O array tem 10 elementos, 10
posies. O primeiro no ndice 0 e o ltimo no ndice 9.
semelhana do que acontece com as variveis, pode-se atribuir o valor dos arrays no momento
da declarao. Por exemplo:
1 int idades[10] = {0, 1, 2, 3, 4, 5, 6, 7, 8, 9}

6.2 Arrays multidimensionais


Um array multidimensional um array que tem mais do que uma dimenso, ou seja, se comparamos
a uma tabela tem mais do que uma coluna.
6.2 Arrays multidimensionais 47

1 tipo nome[linhas][colunas];

Relativamente contagem das posies, comea-se sempre no 0, tal como acontece com os
arrays unidimensionais. Analise ento o seguinte cdigo:
1 float notas[6][5]; // declarao de um array com 6 linhas e 5 colunas
2
3 notas[0][0] = 18.7; // linha 1, coluna 1
4 notas[0][1] = 15.4; // linha 1, coluna 2
5 notas[3][2] = 19.6; // linha 4, coluna 3
6 notas[5][4] = 17.5; // linha 6, coluna 5
7 notas[4][3] = 57.5; // linha 5, coluna 4
8 notas[6][0] = 20.0; // excedeu o mximo de linhas (6)
9 notas[5][5] = 17.4; // excedeu o mximo de colunas (5)

No exemplo anterior possvel visualizar a criao de um array com 6 linhas e 5 colunas. Este
array, com os dados inseridos, poderia ser traduzido na seguinte tabela:

18.7 15.4

19.6
57.5
17.5

Tabela 6.1: Representao de um array 6 por 5

Tal como nos arrays unidimensionais, podemos adicionar os valores ao array multidimensional
no momento da sua declarao. Veja ento o seguinte exemplo:
1 int idades[2][4] = {
2 {1, 2, 3, 4},
3 {0, 1, 2, 3}};
Captulo
7
Apontadores
Este captulo foca num tema que no tem a mesma significncia em todas as linguagens de pro-
gramao, mas algo que torna mais clara a viso do funcionamento do computador e da gesto
da memria RAM. O tema em questo os apontadores.
Para os computadores, tudo se resume a bits, ou seja, a zeros e uns. Ento, para os compu-
tadores, as diferenas que ns conhecemos entre os diversos tipos de dados (char, int, double,
float, etc) so praticamente inexistentes.
Quando uma varivel declarada, uma poro de memria RAM reservada. Ento todas
as variveis/arrays tm um endereo nico. Os apontadores so um tipo de variveis que podem
armazenar endereos da memria.

Definio 31. Apontadores, tambm conhecidos por ponteiros ou pointers, so um tipo de dados
que permite armazenar um endereo da memria, representados, geralmente, em nmeros hexadeci-
mais.

7.1 Tamanho e endereo de uma varivel


Primeiramente, deve-se recordar que todos os tipos de dados ocupam um espao diferente na
memria RAM e que para saber quantas bytes ocupam um determinado tipo se recorrer funo
sizeof. Para saber o quanto ocupa qualquer varivel do tipo int, faria o seguinte:
1 sizeof(int);

Para saber, por exemplo, a quantidade de bytes ocupadas pelos quatro tipos principais de dados
e o endereo da varivel utilizada, executaria o seguinte:
1 #include <stdio.h>
2 #include <stdlib.h>
3
4 int main()
5 {
6 char caractere;
7 int inteiro;
8 float Float;
9 double Double;
10
11 printf("Tipo\tNum de Bytes\tEndereo\n");
12 printf("-------------------------------------\n");
13 printf("Char\t%d byte \t\t%p\n", sizeof(caractere), &caractere);
14 printf("Inteiro\t%d bytes \t%p\n", sizeof(inteiro), &inteiro);
15 printf("Float\t%d bytes \t%p\n", sizeof(Float), &Float);
16 printf("Double\t%d bytes \t%p\n", sizeof(Double), &Double);
17
18 return 0;
19 }

O cdigo acima ir gerar uma espcie de tabela e utiliza %p com a funo printf de forma a
imprimir um pointer. No meu caso, recebi algo semelhante ao seguinte:
7.2 Declarao de apontadores 49

Tipo Num de Bytes Endereo


Char 1 byte 0028FF1F
Inteiro 4 bytes 0028FF18
Float 4 bytes 0028FF14
Double 8 bytes 0028FF08

Tabela 7.1: Tamanho e endereo de variveis

Relembro que o endereo que aparece na tabela 7.1 o endereo corresponde posio da
varivel utilizada para saber o nmero de bytes que o tipo em questo ocupava.
Pode verificar que todos os tipos de dados, exceto o tipo char, ocupam mais do que um byte na
memria RAM. Ento, o endereo que imprimido corresponde apenas ao primeiro byte ocupado
pela varivel.
Quando imprimiu o endereo das variveis no excerto de cdigo anterior, verificou que o en-
dereo imprimido no contm apenas nmeros, mas tambm letras. Ao tipo de numerao que
visualizou d-se o nome hexadecimal.
Hexadecimal para Decimal
A numerao hexadecimal tem como base 16 dgitos, enquanto que a decimal tem como
base 10 dgitos. A tabela 10.2 (nos anexos) mostra a correspondncia entre um carcter
hexadecimal a um carcter decimal.
Ir-se- converter o nmero hexadecimal 0028FF1F para decimal. Em primeiro lugar,
ter-se- que tirar os primeiros dois zeros que so, neste caso, desprezveis.
De seguida necessrio conhecer o significado de cada dgito hexadecimal em nmero deci-
mal que est presente nesse nmero. Em decimal, os nmeros 2, 8, F e 1 so, respetivamente,
2, 8, 15 e 1.
Para efetuar a converso, tem que multiplicar cada um desses nmeros por uma potncia de
base 16 cujo expoente igual posio de cada um dos nmeros (da direita para a esquerda).
Ento, tem-se:
(2 165 ) + (8 164 ) + (15 163 ) + (15 162 ) + (1 161 ) + (15 160 ) =
= 2097152 + 524288 + 61440 + 3840 + 16 + 15 =
= 2686751

Sabendo que a varivel inteiro ocupa 4 bytes e que o primeiro byte se localiza na posio
2686744 (em decimal), poderemos dizer que a varivel completa ocupa os bytes cujas posies so
2686744, 2686745, 2686746 e 2686747 (em decimal).

7.2 Declarao de apontadores


A declarao deste tipo de variveis bastante semelhante declarao dos outros tipos de vari-
veis. A nica diferena que de deve colocar um * (asterisco) antes do nome da varivel ou depois
do tipo de dados. O tipo de dados de um apontadores deve ser igual ao tipo de dados da varivel
que para a qual ele vai apontar.
A declarao de apontadores faz-se da seguinte forma:
1 tipo* nome;

7.3 Inicializao de apontadores


Tal como a declarao, a inicializao de um apontador semelhante das variveis. Basta igualar
um apontador ao endereo de uma outra varivel. Para obter o endereo de outra varivel basta
colocar um e comercial antes do seu nome. Ora veja o seguinte exemplo:
7.3 Inicializao de apontadores 50

1 #include <stdio.h>
2 #include <stdlib.h>
3
4 int main() {
5 int numero = 5;
6 int* ponteiro = &numero;
7
8 // igual a: printf("%d e %p", numero, &numero);
9 printf("%d e %p", numero, ponteiro);
10 return 0;
11 }

No cdigo acima, declarada a varivel numero, do tipo int, que igual a 5. Seguidamente,
declarado um apontador denominado ponteiro e inicializado com o valor &numero, ou seja, com
a posio da varivel numero. Podemos dizer que ponteiro aponta para numero. No final
imprimido o contedo da varivel numero e o o apontador da mesma, armazenado na varivel
ponteiro.
Imagine agora que precisa efetuar a soma de duas variveis utilizando apenas apontadores.
Sim, este um exemplo bizarro, mas que funciona.

Se est a ter problemas com a codificao dos caracteres no Windows, inclua a biblioteca
Windows.h e altere a pgina de codificao da linha de comandos como feito na linha seis
do exemplo seguinte.

1 #include <stdio.h>
2 #include <stdlib.h>
3 #include <windows.h>
4
5 int main() {
6 SetConsoleOutputCP(65001);
7
8 int a, b, c;
9 int* p, q;
10
11 a = 5;
12 b = 4;
13
14 p = &a;
15 q = &b;
16 c = *p + *q;
17
18 printf("A soma de %d e %d %d.", a, b, c);
19 return 0;
20 }

No exemplo anterior so declaradas cinco variveis. Trs que contm nmeros inteiros (a, b e c)
e duas que contm endereos da memria RAM (p e q). Para efetuar a soma entre as variveis a e
b e armazenar a mesma na varivel c utilizando apontadores, tem que se igualar os apontadores p
e q ao endereo das variveis a e b. De seguida, a varivel c ter que ser igual soma do contedo
que para o qual os apontadores esto a apontar (*p + *q.
Imagine agora que precisa de um procedimento que troque os valores de duas variveis. Inici-
almente, poderia pensar em fazer algo deste gnero:
1 void trocaDeValores( int x, int y) {
2 int temp;
3
4 temp = x;
5 x = y;
6 y = temp;
7 }

Sintaticamente, nada est errado, mas o procedimento no vai realmente alterar os valores das
variveis. O que acontece no trecho de cdigo anterior que o procedimento recebe apenas o
contedo de duas variveis e coloca-os numas mseras variveis locais, ou seja, aquelas que apenas
esto disponveis apenas dentro de uma funo/procedimento. O procedimento correto a tomar
7.4 Operaes com apontadores 51

seria o seguinte:
1 void trocaDeValores(int* p, int* q) {
2 int temp;
3
4 temp = *p;
5 *p = *q;
6 *q = temp;
7 }

Esta funo realmente troca os valores de duas variveis. Enviam-se dois apontadores, dois
endereos, e a varivel troca os valores que esto em ambos os endereos da memria RAM,
trocando os valores das variveis.

7.4 Operaes com apontadores


Uma das principais vantagens da utilizao de apontadores a fcil modificao de outras variveis
e que algumas linguagens, como a linguagem C, trabalham mais rapidamente com apontadores.
Tal como acontece com as restantes variveis, podemos incrementar e decrementar apontadores,
ou seja, incrementar ou decrementar o endereo que para o qual aponta o apontador.
Imagine que temos um array do tipo double com dois elementos.. Sabemos tambm que
cada varivel desse tipo ocupa, geralmente, 8 bytes na memria RAM. De seguida, criado um
apontador cujo endereo aponta para esse array. O que vai acontecer que esse endereo apontar
para o primeiro byte do array e no para todos eles.
1 double numeros[2]; // declarao do array com dois elementos.
2 double *apontador;
3
4 apontador = numeros;

Hipoteticamente falando, a varivel apontador armazena o endereo 4550. Ento, sabendo


que o array ocupa, na totalidade, 16 bytes (visto que tem a capacidade para armazenar dois
elementos do tipo double, que ocupam 8 bytes cada), podemos dizer que este array ocupa todos os
bytes entre 4550 e 4565 (inclusive).
Se procedermos a uma incrementao do tipo apontador++, a varivel apontador deixar de
apontar para a primeira posio do array, passando logo para a segunda. Porqu? Porque quando
incrementamos/decrementamos um apontador, no estamos a adicionar/diminuir meramente um
byte, mas sim a quantidade que ocupa um elemento do tipo de dados que o array tem.
Imaginando os endereos de variveis como nmeros decimais (o que no so, visto serem
hexadecimais), as duas linhas seguintes seriam equivalentes:
1 apontador++;
2 apontador + sizeof(double);

Como exemplo, tem abaixo uma progresso aritmtica, que faz uso da incrementao de apon-
tadores. Numa progresso aritmtica cada termo igual ao termo anterior somado com a razo,
sendo esta ltima uma constante.
n[y] = n[y 1] + r
Poderamos fazer este pequeno programa da seguinte forma (o cdigo abaixo est explicado):
1 #include <stdio.h>
2 #include <stdlib.h>
3
4 int main()
5 {
6 int pa[10], razao;
7 int *pointer;
8
9 /*
10 * Aqui pedmos o termo inicial, ou seja, o primeiro
11 * nmero da PA (Progresso Aritmtica).
12 *
7.4 Operaes com apontadores 52

13 * De seguida o apontador definido para apontar para


14 * o array pa.
15 */
16 printf("Insira o termo inicial: ");
17 scanf("%d", &pa[0]);
18 pointer = pa;
19
20 printf("Insira razo: ");
21 scanf("%d", &razao);
22
23 while(pointer != &pa[9]) {
24 /*
25 * Cada valor da PA definido somando o valor corrente do apontador com a razo
.
26 * De seguida, o apontador incrementado de forma a apontar para o prximo
27 * elemento do array. (Isto acontece enquanto o apontador for diferente do
28 * endereo do ltimo elemento da PA.)
29 */
30 *(pointer + 1) = *pointer + razao;
31 pointer++;
32 }
33
34 printf("PA");
35
36 for(pointer = pa ; pointer <= &pa[9] ; pointer++) {
37 /*
38 * Aqui todos os elementos do array so percoridos
39 * e imprime-se assim a Progresso Aritmtica criada.
40 */
41 printf(" %d", *pointer);
42 }
43
44 return 0;
45 }
Captulo
8
Strings
Na programao, os tipos de dados no se limitam aos j abordados no captulo 2: char, int,
float, double, etc. O tipo char permite armazenar at um carcter. Mas, no um carcter
muito pouco? E se for necessrio armazenar uma frase? A entram as strings.

Definio 32. Strings so sequncias de caracteres. Qualquer frase considerada uma string, pois
uma sequncia de caracteres. Todas as strings terminam com o carcter \0, um delimitador ASCII
para indicar o final da string.

8.1 Diferena entre string e char


As strings podem conter, tal como as variveis do tipo char, apenas um carcter. A diferena
entre ambas prende-se com a utilizao de aspas ou plicas. As aspas so utilizadas para delimitar
strings e as plicas para delimitar caracteres. Visualize o seguinte exemplo:
1 "Programar" String
2 "P" String
3 'P' Caracter

8.2 Declarao e inicializao de strings


Na linguagem de programao C, as strings so arrays de caracteres, ou seja, arrays do tipo char.
Podem ser declaradas de diversas formas.
Uma forma de declarar strings em C, criar um array do tipo char com um nmero de
caracteres pr-definidos. Por exemplo:
1 // o mesmo que: char nome[8] = {'P', 'p', 'l', 'w', 'a', 'r', 'e', '\0'};
2 char nome[8] = "Pplware";

No exemplo anterior, declarada a string nome que pode armazenar uma frase com 7 caracteres.
Porqu 7 se foram declaradas 8 posies no array? Isto acontece porque o ltimo carcter, o oitavo
carcter, o delimitador do final da frase \0.
Existem, no total, trs formas de declarar string em C: a primeira consiste na criao de um
array com o tamanho pr-determinado; a segunda consiste na criao de um array sem especificar
o seu comprimento, tendo que ser inicializada no momento da declarao de forma a que o espao
na memria seja alocado dependendo do tamanho da string colocada; atravs de um apontador.
1 char nome[8] = "Pplware";
2 char nome[] = "Pplware";
3 char* nome = "Pplware";

Se reparar, este tipo de dados sempre foi utilizado. Na funo printf, por exemplo, o primeiro
argumento foi sempre uma string, pois uma sequncia de caracteres delimitada por aspas.
8.3 Como imprimir strings 54

8.3 Como imprimir strings


As strings podem ser imprimidas recorrendo a diversas funes. Aqui so abordadas duas formas:
recorrendo funo printf e recorrendo funo puts.

8.3.1 Com a funo printf


Para imprimir uma string utilizando a funo printf, basta utilizar o especificador %s. Por
exemplo:
1 printf("Esta uma string: \%s", nomeDaString);

Pode-se concluir que o uso da funo printf para imprimir strings til quando necessrio
imprimir uma string que pode variar.

8.3.2 Com a funo puts


Temos tambm a funo puts, j abordada no captulo 5, cujo nome quer dizer put string, ou
seja, colocar string. Esta funo excelente para imprimir uma string que no esteja intercalada
noutra string. Ora veja o seguinte exemplo:
1 char* nome = "Jos";
2 puts(nome);

8.4 Como ler strings


Quando necessrio um dado do utilizador como o nome, por exemplo, saber como se leem strings
importante. A leitura de strings pode ser feita de diversas formas.

8.4.1 Com a funo scanf


A funo scanf j foi falada diversas vezes ao longo deste livro. Tal como o que acontece com
a funo printf, deve-se utilizar o especificador %s para ler strings. Ora veja como se l uma
string:
1 scanf("%s", variavelParaArmazenarAString);

Analisando o excerto anterior possvel verificar que, ao contrrio do que acontece com os
restantes tipos de dados, neste no colocamos o e comercial no incio do nome da varivel que
utilizada para armazenar a string. Isto acontece porque as variveis que contm strings so, ou
arrays ou apontadores, logo o seu nome j aponta para o endereo da memria.
Imagine agora que precisa do nome, apelido, morada e cdigo postal de um utilizador para
criar o seu carto de identificao. Poderia proceder da seguinte forma:
1 #include <stdio.h>
2 #include <stdlib.h>
3
4 int main() {
5 char nome[21],
6 apelido[21],
7 morada[51],
8 codigoPostal[11];
9
10 printf("Por favor insira os seus dados conforme pedido:\n\n");
11 printf("Primeiro nome: ");
12 scanf("%s", nome);
13
14 printf("ltimo nome: ");
15 scanf("%s", apelido);
16
17 printf("Morada: ");
18 scanf("%s", morada);
8.4 Como ler strings 55

19
20 // limpeza do buffer no Windows; usar "_fpurge(stdin)" em sistemas Unix
21 fflush(stdin);
22
23 printf("Cdigo Postal: ");
24 scanf("%s", codigoPostal);
25
26 printf("\nO seu Carto de Identificao:\n");
27 printf("Nome: %s, %s\n", apelido, nome);
28 printf("Morada: %s\n", morada);
29 printf("Cdigo Postal: %s\n", codigoPostal);
30 return 0;
31 }

Relembro que a utilizao de comandos para limpar o buffer no recomendvel e que devem
ser utilizadas outras funes que no a scanf de forma a obter dados do utilizador sem lixo.

8.4.2 Com a funo gets


A funo gets, cujo nome quer dizer get string, ou seja, obter string. A utilizao desta funo
simples. Ora veja como se utiliza esta funo:
1 gets(nomeDaVariavel);

Onde nomeDaVariavel corresponde ao apontador que aponta para o local onde a string vai
ser armazenada. Recordo que, no caso se ser utilizado um apontador ou um array, no necessrio
utilizar um e comercial no incio.
Imaginando agora que precisa criar um boletim de informao com diversos dados sobre o
utilizador. Poderia fazer da seguinte forma:
1 #include <stdio.h>
2 #include <stdlib.h>
3
4 int main() {
5 char nome[21],
6 apelido[21],
7 morada[51],
8 codigoPostal[11];
9
10 printf("Por favor insira os seus dados conforme pedido:\n\n");
11 printf("Primeiro nome: ");
12 gets(nome);
13
14 printf("ltimo nome: ");
15 gets(apelido);
16
17 printf("Morada: ");
18 gets(morada);
19
20 printf("Cdigo Postal: ");
21 gets(codigoPostal);
22
23 printf("\nO seu Carto de Identificao:\n");
24 printf("Nome: %s, %s\n", apelido, nome);
25 printf("Morada: %s\n", morada);
26 printf("Cdigo Postal: %s\n", codigoPostal);
27 return 0;
28 }

Analisando o cdigo possvel verificar que com esta funo no preciso limpar o buffer de
forma a no obter caracteres indevidos. Isto acontece porque a funo gets os ignora.

8.4.3 Com a funo fgets


Tanto a funo gets como a funo scanf tm alguns contratempos; a primeira tem alguns
problemas quando as strings incluem caracteres como espaos e a segunda obtm caracteres des-
8.4 Como ler strings 56

necessrios. Devido falta de uma soluo efetiva a estes problemas, a funo fgets poder ser
a melhor opo.
A funo fgets permite obter dados, no s do teclado, como de outros locais. Ora veja a sua
sintaxe:
1 fgets(char *str, int n, FILE *stream);

Onde:
str corresponde ao apontador para um array de caracteres onde os dados obtidos sero
armazenados;
n o nmero mximo de caracteres a serem lidos (incluindo o delimitador final). Geralmente
igual ao tamanho do arrar;
stream corresponde ao apontador para o ficheiro ou objeto donde sero lidos os dados.
Imaginando agora que necessrio converter o programa da criao do boletim de informao
do utilizador para utilizar a funo fgets. Ficaria da seguinte forma:
1 #include <stdio.h>
2 #include <stdlib.h>
3
4 int main() {
5 char nome[21],
6 apelido[21],
7 morada[51],
8 codigoPostal[11];
9
10 printf("Por favor insira os seus dados conforme pedido:\n\n");
11 printf("Primeiro nome: ");
12 fgets(nome, 21, stdin);
13
14 printf("ltimo nome: ");
15 fgets(apelido, 21, stdin);
16
17 printf("Morada: ");
18 fgets(morada, 51, stdin);
19
20 printf("Cdigo Postal: ");
21 fgets(codigoPostal, 11, stdin);
22
23 printf("\nO seu Carto de Identificao:\n");
24 printf("Nome: %s, %s\n", apelido, nome);
25 printf("Morada: %s\n", morada);
26 printf("Cdigo Postal: %s\n", codigoPostal);
27 return 0;
28 }

Se compilar e correr o cdigo acima, ir receber algo semelhante ao seguinte:


O seu Carto de Identificao:
Nome: Apelido
, Nome

Morada: Morada

Cdigo Postal: CP

Estas mudanas de linha acontecem porque as strings obtidas atravs da funo fgets ficaram
com o carcter \n no final. Para remover este carcter pode-se recorrer funo strtok. Esta
funo utiliza-se da seguinte forma:
1 strtok(char *str, const char *delim);

Onde:
str o apontador para um array de caracteres onde a string est armazenada;
delim corresponde ao delimitador a remover.
Assim, para que o carcter \n seja removido de todas as strings utilizadas no programa anterior,
bastaria adicionar as seguintes linhas:
8.4 Como ler strings 57

1 strtok(nome, "\n");
2 strtok(apelido, "\n");
3 strtok(morada, "\n");
4 strtok(codigoPostal, "\n");
Captulo
9
Anexos
9.1 Anexo I - Tabela ASCII
Char Dec Oct Hex | Char Dec Oct Hex | Char Dec Oct Hex |
-----------------------------------------------------------------
(nul) 0 0000 0x00 | (sp) 32 0040 0x20 | @ 64 0100 0x40 |
(soh) 1 0001 0x01 | ! 33 0041 0x21 | A 65 0101 0x41 |
(stx) 2 0002 0x02 | " 34 0042 0x22 | B 66 0102 0x42 |
(etx) 3 0003 0x03 | # 35 0043 0x23 | C 67 0103 0x43 |
(eot) 4 0004 0x04 | $ 36 0044 0x24 | D 68 0104 0x44 |
(enq) 5 0005 0x05 | % 37 0045 0x25 | E 69 0105 0x45 |
(ack) 6 0006 0x06 | & 38 0046 0x26 | F 70 0106 0x46 |
(bel) 7 0007 0x07 | 39 0047 0x27 | G 71 0107 0x47 |
(bs) 8 0010 0x08 | ( 40 0050 0x28 | H 72 0110 0x48 |
(ht) 9 0011 0x09 | ) 41 0051 0x29 | I 73 0111 0x49 |
(nl) 10 0012 0x0a | * 42 0052 0x2a | J 74 0112 0x4a |
(vt) 11 0013 0x0b | + 43 0053 0x2b | K 75 0113 0x4b |
(np) 12 0014 0x0c | , 44 0054 0x2c | L 76 0114 0x4c |
(cr) 13 0015 0x0d | - 45 0055 0x2d | M 77 0115 0x4d |
(so) 14 0016 0x0e | . 46 0056 0x2e | N 78 0116 0x4e |
(si) 15 0017 0x0f | / 47 0057 0x2f | O 79 0117 0x4f |
(dle) 16 0020 0x10 | 0 48 0060 0x30 | P 80 0120 0x50 |
(dc1) 17 0021 0x11 | 1 49 0061 0x31 | Q 81 0121 0x51 |
(dc2) 18 0022 0x12 | 2 50 0062 0x32 | R 82 0122 0x52 |
(dc3) 19 0023 0x13 | 3 51 0063 0x33 | S 83 0123 0x53 |
(dc4) 20 0024 0x14 | 4 52 0064 0x34 | T 84 0124 0x54 |
(nak) 21 0025 0x15 | 5 53 0065 0x35 | U 85 0125 0x55 |
(syn) 22 0026 0x16 | 6 54 0066 0x36 | V 86 0126 0x56 |
(etb) 23 0027 0x17 | 7 55 0067 0x37 | W 87 0127 0x57 |
(can) 24 0030 0x18 | 8 56 0070 0x38 | X 88 0130 0x58 |
(em) 25 0031 0x19 | 9 57 0071 0x39 | Y 89 0131 0x59 |
(sub) 26 0032 0x1a | : 58 0072 0x3a | Z 90 0132 0x5a |
(esc) 27 0033 0x1b | ; 59 0073 0x3b | [ 91 0133 0x5b |
(fs) 28 0034 0x1c | < 60 0074 0x3c | \ 92 0134 0x5c |
(gs) 29 0035 0x1d | = 61 0075 0x3d | ] 93 0135 0x5d |
(rs) 30 0036 0x1e | > 62 0076 0x3e | ^ 94 0136 0x5e |
(us) 31 0037 0x1f | ? 63 0077 0x3f | _ 95 0137 0x5f |
-----------------------------------------------------------------
96 0140 0x60 | k 107 0153 0x6b | v 118 0166 0x76 |
a 97 0141 0x61 | l 108 0154 0x6c | w 119 0167 0x77 |
b 98 0142 0x62 | m 109 0155 0x6d | x 120 0170 0x78 |
c 99 0143 0x63 | n 110 0156 0x6e | y 121 0171 0x79 |
d 100 0144 0x64 | o 111 0157 0x6f | z 122 0172 0x7a |
e 101 0145 0x65 | p 112 0160 0x70 | { 123 0173 0x7b |
9.2 Anexo II - Converso Hexadecimal-Decimal 59

f 102 0146 0x66 | q 113 0161 0x71 | | 124 0174 0x7c |


g 103 0147 0x67 | r 114 0162 0x72 | } 125 0175 0x7d |
h 104 0150 0x68 | s 115 0163 0x73 | ~ 126 0176 0x7e |
i 105 0151 0x69 | t 116 0164 0x74 | (del) 127 0177 0x7f |
j 106 0152 0x6a | u 117 0165 0x75 |-------------------- |
--------------------------------------------------------------- |

9.2 Anexo II - Converso Hexadecimal-Decimal

Hexadecimal Decimal Hexadecimal Decimal


0 0 8 8
1 1 9 9
2 2 A 10
3 3 B 11
4 4 C 12
5 5 D 13
6 6 E 14
7 7 F 15

Tabela 9.1: Converso hexadecimal para decimal

Anda mungkin juga menyukai