Logo Passei Direto
Buscar
Material
páginas com resultados encontrados.
páginas com resultados encontrados.
left-side-bubbles-backgroundright-side-bubbles-background

Crie sua conta grátis para liberar esse material. 🤩

Já tem uma conta?

Ao continuar, você aceita os Termos de Uso e Política de Privacidade

left-side-bubbles-backgroundright-side-bubbles-background

Crie sua conta grátis para liberar esse material. 🤩

Já tem uma conta?

Ao continuar, você aceita os Termos de Uso e Política de Privacidade

left-side-bubbles-backgroundright-side-bubbles-background

Crie sua conta grátis para liberar esse material. 🤩

Já tem uma conta?

Ao continuar, você aceita os Termos de Uso e Política de Privacidade

left-side-bubbles-backgroundright-side-bubbles-background

Crie sua conta grátis para liberar esse material. 🤩

Já tem uma conta?

Ao continuar, você aceita os Termos de Uso e Política de Privacidade

left-side-bubbles-backgroundright-side-bubbles-background

Crie sua conta grátis para liberar esse material. 🤩

Já tem uma conta?

Ao continuar, você aceita os Termos de Uso e Política de Privacidade

left-side-bubbles-backgroundright-side-bubbles-background

Crie sua conta grátis para liberar esse material. 🤩

Já tem uma conta?

Ao continuar, você aceita os Termos de Uso e Política de Privacidade

left-side-bubbles-backgroundright-side-bubbles-background

Crie sua conta grátis para liberar esse material. 🤩

Já tem uma conta?

Ao continuar, você aceita os Termos de Uso e Política de Privacidade

left-side-bubbles-backgroundright-side-bubbles-background

Crie sua conta grátis para liberar esse material. 🤩

Já tem uma conta?

Ao continuar, você aceita os Termos de Uso e Política de Privacidade

left-side-bubbles-backgroundright-side-bubbles-background

Crie sua conta grátis para liberar esse material. 🤩

Já tem uma conta?

Ao continuar, você aceita os Termos de Uso e Política de Privacidade

left-side-bubbles-backgroundright-side-bubbles-background

Crie sua conta grátis para liberar esse material. 🤩

Já tem uma conta?

Ao continuar, você aceita os Termos de Uso e Política de Privacidade

Prévia do material em texto

Algoritmo e programação estruturada
Algoritmo
Os algoritmos são as bases para criação de um programa de computador, onde diversas aplicações poderão ocorrer. Um algoritmo bem estruturado vai gerar um programa para solução de um problema que antes, parecia complexo. Todas as áreas estão voltadas para a tecnologia e são através de diversas formas de pensamentos que os algoritmos são realizados.
· Algoritmo é uma sequência ordenada de passos que deve ser seguida para a realização de uma tarefa (BERG e FIGUEIRÓ, 1998).
Os algoritmos nortearão a descobrir qual o melhor percurso para solucionar um problema computacional.
A elaboração de algoritmos é um passo importante para o desenvolvimento de um programa de computador (ou software), pois, a partir da construção de algoritmos para a resolução de algum problema, é possível traduzir o algoritmo para alguma linguagem de programação.
Fonte: Shutterstock.
A seguir, veja alguns exemplos de algoritmo:
Algoritmo para efetuar o cozimento de um arroz
1. Acender o fogo;
2. Refogar os temperos;
3. Colocar o arroz na panela;
4. Colocar a água;
5. Cozinhar o arroz;
6. Abaixar o fogo;
7. Esperar o ponto;
8. Desligar o fogo;
9. Servir o arroz.
Algoritmo para efetuar o cozimento de um arroz (mais detalhado)
Assim, percebemos que não existe somente uma forma de realizar um algoritmo, podem ser criada outras formas e sequências para obter o mesmo resultado, ou seja, eles são independentes, porém, com a mesma finalidade de execução.
Representação dos algoritmos 
O algoritmo é representado em três partes:
Entrada
Dados 
(ingredientes para o preparo do arroz)
Processamento
Execução 
 (cozimento do arroz)
Saída
Solução/Objetivo atingido
(finalização do arroz - momento que será servido)
Linguagem natural
A linguagem natural na definição geral é uma forma de comunicação entre as pessoas de diversas línguas, ela pode ser falada, escrita, gesticulada entre outras formas de comunicação. A linguagem natural tem uma grande contribuição quando vamos desenvolver uma aplicação computacional, pois ela pode direcionar de forma simples e eficiente as descrições dos problemas e suas soluções (SANTOS, 2001).
Para reforçar os conceitos de linguagem natural podemos ver como exemplo o cadastro de notas de alguns alunos de um curso. 
Problema:
 O usuário deverá entrar com dois valores (as notas) e o computador retorna o resultado da média destes valores (média das notas). 
Perceba que a linguagem natural é muito próxima da nossa linguagem.
Solução
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 do total 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.
Outro exemplo é o algoritmo para calcular o máximo divisor comum, o famoso “MDC”: 
1. Dividir um número “a” por “b”, onde o resto é representado por “r”
2. Substituir a por b
3. Substituir b por r
4. Continuar a divisão de a por b até que um não possa ser mais dividido, então “a” é considerado o mdc.
De acordo com a solução, o resultado fica: 
MDC (480,130) = 10
Solução do “MDC” do algoritmo
	a
	b
	R 
	480
	130
	90
	130
	90
	40
	90
	40
	10
	40
	10
	0
	10
	0
	
Fonte: adaptada de Piva (2012).
Variáveis e Atribuições
As variáveis como o próprio nome sugere, é algo que pode sofrer variações, ou seja, estão relacionadas a identificação de uma informação. Exemplos: valor1, nome.
A atribuição (←← ) tem a função de indicar valores para as variáveis, ou seja, atribuir informação para variável. Exemplos:
Valor ←← 8
Valor1 ←← marcio
Significa que o número “8” está sendo atribuído para variável  “valor1”  e que o texto “marcio” está atribuído para variável “ nome”.
Diagrama de Blocos (Fluxograma)
Diagrama de blocos é um conjunto de símbolos gráficos, onde cada um desses símbolos representa ações específicas a serem executadas pelo computador. Determina a linha de raciocínio utilizada pelo programador para resolver problemas. Os símbolos dos diagramas de bloco foram padronizados pela ANSI (Instituto Norte Americano de Padronização). 
A seguir, veja a descrição dos principais símbolos utilizados em um diagrama de blocos, de acordo com Manzano (2015):
Terminal
Representa o início ou o fim de um fluxo lógico. Em alguns casos define as sub-rotinas.
Entrada manual
Determina a entrada manual dos dados, geralmente através de um teclado.
Processamento
Representa a execução de ações de processamento.
Exibição
Mostra o resultado de uma ação, geralmente através da tela de um computador.
Decisão
Representa os desvios condicionais nas operações de tomada de decisão e laços condicionais para repetição de alguns trechos do programa.
Preparação
Representa a execução de um laço incondicional que permite a modificação de instruções do laço.
Processo definido
Mostra o resultado de uma ação, geralmente através da tela de um computador.
Conector
Representa pontos de conexões entre trechos de programas, que podem ser apontados para outras partes do diagrama de bloco.
Linha
Representa os vínculos existentes entre os símbolos de um diagrama de blocos.
A seguir veja a solução de um algoritmo utilizando diagrama de blocos. Clique nos símbolos do diagrama para saber mais sobre cada passo.
Pseudocódigo
O pseudocódigo é considerado uma ferramenta que pode auxiliar a programação, ela pode ser escrita em palavras similares ao inglês ou português para facilitar a interpretação e desenvolvimento de um programa (AGUILAR, 2011).
Exemplo de pseudocódigo que calcula a média das notas dos alunos de um curso:
1. calculo_media;
2.     var
3.     real: valor1, valor2, soma, media;
4.  Início
5.      escreva (“Digite o valor 1”);
6.     leia valor1;
7.     escreva (“Digite valor 2”);
8.     leia valor2;
9.     soma ←← valor1 + valor2;
10.    soma ←← soma/2;
11.     escreva(“A media do aluno e:”; media);
12.     se (media >=6)
13.          então escreva(“Aluno Aprovado”);
14.          senão escreva(“Aluno Reprovado”);
15.     Fim se;
16. Fim.
Comentário:
Linha 1: “calculo_media” esse é o nome reservado para identificar o algoritmo. 
Linha 2: “Var”, indica a declaração das variáveis.
Linha 3: São os nomes dados para as variáveis (valor1, valor2, soma, media), nesta linha também é definida os tipos de variáveis (“real”, veremos com maior detalhe na próxima unidade do livro).
Linha 4: inicia os procedimentos dos algoritmos (início);
Linha 5: “escreva” é um comando de saída, este comando indica o que vai sair na tela do computador, geralmente o conteúdo do texto a ser mostrado fica entre aspas (“”).
Linha 6: “leia” é comando de entrada, o valor digitado é armazenado na variável (valor1)
Linha 7: “escreva” é um comando de saída, este comando indica o que vai sair na tela do computador, geralmente o conteúdo do texto a ser mostrado fica entre aspas (“Digite valor 2”).
Linha 8: “leia” é comando de entrada, o valor digitado é armazenado na variável (valor2)
Linha 9: A adição das variáveis valor1 e valor2 é atribuído para variável soma. (soma ←← valor1 + valor2)
Linha 10: Realiza o calcula da média e atribui o valor encontrado na variável media. (media ←← soma/2)
Linha 11: Escreve na tela o que está entre aspas. Escreva (“A media do aluno e:”; media). Perceba que a variável é colocada fora das aspas, para que a mesma seja representada pelo seu valor correspondente.
Linha 12: Utiliza o resultado da média para criar uma condição verdadeira ou falsa: se (media >=6).
Linha 13: se o resultado da média for maior ou igual a seis (condição verdadeira), o computador escreve na tela “Aluno Reprovado”.
Linha 14: se o resultado da média for menor que seis (condição falsa) o computador escreve na tela “Aluno Aprovado”. 
Linha 15: Encerra a condição (fim se). 
Linha 16: Encerra o algoritmo com a palavra “fim” e o ponto final.
Exemplo de algoritmo escritoem pseudocódigo e executado em Visualg :
algoritmo "media"
var
            valor1, valor2, soma, media: real
inicio
            Escreval("Digite o valor da nota 1: ")
            Leia (valor1)
            Escreval("Digite o valor da nota 2: ")
            Leia (valor2)
            soma ←← (valor1 + valor2)
            soma ←← (soma / 2 )
            soma ←← (soma / 2 )
            Escreval(“A media do aluno e:” media)
            se media >=6 entao
                        escreval ("Aluno Aprovado média = ", media)
                        senao
                        escreval ("Aluno Reprovado média = ",media)
            fimse
Finalgoritmo
Perceba que os parâmetros utilizados também são considerados um algoritmo do tipo português estruturado, ou seja, de fácil entendimento e interpretação.
Paradigmas de programação
Após os estudos de algoritmos e as suas formas de construções, Manzano (2015) coloca em destaque os paradigmas de programação, que são caracterizados pelos paradigmas da:
Programação estruturada
Onde o algoritmo é construído como sequência linear de funções ou módulo.
Programação Orientada a Objetos
Onde o programador abstrai um programa como uma coleção de objetos que interagem entre si.
Os algoritmos são as bases para criação de um programa de computador, onde diversas aplicações poderão ocorrer. Um algoritmo bem estruturado vai gerar um programa para solução de um problema que antes, parecia complexo. Todas as áreas estão voltadas para a tecnologia e são através de diversas formas de pensamentos que os algoritmos são realizados.
Algoritmos e Programação Estruturada
Componentes e elementos de linguagem de programação
Foguete Ariane 5
Você conhece o caso do foguete Ariane 5? 
Trata-se de um projeto da Agência Espacial Europeia de um primeiro voo não tripulado em 4 de junho de 1996, que custou bilhões de dólares e levou 10 anos para ser construído. O Foguete Ariane 5 explodiu 40 segundos após a decolagem em seu voo inaugural. Com isso, houve a destruição do foguete e de toda a carga que custava milhões de dólares, causando um enorme prejuízo financeiro e de tempo. 
E tudo isso não aconteceu por uma falha mecânica, mas por um erro de programação. 
O programa que convertia um valor em float (ponto flutuante) para um inteiro de 16 bits (long int) recebeu como entrada um valor fora da faixa que suportava (“um estouro de inteiros”). Com esse bug, os computadores principais, inclusive o de backup, desligaram ao mesmo tempo, alegando um erro de execução (run time error). Por isso, é importante destacar que a declaração de uma variável de forma incorreta ou com tipos incompatíveis pode trazer erros muitas vezes catastróficos. Esse desastre mostra a importância da declaração de variáveis corretamente.
Saiba Mais
BUG do milênio (Y2K)
Você sabia que no fim do século XX houve uma grande mobilização no mundo e em uma comunidade programadores, devido ao chamado "bug do milênio”? 
Esse foi o nome dado para um provável acontecimento – que não se concretizou – na virada do ano de 1999 para 2000: havia o receio de que os sistemas da época não reconhecessem as datas do ano 2000 e retornassem para 1900. 
Placa eletrônica exibindo o ano incorretamente
Fonte: Wikimedia. 
Mas por que isso? 
Na época, recursos de memória eram caros e limitados – por exemplo, 1 MB de memória custava em torno de 700 dólares. Por isso, havia uma constante necessidade, por parte dos desenvolvedores, de economizar e otimizar espaço em memória. Assim, na década de 1960 as datas eram armazenadas, porém, eram interpretados apenas dois dígitos para o ano – os dois últimos dígitos.
No caso, o ano de 1999 seria interpretado apenas como “99” (dois últimos dígitos). Com isso, o receio era que, em vez de os sistemas reconhecerem o ano de 2000, o identificassem como ano de 1900, zerando os dois últimos dígitos na data. 
De fato, o problema não causou tantos impactos, pois muitos sistemas desenvolvidos na época já consideravam o ano com quatro dígitos. Porém, problemas pontuais ocorreram; alguns sites da época não reconheciam a data e mostravam a data “01/01/19100”, e houve falhas em terminais de ônibus e equipamentos de medição de radiação. Houve, também, investimentos de bilhões de dólares em medidas preventivas. 
Caso realmente tivesse se concretizado, esse acontecimento causaria um enorme prejuízo para bancos, com juros negativos, investidores e empresas poderiam indo à falência. Os sistemas de aeroportos e usinas nucleares poderiam entrar em colapso, causando quedas de aviões e vazamentos radioativos. Atualmente é improvável que esse tipo de problema ocorra, pois já temos alternativas de armazenamento em nuvem e recursos de memória mais baratos. 
VAMOS PRATICAR!
Para exercitar um pouco, observe o código com o erro que se assemelha ao ocorrido no caso do foguete Ariane 5. Mostra que os erros de execução (run time error) são comuns quando se declara um vetor ou array com menor capacidade que o necessário para o problema. Nesse caso, o código é compilado sem erros, porém ocorrem problemas na execução. 
Análise o código e faça o teste utilizando a ferramenta Online GDB (um compilador online em C), clique no botão Run:
 
Operações e expressões
Sistemas computacionais
Desde o momento em que você liga um computador (ou tablet, ou smartphone), centenas de processos são inicializados e passam a competir pelo processador para que possam ser executados e fazer a “mágica” do mundo digital acontecer. 
Todos os resultados desses sistemas são obtidos através do processamento de dados e nesta webaula começaremos a estudar os recursos que lhe permitirão implementar soluções com processamento.
Fonte: Shutterstock.
Os sistemas computacionais são construídos para resolver os mais diversos problemas. Todos esses sistemas, independentemente da sua aplicação, são construídos em três partes: entrada, processamento e saída.
Nos três casos, a leitura dos dados é feita para um único fim: processamento e geração de informações e essa etapa é construída a partir da combinação de operações aritméticas, relacionais, lógicas e outras técnicas de programação.
Operadores aritméticos 
Vamos começar a aprimorar nossos algoritmos através das operações aritméticas. Os operadores aritméticos podem ser classificados em unários ou binários (MANZANO, 2015). 
Operadores aritméticos unários
	Operador
	Descrição
	Exemplo
	Resultado
	++
	Pós-incremento
	x ++
	x + 1
	++
	Pré-incremento
	++ x
	 x + 1
	--
	Pós-decremento
	y --
	y - 1
	--
	Pré-decremento
	-- y
	 y - 1
Fonte: elaborado pela autora.
Quando trabalhamos com operadores, a ordem de precedência é muito importante. Segundo Soffner (2013), os operadores aritméticos possuem a seguinte ordem de execução:
1° Parênteses.
2° Potenciação e radiciação.
3° Multiplicação, divisão e módulo.
4° Soma e subtração.
Operadores relacionais 
Faz parte do processamento fazer comparações entre valores e, a partir do resultado, realizar novas ações. Em programação, para compararmos valores usamos operadores relacionais. Os operadores relacionais são utilizados para construir expressões booleanas, ou seja, expressões que terão como resultado verdadeiro ou falso. 
Operadores aritméticos unários
	Operador
	Descrição
	Exemplo
	==
	igual a
	x == y
	!=
	diferente de
	X != y
	> 
	maior que
	X > y
	< 
	menor que
	X < y
	>=
	maior ou igual que 
	X >= y
	<=
	menor ou igual que
	X <= y
Fonte: adaptado de Manzano (2015, p. 82).
Observe o código a seguir, de acordo com as entradas n1=5, n2=10 e n3=5
· A instrução (n1 == n2) && (n1 == n3), mostrará se n1 é igual a n2  E(&&) n1 é igual a n3. No caso será impresso o valor 0 (falso), pois n1 e n2 são diferentes.
· A instrução (n1 == n2) || (n1 == n3), mostrará se n1 é igual a n2 OU(||) n1  é igual a n3. No caso será impresso o valor 1 (verdadeiro), pois, os valores de n1 e n3 são iguais.
· A instrução (n1 < n3) || (n1 > n2), mostrará se n1é menor que n3 OU (||) n1 é maior que n2. No caso será impresso o valor 0 (falso), pois, os valores de n1 e n3 são iguais e n1 é maior que n2.
 #include<stdio.h>int main(){
 int n1 = 5, n2 = 10, n3 = 5;
 
 printf("\n (n1 == n2) && (n1 == n3) = %d", ((n1 == n2) && (n1 == n3)));
 printf("\n (n1 == n2) || (n1 == n3) = %d", ((n1 == n2) || (n1 == n3)));
 printf("\n (n1 < n3) || (n1 > n2) = %d", ((n1 < n3) || (n1 > n2)));
 
}
Operadores lógicos 
Além dos operadores relacionais, outro importante recurso para o processamento é a utilização de operadores lógicos, que possuem como fundamento a lógica matemática clássica e a lógica boolena (GERSTING, 2017). 
Operadores lógicos 
	Operador
	Descrição
	Exemplo
	!
	negação (NOT - NÃO)
	!(x == y)
	&&
	conjunção (AND - E)
	 (x > y) && (a == b)
	||
	disjunção (OR - OU)
	(x > y) || (a == b)
Fonte: adaptado de Soffner (2013, p. 35).
Observe no código a seguir, que na linha 14 if (strcmp(login, "aluno01")==0 && strcmp(senha, "teste01")==0)utilizamos os operadores “==” e “&&”.
· O operador “==” compara se as strings de entradas em login é igual a “aluno01” e senha é igual a “teste01”.
· O operador “&&” verifica se o login e a senha correspondem os valores de entradas.
 
#include <stdio.h>
#include <string.h>
int main()
{
 char login[10];
 char senha[10];
 
 printf("Entre com seu login: \n" );
 scanf("%s", login );
 printf("Digite a sua senha:\n" );
 scanf("%s", senha );
 if (strcmp(login, "aluno01")==0 && strcmp(senha, "teste01")==0){
 printf("Bem-vindo aluno\n" );
 }
 else {
 printf("Login falhou!\n");
 }
 
 return 0;
}
Funções predefinidas 
Para facilitar o desenvolvimento de soluções em software, cada linguagem de programação oferece um conjunto de funções predefinidas que ficam à disposição dos programadores. Entende-se por função “um conjunto de instruções que efetuam uma tarefa específica.” (MANZANO, 2015, p. 153).
Algumas bibliotecas e funções na linguagem C
	Biblioteca
	Função
	Descrição
	<stdio.h>
	printf()
scanf()
fgets(variavel, tamanho, fluxo)
	Imprime na tela.
Faz leitura de um dado digitado.
Faz a leitura de uma linha digitada.
	<math.h>
	pow(base,potencia)
sqrt(numero)
sin(angulo)
cos(angulo)
	Operação de potenciação.
Calcula a raiz quadrada.
Calcula o seno de um ângulo.
Calcula o cosseno de um ângulo.
	<string.h>
	strcmp(string1, string2)
strcpy(destino, origem)
	Verifica se duas strings são iguais.
Copia uma string da origem para o destino.
	<stdlib.h>
	malloc(tamanho)
realloc(local,tamanho)
free(local)
	Aloca dinamicamente espaço na memória.
Modifica um espaço já alocado dinamicamente.
Libera um espaço alocado dinamicamente.
Fonte: adaptado de Tutorials point (2020).
Estruturas de decisão condicionais 
Estrutura de decisão condicional if/else (se/então)
Para a solução de um problema que envolva situações podemos utilizar a instrução “if”, em português “se”, onde sua função é tomar uma decisão e criar um desvio dentro do programa, desta forma, podemos chegar a uma condição verdadeira ou falsa. Lembrando que a instrução pode receber valores em ambos os casos. (Manzano, 2013)
Estrutura condicional simples
Sintaxe da instrução “if” (se) utilizada na linguagem C:
if <(condição)> 
{
<conjunto de comandos>;
}
Fluxograma – função “if”
Fonte: elaborada pelo autor.
No exemplo de condicional simples, será executado um teste lógico, onde, se o resultado for verdadeiro então ele trará uma resposta, caso contrário não retornará nada. Veja no exemplo a seguir, a situação de um jovem que verifica se poderá ou não tirar a carteira de habilitação.
· Neste exemplo não é considerado o “senão (else)”, simplesmente se a condição não for verdadeira ela não exibirá nada como resposta.
Estrutura condicional composta
Sintaxe da instrução “if/else” (se/senão):
if <(condição)> 
{
<primeiro conjunto de comandos>;
}
else
{
<segundo conjunto de comandos>;
}
Fluxograma – função “if/else”
Fonte: elaborada pelo autor.
No exemplo de estrutura condicional composta a seguir, Maria e João estão se preparando para uma viagem, porém, se o orçamento final deles for igual ou maior que R$ 10.000,00 eles farão uma viagem internacional, senão deverão ficar com uma viagem nacional.
Estrutura condicional de Seleção de Casos “switch-case”
A estrutura condicional de seleção de casos “switch-case” testa sucessivamente o valor de uma expressão contra uma lista de constantes inteiras ou de caractere”. Quando os valores são avaliados o comando é executado. (Schildt,1997)
Fluxograma – estrutura condicional de seleção de casos
Fonte: elaborada pelo autor.
Sintaxe:
switch (variável)
{
case constante1:    
   <comandos>
   break;
case constante2:    
   break;
default: <comandos>
}
Saiba Mais
No exemplo de estrutura condicional de seleção de casos a seguir, é aplicado um desconto de acordo com a escolha de uma cor específica pelo cliente.
Estrutura condicional Encadeada
Conhecida como ifs aninhados. É um comando if que é o objeto de outros if e else. Ou seja, sempre um comando else estará ligado ao comando if de seu nível de aninhamento. (Schildt,1997)
Fluxograma – estrutura condicional de seleção de casos
Fonte: elaborada pelo autor.
Sintaxe:
if (condição) {
  <comandos>;
} else {
  if (condição) {
    <comandos>;
   } else (condição) {
     <comandos>;
  }
}
No exemplo de estrutura condicional encadeada a seguir, será analisado os tipos de triângulo, partindo da premissa que ele deverá ser testado antes, para ver se forma ou não um triângulo.
Nesta webaula foram apresentadas as estruturas condicionais e de seleção. Pense nas possibilidades que você pode ter usando essas estruturas de tomadas de decisão “if-else”, “if- else-if” e “switch-case”. Lembre-se que para cada caso poderá ter uma particularidade diferente em desenvolver um programa. 
Estruturas de repetição condicional
Nesta webaula, vamos conhecer a estrutura de repetição condicional.
Estrutura de repetição condicional while, do-while 
Assim como nas estruturas de decisão, as estruturas de repetição desenvolvem aplicações para a otimização do pensamento computacional e ao mesmo tempo, a agilidade nas soluções dos problemas de repetição.
Vamos iniciar com as repetições com teste no início – while, neste caso algo será repetidamente executado enquanto uma condição verdadeira for verificada, somente após a sua negativa essa condição será interrompida.
· O programa “não executará nenhuma repetição (e as ações que ali dentro estiverem programadas) sem antes testar uma condição”. Na realização desta condição fazemos uso do comando iterativo “while” que significa em português “enquanto”. offner, 2013 p. 64)
Estrutura de repetição com teste no início - while
Sintaxe do comando “while” (enquanto) utilizada na linguagem C:
while (<condição>)
{
Comando 1;
Comando 2;
Comando n;
}
Fluxograma – comando “while”
Fonte: elaborada pelo autor.
Quando utilizamos teste no início, pode ocorrer o famoso loop (laço) infinito, que é quando um processo é executado repetidamente. Clique para ver os recursos que podem ser utilizados para que isso não aconteça.
Contador
É utilizado para controlar as repetições, quando esta é determinada.
Incremente e decremento
Trabalha o número do contador, seja ele, aumentado ou diminuído.
Acumulador
Irá somar as entradas de dados de cada iteração da repetição, gerando um somatório a ser utilizado quando da saída da repetição. (Soffner, 2013)
Condição de parada
Utilizada para determinar o momento de parar quando não se tem um valor exato desta repetição.
No exemplo de repetição condicional a seguir, utilizando o comando while com teste no início, mostrará a palavra “PROGRAMA” dez vezes.
#include <stdio.h>
int main() {
	int cont=0; 
 // Será executado enquanto cont for menor que 10
 while (cont < 10) {
	 printf("\n PROGRAMA");
	 
 // incrementa cont, para que não entre em loop infinito
	 cont++; 
	 } 
	 return 0;
}
TEXT
 PROGRAMA
 PROGRAMA
 PROGRAMA
 PROGRAMA
HTML
PROGRAMA PROGRAMA PROGRAMA PROGRAMA PROGRAMA PROGRAMA PROGRAMA PROGRAMA PROGRAMA PROGRAMA
JSON
 PROGRAMA
 PROGRAMA
 PROGRAMA
Estrutura de repetição condicional com testeno final –do-while
O laço “do-while” analisa a condição ao final do laço, ou seja, os comandos são executados antes do teste de condição. Neste caso, em específico, o usuário tem a possibilidade de digitar novamente uma nova informação. (Schildt,1997)
Sintaxe para realização da repetição com teste no final:
Do
{
comandos; 
} 
while (condição);
Fluxograma – comando “do/while”
Fonte: elaborada pelo autor.
O exemplo a seguir, realiza um programa que calcula a metragem quadrada de um terreno usando o teste no final para criar a opção de digitar novos valores sem sair do programa.
#include <stdio.h>
int main() {
 float metragem1, metragem2, resultado;
 int resp;
 metragem1 = 0;
 metragem2 = 0;
 resultado = 0;
 printf("\nC Á L C U L O D E M E T R O S Q U A D R A D O S");
 do {
 printf("\n\nDigite a primeira metragem do terreno: ");
 scanf("%f", &metragem1);
 printf("\nDigite a segunda metragem do terreno: ");
 scanf("%f", &metragem2);
 resultado = metragem1 * metragem2;
 printf("\n\nO Terreno tem = %.2f m2", resultado);
 printf("\n\nDigite 1 para continuar ou 2 para sair: ");
 scanf("%d", &resp);
 } while (resp == 1);
 return 0;
}
TEXT
C Á L C U L O D E M E T R O S Q U A D R A D O S
Digite a primeira metragem do terreno:
HTML
C Á L C U L O D E M E T R O S Q U A D R A D O S Digite a primeira metragem do terreno: Digite a segunda metragem do terreno: O Terreno tem = 0.00 m2 Digite 1 para continuar ou 2 para sair:
JSON
C Á L C U L O D E M E T R O S Q U A D R A D O S
Digite a primeira metragem do terreno:
O exemplo a seguir, realiza um programa que simula uma conta bancária (com tela de opções das transações. Ele repete uma entrada de dados até que determinada condição de saída seja atingida e, em seguida, acumule os valores digitados. Observe que foi utilizado o laço do-while para implementar o menu do programa, uma estrutura de repetição usando comparativo. Adaptado do livro do Soffner (2013). 
#include <stdio.h>
int main() {
 float soma=0; 
 float valor; 
 int opcao; 
 do {
 printf("\n M E N U D E O P Ç Õ E S");
 printf("\n 1. Depósito"); 
 printf("\n 2. Saque"); 
 printf("\n 3. Saldo"); 
 printf("\n 4. Sair"); 
 printf("\n Informe uma opção: "); 
 scanf("%d", &opcao);
 switch(opcao) {
 case 1: 
 printf("\n Informe o valor: "); 
 scanf("%f", &valor); 
 soma += valor; 
 break;
 case 2: 
 printf("\n Informe o valor: "); 
 scanf("%f", &valor); 
 soma -= valor; 
 break;
 case 3: 
 printf("\n Saldo atual = R$ %.2f", soma); 
 break; 
 case 4: 
 printf("\n Saindo..."); 
 break; 
 default: 
 printf("\n Opção inválida!"); 
 } 
 } while (opcao != 4); 
 printf("\n\n Fim das operações!");
	return 0;
}
TEXT
 M E N U D E O P Ç Õ E S
 1. Depósito
 2. Saque
HTML
M E N U D E O P Ç Õ E S 1. Depósito 2. Saque 3. Saldo 4. Sair Informe uma opção: Informe o valor: M E N U D E O P Ç Õ E S 1. Depósito 2. Saque 3. Saldo 4. Sair Informe uma opção: Informe o valor: M E N U D E O P Ç Õ E S 1. Depósito 2. Saque 3. Saldo 4. Sair Informe uma opção: Saldo atual = R$ 490.00 M E N U D E O P Ç Õ E S 1. Depósito 2. Saque 3. Saldo 4. Sair Informe uma opção: Informe o valor: M E N U D E O P Ç Õ E S 1. Depósito 2. Saque 3. Saldo 4. Sair Informe uma opção: Informe o valor: M E N U D E O P Ç Õ E S 1. Depósito 2. Saque 3. Saldo 4. Sair Informe uma opção: Informe o valor: M E N U D E O P Ç Õ E S 1. Depósito 2. Saque 3. Saldo 4. Sair Informe uma opção: Saldo atual = R$ 310.00 M E N U D E O P Ç Õ E S 1. Depósito 2. Saque 3. Saldo 4. Sair Informe uma opção: Saindo.
JSON
 M E N U D E O P Ç Õ E S
 1. Depósito
 2. Saque
Algoritmos e Programação Estruturada
Listas
Nesta webaula vamos conhecer o funcionamento das listas ligadas.
Estruturas de dados
As estruturas de dados são formas de organização e distribuição de dados para tornar mais eficientes a busca e manipulação dos dados por algoritmos. As listas são estruturas de dados dinâmicas, uma vez que o número de elementos de uma lista é variável conforme eles são inseridos ou removidos.
Para a implementação de listas, os vetores são muito utilizados para representar um conjunto de dados, permitindo definir um tamanho máximo de elementos a ser utilizados neste vetor.
Exemplo de vetor
Fonte: Celes, Cerqueira, Rangel, ( 2004, p. 134).
O uso do vetor, ao ser declarado, reserva um espaço contíguo na memória para armazenar seus elementos. Assim, é possível acessar qualquer um dos seus elementos a partir do primeiro elemento, por meio de um ponteiro (CELES, CERQUEIRA e RANGEL, 2004).
Listas Ligadas
Uma Lista Ligada, também conhecida como Lista Encadeada, é um conjunto de dados dispostos por uma sequência de nós, onde a relação de sucessão desses elementos é determinada por um ponteiro que indica a posição do próximo elemento, podendo estar ordenado ou não (SILVA, 2007).
Uma lista é uma coleção 
L:[a1, a2, ..., an]
onde n > 0
Sua propriedade estrutural baseia-se apenas na posição relativa dos elementos, que são dispostos linearmente.
O nó de lista é composto por duas informações, uma informação armazenada e um ponteiro que indica o próximo elemento da lista.
Modelo de lista ligada
Fonte: Celes, Cerqueira, Rangel, ( 2004, p. 135).
Diferente dos vetores, onde o armazenamento é realizado de forma contígua, a Lista Ligada estabelece a sequência de forma lógica. 
Na lista encadeada é definido um ponto inicial ou um ponteiro para o começo da lista, e a partir daí pode se inserir elementos, remover ou realizar buscas na lista.
Quando uma lista está sem nós, definimos como lista vazia ou lista nula, assim, o valor do ponteiro para o próximo nó da lista, é considerado como ponteiro nulo.
Criação ou definição da estrutura de uma lista
Inicialização da lista
Inserção com base em um endereço como referência
Alocação de um endereço de nó para inserção na lista
Remoção do nó com base em um endereço como referência
Deslocamento do nó removido da lista
Elementos de dados em listas ligadas
Os elementos de uma lista são armazenados em posições sequenciais de memória, sempre que possível e de forma dinâmica, e permitem que a lista seja percorrida em qualquer direção.
Os elementos de informação de uma lista podem ser do tipo int, char e/ou float .
Ao criar uma estrutura de uma lista, definimos também o tipo de dados que será utilizado em sua implementação. 
struct lista {
 int info;
 struct lista * prox;
};
typedef struct lista Lista;
Exemplo de declaração para criar uma lista em C
/*Cria a estrutura da lista*/
struct alunos
 char nome[25];
 struct alunos*prox;
};
Typedef struct alunos Classe;
· Criado uma struct (registro) alunos;
· Na struct, há uma variável nome do tipo char, que será nossa informação;
· Outra struct prox com ponteiro para a própria struct alunos para receber o endereço de apontamento da próxima informação.
Inicialização da lista
Precisamos inicializar a lista para utilizarmos após sua criação. 
Para isso, basta criarmos uma função onde inicializamos a lista como nula, como uma das possíveis formas de inicialização.
/* Função para inicialização: retorna uma lista vazia */
Lista* inicializa (void)
{
 return NULL;
}
Ponteiros – elementos de ligação
A utilização de ponteiros é indicada nos casos onde é preciso conhecer o endereço que está armazenada a variável. 
int *ptr; /* sendo um ponteiro do tipo inteiro*/
float *ptr; /* sendo um ponteiro do tipo ponto flutuante*/
char *ptr; /* sendo um ponteiro do tipo caracteres*/
A seguir, veja uma exemplo de uma estrutura de lista declarada para armazenar dados de uma agenda. 
typedef struct lista {
 char *nome;	/*Declaração de um ponteiro do tipo char
 int telefone;struct lista *proximo;
} Dados;
Para sabermos o endereço da memória reservada para a variável, utiliza se o operador & juntamente ao nome de uma variável. 
 int x = 10; /*variável
 int *p; /*ponteiro
 p = &x; /*ponteiro p aponta para o endereço da variável x
Função malloc()
Em listas, além do uso de ponteiros, utilizamos também as alocações dinâmicas de memória, que são porções de memórias para utilização das listas. Para isso são utilizadas a função malloc(), Memory Allocation ou Alocação de Memória. Ela é a responsável pela reserva de espaços na memória principal. Sua finalidade é alocar uma faixa de bytes consecutivos na memória do computador e retornar seu endereço ao sistema. 
Exemplo de utilização da função malloc() e de ponteiro:
 char *pnt;
 pnt = malloc (2); /* Aloca 2 bytes na memória */
 scanf ("%c", pnt); 
O endereço retornado é o da posição inicial onde se localiza os bytes alocados.
Em uma lista, precisamos alocar o tipo de dado no qual foram declarados os elementos da lista, e por este tipo de dados ocupar vários bytes na memória, precisaremos utilizar a função sizeof, que permite nos informar quantos bytes o tipo de elemento criado terá. 
Exemplo de programa em C com malloc() e sizeof
#include <stdio.h>
#include <stdlib.h>
int main () {
 
 int *p;
 p=(int *) malloc(sizeof(int));
 
 if (!p) {
 printf("Erro de memoria insuficiente");
 }else{
 printf("Memoria alocada com sucesso");
 }
 
 return 0;
}
Podemos classificar as listas de duas formas. 
Lista com cabeçalho
Onde o primeiro elemento permanece sempre como ponto inicial na memória, independente se a lista está com valores ou não. Assim, o start é o endereço inicial da nossa lista e para determinar que a lista está vazia.
 celula *start;
 start = malloc (sizeof (celula));
 start -> prox = NULL;
Lista sem cabeçalho
Exemplo de um trecho de uma função do tipo inteiro, para inserir pacientes com prioridades na lista.
int insere_com_prioridade(Fila *F , Paciente *P){
 Lista *ptnodo, *aux , *ant;
 ptnodo = (Lista*)malloc(sizeof(Lista));
Aplicação de listas ligadas no nosso dia a dia
Lista de compra de supermercado
Ao anotar tudo que você precisa comprar, você automaticamente está criando uma lista, e esta lista pode ser alocada com novos produtos ou remover produtos dela conforme a compra está sendo realizado.
Dados *inicia_listaMerc(char *prod, int numpro) {
 
 Dados *novo;
 
 novo = (Dados *)malloc(sizeof(Dados));
 
 novo -> prod = (char *)malloc(strlen(prod) +1);
 strncpy (novo -> prod, prod, strlen(prod) +1);
 novo -> numpro = numpro;
 novo -> proximo = NULL;
 
 return novo;
}
Desenvolvimento de um sistema para o site de uma empresa de casamentos
Os usuários criam a lista de convidados e a lista de presentes, os noivos podem adicionar convidados ou presentes e remover ou alterar da lista quando necessário.
void convidados inserirConvid(tipoitem elemento,int &cont)
{
 festa *novo, *aux, *aux1;
 aux = inicio;
 aux1 = inicio -> prox;
 
 while (aux1 != NULL) {
 if(strcmp(aux1 -> item.nome, elemento.nome) > 0)
 break;
 
 aux = aux -> prox;
 aux1 = aux1 -> prox;
 }
 
 if((novo = new(festa) == NULL)
 printf("\nMemoria insuficiente");
 else {
 novo -> prox = aux -> prox;
 aux - > prox = novo;
 novo -> item = elemento;
 cont++;
 printf("\nConvidado inserido com sucesso!");
 }
 
 if (aux1 == NULL)
 fim = novo;
 
 return;
}
Estruturas de repetição determinísticas
Estrutura de repetição com variáveis de controle - for
O comando iterativo “for” que em português significa “para”, é geralmente usado para repetir uma informação por um número fixo de vezes, isto é, podemos determinar quantas vezes acontecerá a repetição. Mizrahi, 2008).
Sintaxe do comando “for” (para) utilizada na linguagem C: 
for(inicialização; condição final; incremento) 
{
  <comandos>;
}
Fluxograma – comando “for”
Fonte: elaborada pelo autor.
Exemplos
A seguir, veremos alguns exemplos de utilização do comando for.
Como primeiro exemplo, iremos criar uma contagem regressiva de um número qualquer, digitado pelo usuário (Exemplo estrutura de repetição com variável de controle).
#include <stdio.h>
int main(){
 int parar_em = 30;
 for(int i = 0; i < 100; i++) {
 if (i == parar_em) {
 break;
 }
 printf("%d ", i);
 }
 
}
Pode-se usar o comando “break” dentro de um laço “for” para uma determinada condição, forçando assim, o término do laço.
#include <stdio.h>
int main(){
 int parar_em = 30;
 for(int i = 0; i < 100; i++) {
 if (i == parar_em) {
 break;
 }
 printf("%d ", i);
 }
 
}
No exemplo a seguir, temos um programa que mostra uma sequência de números, onde x vai de 10 a 0 e y vai de 0 a 10.
#include <stdio.h>
int main() 
{
 int x,y; 
 for (x = 10, y = 0; x >=0, y<= 10; x--, y++)
 {
 printf("x=%2d y=%2d\n", x, y);
 }
 
 return 0;
}
text
x=10 y= 0
x= 9 y= 1
x= 8 y= 2
x= 7 y= 3
HTML
x=10 y= 0 x= 9 y= 1 x= 8 y= 2 x= 7 y= 3 x= 6 y= 4 x= 5 y= 5 x= 4 y= 6 x= 3 y= 7 x= 2 y= 8 x= 1 y= 9 x= 0 y=10
JSON
x=10 y= 0
x= 9 y= 1
x= 8 y= 2
x= 7 y= 3
for (x = 10,y = 0; x >= 0, y <= 10; x--,y++)
Na primeira expressão “x” tem o seu valor iniciado em “10” e “y” iniciado em “0”.
Na segunda expressão o laço se repetirá enquanto x for maior ou igual a zero e enquanto y for menor ou igual a 10”.
Ao final da execução dos comandos do laço de repetição, x será decrementado de 1 e y será incrementado de 1.
Aplicações com vetores
Vetor (array) é um tipo especial de variável capaz de armazenar diversos valores “ao mesmo tempo”, usando um mesmo endereço na memória. 
Sintaxe: tipo variavel [n]
Na sintaxe acima [n] representa a quantidade de colunas ou linhas.
Exemplo: armazenar valores em um vetor.
#include <stdio.h>
#define VET_TAM 5
int main () {
 int num[VET_TAM];
 
 for (int i = 0; i < VET_TAM; i++) {
 printf("\nEntre com um número: ");
 scanf("%d", &num[i]);
 printf("\nO valor digitado foi: %d", num[i]);
 }
 
 return 0;
}
TEXT
Entre com um número: 
O valor digitado foi: 1
Entre com um número:
HTML
Entre com um número: O valor digitado foi: 1 Entre com um número: O valor digitado foi: 5 Entre com um número: O valor digitado foi: 10 Entre com um número: O valor digitado foi: 15 Entre com um número: O valor digitado foi: 20
JSON
Entre com um número: 
O valor digitado foi: 1
Entre com um número:
Instrução continue
Uma instrução continue dentro de um laço possibilita que a execução de comandos corrente seja terminada, passando à próxima iteração do laço.
No exemplo a seguir, temos um programa que percorrerá os números de 1 a 30 e neste percurso, irá testar se foi digitado algum número ímpar, caso seja ímpar o programa continua o teste até o fim do laço.
#include <stdio.h>
int main() {
 for (int i = 1; i <= 30; i++) {
 if (i % 2 == 0) {
 continue;
 }
 printf("%d ", i);
 }
 
}
TEXT
1 3 5 7 9 11 13 15 17 19 21 23 25 27 29 
HTML
1 3 5 7 9 11 13 15 17 19 21 23 25 27 29
JSON
1 3 5 7 9 11 13 15 17 19 21 23 25 27 29 
Aplicação com matrizes
Matrizes são arranjos de duas ou mais dimensões.
Sintaxe: tipo variável [M][N]
Onde, [M] representa a quantidade de linhas e [N] a quantidade de colunas.
Exemplo: montar uma matriz 3 x 3, onde os valores são lançados de acordo com a linha e coluna. 
#include <stdio.h>
int main() {
 int linha, coluna;
 int matriz[3][3];
 for (linha = 0; linha < 3; linha++) {
 for (coluna = 0; coluna < 3; coluna++) {
 printf("\nDigitar os valores da matriz para [linha %d, coluna %d]: ", linha + 1, coluna + 1);
 scanf("%d", &matriz[linha][coluna]);
 }
 }
 printf("\n\nVeja a sua Matriz\n");
 for (linha = 0; linha <= 2; linha++) {
 for (coluna=0;coluna<3;coluna++){
 printf("%d\t", matriz[linha][coluna]);
 }
 printf("\n");
 }
 return 0;
}
TEXT
Digitar os valores da matriz para [linha 1, coluna 1]: 
Digitar os valores da matriz para [linha 1, coluna 2]: 
Digitar os valores da matriz para [linha 1, coluna 3]: 
HTML
Digitar os valores da matriz para [linha 1, coluna 1]: Digitar os valores da matriz para [linha 1, coluna 2]: Digitar os valores da matriz para [linha 1, coluna 3]: Digitar os valores da matriz para [linha 2, coluna 1]: Digitar os valores da matriz para [linha 2, coluna 2]: Digitar os valores da matriz para [linha 2, coluna 3]: Digitar os valores da matriz para [linha 3, coluna 1]: Digitar os valores da matriz para [linha 3, coluna 2]: Digitar os valores da matriz para [linha 3, coluna 3]: Veja a sua Matriz 1 2 3 4 5 6 7 8 9
JSON
Digitar os valores da matriz para [linha 1, coluna 1]: 
Digitar os valores da matriz para [linha 1, coluna 2]: 
Digitar os valores da matriz para [linha 1, coluna 3]: 
Procedimentos e funções
Um software deve ser construído de forma organizada onde cada funcionalidade deve ser colocada em um “local” com uma respectiva identificação, para que o requisitante possa encontrá-la. Uma das técnicas de programação utilizada para construir programas dessa forma é a construção de funções. Assim, nesta webaula vamos ver a criação de funções na linguagem C bem como seu tipo de retorno.
Funções da linguagem C
printf()e scanf() são exemplos de funções que fazem parte das bibliotecas da linguagem C.
Na imagem a seguir, o comando na linha 2, int main() especifica uma função que chama “main” e que irá devolver para quem a requisitou um valor inteiro, nesse caso, zero. 
Código Hello World
	
	#include<stdio.h>
	
	int main(){
	
	printf("Hello World!");
	
	return 0;
	
	}
Fonte: elaborado pelo autor.
A ideia de criar programas com blocos de funcionalidades vêm de uma técnica de projeto de algoritmos chamada dividir para conquistar (MANZANO; MATOS; LOURENÇO, 2015). A ideia é simples, dado um problema, este deve ser dividido em problemas menores, que facilitem a resolução e organização. A técnica consiste em três passos:
Dividir
Quebrar um problema em outros subproblemas menores.
Conquistar
Usar uma sequência de instruções separada, para resolver cada subproblema.
Combinar
Juntar a solução de cada subproblema para alcançar a solução completa do problema original.
Função
Uma função é um trecho de código escrito para solucionar um subproblema. Esses blocos são escritos tanto para dividir a complexidade de um problema maior, quanto para evitar a repetição de códigos. Essa técnica também pode ser chamada de modularização, ou seja, um problema será resolvido em diferentes módulos
Para criar uma função utiliza-se a sintaxe a seguir.
<tipo de retorno> <nome> (<parâmetros>){   
   <Comandos da função>
   <Retorno> (não obrigatório)
}
Em cada declaração da função alguns parâmetros são obrigatórios e outros opcionais. Veja-os a seguir:
<tipo de retorno>
Obrigatório. Esse parâmetro indica qual o tipo de valor a função irá retornar. Pode ser um valor inteiro (int), decimal (float ou double), caractere (char), etc. Quando a subrotina faz um processamento e não retorna nenhum valor, usa-se o parâmetro void e, nesse caso, é chamado de procedimento (MANZANO, 2015).
<nome>
Obrigatório. Parâmetro que especifica o nome que identificará a função. É como o nome de uma pessoa, para você convidá-la para sair você precisa “chamá-la pelo nome”. O nome não pode ter acento, nem caractere especial e nem ser nome composto (mesmas regras para nomes de variáveis).
<parênteses depois do nome>
Obrigatório. Toda função ou procedimento, sempre terá o nome acompanhado de parênteses. Por exemplo, main(), printf(), somar(), etc.
<parâmetros>
Opcional
<comandos da função>
Obrigatório. Só faz sentido criar uma função se ela tiver um conjunto de comandos para realizar. 
<retorno>
Quando o tipo de retorno for void esse parâmetro não precisa ser usado, porém, quando não for void é obrigatório. O valor a ser retornado tem que ser compatível com o tipo de retorno, senão o problema dará um erro de compilação em algumas linguagens, em outras retornará um valor errôneo. Na linguagem C, irá ser retornado um valor de acordo com o tipo.
Local da função
Em qual parte do código a função deve ser programada?
Na linguagem C, vamos adotar sempre criar as funções (subrotinas) antes da função main(), por uma questão de praticidade e conveniência.
Veja a seguir, um exemplo de programa que utiliza uma função para calcular a soma entre dois números.
#include<stdio.h>
int somar() {
 return 2 + 3;
}
int main() {
 int resultado = 0;
 resultado = somar();
 printf("O resultado da função é = %d", resultado);
 return 0;
}
TEXT
O resultado da função é = 5
HTML
O resultado da função é = 5JSON
O resultado da função é = 5
Explicação
×
A função somar(), inicia-se na linha 2 e termina na linha 4 com o fechamento das chaves. 
Vamos analisar os parâmetros para esse caso:
<tipo de retorno> - Foi especificado que a função irá retornar um valor inteiro (int).
<nome> - somar.
<comandos da função> - Essa função foi criada de modo a retornar a soma de dois valores, tudo em um único comando: return 2 + 3
Outra característica da utilização de funções é que estas “quebram” a linearidade de execução, pois a execução pode “dar saltos” quando uma função é invocada (SOFFNER, 2013). 
Para entender melhor como funciona esse mecanismo, veja a seguir uma função que solicita um número para o usuário, calcula o quadrado desse número e retorna o resultado.
#include<stdio.h>
float calcular() {
 float num;
 printf("\nDigite um número: ");
 scanf("%f", &num);
 return num * num;
}
int main(){
 float resultado = 0;
 resultado = calcular();
 printf("\nO quadrado do número digitado é %.2f ", resultado);
 return 0;
}
TEXT
Digite um número: 
O quadrado do número digitado é 4.00 
HTML
Digite um número: O quadrado do número digitado é 4.00
JSON
Digite um número: 
O quadrado do número digitado é 4.00 
	Explicação
×
Todo programa, sempre começa pela função main(), ou seja, esse programa começará a ser executado na linha 10. Na linha 12 a função calcular() é chamada, ou seja, a execução “pula” para a linha 3.
Na função calcular() é solicitado um valor ao usuário (linha 5), armazenado em uma variável (linha 6) e retornado o valor multiplicado por ele mesmo (linha 7).
Após retornar o valor, a execução do programa “volta” para a linha 10, pois foi nesse ponto que a função foi chamada.
O resultado da função é armazenado na variável resultado e impresso na linha 13.
O uso de funções com ponteiros
Uma função pode retornar um número inteiro, um real e um caractere, assim como também pode retornar um vetor. Para isso, devemos utilizar ponteiros (ou apontador). A única forma de retornar um vetor é por meio de um ponteiro, pois não é possível criar funções como por exemplo, int[10] calcular(), onde int[10] quer dizer que a função retorna um vetor com 10 posições. (MANZANO, 2015).
A seguir veja um exemplo de uso desse recurso através de uma função, que cria um vetor de dez posições e os preenche com valores aleatórios, imprime os valores, e posteriormente passa esse vetor para “quem” chamar a função.
#include<stdio.h>
int* gerarRandomico() {
 static int r[10];
 int a;
 for(a = 0; a < 10; a++) {
 r[a] = rand() % 100;
 printf("\nr[%d] = %d", a, r[a]);
 }
 return r;
}
int main(){
 int *p;
 int i;
 p = gerarRandomico();
 for ( i = 0; i < 10; i++ ) {
 printf("\np[%d] = %d", i, p[i]);
 }
 return 0;
}
TEXT
r[0] = 83
r[1] = 86
r[2] = 77
HTML
r[0] = 83 r[1] = 86 r[2] = 77 r[3] = 15 r[4] = 93 r[5] = 35 r[6] = 86 r[7] = 92 r[8] = 49 r[9] = 21 p[0] = 83 p[1] = 86 p[2] = 77 p[3] = 15 p[4] = 93 p[5] = 35 p[6] = 86 p[7] = 92 p[8] = 49 p[9] = 21
JSON
r[0] = 83
r[1] = 86
r[2] = 77
Explicação
×
O programa começa sua execução pela linha 15, na função main().
Na linha 17 é criado um ponteiro do tipo inteiro, ou seja, este deverá apontarpara um local que tenha número inteiro.
Na linha 18 é criada uma variável para controle do laço de repetição.
Na linha 20 a função gerarRandomico() é invocada; nesse momento a execução “pula” para a linha 3, a qual indica que a função retornará um endereço para valores inteiros (int*).
Na linha 5 é criado um vetor de números inteiros com 10 posições e este é estático (static), ou seja, o valor desse vetor não será alterado entre diferentes chamadas dessa função.
Na linha 8 é criada uma estrutura de repetição para percorrer as 10 posições do vetor. 
Na linha 9, para cada posição do vetor é gerado um valor aleatório por meio da função rand() % 100 (gera valores entre 0 e 99), e na linha 10 o valor gerado é impresso para que possamos comparar posteriormente.
Na linha 12 a função retorna o vetor, agora preenchido, por meio do comando return r; com isso, a execução volta para a linha 20, armazenando o endereço obtido pela função no ponteiro p.
Na linha 22 é criada uma estrutura de repetição para percorrer o vetor.
Recursividade
Vimos como criar uma função, qual sua importância dentro de uma implementação, estudamos a saída de dados de uma função, bem como a entrada, feita por meio dos parâmetros. E nesta webaula, vamos ver uma categoria especial de função, chamada de funções recursivas.
Recursividade
A palavra recursividade está associada a ideia de recorrência de uma determinada situação. Em programação, as funções recursivas, quando uma função chama a si própria.
A sintaxe para implementação de uma função recursiva, nada difere das funções gerais, a diferença está no corpo da função, pois a função será invocada dentro dela mesma.
Algoritmo para função recursiva
Fonte: elaborada pela autora.
Veja a seguir alguns pontos de atenção da função recursiva.
Ponto de parada
A função recursiva chama a si própria até que um ponto de parada seja estabelecido. O ponto de parada poderá ser alcançado através de uma estrutura condicional ou através de um valor informado pelo usuário.
Instâncias
Variáveis
Caso base
Mecanismo da função recursiva
A instância 1 representa a primeira chamada à função funcaoRecursiva(), que por sua vez, possui em seu corpo um comando que chama a si mesma, nesse momento é criada a segunda instância dessa função na memória de trabalho. Um novo espaço é alocado, com variáveis e comandos, como a função é recursiva, novamente ela chama a si mesma, criando então a terceira instância da função.
Dentro da terceira instância, uma determinada condição de parada é satisfeita, nesse caso, a função deixa de ser instanciada e passa a retornar valores. A partir do momento que a função recursiva alcança o ponto de parada, cada instância da função passa a retornar seus resultados para a instância anterior (a que fez a chamada). No caso, a instância três retornará para a dois e, a dois, retornará para a um.
Mecanismo da função recursiva
Fonte: elaborada pela autora.
Veja no exemplo uma função recursiva que faz a somatória dos antecessores de um número, inteiro positivo, informado pelo usuário, ou seja, se o usuário digitar 5, o programa deverá retornar o resultado da soma 5 + 4 + 3 + 2 + 1 + 0. A função deverá somar até o valor zero, portanto esse será o critério de parada.
#include<stdio.h>
int somar(int valor) {
 if(valor == 0) {
 //critério de parada
 return valor;
 } else {
 //chamada recursiva
 return valor + somar(valor - 1); 
 }
}
int main() {
 int n, resultado;
 printf("\nDigite um número inteiro positivo: ");
 scanf("%d", &n);
 resultado = somar(n); // primeira chamada da função
 printf("\nResultado = %d",resultado);
 return 0;
}
TEXT
Digite um número inteiro positivo: 
Resultado = 15
HTML
Digite um número inteiro positivo: Resultado = 15
JSON
Digite um número inteiro positivo: 
Resultado = 15
Explicação
×
A execução inicia pela função principal, a qual solicita um número ao usuário e, na linha 15, invoca a função fatorial(), passando o valor digitado como parâmetro. Dentro da função fatorial(), enquanto o valor for diferente de 1, a função chamará a si própria, criando instâncias na memória, passando a cada vez como parâmetro o valor decrementado de 1. Quando o valor chegar a 1, a função retorna o próprio valor, permitindo assim o retorno da multiplicação dos valores encontrados em cada instância. Veja que os resultados só são obtidos quando a função chega no caso base e, então, começa a “devolver” o resultado para a instância anterior.
Técnica de recursividade ou estruturas de repetição?
A técnica de recursividade pode substituir o uso de estruturas de repetição, tornando o código mais elegante, do ponto de vista das boas práticas de programação. Entretanto, as funções recursivas podem consumir mais memória que as estruturas iterativas.
· Portanto, a recursividade é indicar quando um problema maior, pode ser dividido em instâncias menores do mesmo problema, porém considerando a utilização dos recursos computacionais que cada método empregará.
Veja um exemplo clássico de cálculo do fatorial. O fatorial de um número qualquer N, consiste em multiplicações sucessivas até que N seja igual ao valor unitário, ou seja, 5! = 5 . 4 . 3 . 2 .1, que resulta em 120.
#include<stdio.h>
int fatorial(int valor) {
 if(valor != 1) { 
 //chamada recursiva
 return valor * fatorial(valor - 1); 
 } else {
 //critério de parada
 return valor;
 }
}
int main() {
 int n, resultado;
 printf("\nDigite um número inteiro positivo: ");
 scanf("%d", &n);
 resultado = fatorial(n);
 printf("\nResultado = %d", resultado);
 return 0;
}
TEXT
Digite um número inteiro positivo: 
Resultado = 120
HTML
Digite um número inteiro positivo: Resultado = 120
JXON
Digite um número inteiro positivo: 
Resultado = 120
Explicação
×
A execução inicia pela função principal, a qual solicita um número ao usuário e, na linha 15, invoca a função fatorial(), passando o valor digitado como parâmetro. Dentro da função fatorial(), enquanto o valor for diferente de 1, a função chamará a si própria, criando instâncias na memória, passando a cada vez como parâmetro o valor decrementado de 1. Quando o valor chegar a 1, a função retorna o próprio valor, permitindo assim o retorno da multiplicação dos valores encontrados em cada instância. Veja que os resultados só são obtidos quando a função chega no caso base e, então, começa a “devolver” o resultado para a instância anterior.
Recursividade em cauda
O mecanismo da função recursiva é custoso para o computador, pois tem que alocar recursos para as variáveis e comandos da função, procedimento chamado de empilhamento, e tem também que armazenar o local onde foi feita a chamada da função (OLIVEIRA, 2018). Para usar de forma mais otimizada a memória, existe uma alternativa chamada recursividade em cauda.
· Nesse tipo de técnica a recursividade funcionará como uma função iterativa (OLIVEIRA, 2018). Uma função é caracterizada como recursiva em cauda quando a chamada a si mesmo é a última operação a ser feita no corpo da função. Nesse tipo de função, o caso base costuma ser passado como parâmetro, o que resultará em um comportamento diferente.
Veja no exemplo como implementar o cálculo do fatorial usando essa técnica. Na linha 3, a função recursiva em cauda retorna o fatorial, sem nenhuma outra operação matemática e passa o número a ser calculado e o critério de parada junto. Foi preciso criar uma função auxiliar para efetuar o cálculo.
#include<stdio.h>
int fatorialCauda(int n) {
 return fatorialAux(n, 1);
}
int fatorialAux(int n, int parcial) {
 if (n != 1) {
 return fatorialAux(n - 1, parcial * n);
 } else {
 return parcial;
 }
}
int main() {
 int n, resultado;
 printf("\nDigite um número inteiro positivo: ");
 scanf("%d", &n);
 resultado = fatorialCauda(n);
 printf("\nResultado do fatorial = %d", resultado);
 return 0;
}
TEXT
Digite um número inteiro positivo: 
Resultado do fatorial = 120
HTML
Digite um número inteiro positivo: Resultado do fatorial = 120JSON
Digite um número inteiro positivo: 
Resultado do fatorial = 120
Explicação
×
Na linha 8 a função recursiva em cauda retorna o fatorial, sem nenhuma outra operação matemática, e passa o número a ser calculado e o critério de parada junto. Foi necessário criar uma função auxiliar para que o usuário possa calcular o fatorial passando apenas um número inteiro.
O mecanismo de funcionamento da recursividade em cauda é diferente. A função main() invoca a função fatorialCauda(), passando como parâmetro o valor a ser calculado. Esta, por sua vez, invoca a função fatorialAux, passando o valor a ser calculado e o critério de parada. A partir desse ponto, inicia a maior diferença entre as técnicas. Veja que as instâncias vão sendo criadas, porém, quando chega na última (nesse caso a instância 3), o resultado já é obtido e as funções não precisam retornar o valor para “quem” invocou, pois o comando que invoca a função era o último comando da função. Isso gera uma otimização na memória, pois não precisa armazenar nenhum ponto para devolução de valores.
Escopo e passagem de parâmetros
Nesta webaula vamos ver sobre escopo de variáveis, bem como a passagem de parâmetros em uma função.
Escopo de variáveis
As variáveis são usadas para armazenar dados temporariamente na memória, porém o local onde esse recurso é definido no código de um programa determina seu escopo e sua visibilidade.
Veja a seguir um exemplo de variáveis em funções.
#include<stdio.h>
int testar(){
 int x = 10;
 return x;
}
int main(){
 int x = 20;
 printf("\n Valor de x na função main() = %d", x);
 printf("\n Valor de x na função testar() = %d", testar());
 return 0;
}
TEXT
Valor de x na função main() = 20
 Valor de x na função testar() = 10
HTML
Valor de x na função main() = 20 Valor de x na função testar() = 10
JSON
Valor de x na função main() = 20
 Valor de x na função testar() = 10
No exemplo, há duas variáveis chamadas “x”, mas isso não acarreta erro, pois mesmo as variáveis tendo o mesmo nome elas são definidas em lugares diferentes, uma está dentro da função main() e outra dentro da testar() e cada função terá seu espaço na memória de forma independente. Na memória, as variáveis são localizadas pelo seu endereço, portanto mesmo sendo declaradas com o mesmo nome, seus endereços são distintos.
O escopo é dividido em duas categorias: local ou global.
Variáveis locais
Elas existem e são “enxergadas” somente dentro do corpo da função onde foram definidas.
Variáveis globais
Elas existem e são “enxergadas” por todas as funções do programa.
No exemplo anterior, ambas as variáveis são locais.
No exemplo a seguir, veja a declaração e uso da variável global.
Sua inclusão é feita após a biblioteca de entrada e saída padrão. Na função principal não foi definida nenhuma variável com o nome de “x” e mesmo assim pode ser impresso seu valor na linha 10, pois é acessado o valor da variável global. Já na linha 12 é impresso o valor da variável global modificado pela função testar(), que retorna o dobro do valor.
#include<stdio.h>
int x = 10;
void testar(){
 x = 2 * x;
}
int main(){
 printf("\nValor de x global = %d", x);
 testar();
 printf("\nValor de x global alterado em testar() = %d", x);
 return 0;
}
TEXT
Valor de x global = 10
Valor de x global alterado em testar() = 20
HTML
Valor de x global = 10 Valor de x global alterado em testar() = 20
JSON
Valor de x global = 10
Valor de x global alterado em testar() = 20
Vamos ver um exemplo de utilização do escopo global de uma variável, um programa que calcula a média entre duas temperaturas distintas. Na linha 2 foram declaradas duas variáveis. O programa inicia a execução na linha 8. Na 9 é solicitado ao usuário digitar duas temperaturas, as quais são armazenadas dentro das variáveis globais criadas. Na linha 11 a função calcularMedia()é invocada para fazer o cálculo da média usando os valores das variáveis globais.
#include<stdio.h>
float t1, t2;
float calcularMedia(){
 return (t1 + t2) / 2;
}
int main() {
 printf("\nDigite as duas temperaturas: ");
 scanf("%f %f", &t1, &t2);
 printf("\nA temperatura média é %.2f ºC", calcularMedia());
 return 0;
}
TEXT
Digite as duas temperaturas: 
A temperatura média é 15.80 ºC
HTML
Digite as duas temperaturas: A temperatura média é 15.80 ºC
JSON
Digite as duas temperaturas: 
A temperatura média é 15.80 ºC
Variável global e local com mesmo nome
Na linguagem C, para conseguirmos acessar o valor de uma variável global, dentro de uma função que possui uma variável local com mesmo nome, devemos usar a instrução extern (MANZANO, 2015). Veja no exemplo, que foi necessário criar uma nova variável chamada “b”, com um bloco de instruções (linhas 8 – 11), que atribui a nova variável o valor “externo” de x.
#include<stdio.h>
int x = 10;
int main(){
 int x = -1;
 int b;
 {
 extern int x;
 b = x;
 }
 printf("\n Valor de x = %d",x);
 printf("\n Valor de b (x global) = %d",b);
 return 0;
}
TEXT
 Valor de x = -1
 Valor de b (x global) = 10
HTML
Valor de x = -1 Valor de b (x global) = 10
JSON
 Valor de x = -1
 Valor de b (x global) = 10
Passagem de parâmetros para funções
Ao definir uma função, pode-se também estabelecer que ela receberá informações “de quem” a invocou, ou seja, “quem chamar” a função deve informar os valores, sobre os quais o cálculo será efetuado. Ao criar uma função que recebe parâmetros é preciso especificar qual o tipo de valor que será recebido. Uma função pode receber parâmetros na forma de valor ou de referência (SOFFNER, 2013). 
Veja a seguir, a sintaxe utilizada:
<tipo de retorno> <nome> (<parâmetros>) {
   <Comandos da função>
   <Retorno> (não obrigatório)
} 
Passagem por valor
Na passagem parâmetros por valores, a função cria variáveis locais automaticamente para armazenar esses valores e após a execução da função essas variáveis são liberadas. Veja a seguir, um exemplo de definição e chamada de função com passagem de valores.
#include<stdio.h>
void testar(int n1, int n2){
 n1 = -1;
 n2 = -2;
 printf("\n\nValores dentro da função testar(): ");
 printf("\nn1 = %d e n2 = %d", n1, n2);
}
int main(){
 int n1 = 10;
 int n2 = 20;
 printf("\nValores antes de chamar a função testar(): ");
 printf("\nn1 = %d e n2 = %d", n1, n2);
 testar(n1, n2);
 printf("\n\nValores depois de chamar a função testar(): ");
 printf("\nn1 = %d e n2 = %d", n1, n2);
 return 0;
}
TEXT
Valores antes de chamar a função testar(): 
n1 = 10 e n2 = 20
HTML
Valores antes de chamar a função testar(): n1 = 10 e n2 = 20 Valores dentro da função testar(): n1 = -1 e n2 = -2 Valores depois de chamar a função testar(): n1 = 10 e n2 = 20
JSON
Valores antes de chamar a função testar(): 
n1 = 10 e n2 = 20
Explicação
×
Na linha 13, o comando determina a impressão dos valores das variáveis, na linha 14, a função testar() é invocada passando como parâmetro as duas variáveis. Nesse momento, é criada uma cópia de cada variável na memória para utilização da função. Veja que dentro da função o valor das variáveis é alterado e impresso, mas essa alteração é local, ou seja, é feita na cópia dos valores e não afetará o valor inicial das variáveis criadas na função principal. Na linha 19, imprimimos novamente os valores após a chamada da função.
· Ao utilizar variáveis como argumentos, na passagem de parâmetros por valores, essas variáveis não são alteradas, pois é fornecido uma cópia dos valores armazenados para a função (SOFFNER, 2013). 
Passagem por referência
A utilização funções com de passagem de parâmetros por referência está diretamente ligada aos conceitos de ponteiro e endereço de memória. A ideia da técnica é análoga a passagem por valores, ou seja, a função será definida de modo a receber certos parâmetros de “quem” faz a chamada do método deve informar esses argumentos. Entretanto, o comportamento e o resultado são diferentes.
· Na passagem por referência não será criada uma cópia dos argumentos passados, na verdade, será passado o endereço da variável e função irá trabalhar diretamentecom os valores ali armazenados (SOFFNER, 2013).
Como a função utiliza o endereço (ponteiros), na sintaxe serão usados os operadores * e & (MANZANO, 2015). 
Na definição da função os parâmetros a serem recebidos devem ser declarados com *, por exemplo:
int testar(int* parametro1, int* parametro2)
Na chamada da função os parâmetros devem ser passados com o &, por exemplo: 
resultado = testar(&n1,&n2) 
#include<stdio.h>
void testar(int* n1, int* n2){
 *n1 = -1; // o operador * permite acessar o valor da variável
 *n2 = -2;
 printf("\n\nValores dentro da função testar(): ");
 printf("\nn1 = %d e n2 = %d", *n1, *n2);
}
int main(){
 int n1 = 10;
 int n2 = 20;
 printf("\nValores antes de chamar a função testar(): ");
 printf("\nn1 = %d e n2 = %d", n1, n2);
 testar(&n1, &n2);
 printf("\n\nValores depois de chamar a função testar(): ");
 printf("\nn1 = %d e n2 = %d", n1, n2);
 return 0;
}
TEXT
Valores antes de chamar a função testar(): 
n1 = 10 e n2 = 20
HTML
Valores antes de chamar a função testar(): n1 = 10 e n2 = 20 Valores dentro da função testar(): n1 = -1 e n2 = -2 Valores depois de chamar a função testar(): n1 = -1 e n2 = -2
JSON
Valores antes de chamar a função testar(): 
n1 = 10 e n2 = 20
Explicação
×
A única diferença desse código para o anterior é a utilização dos operadores * e &, porém, o resultado é completamente diferente. Com a passagem por referência os valores das variáveis são alterados. 
Nas linhas 4 e 5, usamos asterisco para acessar o conteúdo guardado dentro do endereço que ele aponta, pois se usássemos somente n1 e n2 acessaríamos o endereço que eles apontam.
Passagem de vetor
Esse recurso pode ser utilizado para criar funções que preenchem e imprimem o conteúdo armazenado em um vetor, evitando a repetição de trechos de código.  Na linguagem C, a passagem de um vetor é feita implicitamente por referência. Isso significa que mesmo não utilizando os 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 parâmetros a serem recebidos devem ser declarados com colchetes sem especificar o tamanho, por exemplo:
int testar(int v1[], int v2[]) 
Na chamada da função os parâmetros devem ser passados como se fossem variáveis simples, por exemplo:
 resultado = testar(n1,n2)
No exemplo a seguir o programa por meio de uma função preenche um vetor de três posições e em outra função percorre o vetor imprimindo o dobro de cada valor do vetor.
#include<stdio.h>
void inserir(int a[]) {
 int i = 0;
 for(i = 0; i < 3; i++){
 printf("\nDigite o valor %d: ", i);
 scanf("%d", &a[i]);
 }
}
void imprimir(int b[]) {
 int i = 0;
 for(i = 0; i < 3; i++){
 printf("\nNúmero[%d] = %d", i, 2 * b[i]);
 }
}
int main(){
 int numeros[3];
 printf("\nPreenchendo o vetor... \n ");
 inserir(numeros);
 printf("\n\nDobro dos valores informados:");
 imprimir(numeros);
 return 0;
}
TEXT
Preenchendo o vetor... 
 
Digite o valor 0: 
Digite o valor 1: 
HTML
Preenchendo o vetor... Digite o valor 0: Digite o valor 1: Digite o valor 2: Dobro dos valores informados: Número[0] = 2 Número[1] = 4 Número[2] = 6
JSON
Preenchendo o vetor... 
 
Digite o valor 0: 
Digite o valor 1: 
Explicação
×
O código que começa a ser executado pela linha 17. 
Na linha 20, a função inserir() é invocada, passando como parâmetro o vetor “numeros”. Propositalmente criamos a função na linha 3, recebendo como argumento um vetor de nome “a”, para que você entenda que o nome da variável que a função recebe não precisa ser o mesmo nome usado na chamada. Na maioria das vezes, utilizamos o mesmo nome como boa prática de programação.
Na função inserir(), será solicitado ao usuário digitar os valores que serão armazenados no vetor “numeros”, pois foi passado como referência implicitamente. Após essa função finalizar, a execução vai para a linha 21 e depois para a 22, na qual é invocada a função imprimir(), novamente passando o vetor “numeros” como argumento.
Mais uma vez, criamos a função na linha 11 com o nome do vetor diferente para reforçar que não precisam ser os mesmos. Nessa função o vetor é percorrido, imprimindo o dobro de cada valor. 
Pilhas
Pilhas
Uma pilha tem como definição básica ser um conjunto de elementos ordenados que permite a inserção e a remoção de mais elementos em apenas uma das extremidades da estrutura denominada topo da pilha. (TENENBAUM, LANGSAM e AUGENSTEIN, 2007). Assim, um novo elemento que é inserido passa a ser o topo da pilha, e o único elemento que pode ser removido da pilha é o elemento que está no topo.
Modelo de estrutura de dados pilha
Fonte: elaborada pelo autor.
Os elementos inseridos em uma pilha apresenta, uma sequência de inserção. O primeiro elemento que entra na pilha só pode ser removido por último, após todos os outros elementos serem removidos.
Segundo Celes, Cerqueira e Rangel (2004), os elementos da pilha só podem ser retirados na ordem inversa da ordem em que nela foram inseridos. Isso é conhecido como LIFO (last in, first out, ou seja, o último que entra é o primeiro a sair) ou FILO (first in, last out, ou seja, primeiro que entra é o último a sair). 
Inserindo elemento na pilha
Fonte: elaborada pelo autor.
Removendo um elemento da pilha
Fonte: elaborada pelo autor.
Operações de pilhas
Uma pilha também pode estar no estado de pilha vazia quando não houver elementos. Segundo Celes, Cerqueira e Rangel (2004), os passos para a criação de uma pilha são:
· Criar uma pilha vazia.
· Inserir um elemento no topo.
· Remover o elemento do topo.
· Verificar se a pilha está vazia.
· Liberar a estrutura de pilha.
Empilhar e desempilhar
A operação de empilhar um novo elemento, segundo Lorenzi, Mattos, Carvalho (2015), tem a função de inserir um novo elemento na pilha, e definida na programação em C++ como push(). Já a operação de desempilhar , tem a função de remover um elemento do topo da Pilha e utilizada na programação em C++ como pop().
Fonte: elaborada pelo autor.
Conforme Drozdek(2016), outras operações que podem ser implementadas na pilha são as funções clear(), para limpar a
pilha e isEmpty(), para verificar se a pilha está vazia.
Conforme Tenenbaum (2007), uma pilha possui uma estrutura que pode ser declarada contendo dois objetos:
· Um ponteiro, que irá armazenar o endereçamento inicial da pilha.
· Um valor inteiro, que irá indicar a posição no topo da pilha.
A seguir, veja as implementações de pilha:
Declaração da estrutura inicial
struct Pilha {
	int topo;
	int capacidade;
	float * proxElem;
};
struct Pilha minhaPilha;
Criar a pilha
void cria_pilha(struct Pilha *p, int c ){
 p -> proxElem = (float*) malloc (c * sizeof(float));
 p -> topo = -1;
 p -> capacidade = c;
}
Inserir elemento na pilha
void push_pilha(struct Pilha *p, float v){
	p -> topo++;
	p -> proxElem [p -> topo] = v;
}
Fonte: elaborada pelo autor
Remover elemento da pilha
float pop_pilha (struct Pilha *p){
 float aux = p -> proxElem [p -> topo];
 p -> topo--;
 return aux;
}
Fonte: elaborada pelo autor
Informar se a pilha está vazia
/*Declaração da função pilha_vazia com passagem da pilha por parâmetro*/
int pilha_vazia (struct Pilha *p ){ 
 if( p -> topo == -1 ) 
 return 1; /*Sendo o topo igual a -1, a função retorna verdadeiro*/
 else
 return 0; /*Caso contrário, a função retorna verdadeiro*/
}
Verificar se a pilha está cheia
int pilha_cheia ( struct Pilha *p ){
	if (p -> topo == p -> capacidade - 1)
		return 1;
	else
		return 0;
}
Problema do Labirinto
Os labirintos são desafios criados como problematização de estrutura de dados. 
Em um labirinto, por exemplo, para encontrar um caminho correto, podemos andar pelo labirinto até que se encontre uma divisão neste caminho. Caso o caminho escolhido não possua uma saída, é removido o ponto anterior da pilha, voltando ao último ponto em que o labirinto se dividiu e recomeçamos por um outro caminho ainda não escolhido, adicionando na pilha o novo caminho.
A seguir,um trecho de implementação de criação de uma solução para labirinto:
/*Chama a função inicLabirinto, passando o labirinto, a pilha, o valor da linha e da coluna como passagem de parâmetros*/
void inicLabirinto(Labirinto *l, Pilha *p_l, int linha, int coluna){
 int i, j, flag = 0;
 char aux;
 elem_t_pilha origem;
/*Aplicamos uma rotina em matriz para verificar se a posição foi visitada (1) ou não (0)*/
 for(i = 0 ; i < linha ; i++){
 for(j = 0 ; j < coluna ; j++){
 if(l->p[i][j].tipo == '0'){
 l->p[i][j].visitado = 1; //Visitado
 origem.x = i;
 origem.y = j;
 /*Insere na pilha a posição de origem*/
 push(p_l, origem);
 }
 }
 }
}
Backtracking
As pilhas podem ser aplicadas também no uso de algoritmos de Backtracking, que consiste em criar marcações para onde o algoritmo pode retornar. Podem ser aplicados também como operação de desfazer, existente em diversas aplicações de usuários, como a utilização deste algoritmo em sistema de GPS. Quando o motorista utiliza uma rota não indicada pelo programa, o algoritmo de Backtracking é aplicado para redefinir a nova rota.
O algoritmo de Backtracking tem como meta resolver o problema no menor intervalo de tempo possível, sem levar em consideração o esforço de operações para alcançar a solução do problema.
Filas
Fila
Uma fila é a representação de um conjunto de elementos. Podemos remover esses elementos deste conjunto por uma extremidade chamada de início da fila, e pela outra extremidade, na qual são inseridos os elementos, chamada de final da fila (TENENBAUM, LANGSAM e AUGENSTEIN, 2007). 
Assim como uma pilha, as filas também são estruturas dinâmicas com tamanho variável, podendo aumentar ou diminuir conforme são inseridos ou removidos elementos da fila.
Exemplo de uma estrutura de dados do tipo fila
Fonte: elaborada pelo autor.
Em uma fila os elementos entram por uma extremidade e são removidos pela outra extremidade. Isso é conhecido como FIFO (first in, first out, ou seja, o primeiro que entra é o primeiro a sair). No caso desta fila, sabemos quais os elementos com base em seu número de índice. Assim, a fila apresenta sua ordem de entrada (fim da fila) e sua ordem de saída dos elementos (início da fila).
Entrada de elemento pelo final da fila
Fonte: elaborada pelo autor.
Saída de elemento pelo início da fila
Fonte: elaborada pelo autor.
Operações de filas
Segundo Drozdek (2016), a estrutura de dados de fila possui operações similares as da estrutura de pilha para gerenciamento de uma fila, como:
· Criar uma fila vazia.
· Inserir um elemento no fim da fila.
· Remover o elemento do início da fila.
· Verificar se a fila está vazia.
· Liberar a fila.
Conforme Celes, Cerqueira e Rangel (2004), podemos simplesmente utilizar um vetor para armazenar os elementos e implementarmos uma fila nessa estrutura de dados, ou podemos utilizar uma alocação dinâmica de memória para armazenar esses elementos.
A seguir, veja as implementações de fila:
Declaração da estrutura inicial
#define N 100
struct fila {
	int n;
	int ini;
	char vet[N];
};
typedef struct fila Fila;
A seguir, veja as implementações de fila:
Declaração da estrutura inicial
#define N 100
struct fila {
	int n;
	int ini;
	char vet[N];
};
typedef struct fila Fila;
Inicializar a fila
Fila* inicia_fila (void){
	Fila* f = (Fila*) malloc(sizeof(Fila));
	f -> n = 0; 
	f -> ini = 0;
	return f;
}
Inserir elemento na fila
void insere_fila (Fila* f, char elem){
	int fim;
	if (f -> n == N){ 
		printf("A fila está cheia.\n");
		exit(1); 
	}
	fim = (f -> ini + f -> n) % N;
	f -> vet[fim] = elem;
	f -> n++;
}
Fonte: elaborada pelo autor
Remover elemento na fila
float remove_fila (Fila* f){
	char elem;
	if (fila_vazia(f)){
		printf("A Fila esta vazia\n");
		exit(1); 
	}
	elem = f -> vet[f -> ini];
	f -> ini = (f -> ini + 1) % N;
	f -> n--;
	return elem;
}
Fonte: elaborada pelo autor
Informar se a fila está vazia
int fila_vazia (Fila* f){
	return (f -> n == 0);
}
Liberar alocação de memória
void libera_fila(Fila* f){
	free(f);
}
ilas Circulares
Segundo Silva (2007), as filas não apresentam uma solução completa, sendo que, mesmo chegando ao final do vetor poderemos ter a fila cheia mesmo não estando cheia, uma vez que elementos podem ter sido removidos e para isso, podemos utilizar as Filas Circulares como solução para esta situação. A Fila Circular possui a seguinte definição, em sua implementação:
Um vetor para os elementos
Um valor inteiro para o tamanho da fila
Um valor inteiro para o início da fila
Um valor inteiro para o fim da fila
Conforme Drozdek (2016), em uma Fila Circular, o conceito de circularidade se baseia quando o último elemento da fila está na última posição do vetor, e é adjacente à primeira. Assim, são os ponteiros, e não os elementos da fila que se movem em direção ao início do vetor. 
Estrutura da fila circular
Fonte: elaborada pelo autor.
Para implementar uma estrutura de fila circular, podemos utilizar como exemplo o código a seguir:
Definição da constante
/* Vamos definir a constante N com valor de 10 */
#define N 10
struct filacirc { /* Criação da estrutura da Fila Circular */
	int tam, ini, fim;
	char vet[N];
};
typedef struct filacirc FilaCirc;
Função para inicializar a fila
/* Função para inicializar a Fila */ 
void inicia_fila (FilaCirc *f){
	f -> tam = 0;
	f -> ini = 1;
	f -> fim = 0;
}
Função para inserir a fila
/* Função para inserir na Fila */ 
void insere_fila (FilaCirc* f, char elem){
	if (f -> tam == N - 1){ /* Verifica se a Fila está completa */
		printf("A fila esta cheia\n");
	} else { /* Caso a Fila não esteja completa, inserimos o elemento */
		f -> fim = (f -> fim % (N - 1)) + 1;
		f -> vet[f -> fim] = elem;
		f -> tam++;
	}
}
Verificar se a fila está vazia
int fila_vazia (FilaCirc* f){
	return (f -> tam == 0); /* Retorna verdadeiro se a Fila estiver vazia */
}
Remover da fila
char remove_fila (FilaCirc* f){
	if (fila_vazia(f)){ /* Verifica se a Fila está vazia */
		printf("Fila vazia\n");
	} else { /* Caso a Fila contenha elemento, é removido o primeiro */
		f -> ini = (f -> ini % (N-1)) + 1;
		f -> tam--;
	}
}
Problemas com a utilização de fila
Considerando a utilização de uma fila, alguns problemas podem surgir. 
· Utilização de vetor
Se utilizarmos um vetor, teremos o problema de possuir um armazenamento de tamanho fixo e limitado, enquanto a fila pode crescer com a necessidade de uso do sistema. Para resolver essa problemática, teríamos que limitar o tamanho máximo da fila ao tamanho do vetor.
· Fila cheia ou fila vazia
Em ambos os casos seria impossível realizar as operações. Como solução, é importante sempre implementar as funções para verificar se a fila está cheia (fila_cheia(F)) e para verificar se ela está vazia (fila_vazia(F)).
· Identificação das posições da fila
Podem surgir problemas relacionados aos controles de início e fim de fila, em que não é possível identificar as posições em que se encontram. Como solução, é preciso incluir duas variáveis (inicio e fim) para armazenar a posição do início e do fim da fila, e sempre atualizar esses valores conforme a fila aumenta ou diminui.
Colocando em prática:
Resposta: F-V-F
Resposta: F-V-F
Resposta: V-V-V
Resposta: F-V-V
Resposta: V-V-F
A passagem de parâmetro por valor cria uma cópia, a passagem de parâmetro por referência não cria uma cópia dos argumentos passados. A afirmativa é falsa por não ter especificado, criando uma generalização. 
Resposta: F-V-V
Resposta: F-V-F
 O Pseudocódigo é uma forma genérica de escrever um algoritmo, utilizando uma linguagem simples (nativa a quem o escreve, de forma a ser entendida por qualquer pessoa) sem necessidade de conhecer a sintaxe de nenhuma linguagem de programação. 
 Um algoritmo é uma sequência finita de ações executáveis que visam obter uma solução para um determinado tipo de problema. São procedimentos precisos, não ambíguos, padronizados, eficientes e corretos.
Os algoritmos são utilizados em, basicamente, todas as nossas ações diárias, como, por exemplo, levantar da camae se preparar para então começar um dia de trabalho ou seguir todos os dias o mesmo caminho e pegar o mesmo ônibus para chegar a um determinado ponto. É um passo a passo de ações. Assim funciona um algoritmo.
Algoritmos nas buscas do Google
A nossa forma de pesquisa mais eficiente na atualidade conta com a presença de algoritmos para que o usuário tenha o resultado esperado em suas buscas na internet. No Google, os algoritmos funcionam da seguinte forma:
1. você digita algo no Google;
2. o buscador filtra milhões de páginas na internet de acordo com o que ele acredita ser mais relevante e útil;
3. é feita então uma análise das palavras empregadas na pesquisa, ocorrendo a busca por links que possuam maior relação com o tema procurado, seja em títulos, no decorrer do texto ou em hiperlinks.
A ferramenta também usa como critério a experiência de outros usuários com as páginas e os dados de publicação dos posts.
O algoritmo abaixo esta escrito em pseudocódigo e tem como objetivo realizar a leitura de três nomes, armazenar e no final imprimir os nomes:
algoritmo "nomes"
var
  nome1, nome2, nome3: caractere
inicio
escreva("Informe o primeiro nome ")
leia(nome1)
escreva("Informe o segundo nome ")
leia(nome2)
escreva("Informe o terceiro nome ")
leia(nome3)
escreva("Os nomes informados foram: ", nome1 - nome2 - nome 3)
fimalgoritmo
Atividades 
1 Pseudocódigos é considerado uma ferramenta que pode auxiliar a programação, ela pode ser escrita em palavras similares ao inglês ou português para facilitar a interpretação e desenvolvimento de um programa. Neste contexto, analise o seguinte algoritmo escrito em pseudocódigo.
 
var
real: v1, v2, v3, v4, N1, x;
Início
escreva (“Digite Nota 1:”);
leia v1;
escreva (“Digite Nota 2:”);
leia v2;
escreva (“Digite Nota 3:”);
leia v3;
escreva (“Digite Nota 4:”);
leia v4;
N1 ¿ v1 + v2 + v3 + v4;
x ¿ N1 / 4;
escreva(“Resultado = ”, x);
Fim.
Agora, assinale a alternativa correta.
Alternativas:
a)
Este algoritmo armazena as notas em variáveis para depois realizar um calculo onde o restado final é armazenado em X e por fim é exibido.
Alternativa assinalada
b)
Este algoritmo armazena as notas em variáveis para depois realizar um calculo onde o restado final é armazenado em N1 e por fim é exibido.
c)
Este algoritmo não armazena as notas em variáveis, o calculo é realizado diretamente em N1 e o restado final é armazenado em X e por fim é exibido.
d)
Este algoritmo não armazena as notas em variáveis, o calculo é realizado diretamente em X e o restado final é armazenado em N1 e por fim é exibido.
e)
Este algoritmo não exibi nenhum resultado.
2)
A lógica de programação pode ser definida como uma técnica de encadear pensamentos para atingir determinado objetivo. Ela faz-se necessária para desenvolver programas e sistemas, pois permite definir a sequência lógica para a solução de um problema.
 
	1
	var
   real: x, y, z;
	2
	Início
	3
	   escreva (“Digite um Numero:”);
   leia x;
   escreva (“Digite outro Numero:”);
   leia y;
	4
	   z ¿ x + z + 1;
   escreva(“Resultado = ”, z);
	5
	Fim.
 
Considerando o algoritmo apresentado, julgue as afirmações que seguem e marque (V) para verdadeiro ou (F) para falso.
 
(   ) A parte 1 do pseudocódigo indica a declaração das variáveis que são compatíveis com qualquer tipo de dados.
(   ) A parte 3 do pseudocódigo corresponde a entrada de dados do algoritmo.
(   ) A parte 4 do pseudocódigo corresponde tando a parte de processamento quanto a parte de saída de dados do algoritmo..
Agora, assinale a alternativa que contém sequência correta.
Alternativas:
a)
F - V - V.
Alternativa assinalada
b)
F - V - F.
c)
V - V - V.
d)
V - V - F.
e)
F - F - F.
3)
Variáveis com estruturas compostas do tipo vetor ou matriz, só são capazes de  armazenar valores de um mesmo tipo, porem, além das estruturas homogêneas as linguagens de programação oferecem um tipo de variável composta heterogênea chamada de estruturas (structs) ou ainda de registros.
Na linguagem C, a criação de uma estrutura deve ser feita antes da função main() e deve possuir a seguinte sintaxe:
Alternativas:
a)
struct <nome>; <tipo> <nome_da_variavel1>; <tipo> <nome_da_variavel2>; ... ;
b)
struct { <tipo> <nome_da_variavel1>; <tipo> <nome_da_variavel2>; ... };
c)
struct <nome>{ <nome_da_variavel1>; <nome_da_variavel2>; ... };
d)
struct <nome>{ <tipo> <nome_da_variavel1>; <tipo> <nome_da_variavel2>; ... };
Alternativa assinalada
e)
<nome> struct{ <tipo> <nome_da_variavel1>; <tipo> <nome_da_variavel2>; ... };
4)
Conforme Deitel e Deitel (2011) podemos utilizar a estrutura de um vetor para armazenar variáveis do mesmo tipo de dado. Um vetor é uma estrutura de dados homogênea e que deve ser declarado com a quantidade de elementos que a estrutura deverá armazenar.
Fonte: DEITEL, Paul; DEITEL, Harvey. C Como Programar. 6. ed. São Paulo: Pearson, 2011.
 
Observe o programa a seguir que faz a leitura de três notas utilizando um vetor.
 
	1.
2.
3.
4.
5.
6.
7.
8.
9.
10.
11.
12.
13.
14.
	#include <stdio.h>
int main ()
{
float nota[3],media=0;
printf("Digite a Primeira Nota");
scanf("%f",&nota[0]);
printf("Digite a Segunda Nota");
scanf("%f",&nota[1]);
printf("Digite a Terceira Nota");
scanf("%f",&nota[2]);
// cálculo da média
// impressão da média das notas
return 0;
}
 
Considerando  o programa apresentado, julgue as afirmativas a seguir  e marque  (V) para Verdadeiras ou (F) para  Falsas:
(  ) Na linha 11, para calcular a média devemos inserir o seguinte código:    media = (nota[0] + nota[1] + nota[2]) / 3;
(  ) Na linha 11, para calcular a média devemos inserir o seguinte código:    media = (nota[0] + nota[1] + nota[2] / 3);
(  ) Na linha 12, para imprimir a média devemos inserir o seguinte código:   printf ("A media das notas informadas  %.d\n", medias);
(  ) Na linha 12, para imprimir a média devemos inserir o seguinte código:  printf ("A media das notas informadas  %.2f\n", media);
Assinale a alternativa que apresenta a sequência correta.
Alternativas:
a)
V – F – V – F.
b)
V – F – F – V.
Alternativa assinalada
c)
V – V – F – F.
d)
V – V – V – V.
e)
F – F – F – F.
Atividades 
1) Segundo Schildt (1997), a estrutura condicional de seleção de casos, “switch-case”, “testa sucessivamente o valor de uma expressão contra uma lista de constantes inteiras ou de caractere”. Quando os valores são avaliados o comando é executado. É preciso estar atento para algumas particularidades para o comando switch / case: caso nenhum dos valores seja encontrado, o comando default será executado e os comandos são executados até o ponto que o comando break for localizado. Na figura a seguir, o fluxograma representa a estrutura condicional de seleção de casos:
 
Figura 5 - Fluxograma de estrutura condicional de seleção de casos
 
 
Fonte: do autor.
Assinale a alternativa que contém a sintaxe em C que representa o fluxograma da figura anterior.
Alternativas:
a)
case (variável)
{
case constante1:
<comandos>
break;
case constante2:
<comandos>
break;
default: <comandos>
}
 b)
 switch (variável)
{
case constante1:
>comandos<
break;
switch (variável)
case constante2:
<comandos>
break;
default: <comandos>
}
 c)
 {
switch (variável)
case constante1:
<comandos>
break;
case constante2:
<comandos>
break;
default: <comandos>
}
 d)
 switch (variável)
{
case constante1:
<comandos>
break;
case constante2:
<comandos>
break;
default: <comandos>
}
Alternativa assinalada
 e)
 {switch (variável)
case constante1:
<comandos>
break;
case constante2:
<comandos>
break;
default: <comandos>}
2)
 Existem casos em que é necessário estabelecer verificação de condições sucessivas, em que uma determinada ação poderá ser executada se um conjunto anterior de instruções ou condições for satisfeito. Sendo a ação executada, ela poderá ainda estabelecer novas condições. Isto significa utilizar uma condição dentro de outra condição. 
 Fonte:Disponível em<http://estruturacondicional.blogspot.com/2008/07/estrutura-condicional-encadeada.html>Acesso.11.Jul.2018 (Modificado)
Este tipo de estrutura poderá possuir diversos níveis de condição,sendo chamadas de:
Alternativas:
a)
alinhamentos.
b)
aninhamentos ou encadernamentos.
c)
encadernamentos.
d)
alinhamentos ou encadernamentos.
e)
aninhamentos ou encadeamentos.
Alternativa assinalada
3)
O laço do-while executa, pelo menos uma vez, o que está dentro dele e só ao final da execução é que ele faz o teste, usando o velho e conhecido laço while. Ou seja, tem-se a garantia que o laço vai ser executado uma vez, sem precisar inicializar variável ou pedir dados ao usuário antes do while. Vale lembra que do, em inglês e nesse contexto, do significa "faça" e while significa "enquanto".
 Fonte:Disponível em<Adaptado de https://www.cprogressivo.net/2013/02/O-que-e-e-como-usar-o-laco-DO-WHILE-em-linguagem-C.html>Acesso.16.Jul.2018.
Esse laço do-while quer dizer:
Alternativas:
a)
"faça isso" -> código -> "enquanto essa condição for verdadeira, repita".
Alternativa assinalada
b)
"faça aquilo" -> código -> "enquanto essa condição for verdadeira, repita".
c)
"faça isso" -> laço -> "enquanto essa condição for falsa, repita".
d)
"faça aquilo" -> laço -> "se essa condição for verdadeira, pare".
e)
"faça isso" -> código -> "se essa condição for verdadeira, pare".
4)
Na repetição com variáveis de controle, ou seja, usando o laço “for”, o comando iterativo “for” que em português significa “para”, segundo Mizrahi (2008), é geralmente usado para repetir uma informação por um número fixo de vezes, isto é, pode-se determinar quantas vezes acontecerá a repetição. Para facilitar ainda mais, veja a seguinte representação:
 
for(x = 10,y = 0; x >= 0, y <= 10; x--,y++)
 
Conforme esta representação, associe as colunas corretamente:
 
	Trecho do programa
	Representação
	I. (x = 10, y = 0;
	A.       O laço se repetirá enquanto x for maior ou
 igual a zero e enquanto y for menor ou igual a 10.
	II.  x >= 0, y <=10;
	B.       O “x”  tem o seu valor iniciado em “10” e 
“y” iniciado em “0”.
	III.   x--,y++)
	C.       x será decrementado de 1 e 
y será incrementado de 1.
Assinale a alternativa que contém a associação correta:
Alternativas:
a)
I-A ,  II-B, III-C.
b)
I-B,  II-C, III-A.
c)
I-C,  II-A , III-B.
d)
I-C,  II-B,  III-A.
e)
I-B,  II-A , III-C.
Alternativa assinalada
Atividades 
1) As funções são utilizadas nos programas para acelerar o processo de programação. Muitas vezes precisamos fazer o mesmo tipo de programa que tem a seguinte opção: “leia um vetor de N números”.  Para essa atividade, podemos criar uma função que gera automaticamente o vetor, utilizando a função rand (). A função rand () gera números aleatórios e basta então inserir esses números em um vetor.  Suponha que seja necessário ordenar o vetor. As linguagens de programação já possuem métodos de ordenação, os mais populares métodos de ordenação são: Insertion Sort, Selection Sort, Bubble Sort, Comb Sort, Quick Sort, Merge Sort, Heap Sort e Shell Sort.
 
Observe atentamente o programa que demonstra o uso das funções para gerar o vetor e para ordenar o vetor com o método Bubble Sort:
 
	#include<stdio.h>
#include <stdlib.h>
int r[10];
 
void gerarRandomico(){
int a;
for(a = 0; a < 10; ++a) {
r[a] = rand()%100;
}}
 
void ordena(){
 int i, j, aux;
for( i=0; i<10; i++ ){
  for( j=i+1; j<10; j++ ){
    if( r[i] > r[j] ){
      aux = r[i];
      r[i] = r[j];
      r[j] = aux;
    }}}}
 
int main(){
int i;
gerarRandomico();
ordena();
for ( i = 0; i < 10; i++ ) {
printf("\n Vetor[%d] = %d", i, r[i]);}
return 0; }
 
Tomando como referência o contexto apresentado, julgue as afirmativas a seguir em (V) Verdadeiras ou (F) Falsas .
(    ) Uma função criada para retornar um valor char, o comando return somente poderá retornar o valor char.
(    ) Uma função pode ser chamada quantas vezes forem necessárias para realizar uma tarefa, a única exceção é de que não podemos fazer essa chamada dentro de uma estrutura de repetição for ( ), somente poderá ser utilizado o comando while ( ).
(    ) No programa apresentado, existem duas funções que não utilizam o return porque elas são do tipo void.
(    ) A variável que foi utilizada no comando for ( i = 0; i < 10; i++ ) foi declarada como tipo int e deveria ser float pois, quando usamos vetores os números podem ser maiores.
(    ) No programa apresentado foi utilizado duas funções pois, cada função tem um objetivo específico, devemos evitar misturar as funcionalidades das funções.
Assinale a alternativa que apresenta a sequência correta:
Alternativas:
a)
V – V – V – V – V.
b)
F – V – V – F – V.
c)
F – F – V– F – V.
d)
V – F – V – F – V.
Alternativa assinalada
e)
F – F – F – F – F.
2)
 É comum utilizarmos ponteiros com funções. Um caso importante de ponteiros com funções é na alocação de memória dinâmica. A função malloc ( ) pertencente a biblioteca <stdlib.h> é usada para alocar memória dinamicamente. Entender o tipo de retorno dessa função é muito importante, principalmente para seu avanço, quando você começar a estudar estruturas de dados.
 
Observe atentamente o programa que demonstra o uso de funções:
 
	#include<stdio.h>
#include<stdlib.h>
int* alocar(){
return malloc(200);
}
int main(){
int *memoria;
memoria = alocar();
if(memoria != NULL){
printf("Endereço de memória alocada = %x",memoria);
}
else{
printf("Memória não alocada");
}
return 0;
}
 Conforme demonstrado no programa apresentado a função malloc ( ) irá reservar um espaço de memória dinamicamente, a função malloc ( ) pode retornar dois valores e são eles:
Alternativas:
a)
 null  ou um ponteiro genérico (ponteiro genérico é do tipo void)
Alternativa assinalada
b)
 int  ou um ponteiro genérico (ponteiro genérico é do tipo void)
c)
 float  ou um ponteiro genérico (ponteiro genérico é do tipo void)
d)
 char  ou numérico (int ou float)
e)
 string  ou  null
3)
O escopo é dividido em duas categorias, local ou global. Quando se tem variáveis que ambas são locais, elas existem e são notadas somente dentro do corpo da função onde foram definidas. Para definir uma variável global é preciso criá-la fora da função, assim ela será visível por todas as funções do programa.
Fonte: SCHEFFER, V.C. Escopo e passagem de parâmetros.
 
 Nesse contexto, analise as asserções a seguir:
I - A utilização de variáveis globais permite dimensionar o uso da memória.
 II -  As  funções e procedimento tem  pouca relevância em programação.
III -  As variáveis locais são criadas e mantidas na memória ao fim da função
 IV - As variáveis globais permanecem na memória durante todo o tempo de execução.
É correto apenas o que se afirma em:
Alternativas:
a)
I e II.
b)
III e IV.
c)
II e III.
d)
I e IV.
Alternativa assinalada
e)
I, II, III e IV.
4)
Analise a figura a seguir.
 
 
Para compreender o mecanismo  apresentado na imagem anterior, organize as operações em sequência correta:
 
1 -  Chamada a função funcaoRecursiva(), que por sua vez, possui em seu corpo um comando que invoca a si mesma.
2 -  Na terceira instância, uma determinada condição de parada é satisfeita.
3 - Um novo espaço é alocado, com variáveis e comandos. Como a função é recursiva, novamente ela chama a si mesma, criando então a terceira instância da função.
4 -  Cada instância da função passa a retornar seus resultados para a instância anterior.
5 -  Nesse momento é criada a segunda instância dessa função na memória de trabalho.
Assinale a alternativa que contém a sequência correta:
Alternativas:
a)
1-3-5-2-4.
b)
4-5-3-2-1.
c)
1-5-3-2-4.
Alternativa assinalada
d)
1-5-2-4-3.
e)
2-5-1-3-4.
Atividades 
1) Na área da computação é comum que criemos analogias entre os conceitos e situações cotidianas, afim de facilitar o entendimento dos mesmos.
 
Com base nisso associe a COLUNA-A, que apresenta alguns elementos de programação, com a COLUNA-B, que apresenta alguns exemplos aplicáveis:
 
	COLUNA-A
	COLUNA-B
	I. Vetor
	A. Uma música em uma playlist criada pelo usuário.
	II. Índice do Vetor
	B. Edifício com 10 apartamentos.
	III. Lista ligada
	C. Brincadeira do amigo – secreto.
	IV - Elemento de uma lista
	D. O número de uma casa em uma rua.
A seguir assinale a alternativa que apresenta a associação correta.Alternativas:
a)
I - B; II - D; III - C; IV - A.
Alternativa assinalada
b)
I - B; II - C; III - D; IV - A.
c)
I - B; II - A; III - C; IV - D.
d)
I - C; II - D; III - B; IV - A.
e)
I - C; II - A; III - B; IV - D.
2)
As listas ligadas são estruturas de dados conhecidas por serem flexíveis quanto às suas operações e seu tamanho é dinâmico. Toda lista é composta por nós, e o nó é um conjunto de informações que permitem apontar para o próximo elemento.
Considere a organização das pessoas na fila do banco, porém seu funcionamento coerente depende do comportamento da lista ligada, então aplique o conceito de inserção em listas ligadas para assinalar a alternativa correta:
Alternativas:
a)
As listas só permitem inserção de elementos em seu início.
b)
As listas só permitem inserção de elementos em seu fim.
c)
As listas só permitem inserção de elementos em seu início ou seu fim.
d)
As listas permitem inserção de elementos em qualquer posição.
Alternativa assinalada
e)
As listas não permitem sobreposição ao inserir elementos.
3)
A declaração da estrutura inicial para criação de uma pilha pode ser implementada por:
 
struct Pilha {
int topo;
int capacidade;
float * proxElem;
};
struct Pilha minhaPilha;
 
Segundo Celes, Cerqueira e Rangel (2004), com a estrutura declarada é possível criar a função para criar uma pilha. Esta função aloca dinamicamente na memória o espaço para utilização da pilha. O trecho de código para criação da pilha pode ser implementado por:
 
void cria_pilha(struct Pilha *p, int c ){
p -> proxElem = (float*) malloc (c * sizeof(float));
p -> topo = -1;
p -> capacidade = c;
}
 
Com a função para criar a pilha realizada, ela estará vazia, ou seja, não terá nenhum elemento na pilha em sua criação. Assim, é possível criar a função que vai permitir ser inserido um novo elemento na pilha.
 Considerando os códigos apresentados, o  correto  formato  para inserir um novo elemento na pilha  usando o nome push( )  é 
Alternativas:
a)
void push-pilha(struct Pilha *p, float **v){
p -> topo++;
p -> proxElem [p -> topo] = v;
}
b)
void push_pilha(struct Pilha *p, float v){
p -> topo-+;
p -> proxElem [p -> topo] = v;
}
c)
void push_pilha(struct Pilha *p, float v){
p -> topo++;
p -> proxElem [p -> topo] = v;
}
Alternativa assinalada
d)
void push-pilha(struct Pilha /p, float v){
p -> topo+-;
p -> proxElem [p -> topo] = v;
}
e)
void push_pilha(struct Pilha /p, float v){
p -> topo++;
p -> proxElem [p -> topo] = v;
}
4)
Em uma fila, só é possível remover um elemento pelo seu início. É possível implementar o trecho de código a seguir para remoção do elemento e apresentar seu valor no retorno da função:
 
float remove_fila (Fila* f){
char elem;
if (fila_vazia(f)){
printf(“A Fila esta vazia\n”);
exit(1);
}
elem = f -> vet[f -> ini];
f -> ini = (f -> ini + 1) % N;
f -> n--;
return elem;
}
 
De acordo com o trecho, marque (V) verdadeiro ou (F) falso nas asserções a seguir:
 
(   ) Nesse trecho é possível observar que, antes de remover o elemento da fila, é preciso verificar se ela possui elementos, chamando a função fila vazia.
(   ) Caso a fila esteja vazia, a função apresenta uma mensagem informando ao usuário que não há elementos para serem removidos e finaliza a função.
(   ) Caso a fila possua elementos, a variável vet recebe o elemento da primeira posição da fila.
(   ) Assim, o início da fila volta para o elemento anterior.
(   ) Este elemento incrementa a quantidade de elementos e retorna o elemento removido.
Assinale a alternativa que contém a sequência correta:
Alternativas:
a)
V-F-V-F-V.
b)
F-V-F-V-F.
c)
F-V-V-F-V.
d)
V-V-F-F-F.
Alternativa assinalada
e)
V-F-F-V-F.
Atividades 
1)Sabemos que um algoritmo é uma sequência logica de procedimentos para conseguir chegar a um resultado desejado. Existem diversos tipos de algoritmos, dentre eles, podemos citar: Linguagem natural , Diagramas de blocos (fluxograma) e os Pseudocódigos. Neste contexto, relacione corretamente as colunas a seguir.
 
	Coluna -A
	Coluna -B
	a - Linguagem natural 
	1 - Um conjunto de símbolos gráficos, onde
 cada um desses símbolos representa ações
 especificas a serem executadas pelo computador.
	b - Diagramas de blocos (fluxograma)
	2 - Considerado uma ferramenta que pode auxiliar a programação, ela pode ser escrita em palavras similares ao inglês ou português para facilitar a interpretação e desenvolvimento de um programa.
	c - Pseudocódigos
	3 - Na definição geral é uma forma de comunicação
 entre as pessoas de diversas línguas, ela pode ser 
falada, escrita, gesticulada entre outras formas de
 comunicação, tem uma grande contribuição 
quando vamos desenvolver uma aplicação 
computacional, pois ela pode direcionar de forma 
simples e eficiente as descrições dos problemas e 
suas soluções.
Assinale a alternativa que apresenta a associação CORRETA:
Alternativas:
a)
a-3, b-1, c-2.
Alternativa assinalada
b)
a-3, b-2, c-1.
c)
a-1, b-3, c-2.
d)
a-1, b-2, c-3.
e)
a-2, b-3, c-1.
2)
Cada país e região tem sua língua nativa, dessa mesma forma ocorrem com as linguagem de programação, cada linguagem existe uma sintaxe a ser seguida, por isso é fundamental entender todos os componentes de uma determinada linguagem de programação, para conseguir programar.
 
Tomando como referência as definições e características de Algoritmos e Linguagem de Programação, julgue as afirmativas a seguir  e marque (V)  para verdadeiras ou (F) para falso.
(   ) Em algoritmos a forma de escrever (maiúsculas e minúsculas) não acarretará em erros, porém, em linguagem de programação C é preciso diferenciar as palavras em letras maiúsculas e minúsculas.
(   )  As sintaxes (instrução) deverão ser escritas e armazenada na memória do computador na mesma ordem que se espera ser executada, ou seja, ela pode ser linear
(executada sequencialmente) e não linear (executada de forma a serem redirecionadas, isto é, uma instrução de bifurcação).
(   ) Um programa é uma sequência de código organizada de tal forma que, na maioria dos casos, permita resolver um determinado problema. Um programa pode ser desenvolvido em módulos distintos e/ou em subprogramas.
Assinale a alternativa que apresenta a sequência correta.
Alternativas:
a)
V - F - V.
b)
V - V - F.
Alternativa assinalada
c)
F - V - V.
d)
F - V - F.
e)
V - V - V.
3)
Para se usar uma variável em uma linguagem de programação é preciso criá-la e para isso usase a seguinte sintaxe: <tipo> <nome_da_variavel>;
Com relação a criação de variáveis na linguagem C, complete as lacunas da sentença a seguir:
 
#include <stdbool.h>
void main(){
  ____ idade = 23;
  ____ salario = 750.50;  
  ____ confirma = false;
  ____ genero = 'M';
}
Assinale a alternativa que completa as lacunas corretamente:
Alternativas:
a)
float / float / char / bool.
b)
int / int / bool / char.
c)
float / int / char / bool.
d)
int / float / bool / char.
Alternativa assinalada
e)
bool / float / char / bool.
4)
Na programação, uma variável é um objeto (uma posição, frequentemente localizada na memória) capaz de reter e representar um valor ou expressão. Enquanto as variáveis só "existem" em tempo de execução, elas são associadas a "nomes", chamados identificadores, durante o tempo de desenvolvimento. Com relação aos tipos de variáveis, complete as lacunas da sentença a seguir:
 
Além das variáveis primitivas e compostas existe um tipo de variável muito especial na linguagem C chamada de ____________, são usadas exclusivamente para armazenar endereços de memória. Para acessa-las são usados dois operadores, o ____________ usado para criação do ponteiro e o ____________ usado para acessar o endereço da memória, por isso é chamado de operador de referência.
Assinale a alternativa que completa as lacunas corretamente:
Alternativas:
a)
ponteiro / * (asterisco) / & (e comercial)
Alternativa assinalada
b)
constante / * (asterisco) / || (duas barras)
c)
ponteiro / & (e comercial) / * (asterisco)
d)
constante / * (asterisco) / & (e comercial)
e)
ponteiro / * (asterisco) / || (duas barras)
Atividades 
1)A estrutura condicional possibilita a escolha de um grupo de açõese estruturas a serem executadas quando determinadas condições são ou não satisfeitas. A estrutura condicional pode ser simples ou composta. Nesse contexto, analise as asserções a seguir e marque (V) verdadeiro ou (F) falso:
 
(   ) A estrutura condicional simples executa um comando ou vários comandos se a condição for verdadeira.
(   ) Se a condição for falsa, a estrutura condicional simples é finalizada após executar todos os comandos.
(   ) O comando que define a estrutura condicional simples é representado pela palavra SE.
(   ) A estrutura condicional composta segue o mesmo princípio da estrutura condicional simples, com a diferença de que quando a condição não é satisfeita, o mesmo comando é executado até a condição ser satisfeita.
(   ) O comando que define a estrutura é representado pelas palavras SE e SENÃO.
Assinale a alternativa que contém a sequência correta:
Alternativas:
a)
V-V-F-F-V.
b)
F-F-V-V-F.
c)
V-F-F-F-V.
d)
F-V-F-V-F.
e)
V-F-V-F-V.
Alternativa assinalada
2)
Em lógica de programação, usa-se condições para tomar decisões no decorrer da execução de um programa. Através de estruturas condicionais é possível alterar todo o fluxo de processamento. Um exemplo simples de estrutura de decisão é uma conta corrente de um banco.
 Fonte: Disponível em<Adaptado de http://profanderson.blog.etecarmine.com.br/estrutura-condicional-se-senao/>Acesso.11.Jul.2018.
  Neste contexto, complete corretamente as lacunas da asserção a seguir:
Entende-se que ____________ realizar saques na conta se houver saldo disponível, caso contrário, o saque será negado. Esta decisão, basicamente, é ____________, ou seja, ____________, a condição será verdadeira e _____________, senão, a condição falsa ____________.
Assinale a alternativa que completa corretamente as lacunas:
Alternativas:
a)
somente será possível / um verdadeiro ou falso / se houver saldo / o saque será permitido / negará o saque.
Alternativa assinalada
b)
sempre será possível / falsa / se houver saldo / o saque será permitido / negará o saque.
c)
somente será possível / verdadeira / se não houver saldo / o saque será permitido / negará o saque.
d)
sempre será possível / um verdadeiro ou falso / sem saldo / o saque será bloqueado / permitirá o saque.
e)
somente será possível / um verdadeiro ou falso / sem saldo / o saque será bloqueado / negará o saque.
3)
Segundo Manzano (2013), para a solução de um problema é possível utilizar a instruça~o “if” para tomada de decisão e também criar desvios dentro de um programa para uma condição verdadeira ou falsa. Seguindo essa premissa, as repetições com teste no início – while, para deixar claro, acontecem para que algo seja repetidamente executado enquanto uma condição verdadeira for verificada, somente após a sua negativa essa condição será interrompida.
Sobre o comando while com teste no inicio é correto afirmar que:
Alternativas:
a)
“não executara´ nenhuma repetição e ações que ali dentro estiverem programadas sem antes testar uma condição.”
Alternativa assinalada
b)
“não executara´ nenhuma condição e ações que ali dentro estiverem programadas sem antes testar uma repetição.”
c)
“executara´ repetição e ações que ali dentro estiverem programadas, sem antes testar uma condição.”
d)
“não executara´ condição e ações que ali dentro estiverem programadas, sem antes que o programador tecle enter.”
e)
“executara´ inúmeras repetições e ações que ali dentro estiverem programadas antes de testar mais de uma condição.”
4)
Usando a estrutura de repetição “for”, os históricos e aplicações de estruturas de repetição determinísticas e os comparativos com estruturas condicionais, serão aplicados dentro da linguagem de programação. Para tal, será usada a repetição com variáveis de controle, ou seja, aplicar o laço “for”. Nesse contexto, complete corretamente a afirmativa a seguir:
O comando iterativo “for”, que em português significa “para”, segundo Mizrahi (2008), é:
Alternativas:
a)
geralmente usado para repetir várias informações por um número alternado de vezes, isto é, pode-se determinar quantas vezes acontecerá a repetição.
b)
geralmente usado para repetir uma informação por um número fixo de vezes, isto é, pode-se determinar quantas vezes acontecerá a repetição.
Alternativa assinalada
c)
raramente usado para repetir um comando por um número fixo de vezes, isto é, pode-se determinar quantas vezes acontecerá a repetição.
d)
raramente usado para repetir várias informações por um número fixo de vezes, isto é, pode-se determinar quantas vezes acontecerá a repetição.
e)
geralmente usado para repetir um comando por um número alternado de vezes, isto é, pode-se determinar quantas vezes acontecerá a repetição.
Atividades 
1) A modularização é uma técnica de programação que permite a divisão da solução de um problema, afim de diminuir a complexidade, tornar o código mais organizado e evitar a repetição de códigos. Em cada declaração da função alguns parâmetros são obrigatórios e outros opcionais, veja cada parâmetro: tipo de retorno da função, o nome da função, parênteses após o nome da função, parâmetros, comandos e o tipo de retorno da função.
 
Neste contexto, complete as lacunas da sentença a seguir:
 
Quando o tipo de retorno da função for do tipo void  esse ____________ não precisa ser usado, porém, quando não for void  é ____________. O valor a ser retornado em uma função tem que ser ____________ com o tipo de retorno, senão o problema dará um erro de ____________ em algumas linguagens, em outras retornará um valor errôneo. Na linguagem C, deverá ser retornado um valor de acordo com o ____________ de retorno da função.
Assinale a alternativa que completa as lacunas corretamente:
Alternativas:
a)
vetor / permitido / provável / programação / valor
b)
valor / válido / igualitário / estrutura / fator
c)
programa / provável / condizente / acesso / comando
d)
parâmetro / obrigatório / compatível / compilação / tipo
Alternativa assinalada
e)
arquivo / assentido / favorável / otimização / aspecto
2)
De acordo com Mizrahi (2008) uma das definições de função é que ela é uma sub-rotina usada em um programa. Na linguagem de programação C, denominamos função a um conjunto de comandos que realiza uma tarefa específica em um módulo dependente de código. Uma função é referenciada pelo programa principal através do nome atribuído a ela. A utilização de funções visa modularizar um programa, o que é muito comum em programação estruturada. Desta forma podemos dividir um programa em várias partes, no qual cada função realiza uma tarefa bem definida.
 
 
A sintaxe de uma função:
 
tipo_de_retorno nome_da_função (listagem de parâmetros)
{
   instruções;
   retorno_da_função;
}
Uma função é definida como um trecho de código escrito para solucionar um subproblema. Esses blocos são escritos tanto para:
Alternativas:
a)
aumentar a quantidade de linhas do programa, quanto para facilitar o trabalho do programador.
b)
evitar erros de compilação, quanto para depurar o programa afim de achar os futuros erros de código e lógica.
c)
dividir a complexidade de um problema maior, quanto para evitar a repetição de códigos.
Alternativa assinalada
d)
possibilitar o uso de ponteiros em funções que possuem vetores, quanto funções que não possuem vetores.
e)
usar funções com passagem de parâmetros por valor, quanto usar passagem de parâmetros por referência.
3)
As variáveis em C podem ser declaradas basicamente de três maneiras diferentes: dentro de uma função, fora de uma função, e como parâmetro de uma função. Essas três maneiras de declaração fazem com que as variáveis sejam chamadas de locais, globais ou parâmetros formais.
 Fonte:disponível em<http://www.di.ufpb.br/liliane/aulas/escopo.html>Acesso06.Ago.2018.
 Nesse contexto, julgue as seguintes afirmações
 I. As variáveis globais existem durante a execução de todo o programa.
 II. Uma variável local só pode ser utilizada pela função ou bloco que a declarou.
III. Os parâmetros formais são variáveis locais de uma função que são inicializadas no momento da chamada da função.
É corretoapenas o que se afirma em:
Alternativas:
a)
I.
b)
III.
c)
I e II.
d)
II e III.
e)
I, II e III.
Alternativa assinalada
4)
Embora a sintaxe da função recursiva seja similar as não recursivas, o funcionamento de ambas é bastante distinto e o mau uso dessa técnica pode acarretar em uso indevido de memória, muitas vezes chegando a travar a aplicação e o sistema. Para entender o processo,julgue as seguintes afirmações.
 I - A função recursiva chama a si própria até que um ponto de parada seja estabelecido, podendo ser alcançado através de uma estrutura condicional ou através de um valor informado pelo usuário.
 II -  No uso de uma função recursiva, os recursos são alocados em outro local da memória, ou seja, para cada chamada da função, novos espaços são destinados a execução do programa. E é justamente por esse ponto que o ponto de parada é crucial.
III - As variáveis criadas em cada instância da função na memória são dependentes, ou seja, quando as variáveis possuem nomes iguais, cada uma terá seu próprio endereço de memória, mas a alteração do valor em uma afetará a outra.
É correto apenas o que se afirma em:
Alternativas:
a)
I.
b)
II.
c)
III.
d)
I e II.
Alternativa assinalada
e)
II e III.
Atividades
1) Uma lista ligada ou lista encadeada é uma forma de estruturar dados para o seu armazenamento, ou seja, é determinar a forma de inseri-los ou remove-los, sendo necessário organizá-los em células e inserir um ponteiro que aponte para o primeiro elemento e outro que aponte para o seu fim.
 
Assim, toda vez que queremos manipular uma estrutura de dados em uma memória, ou em uma unidade de armazenamento qualquer, podemos fazer isso de ao menos três formas diferentes conforme a seguir:
a) reservar os espaços em memória na forma estática, ou seja, alocar uma determinada quantidade de memória previamente definida, mesmo sem considerar a quantidade que seria realmente necessária;
b) reservar os espaços em memória através de variáveis locais. O espaço estará disponível somente enquanto a função que o declarou estiver executando o programa.
c) alocação de espaço em memória dinamicamente, ou seja, o Sistema Operacional aloca blocos de espaços que estão disponíveis (livres) ou para atender uma determinada demanda. 
 
Com base nas informações disponíveis e em Listas Encadeadas (ou Listas Ligadas), avalie a seguinte afirmativa preenchendo suas lacunas:
 
"Os elementos armazenados numa lista não ocupam um espaço de memória ___________, fazendo com que o acesso aos elementos da lista seja ___________. Enquanto que a utilização de vetores é considerada primária para a representação de conjuntos de dados, a utilização de listas ligadas é uma maneira mais ______________, para a organização e disponibilização dos dados, isto porque em listas ligadas, cada um de seus elementos___________________."
Agora assinale a alternativa que preenche corretamente as lacunas do texto.
Alternativas:
a)
 distribuído / aleatório / flexível / indica o máximo de elementos.
b)
 contíguo / sequencial / flexível / indica qual é o seu próximo.
Alternativa assinalada
c)
 aleatório / contíguo / simplória / indica o mínimo de elementos.
d)
 contíguo / aleatório / íntegra / indica qual é o seu próximo.
e)
 distribuído / sequencial / limitada / indica o máximo de elementos.
2)
O uso do vetor, ao ser declarado, reserva um espaço na memória contíguo para armazenar seus elementos e assim é possível acessar qualquer dos seus elementos a partir do primeiro elemento, por meio de um ponteiro (CELES, 2004).
 
Com base no funcionamento das Estruturas de Dados, avalie as seguintes asserções e a relação proposta entre elas:
 
I – Além do primeiro elemento é necessário que se conheça o último elemento, que é o que controla o acesso do vetor.
 
PORQUE
 
II – Vetores permitem que os elementos sejam acessados de forma aleatória.
Assinale a alternativa correta.
Alternativas:
a)
As asserções I e II são verdadeiras, mas a II não é uma justificativa da I.
b)
As asserções I e II são verdadeiras e a II é uma justificativa da I.
c)
A asserção I é verdadeira e II é falsa.
d)
A asserção I é falsa e II é verdadeira.
e)
As asserções I e II são falsas.
Alternativa assinalada
3)
Existem ótimos exemplos de utilização de Pilhas em nosso cotidiano, nos brinquedos usados em sala de aula ou até mesmo numa simples pilha de livros, onde é possível se determinar qual o algoritmo (critério) utilizado para empilhá-los: tamanho, grossura, cor, tema, etc.. Muitos professores usam estas artimanhas a fim de que os alunos possam desenvolver o raciocínio lógico.
 
Pensando nisso, um programador desenvolveu o código abaixo, para que os professores possam informar a quantidade de discos e o sistema informasse a quantidade total de movimentos que serão realizados. Com esse algoritmo, eles poderiam criar gincanas e desafios entre os alunos para resolverem a ferramenta lógica que eles usam em sala de aula, com um número maior de discos.
 
Abaixo apresenta-se o código desenvolvido pelo programador mencionado.
 
#include <stdio.h>
#include <stdlib.h>
int contador = 0;
void algoritmo(int n, char a, char b, char c)
{
  if (n == 1)
   {
     printf("Move o disco %d de %c para %c\n", n, a, b);
     contador++;
   } else
      {
        algoritmo(n - 1, a, c, b);
         printf("Move o disco %d de %c para %c\n", n, a, b);
        algoritmo(n - 1, c, b, a);
        contador++;
      }
}
int main(void)
{
   int numDiscos;
   printf("Informe o numero de discos: ");
   scanf("%d", &numDiscos);
  algoritmo(numDiscos, 'A', 'B', 'C');
   printf("\n\nA quantidade de movimentos foi: %d", contador);
   return 0;
}
 
Sobre o algoritmo apresentado acima, analise as seguintes afirmações:
 
I - O Algoritmo trata-se da solução da Torre de Hanói.
II - Para o desenvolvimento deste algoritmo foi necessário o uso da recursividade assim como o uso de Pilhas.
III - Foi necessário, um contador para realizar a contagem da quantidade de movimento.
IV - O algoritmo limita o numero de pilhas informadas em 10 unidades.
Agora, assinale a alternativa correta.
Alternativas:
a)
Apenas as afirmativas I, III e IV estão corretas.
b)
Apenas as alternativas I, II e III são corretas.
Alternativa assinalada
c)
Apenas as afirmativas I e III estão corretas.
d)
Apenas as afirmativas I, II e IV estão corretas.
e)
Apenas as afirmativas II, III e IV estão corretas.
4)
As Filas não apresentam uma solução completa, sendo que, mesmo chegando ao final do vetor poderemos ter a Fila cheia mesmo não estando cheia, uma vez que elementos podem ter sido removidos e para isso, podemos utilizar as Filas Circulares como solução para esta situação.
Tendo como referência Filas Circulares, avalie as seguintes afirmativas:
I - Uma Fila Circular utiliza menos instruções a serem executadas, podendo ser mais adequada e eficiente na utilização de programação.
II -  Em relação ao driver-thru (serviço de vendas alimentos fast food, que permite ao cliente comprar o produto sem sair do carro),  seu processo todo se encaixa no modelo de Fila Circular.
III -  Em uma Fila Circular, o conceito de circularidade se baseia quando o último elemento da fila está na última posição do vetor, e é adjacente à primeira
IV -  Em uma Fila Circular são os ponteiros, e não os elementos da fila que se movem em direção ao início do veto.
Agora assinale a alternativa correta.
Alternativas:
a)
Apenas a afirmativa IV está correta.
b)
Apenas as afirmativas II e III estão corretas.
Alternativa assinalada
c)
Apenas as afirmativas I e II estão corretas.
d)
Apenas as afirmativas I, III e IV estão corretas.
e)
As afirmativas I, II, III e IV estão corretas.
Atividades
1) A criação de um ponteiro só faz sentido se for associado a algum endereço de memória, para isso usa-se a seguinte sintaxe:
1. int idade = 18;
2. int *ponteiro_para_idade = &idade;
Na linha 1 criamos uma variável primitiva inteira com valor 18 e na linha 2 associamos um ponteiro chamado ponteiro_para_idade ao endereço da variável primitiva idade.
Podemos imprimir o conteúdo do ponteiro, que será o endereço da variávelque ele aponta. Utilizando o ponteiro criado anteriormente (ponteiro_para_idade) temos a seguinte sintaxe:
Alternativas:
a)
printf("\n Conteudo do ponteiro: %d", &idade);
b)
scanf("\n Conteudo do ponteiro: %p", ponteiro_para_idade);
c)
gets("\n Conteudo do ponteiro: %d", &idade);
d)
printf("\n Conteudo do ponteiro: %p", ponteiro_para_idade);
Alternativa assinalada
e)
scanf("\n Conteudo do ponteiro: %d", &idade);
2)
As variáveis são muito úteis para o armazenamento de diversos tipos de dados.
 
De acordo com as informações apresentadas na tabela a seguir, faça a associação dos tipos de variáveis com suas respectivos características.
 
	Coluna -A 
	 
	Coluna -B
	I. Vetor
	 
	1. Podemos manipular variáveis e outros recursos pelo endereço de memória.
	II. Matriz
	 
	2. Possuem a estrutura de uma tabela contendo apenas 1 coluna e N linhas. 
	III. Struct
	 
	3. Possuem a estrutura de uma tabela contendo apenas N coluna e N linhas. 
	IV. Ponteiro
	 
	4. Um tipo de variável composta heterogênea.
 
I - 2; II - 3; III - 4; VI - 1.
Assinale a alternativa que apresenta a associação correta.
Alternativas:
a)
I - 3; II - 2; III - 1; IV- 4.
b)
I - 2; II - 3; III - 1; IV - 4.
c)
I - 4; II - 1; III - 2; IV - 3.
d)
I - 1; II - 2; III - 3; IV - 4.
e)
I - 2; II - 3; III - 4; IV - 1.
Alternativa assinalada
3)
 Manzano, Matos e Lourenço(2015) afirmam que a criação de um vetor é similar a uma variável primitiva tendo que acrescentar apenas um número entre colchetes indicando qual será o tamanho desse vetor por exemplo: int valores [15], neste caso, estamos criando 15 espaços para armazenar valores inteiros. Cada elemento no vetor é acessado através do seu índice, que sempre começará pelo valor zero, independentemente da linguagem de programação.
 
Observe o programa a seguir utilizando um vetor.
 
#include <stdio.h>
const int valor = 3;
int main ()
{
int vetor[4]={2,4,6,8};
vetor [0] = vetor [0] * valor;
vetor [1] = vetor [1] * valor;
vetor [2] = vetor [2] * valor;
vetor [3] = vetor [3] * valor;
printf ("\n  %d - ", vetor [3]);
printf ("\n  %d -", vetor [2]);
printf ("\n  %d -", vetor [1]);
printf ("\n  %d .", vetor [0]);
return 0;
}
Assinale a opção correta que apresenta o resultado que será impresso na tela após o programa ser executado.
Alternativas:
a)
6 – 8 – 10 – 12.
b)
24 – 18 – 12 – 6.
Alternativa assinalada
c)
6 – 12 – 18 – 24.
d)
18 – 12 – 6 – 24.
e)
24 – 12 – 18 – 6.
4)
Conforme Mizrahi (2008) um vetor é uma estrutura de dados do mesmo tipo primitivo. Possui um índice que deve ser rigorosamente respeitado, não podemos por exemplo armazenar mais valores do que a quantidade que foi informada na declaração do vetor.
 
Observe o programa a seguir que realiza a troca de elementos entre o próprio vetor.
 
	#include <stdio.h>
const int TAM = 2;
int main ()
{
  int idade[TAM]={25,48};
  int troca;
  printf ("\n Antes da Troca: ");
  printf ("\n  %d ", idade [0]);
  printf ("\n  %d ", idade [1]);
  troca = idade[0];
  idade [0]= idade [1];
  idade [1] = troca;
  printf ("\n Depois da Troca: ");
  printf ("\n  %d ", idade [0]);
  printf ("\n  %d ", idade [1]);
  return 0;
} 
 
Fonte: MIZRAHI, V. V. Treinamento em linguagem C. 2ª ed. São Paulo. Pearson Prentice Hall, 2008.
 
Com base nas afirmações sobre vetor e o programa apresentado, avalie as seguintes asserções e a relação proposta entre elas:
 
I. Existem algumas facilidades que podem ser utilizadas para ajudar o trabalho do programador e é o caso da utilização de constantes. Podemos utilizar uma constante para determinar o tamanho do vetor. Primeiro criamos uma constante do tipo inteiro e atribuímos um valor. Ao criar o vetor, usamos a constante para informar o tamanho do vetor.
 
PORQUE
 
II. Essa ação pode agilizar o trabalho do programador, suponha que o vetor tenha o tamanho de 30 elementos, para testar o programa devemos informar 30 elementos toda vez. Por exemplo: usando uma constante com o valor 4, basta informar o valor de 4 elementos e o podemos testar o programa com 4 elementos do vetor. No final dos testes, basta modificar o valor 4 da constante para o valor 30 (e que era a proposta inicial do programa).
Analise atentamente as asserções e assinale a alternativa CORRETA.
Alternativas:
a)
As asserções I e II são proposições verdadeiras, e a II é uma justificativa da I.
Alternativa assinalada
b)
As asserções I e II são proposições verdadeiras, mas a II não é uma justificativa da I.
c)
A asserção I é uma proposição verdadeira, e a II é uma proposição falsa.
d)
A asserção I é uma proposição falsa, e a II é uma proposição verdadeira.
e)
As asserções I e II são proposições falsas.
5)
A programação é utilizada para ajudar a resolver problemas de todos os níveis. Operações matemáticas são os exemplos preferidos para ajudar no entendimento das estruturas das linguagens de programação.  A área de um quadrado corresponde ao tamanho da superfície desta figura. Um quadrado é um quadrilátero que possui seus lados congruentes ou seja, eles possuem exatamente a mesma medida.
 
O programa a seguir que calcula a área de um quadrado, observe que está faltando uma linha no programa:
 
	1.
2.
3.
4.
5.
6.
7.
8.
9.
10.
	#include <stdio.h>
int lado, area;
int main()
{
 printf("Insira o Lado: ");
scanf("%d", &lado);
// Cálculo da área
printf("A área e: %d \n", area);
return 0;
}
Assinale a opção correta que apresenta o comando que deve ser inserido na linha 7, para calcular a área do quadrado:
Alternativas:
a)
 area = (lado1 * lado2);
b)
 area = (lado * 2);
c)
 area = (lado)2;
d)
 area = (lado * lado);
Alternativa assinalada
e)
 lado = (area * area);
Atividades
1)A linguagem de programação C permite que os parâmetros sejam passados para as funções de duas maneiras, por valor e por referência. Na passagem por valor, uma expressão pode ser utilizada na chamada. Na passagem por referência, o endereço de uma variável deve ser passado na chamada da função. Dessa forma, a função pode modificar a variável diretamente, o que em geral não é recomendável, mas há situações onde esse recurso é necessário. Sempre que possível é recomendável utilizar a forma de passagem por valor, para evitar "efeitos colaterais", mas em algumas situações, esses efeitos são desejáveis quando é preciso criar uma função que retorne mais de um valor.
 Fonte:Disponível em:< https://www.ime.usp.br/~elo/IntroducaoComputacao/Funcoes%20passagem%20de%20parametros.htm>Acesso.13.Ago.2018.
  Como exemplo um número complexo, que possui uma parte real e outra complexa. Analise o trecho de programa e as asserções a seguir:
 
#include <stdio.h>
#include <stdlib.h>
void complexo2 (float *r, float *t);
int main ()
{
float a, b;
printf ("Entre com um numero complexo (2 numeros inteiros): ");
scanf("%f %f", &a, &b);
complexo2 ( &a, &b);
printf("O quadrado do número complexo é %f + i %f\n", a, b);
system("pause");
return 0;
}
 
Neste contexto, julgue as afirmações que se seguem.
 I. No main são declaradas apenas duas variáveis reais a e b. E tanto na chamada da função scanf, quanto na chamada da função complexo2, as variáveis a e b são precedidas pelo caractere '*'.
  II. Esse caractere ‘*’ indica a necessidade de que esses parâmetros sejam modificados pela função e retornem os valores apropriados.
 III. No caso da função scanf, esses valores correspondem aos valores digitados pelo usuário, mas no caso da função complexo2, esses valores são computados pela função. Ou seja, os parâmetros a e b são utilizados apenas para saída, e no caso da complexo2, os parâmetros a e b são utilizados como entrada e saída da função.
 IV. Os próprios valores armazenados nas variáveis a e b são utilizados como entrada da função complexo2, ou seja, como parte real e imaginária para calcular o valor do quadrado do número complexo, e ao mesmo tempo para devolver o resultado.
  V. Na função printf, as variáveis a e b não são precedidas pelo caractere '&', portanto, não são modificadas pela função printf.
  VI. Quando deseja-se criar uma função que devolva mais de um valor, é preciso definir esses parâmetros comum caractere '&' no protótipo da função, e ao chamar a função, os parâmetros utilizados na chamada correspondentes à entrada precisam ser precedidos pelo caractere '*' para indicar que eles podem ser modificados pela função chamada.
É correto apenas o que se afirma em:
Alternativas:
a)
I, II e VI.
b)
III, IV e V.
Alternativa assinalada
c)
I e IV.
d)
II e V.
e)
III e VI.
2)
Leia o trecho de programa a seguir:
 
#include<stdio.h>
int x = 10;
int main(){
int x = -1;   int b;
{
extern int x;     b = x;
}
printf("\n Valor de x = %d",x);
printf("\n Valor de b (x global) = %d",b);
return 0;
}
 
De acordo com o trecho de programa, analise as asserções a seguir:
 
 I. Na linguagem C, para acessar o valor de uma variável global dentro de uma função que possui uma variável local com mesmo nome, deve-se usar a instrução extern.
PORQUE
 II. Utilizar variáveis globais e locais com mesmo nome na linguagem C necessita criar uma nova variável chamada “b”, com um bloco de instruções, que atribui à nova variável o valor “interno” de x.
A respeito dessas asserções, assinale a alternativa correta:
Alternativas:
a)
As asserções I e II são proposições verdadeiras, e a II é uma justificativa da I.
b)
As asserções I e II são proposições verdadeiras, mas a II não é uma justificativa da I.
c)
A asserção I é uma proposição verdadeira, e a II é uma proposição falsa.
Alternativa assinalada
d)
A asserção I é uma proposição falsa, e a II é uma proposição verdadeira.
e)
As asserções I e II são proposições falsas.
3)
Para usar de forma mais otimizada a memória, existe uma alternativa chamada recursividade em cauda. Nesse tipo de técnica a recursividade funcionará como uma função iterativa. Uma função é caracterizada como recursiva em cauda quando a chamada a si mesmo é a última operação a ser feita no corpo da função. Nesse tipo de função, o caso base costuma ser informado como parâmetro, o que resultará um comportamento diferente.
A principal vantagem da recursividade em cauda consiste em:
Alternativas:
a)
as instâncias vão sendo criadas, porém quando chega na última, as funções precisam retornar o valor para “quem” invocou, gerando otimização na memória, pois precisa armazenar um ponto para devolução de valores.
b)
as instâncias vão sendo criadas, porém quando chega na última, as funções não precisam retornar o valor para “quem” invocou, gerando otimização na memória, pois não precisa armazenar nenhum ponto para devolução de valores.
Alternativa assinalada
c)
as instâncias vão sendo descartadas, porém quando chega na última, as funções não descartam o valor invocado, gerando otimização na memória, pois não precisa armazenar nenhum ponto para devolução de valores.
d)
as instâncias vão sendo criadas, porém quando chega na última, as funções não retornam valor, gerando conflito na memória, pois não precisa armazenar nenhum ponto para devolução de valores.
e)
as instâncias vão sendo criadas, porém quando chega na última, as funções não precisam retornar o valor para “quem” invocou, gerando conflito na memória, pois não precisa armazenar nenhum ponto para devolução de valores.
4)
“Muitos problemas têm a seguinte propriedade: cada instância do problema contém uma instância menor do mesmo problema. Diz-se que esses problemas têm estrutura recursiva. Para resolver tal problema, pode-se aplicar o seguinte método: se a instância em questão for pequena, resolva-a diretamente; senão, reduza-a a uma instância menor do mesmo problema, aplique o método à instância menor, volte à instância original. A aplicação desse método produz um algoritmo recursivo.” (FEOFILOFF, 2017, p. 1). Baseado nesse conceito, avalie as asserções a seguir:
 
 I -  Recursividade significa indicar quando um problema maior pode ser dividido em instâncias menores do mesmo problema.
PORQUE
 II - A técnica de recursividade pode substituir o uso de estruturas de repetição tornando o código mais elegante.
A respeito dessas asserções, assinale a alternativa correta:
Alternativas:
a)
As asserções I e II são proposições verdadeiras, e a II é uma justificativa da I.
Alternativa assinalada
b)
As asserções I e II são proposições verdadeiras, mas a II não é uma justificativa da I.
c)
A asserção I é uma proposição verdadeira, e a II é uma proposição falsa.
d)
A asserção I é uma proposição falsa, e a II é uma proposição verdadeira.
e)
As asserções I e II são proposições falsas.
5)
Recursividade é uma técnica sofisticada em programação, na qual uma função chama a si mesma criando várias instâncias (chamadas recursivas). Embora seja uma técnica que proporciona um código mais limpo e facilita a manutenção, seu uso deve levar em consideração a quantidade de memória necessária para a execução do programa. Nesse contexto, avalie as asserções a seguir:
 
I. A cada chamada recursiva é alocado recursos na memória para a função, se a função for muito grande poderá ocorrer um acúmulo de memória.
PORQUE
 II. É preciso avaliar o custo-benefício em se ter um código mais sofisticado em detrimento de uma estrutura de repetição, pois a segunda opção gasta menos memória.
A respeito dessas asserções, assinale a alternativa correta:
Alternativas:
a)
As asserções I e II são proposições verdadeiras, e a II é uma justificativa da I.
b)
As asserções I e II são proposições verdadeiras, mas a II não é uma justificativa da I.
c)
A asserção I é uma proposição verdadeira, e a II é uma proposição falsa.
d)
A asserção I é uma proposição falsa, e a II é uma proposição verdadeira.
Alternativa assinalada
e)
As asserções I e II são proposições falsas.
Questão 1
As variáveis são locais reservados na memória para armazenamento dos dados, cada uma possui um nome próprio para sua identificação. Existe um tipo variável para cada representação da informação, não podendo assim, um determinado tipo de variável, ser usada em situações controversas.
De acordo com o texto acima, responda a alternativa correta:
A)
 
Variável do tipo inteiro armazena os números inteiros somente positivos e as variáveis do tipo real permite armazenar valores de pontos flutuantes e com frações.
B)
 
Variável do tipo inteiro armazena os números flutuante e as variáveis do tipo real permite armazenar valores inteiros.
C)
 
Variável do tipo inteiro armazena os números inteiros (negativos ou positivos) e as variáveis do tipo real permite armazenar somente valores de pontos flutuantes.
D)
 
Variável do tipo inteiro armazena os números inteiros (negativos ou positivos) e as variáveis do tipo real permite armazenar valores de pontos flutuantes com frações e caracteres.
E)
 
Variável do tipo inteiro armazena os números inteiros (negativos ou positivos) e as variáveis do tipo real permite armazenar valores de pontos flutuantes e com frações.
Questão 2
O escopo de variável é dividido em duas categorias, local ou global. Sobre este conceito, analise as afirmativas a seguir:
I- As variáveis do tipo local são "enxergadas" somente dentro do corpo da função onde foram definidas.
II- As variáveis do tipo local devem ser definidas fora da função, assim ela será visível por todas as funções do programa;
III- As variáveis do tipo global podem ser utilizadas por qualquer função do programa, logo isso exige um cuidado ao manipula-la.
Agora, assinale a alternativa que apresenta a resposta CORRETA: 
A)
 
Apenas as afirmativas I e III estão corretas;
B)
 
Apenas a afirmativa I está correta;
C)
 
Apenas as afirmativas I e II estão corretas;
D)
 
As afirmativas I, II e III estão corretas.
E)
 
Apenas a afirmativa II está correta;
Questão 3
Analise as afirmativas a seguir e marque V para verdadeiro e F para falso:
( ) Asterisco (*) é usado para criação do ponteiro e o "&" é usado para acessar o endereço da memória;
( ) A função busca dividir a complexidade de um problema maior e evitar repetição de código;
( ) Na passagem de valor por parâmetros, a função cria variáveis locais automaticamente para armazenar esses valores e após a execução da função essas variáveis são liberadas.
Agora, assinale a alternativa que apresenta a sequência CORRETA:
A)
 
F-V-V;B)
 
V-V-V;
C)
 
F-F-F;
D)
 
F-V-F;
E)
 
V-F-F;
Questão 4
Analise as afirmativas a seguir e marque V para verdadeiro e F para falso:
( ) Uma matriz aceita diversos tipos de variáveis;
( ) Não é obrigatório que todas as posições sejam ocupadas de um vetor ou de uma matriz.
( ) O for busca repetir uma informação por um número fixo de vezes.
Agora, assinale a alternativa que apresenta a sequência CORRETA:
A)
 
F-V-V;
B)
 
F-V-F;
C)
 
V-V-V;
D)
 
V-F-F;
E)
 
F-F-F;
Questão 5
Dado um certo problema para ser resolvido por meio de um programa, a solução pode ser implementada em blocos de funcionalidades, técnica essa conhecida como dividir para conquistar. A aplicação dessa técnica em uma linguagem de programação pode ser feita por meio de funções.
A respeito de funções, análise as afirmações a seguir:
I. Função tem como objetivo resolver parte de um problema maior. Um função sempre deve retornar um valor para quem a chamou. 
II. Uma função sempre precisa receber parâmetros, caso isso não ocorra, o compilador irá relatar um erro. 
III. Uma função pode ser invocada quantas vezes for necessário em um programa.
Escolha a alternativa que representa a resposta correta.
A)
 
Somente a afirmação II está correta.
B)
 
Somente a afirmação I e II estão corretas.
C)
 
Somente a afirmação I está correta.
D)
 
Somente a afirmação III está correta.
E)
 
Somente a afirmação II e III estão corretas.
Questão 6
A recursividade é uma técnica de programação na qual uma função chama a si própria tornando o código mais limpo e elegante, o que facilita a manutenção e reutilização de trechos de códigos e funções. Toda chamada recursiva deve retornar um valor à função que "fez o chamado". Analise as asserções a seguir e a relação proposta entre elas.
I - Funções recursivas sempre podem ser utilizadas para substituir estruturas de repetição.
PORQUE
II - Toda função recursiva é composta pelo caso base e pelas chamadas recursivas funcionando como um laço de repetição.
A)
 
As asserções I e II são proposições falsas.
B)
 
A asserção I é uma proposição verdadeira, e a II é uma proposição falsa.
C)
 
As asserções I e II são proposições verdadeiras, e a II é uma justificativa correta da I.
D)
 
A asserção I é uma proposição falsa, e a II é uma proposição verdadeira.
E)
 
As asserções I e II são proposições verdadeiras, mas a II não é uma justificativa correta da I.
Questão 7
Vetores são estruturas de dados estáticas, ou seja, não são redimensionadas em tempo de execução. Uma vez criadas com tamanho N, esse tamanho se mantém fixo. Para criar uma função que retorna um vetor é preciso recorrer ao uso de ponteiros.
Avalie o código a seguir e escolha a opção correta.
#include
int* retornarVetor(){
static int v[10];
int a;
for(a = 0; a < 10; ++a) {
v[a] = 2 * a;
}
return v;
}
int main(){
int *p;
p = retornarVetor();
printf("Valor = %d",*(p + 2));
return 0;
}
A)
 
Será impresso na tela "Valor = 6".
B)
 
Será impresso na tela "Valor = 8".
C)
 
Será impresso na tela "Valor = 2".
D)
 
Será impresso na tela "Valor = 4".
E)
 
Será impresso na tela "Valor = 0".
Questão 8
Analise a sintaxe utilizada para a criação de funções:
< tipo de retorno > < nome > (< parâmetros >) {
< Comandos da função >
< Retorno > ( )
}
Na declaração da função alguns elementos são obrigatórios e outros opcionais. Sobre estes elementos, analise as afirmativas a seguir e marque V para verdadeiro e F para falso.
(  ) Os paramentos são opcionais;
( ) O tipo de retorno indica qual o tipo de valor a função irá retornar. Pode ser um valor inteiro (int), decimal (float ou double), caractere (char), etc. Este é um elemento obrigatório;
(  ) O retorno só é opcional quando o tipo de retorno for void, caso contrário, este é um elemento obrigatório.
Agora, assinale a alternativa que apresenta a sequência CORRETA:
A)
 
V-V-V;
B)
 
F-F-V;
C)
 
F-F-F;
D)
 
F-V-V;
E)
 
V-F-F;
Questão 9
Uma lista ligada, também conhecida como lista encadeada, é um conjunto de dados dispostos por uma sequência de nós, em que a relação de sucessão desses elementos é determinada por um ponteiro que indica a posição do próximo elemento, podendo estar ordenado ou não.
Assinale a alternativa a seguir que apresenta a informação correta quanto à composição de um nó da lista ligada:
A)
 
Ponteiro para o próximo elemento e um ponteiro para o elemento anterior.
B)
 
Ponteiro para o elemento anterior e uma informação.
C)
 
Uma informação e um ponteiro para o próximo elemento.
D)
 
Ponteiro para o próximo elemento e um ponteiro para NULL.
E)
 
Uma informação e um ponteiro para o elemento anterior.
Questão 10
Sobre as variáveis do tipo composta, analise as afirmativas a seguir e marque V para verdadeiro e F para falso:
( ) As structs são variáveis compostas heterogêneas, este tipo só pode armazenar valores de um mesmo tipo.
(  ) A criação de um vetor é similar a uma variável primitiva, tendo que acrescentar apenas um número entre colchetes indicando qual será o tamanho desse vetor;
(  ) Na linguagem C, a criação de uma struct deve ser feita antes da função main( );
Agora, assinale a alternativa que apresenta a sequência CORRETA:
A)
 
V-V-V;
B)
 
F-F-V;
C)
 
V-F-F;
D)
 
F-F-F;
E)
 
F-V-V;
Questão 11
Analise as afirmativas a seguir sobre as estruturas de dados pilha e fila:
I- Uma pilha é uma estrutura de dados do tipo LIFO, onde o primeiro elemento a ser inserido, será o primeiro a ser retirado.
II- As filas são estruturas de dados do tipo FIFO (first-in first-out), adiciona-se itens no fim e remove-se do início.
III- As principais funções da fila são push e pop;
Agora, assinale a alternativa que apresenta a resposta CORRETA: 
A)
 
Apenas as afirmativas I e II estão corretas;
B)
 
Apenas a afirmativa II está correta;
C)
 
As afirmativas I, II e III estão corretas.
D)
 
Apenas as afirmativas II e III estão corretas;
E)
 
Apenas a afirmativa I está correta;
Questão 12
A linguagem C de programação utiliza especificadores de formato para identificar o tipo de valor guardado nas variáveis e constantes. Eles devem ser usados tanto para leitura de um valor, como para a impressão. Quando um programa é executado, o compilador usa esses elementos para fazer as devidas referências e conexões, por isso o uso correto é fundamental para os resultados.
Considerando o código apresentado, analise as asserções e escolha a opção correta.
Anexo - Consulte a imagem em melhor resolução no final do cadernos de questões.
I- O comando scanf("%f", idade); guardará o valor digitado na variável idade.
II- O comando printf("%d",a_letra); imprimirá a letra a na tela.
III- O comando printf("%c",A_letra); imprimirá a letra A na tela.
A)
 
Somente a alternativa II está correta.
B)
 
Somente a alternativa III está correta.
C)
 
Somente as alternativas II e III estão corretas.
D)
 
Somente as alternativas I e II estão corretas.
E)
 
Somente a alternativa I está correta.
Questão 13
Uma estrutura de dados é uma coleção de valores que possuem uma organização dependendo das suas características. Sabendo disso, relacione a estrutura de dados com a sua definição:
I- Lista;
II- Fila;
III- Pilha;
1- é um conjunto de elementos ordenados que permite a inserção e a remoção de mais elementos em apenas uma das extremidades da estrutura denominada topo;
2- esta estrutura de dados é do tipo FIFO (First in, First out), ou seja, o primeiro elemento que entra é o primeiro a ser removido.
3- é composta de um conjunto de dados dispostos por uma sequência de nós, em que a relação de sucessão desses elementos é determinada por um ponteiro que indica a posição do próximo elemento, podendo estar ordenado ou não. Nesta estrutura, tanto a inserção e remoção de dados não segue uma regra definida.
A seguir, assinale a alternativa que contém a sequência correta da associação:
A)
 
I-1; II-2; III-3;
B)
 
I-2; II-3; III-1;
C)
 
I-3; II- 1; III-2;
D)
 
I-3; II-2; III-1;
E)
 
I-2; II-1; III-3;
Questão 14
_____________ são arranjos de duas ou mais dimensões. Todos os elementos são do mesmo tipo, armazenando informações semanticamente semelhantes.
Agora, assinale a alternativa quecompleta corretamente a lacuna:
A)
 
Structs;
B)
 
Vetores;
C)
 
Pilha;
D)
 
Lista;
E)
 
Matrizes;
Questão 15
Analise o código do programa abaixo, em que foi utilizada a estrutura de repetição com variável de controle:
Anexo - Consulte a imagem em melhor resolução no final do cadernos de questões.
Analisando o programa acima, qual é a leitura que podemos fazer da linha 5:
A)
 
Na primeira expressão, "contador" tem o seu valor iniciado em "1". Na segunda expressão, "contador" está condicionado a ser menor a "10". Na terceira expressão, "contador" será realizado o incrementado de 1 para ao seu valor
B)
 
Na primeira expressão, "contador" tem o seu valor iniciado em "1". Na segunda expressão, "contador" está condicionado a ser igual a "10". Na terceira expressão, "contador" será realizado o incrementado de 1 para ao seu valor.
C)
 
Na primeira expressão, "contador" tem o seu valor iniciado em "0". Na segunda expressão, "contador" está condicionado a ser menor ou igual a "10". Na terceira expressão, "contador" será realizado o incrementado de 2 para ao seu valor.
D)
 
Na primeira expressão, "contador" tem o seu valor iniciado em "1". Na segunda expressão, "contador" está condicionado a ser maior ou igual a "10". Na terceira expressão, "contador" será realizado o decremento de 1 para ao seu valor.
E)
 
Na primeira expressão, "contador" tem o seu valor iniciado em "1". Na segunda expressão, "contador" está condicionado a ser menor ou igual a "10". Na terceira expressão, "contador" será realizado o incrementado de 1 para ao seu valor.
Questão 16
Todo sistema computacional é construído para se obter alguma solução automatizada. Uma das áreas promissoras da computação é a mineração de dados, que, como o nome sugere, se refere a um determinado montante de dados e o modo como eles podem ser minerados para gerar informações de valor. Dentro do processamento de informações, os operadores matemáticos, relacionais e lógicos são essenciais, pois são a base do processo.
Considerando o comando resultado = a + b * (c – b) / a, e os valores a=2, b=3 e c=5. Escolha a opção correta.
A)
 
O valor em resultado será 10.
B)
 
O valor em resultado será 8.
C)
 
O valor em resultado será 7.
D)
 
O valor em resultado será 6.
E)
 
O valor em resultado será 5.
1)
A diferença entre o comando while e o do…while é justamente o local onde a condição que controla o laço é testada. No comando while a condição é testada antes do bloco de instruções, e caso a condição seja falsa a repetição não será executada. No do…while o bloco de comandos é executado pelo menos uma vez de forma obrigatória, independente do resultado da expressão lógica. Analise o código a seguir.
Disponível em: <http://linguagemc.com.br/comando-do-while/> Acesso em: 22 out. 2018.
 
 #include <stdio.h>
#include <stdlib.h>
main()
{
int cont=0; 
valor inicial de "0"
while (cont < 5)
 printf("Teste \n");
cont++; 
}
system("PAUSE");
return 0;
}
 
De acordo com o cotexto apresentado, avalie as afirmativas a seguir:
 
I. Um contador é utilizado para controlar as repetições, quando são determinadas. Por exemplo, o código será executado enquanto a cont for menor que 5.
II. O cont ++ é o incremento para que o número do contador seja aumentado ou diminuído.
III. Ao atingir o valor 5, é considerada uma condição de parada do while.
Considerando o contexto apresentado, assinale a alternativa correta.
Alternativas:
· a)
Apenas as afirmativas I e II estão corretas.
Alternativa assinalada
· b)
Apenas as afirmativas I e III estão corretas.
· c)
Apenas a afirmativa I está correta.
· d)
Apenas a afirmativa II está correta.
· e)
As afirmativas I, II e III estão corretas.
2)
 O laço do-while executa, pelo menos uma vez, o que está dentro dele e só ao final da execução é que ele faz o teste. Ou seja, tem-se a garantia que o laço vai ser executado uma vez, sem precisar inicializar variável ou pedir dados ao usuário antes do while. Um dos usos da estrutura do-while é em menus, nos quais você quer garantir que o valor digitado pelo usuário seja válido. Analise o programa a seguir:
  
Disponível em <http://mtm.ufsc.br/~azeredo/cursoC/aulas/c450.html> Acesso.13.jul.2018.
 
Considerando o contexto, avalie as afirmativas a seguir:
I. O usuário deverá digitar os números de 1 a 3 como entrada para ter como resultado a fruta de acordo com o número escolhido.
 II. Ao digitar o número 0 mostrará o menu com as opções de frutas e o comando para escolher uma fruta pelo número.
III. Ao digitar o número 2, será exibida como resultado a fruta abacaxi.
Considerando o contexto apresentado, assinale a alternativa correta.
Alternativas:
· a)
Apenas a afirmativa II está correta.
· b)
Apenas a afirmativa III está correta.
· c)
Apenas as afirmativas I e III estão corretas.
· d)
Apenas as afirmativas I e II estão corretas.
· e)
As afirmativas I, II e III estão corretas.
Alternativa assinalada
3)
O laço “for”, que em português significa “para”, segundo Mizrahi (2008), é geralmente usado para repetir uma informação por um número fixo de vezes, isto é, podemos determinar quantas vezes acontecerá a repetição. Análise o trecho do código a seguir.
for(x=5, y = 0; x>=0, y <= 5; x --, y++)
 
Considerando o contexto, avalie as afirmativas a seguir:
 
I. No primeiro valor x tem o valor iniciado em "5" e y iniciado em "0".
II. Na segunda expressão, o laço se repetirá apenas enquanto x for maior ou igual a 0 e enquanto y for menor ou igual a 5.
III. Ao final da execução dos comandos do laço de repetição, x será decrementado em 1 e x incrementado em 1.
Considerando o contexto apresentado, assinale a alternativa correta.
Alternativas:
· a)
Apenas a afirmativa I está correta.
· b)
Apenas a afirmativa II está correta.
· c)
Apenas a afirmativa III está correta.
· d)
Apenas as afirmativas I e II estão corretas.
· e)
As afirmativas I, II e III estão corretas.
Alternativa assinalada
4)
 O código a seguir realiza o cálculo do fatorial de um número. No código é utilizada a estrutura while, com o while, uma instrução será repetidamente executado enquanto uma condição verdadeira for verificada, somente após a sua negativa essa condição será interrompida. Analise o código a seguir.
#include <stdio.h>
int main()
{
 int num;
 long long fatorial;
 printf("entrar com um número inteiro: ");
 scanf("%d",&num);
 fatorial = 1;
 while (number > 0)
 {
 fatorial *= num;
 --num;
 }
 printf("Fatorial= %lld", fatorial);
 return 0;
}
 
Considerando o contexto, avalie as afirmativas a seguir:
 
I. O fatorial de um número será calculado sempre que receber como entrada um valor maior que "0".
II. Nesse exemplo o loop (while) será finalizado se for menor ou igual a zero.
III. A opção --num realiza o decremento após calcular o valor do fatorial do número (num) e sempre que o comando while  for maior que 0.
Considerando o contexto apresentado, assinale a alternativa correta.
Alternativas:
· a)
Apenas a afirmativa I está correta.
· b)
Apenas a afirmativa II está correta.
· c)
Apenas a afirmativa III está correta.
· d)
Apenas as afirmativas I e II estão corretas.
· e)
As afirmativas I, II e III estão corretas.
Alternativa assinalada
5)
 Para fazer o preenchimento de uma matriz, devemos percorrer todos os seus elementos e atribuir-lhes um valor. Isto pode ser feito tanto gerando valores para cada elemento da matriz, como recebendo os valores pelo teclado. Um método interessante para percorrer uma matriz é usar duas estruturas de repetição for e duas variáveis inteiras, uma para a linha e a outra para a coluna.
  Suponha que deseja-se implementar uma matriz do tipo inteiro. Para percorrer a matriz recebendo seus valores, podemos implementar conforme o trecho de código a seguir.
for ( i=0; i<3; i++ )
 for ( j=0; j<3; j++ )
 {
 scanf ("%d", &matriz[ i ][ j ]);
 }
 
 
  Considerando o contexto apresentado, avalie as afirmativas a seguir:
 I.  A variável i representa a linha e j a coluna da matriz. Logo o primeiro for é utilizado para preencher as 3 linhas da matriz o qual é incrementadode 1.
II. A variável inicia de j = 0 e irá incrementar até  j = 2 totalizando 2 colunas da matriz.
III. A utilização do for deveria ser de ( i=0; i<=3; i++ ), para que seja preenchida a matriz com 3 linhas.
Considerando o contexto apresentado, assinale a alternativa correta.
Alternativas:
· a)
Apenas a afirmativa I está correta.
Alternativa assinalada
· b)
Apenas a afirmativa II está correta.
· c)
Apenas a afirmativa III está correta.
· d)
Apenas as afirmativas I e II estão corretas.
· e)
As afirmativas I, II e III estão corretas..
image4.png
image42.png
image43.png
image44.jpeg
image45.jpeg
image46.png
image5.png
image47.png
image48.png
image6.png
image7.png
image8.png
image9.png
image10.jpeg
image11.png
image12.png
image13.png
image14.png
image15.png
image16.png
image17.png
image18.png
image19.png
image20.jpeg
image21.jpeg
image22.png
image23.png
image24.png
image25.png
image26.png
image1.png
image27.png
image28.png
image29.png
image30.png
image2.png
image31.png
image32.png
image33.png
image3.png
image34.png
image35.png
image36.png
image37.png
image38.png
image39.png
image40.png
image41.png

Mais conteúdos dessa disciplina