Prévia do material em texto
ALGORITMOS E
PROGRAMAÇÃO APLICADA
PROF. FÁBIO ATAIDE DE LIMA
PROFA MA. CLAUDIA HEIDEMANN DE SANTANA
Presidente da Mantenedora
Ricardo Benedito Oliveira
Reitor:
Dr. Roberto Cezar de Oliveira
Pró-Reitoria Acadêmica
Gisele Colombari Gomes
Diretora de Ensino
Prof.a Dra. Gisele Caroline
Novakowski
PRODUÇÃO DE MATERIAIS
Diagramação:
Alan Michel Bariani
Edson Dias Vieira
Thiago Bruno Peraro
Revisão Textual:
Camila Cristiane Moreschi
Danielly de Oliveira Nascimento
Fernando Sachetti Bomfim
Luana Luciano de Oliveira
Patrícia Garcia Costa
Produção Audiovisual:
Adriano Vieira Marques
Márcio Alexandre Júnior Lara
Osmar da Conceição Calisto
Gestão de Produção:
Cristiane Alves© Direitos reservados à UNINGÁ - Reprodução Proibida. - Rodovia PR 317 (Av. Morangueira), n° 6114
33WWW.UNINGA.BR
U N I D A D E
INTRODUTÓRIA
U N I D A D E
SUMÁRIO DA UNIDADE
INTRODUÇÃO ................................................................................................................................................................4
1 ORGANIZAÇÃO BÁSICA DE UM SISTEMA COMPUTACIONAL ..............................................................................5
1.1 EVOLUÇÃO DOS SISTEMAS COMPUTACIONAIS .................................................................................................5
1.2 COMPONENTES DE UM SISTEMA COMPUTACIONAL ....................................................................................... 7
1.2.1 HARDWARE .......................................................................................................................................................... 7
1.2.2 SOFTWARE ...........................................................................................................................................................9
1.3 SISTEMAS DE NUMERAÇÃO UTILIZADOS NOS SISTEMAS COMPUTACIONAIS ............................................ 11
1.3.1 SISTEMA DECIMAL ............................................................................................................................................. 12
1.3.2 SISTEMA BINÁRIO ............................................................................................................................................. 13
1.3.3 SISTEMAS OCTAL E HEXADECIMAL ................................................................................................................ 13
CONSIDERAÇÕES FINAIS ........................................................................................................................................... 15
ORGANIZAÇÃO BÁSICA DE UM
SISTEMA COMPUTACIONAL
PROFA MA. CLAUDIA HEIDEMANN DE SANTANA
ENSINO A DISTÂNCIA
DISCIPLINA:
ALGORITMOS E PROGRAMAÇÃO APLICADA
4WWW.UNINGA.BR
AL
GO
RI
TM
OS
E
P
RO
GR
AM
AÇ
ÃO
A
PL
IC
AD
A
| U
NI
DA
DE
IN
TR
OD
UT
ÓR
IA
EDUCAÇÃO A DISTÂNCIA
INTRODUÇÃO
Você está pronto(a) para iniciar seus estudos introdutórios sobre Algoritmos e
Programação Aplicada? Especificamente nesta unidade introdutória, vamos trabalhar sobre a
organização básica de um sistema computacional. Pronto(a) para o início da aprendizagem?
Caro(a) aluno(a), esta unidade procura explicar algumas definições, conceitos e
curiosidades sobre os Sistemas Computacionais e seus principais componentes. Você também
aprenderá a categorizar as principais partes de um computador e as diferenças entre elas.
Ao final desta unidade, você deve apresentar os seguintes aprendizados:
• Reconhecer processamento de dados e sistemas de computação;
• Identificar a evolução dos computadores;
• Descrever a diferença entre hardware e software;
• Conhecer sobre os Sistemas de Numeração utilizados nos sistemas digitais.
Em um mundo cada vez mais digital, é necessário conhecer os termos básicos relacionados
à informática. Seja qual for a sua área, a tecnologia e os sistemas digitais estão cada vez mais
presentes no nosso dia a dia, no celular, na TV, no carro, no ar-condicionado e até mesmo no seu
grill.
5WWW.UNINGA.BR
AL
GO
RI
TM
OS
E
P
RO
GR
AM
AÇ
ÃO
A
PL
IC
AD
A
| U
NI
DA
DE
IN
TR
OD
UT
ÓR
IA
EDUCAÇÃO A DISTÂNCIA
1 ORGANIZAÇÃO BÁSICA DE UM SISTEMA COMPUTACIONAL
“O software tornou-se o elemento-chave da evolução e produtos baseados em
computador” (PRESSMAN, 1995).
Um Sistema Computacional é um tipo especializado de sistema, que tem como finalidade
processar e armazenar informações. O que torna os sistemas computacionais tão essenciais hoje?
O que você está fazendo agora? Utilizando o computador, não é verdade? Mas o que está por trás
deste monitor? O que torna possível você acessar este curso?
No computador, existem componentes envolvidos no processo, vale dizer, o sistema
computacional. Esse sistema possui dois componentes principais: o Software e o Hardware.
Um sistema computacional refere-se ao conjunto de dispositivos eletrônicos (hardware)
que processam informações através de um programa (software). Ele é uma combinação de
hardware, software e inteligência humana.
Vou explicar melhor os componentes de um Sistema Computacional:
Hardware: é o equipamento físico, computadores e periféricos. Juntos, processam dados
e informações e permitem sua visualização.
Software: consiste nas instruções, conjunto de programas que permitem que o hardware
processe os dados. São divididos em duas principais categorias: Sistema Operacional - controla
e coordena o uso do hardware entre os vários programas de aplicação de vários usuários; e
Programas de Aplicação - definem como os recursos do sistema serão utilizados pelos usuários
(gerenciadores de bancos de dados, antivírus, editores de texto, planilhas eletrônicas etc.).
Veremos mais adiante, com mais detalhes, sobre software e seus diferentes tipos.
Para completar este sistema, temos ainda os usuários, que são os indivíduos que trabalham
com o sistema ou utilizam a sua saída. São usuários e operadores de hardware e software.
Assim, já temos os elementos para um sistema computacional, mas, no caso da pergunta
inicial, que envolvia como você está tendo acesso a este curso, temos ainda:
- Tecnologia de redes: sistema de ligação, que permite o compartilhamento de recursos
entre computadores.
- Tecnologia de dados: softwares e hardwares que comandam a organização dos dados
em meios físicos de armazenagem.
1.1 Evolução dos Sistemas Computacionais
Os sistemas computacionais evoluíram com o passar do tempo (assim como a tecnologia),
passando da operacionalização das tarefas rotineiras à integração entre os diferentes sistemas,
com recursos e usos diferenciados.
Dos primeiros computadores à Internet: nesse vídeo, você verá
sobre a evolução dos computadores, sua utilização, primeiros
games, interfaces, surgimento da Internet no mundo e primeiras
experiências no Brasil.
Acesse-o em https://www.youtube.com/watch?v=B3flG27KgVQ.
https://www.youtube.com/watch?v=B3flG27KgVQ
6WWW.UNINGA.BR
AL
GO
RI
TM
OS
E
P
RO
GR
AM
AÇ
ÃO
A
PL
IC
AD
A
| U
NI
DA
DE
IN
TR
OD
UT
ÓR
IA
EDUCAÇÃO A DISTÂNCIA
Cronologicamente, a evolução dos sistemas computacionais se deu em cinco gerações,
que são: computadores à válvula, computadores a transistor, circuitos integrados, circuitos VLSI
e tecnologia ULSI (Ultra Large Scale Integration). O primeiro computador, segundo pesquisas, foi
desenvolvido pelo engenheiro mecânico Charles Babbage, que inventou o primeiro equipamento
considerado um computador mecânico, ainda no século XIX. Já na década de 1940, os
computadores de uso geral, que usavam algoritmos simples para perfurar cartões, substituíram
os computadores mecânicos, sendo o ENIAC (Electronic Numerical Integrator and Computer) o
primeiro computador digital eletrônico programável e principal representante dessa primeira
geração.
Da segunda geração, marcada pelos transistores (e com eles a possibilidade de
comercialização do computador), podemos destacar o UNIVAC ERA 1101, que foi o primeiro
programa de computador armazenado nos EUA. Os transistores eram também mais rápidos que
as válvulase, portanto, eles também contribuíram para aumentar a velocidade computacional.
Figura 1 - UNIVAC/ERA 1101: primeiro computador da história que rodava um programa da memória.
Fonte: Dibble (2021).
Portanto, os computadores da era dos transistores (ou da segunda geração) eram não só
mais pequenos, mas também mais rápidos que os das válvulas eletrônicas.
Com a terceira geração (no início da década de 1960, surgimento dos circuitos integrados
(CHIP)), viu-se a diminuição do tamanho, maior capacidade de processamento e início da
utilização dos computadores pessoais. Surgiram os softwares integrados, como processadores de
texto, planilhas eletrônicas e outros.
Figura 2 - Intel 8008, 1972 - primeiro microprocessador de 8 bits.
Fonte: Wikiwand (2021).
7WWW.UNINGA.BR
AL
GO
RI
TM
OS
E
P
RO
GR
AM
AÇ
ÃO
A
PL
IC
AD
A
| U
NI
DA
DE
IN
TR
OD
UT
ÓR
IA
EDUCAÇÃO A DISTÂNCIA
Já a quarta geração, iniciada nos anos 1970, ficou conhecida pela grande massa de
microcomputadores pessoais, com circuitos integrados VLSI – Very Large Scale Integration – e
integração em escala muito alta. Em 1977, houve uma explosão no mercado de microcomputadores,
sendo fabricados em escala comercial, e, a partir daí, a evolução foi sendo cada vez maior, até
chegar aos micros atuais, os microprocessadores de ULSI (Ultra Large Scale of Integration),
utilizados a partir de 1980. Nessa geração, começa a utilização das linguagens de altíssimo nível,
orientadas para um problema.
A quinta geração é baseada em hardware de processamento paralelo (que é uma forma
de computação em que vários cálculos são realizados ao mesmo tempo) e na IA (Inteligência
Artificial) do software. A inteligência artificial é um “novo” ramo da ciência da computação,
que interpreta meios e métodos de fazer computadores pensar como seres humanos. Todas
as linguagens de alto nível, robótica, desenvolvimento de sistemas especialistas e a era online,
comunicação através da Internet, fazem parte desta geração.
Figura 3 - Exemplo de um computador de quinta geração. Fonte: Gerações de Computadores (2021).
Assim, vimos como os computadores vêm evoluindo e acompanhando os avanços nos
campos da matemática, engenharia e eletrônica. Os computadores passaram por muitas mudanças
e foram continuamente aprimorados ao longo do tempo. Continuam seguindo a tendência de
miniaturização de seus componentes, tornando-se cada vez mais práticos para as tarefas diárias.
1.2 Componentes de um Sistema Computacional
Um sistema de computação é composto por três (3) componentes principais: hardware,
software e peopleware.
O peopleware são todos os usuários, as pessoas que, de alguma forma, trabalham e/ou
interagem com o computador, como digitadores, programadores, analistas ou simplesmente
usuários finais. Veremos agora, mais detalhadamente, os componentes de hardware e software.
1.2.1 Hardware
A parte física de um sistema computacional é o que chamamos de hardware. São todos
os componentes de entrada e saída, componentes eletrônicos, circuitos integrados e placas.
O “hardware” não se refere apenas aos computadores pessoais, mas também aos equipamentos
embarcados em produtos que precisam de processamento computacional, como os dispositivos
encontrados em equipamentos como micro-ondas, automóveis, máquinas, aparelho celular e outros.
8WWW.UNINGA.BR
AL
GO
RI
TM
OS
E
P
RO
GR
AM
AÇ
ÃO
A
PL
IC
AD
A
| U
NI
DA
DE
IN
TR
OD
UT
ÓR
IA
EDUCAÇÃO A DISTÂNCIA
Para esta disciplina, é interessante entender que os componentes de hardware são divididos
em sistema central (composto pela CPU - Unidade Central de Processamento (ou processador)
-, Memória Principal e as suas interconexões) e os periféricos (que podem ser de Entrada, Saída
e/ou Armazenamento e as suas interconexões).
De acordo com a arquitetura de von Neumann, a CPU (do inglês Central Processing
Unit), que é Unidade Central de Processamento, armazena informações, controla as operações
aritméticas e lógicas e efetua o processamento de entradas e saídas.
Figura 4 - Tráfego das informações na CPU. Fonte: Adaptado de Manzano e Manzano (2009).
A memória principal (ou memória primária) tem por finalidade o armazenamento de
instruções e dados de programas que serão e/ou estão sendo executados pela CPU. É considerada
como uma memória de trabalho, sendo organizada em células com tamanho fixo e igual, cada
uma identificada por um número denominado endereço.
A memória principal pode ser acessada por meio de duas operações: leitura (ler da
memória significa requisitar à memória principal o conteúdo de uma determinada célula) e
escrita (escrever na memória significa escrever uma informação em uma célula da MP).
É classificada em dois grupos:
- RAM (do inglês Random Access Memory – Memória de Acesso Aleatório) dinâmica
ou estática - esta memória volátil retém as instruções e dados de programas que estão sendo
executados, tornando o tempo de leitura e escrita bastante rápido.
- ROM (do inglês Read Only Memory – Memória Somente de Leitura) - as informações são
gravadas no momento da fabricação e não mais são alteradas. Contém basicamente informações
necessárias para o funcionamento do computador, como rotinas que verificam se os meios físicos
(hardware) estão aptos para o funcionamento. Outras versões de ROMs são PROM, EPROM,
EEPROM ou EAPROM e memória flash.
A memória cache é uma memória (RAM estática) volátil de alta velocidade, localizada
entre a CPU e a memória principal, usada com a finalidade de acelerar o processamento,
funcionando como um buffer da memória.
As memórias secundárias são um tipo de memória não volátil de grande capacidade de
armazenamento, usadas para guardar informações (instruções e dados de programas) que não
são perdidas quando o computador for desligado. Como exemplos, podemos citar: disco rígido
(HD) e mídias removíveis, como o CD-ROM, o DVD e o pendrive.
9WWW.UNINGA.BR
AL
GO
RI
TM
OS
E
P
RO
GR
AM
AÇ
ÃO
A
PL
IC
AD
A
| U
NI
DA
DE
IN
TR
OD
UT
ÓR
IA
EDUCAÇÃO A DISTÂNCIA
- Dispositivos de Entrada e Saída de Dados:
No sistema computacional, todos os dispositivos que realizam as funções de receber e/
ou enviar as informações do usuário são considerados dispositivos de entrada e saída de dados.
Esses dispositivos externos são conectados em um computador e podem ser classificados
em três categorias:
1. Os que transmitem/recebem informações inteligíveis para o ser humano - são
adequados para estabelecimento de comunicação com o usuário. É o caso das
impressoras, monitores de vídeo, plotters, multimídia etc.
2. Os que transmitem/recebem informações inteligíveis apenas para a máquina - são
adequados para comunicação máquina a máquina ou internamente a uma máquina.
É o caso dos teclados, mouses, scanners, discos magnéticos, fitas magnéticas, discos
óticos, sensores e atuadores em aplicação robótica.
3. Os que transmitem/recebem de/para outros dispositivos remotamente instalados,
tais como os modems e regeneradores digitais.
1.2.2 Software
Já sabemos que vamos agora entender brevemente como os softwares são feitos.
As etapas para a execução de uma tarefa, elaboradas e executadas passo a passo, constituem
o que se chama programa, ou também chamadas de software. Cada um dos passos mencionados
é uma diferente instrução, ou ordem de comando, dada ao hardware com o objetivo de realização
de uma determinada tarefa e/ou ação (por exemplo: uma operação aritmética, uma transferência
de informação). O programa (software) é o conjunto dessas instruções.
Córdova et al. (2018) nos dizem que o computador é uma máquina que resolve problemas
por meio da execução de instruções que são passadas a ele. Essas instruções são chamadas de
programas de computador. O programa é um conjunto de instruções lógicas e finitas (também
chamado de algoritmo), que executam uma tarefa específica.
Um programa de computador é a formalização de um algoritmo, em linguagem inteligível
pelo computador.
Figura 5 - Fases do processamentode um software. Fonte: A autora.
Assim, o computador precisa entender cada instrução de modo a executar corretamente
a operação que se pretende. O usuário entende Português, sua linguagem de comunicação com
outras pessoas. Os computadores têm uma linguagem própria, a linguagem binária. Nela, os
caracteres inteligíveis são apenas zero (0) e um (1), presença ou ausência de corrente elétrica. Todo
dado coletado pelos computadores, as instruções por eles executadas, bem como os resultados de
um processamento são sempre constituídos de conjuntos ordenados de zeros e uns.
10WWW.UNINGA.BR
AL
GO
RI
TM
OS
E
P
RO
GR
AM
AÇ
ÃO
A
PL
IC
AD
A
| U
NI
DA
DE
IN
TR
OD
UT
ÓR
IA
EDUCAÇÃO A DISTÂNCIA
Como o computador não entende nossa linguagem, ela deve ser compilada. Esse processo
de compilação, em termos gerais, consiste em transformar uma linguagem em outra, neste caso,
as nossas instruções para a linguagem binária (0 e 1), que é a linguagem que o computador
compreende. Isso é feito por um tipo de software/sistema chamado Linguagem de Programação.
Assim, podemos entender que o conceito de software refere-se a todos os elementos de
programação de um sistema de computação, isto é, a todos os programas, sejam eles de softwares
de aplicação sejam softwares básicos.
a) Software básico: são os programas que definem o padrão do equipamento, sendo
necessários para o seu funcionamento. Os tipos de software básico são: sistema operacional,
linguagens de programação, tradutores e utilitários.
b) Software aplicativos: são programas para as mais variadas finalidades e situações, são
utilizados pelos usuários para realizar trabalhos rotineiros. Exemplos: editores de texto,
calculadoras, aplicativos para ouvir músicas, aplicativos para contabilidade e de recursos
humanos.
Vamos dar destaque a dois tipos de softwares, importantes para o nosso domínio de
conhecimento na disciplina de Algoritmos e Programação Aplicada. São eles:
Sistema Operacional: segundo Manzano e Manzano (2009), o sistema operacional (SO)
é responsável pelo gerenciamento, funcionamento e execução de todos os programas e todos os
periféricos do sistema computacional. Sem o SO, o computador não tem “vida”, é um software
que se encontra na categoria dos programas de sistema. Ele é o mais importante entre todos,
pois representa o papel de tradutor e intérprete entre a máquina e o homem (e vice-versa) e
gerencia todos os periféricos e softwares, pois trabalha juntamente com a CPU. Entre os sistemas
operacionais, citem-se: Microsoft Windows; OS/2; Unix; Mac/OS.
Figura 6 - Posicionamento de um Sistema Operacional num Sistema Computacional. Fonte: A autora.
Linguagens de Programação: é um conjunto de símbolos (vocabulário) e regras
(gramática) que especificam como transmitir informações entre usuários e computador. As
linguagens de programação estão divididas em: linguagem de máquina, linguagem de baixo nível
e linguagem de alto nível.
11WWW.UNINGA.BR
AL
GO
RI
TM
OS
E
P
RO
GR
AM
AÇ
ÃO
A
PL
IC
AD
A
| U
NI
DA
DE
IN
TR
OD
UT
ÓR
IA
EDUCAÇÃO A DISTÂNCIA
A linguagem de máquina é baseada em código binário, em 0s e 1s. É utilizada diretamente
pelo computador. A linguagem de baixo nível é uma simplificação da linguagem de máquina.
Faz uso de códigos mnemônicos para expressar as instruções. Exemplo: Assembly. A linguagem
de alto nível utiliza a combinação de um conjunto de símbolos de acordo com certas regras de
sintaxe para expressar uma sequência de operações de máquina. É uma linguagem que não exige
conhecimento do código binário. Exemplo: C, JAVA, Python.
1.3 Sistemas de Numeração Utilizados nos Sistemas Computacionais
A história da matemática conta sobre a necessidade de contar do ser humano desde
que ele deixou de ser nômade. A necessidade de contagem foi impulsionada por atividades de
agricultura e pastoreio, pela representação da quantidade de cabeças em um rebanho, fases da
Lua e estações do ano para o plantio etc. Dessa forma, a representação numérica foi ganhando
forma por meio dos algarismos.
O sistema de numeração é um conjunto de regras para a representação dos números.
O sistema numérico decimal é o mais utilizado pela humanidade. Acredita-se que o número
de dedos que o homem tem nas mãos foi um fato decisivo, nos primórdios, para a criação e
disseminação desse sistema.
Um sistema de numeração é definido principalmente pela BASE, que indica a quantidade
de símbolos e o valor de cada símbolo. Exemplos: Sistema Decimal (base 10): 0, 1, 2, 3, 4, 5, 6,
7, 8, 9; Sistema Binário (base 2): 0, 1; Sistema Octal (base 8): 0, 1, 2, 3, 4, 5, 6, 7, 8; e Sistema
Hexadecimal (base 16): 0, 1, 2, 3, 4, 5, 6, 7, 8, 9, A, B, C, D, E, F.
Com o advento da eletrônica digital e, principalmente, do computador, surgem outras
necessidades, como a de representar os números utilizando a eletricidade. Como você já sabe,
um computador funciona movido à energia elétrica. A ausência ou presença de energia (0v ou
+5v) é representada por 0’s e 1’s, ou seja, o Sistema Binário. O matemático indiano Pingala
apresentou a primeira descrição conhecida de um sistema numérico binário no século III a.C.,
representando os números de 1 a 8 com a sequência (usando símbolos modernos) 000, 001, 010,
011, 100, 101,110 e 111.
Nesse contexto computacional, o computador opera valores utilizando a lógica binária
que trabalha com o sistema binário que contém somente dois algarismos: 0 e 1. Para simplificar
a codificação de instruções em nível de máquina, são utilizadas conversões para outros tipos de
sistemas de numeração a fim de tornar a definição das instruções mais inteligível ao ser humano.
Veja uma linha do tempo da história do software e das linguagens de
programação. Acesse: https://www.computerhistory.org/timeline/
software-languages/.
https://www.computerhistory.org/timeline/software-languages/
https://www.computerhistory.org/timeline/software-languages/
12WWW.UNINGA.BR
AL
GO
RI
TM
OS
E
P
RO
GR
AM
AÇ
ÃO
A
PL
IC
AD
A
| U
NI
DA
DE
IN
TR
OD
UT
ÓR
IA
EDUCAÇÃO A DISTÂNCIA
Figura 7 - Representação dos dados. Fonte: A autora.
Por fim, como a representação de números binários de alto valor torna os dígitos quase
ilegíveis para nós, é comum utilizar o sistema hexadecimal para abreviá-los, pois cada dígito
hexadecimal guarda 4 dígitos binários.
A seguir, vamos detalhar alguns sistemas numéricos presentes na nossa vivência com os
sistemas computacionais.
1.3.1 Sistema decimal
É o nosso sistema mais familiar. Sua base numérica é de dez, ou seja, a quantidade de
símbolos é 10. De zero a nove, utilizam-se dez algarismos diferentes para representar todos os
números - 0, 1, 2, 3, 4, 5, 6, 7, 8, 9. É um sistema posicional, ou seja, a posição do algarismo no
número modifica o seu valor. Ou seja, cada número em uma sequência de algarismos tem valor
diferente, dependendo de sua posição.
Veja um exemplo: no número decimal 777, cada cinco tem um valor diferente. O primeiro
vale sete centenas (700); o segundo, sete dezenas (70); e o terceiro, sete unidades (7). O valor
final é fornecido por 777 = 700 + 70 + 7 = 7 * 102 + 7 * 101 + 7 * 100. Os pesos das posições são
potências de dez, no caso do sistema decimal.
Veremos em seguida os sistemas binário, octal e hexadecimal, que também são sistemas
posicionais, mas, no sistema binário são potências de dois, no octal são potências de oito e no
sistema hexadecimal são potências de 16.
Você sabe o que é Código ASCII?
O Código ASCII - American Standard Code for Information Interchange (Código
Padrão Americano para o Intercâmbio de Informação) - é baseado no alfabeto
romano, e sua função é padronizar a forma como os computadores representam
letras, números, acentos, sinais diversos e alguns códigos de controle. Foi proposto
por Robert W. Bemer, visando a padronizar os códigos. Assim, foi possível que
computadores de diferentes fabricantes conseguissem entender os códigos. Ele
é um padrão de codificação de letras e símbolosbastante antigo e usado até hoje.
13WWW.UNINGA.BR
AL
GO
RI
TM
OS
E
P
RO
GR
AM
AÇ
ÃO
A
PL
IC
AD
A
| U
NI
DA
DE
IN
TR
OD
UT
ÓR
IA
EDUCAÇÃO A DISTÂNCIA
1.3.2 Sistema binário
Representação binária ou de base 2, este sistema usa apenas dois símbolos básicos: o 0 e o
1. É um sistema de numeração posicional em que todas as quantidades se representam com base
nos algarismos zero e um. Da mesma forma que no sistema decimal discutido antes, cada dígito
pode ser representado pela sua potência ou peso.
Palavras binárias com certas quantidades de dígitos podem adquirir nomes especiais, por
exemplo, um dígito binário é chamado de BIT, proveniente das palavras inglesas BInary digiT.
O bit, do inglês BInary digiT, é um símbolo ou elemento que pode representar dois
estados possíveis, como uma luz que está ligada (1) ou desligada (0). Em computadores, o valor
0 é usualmente associado a alguma voltagem baixa, e o valor 1, a uma voltagem mais alta. No
momento atual, um grande número de tecnologias tem convergido para o uso da representação
binária, usando diferentes meios para a representação física do bit.
1.3.3 Sistemas octal e hexadecimal
Até o momento, foi discutido que os computadores digitais usam o sistema de numeração
binária (base 2) por sua facilidade em associar seus dois possíveis valores, 0 e 1, a fenômenos
físicos que ocorrem internamente no computador. Outros sistemas numéricos utilizados na
computação são os sistemas de numeração octal e hexadecimal, que compactam significativamente
a representação de números binários, ou seja, a principal utilização para números hexadecimal e
octal em computação é abreviar longas representações binárias.
A Tabela 1 representa números binários longos e como eles podem ser expressos
brevemente em sistemas de numeração com bases mais altas.
Tabela 1 - Equivalentes decimais, binários, octais e hexadecimais.
Número Decimal Representação Binária Representação Octal Representação Hexadecimal
0 0 0 0
1 1 1 1
2 10 2 2
3 11 3 3
4 100 4 4
5 101 5 5
6 110 6 6
7 111 7 7
8 1000 10 8
9 1001 11 9
10 1010 12 A
11 1011 13 B
12 1100 14 C
13 1101 15 D
14 1110 16 E
15 1111 17 F
16 100000 20 10
Fonte: A autora.
14WWW.UNINGA.BR
AL
GO
RI
TM
OS
E
P
RO
GR
AM
AÇ
ÃO
A
PL
IC
AD
A
| U
NI
DA
DE
IN
TR
OD
UT
ÓR
IA
EDUCAÇÃO A DISTÂNCIA
Um relacionamento importante que os sistemas de numeração octal (como o hexadecimal)
têm com o binário é que as bases octal e hexadecimal são potências da base do sistema de
numeração binário.
Considere o número binário de 12 algarismos 100011010001. Para ver como o número
binário é facilmente convertido em octal, divida o número binário de 12 dígitos em grupos de três
bits consecutivos cada e escreva esses grupos sobre os dígitos correspondentes do número octal
como a seguir, de acordo com o seu correspondente na Tabela 1.
Binário 100 011 010 001
Otal 4 3 2 1
O mesmo tipo de relacionamento pode ser observado ao se converter de binário para
hexadecimal. Divida o número binário de 12 algarismos em grupos de quatro bits consecutivos
cada e escreva esses grupos sobre os dígitos correspondentes do número hexadecimal como a
seguir:
Binário 1000 1101 0001
Hexa 8 D 1
O sistema hexadecimal está vinculado aos sistemas computacionais, pois os computadores
costumam utilizar o byte como unidade básica da memória, 1 byte = 8 bits e, então, um byte pode
ser representado por 8 algarismos do sistema binário ou por 2 algarismos do sistema hexadecimal.
Por exemplo: 1110 0110 [binário] = E6 [hexadecimal].
Para mais informações sobre os sistemas de numeração e suas
conversões, ler o capítulo 4 do livro:
CARVALHO, A. C. P. L. F.; LORENA, A. C. Introdução à Computação -
Hardware, Software e Dados. LTC, 2016.
O material está disponível em:
https://integrada.minhabiblioteca.com.br/#/books/9788521633167/.
https://integrada.minhabiblioteca.com.br/#/books/9788521633167/
15WWW.UNINGA.BR
AL
GO
RI
TM
OS
E
P
RO
GR
AM
AÇ
ÃO
A
PL
IC
AD
A
| U
NI
DA
DE
IN
TR
OD
UT
ÓR
IA
EDUCAÇÃO A DISTÂNCIA
CONSIDERAÇÕES FINAIS
Assim, finalizamos nossa unidade introdutória sobre sistemas computacionais, este tema
tão importante quanto a como são organizados estes sistemas, para que você consiga aprofundar
seus estudos sobre algoritmos e a programação propriamente dita, produzindo seus códigos e
comandos (software) para o hardware executar as operações que você necessita automatizar.
Esta é uma das intenções desta unidade introdutória: chamar a atenção para assuntos que
vão além do “para que isto me servirá?”, que domina o senso-comum. Esta unidade de estudo
trouxe a essência e os fundamentos dos sistemas computacionais.
1616WWW.UNINGA.BR
U N I D A D E
01
SUMÁRIO DA UNIDADE
INTRODUÇÃO ............................................................................................................................................................... 18
1 ALGORITMOS ............................................................................................................................................................ 19
1.1 DESCRIÇÃO NARRATIVA .......................................................................................................................................20
1.2 FLUXOGRAMA ........................................................................................................................................................ 21
1.3 PSEUDOCÓDIGO ....................................................................................................................................................22
2 PROGRAMAS E LINGUAGENS DE PROGRAMAÇÃO..............................................................................................23
2.1 COMPILADORES ....................................................................................................................................................24
2.2 INTERPRETADORES .............................................................................................................................................25
2.3 LINGUAGENS DE PROGRAMAÇÃO ......................................................................................................................25
2.4 LINGUAGEM C .......................................................................................................................................................26
3 TIPOS DE DADOS ..................................................................................................................................................... 31
3.1 TIPOS DE DADOS BÁSICOS .................................................................................................................................. 31
ALGORITMOS E ELEMENTOS
BÁSICOS DE PROGRAMAÇÃO
PROF. FÁBIO ATAIDE DE LIMA
ENSINO A DISTÂNCIA
DISCIPLINA:
ALGORITMOS E PROGRAMAÇÃO APLICADA
17WWW.UNINGA.BR
EDUCAÇÃO A DISTÂNCIA
3.2 ENUMERADORES ..................................................................................................................................................33
3.3 PONTEIROS ...........................................................................................................................................................33
4 CONSTANTES E VARIÁVEIS ....................................................................................................................................34
4.1 CONSTANTES .........................................................................................................................................................34
4.1.1 CONSTANTES LITERAIS .....................................................................................................................................35
4.1.2 CONSTANTES MANIFESTAS .............................................................................................................................35
4.2 VARIÁVEIS .............................................................................................................................................................365 EXPRESSÕES E OPERADORES ...............................................................................................................................37
5.1 EXPRESSÕES ARITMÉTICAS ...............................................................................................................................37
5.2 EXPRESSÕES RELACIONAIS ...............................................................................................................................38
5.3 EXPRESSÕES LÓGICAS ........................................................................................................................................39
5.4 PRECEDÊNCIA DE OPERADORES .......................................................................................................................40
5.5 CONVERSÕES DE TIPOS ...................................................................................................................................... 41
6 ENTRADA E SAÍDA DE DADOS ................................................................................................................................42
6.1 ENTRADA DE DADOS .............................................................................................................................................43
6.2 SAÍDA DE DADOS ..................................................................................................................................................46
CONSIDERAÇÕES FINAIS ...........................................................................................................................................50
18WWW.UNINGA.BR
AL
GO
RI
TM
OS
E
P
RO
GR
AM
AÇ
ÃO
A
PL
IC
AD
A
| U
NI
DA
DE
1
EDUCAÇÃO A DISTÂNCIA
INTRODUÇÃO
Caro(a) aluno(a), seja bem-vindo(a) à disciplina de Algoritmos e Programação Aplicada.
Nesta disciplina, serão apresentados os princípios básicos de lógica de programação e os principais
comandos necessários para o desenvolvimento de algoritmos.
A lógica está relacionada ao processo de raciocínio, à capacidade de ordenar os
pensamentos e à busca de soluções através de ideias coerentes. Por exemplo, para pegar uma
caneta que está dentro de uma caixa, deve-se primeiro abrir a caixa para depois pegar a caneta;
não é possível atravessar a caixa sem abri-la.
A utilização da lógica é fundamental para a criação de algoritmos, primeiro assunto
abordado nesta unidade, onde descrevemos a sua definição e as suas formas de representação. Em
seguida, é abordado o conceito de programa, seus componentes básicos e o fluxo de transformação
de um código escrito a um programa executável.
Prosseguimos abordando as linguagens de programação, ferramenta utilizada na
codificação de programas, e introduzimos o aluno à linguagem C, adotada neste livro para o
aprendizado da lógica de programação.
Em seguida, já com base na linguagem C, apresentamos os tipos de dados existentes, a
definição de constantes e variáveis, esta última um recurso importante para o armazenamento e a
recuperação de informações da memória RAM. Prosseguimos abordando os tipos de operadores
e as expressões que podem ser formadas para cálculos e processamentos diversos.
Concluímos a unidade descrevendo os processos de como o usuário informa dados ao
programa, e como o programa retorna esses dados em forma de resultados para o usuário.
19WWW.UNINGA.BR
AL
GO
RI
TM
OS
E
P
RO
GR
AM
AÇ
ÃO
A
PL
IC
AD
A
| U
NI
DA
DE
1
EDUCAÇÃO A DISTÂNCIA
1 ALGORITMOS
Segundo Manzano e Oliveira (2012), a palavra algoritmo pode ser empregada na
matemática e na ciência da computação:
O termo algoritmo, do ponto de vista computacional, pode ser entendido
como regras formais, sequenciais e bem definidas a partir do entendimento
lógico de um problema a ser resolvido por um programador com o objetivo de
transformá-lo em um programa que seja possível de ser tratado e executado por
um computador, em que dados de entrada são transformados em dados de saída
(MANZANO; OLIVEIRA, 2012, p. 28).
De acordo com o problema a ser resolvido, são vários os caminhos que podem ser
utilizados para encontrar a sua solução. O algoritmo é um conjunto de passos que define um
desses caminhos. Cada passo é chamado de instrução; assim, um algoritmo pode também ser
definido como um conjunto de instruções (LOPES; GARCIA, 2002).
O Quadro 1 a seguir apresenta dois exemplos de algoritmos para ir ao trabalho, desde o
momento em que o indivíduo acorda até a chegada ao escritório.
1. Desligar o despertador
2. Ir para o banheiro
3. Lavar o rosto
4. Escovar os dentes
5. Tirar o pijama
6. Colocar uma roupa
7. Tomar café da manhã
8. Pegar o carro
9. Estacionar o carro
10. Entrar no escritório
1. Desligar o despertador
2. Ir para o banheiro
3. Escovar os dentes
4. Tomar banho
5. Colocar uma roupa
6. Se estiver chovendo, pegar
guarda-chuva
7. Pegar ônibus
8. Descer do ônibus
9. Entrar no escritório
Quadro 1 – Algoritmos de ida ao trabalho. Fonte: O autor.
Os dois algoritmos do Quadro 1 resolvem o problema de “ida ao trabalho” de formas
diferentes. Cada linha numerada representa uma instrução a ser executada e pode ser detalhada
se necessário. Por exemplo, a instrução “escovar os dentes” poderia ser subdividida nos seguintes
passos:
• Pegar a pasta e a escova de dentes;
• Aplicar a pasta de dentes na escova;
• Molhar a escova com um pouco de água;
• Escovar os dentes;
• Enxaguar a boca;
• Guardar a pasta e a escova de dentes.
Qualquer outra instrução poderia ser igualmente detalhada, estruturando o algoritmo
de forma lógica e organizada. Como a essência do algoritmo está em resolver um determinado
problema em passos, podemos dizer que conhecemos diversos algoritmos de forma empírica,
já que na realidade lidamos com vários tipos de “problemas” cotidianos que demandam uma
solução.
20WWW.UNINGA.BR
AL
GO
RI
TM
OS
E
P
RO
GR
AM
AÇ
ÃO
A
PL
IC
AD
A
| U
NI
DA
DE
1
EDUCAÇÃO A DISTÂNCIA
Apesar de a lógica de programação ser considerada por alguns como um “dom” que
já nasce com o afortunado, qualquer pessoa pode desenvolver sua própria lógica, por meio de
muita prática e exercício. É como aprender a dirigir: a pessoa recebe os ensinamentos teóricos
e práticos, mas somente com a experiência contínua de dirigir nas ruas é que ela irá adquirir
prática e experiência.
E nessa jornada de aprendizado, por quanto mais situações complexas e difíceis passamos,
mais maduros e experientes ficamos. É normal que o aspirante a programador venha a se deparar
com muitos erros e falhas durante o desenvolvimento de seus algoritmos (programas), mas são
exatamente esses obstáculos que formarão uma lógica de programação robusta e consistente nele.
De acordo com Ascencio e Campos (2012), existem três formas de representação de
algoritmos: descrição narrativa, fluxograma e pseudocódigo. Detalhamos cada um desses tipos
nas seções seguintes.
1.1 Descrição Narrativa
A descrição narrativa consiste em escrever as instruções na linguagem natural, em
sequência (ASCENCIO; CAMPOS, 2012). O Quadro 2 a seguir ilustra um algoritmo para somar
dois números em descrição narrativa.
1. Obter dois números
2. Somar os dois números
3. Mostrar o resultado da soma
Quadro 2 – Algoritmo no formato de descrição narrativa. Fonte: O autor.
Segundo Ascencio e Campos (2012), a descrição narrativa possui a vantagem de ser de
fácil aprendizado, uma vez que as instruções são escritas na língua natural. Por outro lado, como
desvantagem ela é ambígua, ou seja, pode gerar diversas interpretações e isso dificulta a conversão
do algoritmo em um programa.
21WWW.UNINGA.BR
AL
GO
RI
TM
OS
E
P
RO
GR
AM
AÇ
ÃO
A
PL
IC
AD
A
| U
NI
DA
DE
1
EDUCAÇÃO A DISTÂNCIA
1.2 Fluxograma
O fluxograma consiste em escrever as instruções do algoritmo utilizando os símbolos
gráficos descritos no Quadro 3 a seguir (ASCENCIO; CAMPOS, 2012).
Quadro 3 – Conjunto de símbolos utilizados do fluxograma. Fonte: Ascencio e Campos (2012).
Na Figura 1 a seguir, temos a representaçãodo algoritmo de somar dois números em
forma de fluxograma.
Figura 1 – Algoritmo no formato de fluxograma. Fonte: O autor.
Segundo Ascencio e Campos (2012), a vantagem do fluxograma está nos símbolos gráficos,
que são universais e podem ser interpretados independente do idioma. Como desvantagem, é
necessário aprender a simbologia apresentada no Quadro 3; além disso, ele não apresenta muitos
detalhes e, por isso, dificulta a conversão do algoritmo em um programa.
22WWW.UNINGA.BR
AL
GO
RI
TM
OS
E
P
RO
GR
AM
AÇ
ÃO
A
PL
IC
AD
A
| U
NI
DA
DE
1
EDUCAÇÃO A DISTÂNCIA
1.3 Pseudocódigo
O pseudocódigo, também conhecido como Portugol ou português estruturado, consiste
em escrever as instruções com regras de sintaxe predefinidas, sendo uma linguagem restrita que
descreve o significado dos termos utilizados (ASCENCIO; CAMPOS, 2012).
O Quadro 4 a seguir ilustra o algoritmo de somar dois números representado em
pseudocódigo.
Algoritmo "soma"
Var
n1, n2, s: inteiro
Inicio
Leia(n1, n2)
s <- n1 + n2
Escreva(s)
FimAlgoritmo
Quadro 4 – Algoritmo em forma de pseudocódigo. Fonte: O autor.
Segundo Ascencio e Campos (2012), o pseudocódigo oferece a vantagem de ser muito
próximo a uma linguagem de programação, tornando a conversão de um algoritmo em um
programa quase que imediata. A desvantagem está na necessidade de ter que aprender as regras do
pseudocódigo; muitas vezes isto leva diretamente ao estudo de uma linguagem de programação
real, embora existam diversos programas no mercado voltados à execução de algoritmos escritos
em pseudocódigo.
Adotamos em nosso livro o aprendizado da lógica de programação tendo como base a
linguagem C, abordada com detalhes na seção seguinte.
23WWW.UNINGA.BR
AL
GO
RI
TM
OS
E
P
RO
GR
AM
AÇ
ÃO
A
PL
IC
AD
A
| U
NI
DA
DE
1
EDUCAÇÃO A DISTÂNCIA
2 PROGRAMAS E LINGUAGENS DE PROGRAMAÇÃO
Programas de computador são, em sua essência, algoritmos que dizem ao computador
os passos específicos para a solução de um problema e em que ordem eles devem ser executados
(DEITEL, 2011).
O computador, por sua vez, traduz as instruções dos programas em operações primitivas.
O Quadro 5 a seguir apresenta estas operações, comuns não só aos computadores, mas a todos os
demais aparelhos digitais eletrônicos.
Operação Tipo de instrução Descrição
Processamento de
dados Aritmética e lógica
Fornecem a capacidade computacional para processar
dados numéricos e booleanos
Armazenamento de
dados Memória Move dados entre a memória e os registradores
Movimentação de
dados Entrada e saída
Comandos para obtenção e apresentação de dados em
dispositivos de E/S
Controle Teste e desvio Testa o valor de uma palavra ou desvia a execução do programa para uma nova instrução
Quadro 5 – Operações primitivas realizadas por computadores. Fonte: Tanenbaum (2013).
O computador pode executar programas gerados por meio de duas ferramentas: o
compilador e o interpretador. Elas são responsáveis por transformar as instruções escritas nos
programas em linguagem compreensível pelo computador, e são detalhadas nas seções seguintes.
24WWW.UNINGA.BR
AL
GO
RI
TM
OS
E
P
RO
GR
AM
AÇ
ÃO
A
PL
IC
AD
A
| U
NI
DA
DE
1
EDUCAÇÃO A DISTÂNCIA
2.1 Compiladores
Segundo Sebesta (2011), compilação é o processo onde um programa escrito em uma
linguagem de programação é traduzido para linguagem de máquina. O software responsável por
esse processo é o compilador, que executa as seguintes tarefas:
• Gera um código intermediário em linguagem de montagem, usado como base para a
criação de um arquivo binário chamado código-objeto;
• Resolve as chamadas de funções do sistema operacional ou de bibliotecas externas usadas
no programa, por meio de uma ferramenta auxiliar chamada de ligador (linker) no
processo conhecido como linkagem ou ligação;
• Gera o código de máquina final, geralmente um arquivo executável ou uma biblioteca de
funções que podem ser usadas para gerar outros programas.
Este processo é ilustrado com detalhes na Figura 2 a seguir.
Figura 2 – Processo de compilação. Fonte: Tucker e Noonan (2010).
O compilador apresenta como vantagem o desempenho em tempo de execução, uma vez
que o mapeamento para entradas e saída ocorre muito mais rapidamente. Por outro lado, tem
a desvantagem de ter que repetir todo o processo de compilação cada vez que o código-fonte é
alterado (TUCKER; NOONAN, 2010).
25WWW.UNINGA.BR
AL
GO
RI
TM
OS
E
P
RO
GR
AM
AÇ
ÃO
A
PL
IC
AD
A
| U
NI
DA
DE
1
EDUCAÇÃO A DISTÂNCIA
2.2 Interpretadores
A interpretação é caracterizada por efetuar as fases abordadas na compilação, linha por
linha de instrução do programa. Assim, este é executado junto com as entradas diretamente por
um programa denominado interpretador, que produz o resultado. Por essa razão, também não há
arquivos intermediários, como código-objeto ou arquivo executável (SEBESTA, 2011).
Em resumo, cada linha do programa é lida pelo interpretador, convertida e imediatamente
executada antes que o comando seguinte seja lido. A Figura 3 a seguir ilustra esse processo.
Figura 3 – Processo de interpretação. Fonte: Tucker e Noonan (2010).
A qualidade da interação com o sistema pode ser melhor com um interpretador do
que com um compilador, pois o primeiro executa o programa instrução por instrução. Já que o
desenvolvimento de programas é interativo, trechos de programas podem ser testados na medida
em que são escritos, oferecendo assim um melhor diagnóstico de erro (TUCKER; NOONAN,
2010).
No entanto, isso acaba por tornar lento o processamento do programa interpretado se
comparado ao programa compilado. Além dessa desvantagem, geralmente corre-se o risco de
deixar o código-fonte do programa exposto ao usuário (MANZANO; OLIVEIRA, 2012).
2.3 Linguagens de Programação
As linguagens de programação constituem um vocabulário acompanhado de um conjunto
de regras gramaticais. Esse conjunto de comandos e regras permite a escrita de um programa
que pode ser lido e compreendido por um ser humano com certa naturalidade e traduzido sem
ambiguidade pelo próprio computador para a linguagem de máquina (TUCKER; NOONAN,
2010).
As linguagens de programação geralmente são divididas em três tipos gerais, segundo
Deitel (2011):
• Linguagem de máquina, formada por uma sequência de números – em última instância,
reduzidos a 0s e 1s. É a “linguagem natural” de um computador em particular, definida
pelo projeto de hardware;
26WWW.UNINGA.BR
AL
GO
RI
TM
OS
E
P
RO
GR
AM
AÇ
ÃO
A
PL
IC
AD
A
| U
NI
DA
DE
1
EDUCAÇÃO A DISTÂNCIA
• Linguagens simbólicas ou de montagem, também conhecida como assembly. Sua finalidade
é simplificar a escrita e a leitura da linguagem de máquina por meio de declarações que
produzem instruções correspondentes de máquina;
• Linguagens de alto nível, onde seu conjunto de regras e instruções é mais próximo da
linguagem humana. Exemplos: Fortran, Basic, C, C++, C#, COBOL, Harbour, Pascal,
Delphi, Pearl, Phyton, PHP, Java, Javascript, entre muitas outras.
Adotamos em nossa disciplina a C como base para o aprendizado de lógica de programação;
portanto, apresentamos essa linguagem na próxima seção e usamo-na para exemplificar os demais
elementos de programação abordados neste livro.
2.4 Linguagem C
A linguagem C foi originada de outras duas linguagens, segundo Schildt (1996):
A linguagem C foi inventada primeiramente por Dennis Ritchie em um DEC
PDP-11 que utilizava o sistema operacional UNIX. C é o resultado de um
processo de desenvolvimento que começou com uma linguagem mais antiga,
chamada BCPL, que ainda está em uso, em sua forma original, na Europa. BCPL
foi desenvolvida por Martin Richards e influenciou uma linguagem chamada B,
inventada por Ken Thompson. Na década de 1970, B levou ao desenvolvimento
de C (SCHILDT, 1996, p. 3).
Ainda de acordo com Schildt (1996), C é frequentemente classificada como linguagem
de médio nível para computadores porque combina elementos de linguagem de altonível com a
funcionalidade da linguagem de montagem. Além disso, um programa escrito em C é portável,
ou seja, pode ser executado em tipos diferentes de computadores com poucas adaptações.
C é uma linguagem compilada e seus programas percorrem seis passos até que possam
ser executados (DEITEL, 2011), ilustrados na Figura 4 a seguir.
27WWW.UNINGA.BR
AL
GO
RI
TM
OS
E
P
RO
GR
AM
AÇ
ÃO
A
PL
IC
AD
A
| U
NI
DA
DE
1
EDUCAÇÃO A DISTÂNCIA
Figura 4 – Ambiente típico de desenvolvimento em C. Fonte: Deitel (2011).
28WWW.UNINGA.BR
AL
GO
RI
TM
OS
E
P
RO
GR
AM
AÇ
ÃO
A
PL
IC
AD
A
| U
NI
DA
DE
1
EDUCAÇÃO A DISTÂNCIA
Devido ao paradigma procedural da linguagem, todo programa em C é estruturado em
funções e dentro delas estão contidas as instruções a serem executadas. O Quadro 6 a seguir
ilustra um esboço desta estrutura.
tipo nome_da_função(parâmetros)
{
variáveis locais
instruções
}
Quadro 6 – Estrutura de um programa em C. Fonte: O autor.
Cada item é descrito da seguinte forma:
• tipo: tipo de dado a ser retornado pela função;
• parâmetros (opcional): lista de argumentos a serem passados para a função, devidamente
tipados;
• {}: delimitam o início e o final da função;
• variáveis locais (opcional): declaração das variáveis locais a serem usadas, devidamente
tipadas;
• instruções: comandos a serem executados.
Todo programa em C, após ser escrito, deve ser gravado no formato de arquivo texto –
cujo nome deve ter a extensão .c – em um dispositivo de armazenamento secundário, como por
exemplo um disco rígido ou um pendrive (DEITEL, 2011).
Existem vários ambientes de desenvolvimento integrado (IDE)
disponíveis para a linguagem C em vários sistemas operacionais.
Deixamos o aluno à vontade para usar o de sua preferência. Para
Windows, temos: Turbo C, DevC++, Code Blocks etc.; este último
possui disponível um tutorial de como compilar seu primeiro
programa.
Linguagem C #02: Primeiro programa em C
Disponível em: https://www.youtube.com/watch?v=VGC-XEj76xI .
Acesso em: 9 set. 2020.
29WWW.UNINGA.BR
AL
GO
RI
TM
OS
E
P
RO
GR
AM
AÇ
ÃO
A
PL
IC
AD
A
| U
NI
DA
DE
1
EDUCAÇÃO A DISTÂNCIA
Vamos enfim ao nosso primeiro programa em C, o famigerado “Alô Mundo” – sugestão
de nome de arquivo: AloMundo.c. O Quadro 7 a seguir ilustra como ficaria o código desse
programa.
#include <stdio.h> // Inclui o cabeçalho de funções de E/S
/* Trecho do programa principal */
int main(void)
{
printf(“Alo, Mundo!”); // Imprime o texto na tela
return 0; // Retorna o valor para o SO
}
Quadro 7 – Programa “Alô Mundo”. Fonte: O autor.
Esse programa consiste em 6 linhas, já desconsiderando a linha em branco, mas pode
ser reduzido ainda mais devido à flexibilidade de estruturar várias instruções em uma só linha.
Vamos descrever o significado dos comandos linha por linha:
• #include <stdio.h> – todo comando que inicia com # é uma diretiva de pré-processamento
e é analisado na Fase 2 da Figura 4. #include permite que funções em um determinado
cabeçalho-padrão sejam chamadas no programa. stdio.h contém o protótipo da função
printf(), usada umas linhas adiante no programa do Quadro 7;
• /* Trecho do programa principal */ – essa linha é um comentário e será ignorada pelo
compilador. C oferece dois comandos para fazer comentários em programas: /* */, que
permitem comentários em múltiplas linhas; e //, que pode ser usado no final de uma linha
com instruções, e os comentários estendem-se até o final da linha. É uma boa prática fazer
comentários nos programas, como forma de documentação e de guia para determinadas
operações realizadas nele, com o objetivo de auxiliar em uma ocasional manutenção;
• int main(void) – todo programa em C deve conter uma função denominada main(), toda
em minúscula, pois é por meio dela que a execução é iniciada. Geralmente ela retorna um
valor numérico para o sistema operacional, sendo que 0 indica sucesso de execução e
outro número indica um erro a ser tratado externamente; por isso, definimos int como
tipo de retorno. A palavra void entre os parênteses é usada para indicar que a função não
receberá parâmetros.
• printf(“Alo, Mundo!”); – essa função imprime dados no dispositivo de saída corrente,
nesse caso, a tela do monitor. Uma lista de parâmetros pode ser passada para a função
inclusive com a opção de formatar os dados a serem exibidos;
• return 0; – esse comando retorna o valor especificado para a função chamadora. No caso
da função main(), sempre retornaremos 0, indicando sucesso na execução.
30WWW.UNINGA.BR
AL
GO
RI
TM
OS
E
P
RO
GR
AM
AÇ
ÃO
A
PL
IC
AD
A
| U
NI
DA
DE
1
EDUCAÇÃO A DISTÂNCIA
Com exceção das diretivas de pré-processamento, os demais comandos – incluindo
as chaves delimitadoras {} – podem ser agrupados em uma linha. O Quadro 8 a seguir ilustra
algumas formas alternativas para codificar o programa “Alô Mundo”.
int main(void) {
printf(“Alo, Mundo!”);
return 0;
}
int main(void)
{ printf(“Alo, Mundo!”);
return 0;
}
int main(void) { printf("Alo, Mundo!"); return 0; }
Quadro 8 – Variantes do programa “Alô Mundo”. Fonte: O autor.
Todos os exemplos do Quadro 8 fazem exatamente a mesma coisa do programa do
Quadro 7. A única diferença está na forma em que as instruções foram distribuídas.
C é uma linguagem case-sensitive, isto é, faz distinção entre maiúscula e
minúscula. Todas as palavras reservadas em C são minúsculas; a função main(),
como já visto, deve ser declarada em minúscula; a variável valor é diferente de
Valor ou VALOR, são três variáveis distintas; processa() é diferente de Processa()
ou PROCESSSA(), são três funções distintas (SCHILDT, 1996).
Além disso, todos os comandos são concluídos com um ponto-e-vírgula (;),
também chamado de terminador de instruções. Exceções a esta regra são as
declarações de funções e as diretivas de pré-processamento (DEITEL, 2011).
31WWW.UNINGA.BR
AL
GO
RI
TM
OS
E
P
RO
GR
AM
AÇ
ÃO
A
PL
IC
AD
A
| U
NI
DA
DE
1
EDUCAÇÃO A DISTÂNCIA
3 TIPOS DE DADOS
Na linguagem C, existem cinco tipos de dados básicos e dois tipos de dados especiais,
abordados nas seções seguintes.
3.1 Tipos de Dados Básicos
Segundo Schildt (1996), os dados podem ser representados por cinco tipos básicos:
• char: caractere;
• int: inteiro;
• float: ponto flutuante;
• double: ponto flutuante de precisão dupla;
• void: nulidade ou ausência de valor.
Com exceção do void, os demais tipos podem ter sua capacidade ou faixa de valores
alterada com o uso de modificadores. Existem quatro modificadores, segundo Schildt (1996):
• unsigned: utilizado para declarar os tipos como sem sinal, duplicando assim a gama de
valores que pode ser representado;
• signed: declara tipos contendo sinal;
• short: reduz a capacidade de armazenamento;
• long: aumenta a capacidade de armazenamento.
32WWW.UNINGA.BR
AL
GO
RI
TM
OS
E
P
RO
GR
AM
AÇ
ÃO
A
PL
IC
AD
A
| U
NI
DA
DE
1
EDUCAÇÃO A DISTÂNCIA
Na prática, signed e short são redundantes e pouco usados, pois a declaração padrão de
tipos já considera, respectivamente, o sinal e a menor faixa de valores.
O Quadro 9 a seguir apresenta os tipos de dados com e sem modificadores, seu tamanho
e sua faixa de dados permitida.
Tipo Faixa de valores Tamanho aproximado
char -128 a 127 8 bits (1 byte)
unsigned char 0 a 255 8 bits (1 byte)
int -32.768 a 32.767 16 bits (2 bytes)
short int -32.768 a 32.767 16 bits (2 bytes)
unsigned int 0 a 65.535 16 bits (2 bytes)
long int -2.147.483.648 a 2.147.489.647 32 bits (4 bytes)
long -2.147.483.648 a 2.147.489.647 32 bits (4 bytes)
unsigned long 0 a 4.294.967.295 32 bits (4 bytes)
float 3.4 x 10-38 a 3.4 x 1038 32 bits (4 bytes)
double 1.7 x 10-308 a 1.7 x 10308 64 bits (8 bytes)
long double 3.4 x 10-49328 a 3.4 x 1049328 128 bits (16 bytes)
Quadro 9 – Todos os tipos dados definidos pelo padrão ANSI. Fonte: adaptado de Schildt (1996).
Alguns tipos de dados podem variar dependendodo hardware, do compilador e do
sistema operacional. Por exemplo, o tipo int possui 4 bytes nos computadores mais atuais e,
consequentente, a mesma faixa de valores de um long.
Além dos cinco tipos de dados básicos e seus modificadores, a linguagem C possui dois
tipos especiais de dados: enumeradores e ponteiros.
Reparamos no Quadro 9 que o tipo char, embora seja para representar caracteres,
também possui uma faixa de valores. Na verdade, esse tipo armazena o código
numérico do caractere na tabela ASCII da máquina (DEITEL, 2011). Exemplos:
• ‘z’ representa o código de z, que é 122;
• ‘7’ representa o código no número 7, que é 55;
• ‘\n’ representa o código do caractere de nova linha, que é 10.
33WWW.UNINGA.BR
AL
GO
RI
TM
OS
E
P
RO
GR
AM
AÇ
ÃO
A
PL
IC
AD
A
| U
NI
DA
DE
1
EDUCAÇÃO A DISTÂNCIA
3.2 Enumeradores
De acordo com Deitel (2011, p. 340), “uma enumeração, introduzida pela palavra-chave
enum, é um conjunto de constantes de enumeração inteiras, representadas por identificadores”.
Os valores em uma enumeração iniciam em 0 e são incrementados por 1 a cada item
da lista. Por exemplo: enum semana { DOM, SEG, TER, QUA, QUI, SEX, SAB }; cria uma
lista com os dias da semana enumerados de 0 a 6. Para iniciar a lista com 1, basta atribui-lo no
primeiro item, desta forma:
enum semana { DOM = 1, SEG, TER, QUA, QUI, SEX, SAB };
Os demais itens serão incrementados com 1 automaticamente, fazendo com que SEG
valha 2 e SAB valha 7. Depois de declarada, variáveis podem ser criadas usando a enumeração
como tipo de dado e usando suas constantes como valores.
3.3 Ponteiros
Basicamente, um ponteiro é tipo de dado que armazena um endereço de memória.
Este endereço de memória, por sua vez, pode conter uma variável ou uma função carregada na
memória (DEITEL, 2011).
Depois de armazenado um endereço de memória no ponteiro, existe um operador em C
que permite recuperar:
• o seu valor, no caso do endereço conter uma variável;
• o seu código para ser executado, no caso do endereço conter uma função.
Ponteiros são um dos recursos que tornam a linguagem C mais poderosa em comparação
a outras linguagens. Por outro lado, é um assunto complexo e que demanda muito entendimento
e prática para poder ser aplicado com eficiência.
Abordamos ponteiros neste livro porque são necessários na representação de cadeias de
caracteres e na passagem de parâmetros por referência a funções. Portanto, esse tipo de dado é
visto com mais detalhes na Unidade IV.
34WWW.UNINGA.BR
AL
GO
RI
TM
OS
E
P
RO
GR
AM
AÇ
ÃO
A
PL
IC
AD
A
| U
NI
DA
DE
1
EDUCAÇÃO A DISTÂNCIA
4 CONSTANTES E VARIÁVEIS
Os tipos de dados apresentados na seção anterior podem ser representados em um
programa por meio de constantes ou de variáveis. Segundo Schildt (1996, p. 19), “em C, nomes
de variáveis, funções, rótulos e vários outros objetos definidos pelo usuário são chamados de
identificadores”. Eles devem ser formados por letras, números ou o caracter sublinhado “_”, sendo
que não pode ser iniciado com números e nem coincidir com as palavras reservadas da linguagem.
O Quadro 10 a seguir mostra alguns exemplos de identificadores válidos e inválidos.
Válidos Inválidos
A 2ª (começa com número e possui caracter inválido: “ª”)
a b@ (possui caracter inválido: “@”)
Media media idade (possui espaço em branco)
altura2 x*y (possui caracter inválido: “*”)
media_idade #media (“#” é para diretivas de pré-processamento)
x36 1anoComputacao (começa com número)
NomeAluno break (palavra reservada da linguagem C)
Quadro 10 – Identificadores válidos e inválidos. Fonte: O autor.
Vale lembrar que, em C, A não é o mesmo que a: cada um é um identificador distinto. O
Quadro 11 a seguir lista todas as palavras reservadas – ou palavras-chave – da linguagem, que
são identificadas pelo compilador para traduzir suas instruções devidamente para a linguagem de
máquina, e, por isso, não podem ser usadas como identificadores.
auto do goto signed unsigned
break double if sizeof void
case else int static volatile
char enum long struct while
const extern register switch
continue float return typedef
default for short union
Quadro 11 – Palavras-chave da linguagem C. Fonte: Deitel (2011).
4.1 Constantes
De acordo com Manzano e Oliveira (2012, p. 46), “constante é tudo que é fixo, estável,
inalterável, imutável, contínuo, incessante, invariável, de valor fixo e que é aplicado em diversos
pontos de vista”. Xavier (2011, p. 37) complementa que “dentro do algoritmo, constantes são os
valores que permanecem os mesmos do início ao fim”.
Existem dois tipos de constantes em C: constantes literais e constantes manifestas. As
constantes literais são a representação direta de cada dado, enquanto as constantes manifestas são
esses mesmos dados atribuídos a um identificador por meio do comando const ou da diretiva
#define (SCHILDT, 1996).
35WWW.UNINGA.BR
AL
GO
RI
TM
OS
E
P
RO
GR
AM
AÇ
ÃO
A
PL
IC
AD
A
| U
NI
DA
DE
1
EDUCAÇÃO A DISTÂNCIA
4.1.1 Constantes literais
O tipo de dado char é representado literalmente de duas formas:
• Com aspas simples para um caractere, por exemplo: ‘A’, ‘B’, ‘1’, ‘-’, ‘@’ etc.;
• Com aspas duplas para dois ou mais caracteres, por exemplo: “Uningá”, “B+” etc.
O tipo de dado int é representado literalmente por números inteiros sem o ponto decimal,
por exemplo: 25, -481, 2020, 10022018 etc. Os tipos de dados float e double, por sua vez, são
representados literalmente por números com o ponto decimal, por exemplo: 8.35, +16.789,
3.1415, -16.44, 0.222222 etc.
4.1.2 Constantes manifestas
Segundo Deitel (2011), constantes manifestas criadas com a diretiva de pré-processamento
#define são automaticamente substituídas pelo seu valor correspondente na fase de pré-
compilação – vide Fase 2 da Figura 1. A sintaxe para a criação de uma constante com esta diretiva
é: #define identificador valor.
Constantes manifestas criadas com o comando const são na verdade variáveis que serão
instruídas pelo compilador a serem armazenadas no espaço de memória ROM, onde seus valores
não poderão ser modificados (SCHILDT, 1996).
O Quadro 12 a seguir ilustra alguns exemplos de definição de constantes com #define e
const.
#define PI 3.1415
#define ANO 2020
#define IE "Uninga"
const int TAMANHO = 10;
const float FATOR = 1.25;
Quadro 12 – Exemplos de criação de constantes. Fonte: O autor.
Embora não seja uma regra, é costume nas linguagens de programação declarar constantes
em maiúsculas, para diferenciar das variáveis que geralmente são criadas em letra minúscula. O
importante em relação à linguagem C é lembrar que elas devem ser referenciadas exatamente da
forma como foram criadas.
Não existe um tipo de dado string em C, como normalmente ocorre em outras linguagens.
Cadeias de caracteres são na verdade um vetor de elementos do tipo char e possuem
operadores e funções específicas para serem manipuladas (DEITEL, 2011). Strings são
abordadas com mais detalhes na Unidade III.
36WWW.UNINGA.BR
AL
GO
RI
TM
OS
E
P
RO
GR
AM
AÇ
ÃO
A
PL
IC
AD
A
| U
NI
DA
DE
1
EDUCAÇÃO A DISTÂNCIA
4.2 Variáveis
Um programa pode receber dados de entrada fornecidos pelo usuário ou efetuar cálculos
complexos que requerem o armazenamento desses dados na memória para serem recuperados
posteriormente e até mesmo serem modificados. As variáveis representam uma posição de
memória com esse propósito. Além do valor armazenado, elas possuem nome e tipo (ASCENCIO;
CAMPOS, 2012).
Segundo Schildt (1996, p. 20), “[...] todas as variáveis em C devem ser declaradas antes de
serem usadas”. A sintaxe para declarar uma variável é:
tipo lista_de_variáveis;
Onde o tipo pode ser qualquer um dos tipos de dados abordados, opcionalmente
acompanhado de modificadores. O Quadro 13 a seguir ilustra alguns exemplos de declaração de
variáveis.
int quantidade;
unsigned int populacao;
float valor, desconto;
double total;
long double cod_barras;
char sexo;
char endereco[30];
Quadro 13 – Declaração de variáveis emC. Fonte: O autor.
Para armazenar dados em variáveis, utilizamos o operador de atribuição (=). A sintaxe
para tal finalidade é:
identificador = expressão;
Onde identificador é o nome da variável previamente declarada, e expressão, o valor de
acordo com o tipo da variável. O Quadro 14 a seguir ilustra algumas atribuições de valores às
variáveis declaradas no Quadro 13.
quantidade = 12;
populacao = 35000;
valor = 35.60;
desconto = 10;
total = quantidade * valor;
total = total – (total * desconto / 100);
cod_barras = 7891237791212;
sexo = 'F';
endereço = "Avenida Brasil, 2855";
Quadro 14 – Exemplos de atribuição. Fonte: O autor.
Para atribuir o mesmo valor a várias variáveis de uma vez, utilizamos o recurso da atribuição
múltipla. Por exemplo, x = y = z = 0; atribuirá o valor zero às variáveis x, y e z (SCHILDT, 1996).
É possível também atribuir um valor no momento da declaração da variável. Por exemplo,
int opcao = 1; fará com que a variável opcao possua o valor inicial de 1, podendo este ser alterado
a qualquer momento no programa. Para isso, basta fazer uma nova atribuição e o novo valor
substituirá o anterior na memória. Variáveis declaradas sem atribuição de valor são inicializadas
com valores aleatórios, dependendo do compilador C; portanto, é importante sempre atribuir
valores a elas.
37WWW.UNINGA.BR
AL
GO
RI
TM
OS
E
P
RO
GR
AM
AÇ
ÃO
A
PL
IC
AD
A
| U
NI
DA
DE
1
EDUCAÇÃO A DISTÂNCIA
Alguns exemplos do Quadro 14 utilizam cálculos aritméticos e as próprias variáveis
criadas como parte da expressão a ser calculada. Abordamos os operadores disponíveis em C na
seção seguinte.
5 EXPRESSÕES E OPERADORES
Segundo Sebesta (2011, p. 342), “[...] expressões são os meios fundamentais de especificar
computações em uma linguagem de programação”. São um conjunto de operadores e operandos
que geram um resultado a ser utilizado no processamento de um programa.
Existem três tipos de expressões em C: aritméticas, relacionais e lógicas. Detalhamos cada
tipo nas seções seguintes, juntamente com os seus operadores.
5.1 Expressões Aritméticas
Expressões aritméticas são aquelas em que o resultado consiste em um valor numérico.
Portanto, podem ser utilizados em expressões desse tipo apenas operadores aritméticos, constantes
numéricas e variáveis numéricas – do tipo int, float, double e derivados.
O Quadro 15 a seguir apresenta os operadores aritméticos fornecidos pela linguagem C.
Operação Operador Exemplo
Soma + vencimento + 30
Subtração - elementos – 1
Multiplicação * quantidade * preco
Divisão / soma_notas / 4
Resto da divisão % número % 2
Quadro 15 – Operadores aritméticos. Fonte: Adaptado de Deitel (2011).
Esses operadores seguem a regra de precedência da matemática. Portanto, em uma
expressão contendo vários operadores, são calculadas primeiramente as multiplicações, divisões
e o resto; em seguida, são calculadas as somas e subtrações. Parênteses podem ser usados para
alterar essa ordem.
De acordo com Deitel (2011, p. 64), “C oferece vários operadores de atribuição que
abreviam as expressões de atribuição. Por exemplo, a instrução c = c + 3; pode ser abreviada com
o operador de atribuição com adição += para c += 3;”. Existe um operador de atribuição para
cada operador aritmético da linguagem C, conforme apresentado no Quadro 16 a seguir.
Operador Exemplo Equivalente a
+= x += y; x = x + y;
-= x -= y; x = x - y;
*= x *= y; x = x * y;
/= x /= y; x = x / y;
%= x %= y; x = x % y;
Quadro 16 – Operadores de atribuição. Fonte: Adaptado de Deitel (2011).
38WWW.UNINGA.BR
AL
GO
RI
TM
OS
E
P
RO
GR
AM
AÇ
ÃO
A
PL
IC
AD
A
| U
NI
DA
DE
1
EDUCAÇÃO A DISTÂNCIA
C também oferece os operadores de incremento (++) e decremento (--), que somam ou
subtraem 1, respectivamente, do seu operando. Eles são unários e podem ser usados como prefixo
ou sufixo da variável a ser alterada; contudo, possuem comportamento diferente, segundo Schildt
(1996):
• Se precederem a variável, alteram-na antes de usá-la na expressão;
• Se estiverem após a variável, usam seu valor atual na expressão antes de alterá-la.
O Quadro 17 a seguir ilustra alguns exemplos dos operadores de atribuição, incremento
e decremento.
int v1, v2, v3;
v1 = 10;
v2 = 5;
v1 += v2; // v1 = 15
v3 = ++v1 + v2; // v3 = 16 (incrementou v1 antes)
v3 = v1 + v2++; // v3 = 16 (incrementou v2 depois)
v1 -= 7; // v1 = 9
v2 *= 3; // v2 = 18
v3 /= 4; // v3 = 4
Quadro 17 – Operadores de atribuição, incremento e decremento. Fonte: O autor.
5.2 Expressões Relacionais
As expressões relacionais referem-se à comparação entre dois valores de um tipo básico;
a isso chamamos de condição, e o seu resultado consiste em um valor lógico verdadeiro ou falso.
Segundo Deitel (2011, p. 32), “[...] em C, uma condição pode ser, realmente, qualquer expressão
que resulte em um valor zero (falsa) ou diferente de zero (verdadeira)”.
O Quadro 18 a seguir apresenta os operadores relacionais da linguagem C.
Operador Símbolo Exemplo
Igual == a == 1
Diferente != a != b
Maior que > a > 5
Menor que < b < 12
Maior ou igual a >= a >= 6
Menor ou igual a <= b <= 7
Quadro 18 – Operadores relacionais. Fonte: Adaptado de Deitel (2011).
39WWW.UNINGA.BR
AL
GO
RI
TM
OS
E
P
RO
GR
AM
AÇ
ÃO
A
PL
IC
AD
A
| U
NI
DA
DE
1
EDUCAÇÃO A DISTÂNCIA
Todos esses operadores possuem a mesma precedência, sendo avaliados da esquerda para
a direita; parênteses podem ser usados para alterar a ordem. Diversos exemplos com operadores
relacionais são apresentados na Unidade II, onde abordamos as estruturas de seleção e repetição.
5.3 Expressões Lógicas
As expressões lógicas permitem que duas ou mais comparações possam ser combinadas
em uma única avaliação, fazendo com que o seu resultado também seja verdadeiro ou falso. Para
isso, C oferece três operadores, apresentados no Quadro 19 a seguir.
Operador Símbolo Descrição
Conjunção && Resulta em um valor verdadeiro somente quando todas as expressões são verdadeiras
Disjunção || Resulta em um valor verdadeiro quando pelo menos uma das expressões é verdadeira
Negação ! Inverte o valor de uma expressão: se for verdadeira, torna-se falsa; e se for falsa, torna-se verdadeira
Quadro 19 – Operadores lógicos. Fonte: Adaptado de Schildt (1996).
Se todos esses operadores forem usados em uma única expressão, a ordem de precedência
é:
4. ! – negação, também chamado de NÃO lógico ou NOT;
5. && – conjunção, também chamado de E lógico ou AND;
6. || – disjunção, também chamado de OU lógico ou OR;
Assim como nas outras expressões, parênteses podem ser usados para alterar essa ordem.
O Quadro 20 a seguir traz alguns exemplos.
char letra = 'J';
int ok = 1, valor = 10, r;
r = ok || valor != 10; // Resulta: 1 (verdadeiro)
r = ok && valor != 10; // Resulta: 0 (falso)
r = ok || valor == 3 || letra == 'A'; // Resulta: 1 (verdadeiro)
r = valor == 10 && !ok; // Resulta: 0 (falso)
r = valor == 2 && ok || letra == 'J'; // Resulta: 1 (verdadeiro)
r = valor == 2 && (ok || letra == 'J'); // Resulta: 0 (falso)
Quadro 20 – Exemplos usando operadores lógicos. Fonte: O autor.
40WWW.UNINGA.BR
AL
GO
RI
TM
OS
E
P
RO
GR
AM
AÇ
ÃO
A
PL
IC
AD
A
| U
NI
DA
DE
1
EDUCAÇÃO A DISTÂNCIA
5.4 Precedência de Operadores
Em uma expressão, como já visto, podemos ter mais de um operador envolvido. Em
situações que há um único operador, a avaliação da expressão é realizada de forma direta. Quando
há mais de um operador, porém, é necessária a avaliação da expressão passo a passo, ou seja, um
operador por vez.
Nesse caso, a precedência de operadores é determinada por parênteses ou pelo Quadro
21 a seguir, onde apresentamos os operadores abordados até o momento e a forma como os seus
operandos são associados.
Quadro 21 – Precedência de operadores de diversos tipos. Fonte: Adaptado de Schildt (1996).
O operador de condição ternária é explicado na unidade seguinte, junto com as estruturasde seleção; e o operador de expressão de função, na Unidade IV, junto com as sub-rotinas.
41WWW.UNINGA.BR
AL
GO
RI
TM
OS
E
P
RO
GR
AM
AÇ
ÃO
A
PL
IC
AD
A
| U
NI
DA
DE
1
EDUCAÇÃO A DISTÂNCIA
5.5 Conversões de Tipos
Quando constantes e variáveis de tipos diferentes estão envolvidas em uma expressão, o
compilador deve convertê-las em um mesmo tipo para poder resolver a expressão com os valores
normalizados; isto se chama promoção de tipo e é feito operação por operação em uma expressão
seguindo esta ordem do menor para o maior tipo: char → int → long → float → double → long
double (SCHILDT, 1996).
A Figura 5 a seguir ilustra alguns exemplos de conversões implícitas, aquelas que o
compilador realiza automaticamente resolvendo a expressão de acordo com o maior operando
em uma operação.
Figura 5 – Exemplo de conversões implícitas. Fonte: Schildt (1996).
É possível também realizar conversões explícitas, conhecidas como casts, onde passamos
o tipo final desejado entre parênteses à esquerda do operando, seja uma constante ou uma
expressão. Sua sintaxe geral é: (tipo) operando (SCHILDT, 1996).
Por exemplo, para garantir que a expressão x / 2 resulte em um valor com decimais,
podemos usar: (float)x / 2. Mesmo que x seja um inteiro, será convertido em ponto flutuante e
terá predominância sobre o segundo operando 2, que é um inteiro. Casts são muito utilizados na
manipulação avançada de ponteiros e estruturas definidas pelo usuário.
42WWW.UNINGA.BR
AL
GO
RI
TM
OS
E
P
RO
GR
AM
AÇ
ÃO
A
PL
IC
AD
A
| U
NI
DA
DE
1
EDUCAÇÃO A DISTÂNCIA
6 ENTRADA E SAÍDA DE DADOS
A maior parte dos programas é estruturada para receber dados de entrada do usuário,
que serão processados de alguma forma e depois serão apresentados os resultados na forma
de informações. Esse ciclo, ilustrado na Figura 6 a seguir, pode-se repetir quantas vezes forem
necessárias dentro de um programa para solucionar um determinado problema.
Figura 6 – Estrutura do fluxo padrão de um programa. Fonte: O autor.
Conforme ilustrado no Quadro 5 desta unidade, a entrada e a saída de dados estão entre
as operações primitivas que o computador realiza. Toda linguagem de programação deve prover
recursos para que o usuário possa:
• informar dados usando um dispositivo de entrada – teclado, mouse, scanner etc.
• visualizar os resultados depois de processados em um dispositivo de saída –monitor,
impressora, projetor etc.
As principais funções fornecidas pela linguagem C com esta finalidade são: scanf(), para
entrada de dados; e printf(), para saída de dados. Abordamos essas funções com detalhes nas
seções seguintes.
43WWW.UNINGA.BR
AL
GO
RI
TM
OS
E
P
RO
GR
AM
AÇ
ÃO
A
PL
IC
AD
A
| U
NI
DA
DE
1
EDUCAÇÃO A DISTÂNCIA
6.1 Entrada de Dados
A função scanf() lê dados fornecidos pelo usuário e os armazena em variáveis. Segundo
Deitel (2011), sua sintaxe é a seguinte:
scanf( string-de-controle-de-formato, outros-argumentos );
Onde string-de-controle-de-formato descreve os formatos da entrada, e outros-
argumentos são ponteiros para as variáveis em que a entrada será armazenada. Cada especificador
de formato inserido na string deve vir acompanhado de um ponteiro para a variável onde o valor
será armazenado, e na devida ordem em que foram especificados.
44WWW.UNINGA.BR
AL
GO
RI
TM
OS
E
P
RO
GR
AM
AÇ
ÃO
A
PL
IC
AD
A
| U
NI
DA
DE
1
EDUCAÇÃO A DISTÂNCIA
O Quadro 22 a seguir apresenta os especificadores de formato disponíveis. Eles devem ser
precedidos na string com o caracter “%”.
Tipo de dado Especificador de conversão Descrição
Argumento
correspondente
Inteiro
d Lê um inteiro decimal com sinal opcional Ponteiro para um int
i Lê um inteiro decimal, octal ou hexadecimal com sinal opcional Ponteiro para um int
o Lê um inteiro octal Ponteiro para um unsigned int
u Lê um inteiro decimal sem sinal Ponteiro para um unsigned int
x ou X Lê um inteiro hexadecimal sem sinal Ponteiro para um unsigned int
h ou l
Colocados antes de qualquer um dos
especificadores de conversão de inteiros
para indicar que um inteiro short ou
um inteiro long deve ser inserido.
N/A
Ponto
flutuante
e, E, f, g ou G Lê um valor de ponto flutuante Ponteiro para um float
l ou L
Colocados antes de qualquer um dos
especificadores de conversão de ponto
flutuante para indicar que um valor
double ou um long double deve ser
inserido
Ponteiro para uma
variável double ou uma
variável long double
Caracteres e
strings
c Lê um caractere Ponteiro para um char
s Lê uma string
Ponteiro para um
vetor do tipo char com
tamanho suficiente
para guardar a string
e um caractere nulo
(‘\0’) de término,
automaticamente
acrescentado
[caracteres de
varredura]
Varre uma string em busca de um
conjunto de caracteres que estão
armazenados em um vetor
N/A
Diversos
p Lê um endereço de memória
Ponteiro para a variável
de ponteiro que
armazenará o endereço
n
Armazena o número de caracteres
inseridos até esse ponto da chamada a
scanf()
Ponteiro para um int
% Salta o sinal de porcentagem (%) na entrada N/A
Quadro 22 – Especificadores de conversão. Fonte: Deitel (2011).
45WWW.UNINGA.BR
AL
GO
RI
TM
OS
E
P
RO
GR
AM
AÇ
ÃO
A
PL
IC
AD
A
| U
NI
DA
DE
1
EDUCAÇÃO A DISTÂNCIA
Para usar a função scanf() em um programa, devemos incluir o arquivo de cabeçalho
padrão stdio.h, conforme explicado na seção 2.4 desta unidade. O Quadro 23 a seguir apresenta
um programa completo que ilustra diversos exemplos de entrada de dados usando scanf().
#include <stdio.h>
int main(void) {
char nome[30], nota;
float altura;
int dia, mes, ano;
printf(“Digite o seu nome: “);
scanf(“%s”, nome);
printf(“Digite a altura: “);
scanf(“%f”, &altura);
printf(“Nascimento (DD/MM/AAAA): “);
scanf(“%d/%d/%d”, &dia, &mes, &ano);
printf(“Digite a nota (A-E): “);
fflush(stdin); // Para prevenir o bug de não editar
scanf(“%c”, ¬a);
return 0;
}
Quadro 23 – Exemplos de entrada de dados. Fonte: O autor.
O endereço de memória de cada variável deve ser passado como parâmetro para a função
scanf(), para que o valor digitado possa ser armazenado nela. Para isso, utilizamos o operador &;
a única exceção no exemplo do Quadro 23 é a variável nome, que é um vetor de 30 elementos do
tipo char – abordamos strings com detalhes na Unidade III. No caso da data de nascimento, temos
três especificadores %d para a entrada respectiva do dia, mês e ano; por isso temos os endereços
destas variáveis sendo passados na mesma ordem em que aparecem na string de entrada. Para
concluir, a instrução fflush(stdin); será colocada antes de cada entrada caractere ou string, para
prevenir um possível bug no buffer de entrada desses tipos de dados, dependendo do compilador
C usado.
46WWW.UNINGA.BR
AL
GO
RI
TM
OS
E
P
RO
GR
AM
AÇ
ÃO
A
PL
IC
AD
A
| U
NI
DA
DE
1
EDUCAÇÃO A DISTÂNCIA
6.2 Saída de Dados
A função printf() é a responsável pela impressão de dados em um dispositivo de saída –
por padrão da tela do monitor. Segundo Deitel (2011), sua sintaxe é idêntica à da função scanf():
printf( string-de-controle-de-formato, outros-argumentos );
Os especificadores de formato apresentados na seção anterior também são válidos para
uso na função printf(), seguindo a mesma lógica de que cada um é acompanhado de uma variável
como parâmetro na ordem em que foram especificados na string.
Além dos especificadores de formato, é possível também utilizar caracteres especiais de
controle, como tabulação e quebra de linha. Chamados de sequência de escape, são representados
pelo caractere de barra invertida “\” seguidos do referido caractere de escape (DEITEL, 2011). O
Quadro 24 a seguir apresenta as sequências de escape disponíveis.
Sequência de escape Descrição
\' Exibe o caractere de aspas simples (')
\" Exibe o caractere de aspas duplas (")
\? Exibe o caractere de ponto de interrogação (?)
\\ Exibe o caractere de barra invertida (\)
\a Causa alerta audível(campainha) ou visual
\b Move o cursor uma posição para trás na linha atual
\f Move o cursor para o início da página seguinte
\n Move o cursor para o início da linha seguinte
\r Move o cursor para o início da linha atual
\t Move o cursor para a posição de tabulação horizontal seguinte
\v Move o cursor para a posição de tabulação vertical seguinte
Quadro 24 – Sequências de escape. Fonte: Deitel (2011).
47WWW.UNINGA.BR
AL
GO
RI
TM
OS
E
P
RO
GR
AM
AÇ
ÃO
A
PL
IC
AD
A
| U
NI
DA
DE
1
EDUCAÇÃO A DISTÂNCIA
O programa ilustrado no Quadro 25 a seguir complementa o programa do Quadro 23,
com exemplos de exibição de dados literais e conteúdos de variáveis.
#include <stdio.h>
int main(void) {
char nome[30], nota;
float altura;
int dia, mes, ano;
printf(“Digite o seu nome: “);
scanf(“%s”, nome);
printf(“Digite a altura: “);
scanf(“%f”, &altura);
printf(“Nascimento (DD/MM/AAAA): “);
scanf(“%d/%d/%d”, &dia, &mes, &ano);
fflush(stdin); // Para prevenir o bug de não editar
printf(“Digite a nota (A-E): “);
scanf(“%c”, ¬a);
// Saída de dados
printf(“\nSeu nome eh %s”, nome);
printf(“\nVoce tem %.2f de altura”, altura);
printf(“\ne nasceu no dia %d do mes %.2d do ano de %d”,
dia, mes, ano);
printf(“\nVoce tirou nota %c\n”, nota);
return 0;
}
Quadro 25 – Exemplos de saída de dados. Fonte: O autor.
48WWW.UNINGA.BR
AL
GO
RI
TM
OS
E
P
RO
GR
AM
AÇ
ÃO
A
PL
IC
AD
A
| U
NI
DA
DE
1
EDUCAÇÃO A DISTÂNCIA
Repare na possibilidade de formatar os dados numéricos informando a precisão do
número a ser apresentado na tela. O resultado da execução desse código é ilustrado na Figura 7
a seguir.
Figura 7 – Resultado da execução do programa do Quadro 25. Fonte: O autor.
Vamos agora reescrever em C o algoritmo da soma de dois números, usado como exemplo
na seção 1 para demonstrar as formas de representação de algoritmos. O Quadro 26 a seguir
mostra a codificação deste programa.
#include <stdio.h>
int main(void) {
int num1, num2;
printf(“Digite o primeiro numero: “);
scanf(“%d”, &num1);
printf(“Digite o segundo numero.: “);
scanf(“%d”, &num2);
printf(“Soma dos dois numeros...: %d\n”, num1 + num2);
return 0;
}
Quadro 26 – Programa para somar dois números. Fonte: O autor.
49WWW.UNINGA.BR
AL
GO
RI
TM
OS
E
P
RO
GR
AM
AÇ
ÃO
A
PL
IC
AD
A
| U
NI
DA
DE
1
EDUCAÇÃO A DISTÂNCIA
Nesse exemplo, poderíamos como alternativa armazenar a soma em uma terceira variável
e passá-la como parâmetro para a função printf(). Repare nos exemplos apresentados que as
variáveis devem ser declaradas logo no início da função, sob pena de erro na hora da compilação.
Esse livro traz um dos estudos mais completos sobre
a linguagem C, abordando vários assuntos básicos e
também de cunho avançado, como manipulação de
bits e arquivos, pré-processador, dentre outros.
Seu conteúdo enfatiza a obtenção de clareza nos
programas por meio de técnicas comprovadas da
programação estruturada.
DEITEL, P. J. C: como programar. Tradução: Daniel
Vieira. 6. ed. São Paulo: Pearson Prentice Hall, 2011.
Fonte: Deitel (2011).
50WWW.UNINGA.BR
AL
GO
RI
TM
OS
E
P
RO
GR
AM
AÇ
ÃO
A
PL
IC
AD
A
| U
NI
DA
DE
1
EDUCAÇÃO A DISTÂNCIA
CONSIDERAÇÕES FINAIS
Nesta unidade, foi dado o pontapé inicial para o aprendizado de lógica de programação
através do estudo dos seus elementos básicos. Iniciamos descrevendo o conceito de algoritmo e
as suas formas de representação para solucionar um determinado problema.
Em seguida abordamos os programas, que são os algoritmos escritos em uma linguagem
de programação e traduzidos para linguagem de máquina. Também apresentamos os dois tipos de
ferramentas existentes para esta finalidade, os compiladores e os interpretadores, e introduzimos
a linguagem de programação C.
A partir daí, já no contexto da linguagem, abordamos os tipos de dados existentes, as
constantes e variáveis, as expressões e os operadores disponíveis para a construção de código de
processamento.
Finalizamos a unidade abordando as funções para entrada e saída de dados na tela do
computador.
5151WWW.UNINGA.BR
U N I D A D E
02
SUMÁRIO DA UNIDADE
INTRODUÇÃO ...............................................................................................................................................................53
1 ESTRUTURAS DE SELEÇÃO .....................................................................................................................................54
1.1 ESTRUTURA DE SELEÇÃO SIMPLES ....................................................................................................................54
1.2 ESTRUTURA DE SELEÇÃO COMPOSTA ...............................................................................................................56
1.3 CONDIÇÃO TERNÁRIA ...........................................................................................................................................58
1.4 ENCADEAMENTO DE IFS ......................................................................................................................................60
1.5 ESTRUTURAS DE SELEÇÃO MÚLTIPLA ...............................................................................................................63
2 ESTRUTURAS DE REPETIÇÃO ................................................................................................................................67
2.1 ESTRUTURAS DE REPETIÇÃO COM LAÇOS CONTADOS ...................................................................................68
2.2 ESTRUTURAS DE REPETIÇÃO ASSOCIADAS A UMA CONDIÇÃO..................................................................... 71
2.2.1 ESTRUTURAS DE REPETIÇÃO COM CONDIÇÃO NO INÍCIO .......................................................................... 71
ESTRUTURAS DE SELEÇÃO E REPETIÇÃO
PROF. FÁBIO ATAIDE DE LIMA
ENSINO A DISTÂNCIA
DISCIPLINA:
ALGORITMOS E PROGRAMAÇÃO APLICADA
52WWW.UNINGA.BR
EDUCAÇÃO A DISTÂNCIA
2.2.2 ESTRUTURAS DE REPETIÇÃO COM CONDIÇÃO NO FINAL ........................................................................... 72
2.3 INTERVENÇÃO NO FLUXO DOS LAÇOS DE REPETIÇÃO .................................................................................... 73
2.3.1 COMANDO BREAK .............................................................................................................................................. 73
2.3.2 COMANDO CONTINUE ......................................................................................................................................74
CONSIDERAÇÕES FINAIS ...........................................................................................................................................76
53WWW.UNINGA.BR
AL
GO
RI
TM
OS
E
P
RO
GR
AM
AÇ
ÃO
A
PL
IC
AD
A
| U
NI
DA
DE
2
EDUCAÇÃO A DISTÂNCIA
INTRODUÇÃO
Até o momento, vimos exemplos de programas sendo executados de maneira sequencial,
ou seja, um comando sendo executado após o outro até o término de seu processamento. Contudo,
existem muitos algoritmos que requerem que uma condição seja analisada e tomar um de dois ou
mais caminhos possíveis, ou seja, um desvio de fluxo. Além disso, alguns algoritmos requerem
que um determinado conjunto de instruções seja executado novamente um determinado número
de vezes ou de acordo com uma condição.
Para essas finalidades, existem as estruturas de seleção e de repetição, as quais serão
abordadas com detalhes nesta unidade. Daremos início abordando a estrutura de seleção simples
e composta, que seria um SE simples e um SE com SENÃO, respectivamente. Em C, essa estrutura
é representada pelo comando if.
Em seguida, explicaremos o funcionamento do operador C de condição ternária, usado
para simplificar comandos if em expressões que podem ser usadas em outros comandos.
Em seguida, abordaremos as estruturas de seleção múltipla, que permitem a escolhadentre mais de dois caminhos disponíveis, de acordo com uma condição a ser avaliada. Em
C, esse objetivo é alcançado de duas formas: encadeando vários ifs seguidamente ou usando o
comando switch.
Por fim, serão abordadas as estruturas responsáveis por permitir que um trecho de código
possa ser repetido quantas vezes forem necessárias ou enquanto uma condição for satisfeita. Em
C, essas estruturas são implementadas pelos comandos for, while e do...while.
54WWW.UNINGA.BR
AL
GO
RI
TM
OS
E
P
RO
GR
AM
AÇ
ÃO
A
PL
IC
AD
A
| U
NI
DA
DE
2
EDUCAÇÃO A DISTÂNCIA
1 ESTRUTURAS DE SELEÇÃO
A lógica de programação é como o nosso cotidiano: em alguns momentos, surge a
necessidade de tomar decisões. Para se fazer isso em lógica, utilizamos as estruturas de seleção,
também conhecidas como estruturas de controle condicional ou estruturas de controle alternativo
(XAVIER, 2011).
Para se ter uma ideia melhor referente a essas estruturas, Lopes e Garcia (2002) deixam
um exemplo com três afirmações:
1. Distribuição gratuita de cestas básicas.
2. Distribuição gratuita de cestas básicas para famílias com 4 ou mais componentes.
3. Distribuição gratuita de ingressos para o teatro, sendo dois para pessoas do sexo
feminino e um para pessoas do sexo masculino (LOPES; GARCIA, 2002, p. 60).
Observando cada uma delas, conclui-se que a primeira seria implementada por meio
de um programa sequencial, a segunda seria implementada usando uma estrutura de seleção
simples e a terceira, por fim, uma estrutura de seleção composta.
1.1 Estrutura de Seleção Simples
Na estrutura de seleção simples, se uma condição for avaliada como verdadeira, será
executado o bloco de instruções compreendido pela estrutura; do contrário, o programa “pula”
esse bloco de instruções e passa para o comando seguinte à estrutura (XAVIER, 2011).
Na Figura 1 a seguir, temos a representação da segunda afirmação da seção anterior,
“distribuição gratuita de cestas básicas para famílias com 4 ou mais componentes”, utilizando
estrutura de seleção simples no formato de fluxograma.
Figura 1 – Estrutura de seleção simples em fluxograma. Fonte: O autor.
55WWW.UNINGA.BR
AL
GO
RI
TM
OS
E
P
RO
GR
AM
AÇ
ÃO
A
PL
IC
AD
A
| U
NI
DA
DE
2
EDUCAÇÃO A DISTÂNCIA
A estrutura de seleção simples é implementada em C por meio do comando if, cuja sintaxe
é descrita no Quadro 1 a seguir.
if (condição)
instrução;
if (condição)
{
instrução 1;
instrução 2;
instrução 3;
...
}
Quadro 1 – Sintaxe do comando if. Fonte: Adaptado de Schildt (1996).
A condição deve estar obrigatoriamente entre parênteses e representa uma expressão que
resultará em zero – falso – ou qualquer valor diferente de zero – verdadeiro; pode ser qualquer
tipo de expressão apresentada na Unidade I: aritmética, relacional ou lógica. Embora o uso das
chaves seja obrigatório no caso de mais de uma instrução dentro do if, elas são opcionais no caso
de apenas uma instrução, podendo ser suprimidas.
Outro ponto importante a considerar no Quadro 1 é o uso da indentação ao estruturar
os blocos de instruções dentro do comando. A maioria dos IDEs adota 4 espaços por padrão em
relação à linguagem C, e vamos seguir esse padrão em nossos exemplos.
No programa de exemplo apresentado no Quadro 2 a seguir, se o número informado for
maior que 10, então é mostrado o aviso na tela; caso contrário, nada é mostrado.
#include <stdio.h>
int main(void) {
int a;
printf(“Digite um numero: “);
scanf(“%d”, &a);
if (a > 10)
printf(“a eh maior que 10”);
return 0;
}
Quadro 2 – Programa com estrutura de seleção simples. Fonte: O autor.
Segundo Manzano e Oliveira (2012), indentação é o processo de descolar um
trecho de código para a direita com o objetivo de indicar que sua execução está
subordinada a um desvio condicional, a uma estrutura de repetição ou a uma sub-
rotina – procedimento ou função. Essa atitude na escrita do código deixa-o mais
claro e legível, e será requisito básico na resolução de atividades, exercícios e
avaliações da disciplina.
56WWW.UNINGA.BR
AL
GO
RI
TM
OS
E
P
RO
GR
AM
AÇ
ÃO
A
PL
IC
AD
A
| U
NI
DA
DE
2
EDUCAÇÃO A DISTÂNCIA
Conforme já explicado na unidade anterior, é possível distribuir os comandos de diversas
maneiras em uma linha. Para exemplificar isso, ilustramos no Quadro 3 a seguir as várias formas
possíveis de escrever o if do Quadro 2.
if (a > 10) printf("A e maior que 10");
if (a > 10) { printf("A e maior que 10"); }
if (a > 10)
{ printf("A e maior que 10"); }
if (a > 10) {
printf("A e maior que 10"); }
if (a > 10)
{
printf("A e maior que 10");
}
if (a > 10) {
printf("A e maior que 10");
}
Quadro 3 – Formas possíveis de escrita de um if em C. Fonte: O autor.
O aluno fique à vontade para escolher a forma de sua preferência. Assumiremos em
nossos exemplos a última forma do Quadro 3 em ifs com duas ou mais instruções e a supressão
das chaves em ifs com uma só instrução.
1.2 Estrutura de Seleção Composta
A estrutura de seleção composta é formada por dois blocos de instruções. Se uma condição
for avaliada como verdadeira, o primeiro bloco de instruções será executado; se for avaliada
como falsa, o segundo bloco de instruções será executado (MANZANO; OLIVEIRA, 2012).
Na Figura 2 a seguir, temos a representação da terceira afirmação da seção
1 desta unidade, “distribuição gratuita de ingressos para o teatro, sendo dois para
pessoas do sexo feminino e um para pessoas do sexo masculino”, utilizando estrutura de seleção
composta em formato de fluxograma.
Figura 2 – Estrutura de seleção composta em fluxograma. Fonte: O autor.
57WWW.UNINGA.BR
AL
GO
RI
TM
OS
E
P
RO
GR
AM
AÇ
ÃO
A
PL
IC
AD
A
| U
NI
DA
DE
2
EDUCAÇÃO A DISTÂNCIA
O comando if possui uma instrução opcional que permite a implementação da estrutura
de seleção composta em C, cuja sintaxe é descrita no Quadro 4 a seguir.
if (condição)
instrução;
else
instrução;
if (condição)
{
instrução 1;
instrução 2;
instrução 3;
...
}
else
{
instrução 1;
instrução 2;
instrução 3;
...
}
Quadro 4 – Sintaxe do comando if...else. Fonte: Adaptado de Schildt (1996).
Se a avaliação da condição for verdadeira, a instrução ou o bloco entre o if e o else é
executada; se a avaliação for falsa, a instrução ou o bloco logo após o else é executada.
O Quadro 5 a seguir apresenta um programa que verifica se o número digitado pelo
usuário é par ou ímpar.
#include <stdio.h>
int main(void) {
int n;
printf(“Digite um numero: “);
scanf(“%d”, &n);
if (n % 2 == 0)
printf(“O numero e par”);
else
printf(“O numero e impar”);
return 0;
}
Quadro 5 – Programa com estrutura de seleção composta. Fonte: O autor.
Nesse exemplo, usamos o operador de resto de divisão (%): se o resultado da divisão do
número digitado por 2 tiver resto 0, então ele é par; se tiver resto 1, então ele é impar. Portanto, se
o usuário entrar com o número 6, o programa imprimirá na tela “O número é par”; se ele entrar
com o número 5, o programa imprimirá na tela “O número é ímpar”.
58WWW.UNINGA.BR
AL
GO
RI
TM
OS
E
P
RO
GR
AM
AÇ
ÃO
A
PL
IC
AD
A
| U
NI
DA
DE
2
EDUCAÇÃO A DISTÂNCIA
A regra para o uso das chaves também se aplica ao bloco de instruções seguinte ao else,
de forma independente ao bloco de instruções seguinte ao if. Isso significa que as chaves podem
ser omitidas no caso de apenas uma instrução no if, no else ou em ambos. O Quadro 6 a seguir
ilustra algumas formas alternativas para o if...else usado no Quadro 5.
if (n % 2 == 0) printf("O numero e par");
else printf("O numero e impar");
if (n % 2 == 0) {
printf("Numero par"); }
else printf("Numero impar");
if (n % 2 == 0)
{
printf("Numero par");
}
else
{
printf("Numero impar");
}
if (n % 2 == 0)
printf("Numero par");
else {
printf("Numero impar"); }
if (n % 2 == 0) {
printf("Numero par");
}
else {
printf("Numeroimpar");
}
if (n % 2 == 0) {
printf("Numero par");
} else {
printf("Numero impar");
}
Quadro 6 – Formas possíveis de escrita de um if...else em C. Fonte: O autor.
1.3 Condição Ternária
A linguagem C oferece o operador de condição ternária ?:, que tem funcionamento
idêntico a um if...else. Sua sintaxe é a seguinte:
condição ? expressão_se_1 : expressão_se_0
Se condição for avaliada como verdadeira, é retornada ou executada expressão_se_1;
se for avaliada como falsa, é retornada ou executada expressão_se_0. Este operador serve para
simplificar blocos if...else em apenas uma linha de instrução, conforme ilustrado no Quadro 7 a
seguir com o if exemplificado na seção anterior.
printf("Numero %s", n % 2 == 0 ? "par" : "impar");
printf(n % 2 == 0 ? "Numero par" : "Numero impar");
n % 2 == 0 ? printf("Numero par") : printf("Numero impar");
Quadro 7 – Exemplos de uso do operador de condição ternária. Fonte: O autor.
59WWW.UNINGA.BR
AL
GO
RI
TM
OS
E
P
RO
GR
AM
AÇ
ÃO
A
PL
IC
AD
A
| U
NI
DA
DE
2
EDUCAÇÃO A DISTÂNCIA
É possível que haja mais de um comando nas expressões de retorno do operador de
condição ternária, bastando para isso colocá-los entre parênteses e separá-los por vírgulas.
Entretanto, o código perde em legibilidade e, neste caso, é preferível usar um bloco de if...else,
pois deixa o código mais claro e compreensível de se ler. Veja a diferença no exemplo do Quadro
8 a seguir.
nota >= 6 ? (result = 'A', printf("Aprovado")) :
(result = 'R', printf("Reprovado"));
if (nota >= 6) {
result = ‘A’;
printf(“Aprovado”);
} else {
result = ‘R’;
printf(“Reprovado”);
}
Quadro 8 – Condição ternária e if...else com mais de uma instrução. Fonte: O autor.
60WWW.UNINGA.BR
AL
GO
RI
TM
OS
E
P
RO
GR
AM
AÇ
ÃO
A
PL
IC
AD
A
| U
NI
DA
DE
2
EDUCAÇÃO A DISTÂNCIA
1.4 Encadeamento de ifs
É possível utilizar quantos comandos ifs forem necessários em um programa, além de
poder encadeá-los da forma como melhor aprouver. Isso auxilia em problemas que requeiram
vários testes e comparações (XAVIER, 2011).
Para exemplificar isso, vamos implementar um programa que leia três números do usuário
e apresente o valor do maior digitado. Esse programa terá dois processamentos diferentes: um
utilizando dois ifs em sequência e outro utilizando um if encadeado em outro.
Portanto, a entrada e a saída de dados serão apresentadas apenas uma vez no exemplo
e a parte onde é feita a descoberta do maior número será dividida de modo que as duas lógicas
fiquem lado a lado. Isso permite que possamos comparar as diferenças entre os processamentos.
O Quadro 9 a seguir apresenta a codificação desse programa.
#include <stdio.h>
int main(void) {
int num1, num2, num3, maior;
printf(“Digite o numero 1: “);
scanf(“%d”, &num1);
printf(“Digite o numero 2: “);
scanf(“%d”, &num2);
printf(“Digite o numero 3: “);
scanf(“%d”, &num3);
maior = num1;
if (maior < num2)
maior = num2;
if (maior < num3)
maior = num3;
if (num1 > num2)
if (num1 > num3)
maior = num1;
else
maior = num3;
else
if (num2 > num3)
maior = num2;
else
maior = num3;
printf(“O maior numero eh: %d”, maior);
return 0;
}
Quadro 9 – Programa implementado com duas lógicas semelhantes. Fonte: O autor.
Repare que ambas cumprem o mesmo objetivo de descobrir o maior número, porém
os ifs em sequência geram um código menor do que os ifs encadeados. Por outro lado, os ifs
encadeados efetuam um menor número de instruções, já que apenas uma operação de atribuição
é realizada, ao passo que nos ifs em sequência podem ser feitas de 1 a 3 atribuições. A escolha da
melhor lógica a ser aplicada dependerá muito dos fatores do programa e do programador que o
escreve.
61WWW.UNINGA.BR
AL
GO
RI
TM
OS
E
P
RO
GR
AM
AÇ
ÃO
A
PL
IC
AD
A
| U
NI
DA
DE
2
EDUCAÇÃO A DISTÂNCIA
É possível fazer uma estrutura de ifs encadeados para tratar mais de dois desvios no fluxo
do programa, fazendo com que cada else abra opção para um novo desvio. Entretanto, com a
endentação, esse código ficará muito “deslocado” para a direita, como demonstrado no exemplo
do Quadro 10 a seguir para obter o dia da semana por extenso.
#include <stdio.h>
int main(void) {
int dia;
printf(“Informe o dia da semana (1-7): “);
scanf(“%d”, &dia);
if (dia == 1)
printf(“Domingo”);
else
if (dia == 2)
printf(“Segunda-feira”);
else
if (dia == 3)
printf(“Terca-feira”);
else
if (dia == 4)
printf(“Quarta-feira”);
else
if (dia == 5)
printf(“Quinta-feira”);
else
if (dia == 6)
printf(“Sexta-feira”);
else
if (dia == 7)
printf(“Sabado”);
else
printf(“Dia invalido”);
return 0;
}
Quadro 10 – Programa com vários ifs encadeados. Fonte: O autor.
62WWW.UNINGA.BR
AL
GO
RI
TM
OS
E
P
RO
GR
AM
AÇ
ÃO
A
PL
IC
AD
A
| U
NI
DA
DE
2
EDUCAÇÃO A DISTÂNCIA
Uma alternativa para evitar esse deslocamento seria iniciar o if seguinte na mesma linha
do else, conforme ilustrado no Quadro 11 a seguir.
#include <stdio.h>
int main(void) {
int dia;
printf(“Informe o dia da semana (1-7): “);
scanf(“%d”, &dia);
if (dia == 1)
printf(“Domingo”);
else if (dia == 2)
printf(“Segunda-feira”);
else if (dia == 3)
printf(“Terca-feira”);
else if (dia == 4)
printf(“Quarta-feira”);
else if (dia == 5)
printf(“Quinta-feira”);
else if (dia == 6)
printf(“Sexta-feira”);
else if (dia == 7)
printf(“Sabado”);
else
printf(“Dia invalido”);
return 0;
}
Quadro 11 – Programa com vários ifs encadeados evitando indentações. Fonte: O autor.
Apesar de nesse exemplo do Quadro 10 termos evitado o deslocamento ocorrido no
Quadro 9, o custo de processamento permanece o mesmo em relação às comparações que devem
ser feitas, dependendo do valor digitado. Para otimizar isso, temos as estruturas de seleção
múltipla, abordadas na seção seguinte.
63WWW.UNINGA.BR
AL
GO
RI
TM
OS
E
P
RO
GR
AM
AÇ
ÃO
A
PL
IC
AD
A
| U
NI
DA
DE
2
EDUCAÇÃO A DISTÂNCIA
1.5 Estruturas de Seleção Múltipla
As estruturas de seleção múltipla também são conhecidas como tomada de decisão por
seleção, segundo Manzano e Oliveira (2012):
A tomada de decisão por seleção é uma alternativa mais rápida ao uso de tomadas
de decisão sequenciais ou encadeadas. Essa estrutura lógica de condição é útil e
pode ser usada em situações em que se possui um grande número de verificações
lógicas a serem realizadas (MANZANO; OLIVEIRA, 2012, p. 73).
Nesse tipo de estrutura, as condições são avaliadas na sequência em que foram definidas.
Caso a avaliação seja falsa, o programa avalia a condição seguinte; caso seja verdadeira, o programa
executará o bloco de instruções referente àquela condição e depois desvia o fluxo para a primeira
instrução após o final da estrutura (MANZANO; OLIVEIRA, 2012).
Na Figura 3 a seguir, temos a representação da estrutura de seleção múltipla no formato
de fluxograma.
Figura 3 – Estrutura de seleção múltipla em fluxograma. Fonte: O autor.
64WWW.UNINGA.BR
AL
GO
RI
TM
OS
E
P
RO
GR
AM
AÇ
ÃO
A
PL
IC
AD
A
| U
NI
DA
DE
2
EDUCAÇÃO A DISTÂNCIA
A estrutura de seleção múltipla é implementada em C por meio do comando switch, cuja
sintaxe é descrita no Quadro 12 a seguir.
switch (expressão)
{
case constante1:
instruções;
break;
case constante2:
instruções;
break;
case constante3:
instruções;
break;
default:
instruções;
}Quadro 12 – Sintaxe do comando switch. Fonte: Adaptado de Schildt (1996).
A expressão deve obrigatoriamente estar entre parênteses e resultar em um valor do tipo
char ou int – pode ser uma variável, um retorno de função ou um cálculo aritmético. A partir daí,
ele verifica o valor de cada case, na ordem especificada, para ver se é igual ao valor da expressão
recebida: em caso negativo, verificará o case seguinte; em caso positivo, executará as instruções
contidas nele e também dos cases subsequentes até encontrar um comando break, responsável
por “sair” da estrutura; a instrução default é opcional e executará suas instruções no caso de
nenhum case ter sido executado (SCHILDT, 1996; DEITEL, 2011).
65WWW.UNINGA.BR
AL
GO
RI
TM
OS
E
P
RO
GR
AM
AÇ
ÃO
A
PL
IC
AD
A
| U
NI
DA
DE
2
EDUCAÇÃO A DISTÂNCIA
Esse comportamento torna o comando switch mais rápido do que um conjunto de ifs
encadeados. O Quadro 13 a seguir ilustra o exemplo do dia da semanda por extenso, usado na
seção anterior, adaptado para o comando switch.
#include <stdio.h>
int main(void) {
int dia;
printf(“Informe o dia da semana (1-7): “);
scanf(“%d”, &dia);
switch (dia) {
case 1:
printf(“Domingo”);
break;
case 2:
printf(“Segunda-feira”);
break;
case 3:
printf(“Terca-feira”);
break;
case 4:
printf(“Quarta-feira”);
break;
case 5:
printf(“Quinta-feira”);
break;
case 6:
printf(“Sexta-feira”);
break;
case 7:
printf(“Sabado”);
break;
default:
printf(“Dia invalido”);
}
return 0;
}
Quadro 13 – Programa com estrutura de seleção múltipla. Fonte: O autor.
No próximo exemplo, obtemos o número de dias de um mês e ano informado pelo
usuário usando um comando switch e o operador ternário em uma de suas opções. O programa
é ilustrado no Quadro 14 a seguir.
66WWW.UNINGA.BR
AL
GO
RI
TM
OS
E
P
RO
GR
AM
AÇ
ÃO
A
PL
IC
AD
A
| U
NI
DA
DE
2
EDUCAÇÃO A DISTÂNCIA
#include <stdio.h>
int main(void) {
int mes, ano, dias = 0;
printf(“Informe o mes e o ano (MM/AAAA): “);
scanf(“%d/%d”, &mes, &ano);
switch (mes) {
case 2:
dias = ano % 4 ? 28 : 29;
break;
case 4:
case 6:
case 9:
case 11:
dias = 30;
break;
case 1:
case 3:
case 5:
case 7:
case 8:
case 10:
case 12:
dias = 31;
}
if (dias)
printf(“O mes informado tem %d dias\n”, dias);
else
printf(“O mes informado eh invalido\n”);
return 0;
}
Quadro 14 – Programa para obter o número de dias do mês. Fonte: O autor.
Se o usuário digitar, por exemplo:
• “02/2019”: 2 será armazenado em mes e 2019 será armazenado em ano. Portanto, o
programa entrará no primeiro case, pois a comparação de mes com 2 resultará em
verdadeiro. De acordo com a condição ternária, será armazenado o valor 28 em dias
porque ano % 4 resultará em 1, pois o resto da divisão de 2019 por 4 é 3 – lembre-se de
que qualquer valor diferente de 0 é verdadeiro em C.
• “02/2020”: será armazenado o valor 29 na variável dias, pois ano % 4 resultará em 0 –
2020 dividido por 4 tem resto zero – e será avaliado como falso pelo operador de condição
ternária.
• “04/2020”: o programa passará o primeiro case e entrará no segundo, com a comparação
por 4. Como não há instrução nenhuma senão cases subsequentes, o fluxo segue até a
primeira instrução não-case, que é a atribuição de 30 na variável dias. Depois disto vem
um break e então o fluxo é desviado para depois do bloco.
• “12/2020”: o programa passará por todos os cases até chegar no último, onde será
avaliado em verdadeiro. Nele, é armazenado o valor 31 na variável dias.
67WWW.UNINGA.BR
AL
GO
RI
TM
OS
E
P
RO
GR
AM
AÇ
ÃO
A
PL
IC
AD
A
| U
NI
DA
DE
2
EDUCAÇÃO A DISTÂNCIA
• Mês fora da faixa entre 1 e 12: o programa não executará nenhuma instrução do switch
devido à ausência da instrução default no bloco e imprimirá que o mês informado é
inválido, devido à variável dias estar valendo 0.
2 ESTRUTURAS DE REPETIÇÃO
As estruturas de repetição também são conhecidas como laços ou malhas de repetição,
além de seus termos em inglês loop e looping. De acordo com Manzano e Oliveira (2012, p. 101),
são “uma técnica de programação que possibilita repetir um trecho de programa, sem que seja
necessário escrevê-lo exatamente o número de vezes que se deseja de fato executar”. Na Figura 4
a seguir, temos a representação da estrutura de repetição no formato de fluxograma.
Figura 4 – Estrutura de repetição em fluxograma. Fonte: Manzano e Oliveira (2012).
Algumas linguagens de programação oferecem uma variação do
comando for para percorrer estruturas de dados, como vetores,
matrizes, registros e itens de coleções. Em C#, por exemplo,
esse tipo de estrutura é implementado pelo comando foreach;
mais informações sobre ele podem ser encontradas no link do
Microsoft Docs, disponível em:
https://docs.microsoft.com/pt-br/dotnet/csharp/language-
reference/keywords/foreach-in
https://docs.microsoft.com/pt-br/dotnet/csharp/language-reference/keywords/foreach-in
https://docs.microsoft.com/pt-br/dotnet/csharp/language-reference/keywords/foreach-in
68WWW.UNINGA.BR
AL
GO
RI
TM
OS
E
P
RO
GR
AM
AÇ
ÃO
A
PL
IC
AD
A
| U
NI
DA
DE
2
EDUCAÇÃO A DISTÂNCIA
Podem existir quantas estruturas de repetição forem necessárias para repetir trechos de
um programa, ou mesmo o programa inteiro, sendo que o número de repetições pode ser fixo ou
associado a uma condição (ASCENCIO; CAMPOS, 2010). Em C, as estruturas de repetição que
repetem um número determinado de vezes são implementadas pelo comando for e as estruturas
associadas a uma condição, pelos comandos while e do...while.
2.1 Estruturas de Repetição com Laços Contados
O comando for é uma estrutura em C do tipo laço contado e é utilizado quando sabemos
previamente o número de vezes que o trecho de código precisa ser repetido. Sua sintaxe é descrita
no Quadro 15 a seguir.
for (variável = valor_inicial; condição; incremento/decremento)
{
instruções;
}
Quadro 15 – Sintaxe do comando for. Fonte: Adaptado de Schildt (1996).
Entre os parênteses após o for, temos três expressões:
• Na primeira expressão, variável será inicializada com valor_inicial e usada para controlar
o número de repetições;
• Na segunda expressão, condição é uma expressão relacional que, ao assumir valor falso,
determinará o fim da repetição;
• Na terceira expressão, incremento/decremento atualiza o valor da variável de controle da
repetição, ao final de cada iteração.
As instruções são os comandos a serem repetidos no laço e é recomendado que estejam
indentadas, para facilitar a leitura do código. Assim como na estrutura if, as chaves podem ser
suprimidas no caso de uma instrução apenas.
69WWW.UNINGA.BR
AL
GO
RI
TM
OS
E
P
RO
GR
AM
AÇ
ÃO
A
PL
IC
AD
A
| U
NI
DA
DE
2
EDUCAÇÃO A DISTÂNCIA
O Quadro 16 a seguir apresenta como exemplo um programa que pede um número e
imprime a sua tabuada, usando um laço contado para multiplicá-lo por 1 a 10.
#include <stdio.h>
int main(void) {
int num, i;
printf(“Digite um numero: “);
scanf(“%d”, &num);
for (i = 1; i <= 10; i++)
printf(“%d x %d = %d\n”, num, i, num * i);
return 0;
}
Quadro 16 – Programa com estrutura de laços contados. Fonte: O autor.
Geralmente, adotam-se variáveis de nomes bem curtos, como apenas uma letra, para
controlar o laço de repetição – i de inteiro no caso do Quadro 16 – por maior conveniência na
manipulação de vetores, assunto da próxima unidade. Repare que esta variável deve ser declarada
no início da função, para poder compilar sem erros; alguns compiladores, contudo, permitem
que a variável seja declarada dentro dos parênteses,como por exemplo: for (int i = 1; i <= 10;
i++).
Dentro dos parênteses, i é inicializada com 1. O laço terminará sua repetição quando esta
variável chegar a um valor maior que 10, sendo que seu incremento será de 1 em 1. A Figura 5 a
seguir ilustra o resultado do processamento do programa do Quadro 16.
Figura 5 – Resultado do programa de tabuada. Fonte: O autor.
70WWW.UNINGA.BR
AL
GO
RI
TM
OS
E
P
RO
GR
AM
AÇ
ÃO
A
PL
IC
AD
A
| U
NI
DA
DE
2
EDUCAÇÃO A DISTÂNCIA
É possível controlar mais de uma variável em uma estrutura for. Para isso, basta separar
por vírgulas a inicialização e o incremento ou decremento das variáveis na primeira e na terceira
expressão, respectivamente. O Quadro 17 a seguir exemplifica essa situação.
#include <stdio.h>
int main(void) {
int num, i, d;
printf(“Digite um numero: “);
scanf(“%d”, &num);
for (i = 1, d = num; i <= num; i++, d--)
printf(“i = %d, d = %d\n”, i, d);
return 0;
}
Quadro 17 – Programa com laço controlado por duas variáveis. Fonte: O autor.
Esse programa pede um número, incrementa uma variável e decrementa outra, usando o
mesmo laço de repetição. O resultado desse programa é ilustrado na Figura 6 a seguir.
Figura 6 – Resultado da execução do programa do Quadro 17. Fonte: O autor.
Um detalhe importante sobre o comando for é que todas as expressões entre parênteses
são opcionais. Isso significa que uma variável já existente e com um valor pode ser usada para
iniciar o controle do laço; também significa que o laço pode ser forçadamente encerrado com
break, conforme abordado na seção 2.3; e também que o incremento pode ser feito dentro do
bloco de repetição ao invés de dentro dos parênteses. Todavia, embora as expressões possam ser
suprimidas, os dois ponto-e-vírgula permanecem obrigatórios dentro dos parênteses (SCHILDT,
1996).
71WWW.UNINGA.BR
AL
GO
RI
TM
OS
E
P
RO
GR
AM
AÇ
ÃO
A
PL
IC
AD
A
| U
NI
DA
DE
2
EDUCAÇÃO A DISTÂNCIA
2.2 Estruturas de Repetição Associadas a uma Condição
Existem situações em que não é possível determinar previamente quantas vezes um
trecho de código deve ser repetido em um programa. Essas situações dependem da avaliação de
uma condição em particular.
Os comandos while e do...while da linguagem C são os responsáveis pela repetição de
instruções de acordo com a avaliação constante de uma condição. A diferença entre eles é que o
primeiro avalia a condição no início do laço e o segundo avalia a condição no final do laço.
2.2.1 Estruturas de repetição com condição no início
O comando while avalia uma condição no início do laço de repetição para determinar
se o bloco sujeito a ele deve ser executado (DEITEL, 2011). Sua sintaxe é descrita no Quadro 18
a seguir.
while (condição)
instrução;
while (condição)
{
instrução 1;
instrução 2;
instrução 3;
...
}
Quadro 18 – Sintaxe do comando while. Fonte: Adaptado de Schildt (1996).
Enquanto condição for verdadeira, ou seja, resultar em um valor não-zero, a instrução
ou o bloco de instruções é executado. Quando condição for falsa, o programa desvia o fluxo
para a instrução subsequente à estrutura. Se acontecer de condição ser falsa quando avaliada
pela primeira vez, o programa simplesmente pula o laço de repetição sem executá-lo (SCHILDT,
1996).
Algumas linguagens de programação oferecem uma variação do
comando for para percorrer estruturas de dados, como vetores,
matrizes, registros e itens de coleções. Em C#, por exemplo,
esse tipo de estrutura é implementado pelo comando foreach.
Mais informações sobre ele podem ser encontradas no link do
Microsoft Docs, disponível em:
https://docs.microsoft.com/pt-br/dotnet/csharp/language-referen-
ce/keywords/foreach-in
https://docs.microsoft.com/pt-br/dotnet/csharp/language-reference/keywords/foreach-in
https://docs.microsoft.com/pt-br/dotnet/csharp/language-reference/keywords/foreach-in
72WWW.UNINGA.BR
AL
GO
RI
TM
OS
E
P
RO
GR
AM
AÇ
ÃO
A
PL
IC
AD
A
| U
NI
DA
DE
2
EDUCAÇÃO A DISTÂNCIA
O Quadro 19 a seguir apresenta como exemplo um programa que fica repetidamente
lendo um número inteiro do usuário enquanto não for digitado 10.
#include <stdio.h>
int main(void) {
int numero;
printf(“Digite um numero: “);
scanf(“%d”, &numero);
while (numero != 10) {
printf(“Digite um numero: “);
scanf(“%d”, &numero);
}
return 0;
}
Quadro 19 – Programa com estrutura de repetição com condição no início. Fonte: O autor.
2.2.2 Estruturas de repetição com condição no final
O comando do...while avalia uma condição no final do laço de repetição, o que significa
que o bloco de instruções do laço será executado pelo menos uma vez (DEITEL, 2011). Sua
sintaxe é descrita no Quadro 20 a seguir.
do
instrução
while (condição);
do
{
instrução 1;
instrução 2;
instrução 3;
...
}
while (condição);
Quadro 20 – Sintaxe do comando do...while. Fonte: Adaptado de Deitel (2011).
Apesar de os parênteses poderem ser omitidos em blocos com apenas uma instrução,
no caso do comando do...while é mais comum e seguro usar a segunda forma do Quadro 20,
com chaves, para prevenir possível ambiguidade entre estruturas while e do…while: na primeira
forma, sem chaves, “a última linha – while (condição); – pode ser mal interpretada como uma
estrutura while com uma instrução vazia” (DEITEL, 2011, p. 93).
73WWW.UNINGA.BR
AL
GO
RI
TM
OS
E
P
RO
GR
AM
AÇ
ÃO
A
PL
IC
AD
A
| U
NI
DA
DE
2
EDUCAÇÃO A DISTÂNCIA
O Quadro 21 a seguir apresenta uma adaptação do programa do Quadro 19, para usar
uma estrutura do...while como laço de repetição.
#include <stdio.h>
int main(void) {
int numero;
do {
printf(“Digite um numero: “);
scanf(“%d”, &numero);
} while (numero != 10);
return 0;
}
Quadro 21 – Programa com estrutura de repetição com condição no final. Fonte: O autor.
Nesse exemplo, a leitura do número pelo programa será feita ao menos uma vez antes da
condição ser testada. Comparando com o exemplo anterior do Quadro 19, repare que as duas
linhas repetidas fora do laço para pedir o número pela primeira vez puderam ser removidas. E o
resultado em tela é o mesmo para ambos, conforme ilustrado na Figura 7 a seguir.
Figura 7 – Resultado da execução dos programas dos Quadros 19 e 21. Fonte: O autor.
2.3 Intervenção no Fluxo dos Laços de Repetição
Conforme abordado nas seções anteriores, as estruturas de repetição estão atreladas a
uma condição ou a uma variável de controle para que mantenham ou encerrem a repetição do
bloco de instruções sujeito a elas.
Contudo, existem dois comandos que podem forçar o desvio do fluxo para o início ou
para fora do laço, independentemente da condição ou da contagem de acordo com o tipo de laço.
Abordamos esses comandos nas seções seguintes.
2.3.1 Comando break
Vimos na seção 1.5 desta unidade que o comando break é utilizado para sair de um bloco
de instruções switch e desviar o fluxo para a linha seguinte do bloco. Na verdade, ele também
serve para interromper a execução de qualquer laço de repetição e continuar a execução do
programa a partir da linha seguinte ao laço interrompido (BACKES, 2016).
74WWW.UNINGA.BR
AL
GO
RI
TM
OS
E
P
RO
GR
AM
AÇ
ÃO
A
PL
IC
AD
A
| U
NI
DA
DE
2
EDUCAÇÃO A DISTÂNCIA
O Quadro 22 a seguir apresenta uma nova versão do programa que repete a leitura de um
número até que seja digitado 10, utilizando o comando break.
#include <stdio.h>
int main(void) {
int numero;
while (1) {
printf(“Digite um numero: “);
scanf(“%d”, &numero);
if (numero == 10)
break;
}
return 0;
}
Quadro 22 – Programa com desvio para o final do laço de repetição. Fonte: O autor.
Nesse exemplo, o programa sairá do laço quando o número digitado for 10, do contrário,
continuará infinitamente dentro do laço, uma vez que mudamos a condição do while para 1 –
sempre verdadeiro. Esta é uma expressão muito comum em programas quando queremosque
haja um trecho de código sempre repetindo até que a verificação de uma condição no meio do
bloco faça a saída dele.
2.3.2 Comando continue
O comando continue, por sua vez, desvia o fluxo para a o início do laço de repetição,
mais precisamente para a próxima iteração. Se esse laço é uma estrutura for, então é realizado o
incremento ou decremento da variável de controle; se esse laço é uma estrutura while, então a
condição é novamente avaliada. Em ambos os casos, o laço pode ser encerrado se a condição de
avaliação for falsa (BACKES, 2016).
O Quadro 23 a seguir apresenta como exemplo um programa que pede um número de
opção do usuário e deixa prosseguir somente se a opção estiver entre 1 e 5.
#include <stdio.h>
int main(void) {
int opcao = 0;
while (opcao != 5) {
printf(“Digite uma opcao (1-5): “);
scanf(“%d”, &opcao);
if (opcao < 1 || opcao > 5)
continue;
printf(“Opcao escolhida: %d\n”, opcao);
}
return 0;
}
Quadro 23 – Programa com desvio para o início do laço de repetição. Fonte: Backes (2016).
75WWW.UNINGA.BR
AL
GO
RI
TM
OS
E
P
RO
GR
AM
AÇ
ÃO
A
PL
IC
AD
A
| U
NI
DA
DE
2
EDUCAÇÃO A DISTÂNCIA
Cuidado ao usar estruturas de repetição, pois se não houver nenhuma condição de
seleção para desviar o código para fora da estrutura e a condição de verificação for
sempre verdadeira, o programa entrará no que chamamos de loop infinito, ou seja,
nunca terminará o processamento, causando o efeito de travamento da máquina
em algumas situações (LOPES; GARCIA, 2002). Em C, isso pode facilmente
acontecer em blocos de instruções encabeçados por for (;;) ou while (1).
76WWW.UNINGA.BR
AL
GO
RI
TM
OS
E
P
RO
GR
AM
AÇ
ÃO
A
PL
IC
AD
A
| U
NI
DA
DE
2
EDUCAÇÃO A DISTÂNCIA
CONSIDERAÇÕES FINAIS
Nesta unidade, foram abordadas as estruturas de seleção e de repetição, necessárias para
programas que dependem da avaliação de uma condição para poderem executar determinados
comandos e repetir a execução de outros.
Iniciamos a unidade abordando as estruturas de seleção simples e composta, implementadas
na linguagem C pelo comando if. Em seguida, vimos o funcionamento do operador de condição
ternária ?:, usado para simplificar blocos de instruções if em apenas uma linha.
Depois abordamos as possibilidades de uso de ifs seguidos ou encadeados, de acordo com
a necessidade do programa em questão. Introduzimos as estruturas de seleção múltipla, ideal
para a avaliação de várias condições relacionadas, implementadas na linguagem C pelo comando
switch.
Prosseguimos abordando as estruturas de repetição, que podem ser subdivididas em
estruturas de laços contados, implementadas pelo comando for, e estruturas de laços atrelada a
uma condição, implementadas pelo comando while, que avalia a condição do início do laço, e
pelo comando do...while, que avalia a condição no final do laço.
Finalizamos a unidade abordando os dois comandos que interrompem a execução das
instruções em um laço de repetição: break, que encerra o laço e desvia o fluxo para a instrução
seguinte, e continue, que desvia o fluxo para o início do laço.
Esse livro tem por objetivo apresentar os
fundamentos da lógica para a programação de
computadores, capacitando o leitor a construir
algoritmos estruturados, e traz assuntos e
exercícios baseados em experiências reais do
autor vivenciadas em sala de aula. A leitura não
exige maior conhecimento do assunto por parte do
leitor, mas apenas familiaridade com a operação
do microcomputador.
VILARIM, G. O. Algoritmos: Programação para
Iniciantes. 3. ed. Rio de Janeiro: Ciência Moderna,
2017.
Fonte: Vilarim (2017)
7777WWW.UNINGA.BR
U N I D A D E
03
SUMÁRIO DA UNIDADE
INTRODUÇÃO ...............................................................................................................................................................79
1 ESTRUTURAS DE DADOS HOMOGÊNEAS ..............................................................................................................80
1.1 VETORES .................................................................................................................................................................80
1.1.1 PESQUISA EM VETORES ....................................................................................................................................83
1.1.2 ORDENAÇÃO EM VETORES ................................................................................................................................85
1.2 CADEIAS DE CARACTERES – STRINGS ...............................................................................................................86
1.3 MATRIZES...............................................................................................................................................................89
1.3.1 MATRIZES COM MAIS DE DUAS DIMENSÕES ................................................................................................ 91
1.3.2 VETORES DE STRINGS .......................................................................................................................................92
2 ESTRUTURAS DE DADOS HETEROGÊNEAS ..........................................................................................................93
2.1 VETORES DE ESTRUTURAS ..................................................................................................................................97
ESTRUTURAS DE
ARMAZENAMENTO DE DADOS
PROF. FÁBIO ATAIDE DE LIMA
ENSINO A DISTÂNCIA
DISCIPLINA:
ALGORITMOS E PROGRAMAÇÃO APLICADA
78WWW.UNINGA.BR
EDUCAÇÃO A DISTÂNCIA
2.2 COMANDO TYPEDEF ............................................................................................................................................99
2.3 UNIÕES ..................................................................................................................................................................99
CONSIDERAÇÕES FINAIS .......................................................................................................................................... 102
79WWW.UNINGA.BR
AL
GO
RI
TM
OS
E
P
RO
GR
AM
AÇ
ÃO
A
PL
IC
AD
A
| U
NI
DA
DE
3
EDUCAÇÃO A DISTÂNCIA
INTRODUÇÃO
Até o momento, as variáveis foram o único recurso que aprendemos para armazenar
dados na memória, de maneira que eles pudessem ser recuperados, manipulados e apresentados
posteriormente ao usuário.
Contudo, existem programas que requerem a entrada de dados de forma repetitiva
e organizada; e as variáveis armazenam apenas um valor por vez, obrigando o programador
a trabalhar com muitas variáveis na necessidade de um volume de dados maior e homogêneo
(MANZANO; OLIVEIRA, 2012).
Para suprir essa necessidade, existem as estruturas de armazenamento de dados, que
permitem o armazenamento de várias informações na memória sob a referência de apenas um
identificador. Conceitualmente, existem dois tipos de estruturas de armazenamento de dados,
segundo Manzano e Oliveira (2012):
• Estruturas homogêneas, também conhecidas como arrays, que permitem o armazenamento
de dados do mesmo tipo e subdividem-se em unidimensionais e multidimensionais;
• Estruturas heterogêneas, também conhecidas como registros, que permitem o
armazenamento de dados de tipos diferentes.
Todos esses tipos de estruturas são implementados pela linguagem C. Inclusive as cadeias
de caracteres – strings – são implementadas por meio de vetores e serão abordadas com detalhes
nesta unidade.
As estruturas homogêneas unidimensionais são comumente chamadas de vetores, primeiro
assunto a ser abordado. Em seguida, veremos as estruturas homogêneas multidimensionais,
também conhecidas como matrizes. E para concluir a unidade, serão abordadas as estruturas de
dados heterogêneas.
80WWW.UNINGA.BR
AL
GO
RI
TM
OS
E
P
RO
GR
AM
AÇ
ÃO
A
PL
IC
AD
A
| U
NI
DA
DE
3
EDUCAÇÃO A DISTÂNCIA
1 ESTRUTURAS DE DADOS HOMOGÊNEAS
Asestruturas de dados homogêneas permitem trabalhar com o agrupamento de várias
informações dentro de uma mesma variável, obedecendo sempre ao mesmo tipo de dado. No
mundo da computação, elas recebem diversos nomes, como variáveis indexadas, variáveis
compostas, arranjos ou arrays em inglês (MANZANO; OLIVEIRA, 2012) – este último termo é
o mais comum.
Essas estruturas também são nomeadas quanto ao número de dimensões que possuem:
vetores, no caso de estruturas com uma dimensão apenas, e matrizes, no caso de estruturas com
duas ou mais dimensões.
1.1 Vetores
Segundo Lopes e Garcia (2002), vetores são arranjos de elementos armazenados na
memória principal, um após o outro, todos com o mesmo nome. Essa estrutura segue a ideia de
matriz linha ou matriz coluna da matemática, isto é, várias colunas em uma linha ou várias linhas
em uma coluna, respectivamente.
A Figura 1 a seguir ilustra a representação de um vetor contendo os 8 primeiros números
primos, nas duas formas.
Figura 1 – Representação de um vetor. Fonte: O autor.
Para o computador, não há diferença se um vetor é representado graficamente na horizontal
ou na vertical – assumiremos aqui a representação vertical, pois facilitará o entendimento quando
estivermos abordando as matrizes. O que importa é que cada elemento desse arranjo é indicado
por um índice numérico inteiro e positivo (MANZANO; OLIVEIRA, 2012). Cada linguagem de
programação implementa esse índice de formas diferentes, sendo que na linguagem C esse índice
inicia em zero e vai até o tamanho do vetor menos uma unidade (BACKES, 2016).
81WWW.UNINGA.BR
AL
GO
RI
TM
OS
E
P
RO
GR
AM
AÇ
ÃO
A
PL
IC
AD
A
| U
NI
DA
DE
3
EDUCAÇÃO A DISTÂNCIA
A sintaxe para a declaração de vetores em C é muito semelhante à criação de variáveis –
inclusive podem ser declarados junto com elas na mesma linha, contanto que sejam do mesmo
tipo. O que diferencia um vetor de uma variável é que o vetor deve ter o número de elementos
especificado entre colchetes:
tipo_de_dado identificador[numero_elementos];
Por exemplo, int vetor[10]; criará um vetor de inteiros contendo dez elementos, indexados
de 0 a 9. A partir daí, é possível atribuir valores aos seus elementos referenciando-os pelo seu
índice, conforme ilustrado no Quadro 1 a seguir.
int main(void) {
int vetor[10], n = 7;
vetor[0] = 3;
vetor[1] = 5;
vetor[4] = vetor[1] + vetor[0];
vetor[n] = vetor[4] + 2;
vetor[n+1] = 55;
return 0;
}
Quadro 1 – Criação de vetor e atribuição de valores aos seus elementos. Fonte: O autor.
Repare que o índice pode ser uma constante ou uma expressão que resulte em um número
inteiro, como uma variável, um cálculo aritmético ou um retorno de função.
Assim como em variáveis, também é possível atribuir elementos em um vetor no momento
em que são declarados, segundo Deitel (2011):
• Com um tamanho constante: int numeros[5] = {10, 20, 30, 40, 50};
• Apenas alguns elementos do vetor: int valores[5] = {2, 4, 6};
Nesse caso, os demais elementos são inicializados automaticamente com zero;
• Sem especificar a quantidade de elementos: int valores[] = {3, 5, 7};
o compilador idenficará a quantidade – neste caso, 3.
82WWW.UNINGA.BR
AL
GO
RI
TM
OS
E
P
RO
GR
AM
AÇ
ÃO
A
PL
IC
AD
A
| U
NI
DA
DE
3
EDUCAÇÃO A DISTÂNCIA
Segundo Lopes e Garcia (2002), não é possível realizar a leitura ou a apresentação de um
vetor como um todo; é necessário fazê-lo elemento por elemento, sendo que, para isso, utiliza-
se geralmente uma estrutura de repetição com laços contados. O Quadro 2 a seguir ilustra um
exemplo de como seria o preenchimento e a exibição dos dados de um vetor.
#include <stdio.h>
int main(void) {
int vetor[10], i;
for (i = 0; i < 10; i++) {
printf(“Digite o %d elemento do vetor: “, i);
scanf(“%d”, &vetor[i]);
}
printf(“\nVetor preenchido\n”);
for (i = 0; i < 10; i++)
printf(“O elemento na posicao %d eh: %d\n”, i, vetor[i]);
return 0;
}
Quadro 2 – Leitura e escrita dos elementos de um vetor. Fonte: O autor.
Repare que foi necessário o uso de dois laços de repetição contados, um para a leitura e
outro para a escrita na tela. Em cada laço, a variável i foi inicializada com 0 – posição do primeiro
elemento do vetor em C – e termina em 9 – o último elemento é sempre o tamanho do vetor - 1.
A Figura 2 a seguir ilustra o resultado da execução desse programa.
Figura 2 – Resultado da execução do programa do Quadro 2. Fonte: O autor.
83WWW.UNINGA.BR
AL
GO
RI
TM
OS
E
P
RO
GR
AM
AÇ
ÃO
A
PL
IC
AD
A
| U
NI
DA
DE
3
EDUCAÇÃO A DISTÂNCIA
1.1.1 Pesquisa em vetores
É muito comum nos sistemas de computação a necessidade de procurar por um item em
uma determinada lista ou coleção de dados. Essa tarefa torna-se praticamente inviável quando
a referida lista possui um número muito grande de elementos – ainda mais nos dias atuais onde
muitos serviços são realizados por telefone ou Internet, que demandam uma resposta rápida e
clara às suas solicitações (GUEDES, 2014).
Existem diversos algoritmos de busca criados para tal finalidade. O mais simples é
o mecanismo de busca sequencial, “[...] pois se baseia apenas em uma estrutura de repetição
que percorre a lista, realizando um teste condicional que compara o elemento desejado com os
elementos existentes” (GUEDES, 2014, p. 111).
Uma tentativa de acessar ou atribuir dados a um elemento fora do escopo do
vetor, isto é, se o índice referenciado for maior que o seu número de elementos,
poderá ocasionar um erro de execução em certas linguagens de programação.
Este tipo de erro pode acontecer às vezes, especialmente quando se usam laços
de repetição com variáveis de controle e não há uma verificação precisa do número
de elementos que o vetor possui.
Em C, a situação piora consideravelmente porque em alguns compiladores não
ocorre um erro que interrompa a execução do programa, mas o possível acesso
a um endereço de memória indevido e a manipulação de conteúdos que podem
comprometer o funcionamento de outros programas abertos e até mesmo do
sistema operacional.
84WWW.UNINGA.BR
AL
GO
RI
TM
OS
E
P
RO
GR
AM
AÇ
ÃO
A
PL
IC
AD
A
| U
NI
DA
DE
3
EDUCAÇÃO A DISTÂNCIA
O Quadro 3 a seguir exemplifica um programa que alimenta um vetor com valores e
depois efetua uma busca nele para verificar se o valor digitado está contido.
#include <stdio.h>
int main(void) {
int valores[10], i, valor;
for (i = 0; i < 10; i++) {
printf(“Digite o elemento %d do vetor: “, i);
scanf(“%d”, &valores[i]);
}
printf(“\nValor a procurar no vetor: “, i);
scanf(“%d”, &valor);
// Efetua a busca sequencial
for (i = 0; i < 10; i++)
if (valores[i] == valor) break;
if (i == 10)
printf(“Valor nao encontrado no vetor\n”);
else
printf(“Encontrado na posicao %d\n”, i);
return 0;
}
Quadro 3 – Programa fazendo uso de pesquisa sequencial. Fonte: O autor.
Nesse exemplo, o usuário entra com dez valores, que são armazenados em um vetor de
inteiros com dez elementos. Em seguida, o usuário digita o valor a ser procurado e então o laço
for efetua a busca fazendo comparações, elemento por elemento; se o valor for encontrado, um
break é acionado para sair do laço. Em seguida, o valor de i é avaliado: se for igual a 10, é porque
percorreu todo o vetor sem encontrar o valor procurado; se for menor que 10, ele encontrou o
valor em alguma posição do vetor e mostrará na tela para o usuário.
A Figura 3 a seguir ilustra o resultado de duas execuções do programa do Quadro 3, com
uma busca bem-sucedida e outra malsucedida.
Figura 3 – Resultado das execuções do programa de busca em vetor. Fonte: O autor.
85WWW.UNINGA.BR
AL
GO
RI
TM
OS
E
P
RO
GR
AM
AÇ
ÃO
A
PL
IC
AD
A
| U
NI
DA
DE
3
EDUCAÇÃO A DISTÂNCIA
1.1.2 Ordenação em vetores
Em aplicações de entrada contínua de dados do mesmo tipo, o usuário não se preocupa
com a ordem em que ele digita essesdados, nem como eles serão armazenados na memória
primária ou secundária do computador. Cabe à aplicação organizá-los e ordená-los de acordo
com a necessidade de utilização (GUEDES, 2014).
Segundo Schildt (1996, p. 501), “[...] ordenação é o processo de arranjar um conjunto
de informações semelhantes numa ordem crescente ou decrescente”. Existem vários algoritmos
voltados para esta finalidade; apresentaremos aqui o mais simples e conhecido: o método da
bolha, também conhecido como BubbleSort.
Em dois laços de repetição encadeados, são feitas comparações entre os elementos atuais
do laço externo e do laço interno; caso o valor do primeiro seja maior que o segundo, é efetuada
a troca de valores entre as posições. Esse processo se repete até que os laços de repetição sejam
concluídos (GUEDES, 2014).
O Quadro 4 a seguir exemplifica um programa que alimenta um vetor com valores e
depois efetua o método da bolha para ordenar esse vetor.
#include <stdio.h>
int main(void) {
int vetor[10];
int i, j, troca;
for (i = 0; i < 10; i++) {
printf(“Digite o elemento %d: “, i);
scanf(“%d”, &vetor[i]);
}
// Efetua o método da bolha
for (i = 0; i < 9; i++)
for (j = i + 1; j < 10; j++)
if (vetor[i] > vetor[j]) {
troca = vetor[i];
vetor[i] = vetor[j];
vetor[j] = troca;
}
printf(“\nVetor ordenado: { “);
for (i = 0; i < 10; i++)
printf(“%d “, vetor[i]);
printf(“}\n”);
return 0;
}
Quadro 4 – Programa fazendo uso do método da bolha para ordenar o vetor. Fonte: O autor.
Neste exemplo, enquanto o laço de repetição externo percorre o vetor do primeiro até o
penúltimo elemento, o laço de repetição interno percorre da posição seguinte à do elemento atual
do laço externo até o último elemento do vetor. Se o valor do elemento do laço externo for maior
que o valor do elemento do laço interno, é feita a troca de valores entre as posições dos elementos.
86WWW.UNINGA.BR
AL
GO
RI
TM
OS
E
P
RO
GR
AM
AÇ
ÃO
A
PL
IC
AD
A
| U
NI
DA
DE
3
EDUCAÇÃO A DISTÂNCIA
A Figura 4 a seguir ilustra o resultado do processamento deste programa.
Figura 4 – Resultado da execução do programa do Quadro 4. Fonte: O autor.
1.2 Cadeias de Caracteres – Strings
Segundo Backes (2016), string é o nome usado para definir uma sequência de caracteres
adjacentes na memória do computador. Na prática, as strings são usadas para representar textos.
Ao contrário de outras linguagens, C não possui um tipo nativo string: cadeias de caracteres são
representadas em C por um vetor de chars.
Assim sendo, a sintaxe para a declaração de uma string é:
char vetor[tamanho+1];
Onde vetor é o nome da variável a armazenar a cadeia de caracteres e o tamanho deve
sempre ter uma posição a mais que o tamanho máximo esperado para o texto; isto porque a
linguagem adiciona automaticamente o caractere ‘\0’, que representa o final da sequência de
caracteres (SCHILDT, 1996).
Vejamos alguns exemplos válidos para declaração de strings:
• Com um tamanho fixo: char cor[20] = “Azul”; ou char cor[20] = {‘A’, ‘z’, ‘u’, ‘l’};
nesse caso, o compilador adiciona automaticamente o caractere ‘\0’;
• Sem definir o tamanho: char cor[] = “Azul”; ou char cor[] = {‘A’, ‘z’, ‘u’, ‘l’};
nesse caso, o compilador assumirá 5 como tamanho para comportar o caractere ‘\0’.
Bubble-sort with Hungarian (“Csángó”) folk dance
Uma simulação do método da bolha em forma de dança húngara. O
processamento demonstrado na dança é feito do final para o início
do vetor.
Disponível em: https://www.youtube.com/watch?v=lyZQPjUT5B4
87WWW.UNINGA.BR
AL
GO
RI
TM
OS
E
P
RO
GR
AM
AÇ
ÃO
A
PL
IC
AD
A
| U
NI
DA
DE
3
EDUCAÇÃO A DISTÂNCIA
Para efetuar entrada de dados do tipo texto, duas funções podem ser usadas, segundo
Backes (2016):
• scanf(“%s”, variável); – aceita apenas uma palavra como entrada, ou seja, termina a string
na primeira ocorrência de espaço em branco, quebra de linha ou tabulação;
• gets(variável); – aceita frases contendo espaço em branco e termina a string apenas na
ocorrência de quebra de linha, com a tecla [ENTER].
Repare em ambas as funções que não é necessário o operador & antes de variável, pois
cadeias de caracteres são vetores de chars e vetores já são em si ponteiros para o endereço de
memória de seu primeiro elemento.
O Quadro 5 a seguir exemplifica um programa lê repetidamente um texto e depois exibe
seu comprimento, até que não seja digitado nada para encerrar.
#include <stdio.h>
int main(void) {
char texto[50];
int tamanho;
while (1) {
printf(“Digite o texto (branco=encerra): “);
fflush(stdin); // Para prevenir o bug de não editar
gets(texto);
if (texto[0] == ‘\0’) // Não foi digitado nada
break;
// Conta quantas letras tem o texto
for (tamanho = 0; texto[tamanho] != ‘\0’; tamanho++);
printf(“Tamanho do texto: %d\n”, tamanho);
}
return 0;
}
Quadro 5 – Programa para leitura de uma cadeia de caracteres. Fonte: O autor.
O resultado deste programa é ilustrado na Figura 5 a seguir.
Figura 5 – Resultado da execução do programa do Quadro 5. Fonte: O autor.
88WWW.UNINGA.BR
AL
GO
RI
TM
OS
E
P
RO
GR
AM
AÇ
ÃO
A
PL
IC
AD
A
| U
NI
DA
DE
3
EDUCAÇÃO A DISTÂNCIA
O Quadro 6 a seguir traz algumas destas funções disponíveis para a manipulação de strings.
Lembre-se que é necessário incluir a instrução #include <string.h> no início do programa.
Nome Função
strcpy(s1, s2) Copia s2 em s1
strcat(s1, s2) Concatena s2 ao final de s1
strlen(s1) Retorna o tamanho de s1
strcmp(s1, s2) Retorna 0 se s1 e s2 forem iguais, menor que 0 se s1 < s2 ou maior que 0 se s1 > s2
strchr(s1, ch) Retorna um ponteiro para a primeira ocorrência de ch em s1
strstr(s1, s2) Retorna um ponteiro para a primeira ocorrência de s2 em s1
strlwr(s1) Retorna o minúsculo de s1
strupr(s1) Retorna o maiúsculo de s1
Quadro 6 – Funções comuns para a manipulação de strings. Fonte: Adaptado de Schildt (1996).
A biblioteca padrão da linguagem C disponibiliza um conjunto de funções espe-
cialmente desenvolvidas para a manipulação de cadeias de caracteres, encontra-
das no arquivo de cabeçalho string.h. Por exemplo, a função strlen() retorna o
tamanho de um texto passado por parâmetro e poderia perfeitamente substituir o
for usado no programa do Quadro 5 para contar quantas letras tem o texto digita-
do (SCHILDT, 1996).
89WWW.UNINGA.BR
AL
GO
RI
TM
OS
E
P
RO
GR
AM
AÇ
ÃO
A
PL
IC
AD
A
| U
NI
DA
DE
3
EDUCAÇÃO A DISTÂNCIA
1.3 Matrizes
Segundo Manzano e Oliveira (2012), matrizes são arrays que possuem duas ou mais
dimensões; geralmente é utilizada em duas dimensões, devido à facilidade de disposição dos
dados em formato de tabela – linhas e colunas. Na prática, um array de duas dimensões significa
que cada elemento da primeira dimensão conterá um outro array, cujo número de elementos será
igual para todos os arrays da segunda dimensão.
A declaração de uma matriz em C é semelhante à de um vetor, com a diferença de que
deve haver um par de colchetes para cada dimensão:
tipo variável[dimensão1][dimensão2]...;
Onde dimensão1 determina o número de elementos da primeira dimensão do vetor,
dimensão2 determina o número de elementos da segunda dimensão, e assim por diante. Cada
dimensão possui seu o próprio índice, numerado de 0 ao seu tamanho menos 1.
O Quadro 7 a seguir traz um exemplo de declaração de uma matriz de duas dimensões e
a atribuição de valores a alguns de seus elementos, sendo que na ilustração a primeira dimensão
está representada pelas linhas e a segunda dimensão, pelas colunas.
int main(void) {
int dados[3][4];
dados[0][2] = 100;
dados[2][0] = 2;
dados[1][1] = 7;
dados[1][3] = 11;
dados[0][0] = 43;
}
Quadro 7 – Declaração de matriz e atribuição de valores a seus elementos. Fonte: O autor.
Matrizes também podem receber valores literais nomomento em que são declaradas,
segundo Deitel (2011):
• Com um tamanho constante: int triangulo[3][2] = { {1,1}, {5,1}, {3,4} };
• Como se fosse um vetor: int valor[3][4] = {1,2,3,4,5,6,7,8,9,10,11,12};
neste caso, os valores serão distribuídos de acordo com as dimensões especificadas;
• Sem especificar a quantidade de elementos: int matriz[][2] = {1,2,3,4,5,6,7,8,9,10}; o
compilador atribuirá 5 à primeira dimensão baseado no tamanho da segunda dimensão,
obrigatório de ser informado neste caso.
90WWW.UNINGA.BR
AL
GO
RI
TM
OS
E
P
RO
GR
AM
AÇ
ÃO
A
PL
IC
AD
A
| U
NI
DA
DE
3
EDUCAÇÃO A DISTÂNCIA
Para percorrer os elementos de uma matriz, seja para leitura ou apresentação dos dados,
deve-se usar uma estrutura de repetição por dimensão (MANZANO; OLIVEIRA, 2012),
conforme exemplificado no Quadro 8 a seguir.
#include <stdio.h>
int main(void) {
int matriz[2][5], i, j;
for (i = 0; i < 2; i++) {
for (j = 0; j < 5; j++) {
printf(“Digite o [%d][%d] elemento da matriz: “, i,
j);
scanf(“%d”, &matriz[i][j]);
}
}
for (i = 0; i < 2; i++)
for (j = 0; j < 5; j++)
printf(“\nElemento da posicao [%d][%d]: %d”, i, j,
matriz[i][j]);
printf(“\n”);
return 0;
}
Quadro 8 – Leitura e escrita dos elementos de uma matriz. Fonte: O autor.
A Figura 6 a seguir ilustra o resultado da execução deste programa.
Figura 6 – Resultado da execução do programa do Quadro 8. Fonte: O autor.
91WWW.UNINGA.BR
AL
GO
RI
TM
OS
E
P
RO
GR
AM
AÇ
ÃO
A
PL
IC
AD
A
| U
NI
DA
DE
3
EDUCAÇÃO A DISTÂNCIA
1.3.1 Matrizes com mais de duas dimensões
Segundo Deitel (2011), as matrizes em C podem ter múltiplas dimensões. Vimos na seção
anterior que uma matriz de duas dimensões se assemelha visualmente a uma tabela, com seus
dados distribuídos em linhas e colunas.
Uma matriz de três dimensões, por sua vez, indica que cada elemento da segunda
dimensão possuirá um subvetor ao invés de um valor único, assemelhando-se visualmente a um
cubo. Por exemplo, a declaração int matriz[3][4][4]; criará uma matriz de 3x4x4, totalizando 48
elementos; a Figura 7 a seguir ilustra como um elemento desta matriz seria referenciado.
Figura 7 – Referência a um elemento de uma matriz de três dimensões. Fonte: O autor.
Uma matriz de 4 dimensões significa que cada elemento da terceira dimensão será um
novo subvetor com tamanho fixo. Uma analogia próxima para uma matriz com esse número de
dimensões seria uma tabela onde cada item conteria uma subtabela independente, conforme
ilustrado na Figura 8 a seguir para a seguinte declaração de matriz: matriz[2][3][2][2]; totalizando
24 elementos.
Figura 8 – Representação visual de uma matriz de quatro dimensões. Fonte: O autor.
92WWW.UNINGA.BR
AL
GO
RI
TM
OS
E
P
RO
GR
AM
AÇ
ÃO
A
PL
IC
AD
A
| U
NI
DA
DE
3
EDUCAÇÃO A DISTÂNCIA
1.3.2 Vetores de strings
Vimos na seção 1.2 desta unidade que uma string é um vetor de chars. Portanto, se
quisermos criar um vetor de strings, na verdade estaremos criando uma lista de vetores, em outras
palavras uma matriz bidimensional de chars. Podemos assumir uma forma geral para declarar
vetores de strings como sendo:
char variável[número_strings][comprimento_strings];
Por exemplo, para criar e inicializar um vetor que contenha três nomes, podemos usar
uma das formas a seguir:
• char nomes[3][10] = {“Joao”, “Maria”, “Jose”};
• char nomes[3][10] = { {‘J’,’o’,’a’,’o’}, {‘M’,’a’,’r’,’i’,’a’}, {‘J’,’o’,’s’,’e’} };
• char nomes[][10] = {“Joao”, “Maria”, “Jose”};
Lembre-se que o tamanho da segunda dimensão deve ser suficiente para comportar o
número de caracteres das strings e o caractere de ‘\0’ de fim de texto.
O Quadro 9 a seguir exemplifica um programa que faz a leitura e a apresentação de cinco
nomes na tela.
#include <stdio.h>
int main(void) {
char nomes[5][30];
int i;
for (i = 0; i < 5; i++) {
printf(“Digite o nome %d: “, i);
fflush(stdin); // Para prevenir o bug de não editar
gets(nomes[i]);
}
printf(“\nNomes digitados:\n”);
for (i = 0; i < 5; i++)
printf(“%s\n”, nomes[i]);
return 0;
}
Quadro 9 – Leitura e escrita de um vetor de strings. Fonte: O autor.
Embora o número de dimensões de um array possa ser ilimitado em C, repare
que a complexidade para visualizar e manipular seus elementos aumenta
consideravelmente a cada nova dimensão. Portanto, em seus programas, verifique
se realmente é necessária a implementação de matrizes com esse porte, uma vez
que duas dimensões já são suficientes para a grande maioria dos problemas a
serem solucionados com algoritmos.
93WWW.UNINGA.BR
AL
GO
RI
TM
OS
E
P
RO
GR
AM
AÇ
ÃO
A
PL
IC
AD
A
| U
NI
DA
DE
3
EDUCAÇÃO A DISTÂNCIA
A Figura 9 a seguir ilustra o resultado da execução deste programa.
Figura 9 – Resultado da execução do programa do Quadro 9. Fonte: O autor.
2 ESTRUTURAS DE DADOS HETEROGÊNEAS
Registros são o nome comumente dado às estruturas de dados heterogêneas, segundo
Manzano e Oliveira (2012):
A estrutura de registro é um recurso que possibilita combinar vários dados de
tipos diferentes (os quais serão chamados de campos) em uma mesma estrutura de
dados. Por esta razão, esse tipo de estrutura de dados é considerado heterogêneo.
De forma mais ampla, pode-se dizer que registro é uma coleção designada de
dados que descreve um objeto de dados como sendo uma abstração de dados
(PRESSMAN, 1995 apud MANZANO; OLIVEIRA, 2012, p. 190).
Com essa estrutura, é possível gerar novos tipos de dados, além dos definidos pelas
linguagens de programação (ASCENCIO; CAMPOS, 2010). A Figura 10 a seguir ilustra a
representação de um veículo, de maneira que visualmente se assemelha a uma ficha de controle.
Figura 10 – Exemplo de layout de um registro com seus campos. Fonte: O autor.
94WWW.UNINGA.BR
AL
GO
RI
TM
OS
E
P
RO
GR
AM
AÇ
ÃO
A
PL
IC
AD
A
| U
NI
DA
DE
3
EDUCAÇÃO A DISTÂNCIA
A linguagem C implementa registros por meio de estruturas ou structs (DEITEL, 2011),
cuja sintaxe é descrita no Quadro 10 a seguir.
struct nome_estrutura
{
tipo campo_1;
tipo campo_2;
...
tipo campo_n;
} lista_variáveis;
Quadro 10 – Sintaxe para declaração de uma estrutura em C. Fonte: Adaptado de Schildt (1996).
Toda estrutura possui um nome e é por meio dele que variáveis podem ser criadas e
tipadas com a estrutura criada. Dentro do bloco, entre as chaves estão a definição das variáveis
que pertencerão a esta estrutura, geralmente chamadas de campos ou membros. Opcionalmente,
após o fecha-chaves, pode-se elencar as variáveis que serão criadas no programa com o tipo da
estrutura definida (SCHILDT, 1996).
O Quadro 11 a seguir ilustra como seria a definição de uma estrutura para implementar
a ficha de veículos exemplificada na Figura 10.
struct veiculo {
char marca[16];
char modelo[16];
char placa[11];
char categ;
char combust[11];
int anofab;
int anomod;
float motor;
};
Quadro 11 – Estrutura em C para armazenar uma ficha de veículo. Fonte: O autor.
Evidentemente, poderíamos agrupar todas as variáveis do mesmo tipo na mesma linha
e separá-las por vírgulas, mas é costume declarar cada membro em uma linha individualmente,
como mostrado no Quadro 11. Repare que nesse exemplo não foi especificada nenhuma variável
a ser instanciada com o tipo da estrutura veículo, mas foi necessário terminar a declaração da
estrutura com o ponto-e-vírgula.
95WWW.UNINGA.BR
AL
GO
RI
TM
OS
E
P
RO
GR
AM
AÇ
ÃO
A
PL
IC
AD
A
| U
NI
DA
DE
3
EDUCAÇÃO A DISTÂNCIA
O Quadro 12 a seguir ilustra um exemplo de como fazer a leitura e a exibição dos valores
de membros de uma estrutura instanciada em uma variável. Aproveitamos a estrutura veículo
definida no Quadro 9.
#include <stdio.h>
struct veiculo {
char marca[16];
char modelo[16];
char placa[11];
char categ;
char combust[11];
int anofab;
intanomod;
float motor;
};
int main(void) {
struct veiculo v;
printf(“Marca..........: “);
fflush(stdin); // Para prevenir o bug de não editar
gets(v.marca);
printf(“Modelo.........: “);
fflush(stdin); // Para prevenir o bug de não editar
gets(v.modelo);
printf(“Placa..........: “);
fflush(stdin); // Para prevenir o bug de não editar
gets(v.placa);
do {
printf(“Categoria (A-E): “);
fflush(stdin); // Para prevenir o bug de não editar
scanf(“%c”, &v.categ);
} while (!(v.categ >= ‘A’ && v.categ <= ‘E’) &&
!(v.categ >= ‘a’ && v.categ <= ‘e’));
printf(“Combustivel....: “);
fflush(stdin); // Para prevenir o bug de não editar
gets(v.combust);
printf(“Ano fabricacao.: “);
scanf(“%d”, &v.anofab);
printf(“Ano modelo.....: “);
scanf(“%d”, &v.anomod);
printf(“Motor..........: “);
scanf(“%f”, &v.motor);
printf(“\nMarca/modelo: %s/%s”, v.marca, v.modelo);
printf(“\nMotor/placa.: %.2f %s”, v.motor, v.placa);
printf(“\nAno fab/mod.: %d/%d”, v.anofab, v.anomod);
printf(“\nCombustivel.: %s\n”, v.combust);
return 0;
}
Quadro 12 – Programa de leitura e escrita de membros de uma estrutura. Fonte: O autor.
96WWW.UNINGA.BR
AL
GO
RI
TM
OS
E
P
RO
GR
AM
AÇ
ÃO
A
PL
IC
AD
A
| U
NI
DA
DE
3
EDUCAÇÃO A DISTÂNCIA
Embora uma estrutura possa ser declarada dentro de uma função, é comum declarar
todas as estruturas no início do programa, fora do escopo de qualquer função, pois isso facilita a
declaração das variáveis locais nas funções e a passagem de parâmetros se necessário – assunto
visto na unidade seguinte.
Repare no exemplo do Quadro 12 que a variável criada para armazenar os dados da
estrutura foi v, tipada como struct veiculo. Segundo Deitel (2011), dois operadores podem ser
usados para manipular os membros de estruturas:
• Operador de membro de estrutura ou operador de ponto (.);
• Operador de ponteiro de estrutura ou operador de seta (->).
Na leitura dos membros tipo string não foi necessário usar o operador de endereço &,
como já explicado em seção anterior. Usamos demais tipos de dados lidos com scanf() para
passar o endereço de memória de cada membro sendo editado. Na leitura da categoria, fizemos
um laço de repetição com do...while para permitir prosseguir somente se a categoria estiver entre
“A” e “E”, seja maiúscula ou minúscula.
A Figura 11 a seguir ilustra o resultado da execução do programa do Quadro 12.
Figura 11 – Resultado da execução do programa do Quadro 12. Fonte: O autor.
As estruturas normalmente são usadas para declarar registros a serem
armazenados em arquivos. Usadas em conjuntos com ponteiros, facilitam a
formação de estruturas de dados mais complexas, como por exemplo, listas
interligadas, filas, pilhas e árvores (DEITEL, 2011).
97WWW.UNINGA.BR
AL
GO
RI
TM
OS
E
P
RO
GR
AM
AÇ
ÃO
A
PL
IC
AD
A
| U
NI
DA
DE
3
EDUCAÇÃO A DISTÂNCIA
2.1 Vetores de Estruturas
Vimos na seção anterior, a leitura e escrita de apenas um registro de estrutura. Como as
variáveis criadas são tipadas com a estrutura em questão, é possível definir um vetor contendo
elementos do mesmo tipo de estrutura. Com isso, podemos criar programas que controlam
cadastros completos de objetos, onde é possível incluir, alterar, excluir e visualizar seus dados.
O Quadro 12 a seguir é uma adaptação do programa do Quadro 11, onde no lugar de uma
variável temos um vetor de estruturas do tipo struct veiculo, com 5 elementos. Primeiro fazemos
a entrada e, em seguida, listamos os veículos digitados.
#include <stdio.h>
struct veiculo {
char marca[16];
char modelo[16];
char placa[11];
char categ;
char combust[11];
int anofab;
int anomod;
float motor;
};
int main(void) {
struct veiculo v[5];
int i;
for (i = 0; i < 5; i++) {
printf(“Marca..........: “);
fflush(stdin); // Para prevenir o bug de não editar
gets(v[i].marca);
printf(“Modelo.........: “);
fflush(stdin); // Para prevenir o bug de não editar
gets(v[i].modelo);
printf(“Placa..........: “);
fflush(stdin); // Para prevenir o bug de não editar
gets(v[i].placa);
do {
printf(“Categoria (A-E): “);
fflush(stdin); // Para prevenir o bug de não editar
scanf(“%c”, &v[i].categ);
} while (!(v[i].categ >= ‘A’ && v[i].categ <= ‘E’) &&
!(v[i].categ >= ‘a’ && v[i].categ <= ‘e’));
printf(“Combustivel....: “);
fflush(stdin); // Para prevenir o bug de não editar
gets(v[i].combust);
printf(“Ano fabricacao.: “);
scanf(“%d”, &v[i].anofab);
printf(“Ano modelo.....: “);
scanf(“%d”, &v[i].anomod);
printf(“Motor..........: “);
scanf(“%f”, &v[i].motor);
printf(“-----------------------------\n”);
}
98WWW.UNINGA.BR
AL
GO
RI
TM
OS
E
P
RO
GR
AM
AÇ
ÃO
A
PL
IC
AD
A
| U
NI
DA
DE
3
EDUCAÇÃO A DISTÂNCIA
printf(“\nMarca Modelo Motor”);
printf(“ Placa Cat A.Fab A.Mod Combustivel”);
for (i = 0; i < 5; i++) {
printf(“\n%-15s %-15s”, v[i].marca, v[i].modelo);
printf(“ %.1f %-10s”, v[i].motor, v[i].placa);
printf(“ %c %d”, v[i].categ, v[i].anofab);
printf(“ %d %s”, v[i].anomod, v[i].combust);
}
printf(“\n”);
return 0;
}
Quadro 12 – Programa de leitura e escrita de um vetor de estruturas. Fonte: O autor.
A Figura 12 a seguir ilustra o resultado da execução do programa do Quadro 12.
Figura 12 – Resultado da execução do programa do Quadro 12. Fonte: O autor.
99WWW.UNINGA.BR
AL
GO
RI
TM
OS
E
P
RO
GR
AM
AÇ
ÃO
A
PL
IC
AD
A
| U
NI
DA
DE
3
EDUCAÇÃO A DISTÂNCIA
2.2 Comando typedef
Segundo Deitel (2011, p. 324), “[...] a palavra-chave typedef oferece um mecanismo de
criação de sinônimos (ou aliases) para tipos de dados previamente definidos”. Sua sintaxe geral é:
typedef tipo_existente novo_nome;
Por exemplo, a instrução typedef int inteiro; permite que uma variável numero do tipo
int seja declarada como inteiro numero; – o compilador fará a associação com o tipo original.
Isto permite que estruturas possam ser referenciadas como um tipo de dado definido pelo usuário,
melhorando a legibilidade do código.
Isto fica claro no exemplo do Quadro 13 a seguir, onde do lado esquerdo temos variáveis
de estrutura criadas como aprendemos até o momento, e do meio e do lado direito como elas são
criadas após definição da estrutura com typedef.
struct Aluno {
char nome[30];
float nota[4];
};
struct Aluno eu, grupo[4];
struct st_al {
char nome[30];
float nota[4];
};
typedef st_al Aluno;
Aluno eu, grupo[4];
typedef struct {
char nome[30];
float nota[4];
} Aluno;
Aluno eu, grupo[4];
Quadro 13 – Criação de variáveis de estruturas definidas com e sem typedef. Fonte: O autor.
No exemplo à esquerda, foi criada a estrutura de nome Aluno e em seguida todas as
variáveis a serem instanciadas devem ser declaradas como struct Aluno. No exemplo do meio,
foi criada uma estrutura de nome st_al e em seguida foi criado um tipo Aluno a partir de struct
st_al; este exemplo é útil apenas no caso de ser necessário ter um nome para a estrutura original.
No exemplo à direita, foi aplicado o typedef direto na estrutura sem nome e já definido o novo
tipo como Aluno – repare que aqui não é a variável sendo criada. Nos dois últimos exemplos, é
possível então criar as variáveis de estrutura usando diretamente o tipo criado com typedef.
Para concluirmos, geralmente tipos novos criados com typedef são colocados no início
do programa, assim como a definição de estruturas. Dessa forma, podemos criar variáveis locais
dentro de qualquer função contida no programa usando o tipo criado.
2.3 Uniões
Segundo Deitel (2011, p. 327), “[...] uma união é um tipo de dado derivado – como uma
estrutura – com membros que compartilham o mesmoespaço de armazenamento”. Geralmente
uma união é formada por membros de tipos diferentes de dado, e o espaço a ser armazenado na
memória será o tamanho do maior tipo. A sintaxe para declarar uma união é semelhante à de
uma estrutura, conforme ilustrado no Quadro 14 a seguir.
union nome_união
{
tipo campo_1;
tipo campo_2;
...
tipo campo_n;
} lista_variáveis;
Quadro 14 – Sintaxe para declaração de uma união em C. Fonte: Adaptado de Schildt (1996).
100WWW.UNINGA.BR
AL
GO
RI
TM
OS
E
P
RO
GR
AM
AÇ
ÃO
A
PL
IC
AD
A
| U
NI
DA
DE
3
EDUCAÇÃO A DISTÂNCIA
As mesmas regras abordadas nas seções anteriores para a declaração de estruturas também
se aplicam para uniões, estando a única diferença no nome do comando: union. O acesso a seus
membros também é feito pelo operador ponto (.).
O Quadro 15 a seguir exemplifica o uso de uma união para armazenar o CPF ou o CNPJ,
de acordo com o tipo de pessoa especificado.
#include <stdio.h>
union PFouPJ {
char cpf[15];
char cnpj[19];
};
int main(void) {
char nome[30], tipo;
union PFouPJ pessoa;
printf(“Nome........: “);
fflush(stdin); // Para prevenir o bug de não editar
gets(nome);
do {
printf(“Pessoa (F/J): “);
fflush(stdin); // Para prevenir o bug de não editar
scanf(“%c”, &tipo);
} while (tipo != ‘F’ && tipo != ‘f’ &&
tipo != ‘J’ && tipo != ‘j’);
if (tipo == ‘F’ || tipo == ‘f’) {
printf(“CPF.........: “);
fflush(stdin); // Para prevenir o bug de não editar
scanf(“%s”, pessoa.cpf);
} else {
printf(“CNPJ........: “);
fflush(stdin); // Para prevenir o bug de não editar
scanf(“%s”, pessoa.cnpj);
}
printf(“\nNome..: %s\nPessoa: “, nome);
if (tipo == ‘F’ || tipo == ‘f’)
printf(“FISICA\nCPF...: %s\n”, pessoa.cpf);
else
printf(“JURIDICA\nCNPJ..: %s\n”, pessoa.cnpj);
return 0;
}
Quadro 15 – Exemplo de uso de uniões. Fonte: O autor.
101WWW.UNINGA.BR
AL
GO
RI
TM
OS
E
P
RO
GR
AM
AÇ
ÃO
A
PL
IC
AD
A
| U
NI
DA
DE
3
EDUCAÇÃO A DISTÂNCIA
As uniões possuem grande utilidade em programas que precisam de conversão
de tipo ou portabilidade. No primeiro caso, podemos referenciar os dados
contidos um uma união de maneiras diferentes; no segundo, o compilador não
perde o tamanho das variáveis que compõem uma união, possibilitando assim
independência de máquina (SCHILDT, 1996).
O conceito de registros e estruturas nos leva
a um pequeno pedaço de outro paradigma de
programação que vem dominando o mundo
da informática nos dias atuais: a Programação
Orientada a Objetos – POO. Este livro ensina os
conceitos básicos que envolvem este paradigma,
como classes, objetos, encapsulamento, herança
etc. Ideal para quem deseja um contato inicial
com este novo mundo.
SINTES, A. Aprenda Programação Orientada
a Objetos em 21 dias. São Paulo: Pearson
Education do Brasil, 2002.
Fonte: Sintes (2002)
102WWW.UNINGA.BR
AL
GO
RI
TM
OS
E
P
RO
GR
AM
AÇ
ÃO
A
PL
IC
AD
A
| U
NI
DA
DE
3
EDUCAÇÃO A DISTÂNCIA
CONSIDERAÇÕES FINAIS
Nesta unidade, foram abordadas as estruturas voltadas para o armazenamento de dados.
Iniciamos abordando as estruturas de dados homogêneas, que permitem o agrupamento de
dados do mesmo tipo sob a referência de um único identificador.
Descrevemos os vetores, estruturas de dados de uma dimensão, e como manipular seus
elementos por meio da leitura, escrita, busca e ordenação. Em seguida, abordamos as strings, que
em C são vetores de chars; descrevendo como são manipuladas e apresentamos algumas funções
da biblioteca padrão para tal.
Em seguida, abordamos as matrizes, estruturas de dados de duas ou mais dimensões, e
descrevemos como vetores de strings são implementados na linguagem.
Finalizamos a unidade abordando as estruturas de dados heterogêneas, mais conhecidas
como registros, que em C são implementadas por meio de estruturas. Abordamos como declarar
estruturas e manipular seus membros, bem como criar novos tipos de dados usando o comando
typedef e explicar a diferença entre estruturas e uniões.
103103WWW.UNINGA.BR
U N I D A D E
04
SUMÁRIO DA UNIDADE
INTRODUÇÃO ...............................................................................................................................................................105
1 SUB-ROTINAS ...........................................................................................................................................................106
1.1 PROTOTIPAGEM ..................................................................................................................................................... 112
1.2 RETORNO DE VALORES EM FUNÇÕES ...............................................................................................................116
2 ESCOPO DE VARIÁVEIS ........................................................................................................................................... 117
2.1 VARIÁVEIS LOCAIS ................................................................................................................................................ 117
2.2 VARIÁVEIS GLOBAIS .............................................................................................................................................118
2.3 VARIÁVEIS EXTERNAS .........................................................................................................................................119
2.4 VARIÁVEIS ESTÁTICAS .........................................................................................................................................120
2.5 VARIÁVEIS DE REGISTRO .................................................................................................................................... 121
3 PONTEIROS ..............................................................................................................................................................122
MODULARIZAÇÃO DE PROGRAMAS
PROF. FÁBIO ATAIDE DE LIMA
ENSINO A DISTÂNCIA
DISCIPLINA:
ALGORITMOS E PROGRAMAÇÃO APLICADA
104WWW.UNINGA.BR
EDUCAÇÃO A DISTÂNCIA
3.1 OPERADOR SIZEOF ...............................................................................................................................................124
3.2 PONTEIROS DE ESTRUTURAS E UNIÕES ..........................................................................................................125
4 PASSAGEM DE PARÂMETROS ................................................................................................................................126
4.1 PASSAGEM DE PARÂMETROS POR VALOR ........................................................................................................130
4.2 PASSAGEM DE PARÂMETROS POR REFERÊNCIA ............................................................................................ 131
5 RECURSIVIDADE ......................................................................................................................................................132
CONSIDERAÇÕES FINAIS ...........................................................................................................................................134
105WWW.UNINGA.BR
AL
GO
RI
TM
OS
E
P
RO
GR
AM
AÇ
ÃO
A
PL
IC
AD
A
| U
NI
DA
DE
4
EDUCAÇÃO A DISTÂNCIA
INTRODUÇÃO
Existem certos problemas que possuem uma escala de grandeza e complexidade tal que
algoritmos muito simples não são capazes de resolver. Segundo Forbellone e Eberspächer (2005, p.
127), “[...] um problema complexo pode ser simplificado quando dividido em vários problemas”.
Seguindo esta abordagem, vários paradigmas de programação foram criados, dentre
eles, a programação estruturada, cuja característica “é a utilização de técnicas que decompõem a
solução de um problema em ‘blocos’ que interagem com um bloco principal” (XAVIER, 2011, p.
221).
Nesse processo de divisãoou modularização dos problemas, utilizamos as sub-rotinas.
Também chamadas de subprogramas, são trechos menores de código que realizam tarefas
específicas, destinados a resolver uma parte do problema como um todo (ASCENCIO; CAMPOS,
2010).
Daremos início a esta unidade abordando os dois tipos de sub-rotinas existentes:
procedimentos e funções, estas últimas implementadas em C. Relacionados a este assunto estão
os escopos de variáveis, onde explicaremos com mais detalhes a diferença entre variáveis locais e
globais, além de outras classes de variáveis em C.
Em seguida, descreveremos ponteiros com mais detalhes do que foi introduzido na
Unidade I, explicando como utilizar seus operadores e destacando a sua importância no contexto
do assunto seguinte: o mecanismo de passagem de parâmetros.
Abordaremos o conceito da passagem de parâmetros e como ele auxilia na construção
de sub-rotinas mais genéricas e reaproveitáveis. Dentro desse assunto, estaremos explicando a
diferença entre passagem de parâmetros por valor e por referência.
Para finalizar a unidade, será abordado o conceito de recursividade, outro recurso
importante na programação estruturada, e suas aplicações na lógica de programação.
106WWW.UNINGA.BR
AL
GO
RI
TM
OS
E
P
RO
GR
AM
AÇ
ÃO
A
PL
IC
AD
A
| U
NI
DA
DE
4
EDUCAÇÃO A DISTÂNCIA
1 SUB-ROTINAS
Sub-rotinas são blocos de instruções com um início e um fim, identificados por um nome
que pode ser usado para chamá-los de qualquer parte do programa. Podem ser classificados em
procedimentos e funções, sendo que a principal diferença é que as funções sempre retornam
um dado de determinado tipo para o programa ou rotina que a chamou, ao passo que os
procedimentos não retornam nada (MANZANO; OLIVEIRA, 2012).
Lopes e Garcia (2002) destacam que dentre as várias vantagens do seu uso estão:
• Dividir e estruturar um programa em partes logicamente coerentes e testar estes trechos
isoladamente;
• Evitar duplicação de código, uma vez que funções e procedimentos podem ser chamados
quantas vezes forem necessárias;
• Possibilidade de o programador criar sua própria biblioteca de funções e procedimentos,
generalizando e padronizando algumas tarefas e comportamentos.
A Figura 1 a seguir ilustra o algoritmo de ida ao trabalho, apresentado na Unidade I,
contendo duas instruções detalhadas em blocos separados, simulando o funcionamento de uma
sub-rotina.
Figura 1 – Exemplo de algoritmo com instruções detalhadas em sub-rotinas. Fonte: O autor.
107WWW.UNINGA.BR
AL
GO
RI
TM
OS
E
P
RO
GR
AM
AÇ
ÃO
A
PL
IC
AD
A
| U
NI
DA
DE
4
EDUCAÇÃO A DISTÂNCIA
Em C, apenas funções são implementadas – veremos que a criação de um procedimento
na linguagem é uma função do tipo void, ou seja, não retorna valor. O Quadro 1 a seguir apresenta
a sintaxe geral para a criação de uma função.
tipo identificador(parâmetros)
{
...
instruções;
...
return valor;
}
Quadro 1 – Sintaxe para a criação de funções em C. Fonte: Adaptado de Schildt (1996).
Onde:
• tipo: tipo de dado a ser retornado pela função. Pode ser um tipo de dado primitivo ou
definido pelo usuário com typedef;
• identificador: nome da função. Deve seguir as regras de nomenclatura de identificadores
apresentadas na seção 4 da Unidade I;
• parâmetros: variáveis de entrada. Embora sejam opcionais, é bom costume colocar void
entre os parênteses quando não houver parâmetros, para evitar mensagens de advertência
em alguns compiladores;
• instruções: comandos a serem executados dentro da função, começando pela declaração
de todas as variáveis a serem usadas;
• valor: dado a ser retornado para a função chamadora, cujo tipo deve ser igual ao tipo
declarado para a função.
O comando return pode ser executado quantas vezes necessárias dentro de uma função,
geralmente dentro de ifs e no final, e pode ser usado isoladamente, bem como ser omitido,
somente nas funções declaradas como void em seu tipo – funções que não retornam valor.
108WWW.UNINGA.BR
AL
GO
RI
TM
OS
E
P
RO
GR
AM
AÇ
ÃO
A
PL
IC
AD
A
| U
NI
DA
DE
4
EDUCAÇÃO A DISTÂNCIA
O Quadro 2 a seguir exemplifica o uso de uma função void que é chamada duas vezes
seguidas pela função main().
#include <stdio.h>
void soma(void) {
float num1, num2;
printf(“Digite o primeiro numero: “);
scanf(“%f”, &num1);
printf(“Digite o segundo numero.: “);
scanf(“%f”, &num2);
printf(“A soma eh %.2f\n\n”, num1 + num2);
}
int main(void) {
soma();
soma();
return 0;
}
Quadro 2 – Exemplo do uso de funções. Fonte: Adaptado de Schildt (1996).
Lembre-se que a execução de qualquer programa em C inicia sempre na função main().
Nesse exemplo, ao chamar a função soma() pela primeira vez, o fluxo desviará para o bloco de
instruções da função; ao terminar, o fluxo volta para a linha seguinte na função main(), que
chamará a função novamente e executará suas instruções (BACKES, 2016). O resultado da
execução deste programa é ilustrado na Figura 2 a seguir.
Figura 2 – Resultado da execução do programa do Quadro 2. Fonte: O autor.
Uma forma alternativa de se implementar o programa do Quadro 2 sem o uso de uma
segunda função seria colocar o bloco de instruções contido na função soma() em um laço que se
repetiria duas vezes na função main(). Isso comprova a tese de que vários caminhos podem ser
usados na solução de um problema em forma de algoritmo.
109WWW.UNINGA.BR
AL
GO
RI
TM
OS
E
P
RO
GR
AM
AÇ
ÃO
A
PL
IC
AD
A
| U
NI
DA
DE
4
EDUCAÇÃO A DISTÂNCIA
Com uma proposta inovadora, esta obra conecta
várias disciplinas da computação a aspectos
históricos do pensamento humano, da lógica dos
filósofos gregos e da organização da sociedade
no decorrer do tempo. Ao longo de sete capítulos,
você compreenderá o uso de muitos dos conceitos
de computação que são empregados hoje e terá
a possibilidade de aprender sobre temas como
programação computacional, banco de dados e
Linguagem de Consulta Estruturada (SQL).
SOUZA, M. F. F. Computadores e sociedade: da
filosofia às linguagens de programação. Curitiba:
InterSaberes, 2016. Fonte: Souza (2016).
110WWW.UNINGA.BR
AL
GO
RI
TM
OS
E
P
RO
GR
AM
AÇ
ÃO
A
PL
IC
AD
A
| U
NI
DA
DE
4
EDUCAÇÃO A DISTÂNCIA
O próximo exemplo, ilustrado no Quadro 3 a seguir, simula uma calculadora onde o
usuário escolhe a operação em um menu e o programa chama a função referente.
#include <stdio.h>
void soma(void) {
float num1, num2;
printf(“\nFuncao SOMA\n”);
printf(“Primeiro numero: “);
scanf(“%f”, &num1);
printf(“Segundo numero.: “);
scanf(“%f”, &num2);
printf(“Resultado da soma: %.2f\n\n”, num1 + num2);
}
void subtracao(void) {
float num1, num2;
printf(“\nFuncao SUBTRACAO\n”);
printf(“Primeiro numero: “);
scanf(“%f”, &num1);
printf(“Segundo numero.: “);
scanf(“%f”, &num2);
printf(“Resultado da subtracao: %.2f\n\n”, num1 - num2);
}
void multiplicacao(void) {
float num1, num2;
printf(“\nFuncao MULTIPLICACAO\n”);
printf(“Primeiro numero: “);
scanf(“%f”, &num1);
printf(“Segundo numero.: “);
scanf(“%f”, &num2);
printf(“Resultado da multiplicacao: %.2f\n\n”, num1 * num2);
}
void divisao(void) {
float num1, num2;
printf(“\nFuncao DIVISAO\n”);
printf(“Primeiro numero..: “);
scanf(“%f”, &num1);
printf(“Segundo numero...: “);
do {
scanf(“%f”, &num2);
} while (num2 == 0);
printf(“Resultado da divisao: %.2f\n\n”, num1 / num2);
}
111WWW.UNINGA.BR
AL
GO
RI
TM
OS
E
P
RO
GR
AM
AÇ
ÃO
A
PL
IC
AD
A
| U
NI
DA
DE
4
EDUCAÇÃO A DISTÂNCIA
int main(void) {
int opcao;
while (opcao != 5) {
printf(“1 - Adicao\n”);
printf(“2 - Subtracao\n”);
printf(“3 - Multiplicacao\n”);
printf(“4 - Divisao\n”);
printf(“5 - Sair\n”);
printf(“Opcao: “);
scanf(“%d”, &opcao);
switch (opcao) {
case 1: soma(); break;
case 2: subtracao(); break;case 3: multiplicacao(); break;
case 4: divisao(); break;
}
}
return 0;
}
Quadro 3 – Exemplo de um programa de calculadora. Fonte: Adaptado de Schildt (1996).
Nesse exemplo, quando uma opção é selecionada, o programa desvia o fluxo para a função
referente e depois volta para o menu, onde o usuário poderá selecionar outra opção, a mesma que
a anterior ou escolher sair do programa. É muito comum o uso de menus em grandes aplicações,
onde suas rotinas são modularizadas.
De acordo com Schildt (1996, p. 139), “[...] em C, todas as funções estão no mesmo
nível de escopo. Isto é, não é possível definir uma função internamente a uma
função. Esta é a razão de C não ser tecnicamente uma linguagem estruturada em
blocos”.
112WWW.UNINGA.BR
AL
GO
RI
TM
OS
E
P
RO
GR
AM
AÇ
ÃO
A
PL
IC
AD
A
| U
NI
DA
DE
4
EDUCAÇÃO A DISTÂNCIA
1.1 Prototipagem
Repare nos exemplos apresentados até o momento que as funções auxiliares em um
programa foram escritas antes da função main(). Segundo Backes (2016), esta é uma regra do uso
de funções na linguagem C: toda função chamada por outra deve ser escrita antes no programa,
sob pena de erro na hora da compilação. Dessa forma, a função main() sempre será a última a ser
escrita – isto acaba gerando uma certa dificuldade de navegação pelo código.
Para resolver isso, ou seja, escrever as funções na ordem em que são executadas, utilizamos
um recurso chamado prototipagem de funções. Quando criamos um protótipo de função,
estamos, na verdade, declarando uma função, ou seja, indicamos para main() que tal função
existe, mas o código dela está em algum outro lugar no programa. Dessa forma, o programa
fica mais fácil de ler, podendo main() ser a primeira função a ser escrita e as demais funções em
seguida (SCHILDT, 1996).
A sintaxe geral para prototipagem de uma função é:
tipo função(parâmetros);
113WWW.UNINGA.BR
AL
GO
RI
TM
OS
E
P
RO
GR
AM
AÇ
ÃO
A
PL
IC
AD
A
| U
NI
DA
DE
4
EDUCAÇÃO A DISTÂNCIA
Essa declaração é colocada no início do programa, geralmente logo após a inclusão dos
arquivos de cabeçalho-padrão, conforme ilustrado no Quadro 4 a seguir, que traz uma adaptação
do programa do Quadro 3 com o uso de protótipos.
#include <stdio.h>
// Prototipagem das funções
void soma(void);
void subtracao(void);
void multiplicacao(void);
void divisao(void);
int main(void) {
int opcao;
while (opcao != 5) {
printf(“1 - Adicao\n”);
printf(“2 - Subtracao\n”);
printf(“3 - Multiplicacao\n”);
printf(“4 - Divisao\n”);
printf(“5 - Sair\n”);
printf(“Opcao: “);
scanf(“%d”, &opcao);
switch (opcao) {
case 1: soma(); break;
case 2: subtracao(); break;
case 3: multiplicacao(); break;
case 4: divisao(); break;
}
}
return 0;
}
void soma(void) {
float num1, num2;
printf(“\nFuncao SOMA\n”);
printf(“Primeiro numero: “);
scanf(“%f”, &num1);
printf(“Segundo numero.: “);
scanf(“%f”, &num2);
printf(“Resultado da soma: %.2f\n\n”, num1 + num2);
}
114WWW.UNINGA.BR
AL
GO
RI
TM
OS
E
P
RO
GR
AM
AÇ
ÃO
A
PL
IC
AD
A
| U
NI
DA
DE
4
EDUCAÇÃO A DISTÂNCIA
void subtracao(void) {
float num1, num2;
printf(“\nFuncao SUBTRACAO\n”);
printf(“Primeiro numero: “);
scanf(“%f”, &num1);
printf(“Segundo numero.: “);
scanf(“%f”, &num2);
printf(“Resultado da subtracao: %.2f\n\n”, num1 - num2);
}
void multiplicacao(void) {
float num1, num2;
printf(“\nFuncao MULTIPLICACAO\n”);
printf(“Primeiro numero: “);
scanf(“%f”, &num1);
printf(“Segundo numero.: “);
scanf(“%f”, &num2);
printf(“Resultado da multiplicacao: %.2f\n\n”, num1 * num2);
}
void divisao(void) {
float num1, num2;
printf(“\nFuncao DIVISAO\n”);
printf(“Primeiro numero..: “);
scanf(“%f”, &num1);
printf(“Segundo numero...: “);
do {
scanf(“%f”, &num2);
} while (num2 == 0);
printf(“Resultado da divisao: %.2f\n\n”, num1 / num2);
}
Quadro 4 – Programa de calculadora com prototipagem. Fonte: Adaptado de Schildt (1996).
115WWW.UNINGA.BR
AL
GO
RI
TM
OS
E
P
RO
GR
AM
AÇ
ÃO
A
PL
IC
AD
A
| U
NI
DA
DE
4
EDUCAÇÃO A DISTÂNCIA
A prototipagem de funções é interessante de se usar em programas extensos, que contém
um número razoável de funções, como no caso da calculadora do Quadro 4. Em programas mais
simples e curtos, com apenas uma ou duas funções auxiliares, talvez seja mais conveniente omitir
a prototipagem. Assumiremos assim deste ponto.
Os protótipos de funções são usados pelo compilador para validar as chamadas
de função, pois informam o tipo de dado retornado pela função, o número, o tipo e
a ordem dos parâmetros que a função espera receber. Portanto, servem como uma
espécie de “assinatura” das funções para serem validadas tanto na compilação
– em resolver chamadas a funções – quanto na execução do programa – em
armazenar estas funções na memória e gerenciá-las na pilha de execução. Se não
houver protótipo para uma função, o compilador assume o cabeçalho da definição
da função para determinar sua “assinatura” (DEITEL, 2011).
116WWW.UNINGA.BR
AL
GO
RI
TM
OS
E
P
RO
GR
AM
AÇ
ÃO
A
PL
IC
AD
A
| U
NI
DA
DE
4
EDUCAÇÃO A DISTÂNCIA
1.2 Retorno de Valores em Funções
Funções do tipo void devem ser chamadas isoladamente em uma linha de instrução,
conforme os exemplos ilustrados até o momento. Funções que retornam valores, por sua vez,
podem ser consideradas como expressões e também fazer parte de outras operações de saída ou
de processamento lógico ou matemático, desde que o tipo de dado retornado seja compatível
(MANZANO; OLIVEIRA, 2010).
O Quadro 5 a seguir exemplifica uma função genérica de confirmação que é usada para perguntar
se o usuário deseja repetir a operação principal do programa.
#include <stdio.h>
int confirma(void) {
char conf;
do {
printf(“\nConfirma (S/N): “);
fflush(stdin); // Para prevenir o bug de não editar
scanf(“%c”, &conf);
} while (conf != ‘S’ && conf != ‘s’ &&
conf != ‘N’ && conf != ‘n’);
return conf == ‘S’ || conf == ‘s’;
}
int main(void) {
int numero;
do {
printf(“Digite um numero: “);
scanf(“%d”, &numero);
printf(“%d ao quadrado = %d”, numero, numero * numero);
printf(“\nDeseja repetir a operacao?”);
} while (confirma());
return 0;
}
Quadro 5 – Exemplo de função que retorna valor. Fonte: O autor.
Como funções e procedimentos possuem a finalidade de estruturar determinadas tarefas
em programas menores, haverá variáveis que terão a necessidade de existirem apenas dentro
delas; outras terão que existir durante toda a execução do programa, mas visíveis apenas em
algumas partes. É por esta razão que podemos declarar variáveis com um determinado escopo,
assunto abordado na seção seguinte.
117WWW.UNINGA.BR
AL
GO
RI
TM
OS
E
P
RO
GR
AM
AÇ
ÃO
A
PL
IC
AD
A
| U
NI
DA
DE
4
EDUCAÇÃO A DISTÂNCIA
2 ESCOPO DE VARIÁVEIS
Segundo Manzano e Oliveira (2012), o escopo de uma variável está vinculado a duas
coisas: à forma de sua visibilidade e ao seu tempo de vida no programa em relação às sub-rotinas
que ele possui. Conceitualmente falando, as variáveis podem ter escopo global ou local, sendo
que em C é possível declarar variáveis locais, globais, externas, estáticas ou de registro.
2.1 Variáveis Locais
As variáveis locais são visíveis apenas dentro da função onde foram declaradas e são
removidas da memória assim que a mesma encerra sua execução; além disto, não são visíveis em
outras funções chamadas por ela (SCHILDT, 1996).
O Quadro 6 a seguir exemplifica isso, com uma ilustração da abrangência destas variáveis
dentro do programa.
void rotina1_1(void) {
int valorW = 47;
}
void rotina1_2(void) {
int valorY = 25;
}
void rotina2_1(void) {
int valorX = 120;
}
void rotina1(void) {
int valorA = 12, valorX = 23;rotina1_1();
rotina1_2();
}
void rotina2(void) {
int valorM = 12;
rotina2_1();
}
int main(void) {
int valorA = 5, valorB = 10;
rotina1();
rotina2();
return 0;
}
Quadro 6 – Exemplos de variáveis locais. Fonte: Adaptado de Manzano e Oliveira (2012).
Todas as variáveis existentes no Quadro 6 são visíveis apenas em suas respectivas funções,
ilustradas pelos retângulos de tonalidades diferentes; portanto não há problema em declarar
uma variável local com nome já usado em outra função, pois elas estarão armazenadas em locais
diferentes na memória do computador.
118WWW.UNINGA.BR
AL
GO
RI
TM
OS
E
P
RO
GR
AM
AÇ
ÃO
A
PL
IC
AD
A
| U
NI
DA
DE
4
EDUCAÇÃO A DISTÂNCIA
Em todos os exemplos apresentados até aqui, note que todas as variáveis foram declaradas
dentro do escopo de suas funções, seja main() ou qualquer outra. Isso significa que todas estas
variáveis possuem escopo local.
2.2 Variáveis Globais
As variáveis globais são visíveis em qualquer parte do programa e são removidas da
memória apenas quando o programa encerra sua execução. São declaradas fora do escopo de
qualquer função, geralmente no início do programa após a inclusão dos cabeçalhos-padrão e dos
protótipos de funções (MANZANO; OLIVEIRA, 2012).
O Quadro 7 a seguir traz uma adaptação do programa do Quadro 2, para ilustrar o uso
de variáveis globais.
#include <stdio.h>
float num1, num2;
void soma(void) {
printf(“Digite o primeiro numero: “);
scanf(“%f”, &num1);
printf(“Digite o segundo numero.: “);
scanf(“%f”, &num2);
printf(“A soma eh %.2f\n\n”, num1 + num2);
}
int main(void) {
soma();
soma();
printf(“num1=%f, num2=%f”, num1, num2);
return 0;
}
Quadro 7 – Exemplos de variáveis globais. Fonte: O autor.
Colocamos um printf() adicional na função main() para mostrar que as variáveis num1
e num2 também são visíveis nela e os valores a serem exibidos serão os que foram armazenados
na última chamada à função soma().
119WWW.UNINGA.BR
AL
GO
RI
TM
OS
E
P
RO
GR
AM
AÇ
ÃO
A
PL
IC
AD
A
| U
NI
DA
DE
4
EDUCAÇÃO A DISTÂNCIA
2.3 Variáveis Externas
Em projetos de grandes aplicações, é comum o uso de vários arquivos de programas que
são compilados e depois linkados em conjunto com as bibliotecas necessárias para a geração de
um arquivo executável final. As variáveis globais declaradas em um arquivo podem ser acessadas
e manipuladas em outros arquivos de programa por meio do comando extern (SCHILDT, 1996).
O Quadro 8 a seguir ilustra dois arquivos de programas, onde variáveis globais são
declaradas em um e referenciadas como externas em outro.
Arquivo1.c Arquivo2.c
int x, y;
char ch;
int main(void) {
...
}
void func1(void) {
x = 123;
}
extern int x, y;
extern char ch;
void func22(void) {
x = y / 10;
}
void func23(void) {
y = 10;
}
Quadro 8 – Exemplos de variáveis externas. Fonte: Schildt (1996).
É recomendável declarar todas as variáveis globais necessárias em apenas um
arquivo de programa – de preferência onde encontra-se a função main() – e nos
demais programas referenciá-las como extern. A redeclaração dessas variáveis
em cada arquivo sem o comando extern passará no processo de compilação, mas
resultará em erro de duplicidade no processo de linkagem por não se saber qual
variável usar (SCHIDLT, 1996).
120WWW.UNINGA.BR
AL
GO
RI
TM
OS
E
P
RO
GR
AM
AÇ
ÃO
A
PL
IC
AD
A
| U
NI
DA
DE
4
EDUCAÇÃO A DISTÂNCIA
2.4 Variáveis Estáticas
Variáveis estáticas possuem escopo restrito à função ou ao arquivo em que foi declarada;
porém, ao contrário das variáveis locais, são mantidas na memória após a execução da função,
preservando assim o seu conteúdo. Dessa forma, uma chamada posterior a esta função recuperará
o último valor atribuído a esta variável. Em C, elas são declaradas com o comando static
(SCHILDT, 1996).
O Quadro 9 a seguir ilustra um exemplo de uso de variável estática, para contar o número
de vezes que a função foi chamada.
#include <stdio.h>
void funcao1(void) {
static int vezes;
printf(“%d\n”, ++vezes);
}
int main(void) {
int i;
for (i = 1; i <= 10; i++)
funcao1();
return 0;
}
Quadro 9 – Exemplo de variável estática. Fonte: O autor.
Segundo Deitel (2011), toda variável estática declarada sem atribuição de valor recebe
o valor inicial de zero. Se no exemplo do Quadro 9 a variável vezes tivesse recebido alguma
atribuição de valor, esse valor seria apenas o valor inicial, atribuído apenas uma vez.
O resultado da execução deste programa é ilustrado na Figura 3 a seguir.
Figura 3 – Resultado da execução do programa do Quadro 9. Fonte: O autor.
Uma variável estática declarada fora do escopo de alguma função terá visibilidade apenas
no arquivo de programa em que foi declarada. Isso significa que ela não poderá ser referenciada
em outros arquivos de programa, nem como externas (DEITEL, 2011).
121WWW.UNINGA.BR
AL
GO
RI
TM
OS
E
P
RO
GR
AM
AÇ
ÃO
A
PL
IC
AD
A
| U
NI
DA
DE
4
EDUCAÇÃO A DISTÂNCIA
2.5 Variáveis de Registro
Variáveis de registro são declaradas com o comando register, que solicita ao compilador
para armazenar estas variáveis no registrador da CPU, ao invés de armazená-las na memória
RAM como qualquer outra variável, segundo Deitel (2011):
Se variáveis muito utilizadas, como contadores ou totais, puderem ser mantidas
nos registradores do hardware, poderemos eliminar o overhead da carga
repetitiva das variáveis da memória para os registradores e o armazenamento
dos resultados na memória (DEITEL, 2011, p. 133).
Em outras palavras, variáveis usadas em laços de repetição para controle do laço ou para
acúmulo de valores podem ser declaradas como register e aumentar o desempenho em tempo de
execução, notado especialmente em laços com milhares ou milhões de iterações.
O Quadro 10 a seguir traz uma adaptação do programa de exemplo na seção anterior,
declarando a variável usada no for como de registro.
#include <stdio.h>
void funcao1(void) {
static int vezes;
printf(“%d\n”, ++vezes);
}
int main(void) {
register int i;
for (i = 1; i <= 10; i++)
funcao1();
return 0;
}
Quadro 10 – Exemplo de variável de registro. Fonte: O autor.
Embora pareça mais conveniente declarar todas as variáveis como globais, devido
à sua facilidade de acesso em todos os arquivos de programa, elas ferem um
dos princípios fundamentais da Engenharia de Software: o “Princípio do Menor
Privilégio”, que defende o acesso aos dados somente quando eles são necessários.
Além disso, variáveis globais podem ter sido atribuídas em qualquer lugar e isso
dificulta seu rastreamento, principalmente quando se precisa identificar e corrigir
falhas em sistemas grandes que contêm muitos arquivos e são divididos em
vários módulos. Por essas razões, recomenda-se fortemente a preferência por
variáveis locais (DEITEL, 2011).
122WWW.UNINGA.BR
AL
GO
RI
TM
OS
E
P
RO
GR
AM
AÇ
ÃO
A
PL
IC
AD
A
| U
NI
DA
DE
4
EDUCAÇÃO A DISTÂNCIA
Se as variáveis locais são mais recomendadas, como fazer para que o seu conteúdo
seja visto por outras funções, já que sua visibilidade é restrita? A solução está na passagem de
parâmetros, assunto abordado na seção 4 desta unidade.
3 PONTEIROS
Ponteiros são variáveis que armazenam um endereço de memória. Geralmente, esse
endereço é a posição de outra variável da memória, por isso, o ponteiro “aponta” para outra
variável (SCHILDT, 1996), conforme ilustrado na Figura 4 a seguir.
Figura 4 – Uma variável apontando para outra na memória. Fonte: Adaptado de Schildt (1996).
No exemplo da Figura 4, temos a variável valor que está armazenada no endereço 1003
da memória; temos também a variável ptr que está armazenando este endereço. Assim, dizemos
que ptr está apontando para valor.
Existem dois operadores para manipular ponteiros, segundo Deitel (2011):
• &: operador denominado referência. Serve para retornar o endereço de memória de uma
variável, de modo que ele possa serpassado por parâmetro ou atribuído em uma variável
de ponteiro;
• *: operador denominado derreferência. Tem duas utilidades: informar que determinada
variável será um ponteiro para o tipo de dado declarado; e retornar o conteúdo do
endereço de memória para o qual a variável está apontando.
O Quadro 11 a seguir ilustra alguns exemplos de declaração de ponteiros
char *pLetra; // Ponteiro para um caractere
int *pInteiro; // Ponteiro para um inteiro
float *pFlutu; // Ponteiro para um ponto flutuante
double *pDouble; // Ponteiro para um ponto flutuante dupla precisão
void *pVoid; // Ponteiro genérico (pode aplicar cast depois)
Quadro 11 – Exemplos de declaração de variáveis de ponteiro. Fonte: O autor.
123WWW.UNINGA.BR
AL
GO
RI
TM
OS
E
P
RO
GR
AM
AÇ
ÃO
A
PL
IC
AD
A
| U
NI
DA
DE
4
EDUCAÇÃO A DISTÂNCIA
Embora ponteiros genéricos possam ser criados, declarando como void*, é recomendável
associá-los ao referido tipo de dado, se souber previamente. A razão disto está em que vetores
são na verdade ponteiros para o seu primeiro elemento, e o tipo correto torna preciso o acesso e
a manipulação dos seus elementos na memória.
Variáveis de ponteiro podem ser inicializadas com NULL ou um endereço válido de
memória. Caso não recebam atribuição em breve após serem declaradas, é recomendável que
sejam inicializadas com NULL, para evitar o risco de receberem algum “lixo” aleatório da
memória (DEITEL, 2011).
O Quadro 12 a seguir ilustra um exemplo de ponteiro para uma variável inteira e uma
representação fictícia da memória armazenando ambas as variáveis.
#include <stdio.h>
int main(void) {
int x, *ptr;
x = 5;
ptr = &x;
printf(“O valor da variavel X eh: %d\n”, *ptr);
*ptr = 10;
printf(“Agora, X vale: %d\n”, *ptr);
return 0;
}
Quadro 12 – Ponteiro para uma variável do tipo inteiro. Fonte: O autor.
Ponteiros são fundamentais na passagem de vetores e strings por parâmetro e na passagem
de parâmetros por referência, assuntos abordados na seção 4 desta unidade.
124WWW.UNINGA.BR
AL
GO
RI
TM
OS
E
P
RO
GR
AM
AÇ
ÃO
A
PL
IC
AD
A
| U
NI
DA
DE
4
EDUCAÇÃO A DISTÂNCIA
3.1 Operador sizeof
O operador unário sizeof obtém o tamanho de uma variável ou especificador de tipo
de dado. Seu operando deve estar entre parênteses se for um especificador de tipo, sob pena de
erro na compilação; por outro lado, os parênteses são opcionais em variáveis (SCHILDT, 1996).
Dependendo do compilador, especificadores de tipo contendo uma única palavra também podem
vir sem parênteses (DEITEL, 2011).
O Quadro 13 a seguir ilustra alguns exemplos do uso de sizeof.
#include <stdio.h>
struct data {
int dia;
int mes;
int ano;
};
union nota {
char letra;
float numero;
};
int main(void) {
int numero = 150, vint[5];
char letra = ‘A’, vchar[5];
printf(“Tamanho de numero......: %d\n”, sizeof numero);
printf(“Tamanho de letra.......: %d\n”, sizeof letra);
printf(“Tamanho de float.......: %d\n”, sizeof(float));
printf(“Tamanho de double......: %d\n”, sizeof(double));
printf(“Tamanho de long double.: %d\n”, sizeof(long double));
printf(“Tamanho de unsigned int: %d\n”, sizeof(unsigned int));
printf(“Tamanho de vint[5].....: %d\n”, sizeof vint);
printf(“Tamanho de vchar[5]....: %d\n”, sizeof vchar);
printf(“Tamanho de data........: %d\n”, sizeof(struct data));
printf(“Tamanho de nota........: %d\n”, sizeof(union nota));
return 0;
}
Quadro 13 – Obtendo o tamanho de variáveis e tipos de dados. Fonte: O autor.
125WWW.UNINGA.BR
AL
GO
RI
TM
OS
E
P
RO
GR
AM
AÇ
ÃO
A
PL
IC
AD
A
| U
NI
DA
DE
4
EDUCAÇÃO A DISTÂNCIA
O resultado da execução desse programa é ilustrado na Figura 5 a seguir.
Figura 5 – Resultado da execução do Quadro 13. Fonte: O autor.
Repare que nos vetores foi retornado o tamanho do tipo de dado multiplicado pelo
número de elementos, na estrutura foi retornada a soma dos tipos de dados de cada membro, e
na união foi retornado o tamanho do maior tipo de dado, no caso float.
O operador sizeof é muito usado em conjunto com ponteiros para um recurso avançado
da linguagem C chamado alocação dinâmica, em que é possível reservar memória em tempo de
execução. Além disto, sizeof permite portabilidade entre sistemas diferentes de computador, uma
vez que o número de bytes usados para armazenar determinado tipo de dado pode variar entre
certas máquinas e sistemas operacionais (DEITEL, 2011).
3.2 Ponteiros de Estruturas e Uniões
Além dos tipos de dados básicos da linguagem, ponteiros também podem ser declarados
com associação a uma estrutura ou união, conforme o exemplo do Quadro 14 a seguir.
#include <stdio.h>
struct data {
int dia;
int mes;
int ano;
};
int main(void) {
struct data hoje; // Variável de estrutura data
struct data *pHoje; // Ponteiro para estrutura data
hoje.dia = 4;
hoje.mes = 1;
hoje.ano = 2020;
pHoje = &hoje; // Armazena o endereço da estrutura no ponteiro
printf(“Hoje eh dia: %.2d/%.2d/%d\n”,
pHoje->dia, pHoje->mes, pHoje->ano);
return 0;
}
Quadro 14 – Exemplo de ponteiros para estruturas. Fonte: O autor.
126WWW.UNINGA.BR
AL
GO
RI
TM
OS
E
P
RO
GR
AM
AÇ
ÃO
A
PL
IC
AD
A
| U
NI
DA
DE
4
EDUCAÇÃO A DISTÂNCIA
Nesse exemplo, temos duas formas de referenciar a estrutura instanciada: pela variável
hoje e pelo ponteiro pHoje, que está apontando para hoje. Repare na diferença do operador de
acesso aos membros: enquanto uma variável de estrutura utiliza o operador de ponto (.), um
ponteiro utiliza o operador de seta (->).
O operador de seta foi criado para simplificar o acesso a membros de estrutura por
ponteiros, pois o operador de ponto tem precedência sobre o operador de ponteiro; por exemplo,
pHoje->dia é exatamente o mesmo que (*pHoje).dia. Já a expressão *pHoje.dia, por sua vez,
seria o acesso ao conteúdo do endereço armazenado no suposto ponteiro dia, membro de pHoje
– se fosse o caso (DEITEL, 2011).
4 PASSAGEM DE PARÂMETROS
De acordo com Manzano e Oliveira (2012):
O processo de passagem de parâmetro permite estabelecer uma linha de
comunicação entre os conteúdos dos trechos de sub-rotinas e dos trechos de
programa que chamam essas sub-rotinas, principalmente quando se usam
variáveis com escopo local (MANZANO; OLIVEIRA, 2012, p. 221).
Os parâmetros podem ser classificados como reais e formais. Os parâmetros reais são
constantes, variáveis ou expressões usadas no momento da chamada de uma sub-rotina para
que o seu conteúdo seja passado para ela; já os parâmetros formais são variáveis declaradas
juntamente com a sub-rotina, onde os parâmetros reais são armazenados para serem usados nela
(MANZANO; OLIVEIRA, 2012).
A sintaxe geral para a passagem de parâmetros para uma função em C é ilustrada no
Quadro 15 a seguir.
tipo funcao(tipo var1, tipo var2, ...)
{
declarações;
instruções;
...
}
Quadro 15 – Sintaxe para a passagem de parâmetros em C. Fonte: Adaptado de Backes (2016).
Cada variável de parâmetro deve ser declarada com um tipo, seja ele nativo da linguagem
ou criado pelo usuário. Essas variáveis são chamadas de parâmetros formais e possuem escopo
local, ou seja, existem apenas dentro da função onde foram declaradas e possuem o mesmo
comportamento de qualquer outra variável local. Já vimos que elas são opcionais, ou seja, a função
pode não receber nenhum parâmetro; nesse caso, colocamos void ou simplesmente nada entre os
parênteses, sendo que a primeira é mais segura do que esta última, pois assegura ao compilador
que a função não deve receber parâmetro sob pena de erro se isso acontecer (BACKES, 2016).
A ordem e o tipo dos parâmetros reais passados na chamada da função devem seguir a
ordem e o tipo dos parâmetros formais declarados, conforme a ilustração da Figura 6 a seguir,
sob pena de erro na compilação.
127WWW.UNINGA.BR
AL
GO
RI
TM
OS
E
P
RO
GR
AM
AÇ
ÃO
A
PL
IC
AD
A
| U
NI
DA
DE
4
EDUCAÇÃOA DISTÂNCIA
Figura 6 – Mecanismo de passagem de parâmetros. Fonte: O autor.
Esse exemplo da Figura 6 demonstra como o mecanismo de passagem de parâmetros
permite a criação de funções de uso genérico que podem ser facilmente reaproveitadas. O Quadro
16 a seguir, por exemplo, ilustra uma função para retornar o valor do maior número dentre três
recebidos por parâmetro.
#include <stdio.h>
int maior(int num1, int num2, int num3) {
int maior = num1;
if (maior < num2)
maior = num2;
if (maior < num3)
maior = num3;
return maior;
}
int main(void) {
int a, b, c;
printf(“Digite o numero a: “);
scanf(“%d”, &a);
printf(“Digite o numero b: “);
scanf(“%d”, &b);
printf(“Digite o numero c: “);
scanf(“%d”, &c);
printf(“O maior numero eh: %d\n”, maior(a, b, c));
return 0;
}
Quadro 16 – Função para retornar o maior número. Fonte: O autor.
128WWW.UNINGA.BR
AL
GO
RI
TM
OS
E
P
RO
GR
AM
AÇ
ÃO
A
PL
IC
AD
A
| U
NI
DA
DE
4
EDUCAÇÃO A DISTÂNCIA
A função maior() escrita neste exemplo do Quadro 16 poderia ser usada em qualquer
outro lugar do programa onde fosse necessário obter o maior número dentre três, bastando
apenas passá-los por parâmetro para a função.
O Quadro 17 a seguir apresenta uma adaptação da função de confirmação mostrada no
Quadro 5 desta unidade, permitindo receber por parâmetro a mensagem a ser mostrada.
#include <stdio.h>
int confirma(char mensagem[]) {
char conf;
do {
printf(“\n%s (S/N): “, mensagem);
fflush(stdin); // Para prevenir o bug de não editar
scanf(“%c”, &conf);
} while (conf != ‘S’ && conf != ‘s’ &&
conf != ‘N’ && conf != ‘n’);
return conf == ‘S’ || conf == ‘s’;
}
int main(void) {
int numero;
do {
printf(“Digite um numero: “);
scanf(“%d”, &numero);
printf(“%d ao quadrado = %d”, numero, numero * numero);
} while (confirma(“Deseja repetir a operacao?”));
return 0;
}
Quadro 17 – Função de confirmação com parâmetro. Fonte: O autor.
Repare nesse exemplo que mensagem é uma string, ou seja, um vetor de chars; todo vetor
recebido como parâmetro formal deve vir com o par de colchetes após o nome da variável. Como
um vetor na verdade é um ponteiro para o seu primeiro elemento, poderíamos também receber
este parâmetro como char *mensagem – o comportamento seria exatamente o mesmo neste caso
(DEITEL, 2011).
129WWW.UNINGA.BR
AL
GO
RI
TM
OS
E
P
RO
GR
AM
AÇ
ÃO
A
PL
IC
AD
A
| U
NI
DA
DE
4
EDUCAÇÃO A DISTÂNCIA
Nosso próximo exemplo apresenta uma função que recebe um vetor de floats por
parâmetro e retorna à média dos seus valores. Seu código é ilustrado no Quadro 18 a seguir.
#include <stdio.h>
float media(float vetor[], int tamanho) {
register int i;
float media = 0;
for (i = 0; i < tamanho; i++)
media += vetor[i];
return media / tamanho;
}
int main(void) {
register int i;
float notas[4];
for (i = 0; i < 4; i++) {
printf(“Digite a %da nota: “, i + 1);
scanf(“%f”, ¬as[i]);
}
printf(“Media: %.2f\n”, media(notas, 4));
return 0;
}
Quadro 18 – Função que retorna a média dos valores de um vetor. Fonte: O autor.
130WWW.UNINGA.BR
AL
GO
RI
TM
OS
E
P
RO
GR
AM
AÇ
ÃO
A
PL
IC
AD
A
| U
NI
DA
DE
4
EDUCAÇÃO A DISTÂNCIA
A passagem de parâmetros pode ocorrer por duas formas: por valor e por referência.
Abordamos estas duas formas com detalhes nas seções seguintes.
4.1 Passagem de Parâmetros por Valor
Na passagem de parâmetros por valor, uma cópia do valor do parâmetro real é criada
na memória e utilizada então pelo parâmetro formal, o que significa que qualquer alteração que
porventura seja feita na variável do parâmetro formal não afetará de forma alguma o valor original
do parâmetro real, preservando-o no momento em que a sub-rotina encerrar sua execução
(MANZANO; OLIVEIRA, 2012).
O Quadro 19 a seguir ilustra um exemplo de uma função que triplica o valor de uma
variável e retorna esse resultado para a função chamadora.
#include <stdio.h>
int triplo(int valor) {
valor *= 3;
return valor;
}
int main( void) {
int num, result;
printf(“Digite um numero: “);
scanf(“%d”, &num);
result = triplo(num);
printf(“\nTriplo de %d = %d\n”, num, result);
return 0;
}
Quadro 19 – Exemplo de passagem de parâmetros por valor. Fonte: O autor.
Nesse exemplo, apesar de a variável estar sendo modificada dentro da função triplo(),
o valor da variável original é mantido, conforme ilustrado no resultado do processamento do
programa. Esta regra também se aplicou em todos os exemplos anteriores em que passamos
variáveis por parâmetro: todas, exceto os vetores, foram passadas por valor para as respectivas
funções.
131WWW.UNINGA.BR
AL
GO
RI
TM
OS
E
P
RO
GR
AM
AÇ
ÃO
A
PL
IC
AD
A
| U
NI
DA
DE
4
EDUCAÇÃO A DISTÂNCIA
4.2 Passagem de Parâmetros por Referência
A passagem de parâmetros por referência só funciona com variáveis, cujo endereço de
memória onde está armazenada é passado para o parâmetro formal ao invés do seu valor. Dessa
forma, qualquer alteração que for feita na variável do parâmetro formal implicará na alteração
imediata do valor da variável do parâmetro real correspondente, mantendo o seu valor modificado
depois que a sub-rotina for encerrada (MANZANO; OLIVEIRA, 2012).
Já que é necessário o endereço da variável para passá-la por referência, em C, isto deve
ser feito por meio de ponteiros: no parâmetro real, passamos o endereço da variável usando
o operador referência & e, por conseguinte, recebemos no parâmetro formal uma variável de
ponteiro para o tipo do parâmetro real e tratamos esta variável dentro da função usando o
operador derreferência * (DEITEL, 2011).
O Quadro 20 a seguir traz uma adaptação da função triplo() exemplificada no Quadro
19, para receber a variável por referência e alterar seu valor dentro da função.
#include <stdio.h>
int triplo(int *valor) {
*valor *= 3;
return *valor;
}
int main(void) {
int num, result;
printf(“Digite um numero: “);
scanf(“%d”, &num);
result = triplo(&num);
printf(“\nTriplo de %d = %d\n”, num, result);
return 0;
}
Quadro 20 – Exemplo de passagem de parâmetros por referência. Fonte: O autor.
Nesse exemplo, foi passado o endereço da variável num por parâmetro para a função
triplo(), que, por sua vez, recebeu um ponteiro para ela. Repare que dentro da função foi
necessário usar o operador * para acessar o conteúdo do endereço de memória armazenado em
valor. Dessa forma, a variável original também foi modificada, confirme ilustrado no resultado
da execução do programa.
Para concluir, pelo fato de vetores já serem ponteiros, como já abordado, eles são
automaticamente passados por referência para as funções chamadas (DEITEL, 2011). Em todos
os exemplos anteriores que passamos vetores e strings por parâmetro para funções, eles foram
passados por referência.
132WWW.UNINGA.BR
AL
GO
RI
TM
OS
E
P
RO
GR
AM
AÇ
ÃO
A
PL
IC
AD
A
| U
NI
DA
DE
4
EDUCAÇÃO A DISTÂNCIA
5 RECURSIVIDADE
Recursividade é o nome dado ao mecanismo que permite a uma sub-rotina chamar a si
mesma direta ou indiretamente, com o propósito de executar determinados processamentos sem
a necessidade de um laço de repetição (MANZANO; OLIVEIRA, 2012).
Seu princípio consiste em diminuir o problema de forma sucessiva em um problema
menor até um ponto que sua simplicidade permita resolvê-lo de modo direto, isto é, sem recorrer
a si mesmo. A este tipo de abordagem damos o nome de “dividir para conquistar” (BACKES,
2016).
Para exemplificar o uso da recursividade, mostraremos duas versões de uma função que
retorna o fatorial de um número: usando um laço de repetição e usando recuresividade para fazer
o cálculo. Seu código é ilustrado no Quadro 21 a seguir.
int fatorial(int x) {
int i, result = 1;
for (i = 1; i <= x; i++)
result *= i;
return result;
}
intfatorial(int x) {
if (x == 0)
return 1;
else
return x * fatorial(x - 1);
}
Quadro 21 – Função de fatorial usando laço de repetição e recursividade. Fonte: Adaptado de Backes (2016).
Se passarmos 5 como parâmetro para qualquer uma dessas duas funções, obteremos como
retorno o valor 120, afinal: 5! = 5 x 4 x 3 x 2 x 1 = 120. No caso da versão à direita, cada chamada
da função fatorial() ocorre de forma a empilhar cada uma de suas instâncias em operação para
depois, no retorno, efetuar a multiplicação sucessiva, calculando assim o fatorial solicitado. Essa
lógica é ilustrada na Figura 7 a seguir.
Figura 7 – Esquema lógico da função de fatorial. Fonte: Adaptado de Manzano e Oliveira (2012).
133WWW.UNINGA.BR
AL
GO
RI
TM
OS
E
P
RO
GR
AM
AÇ
ÃO
A
PL
IC
AD
A
| U
NI
DA
DE
4
EDUCAÇÃO A DISTÂNCIA
Outro exemplo muito comum de recursividade é a Sequência de Fibonacci, que começa
com 0,1 e a partir daí cada termo subsequente corresponde à soma dos dois anteriores, compondo
assim a seguinte sequência: 0, 1, 1, 2, 3, 5, 8, 13, 21, 34, 55 etc. (BACKES, 2016). O Quadro 22 a
seguir ilustra um programa que pede a posição da sequência e retorna o valor correspondente
usando a função recursiva fibonacci().
#include <stdio.h>
int fibonacci(int x) {
if (x == 0 || x == 1)
return x;
else
return fibonacci(x-2) + fibonacci(x-1);
}
int main(void) {
int num;
printf(“Digite um numero inteiro: “);
scanf(“%d”, &num);
printf(“O fibonacci na posicao %d eh: %d\n”, num, fibonacci(num));
return 0;
}
Quadro 22 – Função recursiva que retorna o número da sequência de Fibonacci. Fonte: Adaptado de Backes (2016).
Segundo Manzano e Oliveira (2012), a recursividade tem uma vantagem e uma
desvantagem em programação. A vantagem é que esse processo torna o código mais elegante,
facilitando a abstração e a modularidade no desenvolvimento de funções que podem ser
complexas. A desvantagem é o efeito de empilhamento provocado, que pode consumir um espaço
de memória considerável do computador.
No exemplo do programa de Fibonacci, quanto mais alta for a posição do número da
sequência que se deseja saber, maior será o processamento e o consumo de memória para efetuar
os cálculos recursivos.
Programação em C/C++ - Aula 54 - Torre de Hanoi (Recursiva)
Mais um exemplo interessante de recursividade. O vídeo explica
o desafio do quebra-cabeça e uma solução recursiva utilizando a
linguagem C++.
Disponível em: https://www.youtube.com/watch?v=X-I53cLjidg
134WWW.UNINGA.BR
AL
GO
RI
TM
OS
E
P
RO
GR
AM
AÇ
ÃO
A
PL
IC
AD
A
| U
NI
DA
DE
4
EDUCAÇÃO A DISTÂNCIA
CONSIDERAÇÕES FINAIS
Nesta unidade, foram abordados os conceitos da modularização de programas e
da importância de suas aplicações, como por exemplo o reaproveitamento de código e o
desenvolvimento de rotinas genéricas.
Iniciamos a unidade abordando as sub-rotinas, que podem ser classificadas em
procedimentos e funções. A diferença está em que as funções retornam valor e os procedimentos
não retornam nada. Em C, as sub-rotinas são implementadas apenas por meio de funções, portanto
abordamos como funções são declaradas e escritas nos programas. Explicamos como funciona
a prototipagem de funções e como os valores retornados por elas são usados nas expressões da
função chamadora.
Em seguida, abordamos o escopo de variáveis, explicando a diferença entre variáveis locais
e globais, e destacando a importância de priorizar o uso de variáveis locais no desenvolvimento
de programas. Também abordamos as classes de variáveis estáticas, externas e de registro,
particulares da linguagem C.
Prosseguimos detalhando o recurso de ponteiros da linguagem C e como são importantes
na passagem de parâmetros, assunto seguinte abordado, onde explicamos a diferença entre a
passagem por valor e por referência. Concluímos a unidade abordando o conceito de recursividade,
com alguns exemplos de uso.
Chegamos, enfim, ao final da disciplina de Algoritmos e Programação Aplicada. Com o
conteúdo aprendido aqui, espera-se que o discente tenha o conhecimento básico dos principais
recursos que compõem a lógica de programação e possa partir para o descobrimento de novas
plataformas, ferramentas e linguagens que venham aprimorar esse conhecimento.
135WWW.UNINGA.BR
ENSINO A DISTÂNCIA
REFERÊNCIAS
ASCENCIO, A. F. G.; CAMPOS, E. A. V. Fundamentos da programação de computadores:
Algoritmos, Pascal, C/C++. 3. ed. São Paulo: Prentice Hall, 2012.
BACKES, A. R. Estrutura de dados descomplicada: em linguagem C. Rio de Janeiro: Elsevier,
2016.
DEITEL, P. J. C: como programar. Tradução de Daniel Vieira. 6. ed. São Paulo: Pearson Prentice
Hall, 2011.
DIBBLE, J. UNIVAC/ERA 1101: primeiro computador da história que rodava um programa
da memória. 2021. Disponível em: https://sites.google.com/site/byjessicadibble/home/abacus/
difference-engine/z1/colossus/abc/edsac/electronic-controls-company/univac-1101-era-1101.
Acesso em: 9 set. 2021.
FORBELLONE, A. L. V.; EBERSPACHER, H. F. Lógica de Programação: a construção de
algoritmos e estruturas de dados. 3. ed. São Paulo: Prentice Hall, 2005.
GERAÇÕES DE COMPUTADORES. Exemplo de um computador de quinta geração. 2021.
Disponível em: https://geracoesdecomputadores.files.wordpress.com/2011/08/imac.png. Acesso
em: 9 set. 2021.
GUEDES, S. Lógica de programação algorítmica. São Paulo: Pearson Education do Brasil, 2014.
LOPES, A.; GARCIA, G. Introdução à Programação: 500 Algoritmos Resolvidos. Rio de Janeiro:
Elsevier, 2002.
MANZANO, A. L. N. G.; MANZANO, M. I. N. G. Estudo Dirigido de Informática Básica. São
Paulo: Saraiva, 2009.
MANZANO, J. A. N. G.; OLIVEIRA, J. F. Algoritmos: Lógica para Desenvolvimento de
Programação de Computadores. 26. ed. São Paulo: Érica, 2012.
MICROSOFT DOCS. foreach, in (Referência em C#). 2019. Disponível em: https://docs.
microsoft.com/pt-br/dotnet/csharp/language-reference/keywords/foreach-in. Acesso em: 29
dez. 2019.
PRESSMAN, R. S. Engenharia de Software. 7. ed. São Paulo: Makron, McGraw-Hill, 1995.
SCHILDT, H. C Completo e Total. Tradução de Roberto Carlos Mayer. 3. ed. São Paulo: Makron
Books, 1996.
SEBESTA, R. W. Conceitos de linguagens de programação. Tradução de Eduardo Kessler Piveta.
9. ed. Porto Alegre: Bookman, 2011.
SINTES, A. Aprenda Programação Orientada a Objetos em 21 dias. São Paulo: Pearson
Education do Brasil, 2002.
https://sites.google.com/site/byjessicadibble/home/abacus/difference-engine/z1/colossus/abc/edsac/electronic-controls-company/univac-1101-era-1101.
https://sites.google.com/site/byjessicadibble/home/abacus/difference-engine/z1/colossus/abc/edsac/electronic-controls-company/univac-1101-era-1101.
https://geracoesdecomputadores.files.wordpress.com/2011/08/imac.png.
136WWW.UNINGA.BR
ENSINO A DISTÂNCIA
REFERÊNCIAS
SOUZA, M. F. F. Computadores e sociedade: da filosofia às linguagens de programação. Curitiba:
InterSaberes, 2016.
TANENBAUM, A. S. Organização estruturada de computadores. 6. ed. São Paulo: Pearson
Prentice Hall, 2013.
TUCKER, A. B.; NOONAN, R. E. Linguagens de programação: Princípios e Paradigmas.
Tradução de Mario Moro Fecchio. 2. ed. Porto Alegre: AMGH, 2010.
VILARIM, G, O. Algoritmos: Programação Para Iniciantes. 3. ed. Rio de Janeiro: Ciência
Moderna, 2017.
WIKIWAND. Intel 8008, 1972 - primeiro microprocessador de 8 bits. 2021. Disponível em:
https://www.wikiwand.com/pt/Microprocessador. Acesso em: 9 set. 2021.
XAVIER, G. F. C. Lógica de Programação. 12. ed. São Paulo: Senac, 2011.
https://www.wikiwand.com/pt/Microprocessador.