0% acharam este documento útil (0 voto)
54 visualizações168 páginas

Fundamentos de Algoritmos e Programação

O documento aborda os fundamentos de algoritmos e programação estruturada, destacando a definição e representação de algoritmos, suas aplicações e tipos. Através de videoaulas, os alunos aprendem a criar algoritmos em linguagem natural e diagramas de blocos, além de conceitos básicos de linguagens de programação. O conteúdo é voltado para estagiários sem experiência prévia, com exemplos práticos de cadastro de dados e verificação de números.
Direitos autorais
© All Rights Reserved
Levamos muito a sério os direitos de conteúdo. Se você suspeita que este conteúdo é seu, reivindique-o aqui.
Formatos disponíveis
Baixe no formato PDF, TXT ou leia on-line no Scribd
0% acharam este documento útil (0 voto)
54 visualizações168 páginas

Fundamentos de Algoritmos e Programação

O documento aborda os fundamentos de algoritmos e programação estruturada, destacando a definição e representação de algoritmos, suas aplicações e tipos. Através de videoaulas, os alunos aprendem a criar algoritmos em linguagem natural e diagramas de blocos, além de conceitos básicos de linguagens de programação. O conteúdo é voltado para estagiários sem experiência prévia, com exemplos práticos de cadastro de dados e verificação de números.
Direitos autorais
© All Rights Reserved
Levamos muito a sério os direitos de conteúdo. Se você suspeita que este conteúdo é seu, reivindique-o aqui.
Formatos disponíveis
Baixe no formato PDF, TXT ou leia on-line no Scribd

Disciplina

ALGORITMOS E PROGRAMAÇÃO
ESTRUTURADA

Unidade 1
Fundamentos de Algoritmos e Programação

Aula 1
Definição e Representação de Algoritmos

Definição e representação de algoritmos

Este conteúdo é um vídeo!


Para assistir este conteúdo é necessário que você acesse o AVA pelo
computador ou pelo aplicativo. Você pode baixar os vídeos direto no aplicativo
para assistir mesmo sem conexão à internet.
Dica para você
Aproveite o acesso para baixar os slides do vídeo, isso pode deixar sua
aprendizagem ainda mais completa.

Estudante, esta videoaula foi preparada especialmente para você. Nela, você irá aprender
conteúdos importantes para a sua formação profissional. Vamos assisti-la?

Ponto de Partida

É importante ter em mente que um algoritmo consiste em uma sequência limitada de etapas que
podem ser seguidas para criar e executar uma tarefa específica com o objetivo de resolver um
problema. Portanto, é crucial compreender as definições de um algoritmo, suas aplicações e
seus diferentes tipos antes de prosseguir para os próximos estágios deste material.

Você está iniciando agora seu trabalho em uma empresa que se dedica à criação de softwares
educacionais. Sua responsabilidade é treinar os estagiários recém-contratados para trabalhar
com o desenvolvimento de sistemas na empresa. É importante lembrar que esses estagiários
não possuem experiência prévia com algoritmos ou linguagens de programação.
Disciplina

ALGORITMOS E PROGRAMAÇÃO
ESTRUTURADA

Para despertar o interesse dos estagiários, vamos criar dois algoritmos: um que permita o
cadastro dos dados pessoais dos alunos que precisam ser registrados, como nome, endereço,
cidade e estado; e outro que verifica se um número qualquer é positivo ou negativo. Os
algoritmos devem ser elaborados nos seguintes formatos:

Explicação em linguagem natural.


Representação gráfica por meio de um diagrama de blocos (fluxograma).

Ao analisar os resultados obtidos, os algoritmos podem desempenhar um papel significativo na


criação de códigos de programação. Agora é o momento de iniciar esta jornada. Preste muita
atenção nas aulas e tenha um excelente estudo!

Vamos Começar!

Olá! Daqui para frente, você vai desvendar o funcionamento dos algoritmos e compreender suas
utilidades no âmbito da programação. Com esse propósito, será introduzido aos conceitos,
aplicações e variedades de algoritmos.

Definição de Algoritmo
Um algoritmo pode ser definido como uma sequência lógica e finita de passos (instruções) para
resolver um determinado problema. Nesse contexto, um algoritmo pode guiá-lo na identificação
do caminho mais eficiente para resolver um problema utilizando o computador. A criação de
algoritmos é um passo crucial no processo de construção de um programa de computador (ou
software), pois, ao elaborar algoritmos para resolver um problema específico, é possível
posteriormente traduzi-los para uma linguagem de programação específica. Como destacado,
para qualquer atividade cotidiana, podemos elaborar um algoritmo. Por exemplo, a sequência de
etapas para preparar um bolo de chocolate, como ilustrado a seguir:

1. Bata 4 claras em neve


2. Adicione 2 xícaras de açúcar, 2 colheres de farinha de trigo, 4 gemas, 1 colher de
fermento e duas colheres de chocolate
3. Bata por 3 minutos
4. Unte uma assadeira com margarina e farinha de trigo, e despeje a mistura
5. Coloque o bolo para assar por 20 minutos

Perceba que assim como existem diversas receitas diferentes para se fazer um mesmo bolo de
chocolate, há várias maneiras de desenvolver um algoritmo! No entanto, existe uma ordem lógica
para a execução da tarefa. Por exemplo, o passo 5 (colocar para assar) só pode ser feito após
Disciplina

ALGORITMOS E PROGRAMAÇÃO
ESTRUTURADA

realizar o passo 4 (despejar a mistura em uma forma untada). No entanto, é possível criar outras
abordagens e ordens para alcançar o mesmo objetivo predeterminado.

Para uma compreensão mais abrangente dos algoritmos, é crucial dividi-los em três
componentes principais: entrada, processamento e saída.

Entrada: refere-se aos dados ou elementos de entrada do algoritmo (informações utilizadas


no processamento, para gerar um resultado esperado). No contexto do algoritmo de receita
de bolo, esses dados de entrada seriam os ingredientes necessários.
Processamento: são as etapas e os procedimentos necessários para alcançar o resultado
final, ou seja, o bolo.
Saída: representa o resultado que o algoritmo busca alcançar após o processamento dos
dados de entrada, ou seja, o bolo pronto para ser servido.

Linguagem Natural
A linguagem natural constitui um meio de comunicação utilizado por pessoas de diferentes
idiomas, podendo manifestar-se por meio da fala, da escrita, dos gestos, e outras formas de
interação. A linguagem natural desempenha um papel fundamental no desenvolvimento de
aplicações computacionais, uma vez que facilita de maneira direta e eficaz a descrição de
problemas e suas respectivas soluções.

Para ilustrar os princípios da linguagem natural, podemos tomar como exemplo o registro das
notas de alguns alunos em seu curso. O desafio consiste no seguinte: o usuário deve inserir dois
valores que representam as notas de cada bimestre, e o computador retornará a média desses
valores (média das notas). Caso a média seja igual ou superior a seis, o aluno será considerado
aprovado; caso contrário, será reprovado. Para realizar a solução desse problema, podemos fazer
uso da seguinte estrutura:

1. Início.
2. Entrar com o primeiro valor (nota do primeiro bimestre).
3. Entrar com o segundo valor (nota do segundo bimestre).
4. Realizar a soma do primeiro valor com o segundo.
5. Realizar a divisão da soma dos valores por dois (média das notas dos bimestres).
6. Armazenar o valor encontrado.
7. Mostrar na tela o resultado da média.
8. Se a média do aluno for maior ou igual a seis.
9. O aluno será considerado aprovado.
10. Senão está reprovado.
11. Fim.
Disciplina

ALGORITMOS E PROGRAMAÇÃO
ESTRUTURADA

A grande vantagem de se representar algoritmos por meio de linguagem natural é o fato de não
ser necessário aprender nenhum conceito novo, pois a língua natural, o português, já é
conhecida. Porém, a língua natural abre espaço para diferentes interpretações, ambiguidades, o
que posteriormente dificultará a transição deste algoritmo para o programa.

Siga em Frente...

Diagramas de Bloco (Fluxogramas)


Antes de entrarmos no estudo de diagramas de blocos, é importante compreender de forma
resumida o conceito de variáveis e atribuições, a fim de que você tenha condições de interpretar
e progredir em seus estudos de algoritmos.

As variáveis, como o próprio nome indica, são elementos que podem ser alterados (sofrer
variações), ou seja, estão relacionadas à identificação de informações. Já uma atribuição (←)
serve para designar valores às variáveis, ou seja, para atribuir informações a elas. Por exemplo:

valor1 ← 6
nome ← joao

Significa que a o número “6” está sendo atribuído para variável “valor1” e que o texto “joao” está
sendo atribuído para variável “nome”.

Um diagrama de blocos (ou fluxograma) pode ser descrito como uma coleção de símbolos
gráficos, em que cada um desses símbolos representa ações específicas a serem executadas
pelo computador. É importante ressaltar que o diagrama de blocos estabelece a sequência lógica
adotada pelo desenvolvedor para resolver um problema. Ao criar um diagrama de blocos, o
desenvolvedor precisa assegurar que os símbolos utilizados sejam coerentes e de fácil
compreensão. Para garantir a consistência dos diagramas de blocos, seus símbolos foram
padronizados pela ANSI (Instituto Nacional Americano de Padrões), sendo os principais deles
ilustrados na Tabela 1.

Símbolo Significado Descrição


Representa o início ou
Terminal o fim de um
fluxograma.
Entrada manual Determina a entrada
manual dos dados,
Disciplina

ALGORITMOS E PROGRAMAÇÃO
ESTRUTURADA

geralmente por meio


de um teclado.
Representa a
execução de ações de
Processamento processamento. Por
exemplo, a execução
de uma soma.
Mostra o resultado de
uma ação ou exibição
de alguma
Exibição informação,
geralmente por meio
da tela de um
computador
Representa os desvios
condicionais nas
operações de tomada
Decisão/Condicional de decisão e laços
condicionais para
repetição de alguns
trechos do programa.

Tabela 1 | Principais símbolos utilizados em diagramas de blocos.

A Figura 1 traz um exemplo de algoritmo representado em fluxograma.


Disciplina

ALGORITMOS E PROGRAMAÇÃO
ESTRUTURADA

Figura 1 | Fluxograma - algoritmo.

Este fluxograma ilustra um algoritmo que calcula a média entre duas notas, e exibe como saída
se o aluno está aprovado ou reprovado. Vejamos a seguir a explicação de cada passo do
fluxograma, de acordo com a numeração da figura.

1. O símbolo terminal deu início ao diagrama de blocos.


2. O símbolo de processamento definiu as variáveis.
3. O símbolo exibição mostra na tela o que o usuário deve fazer.
4. O símbolo de entrada manual libera para o usuário entrar com a primeira nota.
5. O símbolo exibição mostra na tela o que o usuário deve fazer.
6. O símbolo de entrada manual libera para o usuário entrar com a segunda nota.
7. símbolo de processamento realiza a soma das notas 1 e 2, e atribui o resultado à
variável soma.
Disciplina

ALGORITMOS E PROGRAMAÇÃO
ESTRUTURADA

8. O símbolo de processamento realiza a divisão da variável soma por 2 e atribui o


resultado à variável média.
9. O símbolo de exibição mostra na tela o resultado da média calculada.
10. O símbolo de decisão define a condicional (verdadeiro ou falso) para a variável média.
11. Se a condição for verdadeira, a resposta será “Aprovado”. Se a condição for falsa, a
resposta será “Reprovado”.
12. O símbolo terminal finaliza o programa.

Vejamos agora algumas dicas para construir um diagrama de blocos (fluxograma):

Estar atento aos níveis.


O diagrama de blocos (fluxograma) deve começar de cima para baixo e da esquerda para
direita.
Ficar atento para não cruzar as linhas, principalmente as linhas de fluxos de dados.
As instruções devem seguir um fluxo lógico.

Por fim, a grande vantagem do uso de fluxogramas é que a compreensão de elementos gráficos
é mais fácil do que a de textos, além de diminuir a ambiguidade presente na representação por
linguagem natural. Porém sua desvantagem consiste em ser necessário aprender a simbologia
dos fluxogramas e, além disso, no fato do algoritmo resultante não apresentar muitos detalhes,
dificultando a sua transcrição para um programa.

Vamos Exercitar?
Agora, é hora de aplicar todo o conhecimento adquirido até aqui! Vale lembrar que a sua tarefa
era introduzir aos estagiários um algoritmo que utilize linguagem natural e/ou diagramas de
blocos (fluxogramas) para realizar duas tarefas: registrar os dados pessoais de um aluno (nome,
endereço, cidade e estado) e exibir o resultado ao final; e verificar se um número é positivo ou
negativo.

Seguem as dicas para realizar a solução do nosso problema:

Quando falamos em linguagem natural, quer dizer que devemos escrever a situação o mais
próximo possível da linguagem convencional. Não se preocupe com os passos a serem
realizados, foque na solução do problema.

Segue um exemplo de resolução em linguagem natural:

Algoritmo para cadastro:


Disciplina

ALGORITMOS E PROGRAMAÇÃO
ESTRUTURADA

1. Declarar as variáveis nome, endereço, cidade e estado.


2. Ler o nome do aluno, do endereço, da cidade e do estado.
3. Armazenar cada informação lida em sua respectiva variável.
4. Exibir os valores de nome, endereço, cidade e estado.

Algoritmo para verificar se um número é positivo ou negativo:

1. Declarar uma variável num.


2. Pedir para o usuário inserir um número qualquer.
3. Atribuir o valor informado pelo usuário à variável num.
4. Verificar se num é maior ou igual a zero.
5. Se for verdade, o número é positivo.
6. Se for falso, o número é negativo.

Agora só falta construir o diagrama de blocos (fluxograma) para as duas tarefas.

Concentre-se na descrição e nos significados dos símbolos, bem como na sequência lógica
de passos para se chegar no objetivo final.

Lembrando que não há uma única resposta correta. Há vários caminhos para se chegar no
mesmo resultado, e esta é a beleza dos algoritmos!

Saiba mais
Para entender melhor o conceito de algoritmos e sua importância no desenvolvimento de
softwares sugerimos a leitura do Capítulo 1 - Introdução do livro Simplificando Algoritmos,
disponível na Biblioteca Virtual.

Já o Capítulo 4 - Algoritmos do mesmo livro traz conceitos complementares sobre a


representação de algoritmos estudados nesta aula.

MENÉNDEZ, A. Simplificando algoritmos. 1. ed. Rio de Janeiro: LTC, 2023.

Para auxiliar no desenvolvimento de diagramas de bloco (fluxogramas), você pode utilizar a


ferramenta on-line gratuita [Link], que possui suporte para diversos tipos de diagramas.

Referências
Disciplina

ALGORITMOS E PROGRAMAÇÃO
ESTRUTURADA

CORMEN, T. H. Desmistificando algoritmos. 1. ed. Rio de Janeiro: Elsevier, 2014.

MENÉNDEZ, A. Simplificando algoritmos. 1. ed. Rio de Janeiro: LTC, 2023.

PIVA JUNIOR, D. Algoritmos e programação de computadores. 2. ed. Rio de Janeiro: Elsevier,


2019.

Aula 2
Conceitos Básicos de Linguagem de Programação

Conceitos básicos de linguagens de programação

Este conteúdo é um vídeo!


Para assistir este conteúdo é necessário que você acesse o AVA pelo
computador ou pelo aplicativo. Você pode baixar os vídeos direto no aplicativo
para assistir mesmo sem conexão à internet.
Dica para você
Aproveite o acesso para baixar os slides do vídeo, isso pode deixar sua
aprendizagem ainda mais completa.

Estudante, esta videoaula foi preparada especialmente para você. Nela, você irá aprender
conteúdos importantes para a sua formação profissional. Vamos assisti-la?

Ponto de Partida
Uma linguagem de programação é um conjunto de regras e símbolos usado para escrever
códigos que o computador pode executar. Ela serve como uma ferramenta para os
programadores comunicarem instruções precisas ao computador, permitindo que desenvolvam
software e aplicativos para uma ampla gama de propósitos.

Você está trabalhando em uma empresa que se dedica à criação de softwares educacionais. Sua
responsabilidade é treinar os estagiários recém-contratados para trabalhar com o
desenvolvimento de sistemas na empresa. Esses estagiários não possuíam experiência prévia
com algoritmos ou linguagens de programação, porém você já os auxiliou com os conceitos
Disciplina

ALGORITMOS E PROGRAMAÇÃO
ESTRUTURADA

introdutórios de algoritmos e as formas de representação por meio de linguagem natural e


fluxogramas.

Para continuar despertando o interesse dos estagiários, você irá aparentar a eles a linguagem de
programação C. E para isto, irá desenvolver um programa que permita o cálculo da média de dois
valores digitados pelo usuário.

Para concluir este desafio, será importante enfatizar aos estagiários o processo básico de
criação de algoritmos, consistindo na definição da entrada, do processamento e da saída.

Agora é o momento de iniciar esta jornada. Preste muita atenção na aula e tenha um excelente
estudo!

Vamos Começar!

Olá! Com o conhecimento sobre algoritmos e como criá-los por meio de linguagem natural e
fluxogramas, o próximo é a representação por meio de uma linguagem de programação.
Portanto, você irá agora se aprofundar no estudo da linguagem de programação C.

Linguagem de programação e criação de algoritmos


A linguagem de programação é o meio de comunicação de ideias entre o computador e os
indivíduos, da mesma forma como as linguagens naturais são utilizadas em nossas interações
cotidianas. As primeiras linguagens de computador utilizadas foram as linguagens de máquina e
a linguagem Assembly, a partir da década de 1940. Desde então, várias linguagens surgiram,
juntamente com o desenvolvimento de novos paradigmas de linguagens de programação.

Cada linguagem de programação destinada à criação de programas possui uma sintaxe


particular, que se refere à forma como o programa é codificado. A sintaxe de uma linguagem de
programação pode ser descrita, como a descrição precisa de todos os programas
gramaticalmente corretos nessa linguagem.

Um programa de computador pode ser definido como um conjunto de instruções ordenadas, em


que você fornece comandos ao computador e ele executa tarefas específicas de acordo com as
instruções fornecidas. Ou seja, é uma série de instruções organizadas de forma a resolver um
problema específico. Esse programa pode ser desenvolvido em módulos distintos e/ou
subprogramas.

Para criar um programa de computador, é necessário seguir certos passos:

1. Definir e analisar o problema a ser resolvido, destacando os pontos mais importantes.


2. Definir os dados de entrada: coleta de informações
Disciplina

ALGORITMOS E PROGRAMAÇÃO
ESTRUTURADA

3. Definir o processamento, ou seja, quais cálculos serão executados e as suas restrições. O


processamento é responsável pela transformação dos dados de entrada em informações
de saída.
4. Definir os dados de saída, ou seja, o que será gerado após o processamento: apresentação
de todas as informações resultantes do processamento de dados em um dispositivo
periférico (monitor, por exemplo).
5. Criar um algoritmo ou um diagrama de fluxo.
6. Testar o algoritmo realizando simulações.

Em um contexto geral, a sequência de instruções para criação de um programa de computador é


da seguinte maneira:

1. Definição de bibliotecas.
2. Início do programa.
3. Definição das variáveis e de possíveis atribuições.
4. Instrução de leitura dos dados.
5. Instrução do formato de escrita.
6. Demais instruções e funções.
7. Fim do programa.

Estrutura básica da Linguagem C


A linguagem C foi criada por Dennis Ritchie em 1972, e com a popularização dos
microcomputadores, um grande número de programas em C foi criado. Desta forma, um
programa desenvolvido em um computador, poderia ser executado em outro (portabilidade),
porém, gerava algumas discrepâncias. Então a ANSI (American National Standards Institute
padronizou de uma vez por todas a linguagem C.

Vamos analisar o código do Quadro 1, que apresenta a estrutura básica de um programa na


linguagem C:

1: #include <stdio.h>
2: int main(){
3: printf("Hello World!");
4: return 0;
5: }

Quadro 1 | Exemplo básico de programa na linguagem C.

As primeiras linhas de programação são definidas pelas bibliotecas, que incorporam ao nosso
programa um conjunto de funções e instruções previamente estabelecidas que não são nativas
da linguagem de programação, e que podem ser usadas pelo programa.
Disciplina

ALGORITMOS E PROGRAMAÇÃO
ESTRUTURADA

Veja alguns exemplos de biblioteca em linguagem de programação C:

stdio – essa biblioteca é responsável pelas funções de entradas e saídas, como é o caso da
função printf e scanf que vamos aprender mais à frente. Utilização: #include <stdio.h>
stdlib – essa biblioteca possui funções envolvendo alocação de memória, controle de
processos, conversões e outras. Utilização: #include <stdlib.h>
string – biblioteca responsável pela manipulação de strings. Utilização: #include<string.h>
time – biblioteca utilizada para manipulação de horas e datas. Utilização: #include<time.h>
math – biblioteca utilizada para operações matemáticas. Utilização: #include<math.h>

Após a definição das bibliotecas, o programa é inicializado pela função principal (main). Esta
função é delimitada pela utilização de chaves, onde a “{“ (chave aberta) indica o início de uma
função em C e a “}” (chave fechada) indica o término das funções. Todo a sequência lógica de
instruções do programa (declarações de variáveis, leitura de dados, instruções, saída de dados,
etc.) deve ser definida dentro do main().

Veja que no exemplo do Quadro 1 usamos o tipo int antes de main (), e isto significa que
retornará um número do tipo inteiro. Ao final da função, o “return 0;” indica que a função principal
(e neste caso o programa como um todo) terminou e retornou um valor inteiro 0. Mas, para que é
importante retornar um valor 0 ao final de qualquer programa? Normalmente, usamos o valor 0
como padrão (return 0) para indicar ao sistema operacional que a função foi concluída sem
erros. Se ocorrer algum erro durante a execução de int main(), um valor inteiro diferente de 0 será
retornado. Se você definir sua função apenas como main(), nenhum valor será retornado ao final
da execução. No entanto, essa prática não é recomendada, pois não seria possível verificar
explicitamente se a função foi executada corretamente, sem erros.

Para prosseguir com nossos estudos, vamos explorar conceitualmente as variáveis. Não se
preocupe! Na próxima aula, abordaremos esse tema com mais profundidade. As variáveis são
áreas reservadas na memória para armazenar dados, sendo que cada uma possui um nome
único para identificação.

Os tipos de variáveis mais comumente utilizados são:

Inteiro (int): armazena os números inteiros (negativos ou positivos).


Real (float): permite armazenar valores de pontos flutuantes e frações. Quando se
necessita do dobro de dados numéricos é utilizado o tipo “double” ou “long double”.
Caractere (char): permite armazenar caracteres, números e símbolos especiais. São
delimitadas por aspas simples (‘).

Veja o seguinte exemplo no Quadro 2:

1: #include <stdio.h>
2: int main(){
3: int num;
Disciplina

ALGORITMOS E PROGRAMAÇÃO
ESTRUTURADA

4: int num2 = 5;
5: float num3;
6: char caractere;
7: num = 10;
8: num3 = 2.5;
9: caractere = 'a';
10: return 0;
11: }

Quadro 2 | Exemplo de variáveis na linguagem C.

O exemplo mostra a declaração de algumas variáveis, seguido da atribuição de valores a elas.


Note que uma variável pode ser declarada e ao mesmo tempo ter um valor atribuído a ela, como
é o caso em “int num2 = 5”. Outro ponto de atenção consiste na atribuição de um valor para a
variável do tipo char, no qual o caractere ‘a’ é atribuído entre aspas simples (seguindo a sintaxe
da linguagem C).

Siga em Frente...

Entrada e Saída de Dados


A função printf() é um comando de saída que está presente na biblioteca stdio.h, e é utilizada
quando se pretende exibir (“imprimir”) alguma informação na tela do computador.

A sua sintaxe é definida por:

printf(“texto e/ou códigos de controle”, listas de argumentos);

Além de texto, o printf() pode exibir valores de variáveis. Porém deve seguir o seguinte formato
conforme o exemplo a seguir:

valor1 = 10;
printf(“O valor encontrado foi %d”, valor1);

Resultado do trecho de código: O valor encontrado foi 10

Perceba que o valor da variável “valor1” foi posicionado no local do “%d”. O “%d” é um código de
controle para um dado do tipo inteiro.
Disciplina

ALGORITMOS E PROGRAMAÇÃO
ESTRUTURADA

A Tabela 1 a seguir os principais códigos de acordo com os tipos de variáveis declaradas.

Código Função
Exibe/lê um número
%d
inteiro
Exibe/lê um número
%f em ponto flutuante
(decimal)
%c Exibe/lê um caractere
Exibe/lê uma
%s sequência de
caracteres (string)
Exibe/lê um número
%e
em notação científica

Tabela 1 | Códigos de controle utilizados em funções de entrada e saída.

No printf() você pode pular linhas com o comando “\n” e pode também obter um resultado
numérico determinando a quantidade de casas decimais.

Veja o exemplo a seguir:

printf (“\n Resposta: a = %.2f e b = %.2f\n”, a, b);

Neste exemplo, antes de apresentar a frase o programa pulou uma linha “\n”, o “%f” é utilizado
quando os dados numéricos são flutuantes, ou seja, valores fracionados. E quando usamos %.2f
significa que o valor será arredondado em duas casas decimais, por exemplo: 2,45.

A função scanf(), também presente na biblioteca stdio.h, opera como um comando de entrada,
permitindo a inserção de dados via teclado. A informação inserida é então armazenada em um
espaço específico da memória, designado pelo nome e tipo específico da variável. Sua sintaxe é
definida por um código de controle (sempre entre aspas duplas) e pela lista de argumento:

scanf(“códigos de controle”, lista de argumentos);

O scanf() utiliza os mesmo códigos de controle listado na tabela X. Veja o seguinte exemplo:
Disciplina

ALGORITMOS E PROGRAMAÇÃO
ESTRUTURADA

int var;
scanf(“%d”, &var);

Neste exemplo, o computador ficará esperando que o usuário digite um valor numérico inteiro
(devido ao uso do código %d) para ser armazenado na variável inteira var. O operador “&” é
utilizado em conjunto com a função scanf()para indicar o endereço de uma variável. Isso ocorre
porque a função scanf() necessita de referências de memória das variáveis nos quais os valores
de entrada serão armazenados.

Segue um exemplo de programa em C utilizando scanf() e printf() no Quadro 3:

1: #include <stdio.h>
2: int main(){
3: int num;
4: printf("Digite um número: ");
5: scanf("%d", &num);
6: printf("Você digitou: %d", num);
7: system(“pause”);
8: return 0;
9: }
10:
11:

Quadro 3 | exemplo de programa em C utilizando scanf e printf.

Neste exemplo simples, o programa aguarda que o usuário digite um valor numérico inteiro, que
será armazenado na variável num e em seguida é exibido na tela com o printf. Perceba que aqui
temos o uso da instrução “system(“pause”)”, que pausa o fluxo de execução do programa
naquele ponto para que o resultado seja visualizado.

Vamos Exercitar?
Agora é a hora de aplicar todo o conhecimento adquirido nesta aula! Lembrando que a sua tarefa
aqui é escrever na linguagem C um programa que calcule a média entre dois valores de entrada
digitados pelo usuário, e exiba o resultado com duas casas após a vírgula.

O primeiro passo é analisar o problema e identificar quais serão as variáveis de entrada e


seus respectivos tipos: serão dois números em ponto flutuante, portanto teremos “float
num1, num2”;
Em seguida, pensamos no processamento necessário para ler dois valores digitados e
calcular a média. A leitura dos dados poderá ser feita com o scanf(), e o cálculo da média
Disciplina

ALGORITMOS E PROGRAMAÇÃO
ESTRUTURADA

por meio de uma expressão matemática simples: media = (num1 + num2)/2. (precisaremos
de uma variável do tipo float para armazenar o resultado desta operação).
Com relação à saída, podemos utilizar o print() para exibir o resultado da variável media.
Como vamos utilizar printf() e scanf(), não podemos nos esquecer de incluir a biblioteca
stdio.h!

Sendo assim, segue o algoritmo em C:

#include <stdio.h>
int main(){
float num1, num2, media;
printf("Digite o primeiro numero: ");
scanf("%f", &num1);
printf("Digite o segundo numero: ");
scanf("%f", &num2);
media = (num1 + num2)/2;
printf("Media = %.2f", media);
return 0;
}

Saiba mais
Para entender melhor o conceito de uma linguagem de programação e a estrutura fundamental
da linguagem C, sugerimos a leitura do Capítulo 1 - Introdução do livro Linguagem C: Completa e
Descomplicada, disponível na Biblioteca Virtual.

BACKES, A. Linguagem C: completa e descomplicada. 2. ed. Rio de Janeiro: LTC, 2023. cap. 1, p.
2.24.

Com relação aos conceitos de variáveis, entrada e saída em C, o Capítulo 2 - Lendo e escrevendo
nas variáveis, do mesmo livro Linguagem C: Completa e Descomplicada complementa bem o
assunto.

BACKES, A. Linguagem C: completa e descomplicada. 2. ed. Rio de Janeiro: LTC, 2023. cap. 2, p.
25-47.

Para auxiliar no desenvolvimento de programas na linguagem C, uma ótima prática é verificar a


documentação da linguagem para entender em detalhes os principais tipos de funções e
elementos utilizados. Para isso, sugerimos a consulta da seguinte documentação sempre que
achar necessário. Nela você encontra todas as bibliotecas utilizadas na linguagem e como
utilizar suas principais funções: Referência da Linguagem C.
Disciplina

ALGORITMOS E PROGRAMAÇÃO
ESTRUTURADA

Referências
BACKES, A. Linguagem C: completa e descomplicada. 2. ed. Rio de Janeiro: LTC, 2023.

CORMEN, T. H. Desmistificando algoritmos. 1. ed. Rio de Janeiro: Elsevier, 2014.

DAMAS, L. Linguagem C. 10. ed. Rio de Janeiro: LTC, 2023.

MENÉNDEZ, A. Simplificando algoritmos. 1. ed. Rio de Janeiro: LTC, 2023.

PIVA JUNIOR, D. Algoritmos e programação de computadores. 2. ed. Rio de Janeiro: Elsevier,


2019.

Aula 3
Variáveis e Constantes

Variáveis e constantes

Este conteúdo é um vídeo!


Para assistir este conteúdo é necessário que você acesse o AVA pelo
computador ou pelo aplicativo. Você pode baixar os vídeos direto no aplicativo
para assistir mesmo sem conexão à internet.
Dica para você
Aproveite o acesso para baixar os slides do vídeo, isso pode deixar sua
aprendizagem ainda mais completa.

Estudante, esta videoaula foi preparada especialmente para você. Nela, você irá aprender
conteúdos importantes para a sua formação profissional. Vamos assisti-la?

Ponto de Partida
Uma linguagem de programação é um conjunto de regras e símbolos usados para escrever
códigos que o computador pode executar. Ela serve como uma ferramenta para os
Disciplina

ALGORITMOS E PROGRAMAÇÃO
ESTRUTURADA

programadores comunicarem instruções precisas ao computador, permitindo que desenvolvam


software e aplicativos para uma ampla gama de propósitos.

Você está trabalhando em uma empresa que está desenvolvendo um software para uma loja de
eletrodomésticos. Nesse sistema, temos a necessidade de calcular o preço final de um produto
com base no preço de venda e na incidência de taxas fixas de impostos e descontos aplicáveis.
Por exemplo, suponha que o preço de venda de um televisor seja de R$ 1500.00. Vamos
considerar que a taxa de imposto aplicável seja de 10%, e que haja um desconto padrão de 5%
para esse produto em particular.

Para concluir este desafio, será importante definir e manipular corretamente as variáveis e
constantes na linguagem C.

Agora é o momento de iniciar esta jornada. Preste muita atenção na aula e tenha um excelente
estudo!

Vamos Começar!
Olá! Com o conhecimento sobre algoritmos e como criá-los por meio de linguagem natural e
fluxogramas, o próximo é a representação por meio de uma linguagem de programação.
Portanto, você irá agora aprofundar no estudo da linguagem de programação C.

Definição, tipos e declaração de variáveis na linguagem C


Considere a seguinte equação para o cálculo da área de uma circunferência: , em que (pi)
equivale a aproximadamente 3,14 e é o raio. Podemos observar que o valor do raio pode variar
de acordo com a circunferência que se deseja calcular a área, e consequentemente o valor da
área também muda (varia). Porém, independente da circunferência, o valor de (pi) é sempre o
mesmo (constante). Há inúmeros exemplos que ilustram situações em que os valores podem
variar ou permanecer fixos, refletindo a natureza diversa do nosso mundo, sujeito a condições
específicas. Dado que os sistemas computacionais são projetados para resolver uma ampla
variedade de problemas, é crucial que sejam capazes de lidar com essa característica – isto é,
realizar cálculos com valores variáveis ou constantes. No contexto da programação, essas
capacidades são conhecidas como variáveis e constantes, as quais desempenham a função
primordial de temporariamente armazenar dados na memória de trabalho.

Uma variável pode ser definida como uma localização temporária na memória em que um valor
pode ser armazenado e utilizado por um programa. Esta localização na memória é identificada
por meio de endereços de memória. Sendo assim, quando criadas, essas entidades realmente
existem na memória de trabalho, ocupando um espaço físico. O mesmo princípio se aplica às
constantes, embora, neste caso, o valor armazenado permaneça inalterado.
Disciplina

ALGORITMOS E PROGRAMAÇÃO
ESTRUTURADA

Agora, observe a Figura 1, que apresenta uma ilustração simbólica da memória de um


computador com a alocação de duas variáveis, A e B, sendo cada espaço equivalente a 1 byte. É
evidente que o espaço reservado para A é maior do que o reservado para B. No entanto, como
ocorre essa distinção de tamanho? A especificação do espaço alocado para uma variável pode
ser determinada de duas maneiras: a primeira relaciona-se com o tipo de dado a ser armazenado
no espaço designado, no qual o programador não tem controle direto sobre o tamanho alocado.
Em contraste, a segunda abordagem é realizada manualmente pelo programador, por meio da
utilização de funções e estruturas específicas que serão abordadas mais adiante.
Disciplina

ALGORITMOS E PROGRAMAÇÃO
ESTRUTURADA

Figura 1 | Exemplo de variáveis na memória.

Todas as linguagens de programação contêm tipos de dados primitivos e compostos. Entre os


tipos primitivos, temos as seguintes categorias:
Disciplina

ALGORITMOS E PROGRAMAÇÃO
ESTRUTURADA

Inteiro (int): refere-se a valores inteiros que podem ser negativos, positivos ou zero.
Exemplos comuns incluem variáveis que armazenam idade, quantidade de produtos,
códigos de identificação, entre outros.
Ponto flutuante (float / double): este tipo armazena valores que pertencem ao conjunto dos
números reais, ou seja, valores que podem conter casas decimais. Peso, altura, dinheiro,
são exemplos de variáveis que se enquadram nessa categoria.
Caractere (char): é o tipo utilizado para armazenar letras. Um exemplo típico é o
armazenamento do gênero de uma pessoa, em que 'F' é utilizado para representar feminino
e 'M' para masculino.
Booleano (bool): variáveis desse tipo são capazes de armazenar apenas um de dois valores
possíveis: verdadeiro ou falso. Geralmente, são empregadas em validações, como para
verificar se um usuário digitou um valor específico ou se selecionou uma opção
determinada em uma lista. Para utilizá-lo em C, devemos incluir a biblioteca <stdbool.h>.

Para se usar uma variável em uma linguagem de programação é preciso criá-la e, para isso, usa-
se a seguinte sintaxe:

<tipo> <nome_da_variável>

Esta sintaxe é amplamente reconhecida em todas as linguagens de programação, embora


algumas permitam certas modificações. Na linguagem de programação C essa norma é
obrigatória, e o campo <tipo> pode ser quaisquer um dos tipos primitivos definidos
anteriormente, como int (inteiros), float ou double (ponto flutuante) e char (caracteres).

Já para o <nome_da_variável> devemos seguir algumas regras, tais como:

Devem começar com uma letra.


Os próximos caracteres podem ser letras ou números.
Não pode utilizar nenhum símbolo, exceto underline ( _ ).
Não pode conter espaços em branco.
Não pode conter letras com acentos.

Veja a seguir alguns exemplos de criações de variáveis no Quadro 1:

1: #include <stdbool.h>
2: int main(){
3: int idade, num2;
4: float salario = 7500;
5: double qtd_atomos;
6: bool confirma = false;
7: char genero = ‘M’;
8: return 0;
Disciplina

ALGORITMOS E PROGRAMAÇÃO
ESTRUTURADA

9: }

Quadro 1 | exemplos de variáveis em C.

Note que ao criar uma variável, o programador tem a opção de atribuir um valor imediatamente
ou deixá-la sem valor inicial. Outro ponto importante é que a maioria das linguagens de
programação é sensível a maiúsculas e minúsculas, o que implica que letras maiúsculas e
minúsculas são tratadas como diferentes. Portanto, a variável "valor" é diferente da variável
"Valor".

Siga em Frente...

O endereço de memória de uma variável


O espaço alocado para uma variável depende do seu tipo. Por exemplo, para uma variável do tipo
int, 4 bytes são reservados na memória. O tamanho alocado na memória com base no tipo de
variável limita o valor que pode ser armazenado nesse espaço. Por exemplo, seria inviável
armazenar o valor de 10 trilhões em uma variável do tipo 'int'. Em um cálculo simples, 4 bytes
correspondem a 32 bits. Cada bit pode armazenar apenas 0 ou 1. Assim, a equação resultante
seria o valor máximo de uma variável inteira, que é 232, ou seja, [Link]. No entanto, esse
valor deve ser dividido por dois, uma vez que um int pode armazenar números negativos e
positivos. Consequentemente, uma variável int pode ter um valor entre -[Link] e
[Link].

Para contornar as limitações dos valores que uma variável pode assumir com base em seu tipo,
foram desenvolvidos modificadores de tipos, os quais são comandos utilizados na declaração da
variável para ajustar sua capacidade padrão. Os três principais modificadores são:

unsigned: utilizado para especificar que a variável armazenará apenas a parte positiva do
número.
short: reduz o espaço reservado na memória.
long: aumenta a capacidade padrão.

A Tabela 1 apresenta o tamanho e os possíveis valores de alguns tipos, incluindo os


modificadores.

Tamanho(bytes
Tipo Faixa de valores
)
int 4 -[Link]
até
Disciplina

ALGORITMOS E PROGRAMAÇÃO
ESTRUTURADA

[Link]

float 4 -3,438 até 3,438

-1,7308 até
double 8
1,7308
char 1 -128 até 127
0 até
unsigned int 4
[Link]
-32.768 até
short int 2
32.767

-3,44932 até
Long double 16
3,44932

Tabela 1 | Principais tipos primitivos e modificadores.

A memória de um computador é fragmentada em blocos de bytes, sendo que cada bloco


consiste em 8 bits, e cada um possui um endereço distinto para identificação. Podemos fazer
uma simples analogia com os endereços das residências, em que cada casa possui uma
localização exclusiva, e a duplicação de endereços geraria problemas significativos. Sabemos
que as variáveis são utilizadas para reservar temporariamente espaços na memória, e cada uma
possui um endereço único para identificação. É possível obter o endereço de alocação de uma
variável ao utilizar o operador "&" no momento da impressão da variável.

O operador "&" é de extrema importância na linguagem C, uma vez que permite o acesso direto
aos endereços de memória das variáveis. À medida que progredimos em nossos estudos,
utilizaremos esse operador para alocar espaços na memória.

Como já estudamos previamente, para armazenar valores digitados pelo usuário em uma
variável, podemos usar a função scanf(), com a seguinte estrutura:

scanf(“especificador”, &variavel);

A Figura 2 apresenta um exemplo no qual se utilizou o especificador “%d” para indicar ao


compilador que o valor que será digitado deve ser um inteiro, e este valor será guardado no
endereço de memória da variável x.
Disciplina

ALGORITMOS E PROGRAMAÇÃO
ESTRUTURADA

Figura 2 | Exemplo de leitura de dados com scanf e sua relação com a memória.

Para obter acesso ao endereço de memória de uma variável e armazenar valores inseridos pelo
usuário, vamos desenvolver um programa em linguagem C que guarda dois valores, cada um em
sua respectiva variável. Para isso, o usuário será solicitado a fornecer as entradas, que serão
então armazenadas nas variáveis `valor1` e `valor2`. A solução para este problema pode ser vista
no Quadro 2. É importante observar que na linha 4, todas as variáveis, sendo do mesmo tipo, são
declaradas na mesma linha, separadas por vírgula. Nas linhas 7, 9 e 10, os valores inseridos pelo
usuário serão armazenados nos endereços das variáveis ‘caractere’, ‘valor1’ e ‘valor2’,
respectivamente.

1: #include <stdio.h>
2: int main(){
3: char caractere;
4: float valor1, valor2;
5:
6: printf("\n Digite um caractere
7: qualquer:");
8: scanf("%c", &caractere);
9: printf("\n Digite o primeiro valor:");
10: scanf("%f", &valor1);
11: printf("\n Digite o segundo valor:");
12: scanf("%f", &valor2);
13:
14: printf("Variável 1 = %c\n", caractere);
15: printf("Variável 2 = %.2f\n", valor1);
16: printf("Variável 3 = %.2f\n", valor2);
17: return 0;
18: }

Quadro 2 | Exemplo de entrada e saída em C.


Disciplina

ALGORITMOS E PROGRAMAÇÃO
ESTRUTURADA

Constantes
Como já vimos, constante se refere a um valor que permanece inalterado ao longo do programa.
Na linguagem C, existem duas maneiras de criar valores constantes. A primeira envolve o uso da
diretiva #define, que é colocada logo após a inclusão das bibliotecas. Nesse caso, a sintaxe seria
a seguinte:

#define <nome_da_constante> <valor>

É importante observar que não deve haver ponto e vírgula no final. Além disso, é fundamental
notar que a diretiva não utiliza espaço na memória; ela simplesmente cria um rótulo associado a
um valor. Como nenhum espaço é alocado na memória, o operador "&" não pode ser usado nesse
contexto.

A segunda maneira de criar valores constantes é semelhante à declaração de variáveis, exceto


pelo uso do comando "const" antes do tipo. Portanto, a sintaxe seria:

const <tipo> <nome_da_constante>;

Quando se utiliza a segunda forma de declaração, a alocação de espaço na memória segue os


mesmos princípios das variáveis, ou seja, int alocará 4 bytes, char 1 byte, e assim por diante. A
diferença fundamental entre constantes e variáveis é que o valor de uma constante nunca pode
ser alterado. Se uma constante, por exemplo “const int x = 5;”, for criada e for feita uma tentativa
de modificar seu valor durante a execução do código, o compilador emitirá um erro e não gerará
o arquivo executável.

Vale ressaltar que tanto para a primeira quanto para a segunda forma de criar constantes, valem
as mesmas regras de nomenclatura de variáveis.

No Exemplo do Quadro 3 há duas formas de sintaxes para constantes. Na linha 2 definimos uma
constante (rótulo) chamada pi com valor 3.14. Na linha 4 criamos uma constante usando o
comando const. Nas linhas 5 e 6 imprimimos o valor de cada constante, veja que nada difere da
impressão de variáveis.

1: #include<s tdio.h>
2: #define pi 3.14
3: int main(){
4: const float g = 9.8;
5: printf(“\n pi = %f”, pi);
6: printf(“\n g = %f”, g);
7: return 0;
Disciplina

ALGORITMOS E PROGRAMAÇÃO
ESTRUTURADA

8: }

Quadro 3 | Utilização de constantes em C.

Vamos Exercitar?

Agora é a sua vez de aplicar todo o conhecimento adquirido sobre variáveis e constantes!
Lembre-se que você está desenvolvendo um software para uma loja de eletrodomésticos, e este
deve calcular o preço final de um produto com base no preço de venda, impostos e descontos
aplicáveis.

Nesse contexto, podemos usar variáveis para armazenar o preço de venda do produto, o valor
dos impostos e o valor do desconto. Podemos usar constantes para representar as taxas de
impostos aplicáveis e os descontos padrão para determinados produtos.

Suponha que o preço de venda de um televisor seja de R$ 1500.00. Vamos considerar que a taxa
de imposto aplicável seja de 10%, e que haja um desconto padrão de 5% para esse produto em
particular.

Aqui está um exemplo simplificado em linguagem C que poderia ser usado para calcular o preço
final do televisor após a aplicação dos impostos e descontos:

1: #include <stdio.h>
2: int main(){
3: // Variáveis
4: float precoVenda, valorImposto,
5: valorDesconto, precoFinal;
6: // Constantes
7: const float taxaImposto = 0.1;
8: const float descontoPadrao = 0.05;
9: // Entrada
10: printf("Informe o preço de venda do
11: produto: ");
12: scanf("%f", &precoVenda);
13: // Processamento
14: valorImposto = precoVenda *
15: taxaImposto;
16: valorDesconto = precoVenda *
17: descontoPadrao;
18: precoFinal = precoVenda +
valorImposto - valorDesconto;
// Saída
Disciplina

ALGORITMOS E PROGRAMAÇÃO
ESTRUTURADA

printf("O preço final do televisor é: R$


%.2f", precoFinal);
return 0;
}

Saiba mais
Para entender melhor o conceito de variáveis e como elas são utilizadas e declaradas na
linguagem C, sugerimos a leitura do Capítulo 2 - Lendo e escrevendo nas variáveis do livro
Linguagem C: Completa e Descomplicada, disponível na Biblioteca Virtual.

BACKES, A. Linguagem C: completa e descomplicada. 2. ed. Rio de Janeiro: LTC, 2023. cap. 2, p.
25-47.

Com relação aos tipos de variáveis que podemos utilizar, o Capítulo 2 - Tipos de Dados Básicos
do livro Linguagem C complementa bem o assunto.

DAMAS, L. Linguagem C. 10. ed. Rio de Janeiro: LTC, 2023. cap. 2, p. 21-50.

Para auxiliar no desenvolvimento de programas na linguagem C, uma ótima prática é verificar a


documentação da linguagem para entender em detalhes os principais tipos de funções e
elementos utilizados. Para isso, sugerimos a consulta da seguinte documentação sempre que
achar necessário. Nela você encontra todas as bibliotecas utilizadas na linguagem e como
utilizar suas principais funções: Referência da Linguagem C.

Referências
BACKES, A. Linguagem C: completa e descomplicada. 2. ed. Rio de Janeiro: LTC, 2023.

CORMEN, T. H. Desmistificando algoritmos. 1. ed. Rio de Janeiro: Elsevier, 2014.

DAMAS, L. Linguagem C. 10. ed. Rio de Janeiro: LTC, 2023. [Minha biblioteca].

MENÉNDEZ, A. Simplificando algoritmos. 1. ed. Rio de Janeiro: LTC, 2023.

PIVA JUNIOR, D. Algoritmos e programação de computadores. 2. ed. Rio de Janeiro: Elsevier,


2019.
Disciplina

ALGORITMOS E PROGRAMAÇÃO
ESTRUTURADA

Aula 4
Operadores e Expressões

Operadores e expressões

Este conteúdo é um vídeo!


Para assistir este conteúdo é necessário que você acesse o AVA pelo
computador ou pelo aplicativo. Você pode baixar os vídeos direto no aplicativo
para assistir mesmo sem conexão à internet.
Dica para você
Aproveite o acesso para baixar os slides do vídeo, isso pode deixar sua
aprendizagem ainda mais completa.

Estudante, esta videoaula foi preparada especialmente para você. Nela, você irá aprender
conteúdos importantes para a sua formação profissional. Vamos assisti-la?

Ponto de Partida

A base fundamental de um computador reside na capacidade de receber dados, processá-los e


apresentar os resultados. Portanto, é fundamental entender o processamento de dados
utilizando operações e expressões matemáticas, combinando-as com o uso de operadores
lógicos.

Com o intuito de manter a progressão do treinamento e contribuir com o avanço tanto teórico
quanto prático, proponha à sua equipe de estagiários o desenvolvimento de um programa em C
que calcule a média da quantidade de produtos vendidos anualmente por uma empresa de varejo
com base nos dados apresentados na Tabela 1. Qual é a média de produtos vendidos em 2020,
2021 e 2022? É possível identificar qual ano teve a média mais alta? Há alguma outra abordagem
para comparar os dados? Certifique-se de apresentar o programa resultante para toda a equipe.

Tipo de Quantidade de produtos vendidos por


produto ano
2020 2021 2022
TV 800 950 725
Disciplina

ALGORITMOS E PROGRAMAÇÃO
ESTRUTURADA

Notebook 650 550 700


Smartphone 1500 1800 2100

Tabela 1 | Relação de produtos vendidos por ano.

Agora é o momento de iniciar esta jornada. Preste muita atenção na aula e tenha um excelente
estudo!

Vamos Começar!

Olá! Com o conhecimento sobre algoritmos e como criá-los por meio de linguagem natural e
fluxogramas, o próximo é a representação por meio de uma linguagem de programação. Portanto
você irá agora aprofundar no estudo da linguagem de programação C.

Operadores Aritméticos
Vamos começar a aprimorar nossos algoritmos com as operações aritméticas. Veja na Tabela 2
algumas operações disponíveis nas linguagens de programação e seus respectivos exemplos.

Operador Descrição Exemplo Resultado


+ Soma 8+4 12
- Subtração 8-4 4
Multiplica
* 8*4 32
ção
/ Divisão 8/4 2
= Atribuição x=8 x=8
% Módulo 8%4 0

Tabela 2 | Operadores aritméticos.

Quando trabalhamos com operadores em programação, a ordem de precedência desempenha


um papel crucial. Os operadores aritméticos seguem a seguinte ordem de execução:

1. Parênteses.
2. Potenciação e radiciação.
3. Multiplicação, divisão e módulo.
4. Adição e subtração.
Disciplina

ALGORITMOS E PROGRAMAÇÃO
ESTRUTURADA

Dentre as operações aritméticas descritas na Tabela 1.1, a operação de módulo (%) é usada para
calcular o resto da divisão de um número, considerando apenas a parte inteira do quociente. Por
exemplo, a divisão inteira de 43 por 3 (43 / 3) resulta no valor 14, com resto igual a 1. Portanto, a
operação 43 % 3 produz como resultado o valor 1.

Ainda, os operadores aritméticos podem ser categorizados como unários ou binários. Os


operadores binários são aqueles que utilizam dois componentes, e foram abordados na Tabela
1.1. Já os operadores unários utilizam apenas um componente. Um exemplo de operadores
unários são os operadores de incremento (++) e decremento (--). Esses operadores aumentam ou
diminuem "um" do valor de uma variável e podem ser utilizados de duas maneiras:

Pré-incremento e pré-decremento: quando o operador é colocado antes da variável (++x ou -


-x), o valor é alterado e utilizado na expressão original.
Pós-incremento e pós-decremento: quando o operador é colocado após a variável (x++ ou
x--), o valor é utilizado na expressão original e depois é alterado.

Veja o trecho de código no Quadro 1 que ilustra esta mecânica dos operadores ++ e --. Execute-o
em seu computador e verifique a diferença na utilização dos operadores.

1: #include <stdio.h>
2: int main(){
3: int x, y;
4: x = 10; y = x++;
5: printf("y = x++ : valor de y => %d\n", y);
6: printf("y = x++ : valor de x => %d\n\n", x);
7: x = 10; y = x--;
8: printf("y = x-- : valor de y => %d\n", y);
9: printf("y = x-- : valor de x => %d\n\n", x);
10: x = 10; y = ++x;
11: printf("y = ++x : valor de y => %d\n", y);
12: printf("y = ++x : valor de x => %d\n\n", x);
13: x = 10; y = --x;
14: printf("y = --x : valor de y => %d\n", y);
15: printf("y = --x : valor de x => %d\n\n", x);
16: return 0;
17: }

Quadro 1 | Exemplo de código com operadores aritméticos.

Operadores Relacionais
Operadores relacionais são fundamentais no processamento de dados em linguagens de
programação, pois permitem a comparação entre valores, o que possibilita a execução de ações
Disciplina

ALGORITMOS E PROGRAMAÇÃO
ESTRUTURADA

com base nos resultados obtidos. Por exemplo, é possível criar um programa que some as notas
de dois bimestres de um aluno e calcule a média aritmética. A partir desse resultado, se a média
for superior a seis, o aluno é considerado aprovado; caso contrário, é reprovado.

Ao lidar com a comparação de valores em programação, utilizamos operadores relacionais. A


Tabela 3 apresenta os operadores utilizados em diversas linguagens de programação.

Operador Descrição Exemplo


== Igual a x == y
!= Diferente de x != y
> Maior que x>y
< Menor que x<y
>= Maior ou igual a x >= y
<= Menor ou igual a x <= y

Tabela 3 | Operadores relacionais.

Os operadores relacionais são empregados na construção de expressões booleanas, ou seja,


expressões que resultam em verdadeiro ou falso. Em linguagem C, ao realizarmos uma
comparação, o resultado é interpretado como um ou zero, em que o primeiro representa
verdadeiro e o segundo, falso.

Vamos considerar a criação de um programa que solicita dois números inteiros ao usuário e
realiza algumas comparações com esses valores. No Quadro 2, é possível observar que na linha
8, comparamos se os números são iguais. Na linha 9, comparamos se o primeiro é maior que o
segundo e, na linha 10, se o primeiro é menor ou igual ao segundo. Os respectivos prinft() irão
exibir na tela os valores de saída 0 ou 1 de acordo com o resultado das comparações efetuadas.
Disciplina

ALGORITMOS E PROGRAMAÇÃO
ESTRUTURADA

1: #include <stdio.h>
2: int main(){
3: int n1, n2;
4: printf(“Digite o primeiro numero: “);
5: scanf(“%d”, &n1);
6: printf(“Digite o segundo numero: “);
7: scanf(“%d”, &n2);
8: printf(“\n n1 e n2 sao iguais? %d”,
9: n1==n2);
10: printf(“\n n1 e maior que n2? %d”,
11: n1>n2);
12: printf(“\n n1 e menor ou igual a n2? %d”,
n1<=n2);
return 0;
}

Quadro 2 | Exemplo de código com operadores relacionais.

Siga em Frente...

Operadores Lógicos
Além dos operadores relacionais, outro recurso fundamental no processamento de dados é a
utilização de operadores lógicos, os quais se baseiam na lógica matemática clássica e na lógica
booleana. Na Tabela 4 são apresentados os operadores lógicos que podem ser utilizados em
diversas linguagens de programação.

Operador Descrição Exemplo


Negação
! !(x == y)
(NOT)
Conjunção (x > y) && (a
&&
(AND) == b)
Disjunção (x > y) || (a ==
||
(OR) b)

Tabela 4 | Operadores lógicos.

Note que nos exemplos da Tabela 4 os operadores lógicos são usados em conjunto com os
operadores relacionais para formar comparações mais complexas.
Disciplina

ALGORITMOS E PROGRAMAÇÃO
ESTRUTURADA

Aqui estão algumas características importantes a serem assimiladas:

O operador de negação é usado para inverter o resultado de uma expressão.


O operador de conjunção é utilizado para estabelecer condições em que todas as
alternativas devem ser verdadeiras.
O operador de disjunção é utilizado para criar condições em que basta uma das condições
ser verdadeira para que o resultado seja verdadeiro também.

No Quadro 3, é possível observar o uso dos operadores relacionais e lógicos aplicados na


comparação dos valores de três variáveis. Na linha 4, a condição estabelecida será verdadeira se
o valor de "a" for igual ao valor de "b" E o valor de "a" for igual a "c"; como a primeira condição não
é verdadeira, o resultado da expressão será 0. Na linha 5, a condição será verdadeira se uma das
condições for satisfeita, portanto o resultado será 1. Por fim, na linha 6, o resultado é invertido
utilizando o operador de negação.

1: #include <stdio.h>
2: int main(){
3: int a=5, b=10, c=5;
4: printf(“\n (a==b)&&(a==c) = %d”,
5: ((a==b)&&(a==c)));
6: printf(“\n (a==b)||(a==c) = %d”, ((a==b)||
7: (a==c)));
8: printf(“\n !(a==b)||(a==c) = %d”, !((a==b)||
(a==c)));
return 0;
}

Quadro 3 | Exemplo de código com operadores lógicos.

Até aqui você já estudou os três tipos principais de operadores: aritméticos, relacionais e lógicos.
Sendo assim, é importante destacar que entre estes três grupos também há uma ordem de
precedência que é seguida na execução de expressões.

1. Parênteses para forçar uma avaliação específica.


2. Operadores unários, como os de incremento (++) e decremento (--).
3. Multiplicação (*), divisão (/) e módulo (%).
4. Adição (+) e subtração (-).
5. Operadores relacionais, como menor que (<), maior que (>), menor ou igual (<=), maior ou
igual (>=), igual (==) e diferente (!=).
6. Operadores lógicos: 'E' (&&), 'OU' (||) e 'NÃO' (!).

Vamos Exercitar?
Disciplina

ALGORITMOS E PROGRAMAÇÃO
ESTRUTURADA

Agora é a sua vez de aplicar todo o conhecimento adquirido sobre operadores! Lembre-se que foi
requisitado o cálculo da média de produtos vendidos anualmente e, para isso, o primeiro passo é
armazenar os dados em variáveis. É importante destacar que não há uma única abordagem para
implementar essa solução, já que cada programador possui seu estilo e suas técnicas de
implementação individuais (além de que há outras estruturas avançadas de programação que
ainda não foram abordadas, mas que serão apresentadas mais adiante).

Vamos proceder ao armazenamento dos dados utilizando variáveis simples. Para cada produto,
criaremos três variáveis (uma para cada ano), conforme o exemplo:

int tv_2020, tv_2021, tv_2022;


int noteb_2020, noteb_2021, noteb_2022;
int smart_2020, smart_2021, smart_2022;

Serão necessárias outras três variáveis para armazenar a média de cada ano:

float media_2020 = 0;
float media_2021 = 0;
float media_2022 = 0;

Em seguida, inseriremos manualmente os valores em todas as variáveis “produto_ano”, ou se


desejar que o usuário insira os valores em vez de fornecê-los manualmente, você pode utilizar
um scanf().

Depois de inserir os dados, podemos prosseguir para o processamento das informações, que
neste caso envolve calcular a média aritmética. Para isso, somamos os dados de cada ano,
dividimos pelo número de ocorrências (três) e armazenamos na respectiva variável de média,
conforme exemplificado abaixo:

media_2020 = (tv_2020 + noteb_2020 + smart_2020) / 3;

Observe que o somatório está entre parênteses, pois a divisão tem precedência sobre a adição.

Após calcular as médias dos demais anos, 2021 e 2022, você pode utilizar operadores
relacionais e lógicos para determinar qual ano teve a maior média. Por exemplo, para verificar se
2020 teve a maior média de produtos vendidos, você pode usar o seguinte comando:

printf("2020 obteve a maior media? %d", ((media_2020 > media_2021) && (media_2020 >
media_2022)));
Disciplina

ALGORITMOS E PROGRAMAÇÃO
ESTRUTURADA

Certifique-se de imprimir as médias e os testes lógicos. Complete o código com os cálculos


necessários e as comparações apropriadas, conforme os exemplos dados, execute-o e verifique
se todos os membros da equipe conseguem fazer o programa funcionar.

Os operadores relacionais e lógicos podem ser incorporados em estruturas condicionais. Na


próxima unidade, você aprenderá sobre esse recurso e poderá aprimorar suas implementações.

Saiba mais
Para entender melhor o conceito de variáveis e como elas são utilizadas e declaradas na
linguagem C, sugerimos a leitura do Capítulo 2 - Lendo e escrevendo nas variáveis, do livro
Linguagem C: Completa e Descomplicada, disponível na Biblioteca Virtual .

BACKES, A. Linguagem C: completa e descomplicada. 2. ed. Rio de Janeiro: LTC, 2023. cap. 2, p.
25-47.

Com relação aos tipos de variáveis que podemos utilizar, o Capítulo 2 - Tipos de Dados Básicos,
do livro Linguagem C complementa bem o assunto.

DAMAS, L. Linguagem C. 10. ed. Rio de Janeiro: LTC, 2023. cap. 2, p. 21-50.

Para auxiliar no desenvolvimento de programas na linguagem C, uma ótima prática é verificar a


documentação da linguagem para entender em detalhes os principais tipos de funções e
elementos utilizados. Para isso, sugerimos a consulta da seguinte documentação sempre que
achar necessário. Nela você encontra todas as bibliotecas utilizadas na linguagem e como
utilizar suas principais funções: Referência da Linguagem C.

Referências
BACKES, A. Linguagem C: completa e descomplicada. 2. ed. Rio de Janeiro: LTC, 2023.

CORMEN, T. H. Desmistificando algoritmos. 1. ed. Rio de Janeiro: Elsevier, 2014.

DAMAS, L. Linguagem C. 10. ed. Rio de Janeiro: LTC, 2023.

MENÉNDEZ, A. Simplificando algoritmos. 1. ed. Rio de Janeiro: LTC, 2023.

PIVA JUNIOR, D. Algoritmos e programação de computadores. 2. ed. Rio de Janeiro: Elsevier,


2019.
Disciplina

ALGORITMOS E PROGRAMAÇÃO
ESTRUTURADA

Aula 5
Encerramento da Unidade

Videoaula de Encerramento

Este conteúdo é um vídeo!


Para assistir este conteúdo é necessário que você acesse o AVA pelo
computador ou pelo aplicativo. Você pode baixar os vídeos direto no aplicativo
para assistir mesmo sem conexão à internet.
Dica para você
Aproveite o acesso para baixar os slides do vídeo, isso pode deixar sua
aprendizagem ainda mais completa.

Estudante, esta videoaula foi preparada especialmente para você. Nela, você irá aprender
conteúdos importantes para a sua formação profissional. Vamos assisti-la?

Ponto de Chegada
Olá, estudante! Para desenvolver a competência desta Unidade, que é “compreender a utilização
dos fundamentos de algoritmos para utilizar na linguagem de programação”, você deverá
primeiramente conhecer os conceitos fundamentais de algoritmos, que são conjuntos de
instruções sequenciais que permitem resolver problemas passo a passo. Esses algoritmos
podem ser representados de diferentes maneiras, como por meio de fluxogramas ou de forma
textual, usando linguagem natural.

Na linguagem de programação C, os conceitos básicos da estrutura de programação são


fundamentais para iniciar o desenvolvimento de aplicativos. A estrutura de programação em C é
baseada em funções, que são blocos de código que realizam tarefas específicas. A função
`main` é o ponto de entrada de qualquer programa em C. Dentro das funções, as variáveis e
constantes são elementos-chave. As variáveis são espaços na memória que armazenam valores
temporários, enquanto as constantes representam valores fixos que não podem ser alterados
durante a execução do programa.

Os principais tipos de variáveis em C incluem inteiros, pontos flutuantes, caracteres, entre outros.
Cada tipo possui um tamanho específico na memória, o que influencia o intervalo de valores que
Disciplina

ALGORITMOS E PROGRAMAÇÃO
ESTRUTURADA

pode ser armazenado. Além disso, os operadores aritméticos, como adição, subtração,
multiplicação e divisão, são essenciais para realizar cálculos matemáticos. Os operadores
relacionais são usados para comparar valores e avaliar se uma condição é verdadeira ou falsa.
Já os operadores lógicos permitem combinar ou inverter condições lógicas para tomar decisões
em um programa.

Dominar esses conceitos é crucial para desenvolver algoritmos eficientes e criar programas
robustos e funcionais em linguagem C. A compreensão desses fundamentos capacita os
programadores a resolver uma ampla variedade de problemas e a criar soluções adaptáveis e de
alto desempenho.

É Hora de Praticar!

Este conteúdo é um vídeo!


Para assistir este conteúdo é necessário que você acesse o AVA pelo
computador ou pelo aplicativo. Você pode baixar os vídeos direto no aplicativo
para assistir mesmo sem conexão à internet.

Você acabou se formar e possui um amplo conhecimento a respeito de programação, e por isso
está à procura de trabalhos de desenvolvimento de software para enriquecer seu portfólio.
Sabendo disso, uma pizzaria do bairro onde mora o procurou, pois gostaria de automatizar seu
caixa. A princípio, foi lhe solicitado apenas implementar um cálculo simples, em que, dado o
valor total da conta de uma mesa, o programa divide esse valor pela quantidade de integrantes
da mesa e calcula o desconto concedido. O programa deve receber como dados o valor da conta,
a quantidade de pessoas e o percentual de desconto (%). Com os dados no programa, como
deverá ser feito o cálculo do valor total da conta com o desconto e o valor que cada pessoa
deverá pagar?

Há outras maneiras de representar algoritmos além de fluxogramas e linguagem natural?


Por que a elaboração de fluxogramas é importante no desenvolvimento de algoritmos no
estudo da programação?
Qual a importância da precedência de operadores em linguagem de programação?

O código a seguir apresenta o resultado do problema. Um ponto importante é o cálculo do


desconto feito na linha 13, para cuja montagem utilizamos uma regra de três simples. Outro
ponto é o cálculo do valor por pessoa, feito na linha 15 diretamente dentro do comando de
impressão. Esse recurso pode ser usado quando não é preciso armazenar o valor.
1: #include<stdio.h>
Disciplina

ALGORITMOS E PROGRAMAÇÃO
ESTRUTURADA

2: int main(){
3: float valor_bruto=0;
4: float valor_liquido=0;
5: float desconto=0;
6: int qtd_pessoas=0;
7: printf("\n Digite o valor total da conta: ");
8: scanf("%f",&valor_bruto);
9: printf("\n Digite a quantidade de pessoas: ");
10: scanf("%d",&qtd_pessoas);
11: printf("\n Digite o desconto (em porcentagem): ");
12: scanf("%f",&desconto);
13: valor_liquido = valor_bruto - (valor_bruto * desconto/100);
14: printf("\n Valor da conta com desconto = %f",valor_liquido);
15: printf("\n Valor a ser pago por pessoa = ");
16: printf("\%f", valor_liquido/qtd_pessoas);
17: }
18:
Agora vamos analisar o código sob todos os aspectos estudados a respeito de algoritmos e
fundamentos de programação:

#include<stdio.h>: este é um pré-processador que inclui a biblioteca de entrada e saída


padrão em C, permitindo o uso de funções como printf e scanf.
main() { ... }: esta é a função principal do programa em C. O programa começa a execução
a partir desta função.
Declaração de variáveis: as variáveis valor_bruto, valor_liquido, desconto e qtd_pessoas são
declaradas e inicializadas. valor_bruto, valor_liquido e desconto são variáveis de ponto
flutuante que armazenam valores monetários e percentuais, enquanto qtd_pessoas é uma
variável inteira que armazena o número de pessoas.
Entrada do usuário: o programa solicita ao usuário que insira o valor total da conta, a
quantidade de pessoas e o desconto em porcentagem. A função scanf é usada para
armazenar os valores fornecidos pelo usuário nas variáveis apropriadas.
Cálculo (Processamento) do valor líquido: O valor líquido é calculado subtraindo o valor
bruto do produto e do desconto, convertido em um valor decimal.
Saída de resultados: os valores do valor líquido da conta com desconto e do valor a ser
pago por pessoa são impressos na tela utilizando a função printf.

O infográfico a seguir ilustra e identifica o passo a passo para se construir um algoritmo


adequadamente, identificando principalmente os seus três principais componentes: entrada,
processamento e saída.
Disciplina

ALGORITMOS E PROGRAMAÇÃO
ESTRUTURADA

BACKES, A. Linguagem C: completa e descomplicada. 2. ed. Rio de Janeiro: LTC, 2023.


CORMEN, T. H. Desmistificando algoritmos. 1. ed. Rio de Janeiro: Elsevier, 2014.
Disciplina

ALGORITMOS E PROGRAMAÇÃO
ESTRUTURADA

DAMAS, L. Linguagem C. 10. ed. Rio de Janeiro: LTC, 2023.


MENÉNDEZ, A. Simplificando algoritmos. 1. ed. Rio de Janeiro: LTC, 2023.
PIVA JUNIOR, D. Algoritmos e programação de computadores. 2. ed. Rio de Janeiro: Elsevier,
2019.
,

Unidade 2
Estruturas de Controle e Repetição

Aula 1
Estrutura de Decisão Condicional

Estrutura de decisão condicional

Este conteúdo é um vídeo!


Para assistir este conteúdo é necessário que você acesse o AVA pelo
computador ou pelo aplicativo. Você pode baixar os vídeos direto no aplicativo
para assistir mesmo sem conexão à internet.
Dica para você
Aproveite o acesso para baixar os slides do vídeo, isso pode deixar sua
aprendizagem ainda mais completa.

Estudante, esta videoaula foi preparada especialmente para você. Nela, você irá aprender
conteúdos importantes para a sua formação profissional. Vamos assisti-la?

Ponto de Partida

Olá! Até aqui você já estudou os conceitos de algoritmos, a linguagem de programação, os tipos
de dados, as variáveis, as constantes, os operadores e as expressões, portanto, agora é o
momento de avançar! Nesta seção, você estudará as estruturas de decisão condicional e
seleção.
Disciplina

ALGORITMOS E PROGRAMAÇÃO
ESTRUTURADA

A instituição de ensino que você trabalha está atualmente em meio a um esforço para melhorar
suas operações, e lançou o seguinte desafio para você: criar um programa em linguagem C que
determine o salário líquido de cada colaborador, considerando as deduções do INSS e Imposto
de Renda conforme especificado nas Tabelas 1 e 2 a seguir. Como parte do processo de
documentação, ao concluir a compilação do programa, você deve gerar um relatório que inclua o
código-fonte.

Salário de
Alíquota / INSS
Contribuição (R$)
Até R$ R$ 1.320,00 7,5%
De R$ 1.320,01 até
9%
2.571,29
De 2.571,30 até R$
12%
3.856,94
De R$ 3.856,95 a R$
14%
7.507,49

Tabela 1 | Descontos INSS.

Salário de
Alíquota / INSS
Contribuição (R$)
Até 1.903,98 -
De 1.903,99 até
7,5%
2.826,65
De 2.826,66 até
15,0%
3.751,05
De 3.751,06 até
22,5%
4.664,68
Acima de 4.664,68 27,5%

Tabela 2 | Descontos IR.

Agora é o momento de iniciar esta jornada. Preste muita atenção nas aulas e tenha um excelente
estudo!

Vamos Começar!
Disciplina

ALGORITMOS E PROGRAMAÇÃO
ESTRUTURADA

Estrutura condicional if-else


Ao lidar com determinadas situações para resolver um problema, podemos empregar a instrução
"if" (em português, "se"), a qual tem a função de tomar uma decisão e criar um desvio no
programa, permitindo assim a avaliação de uma condição como verdadeira ou falsa. É
importante lembrar que essa instrução pode receber valores em ambas as situações.

Na linguagem de programação C, usamos chaves ("{" e "}") para delimitar o início e o fim de uma
instrução. Na Tabela 3, é ilustrada a estrutura condicional simples utilizando um fluxograma
juntamente com sua sintaxe em C.

Fluxograma Linguagem C

if (condição de teste)
{
// conjunto de
comandos;
}

Tabela 3 | Instrução IF.

Agora vamos analisar uma aplicação prática de uma estrutura condicional simples com “if”, em
que será realizado um teste lógico no qual, se o resultado for verdadeiro, uma resposta será
fornecida; caso contrário, não será exibido nada. No exemplo do Quadro 1, consideramos a
situação de um jovem que verifica se está ou não apto a obter a carteira de habilitação.

1: #include <stdio.h>
Disciplina

ALGORITMOS E PROGRAMAÇÃO
ESTRUTURADA

2: int main(){
3: float idade;
4: printf(“Digite sua idade: \n”);
5: scanf(“%f”, &idade);
6: if (idade>=18)
7: {
8: printf(“Você já pode tirar sua
9: carteira de Habilitação você é
10: maior de 18”);
11: }
12: return 0;
}

Quadro 1 | Exemplo de código com estrutura condicional simples.

Neste exemplo em particular, o “senão” (else) não é levado em conta. Em outras palavras, se a
condição não for verdadeira, nenhuma resposta será exibida. Agora, vamos analisar a estrutura
condicional composta, que complementa nossa condição inicial com o uso do comando “else”, o
qual indica “caso contrário”. Vamos observar a representação dessa estrutura no fluxograma
mostrado na Tabela 4.

Fluxograma Linguagem C

if (condição de teste)
{
/* conjunto de
comandos se
condição verdadeira
*/
}
else
{
/* conjunto de
comandos se
condição falsa */
}

Tabela 4 | Instrução IF.

Vamos analisar outro exemplo para ilustrar a estrutura condicional composta em linguagem C.
Veja no Quadro 2 um programa que exibe uma mensagem na tela informando se o valor de um
Disciplina

ALGORITMOS E PROGRAMAÇÃO
ESTRUTURADA

número digitado é positivo ou negativo.

1: #include <stdio.h>
2: int main(){
3: int num;
4: printf (“Digite um número: “);
5: scanf (“%d”,&num);
6: if (num>0) {
7: printf (“\n\nO número e
8: positivo\n”);
9: }
10: else {
11: printf (“O número e negativo”);
12: }
13: return 0;
}

Quadro 2 | Exemplo de código estrutura condicional composta.

Estrutura condicional encadeada


Vamos examinar o funcionamento da estrutura condicional encadeada, também chamada de
“IFs aninhados”. Este tipo de estrutura é um comando if que é dependente de outros ifs e elses.
Em resumo, um comando else sempre estará associado ao comando if no seu nível de
aninhamento. A Tabela 5 ilustra um dos tipos de fluxogramas que representa uma estrutura
condicional encadeada.

Fluxograma Linguagem C
Disciplina

ALGORITMOS E PROGRAMAÇÃO
ESTRUTURADA

if (condição 1)
// comando;

else if (condição 2)
// comando;

else if (condição 3)
// comando;

...

else
// comando;

Tabela 5 | Instrução IF-ELSE-IF (Estrutura condicional encadeada).

Veja agora um exemplo do uso de uma estrutura condicional aninhada no Quadro 3. Perceba as
seguintes características do código com if-else-if:

As condições são avaliadas de cima para baixo.


Assim que uma condição verdadeira é encontrada, o comando associado a ela é
executado.
O restante das condições não é executado.
Se nenhuma das condições for verdadeira, o último else é executado.

1: #include <stdio.h>
2: int main(){
3: int num = 10;
4: if(num < 100)
5: printf(“Menor que 100”);
6: else if(num < 1000)
7: printf(“Menor que 1000”);
Disciplina

ALGORITMOS E PROGRAMAÇÃO
ESTRUTURADA

8: else if(num < 10000)


9: printf(“Menor que 10000”);
10: else
11: printf(“Maior ou igual a 10000”);
12: return 0;
13: }

Quadro 3 | Exemplo de código com if-else-if.

Siga em Frente...

Estrutura condicional de seleção de casos: switch


Agora vamos estudar a estrutura condicional de seleção de casos, conhecida como switch-case.
Esta estrutura avalia sucessivamente o valor de uma expressão em relação a uma lista de
constantes inteiras ou caracteres (lista de “casos”). Quando o valor é encontrado nesta lista de
“casos”, o comando correspondente é executado.

É fundamental estar atento a algumas peculiaridades do comando switch-case:

Se nenhum dos valores for encontrado, o comando default será executado.


Os comandos são executados até que o comando break seja encontrado.

A Tabela 6 a seguir ilustra o fluxograma e a sintaxe de um comando switch-case. Perceba que o


uso do comando break é destinado a interromper o ciclo de repetição. Em outras palavras, ele sai
do comando sem executar as instruções subsequentes. Se o comando break não for incluído, o
programa continua a verificar o próximo caso até o término do switch ou até encontrar um break.

Fluxograma Linguagem C
Disciplina

ALGORITMOS E PROGRAMAÇÃO
ESTRUTURADA

switch (variável)
{
case constante1:
// conjunto de
comandos
break;

case constante2:
// conjunto de
comandos
break;

...

default:
// conjunto de
comandos
}

Tabela 6 | Fluxograma e sintaxe da instrução switch-case.

Vamos agora a um exemplo no Quadro 4. O código aplica uma porcentagem de desconto no


valor da compra de acordo com uma opção selecionada.
Disciplina

ALGORITMOS E PROGRAMAÇÃO
ESTRUTURADA

1: #include <stdio.h>
2: int main(){
3: char opcao;
4: float valor, total;
5: printf("\n Digite o valor da compra \n");
6: scanf("%f", &valor);
7: printf("\n Digite a letra que representa o
8: desconto a ser aplicado:\n");
9: printf("\ta - 10%% de desconto\n");
10: printf("\tb - 15%% de desconto\n");
11: printf("\n Digite sua opção:");
12: scanf("%s", &opcao);
13: switch(opcao)
14: {
15: case 'a':
16: total = valor - (valor*0.10);
17: printf(" \nValor final da compra: R$
18: %.2f\n", total);
19: break;
20: case 'b':
21: total = valor - (valor*0.20);
22: printf(" \nValor final da compra: R$
23: %.2f\n", total);
24: break;
25: default:
26: printf("opcao invalida\n");
27: }
return 0;
}

Quadro 4 | Exemplo de código utilizando switch-case.

Vamos Exercitar?

Prezado estudante, é hora de aplicar todo o conhecimento adquirido até aqui! Vale lembrar que a
sua tarefa era criar um programa em linguagem C que determine o salário líquido de cada
colaborador, considerando as deduções do INSS e Imposto de Renda conforme especificado nas
Tabelas 1 e 2.

O cálculo das alíquotas do INSS e IR são feitas de forma indireta, dividindo o salário de acordo
com as faixas e aplicando cada porcentagem na parte específica do salário. Por exemplo: em um
salário de 1.500,00, incide 7,5% em cima de 1.320,00 (primeira faixa), e incide 9% em cima de
Disciplina

ALGORITMOS E PROGRAMAÇÃO
ESTRUTURADA

180,00 (que é o que excede a primeira faixa salarial). Porém, para simplificar os cálculos, vamos
resolver este problema de forma direta, ou seja, aplicando a porcentagem no salário total. Por
exemplo: em um salário de 1.500,00, como ele está entre 1.320,00 e 2.571,29, incide a taxa de 9%
sobre todo o salário. O cálculo do IR também não é feito de forma direta, mas para simplificar
também vamos aplicar o desconto de forma direta, ou seja, aplicando a porcentagem no salário
total.

1: #include <stdio.h>
2: int main(){
3: float salário, inss, ir, sal_liquido;
4: printf("Calculo de Salario Liquido Com
5: desconto do IR e INSS\n\n");
6: printf("\nDigite seu salario Bruto\n");
7: scanf("%f", &salario);
8: // Calcular o INSS
9: if ( salario <= 1320)
10: inss = salario * 0.075;
11: else if ( salario >= 1320 && salario <=
12: 2571.29)
13: inss = salario * 0.09;
14: else if ( salario >= 2571.30 && salario <=
15: 3856.94)
16: inss = salario * 0.12;
17: else if ( salario >= 3856.95 && salario <=
18: 7507.49)
19: inss = salario * 0.14;
20: else
21: inss = 1051,04; // teto de contribuição
22:
23: //Calcular o IR
24: if ( salario <= 1903.98 )
25: ir = salario*0;
26: else if ( salario >= 1903.99 && salario <=
27: 2826.65)
28: ir = salario * 0.075;
29: else if ( salario >= 2826.66 && salario <=
30: 3751.05 )
31: ir = salario * 0.15;
32: else if ( salario >= 3751.06 && salario <=
33: 4664.68 )
34: ir = salario * 0.225;
35: else if ( salario > 4664.69 )
36: ir = salario * 0.275;
37: //Calculo do Salario liquido
Disciplina

ALGORITMOS E PROGRAMAÇÃO
ESTRUTURADA

38: sal_liquido = (salario - inss) - ir;


//Resultados
printf( "\nDesconto do INSS e: %.2f\n\n",
inss);
printf( "Desconto do imposto de renda e:
%.2f\n\n", ir);
printf( "Salário líquido: %.2f\n\n",
sal_liquido);
return 0;
}

Quadro 5 | Exemplo de código utilizando switch-case.

Lembrando que não há uma única resposta correta. Há vários caminhos para se chegar no
mesmo resultado! Você poderia utilizar switch-case, ou então implementar o cálculo de desconto
de INSS e IR da forma completa como é feito atualmente pelo governo. Fica o desafio para você!

Saiba mais

Para entender melhor o conceito de estruturas condicionais e de seleção na linguagem C,


sugerimos a leitura do Capítulo 3 - Testes e Condições, do livro Linguagem C, disponível na
Biblioteca Virtual.

DAMAS, L. Linguagem C. 10. ed. Rio de Janeiro: LTC, 2023. cap. 3, p. 51-79.

Também sugerimos a leitura do Capítulo 4 - Comandos de controle condicional, do livro


Linguagem C: Completa e Descomplicada, disponível na Biblioteca Virtual, para complementar os
estudos sobre if e else.

BACKES, A. Linguagem C: completa e descomplicada. 2. ed. Rio de Janeiro: LTC, 2023. cap. 4, p.
67-87.

Para auxiliar no desenvolvimento de programas na linguagem C, uma ótima prática é verificar a


documentação da linguagem para entender em detalhes os principais tipos de funções e
elementos utilizados. Para isso, sugerimos a consulta da seguinte documentação sempre que
achar necessário. Nela você encontra todas as bibliotecas utilizadas na linguagem e como
utilizar suas principais funções: Referência da Linguagem C.

Referências
Disciplina

ALGORITMOS E PROGRAMAÇÃO
ESTRUTURADA

BACKES, A. Linguagem C: completa e descomplicada. 2. ed. Rio de Janeiro: LTC, 2023. cap. 4, p.
67-87.

DAMAS, L. Linguagem C. 10. ed. Rio de Janeiro: LTC, 2023. cap. 3, p. 51-79.

PIVA JUNIOR, D. Algoritmos e programação de computadores. 2. ed. Rio de Janeiro: Elsevier,


2019.

Aula 2
Estruturas de Repetição

Estruturas de repetição

Este conteúdo é um vídeo!


Para assistir este conteúdo é necessário que você acesse o AVA pelo
computador ou pelo aplicativo. Você pode baixar os vídeos direto no aplicativo
para assistir mesmo sem conexão à internet.
Dica para você
Aproveite o acesso para baixar os slides do vídeo, isso pode deixar sua
aprendizagem ainda mais completa.

Estudante, esta videoaula foi preparada especialmente para você. Nela, você irá aprender
conteúdos importantes para a sua formação profissional. Vamos assisti-la?

Ponto de Partida
Olá! Até aqui você já estudou as estruturas de decisão condicional e seleção, e como podemos
aplicá-las em alguns contextos. Agora vamos avançar para as estruturas de repetição, mais
precisamente, a instrução while!

Muito bem, agora você precisa desenvolver mais um programa em linguagem C para ajudar a
instituição de ensino para a qual você trabalha. Foi solicitado o desenvolvimento de um programa
que colete as notas de um semestre de uma disciplina específica, no qual o professor deve ter a
capacidade de inserir quantas avaliações achar necessário para calcular a nota final do aluno e,
Disciplina

ALGORITMOS E PROGRAMAÇÃO
ESTRUTURADA

por fim, exibir a média final. Apresente o código sem erros em um documento de texto. Neste
caso particular, qual é a melhor abordagem: usar um teste de repetição no início ou no final?
Realize o teste e otimize ao máximo as possíveis soluções para o problema. Boa sorte e tenha
uma ótima sessão de programação!

Vamos Começar!

Estrutura de repetição com teste no início: while


Sabemos que podemos utilizar a declaração "if" para tomar decisões e criar desvios dentro de
um programa com base em uma condição verdadeira ou falsa. Seguindo essa abordagem,
vamos começar nossos estudos sobre laços de repetição com o comando while. Atenção que
temos dois tipos de laços com while:

Laço com teste no início (while).


Laços com teste no final (do...while).

Nesta aula, vamos iniciar os estudos do comando while com teste no início!

Quando falamos de laços de repetição, é importante ter em mente que algo será repetidamente
executado enquanto uma condição verdadeira for atendida e que essa repetição será
interrompida somente quando a condição não for mais satisfeita. Uma estrutura de repetição
com teste no início não iniciará nenhuma repetição (e os comandos programadas dentro dela)
sem primeiro verificar uma condição. Ao realizar essa verificação, utilizaremos o comando
iterativo "while", que em português significa "enquanto". Na Tabela 1, é possível observar uma
representação simplificada do fluxograma do comando "while" direcionado para o teste no início
juntamente com a sintaxe na linguagem C.

Fluxograma Linguagem C
Disciplina

ALGORITMOS E PROGRAMAÇÃO
ESTRUTURADA

while (condição)
{
// comando 1
// comando 2
...
}

Tabela 1 | Instrução While com teste no início.

Em certas situações, ao empregar um teste no início, pode ocorrer o que é conhecido como um
loop infinito, que é quando um processo é executado repetidamente sem fim. Para prevenir esse
cenário, os laços precisam de uma condição de parada, empregada para determinar o momento
de encerrar o ciclo. Para isso, geralmente utilizamos os seguintes recursos:

Contador: é utilizado uma variável específica para controlar as repetições quando são
especificadas.
Incremento e decremento: são empregados para alterar o número do contador,
aumentando ou diminuindo o valor.
Acumulador: realiza a soma das entradas de dados a cada iteração do ciclo, gerando um
total acumulado a ser utilizado ao final do ciclo.

Agora vamos analisar uma aplicação prática de uma estrutura de repetição while, no qual o
algoritmo irá calcular a tabuada de um número. Veja o Quadro 1.

1: #include <stdio.h>
2: int main(){
3: int multiplicador = 0, resultado, num;
4: printf(“Tabuada de qual numero: ”);
5: scanf(“%d”,&num);
6: while(multiplicador <= 10)
7: {
8: resultado = num * multiplicador;
Disciplina

ALGORITMOS E PROGRAMAÇÃO
ESTRUTURADA

9: printf(“%d”, resultado);
10: multiplicador = multiplicador + 1;
11: }
12: return 0;
}

Quadro 1 | Exemplo de código com while.

Neste exemplo, a variável “multiplicador” além se ser o multiplicador do número informado para
gerar a tabuada, funciona como um contador do laço. Ela é incrementada a cada iteração, e
quando chega a 11 (condição de parada é o multiplicador ser maior que 10), a condição do while
é falsa e o laço é encerrado.

Estrutura de repetição com teste no fim: do...while


Agora, vamos explorar as repetições com teste no final (do-while). O loop do-while avalia a
condição ao final do ciclo, o que significa que os comandos são executados antes de verificar a
condição, ou seja, o bloco de comandos do laço sempre é executado ao menos uma vez, uma
vez que o teste se encontra apenas no final.

Fluxograma Linguagem C

do {

// comando 1
// comando 2
...

} while (condição);

Tabela 2 | Instrução DO...WHILE.


Disciplina

ALGORITMOS E PROGRAMAÇÃO
ESTRUTURADA

Neste tipo de laço em particular, o usuário tem a opção de inserir uma nova informação
novamente, e esta ser utilizada para controlar a continuação ou a saída do laço. Vejamos o
exemplo do Quadro 2, no qual o programa calcula a metragem quadrada de um terreno, usando o
teste no final para criar a opção de digitar novos valores sem fechar e abrir novamente o
programa.

1: #include <stdio.h>
2: int main(){
3: float metragem1=0, metragem2=0,
4: resultado=0;
5: int resp;
6: do {
7: printf("Calculo de metros
8: quadrados\n\n");
9: printf("Digite a 1a metragem do
10: terreno:");
11: scanf("%f", &metragem1);
12: printf("\nDigite a 2a metragem do
13: terreno:");
14: scanf("%f",&metragem2);
15: resultado = (metragem1 *
16: metragem2);
17: printf("\n\nTerreno tem = %.2f
m2 \n",resultado);
printf("Digite 1 para continuar ou
2 para sair\n");
scanf("%d", &resp);
}while (resp == 1); // condição de saída
return 0;
}

Quadro 2 | Exemplo de código estrutura condicional composta.

Siga em Frente...

Aplicações com estruturas de repetição


Agora vamos complementar nossos estudos sobre laços com alguns exemplos de aplicações.

Primeiro, iremos criar um programa que simula uma interface de conta bancária (uma tela com
opções de transações). No exemplo, um programa é desenvolvido para repetir a entrada de
Disciplina

ALGORITMOS E PROGRAMAÇÃO
ESTRUTURADA

dados até que uma condição de término específica seja alcançada, acumulando os valores
inseridos. O código está presente no Quadro 3:

1: #include <stdlib.h>
2: int main() {
3: float soma = 0, valor;
4: int opcao;
5:
6: do {
7: printf("\n Digite uma Operação");
8: printf("\n 1. Deposito");
9: printf("\n 2. Saque");
10: printf("\n 3. Saldo");
11: printf("\n 4. Sair");
12: printf("\n Qual opcao? ");
13: scanf("%d", &opcao);
14:
15: switch(opcao) {
16: case 1:
17: printf("\n Valor do depósito? ");
18: scanf("%f", &valor);
19: soma = soma + valor;
20: break;
21: case 2:
22: printf("\n Valor do saque? ");
23: scanf("%f", &valor);
24: soma = soma - valor;
25: break;
26: case 3:
27: printf("\n Saldo atual = R$ %.2f \n",
28: soma);
29: break;
30: default:
31: if(opcao != 4) {
32: printf("\n Opção Inválida! \n");
33: }
34: }
35: } while(opcao != 4);
36:
37: printf("Fim das operações. \n\n");
38: return 0;
}

Quadro 3 | Exemplo de código estrutura condicional composta.


Disciplina

ALGORITMOS E PROGRAMAÇÃO
ESTRUTURADA

Note que o laço do-while foi empregado para construir o menu do programa, em que a função
desejada é executada pelo menos uma vez dentro do loop.

Um outro exemplo interessante consiste no problema que envolve a aplicação da conjectura de


Collatz: dado um número natural "n", se "n" for par, ele é dividido por 2; se "n" for ímpar, é
multiplicado por 3 e somado 1 ao resultado. Este processo é repetido indefinidamente. A
conjectura de Collatz coloca que, seguindo essas duas regras simples, todos os números
naturais eventualmente chegarão a 1 (e a sequência 1, 4, 2, 1, 4, 2, 1, 4, 2, 1... se repetirá
indefinidamente). Matematicamente, as regras são as seguintes:

se n é par: n = n / 2
se n é ímpar: n = 3n + 1

Vamos agora criar um programa que calcula todos os números na sequência de Collatz para um
dado número de entrada. A sequência de comandos é a seguinte:

Digitar um número inteiro positivo maior que 1.


Se o número for par, dividi-lo por 2.
Se o número for ímpar, multiplicá-lo por 3 e somar 1.
Conforme a conjectura de Collatz, a sequência sempre termina em 1, como já explicado
anteriormente.
Solicitar o número para o qual a sequência de Collatz será calculada.

Agora, vamos observar a implementação disso na linguagem C presente no Quadro 4.

1: #include <stdlib.h>
2: int main() {
3: int num, i;
4: printf("\n\nDigite
5: um numero:\n");
6: scanf("%d", &num);
7: i = 0;
8: while (num > 1) {
9: if (num % 2 == 0)
10: num /= 2;
11: else
12: num = 3 * num
13: + 1;
14: printf("\n%d\n",
15: num);
16: i++;
}
return 0;
Disciplina

ALGORITMOS E PROGRAMAÇÃO
ESTRUTURADA

Quadro 4 | Exemplo de código estrutura condicional composta.

Alguns valores de variáveis podem ser modificados com base em seus valores anteriores. Para
simplificar esse processo, você pode utilizar o que é conhecido como atribuição composta,
indicando qual operação deve ser realizada. Nesse caso, o operador é colocado à esquerda do
sinal de atribuição. Por exemplo, y *= x + 1 tem o mesmo efeito que y = y * (x + 1), o que evita
colocar a variável do lado direito da atribuição. A atribuição composta foi utilizada no algoritmo
do Quadro 4, linha 9, simplificando num = num / 2 por num /= 2 (Atenção na atribuição composta,
pois não pode haver espaço entre o operador e o sinal de =).

Vamos Exercitar?
Prezado estudante, agora é o momento de abordar a resolução do problema requisitado pela
instituição de ensino, para o qual você precisa criar um programa em linguagem C que possa
calcular a média de um aluno com base nas avaliações realizadas. Uma das possíveis soluções
sugeridas para resolver este problema inclui os seguintes passos:

Criar uma variável para inserção das notas.


Estabelecer uma condição para a inserção das notas até que um comando de saída seja
executado.
Após a inserção das notas, inserir uma letra para finalizar o processo e calcular a média do
aluno.

A resolução está presente no Quadro 5.

1: #include <stdlib.h>
2: #include <string.h>
3: int main() {
4: int avalia, cont = 0, soma = 0;
5: char letra;
6: float media;
7: do {
8: printf("Digite uma nota para avaliação:
9: \n");
10: scanf("%d", &avalia);
11: fflush(stdin); // limpa o buffer de entrada
12: cont++;
13: soma = soma + avalia;
14:
15:
Disciplina

ALGORITMOS E PROGRAMAÇÃO
ESTRUTURADA

16: printf("Digite qualquer letra para continuar


17: ou 's' para encerrar: \n");
18: } while ((letra = getchar()) != 's');
19:
20: printf("\n \nQuantidade de avaliação = %d e
21: soma das notas = %d. \n", cont, soma);
22: media = soma / cont;
23: system("PAUSE");
return 0;
}

Quadro 5 | Exemplo de solução.

Lembrando que não há uma única resposta correta. Há vários caminhos para se chegar no
mesmo resultado! Inclusive, como ficaria este programa caso o professor prefira indicar pesos
diferentes para cada nota antes de calcular a média? Fica como desafio para você!

Saiba mais

Para entender melhor o conceito de estruturas de repetição na linguagem C, sugerimos a leitura


do Capítulo 4 - Laços, do livro Linguagem C, disponível na Biblioteca Virtual.

DAMAS, L. Linguagem C. 10. ed. Rio de Janeiro: LTC, 2023. cap. 4, p. 80-103.

Também sugerimos a leitura do Capítulo 5 - Comando de repetição, do livro Linguagem C:


Completa e Descomplicada, disponível na Biblioteca Virtual, para complementar os estudos
sobre while e do-while.

BACKES, A. Linguagem C: completa e descomplicada. 2. ed. Rio de Janeiro: LTC, 2023. cap. 5, p.
88-108.

Para auxiliar no desenvolvimento de programas na linguagem C, uma ótima prática é verificar a


documentação da linguagem para entender em detalhes os principais tipos de funções e
elementos utilizados. Para isso, sugerimos a consulta da seguinte documentação sempre que
achar necessário. Nela você encontra todas as bibliotecas utilizadas na linguagem e como
utilizar suas principais funções: Referência da Linguagem C.

Referências
BACKES, A. Linguagem C: completa e descomplicada. 2. ed. Rio de Janeiro: LTC, 2023. cap. 4, p.
67-87.
Disciplina

ALGORITMOS E PROGRAMAÇÃO
ESTRUTURADA

DAMAS, L. Linguagem C. 10. ed. Rio de Janeiro: LTC, 2023. cap. 3, p. 51-79.

PIVA JUNIOR, D. Algoritmos e programação de computadores. 2. ed. Rio de Janeiro: Elsevier,


2019.

Aula 3
Estruturas Determinísticas

Estruturas determinísticas

Este conteúdo é um vídeo!


Para assistir este conteúdo é necessário que você acesse o AVA pelo
computador ou pelo aplicativo. Você pode baixar os vídeos direto no aplicativo
para assistir mesmo sem conexão à internet.
Dica para você
Aproveite o acesso para baixar os slides do vídeo, isso pode deixar sua
aprendizagem ainda mais completa.

Estudante, esta videoaula foi preparada especialmente para você. Nela, você irá aprender
conteúdos importantes para a sua formação profissional. Vamos assisti-la?

Ponto de Partida

Olá! Até aqui você já estudou as estruturas de repetição while e do-while! Vamos continuar neste
mesmo tema, porém, você será apresentado à estrutura de repetição for.

Você é desenvolvedor de software em uma instituição de ensino e foi designado para criar um
programa que possa ajudar os alunos a visualizar conceitos matemáticos de forma interativa. A
instituição está empenhada em aprimorar o ensino de geometria e quer fornecer aos alunos uma
ferramenta prática para entender a construção de formas geométricas simples, como triângulos,
no contexto do aprendizado de programação. O objetivo é criar um programa em C que permita
aos alunos inserir o número de linhas desejado e exibir um triângulo na tela do computador,
fornecendo uma representação visual imediata dos conceitos discutidos em sala de aula. Isso
Disciplina

ALGORITMOS E PROGRAMAÇÃO
ESTRUTURADA

não apenas tornará o processo de aprendizagem mais envolvente e prático, mas também ajudará
os alunos a compreender melhor os fundamentos da geometria por meio da programação.

O triângulo deve ser desenhado na tela da seguinte forma:

Nº de linhas = 4

Como você utilizará as estruturas condicionais e de laço de repetição para solucionar este
desafio? Vamos ao estudo desta aula que com certeza tudo ficará mais claro!
Disciplina

ALGORITMOS E PROGRAMAÇÃO
ESTRUTURADA

Vamos Começar!

Estrutura de repetição determinística: laço For


Nesta aula vamos explorar a aplicação da estrutura de repetição "for" (para) em programação,
compreendendo seus históricos e usos determinísticos, além de compará-la com estruturas de
repetição while e do-while.

Iniciaremos abordando a repetição com variáveis de controle e como implementar o laço "for".
Este comando, que em português significa "para", é comumente utilizado para iterar uma
instrução por um número pré-definido de vezes, ou seja, é possível determinar a quantidade de
repetições (E por isso que é chamada de determinística!). A Tabela 1 ilustra a representação da
estrutura de repetição utilizando o comando "for" juntamente com sua sintaxe na linguagem C.

Fluxograma

Linguagem C

For (inicialização; condição; incremento)


{
// comandos
}

Tabela 1 | Instrução for.


Disciplina

ALGORITMOS E PROGRAMAÇÃO
ESTRUTURADA

Ao analisar a sintaxe comando "for", você pode observar três expressões distintas separadas por
ponto e vírgula. A seguir estão os significados de cada uma delas:

Inicialização: instrução de atribuição cuja inicialização é realizada apenas uma vez, antes
do início do loop.
Condição: condição final. Realiza um teste que determina se a condição é verdadeira ou
falsa. Se a condição for verdadeira, o loop continua; se for falsa, o loop é encerrado.
Incremento: essa parte permite incrementar uma repetição com base em um contador
específico (varável de controle inicializada no início do laço). Lembrando que o incremento
é executado após os comandos.

Agora vamos analisar um exemplo simples da estrutura de repetição for, no qual o algoritmo irá
calcular a tabuada de um número. Veja o Quadro 1.

1: #include <stdio.h>
2: int main(){
3: int multiplicador, resultado, num;
4: printf(“Tabuada de qual numero: ”);
5: scanf(“%d”, &num);
6: for(multiplicador=10; multiplicador<10;
7: multiplicador++)
8: {
9: resultado = num * multiplicador;
10: printf(“%d”, resultado);
11: }
12: return 0;
}

Quadro 1 | Exemplo de código com for.

Neste exemplo, a inicialização é realizada com o comando multiplicador=10. Em seguida, a


condição final (multiplicador<10) é testada. Se for verdadeira, entramos no laço, realizamos os
comandos, e o incremento (multiplicador++) é executado. Em seguida, a condição final é
novamente testada, e o fluxo se repete até que ela seja verdadeira. A lógica do laço for muito se
assemelha com um while com teste no início. E claro que podemos implementar o mesmo
trecho de código com while e uma variável de controle. A diferença é que aqui controlamos o
número de repetições de forma explícita, dentro da própria instrução for. Facilita a visualização e
o controle.

Siga em Frente...
Disciplina

ALGORITMOS E PROGRAMAÇÃO
ESTRUTURADA

Laço for aninhado


A utilização do laço for é muito popular e ampla. E uma das formas mais comuns e importantes
de utilizá-lo é por meio de laços aninhados. Para entendermos melhor, considere a seguinte
situação em que queremos calcular e imprimir a tabuada de 1 até 5, uma por linha, da seguinte
maneira:

1 2 3 4 5 6 7 8 9 10

2 4 6 8 10 12 14 16 18 20

3 6 9 12 15 18 21 24 27 30

4 8 12 16 20 24 28 32 36 40

5 10 15 20 25 30 35 40 45 50

Já sabemos que pelo código do Quadro 1 podemos calcular qualquer uma destas linhas. Então a
solução seria repetir todo o bloco do for por cinco vezes, mudando o valor da variável num antes
de cada for? Poderia ser! Mas e se quiséssemos imprimir a tabuada de 1 a 10 agora?
Precisaríamos repetir o for por mais cinco vezes (e sempre alterando estaticamente a variável
num). Acredito que tenha dado para perceber que estamos repetindo código, e repetir código não
é uma boa prática. Então vejamos: se estamos repetindo o laço for por cinco vezes, isto já
caracteriza um laço determinístico com duração de cinco iterações, justamente a definição do
laço for conforme estudamos! Então podemos colocar o laço for que calcula e imprime a
tabuada dentro de outro laço que controla o número de vezes que a tabuada será calculada e
impressa. Analise o Quadro 2 com o código completo.

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

Quadro 2 | Cálculo da tabuada de 1 a 5 com for.


Disciplina

ALGORITMOS E PROGRAMAÇÃO
ESTRUTURADA

Veja que o for externo na linha 4 controla a variável “num”, que ao invés de ser definida pelo
usuário, será incrementada dinamicamente de 1 até 5. E a cada iteração deste for externo, o for
interno (linha 5) calcula a tabuada com base no valor de “num”. Perceba que ao término do for
interno, realizamos um printf para pular a linha com “\n”, ainda dentro do for externo. Isso ocorre
para que na próxima iteração, a próxima tabuada seja impressa na linha de baixo.

Utilizar laços for aninhado possui várias aplicações, principalmente na manipulação de matrizes,
que será o objeto de estudo mais à frente! Portanto, é importante que compreenda este conceito
com plenitude para que possa avançar com mais facilidade.

Exemplos de utilização de laços for


Agora vamos expandir nossos estudos sobre laços for com alguns exemplos de aplicações.

Primeiro, vamos verificar que podemos realizar testes em mais de uma variável dentro do mesmo
laço for, bem como a utilização de decremento ao invés de um incremento a cada iteração. Para
isso, considere um programa que mostra uma sequência de números, em que x vai de 10 a 0 e y
vai de 0 a 10. O código está presente no Quadro 3:

1: #include <stdlib.h>
2: int main() {
3: for(int x = 10, y = 0; x >= 0, y <= 10; x--, y++){
4: printf("x = %d, y = %d\n", x,y);
5: }
6: return 0;
7: }

Quadro 3 | Exemplo de código.

Agora vamos discutir o código. Primeiramente, veja que as variáveis x e y foram declaradas
dentro da inicialização do for. Esta é uma prática muito comum que agiliza a codificação. Porém,
fique atento ao detalhe de que estas variáveis só existem enquanto este for estiver em execução.
Quando ele se encerra, estas variáveis são excluídas (desalocadas) pelo compilador. Na
expressão de inicialização, x e y são inicializados com 10 e 0, respectivamente, e as instruções
são separadas por vírgula. Na expressão de condição, temos condições diferentes para as duas
variáveis, também separadas por vírgula. Isso quer dizer que o conteúdo do laço só será
executado enquanto as duas condições forem verdadeiras ao mesmo tempo. Se uma for falsa, o
laço se encerra. E por fim, no incremento, temos o x sendo subtraído de 1, e y sendo adicionado
de 1. Na expressão de incremento podemos realizar qualquer tipo de operação aritmética
envolvendo as variáveis de controle, não somente adição ou subtração.

Um outro exemplo interessante consiste no cálculo do fatorial de um número. Lembre-se que o


fatorial de um número n consiste na multiplicação sucessiva n*(n-1)*(n-2)*...*1, por exemplo, 5! =
Disciplina

ALGORITMOS E PROGRAMAÇÃO
ESTRUTURADA

5*4*3*2*1 = 120. Veja o código do Quadro 4.

1: #include <stdlib.h>
2: int main() {
3: int n;
4: unsigned long long fatorial = 1; // Usamos
5: "unsigned long long" para armazenar números
6: grandes
7: printf("Digite um número inteiro positivo: ");
8: scanf("%d", &n);
9: // Verificação para números negativos
10: if (n < 0) {
11: printf("O fatorial não está definido para
12: números negativos.\n");
13: } else {
14: for (int i = 1; i <= n; i++) {
15: fatorial *= i;
16: }
17: printf("O fatorial de %d é %llu\n", n,
18: fatorial);
19: }
return 0;
}

Quadro 4 | Exemplo de código estrutura condicional composta.

Neste programa, o usuário insere um número inteiro positivo "n", que utiliza um laço "for" para
calcular o fatorial de "n". O resultado é armazenado na variável "fatorial," que é inicializada como
1 para tratar o caso de 0! = 1. Por exemplo, se o usuário insere 0 (zero), o loop “for”não é
executado, e a variável “fatorial” permanece valendo 1. Caso “n” seja maior ou igual a 1, o laço
percorre todos os números de 1 a "n" e multiplica-os para calcular o fatorial. O resultado é
impresso no final.

Vamos Exercitar?
Prezado estudante, agora é o momento de abordar a resolução do problema requisitado pela
instituição de ensino, para o qual você precisa criar um programa em C que permita aos alunos
inserir o número de linhas desejado e exibir um triângulo na tela do computador.

A resolução está presente no Quadro 5.

1: # include <stdio.h>
Disciplina

ALGORITMOS E PROGRAMAÇÃO
ESTRUTURADA

2:
3: int main() {
4: int linhas, espacos, asteriscos;
5: printf("Digite o número de linhas do
6: triângulo: ");
7: scanf("%d", &linhas);
8:
9: for (int i = 1; i <= linhas; i++) {
10: for (espacos = 1; espacos <= linhas - i;
11: espacos++) {
12: printf(" ");
13: }
14: for (asteriscos = 1; asteriscos <= 2 * i - 1;
15: asteriscos++) {
16: printf("*");
17: }
18: printf("\n");
19: }
20:
return 0;
}

Quadro 5 | Exemplo de solução.

Este programa solicita ao usuário o número de linhas desejado para o triângulo e, em seguida,
usa dois loops for para imprimir o triângulo na tela. O primeiro for interno gerencia a quantidade
de espaços em branco que devem ser impressos, ao passo que o segundo imprime os
asteriscos.

Saiba mais

Para entender melhor o conceito de estruturas de repetição na linguagem C, sugerimos a leitura


do Capítulo 4 - Laços, do livro Linguagem C, disponível na Biblioteca Virtual.

DAMAS, L. Linguagem C. 10. ed. Rio de Janeiro: LTC, 2023. cap. 4, p. 80-103.

Também sugerimos a leitura do Capítulo 5 - Comandos de repetição, do livro Linguagem C:


Completa e Descomplicada, disponível na Biblioteca Virtual, para complementar os estudos
sobre while e do-while.

BACKES, A. Linguagem C: completa e descomplicada. 2. ed. Rio de Janeiro: LTC, 2023. cap. 5, p.
88-108.
Disciplina

ALGORITMOS E PROGRAMAÇÃO
ESTRUTURADA

Para auxiliar no desenvolvimento de programas na linguagem C, uma ótima prática é verificar a


documentação da linguagem para entender em detalhes os principais tipos de funções e
elementos utilizados. Para isso, sugerimos a consulta da seguinte documentação sempre que
achar necessário. Nela você encontra todas as bibliotecas utilizadas na linguagem e como
utilizar suas principais funções: Referência da Linguagem C.

Referências

BACKES, A. Linguagem C: completa e descomplicada. 2. ed. Rio de Janeiro: LTC, 2023. cap. 4, p.
67-87.

DAMAS, L. Linguagem C. 10. ed. Rio de Janeiro: LTC, 2023. cap. 3, p.51-79.

PIVA JUNIOR, D. Algoritmos e programação de computadores. 2. ed. Rio de Janeiro: Elsevier,


2019.

Aula 4
Controle de Repetição

Controle de repetição

Este conteúdo é um vídeo!


Para assistir este conteúdo é necessário que você acesse o AVA pelo
computador ou pelo aplicativo. Você pode baixar os vídeos direto no aplicativo
para assistir mesmo sem conexão à internet.
Dica para você
Aproveite o acesso para baixar os slides do vídeo, isso pode deixar sua
aprendizagem ainda mais completa.

Estudante, esta videoaula foi preparada especialmente para você. Nela, você irá aprender
conteúdos importantes para a sua formação profissional. Vamos assisti-la?

Ponto de Partida
Disciplina

ALGORITMOS E PROGRAMAÇÃO
ESTRUTURADA

Olá! Nesta aula vamos explorar o uso das declarações break e continue, além do comando goto
para nos auxiliar a controlar as estruturas de repetições em diferentes situações.

Você trabalha em uma instituição educacional e recebeu uma tarefa relacionada à administração
de disciplinas e controle de alunos matriculados. Você precisa criar um sistema que gerencia o
número de alunos matriculados em cada disciplina da instituição. Nesse cenário, o programa
deve permitir que o administrador insira o número de disciplinas disponíveis e, em seguida, para
cada disciplina, o número de alunos matriculados. O programa deve estar preparado para
controlar a entrada de dados e interromper a contagem de disciplinas se o número total de
alunos matriculados atingir um certo limite.

Agora surge a questão: como fazer este controle de interrupção de uma forma simples e eficaz?
Caro estudante, vamos em frente nos estudos desta aula que com toda certeza você conseguirá
superar o desafio!

Vamos Começar!

Forçar interrupção de repetição: break


Em C, a declaração break é utilizada para encerrar o fluxo de execução de um laço ou de um
switch. Ela pode ser utilizada somente dentro de uma construção de controle, como for, while,
do-while e switch. O break é frequentemente utilizado em situações em que o programador
deseja interromper imediatamente a execução de um loop ou de um bloco switch, e assim sair
do contexto atual de execução.

Vamos analisar as características do break nos diferentes contextos que pode ser aplicado:

Loop: dentro de um loop, quando o break é encontrado, a execução do loop é


imediatamente interrompida, e o controle é passado para a instrução que segue o loop.
Switch: no contexto de um bloco switch-case, o break é utilizado para sair do bloco switch
quando um case (caso) correspondente é encontrado e executado. Se o break não for
usado em um bloco switch, a execução continuará nos cases seguintes até que um break
seja encontrado ou até o fim do bloco switch ser alcançado.

Para compreender melhor o uso do break, veja o exemplo no Quadro 1. Neste programa, um
número secreto é predefinido como 7. O programa solicita que o usuário insira um número e
verifique se este é igual ao número secreto. Se o número inserido for igual ao número secreto, o
programa imprime uma mensagem de parabéns e usa break para sair do loop while. Caso
contrário, o programa continua pedindo ao usuário que insira um novo número até que o número
correto seja adivinhado. O uso de break garante que o loop seja interrompido assim que o
número correto for inserido.
Disciplina

ALGORITMOS E PROGRAMAÇÃO
ESTRUTURADA

1: #include <stdio.h>
2: int main(){
3: int numero_secreto = 7;
4: int tentativa;
5: printf("Adivinhe o número secreto!\n");
6: while (1) { // Causa um loop infinito
7: printf("Insira um número: ");
8: scanf("%d", &tentativa);
9: if (tentativa == numero_secreto) {
10: printf("Parabéns! Você adivinhou o
11: número secreto.\n");
12: break; // Sai do loop quando o
13: número correto é adivinhado
14: } else {
15: printf("Tente novamente!\n");
16: }
17: }
18: return 0;
}

Quadro 1 | Exemplo de código com break.

Reiniciar repetição: continue


O comando continue é uma estrutura de controle na linguagem de programação C que é usado
para pular a execução das instruções restantes em um loop, e então continuar com a próxima
iteração desse loop. Diferente do break, que encerra completamente o loop, o continue permite
ao programador pular apenas o restante do bloco de código da iteração atual dentro do loop e
avançar para a próxima iteração, ignorando as instruções restantes dentro do bloco. Mas o loop
não é encerrado!

Veja agora as características e a definição do comando continue na linguagem C, e tente traçar


um paralelo de comparação com o comando break estudo anteriormente:

Pular iteração: o continue é usado para pular a iteração atual do loop, ou seja, ele faz com
que o programa ignore o restante das instruções no bloco do loop atual e avance para a
próxima iteração do loop.
Útil para filtragem: o continue é frequentemente utilizado para implementar condições de
filtragem em um loop, permitindo que certas iterações sejam ignoradas com base em uma
condição específica.

Vamos agora a um exemplo usando continue. O programa do Quadro 2 percorre os números de 1


a 20 e a cada iteração testa se o número corrente é par, e caso o seja, o programa interrompe a
Disciplina

ALGORITMOS E PROGRAMAÇÃO
ESTRUTURADA

iteração e não imprime o número (pois irá pular o printf em seguida). Ao final, o programa exibe
apenas os números ímpares de 1 a 20.

1: #include <stdio.h>
2: int main(){
3: for (int i = 1; i <= 20; i++) {
4: if (i % 2 == 0) {
5: continue; // Pula iterações
6: com números pares
7: }
8: printf("%d ", i);
9: }
10: return 0;
}

Quadro 2 | Exemplo de código com continue.

Siga em Frente...

Fluxo de execução arbitrário: goto


O comando goto é uma instrução na linguagem C que permite realizar desvios não estruturados
em um programa. Em outras palavras, o goto permite que você pule de um local específico em
um programa para outro local marcado por um rótulo. Embora o uso de goto seja desencorajado
na maioria das situações, em algumas circunstâncias específicas, e em problemas simples pode
ser útil para simplificar a lógica de um programa. No entanto, seu uso indiscriminado pode tornar
o código mais difícil de entender e dar origem a problemas de legibilidade e manutenção.

A seguir, podemos observar a sintaxe do comando goto na linguagem C. Veja que o comando
goto é seguido por um rótulo (identificador) seguido por dois pontos (:). O rótulo é uma marca
que você coloca em algum lugar no seu código onde deseja que o goto salte. Por exemplo:

goto meu_rotulo;
// ...
meu_rotulo: // O rótulo

Antes de irmos aos exemplos, é importante que você se atente a estas características do
comando goto:
Disciplina

ALGORITMOS E PROGRAMAÇÃO
ESTRUTURADA

Desvios não estruturados: o goto permite que você faça desvios não estruturados, o que
significa que ele pode pular para qualquer lugar no programa no qual um rótulo seja
definido.
Riscos de uso indevido: o goto pode tornar o código complexo e difícil de entender. Uso
inadequado de goto pode levar a problemas como loops infinitos, pontos de saída
inesperados e tornar o código propenso a erros.
Escopo local: o goto é limitado ao mesmo bloco de código e não pode ser usado para
desviar o controle para fora de uma função.
Alternativas mais estruturadas: em muitos casos, é possível substituir o goto por estruturas
de controle mais estruturadas, como if, else, while, for e funções. Isso torna o código mais
legível e mais fácil de depurar e manter.

Veja agora o exemplo do Quadro 3, em que o goto é usado para direcionar o fluxo de execução
para o rótulo 'erro' se o número inserido não for positivo. O programa imprime uma mensagem de
erro e termina. Este é um exemplo de uso cuidadoso de goto para manipular situações
específicas, porém, é possível perceber que um simples if-else resolveria o problema, e ficaria
muito mais simples de entender a lógica!

1: #include <stdio.h>
2: int main(){
3: int numero;
4: printf("Insira um número positivo: ");
5: scanf("%d", &numero);
6: if (numero <= 0) {
7: goto erro; // Vai para o rótulo
8: 'erro' se o número não for
9: positivo
10: }
11:
12: printf("Número válido: %d\n", numero);
13: return 0;
14:
15: erro: // Rótulo para manipular erro
16: printf("Erro: Número inválido.\n");
17: return 0;
}

Quadro 3 | Exemplo de código com goto.

Vamos Exercitar?
Disciplina

ALGORITMOS E PROGRAMAÇÃO
ESTRUTURADA

Prezado estudante, agora é o momento de abordar a resolução do problema requisitado pela


instituição de ensino, para o qual você precisa criar um programa em linguagem C que possa
administrar as disciplinas e o número de alunos matriculados.

O programa deve permitir que o administrador insira o número de disciplinas e o número de


alunos matriculados em cada uma delas. Em seguida, o programa precisa verificar se o número
de alunos é válido e se o limite total de alunos é atingido. Se o limite for atingido, o programa
interrompe a contagem de disciplinas usando break. O uso de continue permite pular para a
próxima iteração do loop se um número de alunos inválido for inserido. O programa então exibe o
total de disciplinas contadas e o total de alunos matriculados.

A resolução está presente no Quadro 4.

1: #include <stdlib.h>
2: #include <string.h>
3: int main() {
4: int total_disciplinas, limite_alunos = 100,
5: total_alunos = 0;
6:
7: printf("Sistema de contagem de alunos
8: matriculados!\n");
9: printf("Insira o número de disciplinas
10: disponíveis: ");
11: scanf("%d", &total_disciplinas);
12:
13: for (int i = 1; i <= total_disciplinas; i++) {
14: int alunos_matriculados;
15: printf("Insira o número de alunos
16: matriculados na disciplina %d: ", i);
17: scanf("%d", &alunos_matriculados);
18: // Verifica se o número de alunos
19: matriculados é válido
20: if (alunos_matriculados < 0) {
21: printf("Número de alunos inválido. Tente
22: novamente.\n");
23: i--; // Volta para a mesma disciplina
24: continue; // Pula para a próxima
25: iteração do loop
26: }
27:
28: total_alunos += alunos_matriculados;
29:
30: // Verifica se o limite de alunos foi
31: atingido
Disciplina

ALGORITMOS E PROGRAMAÇÃO
ESTRUTURADA

32: if (total_alunos >= limite_alunos) {


33: printf("Limite de alunos atingido.
34: Encerrando contagem de disciplinas.\n");
break; // Encerra do loop de contagem
de disciplinas
}
}
printf("Total de disciplinas contadas: %d\n",
total_disciplinas);
printf("Total de alunos matriculados: %d\n",
total_alunos);
return 0;
}

Quadro 4 | Exemplo de solução.

Reforçamos que não há uma única resposta correta, e o importante é chegarmos em uma
solução eficaz que utiliza os conceitos aprendidos até aqui! Não se esqueça que sempre há
espaço para otimizações de código, então vale a pena buscar alternativas de implementações e
se atualizar sempre! Bons estudos!

Saiba mais

Para entender melhor o conceito dos comandos break, continue e goto C, sugerimos a leitura do
Capítulo 4 - Laços, do livro Linguagem C, disponível na Biblioteca Virtual.

DAMAS, L. Linguagem C. 10. ed. Rio de Janeiro: LTC, 2023. cap. 4, p. 80-103.

Também sugerimos a leitura do Capítulo 5 - Comandos de repetição, do livro Linguagem C:


Completa e Descomplicada, disponível na Biblioteca Virtual, para complementar os estudos
sobre break, continue e goto.

BACKES, A. Linguagem C: completa e descomplicada. 2. ed. Rio de Janeiro: LTC, 2023. cap. 5, p.
88-108.

Para auxiliar no desenvolvimento de programas na linguagem C, uma ótima prática é verificar a


documentação da linguagem para entender em detalhes os principais tipos de funções e
elementos utilizados. Para isso, sugerimos a consulta da seguinte documentação sempre que
achar necessário. Nela você encontra todas as bibliotecas utilizadas na linguagem e como
utilizar suas principais funções: Referência da Linguagem C.
Disciplina

ALGORITMOS E PROGRAMAÇÃO
ESTRUTURADA

Referências
BACKES, A. Linguagem C: completa e descomplicada. 2. ed. Rio de Janeiro: LTC, 2023. cap. 4, p.
67-87.

DAMAS, L. Linguagem C. 10. ed. Rio de Janeiro: LTC, 2023. cap. 3, p. 51-79.

PIVA JUNIOR, D. Algoritmos e programação de computadores. 2. ed. Rio de Janeiro: Elsevier,


2019.

Aula 5
Estruturas de Controle e Repetição

Videoaula de Encerramento

Este conteúdo é um vídeo!


Para assistir este conteúdo é necessário que você acesse o AVA pelo
computador ou pelo aplicativo. Você pode baixar os vídeos direto no aplicativo
para assistir mesmo sem conexão à internet.
Dica para você
Aproveite o acesso para baixar os slides do vídeo, isso pode deixar sua
aprendizagem ainda mais completa.

Estudante, esta videoaula foi preparada especialmente para você. Nela, você irá aprender
conteúdos importantes para a sua formação profissional. Vamos assisti-la?

Ponto de Chegada
Olá, estudante! Para desenvolver a competência desta Unidade, que é “conhecer os elementos e
componentes que efetuam o processo de desenvolvimento de algoritmos e programação
estruturada”, você deve explorar conceitos fundamentais em programação, concentrando seus
estudos em estruturas condicionais e laços de repetição em linguagem C. Comece por
compreender a importância das estruturas condicionais, como o "if-else" e o "switch-case", para
direcionar o fluxo do programa com base em condições lógicas. Por meio destas estruturas,
Disciplina

ALGORITMOS E PROGRAMAÇÃO
ESTRUTURADA

você pode tomar decisões com base em diferentes cenários, facilitando o desenvolvimento de
lógicas mais complexas em nossos programas.

Além disso, é necessário estudar os laços de repetição para que possa executar blocos de
código repetidamente. Explore o "while" e o "do-while", compreendendo suas aplicações e
diferenças no contexto de execução do código. Em particular, o "while" é valioso quando
queremos repetir um bloco de código enquanto uma condição é verdadeira, enquanto o "do-
while" é ideal para garantir que o bloco de código seja executado pelo menos uma vez, mesmo se
a condição for inicialmente falsa.

Além disso, aprofunde sua compreensão do comando "for". Você deve explorar como esse tipo
de laço oferece uma estrutura mais concisa para repetições com um número fixo de iterações,
permitindo-nos definir uma condição inicial, uma condição de continuação e uma atualização em
um único local.

Por fim, algo importante consiste em aprender os comandos de controle de laços em C, incluindo
"break", "continue" e "goto". O "break" é usado para interromper um laço de repetição
prematuramente, enquanto o "continue" pula para a próxima iteração do laço. Além disso, o "goto"
é uma ferramenta interessante para desviar o fluxo do programa para uma determinada etiqueta,
embora seu uso deva ser feito com cautela devido à sua capacidade de complicar a legibilidade
do código.

Com a compreensão desses conceitos fundamentais, você estará “bem equipado” para
desenvolver programas mais complexos e eficientes, capazes de lidar com uma variedade de
problemas e cenários utilizando estruturas condicionais.

É Hora de Praticar!

Este conteúdo é um vídeo!


Para assistir este conteúdo é necessário que você acesse o AVA pelo
computador ou pelo aplicativo. Você pode baixar os vídeos direto no aplicativo
para assistir mesmo sem conexão à internet.

Você está trabalhando em um projeto de análise de crescimento populacional e precisa calcular


a sequência de Fibonacci para prever o número de indivíduos em uma população de coelhos ao
longo do tempo. A sequência de Fibonacci é amplamente utilizada em modelagem matemática
para representar o crescimento populacional e pode ser útil para prever a expansão de uma
população de animais, como os coelhos.
Disciplina

ALGORITMOS E PROGRAMAÇÃO
ESTRUTURADA

Você deve elaborar um programa em C que, a partir de uma entrada n, exiba os n primeiros
termos da sequência de Fibonacci.
Por exemplo:
N = 5 -> 0 1 1 2 3
N = 8 -> 0 1 1 2 3 5 8 13

Por que o comando "for" é considerado uma estrutura de laço determinístico e como isso
difere dos laços de repetição "while" e "do-while"?
Quais são os possíveis impactos reais do uso indevido dos comandos break/continue/goto
na legibilidade e manutenibilidade do código? Como você garantiria um uso apropriado
desses comandos em seus programas?

O código a seguir apresenta uma sugestão de resultado para o problema:


1: #include <stdio.h>
2: int main() {
3: int n;
4: int primeiro = 0, segundo = 1, proximo;
5: printf("Digite o número de termos da sequência de Fibonacci que você
6: deseja calcular: ");
7: scanf("%d", &n);
8: printf("Sequência de Fibonacci até o termo %d:\n", n);
9: for (int i = 0; i < n; i++) {
10: if (i <= 1) {
11: proximo = i;
12: } else {
13: proximo = primeiro + segundo;
14: primeiro = segundo;
15: segundo = proximo;
16: }
17: printf("%d ", proximo);
18: }
19: return 0;
20: }
Neste programa, calculamos e imprimimos os primeiros 'n' termos da sequência de Fibonacci.
Utilizamos um laço de repetição for para calcular cada termo com base nos dois termos
anteriores e imprimir os valores resultantes. O usuário pode inserir o número de termos
desejados, e o programa calculará a sequência correspondente.

O infográfico a seguir ilustra e identifica as estruturas condicionais e de repetição estudadas


nesta unidade.
Disciplina

ALGORITMOS E PROGRAMAÇÃO
ESTRUTURADA

BACKES, A. Linguagem C: completa e descomplicada. 2. ed. Rio de Janeiro: LTC, 2023.


CORMEN, T. H. Desmistificando algoritmos. 1. ed. Rio de Janeiro: Elsevier, 2014.
Disciplina

ALGORITMOS E PROGRAMAÇÃO
ESTRUTURADA

DAMAS, L. Linguagem C. 10. ed. Rio de Janeiro: LTC, 2023.


MENÉNDEZ, A. Simplificando algoritmos. 1. ed. Rio de Janeiro: LTC, 2023.
PIVA JUNIOR, D. Algoritmos e programação de computadores. 2. ed. Rio de Janeiro: Elsevier,
2019.
,

Unidade 3
Vetores, Matrizes, Structs e Ponteiros

Aula 1
Vetores

Vetores

Este conteúdo é um vídeo!


Para assistir este conteúdo é necessário que você acesse o AVA pelo
computador ou pelo aplicativo. Você pode baixar os vídeos direto no aplicativo
para assistir mesmo sem conexão à internet.
Dica para você
Aproveite o acesso para baixar os slides do vídeo, isso pode deixar sua
aprendizagem ainda mais completa.

Estudante, esta videoaula foi preparada especialmente para você. Nela, você irá aprender
conteúdos importantes para a sua formação profissional. Vamos assisti-la?

Ponto de Partida
Olá! Até aqui você já estudou os conceitos fundamentais de algoritmos e linguagem de
programação, como os tipos de dados, as variáveis, as constantes, os operadores e as
expressões, e as estruturas de controle. Agora vamos avançar um pouco mais em nossos
estudos e introduzir uma estrutura de dado muito importante e amplamente utilizada: o vetor!
Disciplina

ALGORITMOS E PROGRAMAÇÃO
ESTRUTURADA

A instituição de ensino que você trabalha está com um problema na digitação dos CPFs no
momento do cadastro dos alunos. A questão é que, quando o usuário digita o CPF com pontos e
traço, a indexação e a busca são dificultadas, ou seja, pode acontecer um erro de autenticidade.
Para resolver esse impasse, você deverá desenvolver um programa para padronizar o formato do
CPF, eliminando os pontos e traços digitados pelos usuários. E agora, como resolver essa
situação? Garanto que ao final desta aula você conseguirá encontrar a solução mais eficiente
para esta questão! Agora vamos lá, preste muita atenção e tenha um excelente estudo!

Vamos Começar!

Motivação e definição
Conforme estudado anteriormente, as variáveis têm a função de reter dados na memória de
execução e estes podem ser de diversos tipos (como números inteiros, decimais, caracteres ou
booleanos), conhecidos como tipos primitivos. Você já sabe que podemos armazenar
informações como a idade de uma pessoa em uma variável do tipo inteiro, a temperatura em
uma variável de ponto flutuante e assim por diante. No entanto, surge uma questão: Imagine que
você precisa criar um sistema capaz de lidar com múltiplas medições de temperatura de um
dispositivo, por exemplo. Seria viável criar quinze variáveis do tipo float para armazenar cada
uma delas?

Com o conhecimento atual, isso exigiria a criação de quinze variáveis individuais, o que não
apenas pode tornar o código mais extenso, mas também não é considerado uma prática de
programação eficiente. A solução mais adequada para armazenar diversos valores dentro de um
mesmo contexto é o uso de variáveis compostas, ou também chamadas de estruturas de dados
homogêneas. Esse método possibilita armazenar vários valores em uma única estrutura.

Ao alocar uma variável primitiva, como um número inteiro (int), é reservado um espaço de 4 bytes
na memória, ou seja, um bloco é reservado e seu endereço é utilizado para armazenar e
recuperar os dados. Ao alocar uma variável composta, como um conjunto de números inteiros,
um grupo de blocos de 4 bytes é reservado. O tamanho desse conjunto (se será 1, 2, 3, ... ou N
blocos) é especificado pelo programador.

Para compreender as variáveis compostas, podemos estabelecer uma comparação entre casas,
prédios e as próprias variáveis. Uma casa possui uma identificação única, composta por
elementos como rua, número, bairro, cidade, estado e CEP. Podemos equiparar uma casa a uma
variável primitiva, que armazena apenas um único valor em seu endereço específico. Por outro
lado, um prédio possui um endereço que compartilha os mesmos parâmetros que uma casa,
entretanto, nesse mesmo endereço estão instaladas múltiplas residências. Similarmente, as
variáveis compostas são capazes de armazenar diversos valores em um mesmo endereço.
Esses conceitos são exemplificados na Figura 1, onde à esquerda, a variável "casa1" armazena o
Disciplina

ALGORITMOS E PROGRAMAÇÃO
ESTRUTURADA

valor 8 e a variável "casa2" armazena o valor -1.5; na representação à direita, a variável "prédio1"
contém três valores inteiros, enquanto a variável "prédio2" armazena dois valores decimais.

Figura 1 | Variáveis primitivas e variáveis compostas.

Dentro do contexto das variáveis compostas, nos quais múltiplos valores são armazenados em
um único endereço, surge a questão de como diferenciá-los uns dos outros. Assim como os
apartamentos em um prédio são identificados por números, as variáveis compostas são
identificadas por meio de índices. Dessa forma, ao contrário das variáveis primitivas, as variáveis
compostas possuem um endereço na memória e índices que especificam seus subespaços.

As variáveis compostas derivam dos tipos primitivos e podem ser categorizadas como
homogêneas ou heterogêneas. Além disso, podem ser unidimensionais ou multidimensionais.
Quando armazenam valores do mesmo tipo primitivo, são classificadas como homogêneas,
enquanto, se armazenam valores de diferentes tipos, são consideradas heterogêneas.

Os exemplos ilustrados na Figura 1, representados pelas variáveis compostas "predio1" e


"predio2", são considerados homogêneos, uma vez que a primeira armazena exclusivamente
valores do tipo inteiro, enquanto a segunda contém exclusivamente valores decimais. Além
disso, ambas são classificadas como unidimensionais, o que implica que elas seguem a
estrutura de uma tabela com apenas uma coluna e N linhas (esse conceito seria o mesmo se
considerássemos uma estrutura semelhante a uma tabela com uma linha e N colunas). Esse tipo
de estrutura de dados é comumente conhecido como vetor ou array.

Inicialização e utilização
Disciplina

ALGORITMOS E PROGRAMAÇÃO
ESTRUTURADA

A criação de um vetor assemelha-se à criação de uma variável primitiva, com a adição de um


número entre colchetes que indica o tamanho desse vetor (ou a quantidade de blocos). Assim, a
sintaxe é a seguinte:

<tipo> <nome_do_vetor>[tamanho];

Vamos criar dois vetores em C para armazenar informações sobre a idade e a altura (em metros)
de 3 indivíduos. Observando o código apresentado no Quadro 1, na linha 3, é definido o vetor
"idade", que é do tipo inteiro e tem capacidade para armazenar três valores. Na linha 4, o vetor
"altura" é criado e inicializado com valores específicos. Ao declarar os valores no momento da
criação do vetor, os elementos são listados entre chaves e separados por vírgula. Nas linhas de 5
a 7, os valores armazenados no vetor "altura" são impressos, acessando-os pelos seus
respectivos índices.

1: #include <stdio.h>
2: int main(){
3: int idade[3];
4: float altura[3] = {1, 1.5, 1.7};
5: printf("\n Vetor altura[0] = %d",altura[0]);
6: printf("\n Vetor altura[1] = %d",altura[1]);
7: printf("\n Vetor altura[2] = %d",altura[2]);
8: return 0;
9: }

Quadro 1 | Exemplo de criação e inicialização de vetores.

Cada elemento contido em um vetor é acessado por meio de seu índice, que, na maioria das
linguagens de programação, sempre se inicia em zero. No código apresentado no Quadro 1, por
exemplo, na linha 5, a expressão "altura[0]" é utilizada para imprimir o primeiro valor, "altura[1]"
para imprimir o segundo e "altura[2]" para imprimir o terceiro. O índice é usado tanto para leitura
quanto para escrita. Por exemplo, podemos atribuir valores ao vetor "idade" da seguinte maneira:

idade[0] = 10;
idade[1] = 18;
idade[2] = 32;

Para facilitar a compreensão, observe a representação esquemática do vetor "idade" na memória,


conforme ilustrado na Figura 2. O valor associado a um determinado índice é crucial para a
posição do elemento no vetor. É importante destacar que um vetor com N posições terá seus
índices variando de 0 até N-1. No caso do vetor "idade" com capacidade para 3 elementos, os
índices variam de 0 até 2.
Disciplina

ALGORITMOS E PROGRAMAÇÃO
ESTRUTURADA

Figura 2 | Vetor “idade”.

Geralmente, os dados que serão utilizados são inseridos pelo usuário ou obtidos de alguma fonte
de dados. Para armazenar um valor inserido pelo usuário em um vetor, é comum usar a função
scanf(). No entanto, é crucial especificar em qual posição do vetor o valor deve ser armazenado.
Por exemplo, se desejarmos guardar uma idade inserida pelo usuário no vetor, o processo seria
como segue:

printf("Digite uma idade: ");


scanf("%d", &idade[1]);

Neste caso, o valor seria armazenado no índice 1 do vetor, o que corresponde ao segundo bloco,
considerando que o primeiro é o bloco zero.

Vale ressaltar que um vetor é uma estrutura de dados estática, o que significa que seu tamanho
deve ser definido no momento da criação pelo programador e não pode ser alterado durante a
execução do programa. Além disso, ao criar um vetor com N posições, nem todas as posições
precisam ser utilizadas. No entanto, é importante ter em mente que quanto maior o tamanho do
vetor, mais espaço será reservado na memória de trabalho.

Outra questão importante relacionada com a criação de um vetor está relacionada com o fato do
compilador apenas “reservar” o espaço de memória pedido, sem colocar nenhum valor nele. Isso
significa que o vetor conterá inicialmente uma seleção “aleatória” de valores, que chamamos de
“lixo” (Provavelmente que sobraram da execução de algum programa que usou aquele espaço,
exatamente como ocorria para as variáveis comuns).
Disciplina

ALGORITMOS E PROGRAMAÇÃO
ESTRUTURADA

Siga em Frente...

Vetores de caracteres: strings


Vamos começar com uma pergunta: Como é constituída uma palavra? Por uma sequência de
caracteres, correto? Já estabelecemos que o caractere é um tipo primitivo em linguagens de
programação. Considerando que uma palavra é essencialmente uma cadeia de caracteres,
podemos concluir que ela, na verdade, é um vetor de caracteres. Na terminologia da
programação, um vetor de caracteres é comumente referido como "string".

A declaração de uma string em C segue a seguinte estrutura:

char <variavel>[tamanho];

Por exemplo:

char nome[16];
char sobrenome[31];
char frase[101];

Ao criar uma string em C, é importante observar o tamanho da string, pois a última posição é
reservada pelo compilador, que atribui o valor "\0" para indicar o final da sequência. Portanto, a
string nome[16] possui 15 espaços disponíveis para serem preenchidos (índices de 0 a 14).

A atribuição de valores a uma string pode ser feita no momento da declaração de três maneiras:
(i) inserindo cada caractere entre chaves, separados por vírgula (similar aos outros tipos de
vetores); (ii) atribuindo a palavra ou frase entre aspas; e (iii) atribuindo a palavra ou frase entre
aspas e entre chaves. Por exemplo:

char nome[16] = {‘J’,’o’,’a’,’o’};


char sobrenome[31] = “Alberto Gomes”;
char frase[101] = {“Disciplina de Algoritmos”};

Diversas funções são utilizadas para a leitura e impressão de strings em C. Estudaremos duas
delas. A primeira é a função já conhecida, scanf(), que agora é usada com o código de controle
%s para indicar que uma string será armazenada. Portanto, para armazenar um nome digitado
pelo usuário, utilizamos o seguinte formato:

char nome[16];
Disciplina

ALGORITMOS E PROGRAMAÇÃO
ESTRUTURADA

printf("\n Digite um nome:");


scanf("%s", nome);
printf("\n Nome digitado: %s", nome);

É importante observar que, nesse caso, o operador "&" não é obrigatório na função scanf().

Essa forma de atribuição possui uma limitação: somente é possível armazenar palavras simples,
e não compostas. Isso ocorre porque a função scanf() interrompe a atribuição ao encontrar um
espaço em branco. Para contornar essa limitação, uma opção é utilizar a função fgets(), que
também faz parte da biblioteca padrão <stdio.h>. Essa função é utilizada com a seguinte sintaxe:

fgets(destino, tamanho, fluxo);

O parâmetro "destino" especifica o nome da string que será utilizada para o armazenamento. O
parâmetro "tamanho" deve ser o mesmo declarado para a string. O parâmetro "fluxo" indica a
origem da string; no caso em questão, sempre virá do teclado, e, portanto, utilizamos "stdin"
(entrada padrão). Segue um exemplo prático:

char frase[101];
printf("\n Digite uma frase:");
fflush(stdin);
fgets(frase, 101, stdin);
printf("\n Frase digitada: %s", frase);

Observa-se que antes de utilizar o fgets(), empregamos a função fflush(stdin). Embora não seja
obrigatório, essa prática assegura a limpeza da entrada padrão (stdin) antes do armazenamento.

Vamos Exercitar?
Prezado estudante, é hora de aplicar todo o conhecimento adquirido até aqui! Para resolver a
situação, será necessário implementar um programa em C que solicite ao usuário que insira o
CPF no formato "[Link]-NN" e, em seguida, elimine os pontos e os traços para criar um
CPF sem formatação. Dessa forma, o sistema poderá processar e armazenar os CPFs de forma
padronizada, facilitando a indexação e busca. Ainda, você poderá usar vetores com laços de
repetições para eliminar os pontos e traço, além do comando continue dentro da estrutura de
repetição. Veja no Quadro 2 uma das possíveis soluções:

1: #include <stdio.h>
2: int main(){
Disciplina

ALGORITMOS E PROGRAMAÇÃO
ESTRUTURADA

3: char cpf1[15]; // Vetor CPF formatado com


4: pontos e traço
5: char cpf2[11] = ""; // Vetor CPF sem
6: formatação, inicializado como vazio
7: int i = 0, n = 0;
8:
9: printf("Digite seu CPF na forma
10: [Link]-NN: \n");
11: scanf("%s", cpf1);
12:
13: // Laço para percorrer todo o vetor cpf1
14: // Remover pontos e traços e armazenar
15: apenas os dígitos
16: for (i = 0; i < 14; i++) {
17: if (cpf1[i] == '.' || cpf1[i] == '-') {
18: continue; // Ignora pontos e traços
19: } else {
20: // Armazena apenas os dígitos em cpf2
21: cpf2[n] = cpf1[i];
22: n++; // controla o tamanho do cpf2
23: }
24: }
25: // Imprime o CPF formatado sem pontos e
traços
printf("\n\nCPF formatado = %s", cpf2);
return 0;
}

Quadro 2 | Código de resolução.

Lembrando que não há uma única resposta correta. Há vários caminhos para se chegar no
mesmo resultado! Modifique e tente otimizar ao máximo os seus programas.

Saiba mais

Para entender melhor o conceito de vetores em C, sugerimos a leitura do Capítulo 6 - Vetores, do


livro Linguagem C, disponível na Biblioteca Virtual.

DAMAS, L. Linguagem C. 10. ed. Rio de Janeiro: LTC, 2023. cap. 6, p.129-151.

Também sugerimos a leitura do Capítulo 7 - Arrays de caracteres - strings, do livro Linguagem C:


Completa e Descomplicada, disponível na Biblioteca Virtual, para complementar os estudos
Disciplina

ALGORITMOS E PROGRAMAÇÃO
ESTRUTURADA

sobre strings em C.

BACKES, A. Linguagem C: completa e descomplicada. 2. ed. Rio de Janeiro: LTC, 2023. cap. 7, p.
130-139.

Para auxiliar no desenvolvimento de programas na linguagem C, uma ótima prática é verificar a


documentação da linguagem para entender em detalhes os principais tipos de funções e
elementos utilizados. Para isso, sugerimos a consulta da seguinte documentação sempre que
achar necessário. Nela você encontra todas as bibliotecas utilizadas na linguagem e como
utilizar suas principais funções: Referência da Linguagem C.

Referências

BACKES, A. Linguagem C: completa e descomplicada. 2. ed. Rio de Janeiro: LTC, 2023. cap. 4, p.
67-87.

DAMAS, L. Linguagem C. 10. ed. Rio de Janeiro: LTC, 2023. cap. 3, p. 51-79.

PIVA JUNIOR, D. Algoritmos e programação de computadores. 2. ed. Rio de Janeiro: Elsevier,


2019.

Aula 2
Matrizes

Matrizes

Este conteúdo é um vídeo!


Para assistir este conteúdo é necessário que você acesse o AVA pelo
computador ou pelo aplicativo. Você pode baixar os vídeos direto no aplicativo
para assistir mesmo sem conexão à internet.
Dica para você
Aproveite o acesso para baixar os slides do vídeo, isso pode deixar sua
aprendizagem ainda mais completa.
Disciplina

ALGORITMOS E PROGRAMAÇÃO
ESTRUTURADA

Estudante, esta videoaula foi preparada especialmente para você. Nela, você irá aprender
conteúdos importantes para a sua formação profissional. Vamos assisti-la?

Ponto de Partida

Olá! Nesta aula vamos introduzir uma segunda estrutura muito importante e amplamente
utilizada: as matrizes!

A instituição de ensino que você trabalha solicitou que você desenvolva um sistema de
gerenciamento de notas melhorado. O sistema deve ser capaz de armazenar as notas dos alunos
em diferentes disciplinas e calcular a média das notas de cada aluno em cada disciplina, além de
calcular a média geral de cada aluno em todas as disciplinas. Antes, esse controle era feito por
meio de uma tabela manual, mas não era muito prático. Sendo assim, qual estrutura você poderá
utilizar para resolver esta tarefa?

Agora vamos lá, preste muita atenção e tenha um excelente estudo!

Vamos Começar!

Motivação e definição
Considere a Tabela 1 que exibe dados fictícios relacionados às temperaturas máximas e
mínimas da cidade de São Paulo durante 5 dias. Essa tabela representa uma estrutura de dados
matricial com 5 linhas e 2 colunas. Se desejarmos criar um programa que calcule a média
dessas temperaturas, seria necessário armazenar esses valores em uma variável composta
bidimensional, também conhecida como matriz.

Temperatura mínima Temperatura máxima


14º 25º
12º 24º
15º 27º
17º 29º
18º 30º

Tabela 1 | Temperaturas máximas e mínimas de 5 dias em São Paulo.


Disciplina

ALGORITMOS E PROGRAMAÇÃO
ESTRUTURADA

Perceba que neste exemplo, poderíamos facilmente criar dois vetores, um para as mínimas e
outra para as máximas. Mas da mesma forma que vimos não ser tão interessante criar várias
variáveis do mesmo tipo para armazenar um conjunto de valores homogêneos, neste caso
também não seria o mais ideal criar vários vetores. Portanto, podemos criar uma matriz, que
nada mais é do que um conjunto de vetores. Assim como um vetor é um conjunto de variáveis
primitivas.

Em resumo, cada linha de uma matriz é considerada um vetor de n números, e a matriz é um


vetor de m vetores-linha, formando assim uma matriz m × n (m linhas, n colunas). Veja o exemplo
na Tabela 2.

M[0][0] M[0][1] ... M[0][n]


M[1][0] M[1][1] ... M[1][n]
M[2][0] M[0][0] ... M[2][n]
... ... ... ...
M[m][0] M[m][1] ... M[m][n]

Tabela 2 | Exemplo da estrutura de uma matriz.

Inicialização e utilização
Para criar uma matriz em C, a sintaxe utilizada é a seguinte:

<tipo> <nome_da_matriz>[linhas][colunas];

E aqui estão alguns exemplos de declaração de matrizes. Na primeira linha, uma estrutura com 3
linhas e 2 colunas é criada. Na segunda linha, temos a criação da estrutura correspondente à
Tabela 1, com 5 linhas e 2 colunas. Por fim, na terceira linha vemos uma matriz de 3 linhas e 2
colunas sendo criada e inicializada. Perceba que colocamos os valores em subconjuntos
conjuntos entre chaves, em que cada um representa uma linha da matriz.

int coordenadas[3][2];
float temperaturas[5][2];
int valores[3][2] = {{2, 3}, {5, 7}, {9, 11}};

Para manipular matrizes bidimensionais, é necessário especificar dois índices, na qual a


atribuição de valores é feita da seguinte forma:
Disciplina

ALGORITMOS E PROGRAMAÇÃO
ESTRUTURADA

matriz[M][N] = valor;

Aqui, "M" representa a linha na qual o valor será armazenado e "N" representa a coluna. Assim
como nos vetores, os índices de uma matriz em C sempre começam a partir de zero.

Vamos declarar uma matriz em C para armazenar as notas do primeiro e segundo bimestre de
três alunos. No Quadro 1, na linha 3, declaramos uma matriz denominada "notas" com 3 linhas e
2 colunas, o que implica no armazenamento de 6 valores no total (produto das linhas pelo
número de colunas). Nas linhas 4 e 5, são armazenadas as notas do primeiro aluno. É importante
notar que as linhas (primeiro índice) permanecem fixas, enquanto as colunas (segundo índice)
são alteradas para registrar as notas dos respectivos alunos. Este procedimento é repetido para
o segundo e terceiro aluno, que são armazenados na segunda e terceira linha da matriz,
respectivamente.

1: #include <stdio.h>
2: int main(){
3: float notas[3][2];
4: //aluno 1
5: notas[0][0] = 9.5;
6: notas[0][1] = 10;
7: //aluno 2
8: notas[1][0] = 4.5;
9: notas[1][1] = 6.2;
10: //aluno 3
11: notas[2][0] = 7;
12: notas[2][1] = 8,5;
13: return 0;
14: }

Quadro 1 | Exemplo de matriz em C.

A Figura 1 representa a estrutura de dados que é criada na memória para o código apresentado
no Quadro 1. É possível observar que as linhas foram utilizadas para representar os diferentes
alunos, enquanto as colunas foram utilizadas para armazenar as notas referentes aos bimestres.
Disciplina

ALGORITMOS E PROGRAMAÇÃO
ESTRUTURADA

Figura 1 | Estrutura matricial do exemplo do Quadro 1.

Para armazenar valores inseridos pelo usuário em uma matriz, usamos a função scanf(),
indicando os dois índices que selecionam a posição na qual desejamos armazenar o valor. Da
mesma forma, para imprimir valores, também utilizamos os dois índices para especificar a
posição do elemento a ser impresso. Segue um exemplo prático:

printf("Digite uma nota: ");


scanf("%f", &nota[1][0]);
printf("Nota digitada: %.2f", nota[1][0]);

Neste exemplo, a nota inserida pelo usuário será armazenada na linha 1, coluna 0 da matriz.
Posteriormente, o valor armazenado nessa posição será exibido na tela com duas casas
decimais, conforme especificado no comando da linha 3.

E ainda com base no Quadro 1, como poderíamos deixar a inserção de dados a cargo do usuário
e de forma otimizada? Simples! Utilizando dois laços de repetição for aninhados, uma para
percorrer as linhas e outro para percorrer as colunas em cada uma das linhas. Veja o exemplo no
Quadro 2.

1: #include <stdio.h>
2: int main(){
3: float notas[3][2];
4: for (int i=0; i<3; i++) {
Disciplina

ALGORITMOS E PROGRAMAÇÃO
ESTRUTURADA

5: for (int j=0; j<2; j++) {


6: printf(“digite a nota %d do
7: aluno %d:”, j+1,i+1);
8: scanf(“%f”, &notas[i][j])
9: }
10: }
11: return 0;
12: }

Quadro 2 | Exemplo utilizando laços for aninhados para ler dados em uma matriz.

Siga em Frente...

Operações com Matrizes


Neste momento vamos abordar alguns exemplos de utilização de matrizes para reforçar o
conteúdo aprendido até aqui! Vamos lá?

Primeiramente, vamos aprender a manipular os índices de uma matriz dentro de laços for
aninhados. Para isso, considere o seguinte exemplo: ler uma matriz quadrada 3x3 e retornar a
soma dos elementos de sua diagonal principal e diagonal secundária. O Quadro 3 apresenta o
algoritmo que resolve este problema.

1: #include <stdio.h>
2: int main(){
3: int matriz[3][3];
4: int I, j, sDiagPrinc = 0, sDiagSec = 0;
5: // Leitura da matriz
6: printf“"Digite os elementos da matriz
7: 3x3:\”");
8: for (i = 0; i < 3; i++) {
9: for (j = 0; j < 3; j++) {
10: scanf“"%”", &matriz[i][j]);
11: }
12: }
13: // Cálculo da soma da diagonal principal
14: e secundária
15: for (i = 0, j = 2; i < 3, j >=0; i++, j--) {
16: sDiagPrinc += matriz[i][i];
17: sDiagSec += matriz[i][j];
18: }
19:
Disciplina

ALGORITMOS E PROGRAMAÇÃO
ESTRUTURADA

20: printf“"Soma dos elementos da diagonal


21: principal: %d\”", sDiagPrinc);
22: printf“"Soma dos elementos da diagonal
secundaria: %d\”", sDiagSec);
return 0;
}

Quadro 3 | Exemplo com matrizes.

O primeiro conjunto de laços for é responsável por ler os elementos da matriz, percorrendo todos
os elementos, em que i faz a indexação das linhas, e j das colunas. Já o segundo laço for é
responsável por calcular a soma das diagonais. A diagonal primária de uma matriz é aquela cujo
índice da linha é igual ao índice da coluna, portanto somamos os elementos da matriz que
possuem o mesmo valor de índice (matriz[i][i]). Já a diagonal secundária seriam os seguintes
elementos: matriz[0][2], matriz[1][1], e matriz[2][0]. Perceba que enquanto o índice de linhas
aumenta de um em um, o índice de colunas diminui de um em um. Então uma possível solução
seriam duas variáveis de controle dentro de um mesmo for, uma para linha e outra para coluna,
conforme vemos no Quadro 3.

Outro exemplo clássico é relacionado à multiplicação de matrizes. Veja no Quadro 4 um


programa em C que lê duas matrizes e suas respectivas dimensões, verifica se a multiplicação
entre elas é possível e, se for o caso, calcula e exibe o produto das matrizes.

1: #include <stdio.h>
2: int main() {
3: int m, n, p, q, i, j, k;
4: int soma = 0;
5:
6: printf("Digite as dimensões da primeira
7: matriz (m x n): ");
8: scanf("%d %d", &m, &n);
9: printf("Digite as dimensões da segunda
10: matriz (p x q): ");
11: scanf("%d %d", &p, &q);
12:
13: // Verificação se a multiplicação é possível
14: if (n != p) {
15: printf("A multiplicação entre as matrizes
16: não é possível.\n");
17: return 0;
18: }
19:
20:
Disciplina

ALGORITMOS E PROGRAMAÇÃO
ESTRUTURADA

21: // Declaração e entrada dos elementos das


22: matrizes
23: int matriz1[m][n], matriz2[p][q], resultado[m]
24: [q];
25: printf("Digite os elementos da primeira
26: matriz:\n");
27: for (i = 0; i < m; i++) {
28: for (j = 0; j < n; j++) {
29: scanf("%d", &matriz1[i][j]);
30: }
31: }
32: printf("Digite os elementos da segunda
33: matriz:\n");
34: for (i = 0; i < p; i++) {
35: for (j = 0; j < q; j++) {
36: scanf("%d", &matriz2[i][j]);
37: }
38: }
39:
40: // Cálculo do produto das matrizes
41: for (i = 0; i < m; i++) {
42: for (j = 0; j < q; j++) {
43: for (k = 0; k < p; k++) {
44: soma += matriz1[i][k] * matriz2[k][j];
45: }
46: resultado[i][j] = soma;
47: soma = 0;
48: }
49: }
50:
51: printf("O produto das matrizes é:\n");
52: for (i = 0; i < m; i++) {
for (j = 0; j < q; j++) {
printf("%d\t", resultado[i][j]);
}
printf("\n");
}
return 0;
}

Quadro 4 | Multiplicação de matrizes.

Vamos Exercitar?
Disciplina

ALGORITMOS E PROGRAMAÇÃO
ESTRUTURADA

Prezado estudante, é hora de aplicar todo o conhecimento adquirido até aqui! Para desenvolver o
sistema de gerenciamento de notas, podemos usar matrizes para armazenar os dados das notas
dos alunos por disciplina e realizar os cálculos necessários. Nesta lógica, cada linha da matriz
representa um aluno, e as colunas as respectivas disciplinas. Veja no Quadro 5 uma das
possíveis soluções:

1: #include <stdio.h>
2: #define NUM_ALUNOS 3
3: #define NUM_DISCIPLINAS 3
4:
5: int main(){
6: float notas[NUM_ALUNOS]
7: [NUM_DISCIPLINAS] = {{7.5, 8.0, 9.0}, {6.5, 7.0,
8: 8.0}, {8.0, 7.5, 8.5}};
9: float mediasAluno[NUM_ALUNOS];
10: float mediaGeral, soma = 0;
11:
12: // Calcula a média das notas de cada aluno
13: em cada disciplina
14: for (int i = 0; i < NUM_ALUNOS; i++) {
15: float soma = 0;
16: for (int j = 0; j < NUM_DISCIPLINAS; j++) {
17: soma += notas[i][j];
18: }
19: mediasAluno[i] = soma /
20: NUM_DISCIPLINAS;
21: }
22:
23: // Calcula a média geral de cada aluno em
24: todas as disciplinas
25: for (int i = 0; i < NUM_ALUNOS; i++) {
26: soma += mediasAluno[i];
27: }
28: mediaGeral = soma / NUM_ALUNOS;
29:
30: // Imprime as médias de cada aluno em
31: cada disciplina
32: for (int i = 0; i < NUM_ALUNOS; i++) {
33: printf("Média do aluno %d: %.2f\n", i + 1,
34: mediasAluno[i]);
}
// Imprime a média geral de todos os alunos
printf("Média geral de todos os alunos:
%.2f\n", mediaGeral);
Disciplina

ALGORITMOS E PROGRAMAÇÃO
ESTRUTURADA

return 0;
}

Quadro 5 | Código de resolução.

Nesta solução utilizamos uma diretiva chamada #define. Em C, ela é usada para criar constantes
simbólicas. Ela é uma construção do pré-processador e não uma função da linguagem em si.
Com ela, você pode fornecer um nome a um valor constante antes de o programa ser compilado.
Ela substitui todas as ocorrências desse nome no código pelo valor constante especificado. No
caso desta solução, a linha “#define NUM_ALUNOS 3” cria uma constante simbólica
“NUM_ALUNOS” com o valor 3. Em todo o programa, sempre que “NUM_ALUNOS” é usado, ele
será substituído por 3 durante a fase de pré-processamento. Isso torna o código mais legível e
facilita a manutenção, uma vez que você pode ajustar o valor da constante em um único local, se
necessário, em vez de ter que alterar cada ocorrência do valor diretamente.

Lembrando que não há uma única resposta correta. Há vários caminhos para se chegar no
mesmo resultado! Modifique e tente otimizar ao máximo os seus programas.

Saiba mais
Para entender melhor o conceito de matrizes em C, sugerimos a leitura do Capítulo 6 - Vetores,
do livro Linguagem C, disponível na Biblioteca Virtual.

DAMAS, L. Linguagem C. 10. ed. Rio de Janeiro: LTC, 2023. cap. 6, p. 129-151.

Também sugerimos a leitura do Capítulo 6 - Vetores e matrizes - arrays, do livro Linguagem C:


Completa e Descomplicada, disponível na Biblioteca Virtual, para complementar os estudos
sobre matrizes em C.

BACKES, A. Linguagem C: completa e descomplicada. 2. ed. Rio de Janeiro: LTC, 2023. cap. 6, p.
109-129.

Para auxiliar no desenvolvimento de programas na linguagem C, uma ótima prática é verificar a


documentação da linguagem para entender em detalhes os principais tipos de funções e
elementos utilizados. Para isso, sugerimos a consulta da seguinte documentação sempre que
achar necessário. Nela você encontra todas as bibliotecas utilizadas na linguagem e como
utilizar suas principais funções: Referência da Linguagem C.

Referências
Disciplina

ALGORITMOS E PROGRAMAÇÃO
ESTRUTURADA

BACKES, André. Linguagem C: completa e descomplicada. 2. ed. Rio de Janeiro: LTC, 2023. cap.
4, p. 67-87.

DAMAS, L. Linguagem C. 10. ed. Rio de Janeiro: LTC, 2023. cap. 3, p. 51-79.

PIVA JUNIOR, D. Algoritmos e programação de computadores. 2. ed. Rio de Janeiro: Elsevier,


2019.

Aula 3
Structs

Structs

Este conteúdo é um vídeo!


Para assistir este conteúdo é necessário que você acesse o AVA pelo
computador ou pelo aplicativo. Você pode baixar os vídeos direto no aplicativo
para assistir mesmo sem conexão à internet.
Dica para você
Aproveite o acesso para baixar os slides do vídeo, isso pode deixar sua
aprendizagem ainda mais completa.

Estudante, esta videoaula foi preparada especialmente para você. Nela, você irá aprender
conteúdos importantes para a sua formação profissional. Vamos assisti-la?

Ponto de Partida

Olá! Nesta aula vamos introduzir uma forma de definir tipos de dados heterogêneos: as structs!

A instituição de ensino que você trabalha possui uma biblioteca e solicitou que você desenvolva
um sistema de gestão de biblioteca. O sistema deve ser capaz de armazenar informações sobre
vários livros, incluindo título, autor, ISBN, ano de publicação e quantidade disponível em estoque.
Além disso, o sistema deve permitir a busca de livros por autor, verificação de disponibilidade e
atualização do estoque.
Disciplina

ALGORITMOS E PROGRAMAÇÃO
ESTRUTURADA

Nesse cenário, como você poderá realizar a estruturação dos dados?

Nesta aula vamos aprender formas de facilitar esta tarefa para que se torne realidade com muita
facilidade! Preste muita atenção e tenha um excelente estudo!

Vamos Começar!

Definição e criação de structs


Já conhecemos a maneira de aprimorar a eficiência no uso de variáveis ao usar estruturas
compostas, como vetores e matrizes. No entanto, essas estruturas só podem armazenar valores
do mesmo tipo. Além dessas estruturas homogêneas, as linguagens de programação oferecem
estruturas compostas heterogêneas, conhecidas como "structs", ou registros.

Assim como associamos vetores e matrizes a tabelas, podemos associar uma estrutura a um
formulário de cadastro com vários campos. Por exemplo, o cadastro de um cliente pode ser
realizado inserindo o nome, a idade, o CPF e o endereço em uma "struct".

Na linguagem C, a criação de uma estrutura deve ser feita antes da função `main()` e deve seguir
a seguinte sintaxe:

struct <nome> {
<tipo> <nome_da_variavel1>;
<tipo> <nome_da_variavel2>;
...
};

Aqui, `<nome>` é o nome da estrutura, como cliente, carro, fornecedor, etc., e as variáveis internas
são os campos nos quais desejamos armazenar informações dessa estrutura. Na prática, uma
estrutura funciona como um "tipo de dado" e seu uso sempre será atribuído a uma ou mais
variáveis. Veja a seguir um exemplo de criação de uma struct em C:

struct Cadastro {
char cpf[11];
char nome[30];
int idade;
char rua[50];
int numero;
};
Disciplina

ALGORITMOS E PROGRAMAÇÃO
ESTRUTURADA

Observe que os elementos que compõem a estrutura são definidos de maneira semelhante às
variáveis (sejam elas variáveis simples ou compostas). Tal como na declaração de variáveis, os
nomes das variáveis (membros) de uma estrutura devem ser únicos entre si. No entanto,
diferentes estruturas podem ter membros com identificadores idênticos.

Após a definição da estrutura, nós podemos utilizá-la como um novo tipo de dado no programa
principal, declarando variáveis do tipo da estrutura definida, conforme o trecho a seguir:

struct Cadastro cliente1;

No trecho acima, a variável “pessoa1” é do tipo “Cadastro”, portanto, ela possui dentro dela todos
os membros de cadastro, como cpf, nome, idade, rua e número, por exemplo. Perceba que, por
“Cadastro” ser um tipo definido pelo programador, você precisa usar a palavra struct antes do
tipo da nova variável criada.

Por fim, veja no trecho de código logo a seguir que também podemos definir variáveis após a
definição da estrutura. Isso pode ser feito colocando os nomes das variáveis após o fechamento
das chaves (}) da estrutura e antes do ponto e vírgula (;).

struct Cadastro {
char cpf[11];
char nome[30];
int idade;
char rua[50];
int numero;
} cliente1, cliente2;

Manipulação de dados em structs


Após a criação de uma struct e definição de uma variável do tipo de estrutura, podemos acessar
seus campos (ou variáveis) utilizando o operador "." (ponto). Este operador é empregado para
referenciar os campos da estrutura pertencentes à variável declarada. Veja no Quadro 1, um
exemplo de utilização de structs em C que ilustra como os campos da estrutura "Aluno" podem
ser facilmente acessados.

1: #include <stdio.h>
2: #include <string.h>
3:
4: struct Aluno {
5: int numMat;
6: char nome[30];
Disciplina

ALGORITMOS E PROGRAMAÇÃO
ESTRUTURADA

7: char sexo;
8: int idade;
9: };
10:
11: int main(){
12: struct Aluno aluno1;
13:
14: // Inserindo dados no aluno1
15: [Link] = 1000;
16: strcpy([Link], "Joao");
17: [Link] = 'M';
18: [Link] = 19;
19:
20: // Imprimindo os dados do aluno1
21: printf("Número de matrícula: %d\n",
22: [Link]);
23: printf("Nome: %s\n", [Link]);
24: printf("Sexo: %c\n", [Link]);
25: printf("Idade: %d\n", [Link]);
26:
27: return 0;
}

Quadro 1 | Exemplo de struct em C.

Note que o campo “nome” é um vetor de caracteres, portanto, é uma string. Em C, temos a
biblioteca strings.h que possui diversas funções para manipulação de strings. Neste código
utilizamos a função strcpy, que copia o valor do segundo parâmetro (“Joao”) para o primeiro
([Link]).

Caso se faça necessário ler uma entrada de dados do usuário, basta usar o scanf normalmente
como fazemos com variáveis comuns, e de forma independente para cada variável; da estrutura,
respeitando o tipo de cada uma para o código de controle. Veja o trecho de código a seguir que lê
os valores para os campos “numMat” e “nome” da variável “aluno1”.

scanf(“%d”, &[Link]);
fgets([Link], 30, stdin);

Uma outra maneira de atribuir valores à uma variável de estrutura é inicializando-a diretamente
em sua declaração. Para isso, ao declarar a variável do tipo da estrutura, podemos definir uma
lista de valores separados por vírgula e delimitados pelo operador de chaves ({ }). Devemos
prestar atenção na ordem, pois o primeiro valor da inicialização será atribuído ao primeiro
membro da estrutura (numMat), e assim por diante. Por exemplo:
Disciplina

ALGORITMOS E PROGRAMAÇÃO
ESTRUTURADA

struct Aluno aluno2 = { 2000, “Maria”, ‘F’, 18 };

Ainda, elementos não mencionados durante a inicialização são definidos como 0 ou como uma
string vazia ("") no caso de strings/caracteres. No exemplo a seguir o campo "sexo" é inicializado
com uma string vazia ("") e "idade" com zero.

struct Aluno aluno2 = { 2000, “Maria”};

Siga em Frente...

Uso de structs em algoritmos


Imagine agora que você precise trabalhar com dados de cinco alunos, conforme a estrutura
Aluno já definida anteriormente. A princípio, poderíamos criar cinco variáveis do tipo aluno, como:

struct Aluno a1, a2, a3, a4, a5;

Mas isso não é muito prático. Sendo assim, a representação desses cinco registros pode ser
ainda mais simplificada se usarmos o conceito de vetores:

struct Aluno alunos[5];

Dessa forma, é criado um vetor de estruturas, em que cada posição do vetor é uma estrutura do
tipo "Aluno". A declaração de um vetor de estruturas se assemelha à declaração de um vetor de
um tipo básico.

Quando temos um vetor de estruturas, acessamos cada uma e seus membros da seguinte
forma:

alunos[0].idade;
alunos[1].idade;
alunos[2].idade;

Veja que operador de ponto (.) vem depois dos colchetes ([ ]) do índice do vetor. É importante
manter a ordem estabelecida, já que o índice do vetor indica a posição específica que desejamos
Disciplina

ALGORITMOS E PROGRAMAÇÃO
ESTRUTURADA

acessar, na qual cada posição é representada por uma estrutura. Somente após a definição das
estruturas contidas no vetor é que podemos acessar os campos correspondentes.

Em C, a palavra-chave typedef é usada para criar um novo nome para um tipo existente. Isso
pode tornar a declaração de tipos complexos mais legível e facilitar a manutenção do código.
Usar typedef não cria um novo tipo, apenas cria um novo nome para um tipo existente. Veja a
sintaxe a seguir:

typedef <tipo_de_dado_existente> <novo_nome_do_tipo>

Na sintaxe, o campo “tipo_de_dado_existente” pode ser qualquer tipo, desde int até tipos
definidos pelo usuário com structs.

Em structs o typedef pode ser utilizado para eliminar o uso da palavra “struct” antes da
declaração de uma variável do tipo definido pela estrutura. Por exemplo:

typedef struct {
char nome[20];
int idade;
} Aluno;

No trecho anterior temos uma definição de estrutura, em que ela será referenciada no programa
principal apenas como “Aluno”.

Aluno aluno1;

Em termos de significado, não há nenhuma mudança, sendo apenas uma simplificação.

Vamos Exercitar?

Prezado estudante, é hora de aplicar todo o conhecimento adquirido até aqui! Lembre-se que
você precisa desenvolver um sistema capaz de armazenar informações sobre vários livros, além
de permitir a busca de livros por autor, verificação de disponibilidade e atualização do estoque.

Para resolver esta tarefa, vamos criar uma estrutura Livro, contendo os atributos título, autor,
ISBN, ano de publicação e quantidade disponível em estoque. Em seguida, no programa principal
vamos instanciar um vetor desta estrutura de acordo com o número de livros que a escola possui
em estoque. Veja no Quadro 2 uma das possíveis soluções:
Disciplina

ALGORITMOS E PROGRAMAÇÃO
ESTRUTURADA

1: #include <stdio.h>
2: #include <string.h>
3: #define NUM_LIVROS 3
4:
5: typedef struct{
6: char titulo[100];
7: char autor[50];
8: char ISBN[13];
9: int anoPublicacao;
10: int estoque;
11: } Livro;
12:
13: int main() {
14: Livro livros[NUM_LIVROS] = {
15: {"Memórias de um Futuro Esquecido",
16: "Martelo de Assis", "1231231231239", 1899,
17: 10},
18: {"O Silêncio dos Inocentes Gritando",
19: "Franz Kafta", "4564564564569", 1915, 5},
20: {"A Menina que Roubava Livros e os
21: Devolvia com Juros", "Dan Brownie",
22: "7897897897899", 1949, 8}
23: };
24:
25: // Realizar uma busca por autor
26: char autorProcurado[50];
27: fflush(stdin); // limpa o buffer de leitura
28: printf("Digite o nome do autor para procurar
29: livros: ");
31: fgets(autorProcurado, 50, stdin);
32: autorProcurado[strcspn (autorProcurado,
33: "\n")] = 0; // remove o \n ao final da string
34: printf("Livros por %s:\n", autorProcurado);
35: for (int i = 0; i < NUM_LIVROS; i++) {
36: if (strcmp(livros[i].autor, autorProcurado)
37: == 0) {
38: printf("Título: %s\n", livros[i].titulo);
39: printf("ISBN: %s\n", livros[i].ISBN);
40: printf("Ano de Publicação: %d\n",
41: livros[i].anoPublicacao);
42: printf("Estoque Disponível: %d\n",
43: livros[i].estoque);
44: printf("\n");
45: }
Disciplina

ALGORITMOS E PROGRAMAÇÃO
ESTRUTURADA

46: }
47:
48: // Verificar disponibilidade de um livro
49: char ISBNProcurado[13];
50: fflush(stdin);
51: printf("Digite o ISBN do livro para verificar a
52: disponibilidade: ");
53: fgets(ISBNProcurado, 13, stdin);
54: ISBNProcurado[strcspn (ISBNProcurado,
55: "\n")] = 0; // remove o \n ao final da string
56: for (int i = 0; i < NUM_LIVROS; i++) {
57: if (strcmp(livros[i].ISBN, ISBNProcurado)
58: == 0) {
59: printf("O livro %s está disponível em
60: estoque: %d\n", livros[i].titulo, livros[i].estoque);
break;
}
}
return 0;
}

Quadro 2 | Código de resolução.

Nesta solução inicializamos o vetor livros diretamente em sua declaração. Veja que cada
elemento Livro do vetor livros é colocado como uma lista entre chaves ({}), dentro de outro grupo
externo de chaves. Outro detalhe importante é na linha 29, em que utilizamos a função strcspn
para remover a quebra de linha (\n) que é inserido em uma string sempre que usamos uma
leitura com o fgets. E se este \n permanece na string, a comparação com o strcmp não
funcionaria, pois, a string original no vetor livros não possui esta quebra de espaço ao final. A
função strcspn em C é usada para encontrar o comprimento do segmento inicial de uma string
que não contém caracteres de um conjunto de caracteres específico. Ela retorna o comprimento
da substring inicial que não contém os caracteres da segunda string.

Lembre-se de que não há uma única resposta correta, e ainda é possível otimizar este código!
Que tal colocar as opções de pesquisa por autor e ISBN dentro de um switch-case, criando assim
um menu de seleção? Ainda, você pode incluir outra opção neste menu para possibilitar a
alteração dos dados dos livros ou ainda a inclusão de novos livros. Aceita o desafio?

Saiba mais
Para entender melhor o conceito de estruturas em C, sugerimos a leitura do Capítulo 11 -
Estruturas, do livro Linguagem C, disponível na Biblioteca Virtual.
Disciplina

ALGORITMOS E PROGRAMAÇÃO
ESTRUTURADA

DAMAS, L. Linguagem C. 10. ed. Rio de Janeiro: LTC, 2023. cap. 11, p. 266-281.

Também sugerimos a leitura do Capítulo 8 - Tipos definidos pelo programador, do livro


Linguagem C: Completa e Descomplicada, disponível na Biblioteca Virtual, para complementar os
estudos sobre estruturas em C, além de aprender sobre enumerações (enum) e uniões (union).

BACKES, A. Linguagem C: completa e descomplicada. 2. ed. Rio de Janeiro: LTC, 2023. cap. 8, p.
140-157.

Para auxiliar no desenvolvimento de programas na linguagem C, uma ótima prática é verificar a


documentação da linguagem para entender em detalhes os principais tipos de funções e
elementos utilizados. Para isso, sugerimos a consulta da seguinte documentação sempre que
achar necessário. Nela, você encontra todas as bibliotecas utilizadas na linguagem e como
utilizar suas principais funções: Referência da Linguagem C.

Referências

BACKES, A. Linguagem C: completa e descomplicada. 2. ed. Rio de Janeiro: LTC, 2023. cap. 4, p.
67-87.

DAMAS, L. Linguagem C. 10. ed. Rio de Janeiro: LTC, 2023. cap. 3, p. 51-79.

PIVA JUNIOR, D. Algoritmos e programação de computadores. 2. ed. Rio de Janeiro: Elsevier,


2019.

Aula 4
Ponteiros

Ponteiros

Este conteúdo é um vídeo!


Para assistir este conteúdo é necessário que você acesse o AVA pelo
computador ou pelo aplicativo. Você pode baixar os vídeos direto no aplicativo
para assistir mesmo sem conexão à internet.
Dica para você
Disciplina

ALGORITMOS E PROGRAMAÇÃO
ESTRUTURADA

Aproveite o acesso para baixar os slides do vídeo, isso pode deixar sua
aprendizagem ainda mais completa.

Estudante, esta videoaula foi preparada especialmente para você. Nela, você irá aprender
conteúdos importantes para a sua formação profissional. Vamos assisti-la?

Ponto de Partida
Olá! Nesta aula você aprenderá a trabalhar com um recurso muito poderoso em linguagens de
programação: os ponteiros!

A instituição de ensino que você trabalha está promovendo um evento com uma série de
desafios e minicursos aos estudantes de tecnologia. Um grupo de alunos participantes chegou
até você com uma dúvida sobre um exercício envolvendo ponteiros em C: Escrever um programa
que declare um vetor de inteiros e um ponteiro para inteiros. Em seguida, associar o ponteiro ao
vetor e somar mais dez (+10) a cada posição do vetor usando o ponteiro com aritmética de
ponteiros. Como você pode ajudá-los a terminar o desafio e, principalmente, a compreender o
funcionamento dos ponteiros?

Nesta aula vamos aprender o que é um ponteiro e como ele pode ser utilizado! Preste muita
atenção e tenha um excelente estudo!

Vamos Começar!

Conceitos básicos de ponteiros


Além das variáveis primitivas e compostas, há um tipo de variável de extrema importância na
linguagem C: os ponteiros. Por meio dos ponteiros, é possível manipular variáveis e outros
recursos utilizando seus endereços de memória. Assim, existe uma relação intrínseca entre um
ponteiro e os endereços de memória, o que justifica o uso frequente desse tipo de variável,
especialmente para a manipulação de memória, proporcionando suporte às rotinas de alocação
dinâmica.

Variáveis do tipo ponteiro são empregadas exclusivamente para armazenar endereços de


memória. O acesso à memória é realizado utilizando dois operadores: o asterisco (*), usado para
declarar o ponteiro, e o "&", que, como mencionado anteriormente, é utilizado para acessar o
endereço de memória, sendo assim chamado de operador de referência. A sintaxe padrão para
declarar um ponteiro é:
Disciplina

ALGORITMOS E PROGRAMAÇÃO
ESTRUTURADA

<tipo> *<nome_do_ponteiro>;

Por exemplo:

int *idade;

Neste exemplo, um ponteiro do tipo inteiro é criado, o que implica que ele irá "apontar" para o
endereço de uma variável desse tipo. A criação de um ponteiro só tem significado se estiver
associada a algum endereço de memória. Para isso, utiliza-se a seguinte sintaxe:

int ano = 2018;


int *ponteiro_para_ano = &ano;

Na primeira linha, declaramos uma variável inteira com o valor 2018, e na segunda linha
associamos um ponteiro chamado “ponteiro_para_ano” ao endereço da variável “ano”. Agora,
tudo o que for atribuído à variável “ano” será refletido também no ponteiro. A Figura 1 ilustra de
forma simplificada o esquema de uma variável com um ponteiro na memória. É importante
observar que o conteúdo do ponteiro é o endereço da variável para a qual ele aponta, e que ele
também ocupa espaço na memória.

Figura 1 | Representação de um ponteiro na memória do computador (os endereços de variáveis são fictícios).
Disciplina

ALGORITMOS E PROGRAMAÇÃO
ESTRUTURADA

Agora, vamos analisar como imprimir as informações de um ponteiro. Podemos imprimir o


conteúdo do ponteiro, que corresponde ao endereço da variável para a qual ele aponta. Utilizando
o ponteiro criado anteriormente, “ponteiro_para_ano”, podemos imprimi-lo da seguinte maneira:

printf("Conteudo do ponteiro: %p", ponteiro_para_ano);

O especificador de formato “%p” é usado para imprimir o endereço de memória armazenado em


um ponteiro, em hexadecimal (também poderia ser utilizado “%x”).

Também podemos acessar o conteúdo da variável para a qual o ponteiro aponta, de acordo com
o seguinte exemplo:

printf("Conteudo da variavel pelo ponteiro: %d", *ponteiro_para_ano);

A diferença em relação ao comando anterior é o asterisco antes do nome do ponteiro. Além


disso, é possível imprimir o endereço do próprio ponteiro da seguinte maneira:

printf("Endereco do ponteiro: %p", &ponteiro_para_ano);

Operações com ponteiros


Um ponto importante a ser destacado é que um ponteiro pode ter um valor especial chamado
NULL, que é basicamente o "zero" para ponteiros. Este valor é usado para indicar explicitamente
que o ponteiro não está apontando para nenhum endereço de memória válido.

A constante NULL é definida em muitas bibliotecas padrão de C e é frequentemente usada para


inicializar ponteiros ou para verificar se um ponteiro está apontando para algo significativo antes
de acessar seu conteúdo. Por exemplo:

int *ponteiro = NULL;


if (ponteiro == NULL) {
printf("O ponteiro está apontando para NULL\n");
}

Além disso, o valor NULL é amplamente utilizado na criação de estruturas de dados complexas,
como listas ligadas. Nas listas ligadas, o valor NULL é frequentemente usado para indicar o fim
da lista, indicando que não há mais nós a serem percorridos. Isso ajuda a controlar e gerenciar a
estrutura da lista e a evitar erros de acesso à memória não alocada ou inválida. Ainda, o uso do
valor especial NULL para ponteiros desempenha um papel crucial na segurança e na prevenção
Disciplina

ALGORITMOS E PROGRAMAÇÃO
ESTRUTURADA

de erros em programas que lidam com alocação de memória dinâmica e estruturas de dados
complexas.

É importante destacar que, em C, apenas duas operações aritméticas podem ser utilizadas com
ponteiros: adição e subtração. Essas operações são especialmente úteis ao trabalhar com
vetores e estruturas de dados que são representadas em memória de forma contígua
(sequencial). Considere “p” uma variável do tipo ponteiro, e veja a seguir alguns exemplos de
operações:

p++;
// soma +1 no endereço armazenado no ponteiro.
p--;
// subtrai 1 no endereço armazenado no ponteiro.
(*p)++;
// incrementar o conteúdo da variável apontada pelo ponteiro p;
*p = (*p) * 10;
// multiplica o conteúdo da variável apontada pelo ponteiro p por 10;

A aritmética de ponteiros permite que você navegue por elementos de um vetor ou matriz de
maneira eficiente. Por exemplo, suponha que você tenha um vetor de inteiros e um ponteiro para
o primeiro elemento desse vetor. Você pode usar a aritmética de ponteiros para acessar
elementos específicos do vetor. Aqui estão alguns exemplos:

int numeros[5] = {10, 20, 30, 40, 50};


int *ponteiro = &numeros[0];
// Acessando o primeiro elemento
int primeiro_elemento = *ponteiro;
// Acessando o terceiro elemento
int terceiro_elemento = *(ponteiro + 2);
// Avançando para o próximo elemento
ponteiro++; // Agora aponta para o segundo elemento
// Voltando um elemento
ponteiro--; // Volta para o primeiro elemento

A aritmética de ponteiros é flexível e útil ao trabalhar com vetores, matrizes e estruturas de dados
contíguas na memória. No entanto, é importante observar que você só pode somar ou subtrair
valores inteiros a partir de um ponteiro. Isso é coerente com a ideia de que um ponteiro
representa um endereço de memória, e a aritmética de ponteiros é usada para navegar de
maneira precisa através desses endereços. O uso de outros tipos de dados na aritmética de
ponteiros pode levar a comportamento indefinido e erros no programa. Portanto, é importante
garantir que as operações de ponteiro estejam alinhadas com os tipos de dados apropriados.
Disciplina

ALGORITMOS E PROGRAMAÇÃO
ESTRUTURADA

Além das operações de adição e subtração, os operadores relacionais de igualdade (==) e


desigualdade (!=) podem ser utilizados para comparar se dois ponteiros apontam para o mesmo
endereço de memória ou não. Isso é útil ao verificar se dois ponteiros estão apontando para o
mesmo local de armazenamento ou para locais diferentes na memória. Por exemplo:

int a = 5;
int *ptr1 = &a;
int *ptr2 = &a;
if (ptr1 == ptr2) {
printf("Os ponteiros apontam para o mesmo endereço de memória.\n");
} else {
printf("Os ponteiros apontam para endereços de memória diferentes.\n");
}

Quanto aos operadores de comparação (>), (<), (>=) e (<=), você pode comparar ponteiros para
determinar qual deles aponta para um endereço de memória mais alto ou mais baixo. Essas
comparações são úteis para estabelecer a ordem de elementos em uma sequência de memória.
No entanto, tenha em mente que essa comparação só faz sentido se os ponteiros apontarem
para o mesmo bloco de memória (por exemplo, elementos de um vetor) para que a comparação
de endereços seja significativa. Por exemplo:

int numeros[5] = {10, 20, 30, 40, 50};


int *ptr1 = &numeros[2];
int *ptr2 = &numeros[4];
if (ptr1 < ptr2) {
printf("ptr1 aponta para um endereço mais baixo do que ptr2.\n");
}

Siga em Frente...

Ponteiros para estruturas de dados


Além de podermos criar ponteiros variáveis comuns, podemos também criá-los para variáveis
compostas, como os vetores, as matrizes e as estruturas.

Começando com as structs, ponteiros para estruturas são escritos de forma similar a uma
variável comum. A principal diferença é o uso do operador “->” para acesso aos membros. Veja
no Quadro 1 um exemplo de programa em C que trata esta questão.
Disciplina

ALGORITMOS E PROGRAMAÇÃO
ESTRUTURADA

1: #include <stdio.h>
2:
3: struct aluno{
4: int mat;
5: float nota;
6: };
7:
8: int main(){
9: struct aluno joao;
10: struct aluno *ptr; // declaração do
11: ponteiro para struct
12: // Inicialização da struct declarada
13: [Link] = 1000;
14: [Link] = 8.5;
15: //inicialização do ponteiro ptr
16: ptr = &joao;
17:
18: printf(“%d”, ptr->mat); //impressão do
19: atributo nome através do ponteiro
20: printf(“%f”, ptr->nota); //impressão do
21: atributo nota através do ponteiro
22: return 0;
}

Quadro 1 | Exemplo de ponteiro para struct.

Sabemos que vetores são conjuntos de dados do mesmo tipo dispostos contiguamente (um
depois do outro) na memória. No momento da declaração de um vetor, informamos ao
computador para reservar uma certa quantidade de memória a fim de armazenar os elementos
do vetor de forma sequencial. Desta maneira, a variável vetor é um ponteiro que aponta para o
começo da sequência elementos do vetor na memória. Portanto, podemos inicializar uma
variável ponteiro com o endereço de início do vetor. O Quadro 2 apresenta um exemplo de
ponteiro para vetor e a Figura 2 ilustra este procedimento na memória.

1: #include <stdio.h>
2:
3: int main(){
4: char *ptr;
5: int i;
6: char vet[5] = {'a', 'b', 'c', 'd', 'e'};
7: ptr = vet; // A variavel ponteiro ptr
8: aponta para o primeiro elemento do
9: vetor
Disciplina

ALGORITMOS E PROGRAMAÇÃO
ESTRUTURADA

10: for (i=0; i < 5; i++){


11: // conteudo do vetor acessado
12: pela variavel
13: printf("\n Vet[%d] = %c, i, vet[i]);
14: // conteudo do vetor acessado
15: pelo ponteiro
16: printf("\n ptr = %c", *ptr);
17: ptr++;
}
return 0;
}

Quadro 2 | Exemplo de ponteiro para struct.


Disciplina

ALGORITMOS E PROGRAMAÇÃO
ESTRUTURADA

Figura 2 | Representação de um ponteiro para vetor na memória do computador (os endereços de variáveis são fictícios).

Agora em relação às matrizes, apesar de terem mais de uma dimensão, elas são dispostas
linearmente na memória e, por isso, podem ser manipuladas com ponteiros semelhantes aos
vetores. Veja na Figura 3 como uma matriz 5x5 é disposta de forma linear na memória.
Disciplina

ALGORITMOS E PROGRAMAÇÃO
ESTRUTURADA

Figura 3 | Matriz 5x5.

Vamos Exercitar?

Prezado estudante, é hora de aplicar todo o conhecimento adquirido até aqui! Lembre-se de que
você precisa escrever um programa que declare um vetor de inteiros e um ponteiro para inteiros.
Em seguida, associar o ponteiro ao vetor e somar mais dez (+10) a cada posição do vetor usando
o ponteiro com aritmética de ponteiros. No Quadro 3, segue a solução do desafio.

1: #include <stdio.h>
2:
3: int main() {
4: int vetor[5] = {1, 2, 3, 4, 5};
5: int *ponteiro = vetor; // Associando o
6: ponteiro ao vetor
7:
8: for (int i = 0; i < 5; i++) {
9: *(ponteiro + i) += 10;
10: }
11:
12: printf("Elementos do vetor após adicionar
13: 10:\n");
14: for (int i = 0; i < 5; i++) {
15: printf("%d ", vetor[i]);
16: }
17: printf("\n");
18:
return 0;
}
Disciplina

ALGORITMOS E PROGRAMAÇÃO
ESTRUTURADA

Quadro 3 | Exemplo de solução.

Lembrando que não há uma única resposta correta e você pode fazer de maneiras diferentes e
ainda chegar ao mesmo resultado!! Bons estudos!

Saiba mais

Para entender melhor o conceito de ponteiros em C, sugerimos a leitura do Capítulo 8 - Ponteiros


(Pointers), do livro Linguagem C, disponível na Biblioteca Virtual.

DAMAS, L. Linguagem C. 10. ed. Rio de Janeiro: LTC, 2023. cap. 8, p. 174-202.

Também sugerimos a leitura do Capítulo 10 - Ponteiros, do livro Linguagem C: Completa e


Descomplicada, disponível na Biblioteca Virtual, para complementar os estudos sobre ponteiros
em C.

BACKES, A. Linguagem C: completa e descomplicada. 2. ed. Rio de Janeiro: LTC, 2023. cap. 10, p.
194-212.

A fim de ampliar o conhecimento nesta temática, sugerimos a leitura do Capítulo 11 - Alocação


dinâmica, do livro Linguagem C: Completa e Descomplicada, disponível na Biblioteca Virtual. Nele
você estudará os conceitos de alocação dinâmica com ponteiros, uma forma de requisitar
espaço e memória ao compilador em tempo de execução.

BACKES, A. Linguagem C: completa e descomplicada. 2. ed. Rio de Janeiro: LTC, 2023. cap. 11, p.
213-233.

Referências

BACKES, A. Linguagem C: completa e descomplicada. 2. ed. Rio de Janeiro: LTC, 2023. cap. 4, p.
67-87.

DAMAS, L. Linguagem C. 10. ed. Rio de Janeiro: LTC, 2023. cap. 3, p.51-79.

PIVA JUNIOR, D. Algoritmos e programação de computadores. 2. ed. Rio de Janeiro: Elsevier,


2019.

Aula 5
Vetores, Matrizes, Structs e Ponteiros
Disciplina

ALGORITMOS E PROGRAMAÇÃO
ESTRUTURADA

Videoaula de Encerramento

Este conteúdo é um vídeo!


Para assistir este conteúdo é necessário que você acesse o AVA pelo
computador ou pelo aplicativo. Você pode baixar os vídeos direto no aplicativo
para assistir mesmo sem conexão à internet.
Dica para você
Aproveite o acesso para baixar os slides do vídeo, isso pode deixar sua
aprendizagem ainda mais completa.

Estudante, esta videoaula foi preparada especialmente para você. Nela, você irá aprender
conteúdos importantes para a sua formação profissional. Vamos assisti-la?

Ponto de Chegada

Olá, estudante! Para desenvolver a competência desta Unidade, que é “Compreender as técnicas
para realizar a integração de vetores, matrizes, structs e ponteiro para desenvolvimento de
software”, você deve explorar conceitos fundamentais em programação, concentrando seus
estudos em estruturas condicionais e laços de repetição em linguagem C. Comece por
compreender as estruturas de dados homogêneas, fundamentais no campo da programação,
especialmente em linguagens de alto nível. Os vetores, por exemplo, representam conjuntos de
elementos do mesmo tipo, organizados sequencialmente na memória. Eles permitem acesso
rápido e eficiente aos elementos individuais, facilitando operações como ordenação, pesquisa e
manipulação em massa. As matrizes, por sua vez, são uma extensão dos vetores, organizando
os elementos em linhas e colunas, tornando-as essenciais para tarefas envolvendo dados
multidimensionais, como representação de imagens, processamento de sinais e simulações
científicas.

Em seguida, você deve focar nos conceitos de criação de estruturas heterogêneas, como as
structs, a fim de ampliar as possibilidades de representação de dados em linguagens de
programação. As structs permitem que os programadores agrupem diferentes tipos de dados
relacionados em uma única estrutura, o que facilita a organização e manipulação de informações
complexas. Com as structs, é possível criar tipos de dados personalizados, contendo variáveis de
tipos diversos, o que promove uma abordagem mais flexível e modular na resolução de
problemas de programação.

Por fim, os ponteiros são elementos-chave na programação de baixo nível e desempenham um


papel crucial na manipulação direta de memória em linguagens como C e C++. Eles são variáveis
Disciplina

ALGORITMOS E PROGRAMAÇÃO
ESTRUTURADA

que armazenam endereços de memória, permitindo o acesso e a manipulação direta de dados


armazenados em locais específicos da memória do computador. Os ponteiros são
frequentemente usados para otimizar o desempenho, gerenciar estruturas de dados dinâmicas,
acessar recursos de hardware e implementar passagem por referência, o que pode economizar
espaço e tempo de execução. No entanto, seu uso incorreto pode levar a erros difíceis de
depurar, como vazamentos de memória e falhas de segmentação. Portanto, compreender
adequadamente o conceito de ponteiros e suas operações é fundamental para garantir a
robustez e estabilidade de um programa.

Compreendendo esses conceitos essenciais, você estará preparado para criar programas mais
sofisticados e otimizados, aptos a enfrentar uma diversidade de desafios e situações por meio
do uso de vetores, matrizes, structs e ponteiros.

É Hora de Praticar!

Este conteúdo é um vídeo!


Para assistir este conteúdo é necessário que você acesse o AVA pelo
computador ou pelo aplicativo. Você pode baixar os vídeos direto no aplicativo
para assistir mesmo sem conexão à internet.

Imagine que você está desenvolvendo um sistema para uma escola que deseja automatizar o
processo de gerenciamento de notas e informações de alunos. A escola possui várias turmas, e
cada uma tem vários alunos e cada aluno precisa de informações como nome, número de
matrícula e notas em várias disciplinas. O desafio é criar um programa em C que permita ao
usuário realizar operações complexas, como adicionar alunos, lançar notas, calcular médias e
gerar relatórios detalhados para cada turma. Para facilitar, realize de forma direta no código a
inserção de alunos e a criação de turmas (mas sem adicionar alunos às turmas).
O programa deve então realizar as seguintes funções:

Cadastrar aluno em uma turma.


Lançar notas de aluno.
Calcular a média de uma turma.
Gerar o relatório de turma, exibindo as informações de todos os alunos pertencentes à
turma.

Reflita sobre as vantagens e desvantagens das estruturas de dados homogêneas, como


vetores e matrizes, em comparação com estruturas heterogêneas, como structs. Em quais
situações cada tipo de estrutura é mais adequado?
Disciplina

ALGORITMOS E PROGRAMAÇÃO
ESTRUTURADA

Como as structs proporcionam uma abordagem mais flexível e modular na resolução de


problemas?
Quais são os desafios e riscos associados ao uso incorreto de ponteiros, e como podem
ser mitigados para garantir a robustez e estabilidade de um programa?

O código a seguir apresenta uma sugestão de resultado para o problema:


#include <stdio.h>
#include <string.h>

struct Aluno {
char nome[50];
int matricula;
float notas[2]; // Considere 2 disciplinas para simplificar o código
};

struct Turma {
int numeroTurma;
struct Aluno alunos[30]; // Considere até 30 alunos por turma
int totalAlunos;
};

int main(){

struct Aluno alunos[5];


struct Turma turmas[10]; // Suponha até 10 turmas na escola
int op;
// Cadastrar os alunos

strcpy(alunos[0].nome, "João");
alunos[0].matricula = 1001;
alunos[0].notas[0] = 8.5;
alunos[0].notas[1] = 7.0;

strcpy(alunos[1].nome, "Maria");
alunos[1].matricula = 1002;
alunos[1].notas[0] = 7.5;
alunos[1].notas[1] = 8.0;

strcpy(alunos[2].nome, "Pedro");
alunos[2].matricula = 1003;
alunos[2].notas[0] = 9.0;
alunos[2].notas[1] = 9.5;

strcpy(alunos[3].nome, "Ana");
Disciplina

ALGORITMOS E PROGRAMAÇÃO
ESTRUTURADA

alunos[3].matricula = 1004;
alunos[3].notas[0] = 7.0;
alunos[3].notas[1] = 7.5;

strcpy(alunos[4].nome, "Carlos");
alunos[4].matricula = 1005;
alunos[4].notas[0] = 8.0;
alunos[4].notas[1] = 8.5;

// inicializa duas turmas

turmas[0].totalAlunos = 0;
turmas[0].numeroTurma = 5000;

turmas[1].totalAlunos = 0;
turmas[1].numeroTurma = 6000;

int a, t;
float mediaTurma = 0.0;

do{
printf(" \n 1 - cadastrar aluno na turma\n");
printf(" 2 - lançar notas de aluno\n");
printf(" 3 - media da turma\n");
printf(" 4 - relatorio de turma\n");
printf(" 5 - encerrar\n");
printf(" Opcao: ");
scanf("%d", &op);

switch (op)
{
case 1:
printf(" Escolha o aluno: ");
scanf("%d", &a);
printf(" Escolha a turma: ");
scanf("%d", &t);
if (turmas[t].totalAlunos < 30) {
turmas[t].alunos[turmas[t].totalAlunos] = alunos[a];
turmas[t].totalAlunos++;
} else {
printf(" A turma está cheia. Não é possível adicionar mais alunos.\n");
}
break;
Disciplina

ALGORITMOS E PROGRAMAÇÃO
ESTRUTURADA

case 2:
printf(" Escolha o aluno: ");
scanf("%d", &a);
for (int i = 0; i < 2; i++) {
printf(" Nota %d: ", i+1);
scanf("%f", &alunos[a].notas[i]);
}
break;

case 3:
printf(" Escolha a turma: ");
scanf("%d", &t);
mediaTurma = 0.0;
for (int i = 0; i < turmas[t].totalAlunos; i++) {
float somaNotas = 0.0;
for (int j = 0; j < 5; j++) {
somaNotas += turmas[t].alunos[i].notas[j];
}
mediaTurma += somaNotas / 2;
}
printf("\n Media: %f", mediaTurma / turmas[t].totalAlunos);
break;

case 4:
printf(" Escolha a turma: ");
scanf("%d", &t);
printf("\n Turma %d\n", turmas[t].numeroTurma);
for (int i = 0; i < turmas[t].totalAlunos; i++) {
printf(" Aluno: %s\n", turmas[t].alunos[i].nome);
printf(" Matrícula: %d\n", turmas[t].alunos[i].matricula);
printf(" Notas: ");
for (int j = 0; j < 2; j++) {
printf("%.2f ", turmas[t].alunos[i].notas[j]);
}
printf("\n");
}
break;

default:
printf(" programa encerrado!\n\n");
break;
}
}while(op != 5);
Disciplina

ALGORITMOS E PROGRAMAÇÃO
ESTRUTURADA

return 0;
}
A sugestão de solução dada simula um sistema de gerenciamento de turmas e alunos em uma
escola.

Duas estruturas são definidas: struct Aluno e struct Turma, que representam
respectivamente os dados de um aluno e de uma turma. A struct Turma possui como
membro um vetor ds estrutura Aluno, representando os alunos que pertencem à turma.
O usuário tem acesso a um menu de opções que inclui:
Adicionar um aluno a uma turma.
Lançar notas de um aluno.
Calcular a média da turma.
Gerar um relatório da turma.
Encerrar o programa.
As funcionalidades do menu são implementadas utilizando um loop do-while e um switch-
case. O programa imprime na tela as opções do menu e solicita a entrada do usuário para
realizar as operações desejadas.
A lógica de cada funcionalidade esta associada a um “case”.

O mapa mental a seguir ilustra e identifica as estruturas estudadas nesta unidade.


Disciplina

ALGORITMOS E PROGRAMAÇÃO
ESTRUTURADA

BACKES, A. Linguagem C: completa e descomplicada. 2. ed. Rio de Janeiro: LTC, 2023.


CORMEN, T. H. Desmistificando algoritmos. 1. ed. Rio de Janeiro: Elsevier, 2014.
Disciplina

ALGORITMOS E PROGRAMAÇÃO
ESTRUTURADA

DAMAS, L. Linguagem C. 10. ed. Rio de Janeiro: LTC, 2023.


MENÉNDEZ, A. Simplificando algoritmos. 1. ed. Rio de Janeiro: LTC, 2023.
PIVA JUNIOR, D. Algoritmos e programação de computadores. 2. ed. Rio de Janeiro: Elsevier,
2019.
,

Unidade 4
Funções e Passagem de Parâmetros

Aula 1
Funções

Funções

Este conteúdo é um vídeo!


Para assistir este conteúdo é necessário que você acesse o AVA pelo
computador ou pelo aplicativo. Você pode baixar os vídeos direto no aplicativo
para assistir mesmo sem conexão à internet.
Dica para você
Aproveite o acesso para baixar os slides do vídeo, isso pode deixar sua
aprendizagem ainda mais completa.

Estudante, esta videoaula foi preparada especialmente para você. Nela, você irá aprender
conteúdos importantes para a sua formação profissional. Vamos assisti-la?

Ponto de Partida

Olá! Até este ponto você já estudou praticamente todos os conceitos fundamentais de
algoritmos e linguagem de programação, como os tipos de dados, variáveis, constantes,
operadores e expressões, estruturas de controle, estruturas homogêneas e heterogêneas, além
de ponteiros. Agora vamos prosseguir um pouco mais em nossos estudos e introduzir os
conceitos de procedimentos e funções!
Disciplina

ALGORITMOS E PROGRAMAÇÃO
ESTRUTURADA

Você foi recrutado por um laboratório de pesquisa que presta serviços terceirizados para
colaborar com vários profissionais. Seu primeiro projeto será com o departamento de
engenheiros civis. Eles receberam uma solicitação da construtora local para calcular e
determinar qual guindaste deve ser utilizado em uma determinada construção para erguer as
colunas de concreto armado. Eles têm à disposição três tipos de guindastes: G1, G2 e G3. A
seleção do guindaste a ser usado depende do peso da peça que será levantada pelo
equipamento, o qual é calculado pela fórmula P = VR, em que P representa o peso da coluna, V é
o volume e R é a constante utilizada, que é igual a 25 kN/m3. As diretrizes para a escolha do
guindaste estão especificadas na Tabela 1.

Regra Guindaste
Peso <= 500 kg G1
500 < Peso <= 1500
G2
Kg
Peso > 1500 Kg G3

Tabela 1 | Regras para escolha do guindaste.

Para automatizar o processo com base nas medidas da coluna (base, largura e altura), como o
programa determinará e informará aos engenheiros o guindaste que deve ser utilizado?

Para cumprir sua missão, você irá aprender sobre a distinção entre procedimentos e funções,
bem como a criação e utilização desses conceitos. Agora vamos lá, preste muita atenção e tenha
um excelente estudo!

Vamos Começar!

Conceitos e definição de funções


Até este ponto, você já desenvolveu vários algoritmos na linguagem C, correto? Nos programas
que criou, mesmo sem ter um conhecimento formal sobre funções, você já as utilizou! Por
exemplo, printf() e scanf() são funções incluídas nas bibliotecas da linguagem C que você utiliza
desde o início. Mas antes mesmo destas funções você já empregou uma função muito
importante! Observe o código apresentado no Quadro 1, que exibe uma mensagem na tela. Na
linha 2 temos o comando “int main()”. Esse comando define uma função denominada "main" que
retorna um valor inteiro, neste caso, zero. Parece complexo? Fique tranquilo! Vamos
compreender adequadamente como construir e operar esse recurso fundamental.

1: #include <stdio.h>
Disciplina

ALGORITMOS E PROGRAMAÇÃO
ESTRUTURADA

2: int main(){
3: printf("Hello World!",altura[0]);
4: return 0;
5: }

Quadro 1 | Exemplo de programa em C.

A concepção de desenvolver programas com conjuntos de funcionalidades deriva de uma


estratégia de design de algoritmos conhecida como "dividir para conquistar". O conceito é direto:
ao enfrentar um problema, é recomendado dividi-lo em problemas menores, facilitando assim
sua resolução e organização. Essa técnica compreende três etapas (Figura 1):

1. Dividir: fragmentar um problema em subproblemas menores. "Resolver problemas de


menor escala, em vez de um problema único e grande, é, do ponto de vista computacional,
teoricamente mais simples".
2. Conquistar: utilizar uma sequência de instruções separadas para resolver cada
subproblema.
3. Combinar: integrar a solução de cada subproblema para obter a solução completa do
problema original.

Figura 1 | Resumo da técnica dividir para conquistar.

Em linguagem C, uma função é essencialmente um fragmento de código autônomo incorporado


em um programa maior, designado para desempenhar uma tarefa específica com relativa
independência do restante do código. Uma das vantagens fundamentais das funções é a
capacidade de serem executadas repetidamente, o que proporciona a reutilização eficiente do
código. Em vez de repetir várias vezes um conjunto de comandos para realizar uma determinada
operação, é possível simplesmente chamar a função responsável por essa tarefa em múltiplas
ocasiões. Essa prática, que também pode ser chamada de modularização, não só economiza
Disciplina

ALGORITMOS E PROGRAMAÇÃO
ESTRUTURADA

espaço e torna o código mais conciso, mas também viabiliza ajustes ágeis no código associado
a essa tarefa específica.

A organização do código em várias funções também desempenha um papel crucial na


manutenção da clareza e limpeza do programa. Ao dividir o código em partes menores, cada
uma focada em uma tarefa específica, a complexidade geral do programa é reduzida, tornando o
código mais legível e compreensível. Esse método de divisão modular não apenas facilita a
compreensão do funcionamento do programa, mas também simplifica o processo de
identificação e correção de possíveis erros ou problemas no código.

A Figura 2 ilustra esta ideia de que as funções são blocos de construção que permitem a divisão
dos programas em partes menores (Segmentar uma tarefa grande de computação em várias
tarefas menores).

Figura 2 | Ilustração de um programa sendo dividido em funções.

Sintaxe de funções: parâmetros e retorno


Agora que sabemos a motivação por trás do conceito de função, como criá-la? Para isso,
utilizamos a seguinte sintaxe:

<tipo de retorno> <nome> (<parâmetros>)


{
<Comandos da função>
<Retorno> (não obrigatório)
}
Disciplina

ALGORITMOS E PROGRAMAÇÃO
ESTRUTURADA

Cada declaração de função possui uma série de parâmetros, alguns dos quais são fundamentais,
enquanto outros são opcionais. Vamos examinar cada um deles:

Tipo de retorno: este parâmetro é obrigatório e indica o tipo de valor que a função retornará.
Pode ser um valor inteiro (int), decimal (float ou double), caractere (char) ou outro tipo de
dado. No caso de uma sub-rotina que executa um processo sem retornar um valor
específico, utiliza-se o parâmetro void. Nesse contexto de função sem tipo de retorno
(void), a função é denominada de procedimento e o uso do void pode ser omitido.
Nome: outro parâmetro obrigatório que especifica o identificador da função. Funciona de
maneira similar ao nome de uma pessoa, em que é necessário chamá-la pelo nome para
interagir. É importante ressaltar que o nome não deve conter acentos, caracteres especiais
ou espaços, seguindo as mesmas regras aplicadas a nomes de variáveis.
Parênteses após o nome: é um parâmetro obrigatório que acompanha o nome da função
ou procedimento. Por exemplo, temos as expressões main(), printf() e somar().
Parâmetros: este campo é opcional, e contém valores que podem ser passados para a
função, sobre os quais a função deve operar. Os parâmetros das funções atuam de maneira
análoga às variáveis das funções matemáticas. Por exemplo: imagine a função matemática
f(x) = x + 2. Quando calculamos f(3), nós substituímos o valor de x por 3, resultando em f(3)
= 3 + 2 = 5. Desta forma, o 3 é um parâmetro da função f, e o função o utiliza para realizar
seu cálculo (processamento). Este campo será estudado em detalhes mais à frente.
Comandos da função: são obrigatórios, pois uma função só faz sentido se houver um
conjunto de comandos que ela possa executar.
Retorno: quando o tipo de retorno é void, esse parâmetro não precisa ser utilizado. No
entanto, quando não é void, torna-se obrigatório. É importante que o valor retornado seja
compatível com o tipo de retorno, pois, em algumas linguagens, um erro de compilação
pode resultar se isso não for respeitado, enquanto em outras pode resultar em um valor
impreciso. O valor de retorno pode ser qualquer expressão que seja legítima de se colocar
no lado direito de uma atribuição (=), por exemplo: o valor de uma variável; uma constante
numérica ou caractere; ou uma expressão aritmética. Não é possível ter mais de um retorno
em uma função, isto é, somente um valor ou variável pode ser retornado. E é importante
ressaltar que a instrução return também encerra a execução da função (O programador
deve usar esse comando somente quando não houver mais nada a fazer dentro da função).

Veja agora um exemplo de função em C no Quadro 2.

1: #include <stdio.h>
2: int somar(){
3: return 2 + 3;
4: }
5: int main(){
6: int resultado = 0;
7: resultado = somar();
8: printf("O resultado da função é = %d",
9: resultado);
Disciplina

ALGORITMOS E PROGRAMAÇÃO
ESTRUTURADA

10: return 0;
}

Quadro 2 | Exemplo de função em C.

No exemplo apresentado no Quadro 2, a função principal, chamada main(), é um elemento


essencial em muitas linguagens de programação, como C, Java e C#. Ela atua como o ponto de
partida da execução do programa, definindo a rotina principal que deve ser executada. Antes do
main(), temos a definição da funcão somar(). Em C, é comum criar as funções (também
conhecidas como sub-rotinas) antes da função main() para facilitar o desenvolvimento e a leitura
do código. A função somar() começa na linha 2 e termina na linha 4, delimitada por chaves.
Vamos examinar os parâmetros nesse caso específico:

Tipo de retorno: a função foi especificada para retornar um valor inteiro (int).
Nome: o nome da função é somar.
Comandos da função: nessa função, a soma de dois valores é retornada em um único
comando: return 2 + 3. É importante notar que cada programador tem a liberdade de criar
funções de acordo com suas preferências. Por exemplo, os comandos poderiam ter sido
escritos da seguinte forma, conforme o Quadro 3:

Vamos agora analisar o Quadro 3, que apresenta um exemplo de função com parâmetros.

1: int somar(int x, int y){


2: int s = 0;
3: s = x + y;
4: return s;
5: }
6: int main(){
7: int resultado = somar(4, 5);
8: printf("O resultado da função é = %d",
9: resultado);
10: return 0;
}

Quadro 3 | Exemplo de função com parâmetros.

A função do Quadro 3 realiza a soma de dois números inteiros passados como parâmetros, x e y,
e estas duas variáveis são utilizados dentro da função para realizar a soma, armazenar em s, e
retornar seu valor. Quando a função é chamada no main() (linha 7), passamos os valores 4 e 5,
que serão atribuídos aos par6ametros x e y, respectivamente. Portanto, o resultado retornado
pela função será 9 (x + y = 4 + 5).
Disciplina

ALGORITMOS E PROGRAMAÇÃO
ESTRUTURADA

Siga em Frente...

O uso de funções na linguagem C


Você pode ter observado que uma função tem a capacidade de retornar valores de diferentes
tipos primitivos, como inteiros, reais e caracteres. No entanto, surge a questão sobre a
possibilidade de retornar um vetor. E a resposta é afirmativa! Para alcançar esse resultado
devemos utilizar os ponteiros!

É importante destacar que não é possível criar funções com uma sintaxe direta como "int[10]
calcular()", onde "int[10]" indica que a função retorna um vetor com 10 posições. O único meio de
retornar um vetor é através de um ponteiro. Como um ponteiro é um tipo especial de variável que
armazena endereços de memória, podemos empregar essa abordagem para retornar o endereço
de um vetor. Dessa forma, a função que invocou terá acesso ao vetor que foi calculado
internamente.

Assim, a sintaxe apropriada para essa função é a seguinte:

<tipo>* <nome_da_função>(){
<tipo> vetor[tamanho];
<return> vetor;
}

Observa-se que mesmo ao retornar o nome do vetor, ainda há a inclusão do tipo primitivo no
retorno da função, que é acompanhado por um asterisco indicando o retorno de um ponteiro, ou
seja, um endereço.

Para ilustrar o uso desse método, vamos implementar uma função que cria um vetor de cinco
posições, preenche-o com valores aleatórios, imprime esses valores e, em seguida, transmite o
vetor para o chamador da função. A implementação dessa função é exibida no Quadro 4.

Na linha 14, um ponteiro do tipo inteiro é criado, indicando que ele apontará para um local que
contém um número inteiro. Na linha 15, uma variável de controle de loop é criada. A função
gerarRandomico() é invocada na linha 16, direcionando a execução para a linha 3, em que é
especificado que a função retornará um endereço para valores inteiros (int*). Um vetor de
números inteiros com cinco posições é criado na linha 4 e é declarado estático, o que significa
que o valor do vetor não será alterado entre diferentes chamadas da função.

Um loop é estabelecido na linha 6 para percorrer as cinco posições do vetor. Em cada posição,
um valor aleatório é gerado usando a função rand() na linha 7, e esse valor é impresso na linha 9
para futuras comparações. O vetor agora preenchido é retornado pela função na linha 11,
armazenando o endereço obtido no ponteiro p do programa principal. Outro loop é criado na linha
Disciplina

ALGORITMOS E PROGRAMAÇÃO
ESTRUTURADA

17 para percorrer o vetor acessado por seu endereço. Na linha 18, para acessar o conteúdo do
vetor, o comando *(p + i) é utilizado. É importante lembrar que o ponteiro retorna o endereço da
primeira posição do vetor, por isso é adicionado o valor de i para acessar as próximas posições.

1: #include <stdio.h>
2: #include <stdlib.h>
3: int* gerarRandomico(){
4: static int r[10];
5: int a;
6: for(a = 0; a < 10; ++a) {
7: r[a] = rand() % 100; // “% 100” é usado para
8: para limitar o rand a úmeros entre 0 e 99
9: printf(“r[%d] = %d\n”, a, r[a]);
10: }
11: return r;
12: }
13: int main(){
14: int *p;
15: int I;
16: p = gerarRandomico();
17: for (i = 0; i < 10; i++) {
18: printf“"\np[%d] = %”", i, *(p + i));
19: }
20: return 0;
21: }

Quadro 4 | Código de exemplo.

O código apresentado no Quadro 4 resulta na impressão de valores idênticos devido ao uso do


atributo static na declaração do vetor. O resultado do código do Quadro 5 pode ser verificado na
Figura 3.
Disciplina

ALGORITMOS E PROGRAMAÇÃO
ESTRUTURADA

Figura 3 | Saída do programa do Quadro 5.

Vamos Exercitar?

Prezado estudante, é hora de aplicar todo o conhecimento adquirido até aqui! Para resolver a
situação, é necessário ter a fórmula para calcular o peso anotada: P = VR. Além disso, será
preciso criar condicionais para determinar qual guindaste deve ser utilizado. Agora, construa o
programa seguindo as seguintes orientações, sendo que uma sugestão é apresentada no Quadro
5:

Declare uma variável para armazenar um valor real, já que o peso pode não ser um número
inteiro.
Armazene o resultado da função na variável criada.
Disciplina

ALGORITMOS E PROGRAMAÇÃO
ESTRUTURADA

Compare o valor armazenado com a primeira condição para verificar se o guindaste a ser
utilizado é o G1. Se for o caso, imprima uma mensagem para o usuário.
Crie uma estrutura condicional encadeada com a primeira, comparando o valor
armazenado com a terceira condição, para determinar se o guindaste a ser utilizado é o G3.
Em caso afirmativo, exiba uma mensagem para o usuário.
Adicione um bloco "senão" ao final, pois se o peso não corresponder a nenhuma das
condições anteriores, o guindaste a ser utilizado será o G2. Nesse caso, também emita
uma mensagem para o usuário.
Crie uma função para calcular o peso antes da função main().
Declare três variáveis para armazenar os valores da base, altura e comprimento.
Solicite ao usuário que insira os valores e armazene-os nas variáveis criadas.
Calcule o peso da coluna usando a fórmula fornecida pelos engenheiros.

1: #include <stdio.h>
2: int calcularPeso() {
3: float b, c, h = 0;
4: printf("\n Digite o valor da base: ");
5: scanf("%f", &b);
6: printf("\n Digite o valor da altura: ");
7: scanf("%f", &h);
8: printf("\n Digite o valor do comprimento: ");
9: scanf("%f", &c);
10: return (int) (b * h * c * 25); // o (int) é
11: chamado de “cast” e é usado para garantir que
12: o valor resultante será inteiro (se não o for, ele
13: o converte)
14: }
15: int main() {
16: float peso;
17: peso = calcularPeso();
18:
19: if (peso <= 500) {
20: printf("\n O guindaste de modelo G1 deve
21: ser usado");
22: } else if (peso > 1500) {
23: printf("\n O guindaste de modelo G3 deve
24: ser usado");
25: } else {
26: printf("\n O guindaste de modelo G2 deve
ser usado");
}
return 0;
}
Disciplina

ALGORITMOS E PROGRAMAÇÃO
ESTRUTURADA

Quadro 5 | Código de resolução.

Lembrando que não há uma única resposta correta. Há vários caminhos para se chegar no
mesmo resultado! Modifique e tente otimizar ao máximo os seus programas.

Saiba mais

Para entender melhor o conceito de funções e procedimentos em C, sugerimos a leitura do


Capítulo 5 - Funções e Procedimentos, do livro Linguagem C, disponível na Biblioteca Virtual.

DAMAS, L. Linguagem C. 10. ed. Rio de Janeiro: LTC, 2023. cap. 5, p. 104-128.

Também sugerimos a leitura do Capítulo 9 - Funções, do livro Linguagem C: Completa e


Descomplicada, disponível na Biblioteca Virtual, para complementar os estudos sobre funções
em C.

BACKES, A. Linguagem C: completa e descomplicada. 2. ed. Rio de Janeiro: LTC, 2023. cap. 9, p.
158-193.

Para auxiliar no desenvolvimento de programas na linguagem C, uma ótima prática é verificar a


documentação da linguagem para entender em detalhes os principais tipos de funções e
elementos utilizados. Para isso, sugerimos a constante consulta da seguinte documentação
sempre que achar necessário. Nela você encontra todas as bibliotecas utilizadas na linguagem e
como utilizar suas principais funções: Referência da Linguagem C.

Referências
BACKES, A. Linguagem C: completa e descomplicada. 2. ed. Rio de Janeiro: LTC, 2023. cap. 4, p.
67-87.

DAMAS, L. Linguagem C. 10. ed. Rio de Janeiro: LTC, 2023. cap. 3, p. 51-79.

PIVA JUNIOR, D. Algoritmos e programação de computadores. 2. ed. Rio de Janeiro: Elsevier,


2019.

Aula 2
Passagem de Parâmetros por Valor
Disciplina

ALGORITMOS E PROGRAMAÇÃO
ESTRUTURADA

Passagem de parâmetros por valor

Este conteúdo é um vídeo!


Para assistir este conteúdo é necessário que você acesse o AVA pelo
computador ou pelo aplicativo. Você pode baixar os vídeos direto no aplicativo
para assistir mesmo sem conexão à internet.
Dica para você
Aproveite o acesso para baixar os slides do vídeo, isso pode deixar sua
aprendizagem ainda mais completa.

Estudante, esta videoaula foi preparada especialmente para você. Nela, você irá aprender
conteúdos importantes para a sua formação profissional. Vamos assisti-la?

Ponto de Partida
Olá! Vamos prosseguir nossos estudos sobre procedimentos e funções conhecendo um pouco
mais sobre como trabalhar com os parâmetros de uma função!

Continuando seu trabalho no laboratório de pesquisa multidisciplinar, agora é hora de colaborar


com o núcleo de química. Em uma reação química, a relação entre os reagentes é crucial para
determinar o resultado. Dados dois componentes químicos, A e B, sua mistura resultará em um
terceiro composto C (A + B -> C). O núcleo de química solicitou uma otimização das condições
em uma reação específica denominada "proteção". Para alcançar essa otimização, é necessário
variar as condições do experimento, isto é, utilizando diferentes massas dos compostos. Um mol
do composto A possui uma massa de 321,43 g, enquanto um mol de B tem uma massa de
150,72 g. É necessário criar uma função que facilite o cálculo dos produtos químicos. Dessa
forma, a partir de diferentes combinações de massa, seu programa deverá calcular a massa final
do composto. Além do cálculo, o programa deve exibir os resultados das combinações
apresentadas na Tabela 1, uma vez que esses valores servem como referência para os químicos.

Quantidade de mol Quantidade de mol Quantidade de mol


de A de B de C
1,2 1,0 ?
1,4 1,0 ?
1,0 1,6 ?
Disciplina

ALGORITMOS E PROGRAMAÇÃO
ESTRUTURADA

Tabela 1 | Regras para escolha do guindaste.

Para cumprir sua missão, você aprenderá sobre o escopo de variáveis e a passagem de
parâmetros por valor! Agora vamos lá, preste muita atenção e tenha um excelente estudo!

Vamos Começar!

Escopo de variáveis
Já sabemos que as variáveis servem para armazenar temporariamente dados na memória.
Porém, o local em que elas são definidas no código de um programa determina o seu alcance e a
sua visibilidade. O código apresentado no Quadro 1 ilustra esse conceito.

1: #include <stdio.h>
2: int testar(){
3: int x = 10;
4: return x;
5: }
6: int main(){
7: int x = 20;
8: printf("\n Valor de x na funcao main() = %d",
9: x);
10: printf("\n Valor de x na funcao testar() = %d",
11: testar());
return 0;
}

Quadro 1 | Exemplo de escopo de variáveis em C.

Neste exemplo, existem duas variáveis chamadas "x". Isso, no entanto, não causará nenhum
problema, pois apesar de compartilharem o mesmo nome, elas são definidas em locais
diferentes: uma está dentro da função main() e a outra dentro da função testar(). Assim, cada
função possui seu próprio espaço de memória independente. Na memória, as variáveis são
identificadas por seus endereços, o que implica que, mesmo com o mesmo nome, seus
endereços são únicos.

Desta forma podemos definir o escopo de uma variável como a extensão do seu alcance no local
no qual o recurso está definido, permitindo que ele seja acessível em várias partes do código do
programa. O escopo é classificado em duas categorias, local ou global. No caso do Quadro 1,
ambas as variáveis são locais, o que significa que elas existem e são acessíveis apenas dentro
do corpo da função em que foram definidas. Para criar uma variável global, é necessário declará-
Disciplina

ALGORITMOS E PROGRAMAÇÃO
ESTRUTURADA

la fora de qualquer função, tornando-a visível para todas as funções do programa. Por
convenção, optamos por declará-las logo após a inclusão das bibliotecas.

No Quadro 2, é apresentado um exemplo de declaração de uma variável global na linha 2, logo


após a inclusão da biblioteca padrão <stdio.h>. É importante observar que na função principal
não há nenhuma variável definida com o nome "x", no entanto, é possível imprimir o valor da
variável global “x” na linha 7, uma vez que o valor é acessado globalmente. Na linha 8, é exibido o
valor da variável global que foi modificado pela função "dobrar()", que retorna o dobro do valor.

1: #include <stdio.h>
2: int x = 10;
3: int dobrar(){
4: return 2 * x;
5: }
6: int main(){
7: printf("\n Valor de x global = %d", x);
8: printf("\n Valor de x global alterado na
9: função dobrar() = %d", dobrar());
10: return 0;
11: }

Quadro 2 | Exemplo de variável global em C.

Uso de variáveis globais


O uso de variáveis globais permite otimizar a alocação de memória, já que, em muitos casos, o
desenvolvedor não necessita criar variáveis locais. No entanto, é fundamental ter cautela ao
utilizar essa técnica, uma vez que as variáveis locais são criadas e destruídas ao final da função,
enquanto as variáveis globais permanecem na memória durante todo o período de execução do
programa.

Vamos considerar um exemplo prático que demonstra a utilização do escopo global de uma
variável. No Quadro 3 temos um programa que calcula a média entre duas temperaturas distintas
e que possui a declaração de duas variáveis globais na linha 2. É importante lembrar que o
programa começa sempre pela função principal, cuja execução tem início na linha 6. Na linha 7, o
usuário é solicitado a digitar duas temperaturas, que são armazenadas dentro das variáveis
globais criadas. Na linha 9, a função "calcularMedia()" é chamada para realizar o cálculo da
média usando os valores das variáveis globais. Neste exemplo, fica evidente a utilidade dessa
abordagem de programação, já que as variáveis são usadas em diferentes funções, otimizando o
uso da memória, uma vez que não é necessário criar mais variáveis locais em cada uma das
funções.
Disciplina

ALGORITMOS E PROGRAMAÇÃO
ESTRUTURADA

1: #include <stdio.h>
2: float t1, t2;
3: float calcularMedia(){
4: return (t1 + t2) / 2;
5: }
6: int main(){
7: printf("\n Digite as duas temperaturas: ");
8: scanf("%f %f", &t1, &t2);
9: printf("\n A temperatura média = %.2f",
10: calcularMedia());
11: return 0;
}

Quadro 3 | Exemplo prático de variável global em C.

Nós já vimos que é viável criar variáveis com o mesmo nome em diferentes funções, visto que o
escopo delas é local. Entretanto, e se houver uma variável global e uma local com o mesmo
nome, como no exemplo a seguir?

int x = 10;
int main(){
int x = -1;
printf("\n Valor de x = %d", x);
}

Qual valor será impresso na variável "x"? A variável local sempre substituirá o valor da global, e,
nesse caso, o valor -1 será impresso na função principal.

Mas e se você precisar acessar o valor de uma variável global dentro de uma função que possui
uma variável local com o mesmo nome? Neste caso, é necessário utilizar a instrução "extern". No
Quadro 4, é possível observar como usar variáveis globais e locais com o mesmo nome na
linguagem C. Note que foi preciso criar uma variável chamada "b", com um bloco de instruções
(linhas 6 – 9), que atribui o valor "externo" de "x" à nova variável. A criação do bloco é necessário
para separar o trecho de código do restante da função main(), indicando que ali, a variável “x”
utilizada é a global (extern int x).

1: #include <stdio.h>
2: int x = 10;
3: int main(){
4: int x = -1;
5: int b;
6: {
Disciplina

ALGORITMOS E PROGRAMAÇÃO
ESTRUTURADA

7: extern int x;
8: b = x;
9: }
10: printf(“\n Valor de x = %d”, x);
11: printf(“\n Valor de b (x global) = %d”, b);
12: return 0;
13: }

Quadro 4 | Exemplo de acesso a uma variável global com extern em C.

Siga em Frente...

Passagem de parâmetros por valor


Vamos relembrar que, ao criar funções em linguagens de programação, usamos a seguinte
estrutura básica:

<tipo de retorno> <nome_da_função> (<parâmetros>)


{
<Comandos da função>
<Retorno> (opcional)
}

Todos os elementos dessa estrutura já foram apresentados detalhadamente até aqui, exceto os
tipos de parâmetros que uma função pode receber. Portanto, neste momento, vamos nos
concentrar em compreender esse recurso fundamental.

Ao definir uma função, podemos também especificar que ela receberá informações do chamador
(ou seja, “de quem” a invocou). Por exemplo, ao criar uma função para calcular a média, é
possível estabelecer que o chamador (“quem chama”) deve fornecer os valores sobre os quais o
cálculo será realizado.

Na sintaxe de criação de uma função que recebe parâmetros, é fundamental especificar o tipo de
valor que será recebido. Uma função pode receber parâmetros na forma de valor ou referência.
Ao passar parâmetros por valores, a função cria automaticamente variáveis locais para
armazenar esses valores e, após a conclusão da função, essas variáveis são liberadas. A Figura 1
apresenta uma ilustração do processo de passagem de parâmetros por valor em uma função.
Disciplina

ALGORITMOS E PROGRAMAÇÃO
ESTRUTURADA

Figura 1 | Processo de passagem de parâmetros por valor.

No Quadro 5, é apresentado um exemplo de definição e chamada de função com passagem de


valores. Na linha 2, a função "somar()" é definida para receber dois valores inteiros. Internamente,
as variáveis locais "a" e "b" são criadas para armazenar esses valores até o término da função. Na
linha 7, a função "somar" é invocada/chamada, passando os dois valores inteiros que a função
espera receber, e o resultado do cálculo é armazenado na variável "res".

1: #include <stdio.h>
2: int somar(int a, int b){
3: return a + b;
4: }
5: int main(){
6: int re;
7: res = somar(10, 15);
8: printf("\n Resultado da soma = %d", res);
9: return 0;
10: }

Quadro 5 | Exemplo de passagem de parâmetros por valor.

A técnica de passagem de parâmetros para uma função é amplamente utilizada em todas as


linguagens de programação. Ao chamar uma função que espera receber parâmetros, a omissão
de qualquer argumento esperado resultará em um erro de compilação.

Quando usamos variáveis como argumentos na passagem de parâmetros por valores, as


variáveis originais não são modificadas, uma vez que uma cópia dos valores armazenados é
fornecida à função. Para entender claramente essa definição, consideremos o código
apresentado no Quadro 6. A execução do programa começa na linha 9, na função principal, em
Disciplina

ALGORITMOS E PROGRAMAÇÃO
ESTRUTURADA

que são criadas duas variáveis, "n1" e "n2". Na linha 13, o comando determina a impressão dos
valores das variáveis. Em seguida, na linha 14, a função "testar()" é invocada, passando as duas
variáveis como parâmetros. Nesse momento, uma cópia de cada variável é criada na memória
para o uso da função. Dentro da função, o valor das cópias das variáveis é alterado e impresso,
porém essa alteração é local, ou seja, é realizada apenas nas cópias dos valores e não afetará os
valores iniciais das variáveis criadas na função principal. Na linha 16, os valores são impressos
novamente após a chamada da função.

1: #include <stdio.h>
2: int testar(int n1, int n2){
3: n1 = -1;
4: n2 = -2;
5: printf("\n\n Valores dentro da função
6: testar(): ");
7: printf("\n n1 = %d e n2 = %d", n1, n2);
8: return 0;
9: }
10: int main(){
11: int n1 = 10;
12: int n2 = 20;
13: printf("\n\n Valores antes de chamar a
14: função: ");
15: printf("\n n1 = %d e n2 = %d", n1, n2);
16: testar(n1, n2);
17: printf("\n\n Valores depois de chamar a
18: função: ");
printf("\n n1 = %d e n2 = %d", n1, n2);
return 0;
}

Quadro 6 | Exemplo de passagem de parâmetros por valor.

A seguir, a Figura 2 apresenta o resultado deste programa.


Disciplina

ALGORITMOS E PROGRAMAÇÃO
ESTRUTURADA

Figura 2 | Resultado do programa do Quadro 6.

Vamos Exercitar?

Prezado estudante, é hora de aplicar todo o conhecimento adquirido até aqui! Para implementar
a solução para a equipe de química, é possível criar uma função que tome como entrada a
quantidade em mol dos componentes A e B e retorne a massa da reação.

O passo inicial consiste em criar a função de cálculo da massa. Ela pode ser definida da seguinte
maneira:

float calcularMassa(float quantidadeA, float quantidadeB)

Dentro dessa função, os valores de referência devem ser exibidos de acordo com a Tabela 1. A
massa deve ser calculada e o resultado deve ser retornado.

Em seguida, é necessário criar a função principal, na qual o usuário será solicitado a fornecer as
quantidades dos elementos A e B. Uma vez que os valores forem obtidos, a função
“calcularMassa()” deve ser chamada e os valores devem ser passados como argumentos.

O resultado da função deve ser armazenado em uma variável, da seguinte maneira:

resultado = calcularMassa(quantidadeA, quantidadeB)


Disciplina

ALGORITMOS E PROGRAMAÇÃO
ESTRUTURADA

Por último, a massa da reação deve ser exibida.

O Quadro 7 apresenta uma sugestão de resolução da situação.

1: #include <stdio.h>
2: float calcularMassa(float a, float b){
3: const float mA = 321.43;
4: const float mB = 150.72;
5: printf("\n mol A : mol B ");
6: printf("\n 1,2 : 1,0 \t= %f",1.2*mA + 1*mB);
7: printf("\n 1,4 : 1,0 \t= %f",1.4*mA + 1*mB);
8: printf("\n 1,6 : 1,0 \t= %f",1*mA + 1.6*mB);
9: return (a * mA ) + (b * mB);
10: }
11: int main(){
12: float a = 0, b = 0, resultado = 0;
13: printf("\n Digite as massas dos elementos A
14: e B: ");
15: scanf("%f %f",&a,&b);
16: resultado = calcularMassa(a,b);
17: printf("\n\n Massa final do composto = %.2f
18: g/mol",resultado);
return 0;
}

Quadro 7 | Código de resolução.

Lembrando que não há uma única resposta correta. Há vários caminhos para se chegar no
mesmo resultado! Modifique e tente otimizar ao máximo os seus programas.

Saiba mais

Para entender melhor o conceito de funções e parâmetros em C, sugerimos a leitura do Capítulo


5 funções e Procedimentos, do livro Linguagem C, disponível na Biblioteca Virtual.

DAMAS, L. Linguagem C. 10. ed. Rio de Janeiro: LTC, 2023. cap. 5, p. 104-128.

Também recomendamos a leitura do Capítulo 9 - PAssagem de Parâmetors, do mesmo livro,


Linguagem C, disponível na Biblioteca Virtual. Ele traz um estudo mais detalhado sobre
passagem de parâmetros em C.

DAMAS, L. Linguagem C. 10. ed. Rio de Janeiro: LTC, 2023. cap. 9, p. 203-227.
Disciplina

ALGORITMOS E PROGRAMAÇÃO
ESTRUTURADA

Sugerimos a leitura do Capítulo 9 - Funções do livro Linguagem C: Completa e Descomplicada,


disponível na Biblioteca Virtual, para complementar os estudos sobre funções e parâmetros em
C.

BACKES, A. Linguagem C: completa e descomplicada. 2. ed. Rio de Janeiro: LTC, 2023. cap. 9, p.
158-193.

Referências

BACKES, A. Linguagem C: completa e descomplicada. 2. ed. Rio de Janeiro: LTC, 2023. cap. 4, p.
67-87.

DAMAS, L. Linguagem C. 10. ed. Rio de Janeiro: LTC, 2023. cap. 3, p. 51-79.

PIVA JUNIOR, D. Algoritmos e programação de computadores. 2. ed. Rio de Janeiro: Elsevier,


2019.

Aula 3
Passagem de Parâmetros por Referência

Passagem de parâmetros por referência

Este conteúdo é um vídeo!


Para assistir este conteúdo é necessário que você acesse o AVA pelo
computador ou pelo aplicativo. Você pode baixar os vídeos direto no aplicativo
para assistir mesmo sem conexão à internet.
Dica para você
Aproveite o acesso para baixar os slides do vídeo, isso pode deixar sua
aprendizagem ainda mais completa.

Estudante, esta videoaula foi preparada especialmente para você. Nela, você irá aprender
conteúdos importantes para a sua formação profissional. Vamos assisti-la?
Disciplina

ALGORITMOS E PROGRAMAÇÃO
ESTRUTURADA

Ponto de Partida

Olá! Vamos prosseguir nossos estudos sobre procedimentos e funções conhecendo um pouco
mais sobre como trabalhar com passagem de parâmetros por referência!

Vamos considerar que você tem um amigo que possui loja que vende diferentes tipos de
produtos, e ele te pediu uma ajuda! Seu amigo precisa de um programa em C para calcular o
preço total de uma compra, levando em consideração os preços unitários e as quantidades de
cada item adquirido. O programa deve usar funções para calcular o preço total e passar
parâmetros por referência para garantir a atualização correta das variáveis.

Para cumprir sua missão, você irá aprender sobre a passagem de parâmetros por referência!
Agora vamos lá, preste muita atenção e tenha um excelente estudo!

Vamos Começar!

Passagem por referência com ponteiros


O uso de funções que passam parâmetros por referência está intimamente relacionado aos
conceitos de ponteiros e endereços de memória. A abordagem dessa técnica é semelhante à
passagem por valor, na qual a função é definida para receber determinados parâmetros, e o
chamador deve fornecer esses argumentos. No entanto, o comportamento e o resultado diferem.
Na passagem por referência, não é criada uma cópia dos argumentos passados; em vez disso, o
endereço da variável é passado e a função manipula diretamente os valores armazenados lá.

Para utilizar essa abordagem, precisamos dos operadores * e &. Na definição da função, os
parâmetros a serem recebidos devem ser declarados com *, por exemplo:

int testar(int* parametro1, int* parametro2)

E ao chamar a função, os parâmetros devem ser passados com &, por exemplo:

resultado = testar(&n1, &n2)

No exemplo apresentado no Quadro 1, temos uma função que passa variáveis por referência.
Com a passagem por referência, os valores das variáveis são modificados. Nas linhas 3 e 4, o
asterisco é usado para acessar o conteúdo armazenado dentro do endereço apontado, pois se
usássemos apenas n1 e n2, estaríamos acessando os endereços que eles apontam.
Disciplina

ALGORITMOS E PROGRAMAÇÃO
ESTRUTURADA

1: #include <stdio.h>
2: int testar(int* n1, int* n2) {
3: *n1 = -1; // é necessário usar * para acessar
4: o conteúdo
5: *n2 = -2;
6: printf("\n\n Valores dentro da função
7: testar(): ");
8: printf("\n n1 = %d e n2 = %d", *n1, *n2);
9: return 0;
10: }
11: int main() {
12: int n1 = 10;
13: int n2 = 20;
14: printf("\n\n Valores antes de chamar a
15: função: ");
16: printf("\n n1 = %d e n2 = %d", n1, n2);
17: testar(&n1, &n2);
18: printf("\n\n Valores depois de chamar a
função: ");
printf("\n n1 = %d e n2 = %d", n1, n2);
return 0;
}

Quadro 1 | Exemplo de passagem de parâmetros por referência.

Neste exemplo, a função testar() recebe dois argumentos que são ponteiros para inteiros. Dentro
da função, os valores apontados por esses ponteiros são alterados para -1 e -2, respectivamente.
A seguir, a Figura 1 apresenta o resultado deste programa, ilustrando como os valores das
variáveis mudam antes e depois da chamada da função testar.
Disciplina

ALGORITMOS E PROGRAMAÇÃO
ESTRUTURADA

Figura 1 | Resultado do programa do Quadro 1.

A passagem de parâmetros por referência possui várias vantagens e desvantagens que afetam a
eficiência e o desempenho de um programa. Uma das principais vantagens é a capacidade de
transmitir uma grande quantidade de dados para outras partes do programa. Em vez de fazer
cópias dos dados e transmitir essas cópias, é possível passar apenas um ponteiro para esses
dados, o que economiza tempo, processamento e memória. Além disso, essa abordagem
permite a alteração de uma variável ou um objeto externo a uma função, o que possibilita que
uma função gere vários valores de saída.

Por outro lado, a passagem por referência pode comprometer a segurança, já que a função
chamada pode corromper os dados do chamador. Assim, é essencial ter cuidado ao utilizar a
passagem por referência para garantir que os dados não sejam modificados indevidamente por
funções chamadas.

Passagem de vetores e matrizes


Agora, vamos compreender como passar um vetor para uma função, para que possamos
preencher e imprimir o conteúdo armazenado em um vetor, evitando a repetição de trechos de
código. Na linguagem C, a passagem de um vetor é sempre realizada implicitamente por
referência. Isso implica que, mesmo sem o uso dos operadores "*" e "&", quando uma função que
recebe um vetor é invocada, o que é realmente passado é o endereço da primeira posição do
vetor.

Na definição da função, os vetores a serem recebidos devem ser declarados com colchetes, sem
especificar o tamanho, por exemplo:
Disciplina

ALGORITMOS E PROGRAMAÇÃO
ESTRUTURADA

int testar1(int v1[ ], int v2[ ])

Ou ainda, você pode especificar os parâmetros da função como ponteiros:

int testar2(int *v1, int *v2)

Ao chamar a função, independente da forma escolhida para definir os vetores nos parâmetros,
estes devem ser passados como se fossem variáveis simples, por exemplo:

resultado1 = testar1(n1, n2);


resultado2 = testar2(n1, n2);

Para ilustrar esse conceito, é apresentado um programa no Quadro 2, iniciando na linha 15. Na
linha 18, a função “inserir()” é chamada, passando o vetor "numeros" como parâmetro.
Deliberadamente, a função é definida na linha 2, recebendo um vetor chamado "a", para
demonstrar que o nome da variável na função não precisa ser o mesmo usado na chamada.
Geralmente, é uma boa prática de programação utilizar o mesmo nome. Na função “inserir()”, é
solicitado ao usuário digitar os valores que serão armazenados no vetor "numeros" por
referência. Após a conclusão dessa função, a execução continua na linha 18 e depois na 19, na
qual a função “imprimir()” é invocada, passando o vetor "numeros" como argumento. Mais uma
vez, é definida uma função na linha 9 com o nome de vetor diferente para enfatizar que não é
necessário ser o mesmo nome. Nessa função, o vetor é percorrido e o dobro de cada valor é
impresso. O resultado desse programa é ilustrado na Figura 2.

1: #include <stdio.h>
2: void inserir(int a[]){
3: int i=0;
4: for(i=0; i<3; i++){
5: printf("Digite o valor %d: ", i);
6: scanf("%d", &a[i]);
7: }
8: }
9: void imprimir(int b[]){
10: int i=0;
11: for(i=0; i<3; i++){
12: printf("\n numeros[%d] = %d", i, 2 * b[i]);
13: }
14: }
15: int main(){
16: int numeros[3];
Disciplina

ALGORITMOS E PROGRAMAÇÃO
ESTRUTURADA

17: printf("\n Preenchendo o vetor... \n");


18: inserir(numeros);
19: printf("\n Dobro dos valores informados:");
20: imprimir(numeros);
21: return 0;
22: }

Quadro 2 | Exemplo de passagem de vetor para uma função.

Figura 2 | Resultado do programa do Quadro 2.

Podemos também passar matrizes como parâmetros para funções de semelhante à passagem
de vetores, mas requer um detalhe específico na sintaxe devido à natureza multidimensional das
matrizes. Devemos especificar suas dimensões na definição dos parâmetros da função, por
exemplo:

void testeMatriz(int mat[3][3])

E quando esta função for chamada, a matriz passada na função não precisa ir acompanhada de
suas dimensões (já que eles já estão especificados nos parâmetros da função):
Disciplina

ALGORITMOS E PROGRAMAÇÃO
ESTRUTURADA

testeMatriz(m); //onde m é uma matriz

Alternativamente, uma matriz pode ser definida como parâmetro de uma função como “int mat[ ]
[3]”, onde “[3]” é o número de colunas e o número de linhas não é especificado. Isso permite a
passagem de matrizes de diferentes tamanhos como argumentos.

Siga em Frente...

Passagem de estruturas por referência


Em C, a passagem de estruturas (structs) por referência é feita usando ponteiros, da mesma
forma que variáveis comuns. Ao passar uma estrutura como parâmetro para uma função, é
passado o endereço de memória da estrutura, permitindo que a função manipule e altere os
valores dos membros da estrutura original. Isso evita a cópia desnecessária da estrutura, o que
pode ser útil para estruturas grandes ou complexas, economizando memória e tempo de
processamento.

Para passar uma estrutura por referência em C, é necessário usar um ponteiro para a estrutura
como parâmetro da função. Dentro da função, os membros da estrutura podem ser acessados e
modificados usando a notação de seta "->" em função de ser um ponteiro.

O Quadro 3 mostra um exemplo de como passar uma struct por referência.

1: #include <stdio.h>
2: struct Pessoa {
3: char nome[50];
4: int idade;
5: };
6: void modificarPessoa(struct Pessoa *p) {
7: p->idade = 30;
8: }
9:
10: int main() {
11: struct Pessoa pessoa1;
12: strcpy([Link], "João");
13: [Link] = 25;
14:
15: modificarPessoa(&pessoa1);
16:
17: printf("Nome: %s\n", [Link]);
18: printf("Idade: %d\n", [Link]);
Disciplina

ALGORITMOS E PROGRAMAÇÃO
ESTRUTURADA

19:
20: return 0;
21: }

Quadro 3 | Exemplo de passagem de struct por referência.

Neste exemplo, a função “modificarPessoa” recebe um ponteiro para uma estrutura “struct
Pessoa” como parâmetro. Dentro da função, o valor do membro "idade" é modificado para 30. A
estrutura é passada para a função usando o operador de referência "&" na chamada da função. A
impressão dos valores da estrutura após a modificação mostra que a estrutura original foi de
fato alterada dentro da função.

Vamos Exercitar?
Prezado estudante, é hora de aplicar todo o conhecimento adquirido até aqui! Para implementar
a solução para a loja do seu amigo você precisará trabalhar com a passagem de parâmetros por
referência! O Quadro 4 apresenta uma sugestão de resolução da situação.

1: #include <stdio.h>
2: void calcularPrecoTotal(float precoUnitario[],
3: int quantidade[], int numItens, float
4: *precoTotal) {
5: *precoTotal = 0;
6: for (int i = 0; i < numItens; i++) {
7: *precoTotal += precoUnitario[i] *
8: quantidade[i];
9: }
10: }
11: int main() {
12: int numItens;
13: printf(" Digite o número de itens comprados:
14: ");
15: scanf("%d", &numItens);
16: float precoUnitario[numItens];
17: int quantidade[numItens];
18: float precoTotal;
19: // Entrada dos preços unitários e
20: quantidades de cada item
21: for (int i = 0; i < numItens; i++) {
22: printf("\n Digite o preço unitário do item
23: %d: ", i + 1);
24: scanf("%f", &precoUnitario[i]);
Disciplina

ALGORITMOS E PROGRAMAÇÃO
ESTRUTURADA

25: printf(" Digite a quantidade do item %d: ", i


26: + 1);
27: scanf("%d", &quantidade[i]);
28: }
29: // Chamada da função para calcular o preço
30: total
calcularPrecoTotal(precoUnitario,
quantidade, numItens, &precoTotal);
// Exibindo o preço total da compra
printf("\n Preço total da compra: R$
%.2f\n\n", precoTotal);

return 0;
}

Quadro 4 | Código de resolução.

A seguir, seguem alguns detalhes da implementação do Quadro 4.

A função calcularPrecoTotal é usada para calcular o preço total da compra, considerando


os preços unitários e as quantidades de cada item.
Os vetores precoUnitario e a quantidade são passados por referência para a função para
garantir a atualização correta das variáveis.
O programa solicita ao usuário o número de itens comprados e depois solicita o preço
unitário e a quantidade de cada item. Em seguida, ele chama a função calcularPrecoTotal
para calcular o preço total da compra e, em seguida, exibe o preço total na saída.
A passagem de parâmetros por referência neste caso torna o programa mais eficiente, pois
permite que as variáveis sejam atualizadas diretamente na função chamadora sem a
necessidade de retornar valores, além de possibilitar a passagem de vetores e matrizes.

Lembrando que não há uma única resposta correta. Há vários caminhos para se chegar no
mesmo resultado! Modifique e tente otimizar ao máximo os seus programas.

Saiba mais

Para entender melhor o conceito de funções e parâmetros em C, sugerimos a leitura do Capítulo


5 - Funções e Procedimentos, do livro Linguagem C, disponível na Biblioteca Virtual.

DAMAS, L. Linguagem C. 10. ed. Rio de Janeiro: LTC, 2023. cap. 5, p.104-128.

Também recomendamos a leitura do Capítulo 9 - Passagem de Parâmetros, do mesmo livro,


Linguagem C, disponível na Biblioteca Virtual Biblioteca. Ele trás um estudo mais detalhado
Disciplina

ALGORITMOS E PROGRAMAÇÃO
ESTRUTURADA

sobre passagem de parâmetros em C.

DAMAS, L. Linguagem C. 10. ed. Rio de Janeiro: LTC, 2023. cap. 9, p. 203-227.

Sugerimos a leitura do Capítulo 9 do livro Linguagem C: Completa e Descomplicada, disponível


na Biblioteca Virtual, para complementar os estudos sobre funções e parâmetros em C.

BACKES, A. Linguagem C: completa e descomplicada. 2. ed. Rio de Janeiro: LTC, 2023. cap. 9, p.
158-193.

Referências

BACKES, A. Linguagem C: completa e descomplicada. 2. ed. Rio de Janeiro: LTC, 2023. cap. 4, p.
67-87.

DAMAS, L. Linguagem C. 10. ed. Rio de Janeiro: LTC, 2023. cap. 3, p. 51-79.

PIVA JUNIOR, D. Algoritmos e programação de computadores. 2. ed. Rio de Janeiro: Elsevier,


2019.

Aula 4
Recursividade

Recursividade

Este conteúdo é um vídeo!


Para assistir este conteúdo é necessário que você acesse o AVA pelo
computador ou pelo aplicativo. Você pode baixar os vídeos direto no aplicativo
para assistir mesmo sem conexão à internet.
Dica para você
Aproveite o acesso para baixar os slides do vídeo, isso pode deixar sua
aprendizagem ainda mais completa.
Disciplina

ALGORITMOS E PROGRAMAÇÃO
ESTRUTURADA

Estudante, esta videoaula foi preparada especialmente para você. Nela, você irá aprender
conteúdos importantes para a sua formação profissional. Vamos assisti-la?

Ponto de Partida

Olá! Vamos prosseguir nossos estudos sobre procedimentos e funções conhecendo um recurso
poderoso, porém que exige muita cautela: a recursividade!

Após colaborar com as equipes de engenheiros civis e químicos, você está enfrentando um novo
desafio ao trabalhar com a equipe de matemáticos no laboratório. Agora, foi solicitado que você
desenvolva um programa para calcular a raiz quadrada de um número utilizando o método de
aproximações sucessivas de Newton. Os matemáticos contribuíram com a fórmula para essa
tarefa:

2
xn = x + n/2x n−1
n−1

xn

x n−1

Seu gerente, que também é programador, especificou a utilização da técnica de recursividade na


implementação, exigindo que o usuário informe o número para o qual deseja calcular a raiz
quadrada. Quais valores precisam ser informados para que o programa seja executado de
maneira correta? O que determinará o término do cálculo? Esse método exige algum tipo de valor
específico?

Portanto, para realizar essa missão com sucesso, é fundamental entender o conceito de função
recursiva, sua implementação adequada e a relação com as estruturas iterativas. Agora vamos
lá, preste muita atenção e tenha um excelente estudo!

Vamos Começar!

O que é função recursiva?


Dentro do conjunto de funções, existe uma categoria especial conhecida como funções
recursivas. Para adentrarmos nessa nova técnica de programação, é essencial compreender o
conceito de recursão. O termo recursão (ou recursividade) está associado à ideia de repetição de
uma situação específica. Ao aplicarmos esse conceito ao contexto da programação, nos
deparamos com as funções recursivas. Nessa abordagem, uma função é considerada recursiva
quando ela faz referência a si mesma, ou seja, recursividade é a capacidade de uma função
chamar a si mesma.
Disciplina

ALGORITMOS E PROGRAMAÇÃO
ESTRUTURADA

A estrutura para implementação de uma função recursiva não difere significativamente das
funções convencionais, pois requer um tipo de retorno, o nome da função, parênteses e
parâmetros, quando necessário. A diferença está no conteúdo da função, pois ela é invocada
dentro de si mesma. No trecho de código abaixo temos a construção da função, bem como o seu
chamado, primeiro na função principal e, em seguida, dentro dela mesma.

<tipo> funcaoRecursiva(){
// comandos
funcaoRecursiva(); // chamando a si própria
// comandos
}
void main(){
// comandos
funcaoRecursiva();
// comandos
}

Apesar da semelhança na estrutura entre funções recursivas e não recursivas, o comportamento


entre elas difere significativamente, e o uso impróprio dessa técnica pode levar a problemas de
consumo excessivo de memória, frequentemente resultando em falhas na aplicação e no
sistema. Para uma compreensão mais completa do processo, é importante destacar alguns
pontos-chave:

A função recursiva chama a si mesma repetidamente até que um ponto de parada seja
alcançado. Esse ponto pode ser definido por meio de uma estrutura condicional ou por um
valor fornecido pelo usuário.
Dentro do corpo de uma função, existem variáveis e comandos que são armazenados na
memória de trabalho. No caso de uma função recursiva, os recursos (variáveis e
comandos) são alocados em locais distintos da memória, resultando na criação de novas
instâncias a cada chamada da função. Portanto, é crucial definir um ponto de parada
adequado.
As variáveis geradas em cada instância da função na memória são independentes. Assim,
mesmo que as variáveis possuam os mesmos nomes, cada uma possui seu próprio
endereço de memória, garantindo que a alteração de valores em uma não afete as outras.

Para facilitar a compreensão desse mecanismo, observe a Figura 1. A instância 1 representa a


primeira chamada da função “funcaoRecursiva()”, que, por sua vez, contém um comando que
invoca a si mesma. Nesse ponto, uma segunda instância da função é criada na memória de
trabalho. Conforme a função continua a se chamar recursivamente, novos espaços de memória
são alocados, cada um contendo suas próprias variáveis e comandos. No entanto, quando uma
determinada condição de parada é atingida dentro da terceira instância, a função deixa de ser
chamada e passa a retornar valores para as instâncias anteriores.
Disciplina

ALGORITMOS E PROGRAMAÇÃO
ESTRUTURADA

Figura 1 | Mecanismo de uma função recursiva na memória.

Quando a função recursiva atinge o ponto de parada, cada execução subsequente passa a
devolver seus resultados à execução anterior. No exemplo da Figura 2, a execução três retorna à
execução dois, que por sua vez retorna à execução um. É importante notar que, caso o ponto de
parada não fosse especificado na última chamada, a função se instanciaria continuamente,
resultando em um estouro de memória.

Toda função recursiva necessita obrigatoriamente de uma instância que determine o


encerramento das chamadas subsequentes, denominada caso base. Este representa o cenário
mais simples que leva à interrupção do processo.

Refletindo sobre isso, é obrigatório para qualquer função recursiva ter um critério de parada bem
definido. A instância que satisfaz esse critério é conhecida como caso base. Um programador
que erroneamente implementa o critério de parada pode ocasionar um erro apenas na aplicação
dessa função específica, ou tal erro pode impactar outras partes do sistema.

Como funciona a recursividade


Para ilustrar como funciona uma função recursiva, considere a implementação de uma função
recursiva que calcula a soma dos antecessores de um número inteiro positivo inserido pelo
usuário. Por exemplo, se o usuário inserir 5, o programa deve calcular a soma 5 + 4 + 3 + 2 + 1 +
0. Neste caso, o critério de parada é alcançado quando o parâmetro de soma atinge o valor zero,
significando que todos os números anteriores já foram considerados para o cálculo. A
implementação da função pode ser visualizada no Quadro 1, seguida pela explicação.

1: #include <stdio.h>
2: int somar(int valor) {
3: if (valor != 0) { // Critério de parada
4: return valor + somar(valor - 1); // Chamada
5: recursiva
Disciplina

ALGORITMOS E PROGRAMAÇÃO
ESTRUTURADA

6: } else {
7: return valor;
8: }
9: }
10: int main() {
11: int n, resultado;
12: printf("\nDigite um numero inteiro positivo:
13: ");
14: scanf("%d", &n);
15: resultado = somar(n); // Fazendo a primeira
16: chamada da função
printf("\nResultado da soma = %d",
resultado);
return 0;
}

Quadro 1 | Exemplo de função recursiva.

A execução do programa no Quadro 1 tem início na linha 9, pela função principal. Ao chegar na
linha 13, a função “somar()” é chamada, recebendo como argumento um número inteiro inserido
pelo usuário. Nesse ponto, a execução se desloca para a linha 2, onde a função é definida. Nota-
se que a função é configurada para retornar e receber valores inteiros. Na linha 3, é utilizado um
condicional como critério de parada. Se o valor for diferente (!=) de zero, a execução segue para a
linha 4, na qual a função é chamada novamente, desta vez com o parâmetro sendo o valor
reduzido em 1. Quando o valor atinge zero, as instâncias começam a retornar o valor para a
instância que as chamou.

Para ilustrar, a Figura 2 demonstra o processo na memória de trabalho da função “somar()”.


Neste exemplo, o usuário inseriu o valor 2, resultando na invocação da função “somar(2)” pela
função main(). A primeira instância é criada com o parâmetro 2. Como o valor é diferente de zero
nessa instância, o critério de parada não é satisfeito, e a função se chama a si mesma, criando a
segunda instância com o parâmetro 1.

Figura 2 | Exemplo da função somar() do Quadro 1.


Disciplina

ALGORITMOS E PROGRAMAÇÃO
ESTRUTURADA

Observa-se que, na primeira instância, o valor a ser retornado é 2 + ?, pois o resultado da função
ainda não é conhecido. Na segunda instância, o valor também difere de zero, levando à chamada
recursiva com o parâmetro zero (valor - 1). Nesse ponto, o retorno é 1 + ?, pois o resultado da
função ainda não é determinado. Na terceira instância, o critério de parada é alcançado, e a
função retorna zero. Este valor é utilizado pela instância anterior, que, ao somar 1 + 0, retorna seu
resultado para a instância 1, que por sua vez soma 2 + 1 e retorna o valor à função principal,
encerrando o ciclo de recursividade.

1: #include <stdio.h>
2: int somar(int valor) {
3: if (valor != 0) { // Critério de parada
4: return valor + somar(valor - 1); // Chamada
5: recursiva
6: } else {
7: return valor;
8: }
9: }
10: int main() {
11: int n, resultado;
12: printf("\nDigite um numero inteiro positivo:
13: ");
14: scanf("%d", &n);
15: resultado = somar(n); // Fazendo a primeira
16: chamada da função
printf("\nResultado da soma = %d",
resultado);
return 0;
}

Quadro 1 | Exemplo de função recursiva.

Vamos agora analisar o exemplo clássico da recursividade: o cálculo do fatorial! O fatorial de um


número N é obtido por meio de multiplicações sucessivas até que N seja igual a 1, representado
como N! = N * (N-1) * (N-2) * ... * 2 * 1. Por exemplo, 5! = 5*4*3*2*1 = 120. A seguir está o código,
no Quadro 2, que implementa essa solução utilizando uma função recursiva, seguido pela
explicação.

1: #include <stdio.h>
2: int fatorial(int valor) {
3: if (valor > 0) { // Critério de parada
4: return valor * fatorial(valor - 1); //
5: Chamada recursiva
6: } else {
Disciplina

ALGORITMOS E PROGRAMAÇÃO
ESTRUTURADA

7: return 1;
8: }
9: }
10: int main() {
11: int n, resultado;
12: printf("\nDigite um numero inteiro positivo:
13: ");
14: scanf("%d", &n);
15: resultado = fatorial(n);
16: printf("\nResultado do fatorial = %d",
resultado);
return 0;
}

Quadro 2 | Cálculo do fatorial com uma função recursiva.

A execução do código no Quadro 2 inicia pela função main(), que solicita um número ao usuário
e, na linha 13, invoca a função “fatorial()”, passando o valor digitado como parâmetro. Dentro da
função “fatorial()”, enquanto o valor for maior que 0, a função chama a si mesma, criando novas
instâncias na memória, passando, a cada vez, o valor decrementado de 1. Quando o valor chega
a 0, a função retorna 1 e este valor é retornado à multiplicação dos valores encontrados em cada
instância. Isso porque 0! é o caso mais básico, o qual nós sabemos que é igual a 1 sem fazer
qualquer tipo de conta, ou seja, o caso base!

Para uma melhor compreensão, a Figura 3 ilustra as instâncias quando o usuário digita o número
2. Os resultados só são obtidos quando a função atinge o caso base e, então, inicia o processo
de "devolução" do resultado para a instância anterior.

Figura 3 | Exemplo da função fatorial() do Quadro 2.

Siga em Frente...
Disciplina

ALGORITMOS E PROGRAMAÇÃO
ESTRUTURADA

Cuidados na implementação da recursividade


Agora, uma pergunta para você: Daria para refazer o programa do Quadro 1 sem recursividade,
apenas com um laço simples? Sim! Uma das principais dúvidas entre os programadores está
justamente na escolha entre o uso de recursividade e as estruturas de repetição. No caso da
função “somar()” apresentada no Quadro 1, seria possível substituí-la por uma estrutura de
repetição, como exemplificado a seguir:

for (i = 0; i <= 2; i++) {


resultado = resultado + i;
}

De fato, a substituição é viável. A técnica de recursividade pode ser empregada para substituir
estruturas de repetição, conferindo uma elegância ao código sob a perspectiva das boas práticas
de programação. No entanto, como mencionado anteriormente, funções recursivas têm o
potencial de consumir mais memória em comparação com abordagens iterativas.

Para esclarecer o momento adequado para escolher a recursividade, podemos nos valer de
algumas orientações: muitos problemas exibem a propriedade de possuir uma estrutura
recursiva, na qual cada instância do problema contém uma versão menor do mesmo problema.
Nesses casos, o método recomendado é:

Resolver diretamente a instância do problema se ela for pequena, utilizando força bruta se
necessário.
Caso contrário, reduzir a instância para uma versão menor do mesmo problema, aplicar o
método à instância menor e, em seguida, retornar à instância original.

A aplicação desse método resulta em um algoritmo recursivo, indicando a capacidade de um


problema maior ser decomposto em instâncias menores. Contudo, é crucial considerar os
recursos computacionais envolvidos em cada método ao optar pela recursividade.

Vamos Exercitar?
Prezado estudante, é hora de aplicar todo o conhecimento adquirido até aqui! Para implementar
a solução, é necessário desenvolver um programa que solicite ao usuário um número,
especifique um valor inicial para a raiz e um critério de parada. Após pesquisa, constatou-se que
o método iterativo de Newton envolve comparações entre os resultados obtidos em cada
instância. A comparação entre o valor calculado da raiz e o obtido no passo anterior é realizada
até que a diferença entre eles seja menor que o critério de parada. Para isso, as funções “fabs()”
e “pow()”, pertencentes à biblioteca “math.h”, são utilizadas. A primeira retorna o valor absoluto
de um número, enquanto a segunda é empregada para potenciação.
Disciplina

ALGORITMOS E PROGRAMAÇÃO
ESTRUTURADA

Adotando a metade do valor informado pelo usuário como valor inicial e 0.001 como critério de
parada, quanto menor o valor do critério, mais preciso será o cálculo. Os passos para a
implementação são os seguintes:

Crie a função calcularRaiz(), que recebe dois parâmetros: o valor a ser calculado e a raiz
anterior, inicialmente definida como o chute inicial.
Implemente a fórmula sugerida pelos matemáticos usando a função pow().
Calcule a diferença entre o valor obtido no passo 2 e o valor da raiz anterior e verifique se é
menor que o critério de parada:
Se for o caso, o valor é satisfatório e pode ser retornado. Caso contrário, a função
calcularRaiz() deve ser chamada novamente, passando como parâmetro o número e a raiz
obtida no passo 2.

O Quadro 3 apresenta uma sugestão de resolução da situação.

1: #include <stdio.h>
2: #include <math.h>
3: float calcularRaiz(float n, float raizAnt) {
4: float raiz = (pow(raizAnt, 2) + n) / (2 *
5: raizAnt);
6: if (fabs(raiz - raizAnt) < 0.001)
7: return raiz;
8: return calcularRaiz(n, raiz);
9: }
10: void main() {
11: float numero, raiz;
12: printf("\nDigite um número para calcular a
13: raiz: ");
14: scanf("%f", &numero);
15: raiz = calcularRaiz(numero, numero / 2);
printf("\nRaiz quadrada: %f", raiz);
}

Quadro 3 | Código de resolução.

Lembrando que não há uma única resposta correta. Há vários caminhos para se chegar no
mesmo resultado! Tente sempre otimizar ao máximo os seus programas.

Saiba mais

Para entender melhor o conceito de recursividade em C, sugerimos a leitura do Capítulo 9


Passagem de Parâmetros a partir da página 219 (tópico: Recursividade), do livro Linguagem C,
Disciplina

ALGORITMOS E PROGRAMAÇÃO
ESTRUTURADA

disponível na Biblioteca Virtual.

DAMAS, L. Linguagem C. 10. ed. Rio de Janeiro: LTC, 2023. cap. 9, p. 203-227.

Sugerimos a leitura do Capítulo 9 - Funções, do livro Linguagem C: Completa e Descomplicada,


disponível na Biblioteca Virtual, para complementar os estudos sobre recursividade em C.

BACKES, A. Linguagem C: completa e descomplicada. 2. ed. Rio de Janeiro: LTC, 2023. cap. 9, p.
158-193.

Recomendamos o acesso e estudo do conteúdo web no link a seguir, do portal Khan Academy,
que possui várias lições, explicações e vários desafios acerca de recursividade. Vale a pena
conferir!

Referências

BACKES, A. Linguagem C: completa e descomplicada. 2. ed. Rio de Janeiro: LTC, 2023. cap. 4, p.
67-87.

DAMAS, L. Linguagem C. 10. ed. Rio de Janeiro: LTC, 2023. cap. 3, p. 51-79.

PIVA JUNIOR, D. Algoritmos e programação de computadores. 2. ed. Rio de Janeiro: Elsevier,


2019.

Aula 5
Funções e Passagem de Parâmetros

Videoaula de Encerramento
Disciplina

ALGORITMOS E PROGRAMAÇÃO
ESTRUTURADA

Este conteúdo é um vídeo!


Para assistir este conteúdo é necessário que você acesse o AVA pelo
computador ou pelo aplicativo. Você pode baixar os vídeos direto no aplicativo
para assistir mesmo sem conexão à internet.
Dica para você
Aproveite o acesso para baixar os slides do vídeo, isso pode deixar sua
aprendizagem ainda mais completa.

Estudante, esta videoaula foi preparada especialmente para você. Nela, você irá aprender
conteúdos importantes para a sua formação profissional. Vamos assisti-la?

Ponto de Chegada
Olá, estudante! Para desenvolver a competência desta Unidade, que é “Conhecer os métodos de
funções, recursividade, passagem de dados e parâmetros em algoritmos”, você deve explorar
conceitos fundamentais em programação, concentrando seus estudos em funções e passagem
de parâmetros em linguagem C. Comece por compreender a sintaxe de procedimentos e
funções. Aqui, aprenderemos como organizar blocos de código para realizar tarefas específicas,
tornando o programa mais modular e fácil de manter. Entenderemos como declarar, chamar e
definir procedimentos e funções, e como estas estruturas contribuem para a modularização do
código.

Além disso, estude sobre o escopo de uma função e a distinção entre variáveis globais e locais.
Compreender o escopo é crucial para evitar conflitos entre variáveis e garantir que elas sejam
acessíveis somente onde necessário. Isso não apenas promove a clareza do código, mas
também evita potenciais erros decorrentes de variáveis com nomes idênticos em contextos
diferentes.

Ao avançar nos estudos, é importante compreender a passagem de parâmetros, que são


conceitos fundamentais para a comunicação eficiente entre funções. Explore tanto a passagem
por valor quanto a passagem por referência, entendendo suas implicações no comportamento
do programa. Isso proporcionará uma compreensão mais profunda de como os dados são
transmitidos e manipulados em diferentes contextos.

Finalmente, estudo à fundo as funções recursivas! Entenda o que são e como utilizá-las para
resolver problemas que podem ser decompostos em subproblemas semelhantes. A
recursividade, quando aplicada corretamente, pode simplificar a lógica do código e oferecer
soluções elegantes para desafios complexos.
Disciplina

ALGORITMOS E PROGRAMAÇÃO
ESTRUTURADA

Compreendendo esses tópicos essenciais, você terá dominado os conceitos, os recursos e as


ferramentas fundamentais voltadas para o desenvolvimento de softwares!

É Hora de Praticar!

Este conteúdo é um vídeo!


Para assistir este conteúdo é necessário que você acesse o AVA pelo
computador ou pelo aplicativo. Você pode baixar os vídeos direto no aplicativo
para assistir mesmo sem conexão à internet.

Realize a implementação de um sistema bancário simples em linguagem C, em que cada cliente


possui uma conta com saldo. Desenvolva funções que realizem operações bancárias básicas,
como depósito, saque e transferência, utilizando conceitos avançados de passagem de
parâmetros.

Definição da Estrutura: declare uma estrutura chamada Conta que contenha informações
como número da conta, nome do titular e saldo.
Função para Depósito: crie uma função chamada realizarDeposito que permita ao cliente
realizar um depósito em sua conta. A função deve receber como parâmetros a estrutura da
conta e o valor a ser depositado.
Função para Saque: implemente a função realizarSaque que permita ao cliente fazer um
saque de sua conta. A função deve validar se há saldo suficiente antes de efetuar o saque.
Função para Transferência: desenvolva a função realizarTransferencia que permita
transferir um valor de uma conta para outra. A função deve receber as estruturas de ambas
as contas e o valor a ser transferido.
Apresentação de Resultados: no programa principal (main), crie duas instâncias da
estrutura Conta para representar duas contas diferentes. Solicite ao usuário que realize
operações como depósito, saque e transferência entre as contas. Utilize as funções
desenvolvidas para efetuar as operações e apresente o saldo final das contas após cada
transação.
Tratamento de Erros: implemente mecanismos de tratamento de erros, como a verificação
de saldo insuficiente durante saques e transferências, e mensagens explicativas para o
usuário.

Como a escolha entre usar um procedimento ou uma função pode afetar a estrutura e o
fluxo do seu código?
Como a escolha entre passagem por valor e por referência pode impactar a eficiência e o
comportamento de um programa?
Disciplina

ALGORITMOS E PROGRAMAÇÃO
ESTRUTURADA

Em que situações as funções recursivas podem ser mais vantajosas do que soluções
iterativas?

O código a seguir apresenta uma sugestão de resultado para o problema:


#include <stdio.h>

struct Conta {
int numero;
char titular[50];
float saldo;
};

void realizarDeposito(struct Conta *conta, float valor) {


conta->saldo += valor;
}

int realizarSaque(struct Conta *conta, float valor) {


if (conta->saldo >= valor) {
conta->saldo -= valor;
return 1; // Saque bem-sucedido
} else {
printf("Saldo insuficiente para realizar o saque.\n");
return 0; // Saque mal-sucedido
}
}

int realizarTransferencia(struct Conta *origem, struct Conta *destino, float valor) {


if (realizarSaque(origem, valor)) {
realizarDeposito(destino, valor);
return 1; // Transferência bem-sucedida
} else {
printf("Transferência mal-sucedida.\n");
return 0; // Transferência mal-sucedida
}
}

int main() {
// Criação de duas instâncias da estrutura Conta
struct Conta contas[2] = {{1, "Cliente1", 1000.0},{2, "Cliente2", 500.0}};

int op, cc, cc2;


float valor = 0;

do{
Disciplina

ALGORITMOS E PROGRAMAÇÃO
ESTRUTURADA

printf("\n BOLSOFURADO BANK \n\n");

printf(" Saldo Conta 1: R$%.2f\n", contas[0].saldo);


printf(" Saldo Conta 2: R$%.2f\n\n", contas[1].saldo);

printf(" 1 - Deposito\n");
printf(" 2 - Saque\n");
printf(" 3 - Transferencia\n");
printf(" 4 - Sair\n");

printf("\n Escolha uma opção: ");


scanf("%d", &op);
switch (op)
{
case 1:
printf("\n Qual a conta para deposito? ");
scanf("%d", &cc);
printf(" Qual o valor? ");
scanf("%f", &valor);
realizarDeposito(&contas[cc-1], valor);
break;

case 2:
printf("\n Qual a conta para saque? ");
scanf("%d", &cc);
printf(" Qual o valor? ");
scanf("%f", &valor);
realizarSaque(&contas[cc-1], valor);
break;

case 3:
printf("\n Qual a conta de origem? ");
scanf("%d", &cc);
printf(" Qual a conta de destino? ");
scanf("%d", &cc2);
printf(" Qual o valor? ");
scanf("%f", &valor);
realizarTransferencia(&contas[cc-1], &contas[cc2-1], valor);
break;

default:
break;
}
Disciplina

ALGORITMOS E PROGRAMAÇÃO
ESTRUTURADA

} while(op < 4);

return 0;
}
Não há uma resposta correta. Inclusive, fica o desafio para implementar em cada opção os
mecanismos de tratamento de erros, como a verificação de saldo insuficiente durante saques e
transferências, e mensagens explicativas para o usuário.

O infográfico a seguir ilustra e identifica os conceitos vistos nesta unidade.


Disciplina

ALGORITMOS E PROGRAMAÇÃO
ESTRUTURADA

BACKES, A. Linguagem C: completa e descomplicada. 2. ed. Rio de Janeiro: LTC, 2023.


CORMEN, T. H. Desmistificando algoritmos. 1. ed. Rio de Janeiro: Elsevier, 2014.
Disciplina

ALGORITMOS E PROGRAMAÇÃO
ESTRUTURADA

DAMAS, L. Linguagem C. 10. ed. Rio de Janeiro: LTC, 2023.


MENÉNDEZ, A. Simplificando algoritmos. 1. ed. Rio de Janeiro: LTC, 2023.
PIVA JUNIOR, D. Algoritmos e programação de computadores. 2. ed. Rio de Janeiro: Elsevier,
2019.

Você também pode gostar