Вы находитесь на странице: 1из 23

Centro Universitário Vila Velha

Espírito Santo

CENTRO UNIVERSITÁRIO VILA VELHA

PROGRAMAÇÃO I

Elizabeth Maria Klippel


Ester Maria Klippel

Vila Velha / ES
2008
1

1 - Introdução

Quando trabalhamos em PROGRAMAÇÃO de computadores temos que ORGANIZAR O NOSSO PENSAMENTO


de forma a propormos uma solução para o problema que tentamos resolver. Quando organizamos o pensamento
utilizamos o RACIOCÍNIO LÓGICO.

O raciocínio lógico é usado por todos na solução de diversos problemas cotidianos. Especialmente pelos
profissionais de informática, pois seu dia-a-dia profissional consiste em solucionar problemas e atingir os
objetivos apresentados pelos usuários, utilizando os recursos computacionais disponíveis com eficiência
e eficácia.

Esta disciplina não pretende ensinar ninguém a pensar de forma lógica. Todos nós temos este dom.
Nosso objetivo é, através de técnicas de programação, aperfeiçoar o uso do raciocínio lógico no
desenvolvimento de programas de computador, lembrando que isso exigirá persistência e prática
constante, chegando à exaustão sempre que necessário.

Quando programamos utilizamos a lógica para IDENTIFICAR e SEQÜENCIAR os passos a serem


seguidos para solucionar um problema. A esta seqüência finita de passos que ao serem executados
solucionam o problema chamamos de ALGORITMO.

Utilizamos algoritmos quotidianamente, por exemplo, quando seguimos uma receita de omelete:
Pegue uma tigela pequena.
Acrescente 3 ovos sem casca
Acrescente uma colher de café de sal
Mexa durante 2 minutos
Frite em óleo quente

ALGORITMO é uma seqüência finita de passos que ao serem executados visam tingir um objetivo bem definido.

Como exemplo, construiremos um algoritmo para cálculo da média de duas notas de 0 a 10,
fornecidas pelo usuário:
O computador não possui experiências anteriores, nem poder de discernimento e raciocínio. Temos que
fornecer ao computador detalhes de todas as ações que ele deve executar, prevendo todos os
obstáculos e a forma de transpô-los. Ou seja, temos que definir uma seqüência finita de passos que
garantam a solução do problema.

Primeira Solução:
Digite a primeira nota
Digite a segunda nota
Some as notas digitadas
Divida a soma por 2
Mostre o resultado na tela

Involuntariamente seguimos uma determinada seqüência de ações para representar nosso algoritmo,
calculando a média. Mas se o usuário fornecer uma nota inválida (menor que zero ou maior que 10)?
Para solucionar este problema, antes de calcular a média devemos verificar se as notas são válidas.

Segunda Solução:
Digite a primeira nota
Digite a segunda nota
SE as notas forem válidas
inicio
Some as notas digitadas
Divida a soma por 2
Mostre o resultado na tela
fim

Agora estamos ligando algumas ações à condição das notas serem válidas. Observe a inclusão de um
TESTE SELETIVO que determina quais ações serão executadas (note que antes todas eram).

Centro Universitário Vila Velha


Disciplina: Programação I Centro Universitário Vila Velha
Espírito Santo
Professores: Elizabeth Klippel
Ester Maria Klippel
2

Vamos melhorar a interface do nosso programa. Caso as notas não sejam válidas mostraremos uma
mensagem de erro.

Terceira Solução:
Digite a primeira nota
Digite a segunda nota
SE as notas forem válidas
inicio
Some as notas digitadas
Divida a soma por 2
Mostre o resultado na tela
fim
SENÃO
inicio
Mostre na tela a mensagem “valores inválidos digitados para uma ou mais notas.”
fim

Mudemos um pouco o problema, ainda calcularemos a média de duas notas lidas, porém repetiremos a
leitura até que o usuário forneça duas notas válidas. Quando então calcularemos a média. É impossível
definir quantas digitações serão necessárias até que o usuário forneça duas notas válidas. Assim
repetiremos a leitura até a correta digitação.

Quarta Solução:
ENQUANTO notas inválidas
inicio
Digite a primeira nota
Digite a segunda nota
SE notas inválidas
inicio
Mostre na tela a mensagem “valores inválidos digitados para uma ou mais notas.”
fim
fim
Some as notas digitadas
Divida a soma por 2
Mostre o resultado na tela

Nem sempre o primeiro algoritmo proposto representa a melhor solução para o problema. Às
vezes é necessário torná-lo mais eficiente. Observando o exemplo vemos que ele pode ser
aperfeiçoado, podemos testar cada nota em separado.

Quinta Solução:
ENQUANTO primeira nota inválida
inicio
Digite a primeira nota
SE primeira nota inválida
inicio
Mostre na tela a mensagem “valor inválido digitado para a primeira nota.”
fim
fim
ENQUANTO segunda nota inválida
inicio
Digite a segunda nota
SE segunda nota inválida
inicio
Mostre na tela a mensagem “valor inválido digitado para a segunda nota.”
fim
fim
Some as notas digitadas
Divida a soma por 2
Mostre o resultado na tela

A condição nota inválida estabeleceu um FLUXO REPETITIVO que será finalizado assim que a condição
for falsa, ou seja, que uma nota válida for digitada.

Centro Universitário Vila Velha


Disciplina: Programação I Centro Universitário Vila Velha
Espírito Santo
Professores: Elizabeth Klippel
Ester Maria Klippel
3

Até agora estamos efetuando o cálculo da média de um aluno. Imagine se tivermos que calcular a média
de 10 alunos? Uma solução seria repetir o bloco de comandos acima 10 vezes. Poderíamos, entretanto,
fazer com que após o cálculo de uma média o fluxo de execução retornasse e executasse novamente o
cálculo para duas novas notas. Gerando um FLUXO REPETITIVO por 10 vezes.

Sexta Solução:
PARA 10 alunos { número de repetições definido }
inicio
ENQUANTO primeira nota inválida { número de repetições indefinido }
inicio
Digite a primeira nota
SE primeira nota inválida { teste condicional }
inicio
Mostre na tela a mensagem “valor inválido digitado para a primeira nota.”
fim
fim
ENQUANTO segunda nota inválida
inicio
Digite a segunda nota
SE segunda nota inválida
inicio
Mostre na tela a mensagem “valor inválido digitado para a segunda nota.”
fim
fim
Some as notas digitadas
Divida a soma por 2
Mostre o resultado na tela
fim

Quando escrevemos a solução de um problema utilizando uma linguagem de programação estamos construindo um
PROGRAMA.

Exemplo: última solução proposta para o cálculo da média escrito na linguagem C


# include<stdio.h> //contém as implementações do printf e scanf
# include<stdlib.h> //contém a implementação do system
main ()
{
float n1, n2;
for (int i= 1; i <= 10; i++)
{
do {
printf ("Digite a primeira nota: ");
scanf ("%f",&n1);
if ( (n1 < 0) || (n1 > 10))
printf (“\n Primeira nota inválida \n”);
} while ( (n1 < 0) || (n1 > 10));
do {
printf ("Digite a segunda nota: ");
scanf ("%f",&n2);
if ( (n2 < 0) || (n2 > 10))
printf (“\n Segunda nota inválida \n”);
} while ( (n2 < 0) || (n2 > 10));

printf("Media: %f\n", (n1+n2)/2);


}
system("PAUSE"); //exibe a mensagem ”Pressione qualquer tecla para continuar...” e aguarda que algo seja teclado
}

2 - Histórico da Linguagem C

Optamos por trabalhar com a Linguagem de Programação C. Ela tem sido amplamente utilizada na
elaboração de programas e sistemas nas áreas em que a informática atua, e seu aprendizado tornou-se
indispensável para quem trabalha com programação de computadores.

Centro Universitário Vila Velha


Disciplina: Programação I Centro Universitário Vila Velha
Espírito Santo
Professores: Elizabeth Klippel
Ester Maria Klippel
4

A linguagem C foi criada por Dennis Ritchie, em 1972, no centro de Pesquisas da Bell Laboratories. Sua
primeira utilização importante foi a reescrita do Sistema Operacional UNIX, que até então era escrito em
assembly.

Em meados de 1970 o UNIX saiu do laboratório para ser liberado para as universidades. Foi o suficiente
para que o sucesso da linguagem atingisse proporções tais que, por volta de 1980, já existiam várias
versões de compiladores C oferecidas por várias empresas, não sendo mais restritas apenas ao
ambiente UNIX, porém compatíveis com vários outros sistemas operacionais.

O C é uma linguagem de propósito geral, sendo adequada à programação estruturada. No entanto é


mais utilizada para escrever compiladores, analisadores léxicos, bancos de dados, editores de texto etc.

A linguagem C pertence a uma família de linguagens cujas características são: portabilidade,


modularidade, compilação separada, recursos de baixo nível, geração de código eficiente, confiabilidade,
regularidade, simplicidade e facilidade de uso.

3 – Conceitos Fundamentais

3.1 - Modelo de um Computador

Existem diversos tipos de computadores. Embora não seja nosso objetivo estudar hardware, nesta seção
identificaremos os elementos essenciais de um computador. O conhecimento desses elementos nos
ajudará a compreender como um programa de computador funciona. A figura abaixo identifica os
elementos básicos de um computador típico:
Canal de comunicação - BUS

Memória Memória
CPU principal secundária
Dispositivos de
Entrada/Saída
- Canal de Comunicação (BUS): representa o meio de transferência de dados entre os diversos componentes.
- Unidade Central de Processamento (CPU): representa o “cérebro” do computador, e é responsável pelo controle de todas
as operações realizadas.
- Memória Principal: para que a CPU possa executar uma seqüência de comandos ou acessar uma determinada informação,
é necessário armazenar os comandos e os dados correspondentes na memória principal. A memória principal tem
acesso randômico, o que significa que a CPU pode endereçar (acessar) diretamente qualquer posição na memória. Essa
memória não é permanente e, para um programa, os dados são armazenados enquanto ele está sendo executado.
Normalmente, após o término do programa, a área correspondente ocupada na memória fica disponível para ser usada por
outros programas.
- Área de Armazenamento Secundário: Essa memória tem a vantagem de ser permanente, os dados armazenados em
disco permanecem válidos mesmo depois de encerrado os programas. Ela tem custo mais baixo do que a memória principal,
porém o acesso as dados é bem mais lento. Para que a CPU processe um dado armazenado na memória secundária, é
necessário que antes ele seja transferido para a memória principal.
- Dispositivos de Entrada e Saída: os dispositivos de entrada (por exemplo, teclado e mouse) permitem passar dados para
um programa, enquanto os dispositivos de saída permitem que um programa exporte seus resultados (por exemplo, monitor e
impressora).

3.2 - Armazenamento de Dados e Programas na Memória

A memória do computador é dividida em unidades de armazenamento chamadas bytes, sendo cada


byte composto por 8 bits. Cada bit pode armazenar o valor zero (desligado ou desativado) ou um (ligado
ou ativado). Cada posição da memória (byte) tem um endereço único, não sendo possível endereçar
diretamente um bit.

Nada além de zeros e uns pode ser armazenado na memória do computador. Por essa razão, todas as
informações (programas, textos, imagens, etc.) são armazenadas com o uso de uma codificação
numérica na forma binária (seqüência de oito zeros e uns). Por exemplo, o número 5 é representado na
base binária com a seqüência 00000101.

Centro Universitário Vila Velha


Disciplina: Programação I Centro Universitário Vila Velha
Espírito Santo
o
Professores: Elizabeth Klippel
Ester Maria Klippel
5

Já que só podemos armazenar números na memória. Como armazenar um texto?


Para armazenar uma seqüência de caracteres que representa o texto atribui-se, utilizando a tabela ASCII
- American Standard Code for Information Interchange, disponível no blog,a cada caractere um código
numérico. Assim associa-se ao caractere A o código 65, ao caractere B o código 66, e daí por diante. Se
todos os caracteres tiverem códigos associados (inclusive os caracteres de pontuação e formatação),
podemos armazenar um texto na memória do computador como uma seqüência de códigos numéricos.

A mesma estratégia é usada para executar um programa na memória do computador. Um programa


executável é uma seqüência de instruções que a CPU interpreta, executando as operações
correspondentes. Essa seqüência de instruções também é representada como uma seqüência de
códigos numéricos.

3.3 - Construção de Programas

Quando programamos, em geral, utilizamos um ambiente integrado de desenvolvimento (IDE –


Integrated Development Enviromment), que possui basicamente: um editor de texto, que reconhece
o texto como sendo um programa, identificando e destacando os elementos importantes da linguagem, e
um compilador, que verifica se o texto digitado obedece à sintaxe da linguagem de programação e,
caso isso ocorra, traduz o texto para uma seqüência de instruções em linguagem de máquina.

Nós utilizaremos o ambiente de programação Dev-C++ (software livre disponível gratuitamente em


http://www.boodshed.net que utiliza o compilador gcc do Projeto GNU - General Public License
http://www.boodshed.net),
(http://www.gnu.org).

A tradução da linguagem de programação para a linguagem de máquina é necessária porque um


programa escrito em C não pode ser diretamente executado, pois os computadores só executam
programas em Linguagem de Máquina específica a cada modelo de máquina (por exemplo, um PC com
o sistema operacional Windows ou um PC com o sistema operacional Linux, são consideradas
“máquinas” ou “plataformas” diferentes). Assim o processo de compilação deve ser repetido para cada
plataforma. Uma vez que um programa em C compilado para um PC com Windows não pode ser
executado em um PC com Linux e vice-versa.

O processo de compilação, na verdade, se dá em duas fases, como mostra a figura abaixo:


- a fase de tradução, que transforma o Programa Fonte em Programa Objeto e
- a fase de ligação, que junta o Programa Objeto às instruções necessárias das bibliotecas para produzir o
programa executável.

Editor

Programa Programa
Compilador
Fonte Objeto
Programa
Ligador
Executável
Bibliotecas
incluídas

O programa executável, por ser escrito em Linguagem de Máquina, pode ser executado em qualquer
máquina que possua a mesma Linguagem de Máquina. A máquina em que o programa é executado não
precisa ter um Compilador instalado, nem precisa ter acesso ao código C do programa.

4- Estrutura de um Programa em C

Para exemplificar a estrutura de um programa em C, apresentaremos o código de um programa simples


que lê dois números inteiros e imprime a média aritmética. Neste momento não deve haver preocupação
com o entendimento de todo o código apresentado. As características essenciais da linguagem serão
detalhadamente apresentadas e discutidas posteriormente.

Centro Universitário Vila Velha


Disciplina: Programação I Centro Universitário Vila Velha
Espírito Santo
o
Professores: Elizabeth Klippel
Ester Maria Klippel
6

# include<stdio.h> //contém as implementações do printf e scanf


# include<stdlib.h> //contém a implementação do system
main ()
{
float n1, n2;

printf ("Digite o primeiro numero: ");


scanf ("%f",&n1);

printf ("Digite o segundo numero: ");


scanf ("%f",&n2);

printf("Media: %f\n", (n1+n2)/2);

system("PAUSE"); //exibe a mensagem ”Pressione qualquer tecla para continuar...” e aguarda que algo seja teclado
}

Observações:
i - Função main
Um programa em C deve ter obrigatoriamente a função principal main, uma vez que a execução do
programa começa sempre por ela.
A execução se inicia na primeira instrução da função main e continua executando seqüencialmente até a
última instrução, obedecendo a ordem em que elas são dispostas no texto da main.
Por enquanto utilizaremos o cabeçalho da função main em sua forma mais simples, como a mostrada no
exemplo. Posteriormente retornaremos a este assunto para mais detalhes.

ii - Bibliotecas
As bibliotecas são incluídas no programa através do comando #include. No nosso exemplo, a biblioteca
<stdio.h> se fez necessária devido aos comandos printf e scanf. A biblioteca <stdlib.h> se deve ao
comando system. O compilador ao encontrar uma instrução #include no programa fonte traduzirá o texto
presente no arquivo *.h da instrução #include da mesma forma como faria se o texto tivesse sido digitado
no programa fonte.

iii - Chaves
Os símbolos { e } indicam início e fim de uma rotina.

iv - Quebra de linha e Recuo à Direta dos Comandos


A linguagem C não impõe uma formatação rígida. Podemos, por exemplo, escrever vários comandos em
uma mesma linha. No entanto, para que nosso código possua maior legibilidade, escreveremos, sempre
que possível, um comando por linha, recuados à direita, destacando a hierarquia dos comandos.

v - Ponto-e-vírgula
O ponto-e-vírgula é usado para terminar as declarações e comandos.

vi - Comentários:
Os comentários, utilizado para documentação do programa e ignorados durante a compilação, podem
ser incluídos no código fonte utilizando: // para comentários de linha ou /* */ para bloco de comentários.

vii - Case Sensitive


A linguagem C é case sensitive, ou seja, considera diferentes as letras maiúsculas e minúsculas. Assim,
o nome da função principal deve ser escrito em letras minúsculas: main. Qualquer outra forma de
escrever retornará um erro de sintaxe.

viii - keywords - Palavras Reservadas da Linguagem


São usadas para estruturação do programa, tais como main e if. Em geral, são escritas em minúsculas.

ix - Identificadores
São nomes usados para se fazer referência a variáveis, constantes, tipos, funções, e vários outros
objetos definidos pelo usuário. Podem ser escritos usando letras, dígitos e sublinhado. Sendo que o
primeiro caractere deve ser uma letra ou um sublinhado.

Centro Universitário Vila Velha


Disciplina: Programação I Centro Universitário Vila Velha
Espírito Santo
Professores: Elizabeth Klippel
Ester Maria Klippel
7

Cada identificador deve identificar um único objeto dentro de um mesmo escopo do programa e deve ser
representativo quanto a sua função no programa.
A forma de escrita de um identificador é de fundamental importância para a qualidade e extencibilidade
do programa. Atualmente desenvolvedores do mundo todo tem usado os padrões de nomes sugeridos
pela Microsoft, sendo eles:

Pascal Case:
A primeira letra do identificador e a primeira letra de cada palavra subseqüente concatenada é escrita em
maiúscula.
Exemplos: SalarioFamilia, DataAniv

Camel Case:
A primeira letra do identificador é escrita em minúscula e a primeira letra de cada palavra subseqüente
concatenada é escrita em maiúscula.
Exemplos: salarioFamilia, dataAniv

Uppercase:
Todas as letras do identificador são escritas em maiúscula. Este padrão deve ser usado apenas para
identificadores compostos por duas ou menos letras.
Exemplos: ID

Seguindo a sugestão da Microsoft, nós utilizaremos os padrões como mostrado a seguir:


Objeto Case
Constante Pascal
Variável Camel
Tipo de Dado Pascal
Função Pascal
Parâmetro Camel

5 - Tipos de Dados Básicos

Para armazenar um dado (valor) na memória do computador devemos reservar o espaço (em bytes)
correspondente ao tipo do dado. A linguagem C possui diversos tipos básicos de dados, nós
trabalharemos com os listados abaixo, observe que cada um utiliza um espaço de memória (número de
bytes) diferente.

Tipo Tamanho Valor Faixa de Abrangência


(bytes)
char 1 Um caractere ou um inteiro de -128 a 127. Um Um caractere ou um inteiro de -128 a
caractere é representado entre apóstrofos (‘ ’). 127.
Observaremos posteriormente que uma seqüência de
caracteres é representada entre aspas (“ ”).
int 4 Um número inteiro. de –2147483648 a 2147483647
float 4 Um número com parte fracionária, com pelo menos 6 de 3.4 E-38 a 3.4 E+38
dígitos de precisão decimal.
double 8 Um número com parte fracionária, com pelo menos 10 de 1.7 E-308 a 1.7 E+308
dígitos de precisão decimal.

O tipo lógico (falso ou verdadeiro) não existe na linguagem C. Um valor igual a zero é considerado um
valor lógico falso, e qualquer valor diferente de zero (por exemplo, 1) é considerado um valor lógico
verdadeiro. Mais tarde usaremos este fato nas condições das estruturas de controle.

6 - Variáveis

Quando desenvolvemos um programa este normalmente recebe dados, os quais precisam ser
armazenados na memória RAM do computador para que possam ser usados no processamento. As
variáveis são usadas para permitir o armazenamento e o processamento destes dados.

Variável, no sentido de programação, é uma região previamente identificada e que tem por finalidade
armazenar temporariamente os dados de um programa.

Centro Universitário Vila Velha


Disciplina: Programação I Centro Universitário Vila Velha
Espírito Santo
Professores: Elizabeth Klippel
Ester Maria Klippel
8

O tipo do dado do valor armazenado deve ser definido previamente, uma vez que, cada tipo de dado é
armazenado de forma diferente na memória, gastando quantidades diferentes de bytes.

Sintaxe:
<tipo de dado> <nome da variável>;

onde:
<tipo de dado> - determina a natureza do dado que será armazenado.
<nome da variável> - serve de referência ao dado armazenado no espaço de memória

Quando duas ou mais variáveis forem do mesmo tipo, estas podem ser declaradas juntas, basta separá-
las por vírgula.

Exemplos:
int num;
float nota1, nota2;
char sexo;

Um valor pode ser atribuído a uma posição de memória representada por uma variável através do
operador de atribuição =. O operador de atribuição, em geral, possui à esquerda um nome de variável e
à direita um valor.

Uma vez declarada a variável só podemos lhe atribuir valores do mesmo tipo declarado, ou menores.
Não é possível, por exemplo, armazenar um valor real em uma variável inteira. Se fizermos:
int x;
x = 4.3;
será armazenado em x apenas a parte inteira do número real, isto é, 4. Alguns compiladores exibem
uma advertência quando encontram este tipo de atribuição. Uma exceção permitida é a atribuição de um
valor inteiro a uma variável float ou double, neste caso o valor inteiro é automaticamente convertido para
float ou double.

As variáveis podem ser inicializadas durante a declaração, como mostrado a seguir:


int x = 3, y = 4;

7 - Constantes

Declaramos como constantes dados que permanecerão inalterados durante toda a execução do
programa. As constantes são usadas muitas vezes para aumentar a clareza, a facilidade de manutenção
e a legibilidade do programa.

Sintaxe:
#define <nome da constante> <valor>

Exemplo:
#define Media 7

8 - Operadores

8.1 - Operadores Aritméticos

Trabalham com operandos numéricos. São eles:


Operadores Aritméticos
Prioridade Operador Significado
1 - Operador menos unário
2 * Multiplicação
2 / Divisão
2 % Operador Módulo. Retorna o resto inteiro da divisão. Aplica-se

Centro Universitário Vila Velha


Disciplina: Programação I Centro Universitário Vila Velha
Espírito Santo
Professores: Elizabeth Klippel
Ester Maria Klippel
9

somente a operandos inteiros.


3 + Soma
3 - Subtração

Exemplos de uso do operador %:


10 % 3 retorna 1
2%3 retorna 2
5%1 retorna 0

As operações são feitas no tipo do operando de maior precisão. Assim, se somarmos um número int a
um número double, teremos um resultado double.

Particularmente, na divisão a expressão 5/2 resulta no valor 2, já que a operação / é feita na precisão
inteira, uma vez que 5 e 2 são inteiros. Já as expressões 5.0/2.0, 5/2.0 ou 5.0/2 resultam no valor real
2.5, uma vez que pelo menos um dos operandos é real.

Exemplo utilizando a precisão dos operandos:


int a;
double b, c;

a = 3.5; // armazena o valor 3 na variável a, truncando 0.5
printf("a= %d", a);
b = a/2.0; // armazena 1.5 na variável b
printf("b= %f", b);
c = 1/3 + b; // armazena 1.5 na variável c, uma vez que, 1/3 resulta no valor 0
printf("c= %f", c);

Operadores com a mesma ordem de prioridade são avaliados da esquerda para a direita, ou seja, o
operador que aparece primeiro. Assim, na expressão
a+b*c/d
executa-se 1º a multiplicação, seguida da divisão e da soma. A Ordem de Prioridade pode ser alterada
através dos parênteses. Assim, na expressão
(a + b) * c / d
executa-se primeiro a soma seguida da multiplicação e divisão.

8.2 - Operadores de Atribuição

A linguagem C, como usado anteriormente, utiliza o símbolo = para atribuir valores a variáveis. Por
exemplo, x = 5, armazena o valor 5 no espaço de memória reservado para a variável x.

È possível atribuir valores a mais de uma variável ao mesmo tempo. Neste caso a ordem de avaliação é
da direita para a esquerda. No exemplo,
y = x = 5;
o computador avalia x = 5, armazenando 5 em x, e, em seguida, armazena em y o valor produzido por x
= 5, que é 5. Portanto, x e y recebem o valor 5.

È possível ainda utilizar os chamados operadores de atribuição compostos. Comandos do tipo


i = i + 1;
em que a variável aparece em ambos os lados do comando de atribuição podem ser escritos na forma
compacta
i += 1;
usando o operador de atribuição composto +=. Analogamente, existem os operadores compostos -=, *=,
/=, %=.

8.3 - Operadores de Incremento e Decremento

Uma operação muito comum em programação e o incremento ou decremento de uma unidade no valor
de uma variável. A linguagem C traz dois operadores, ++ e --, para facilitar estas operações.

Centro Universitário Vila Velha


Disciplina: Programação I Centro Universitário Vila Velha
Espírito Santo
Professores: Elizabeth Klippel
Ester Maria Klippel
10

Assim, ao invés de escrevermos x = x + 1 podemos escrever x++.

Analogamente, no lugar de x = x – 1 podemos escrever x--.

Os operadores ++ e -- podem ser prefixos ou sufixos ao nome da variável. Quando a operação de


incremento ou decremento aparece isolada não faz diferença usar o operador como prefixo ou sufixo.

Exemplo:
int x = 5;
x++; // resulta em x=6
x = 5;
++x; // resulta em x=6

Contudo, quando a operação de incremento ou decremento faz parte de uma expressão faz muita
diferença usar o operador como prefixo ou sufixo.

Exemplo:
int y;
int x = 5;
y = x++ + 2; // equivalente a y = x + 2; seguido de x = x + 1; resulta em y = 7 (5+2) e x = 6
x = 5;
y = ++x + 2; // equivalente a x = x + 1; seguido de y = x + 2; resulta em x = 6 e y = 8 (6+2)

8.4 - Operadores Relacionais

São usados para comparar dois valores. São eles:


Operadores Relacionais
Operador Significado
== Igual a
!= Diferente de
> Maior que
< Menor que
>= Maior ou igual a
<= Menor ou igual a

As expressões relacionais retornam os valores zero (falso) ou diferente de zero (verdadeiro).

A prioridade dos operadores segue a precedência posicional, ou seja, o operador que primeiro aparece
na expressão tem maior prioridade. Os parênteses podem ser usados para alterar a prioridade.

Exemplo:
Supondo A = 10 e B = 5, temos:
A>B não retorna 0 - verdadeiro
(A = = B) != (5 < B) retorna 0 - falso

8.5 - Operadores Lógicos

São utilizados para combinar expressões booleanas. São eles:


Operadores Lógicos
Prioridade Símbolo Operador
1 ! Operador unário de negação NÃO
2 && Operador binário E
3 || Operador binário OU

Expressões conectadas por !, &&, ou || são avaliadas da esquerda para a direita, e a avalição pára
assim que a veracidade ou a falsidade do resultado for conhecida. O resultado obtido será sempre um
valor 0 (falso) ou diferente de zero (verdadeiro). Os parênteses podem ser usados para mudar a
prioridade das operações.

Centro Universitário Vila Velha


Disciplina: Programação I Centro Universitário Vila Velha
Espírito Santo
Professores: Elizabeth Klippel
Ester Maria Klippel
11

Operador NÃO: ! <operando>


Inverte o estado lógico do operando, como mostra a tabela abaixo.
Operando: p Resultado: ! p
V F
F V

Exemplo: Supondo a verdadeiro, temos:


!a resultando 0 - falso
! !a não resultando 0 - verdadeiro

Operador E: <operando 1> && <operando 2>


Retorna verdadeiro somente quando todos os operandos são verdadeiros, como mostra a tabela abaixo.
Operando 1: p Operando 2: q Resultado: p && q
V V V
V F F
F V F
F F F

Exemplo: Supondo a verdadeiro e b falso, temos:


a && b resultando 0 - falso
a && !b não resultando 0 - verdadeiro
!(b && a) não resultando 0 - verdadeiro

Operador OU: <operando 1> || <operando 2>


Retorna verdadeiro sempre que um dos operandos for verdadeiro, como mostra a tabela abaixo.
Operando 1: p Operando 2: q Resultado: p || q
V V V
V F V
F V V
F F F

Exemplo: Supondo a verdadeiro e b falso, temos:


a || b não resultando 0 - verdadeiro
!a || b resultando 0 - falso
! (b || a) resultando 0 - falso
a || b && !a não resultando 0 - verdadeiro

8.6 - Expressões Mistas

Como os operadores aritméticos, relacionais e lógicos podem ser combinados dentro de uma mesma
expressão a prioridade entre eles deve ser observada. Os parênteses podem ser usados para mudança
na prioridade.
Prioridade Operador
1 !
2 *, /, %, &&
3 +, -, ||
4 = = , !=, >, <, >=, <=

Exemplo: Supondo x = 3, y = 1 e b falso, temos:


!(x < y + 2) || !b não resultando 0 – verdadeiro.

Observe que !b não chega a ser avaliada, pois, independente do seu resultado a expressão terá como resultado verdadeiro, uma
vez que !(x < y + 2) tem valor verdadeiro.

9 - Funções de Entrada e Saída de Dados


Utilizam a biblioteca stdio.h.

9.1 - Função de Saída de Dados

Transmite para o mundo exterior (dispositivo de saída - adotaremos o monitor como dispositivo de saída
padrão) um ou mais valores, permitindo ao usuário acesso aos resultados obtidos pelo algoritmo.

Centro Universitário Vila Velha


Disciplina: Programação I Centro Universitário Vila Velha
Espírito Santo
Professores: Elizabeth Klippel
Ester Maria Klippel
12

Sintaxe:
printf (<formatos>, <lista de constantes/variáveis/expressões>);

Onde <formatos> é uma cadeia de caracteres, delimitada por aspas, que contém o formato de saída das
constantes, variáveis e expressões listadas a seguir.

Na <lista de constantes/variáveis/expressões>, para cada valor que se deseja imprimir, deve existir
ordenadamente um especificador de formato correspondente na cadeia de caracteres <formatos>. Os
diversos valores devem ser separados por vírgula.

Os especificadores de formato (ou tags) variam com o tipo do valor e a precisão com que queremos que
sejam impressos. Estes especificadores são precedidos pelo caracter % e podem ser, entre outros:
Especificador ou Tag Significado
%c Especifica um char
%d Especifica um int
%f Especifica um double ou float
%e Especifica um double ou float no formato científico
%s Especifica uma cadeia de caracteres

A precisão é informada após o símbolo %, como mostrado a seguir:


%7f – especifica a impressão de um double ou float usando no mínimo 7 caracteres (incluindo os dígitos, o sinal e o ponto decimal,
se houver).

%7.2f – especifica a impressão de um double ou float usando no mínimo 7 caracteres, fixando 2 casas decimais. Espaços em
branco por ventura existentes são alinhados à esquerda.

%.2f – especifica a impressão de um double ou float fixando 2 casas decimais.

Se o tamanho do campo for maior do que o necessário para a impressão são incluídos caracteres brancos à esquerda. Se o
tamanho do campo for menor que o necessário para a impressão este é ignorado e o número é impresso normalmente.

Exemplo:
Comando Valor Impresso
float x = 21.5687124; printf("%5f", x); 21.568712
printf("%7.2f", x); 21.57
printf("%5.2f", x); 21.57
printf("%.3f", x); 21.569

Existem ainda outros caracteres de escape freqüentemente usados nos formatos de saída. Entre eles:
Caracter de Escape Significado
\n Imprime uma nova linha
\t Imprime uma tabulação horizontal
\” Imprime o caracter “
\\ Imprime o caracter \

Exemplos:
printf (“Salário Mensal: R$ %7.2f \n”, salarioFunc);
printf (“Média: %5.2f Total de Faltas: %d, (nota1 + nota2)/2, faltas);

9.2 - Função de Entrada de Dados

Transfere um ou mais dados do mundo exterior (dispositivo de entrada - adotaremos o teclado como
dispositivo de entrada padrão) para uma ou mais variáveis na memória.

Como no comando de atribuição o valor transferido para a variável deve ser compatível com o tipo para
ela declarado.

Sintaxe:
scanf (<formatos>, <lista de endereços das variáveis>);

Centro Universitário Vila Velha


Disciplina: Programação I Centro Universitário Vila Velha
Espírito Santo
Professores: Elizabeth Klippel
Ester Maria Klippel
13

Onde <formatos> possuem especificadores similares aos usados pela função printf. Exceção para os
tipos float e double que possuem especificadores distintos.
Especificador Significado
%c Especifica um char
%d Especifica um int
%f Especifica um float
%lf Especifica um doble
%s Especifica uma cadeia de caracteres

Na <lista de endereços das variáveis> é necessário passar o endereço de cada variável, isto é feito
escrevendo o operador & antes do nome de cada variável.

Exemplos:
float salario;
char sexo;
int idade;
printf (“Digite o salário: ”);
scanf (“%f”, &salário);
printf (“Digite a idade e o sexo: ”);
scanf (“%d %c”, &idade, &sexo);

Quando uma instrução como scanf(“%f”, &salario); é realizada a execução do programa é


interrompida e o computador fica aguardando que o usuário digite um valor correspondente ao tipo da
variável e, em seguida, pressione enter.

Ao reconhecer que o usuário pressionou enter o computador armazena o valor digitado na variável e
volta à execução do programa.

Vale ressaltar que o especificador %c não pula os caracteres brancos (caractere espaço ‘ ‘, caractere de
tabulação ‘\t’ ou caractere de nova linha ‘\n’). Assim, se o usuário teclar um caractere branco antes de
teclar o caractere a ser lido, o código do branco será capturado, e o caractere que realmente interessava
somente será capturado em uma nova chamada da função scanf. Para resolver este problema, ou seja,
se desejarmos ignorar todas as ocorrências de caracteres brancos que, porventura, antecedam o
caractere que desejamos capturar, basta incluir um espaço em branco no formato, antes do
especificador.

Exemplo:
char sexo;
printf (“Digite o sexo: ”);
scanf (“ %c”, &sexo);

Outra forma de resolver o problema é usar a função fflush com o argumento stdin antes da execução
de um scanf com o especificador %c. A função fflush (stdin) limpará o buffer associado ao teclado (stdin
– standard input).

Exemplo:
char sexo;
printf (“Digite o sexo: ”);
fflush (stdin);
scanf (“ %c”, &sexo);

Exercícios em aula: os 7 primeiros da lista “Seqüência Simples de Comandos”.

10 - Comandos de Decisão

São comandos que causam desvio no processamento, permitindo que um determinado bloco de
comandos possa ser escolhido ou não para a execução.

Centro Universitário Vila Velha


Disciplina: Programação I Centro Universitário Vila Velha
Espírito Santo
Professores: Elizabeth Klippel
Ester Maria Klippel
14

10.1 - Comando if

Sintaxe:
if ( <condição> )
{
<bloco de comandos>
}

A <condição> deve ser uma expressão que retorne um valor falso (0) ou verdadeiro (diferente de 0).

Quando a <condição> retorna o valor lógico verdadeiro o <bloco de comandos> é executado. Caso
contrário, o comando seguinte ao comando if é executado.

As chaves { } são opcionais quando o <bloco de comandos> for composto por apenas um comando.

Exercícios em aula: exercícios 1, 2 e 3 da lista “Comandos de Seleção”.

10.2 - Comando if/else

Sintaxe:
if ( <condição> )
{
< bloco de comandos 1 >
}
else
{
< bloco de comandos 2 >
}

Quando a <condição> retorna o valor lógico verdadeiro o <bloco de comandos1> é executado. Caso
contrário, o < bloco de comandos2> é executado.

As chaves { } são opcionais quando o <bloco de comandos> for composto por apenas um comando.

Exercícios em aula: exercícios 4 a 11 da lista “Comandos de Seleção”.

10.3 - Comando switch

Sintaxe:
switch ( <seletor> )
{
case <valor1> :
< bloco de comandos executado se seletor = = valor1 >;
break;
case <valor2> :
< bloco de comandos executado se seletor = = valor2 >;
break;

...

default :
< bloco de comandos executado se seletor diferente de todos os valores >;
break;
}

Permite que um ou mais < blocos de comandos> sejam executados, dependendo do valor do <seletor>.

O valor do <seletor> é comparado com cada um dos <valores>. Se existir um <valor> igual ao do
<seletor> o < bloco de comandos> relacionado é executado até encontrar um break. Se o comando
break for omitido a execução continua com os comandos dos case seguintes.

Se o valor do <seletor> for diferente de todos os valores dos case o < bloco de comandos> relacionado
a clausula default é executado.

Centro Universitário Vila Velha


Disciplina: Programação I Centro Universitário Vila Velha
Espírito Santo
Professores: Elizabeth Klippel
Ester Maria Klippel
15

A clausula default é opcional e pode aparecer em qualquer posição, mas normalmente é colocada no
final.

O <seletor> deve ser um número inteiro ou um caracter.

Exercícios em aula: 12 da lista “Comandos de Seleção”

Quando um mesmo < bloco de comandos> deve ser executado para diferentes valores, devemos
encadear uma seqüência de case sem break, e o < bloco de comandos> é colocado no último dos case,
que conterá um break.

Exemplo:
#include <stdio.h>
#include <stdlib.h>
main()
{
int n;
printf("Digite um numero inteiro no intervalo [2, 6]: ");
scanf ("%d", &n);
switch (n)
{
case 2 : case 4 : case 6 :
printf("numero par\n");
break;
case 3 : case 5 :
printf("numero impar\n");
break;
default :
printf("valor fora do intervalo\n");
break;
}
system("PAUSE");
}

Exercícios em aula: exercícios 13 a 17 da lista “Comandos de Seleção”.

11 - Comandos de Repetição

Permitem que um bloco de comandos seja executado um número repetido de vezes.

11.1 - Comando while

Sintaxe:
while ( <condição> )
{
< bloco de comandos>
}

Antes de executar o < bloco de comandos> a <condição> é avaliada. Caso seja verdadeira o <bloco de
comandos> é executado. Caso contrário, o comando seguinte ao comando while é executado.

Supondo que o < bloco de comandos> seja executado, após a execução o processamento é desviado
para o início do comando while, e a <condição> é novamente avaliada.

O processo descrito acima se repete até que a <condição> se torne Falsa.

Observe que a <condição> deve ser tornar falsa em algum momento. Caso contrário, teremos,
teoricamente, infinitas repetições (loop).

Centro Universitário Vila Velha


Disciplina: Programação I Centro Universitário Vila Velha
Espírito Santo
Professores: Elizabeth Klippel
Ester Maria Klippel
16

Observe ainda que se a <condição> for falsa na primeira avaliação (quando o while é iniciado) o < bloco
de comandos> não é executado vez alguma.

As chaves { } são opcionais quando o <bloco de comandos> for composto por apenas um comando.

Exercícios em Aula: exercícios 1 a 12 da lista “Comandos de Repetição”.

11.2 - Comando do-while

Sintaxe:
do
{
< bloco de comandos>
}
while ( <condição> );

Observe que como a <condição> é testada no final de cada iteração, o <bloco de comandos> é
executado pelo menos uma vez.

Ao término da execução do <bloco de comandos> a <condição> é avaliada. Caso seja verdadeira, o


processamento é desviado para o início do comando do while e o <bloco de comandos> é novamente
executado. Caso contrário, o comando seguinte ao comando do while é executado.

O processo descrito acima se repete até que a <condição> se torne Falsa.

Observe que a <condição> deve ser tornar falsa em algum momento. Caso contrário, teremos,
teoricamente, infinitas repetições (loop).

As chaves { } são opcionais quando o <bloco de comandos> for composto por apenas um comando.

Exercícios em Aula: exercícios 22 a 25 da lista “Comandos de Repetição”.

11.3 - Comando for

O mais compacto dos comandos de repetição.

Sintaxe:
for ( <expr de inicialização> ; <condição> ; <expr de incremento ou decremento> )
{
<bloco de comandos>
}

Em sua forma mais simples, a <expr de incialização> é um comando de atribuição que o compilador usa
para estabelecer a variável de controle do for. A <condição> é uma expressão de relação que testa a
variável de controle do for contra algum valor para determinar quando o loop terminará. O <expr. de
incremento ou decremento> define a maneira como a variável de controle do loop será alterada cada vez
que o <bloco de comandos> for repetido.

As chaves { } são opcionais quando o <bloco de comandos> for composto por apenas um comando.

Passos Executados Automaticamente pelo Comando for:


Passo 1: a <expr de inicialização> é avaliada
Passo 2: a <condição> é avaliada
SE verdadeira vai para o passo 3
SE falsa encerra o comando for

Centro Universitário Vila Velha


Disciplina: Programação I Centro Universitário Vila Velha
Espírito Santo
Professores: Elizabeth Klippel
Ester Maria Klippel
17

Passo 3:
3 Executa o <bloco de comandos>
Passo 4: Retorna ao início do comando FOR e executa a <expr de incremento ou decremento>
Passo 5: Vai para o Passo 2.

O comando for
for ( <expr de inicialização> ; <condição> ; <expr de incremento ou decremento> )
{ < bloco de comandos> }
é equivalente a:
<expr de inicialização>
while ( <condição> )
{
< bloco de comandos>
<expr de incremento>
}

Exercícios em Aula: exercícios 26 a 32 da lista “Comandos de Repetição”.

12 - Vetores – Variáveis Compostas Homogêneas Unidimensionais

Permitem o armazenamento de várias informações dentro de uma mesma variável, ou seja, em um


espaço contínuo de memória (variáveis compostas). Contudo, as informações armazenadas são todas
de um mesmo tipo de dado (variáveis compostas homogêneas). Cada informação é acessada
individualmente através de um índice (variáveis compostas homogêneas unidimensionais ou vetores).

Declaração:
<tipo do dado> <nome do vetor> [<tamanho>];

Onde: <tipo do dado> : tipo dos dados armazenados no vetor.


<tamanho> : nº de elementos do vetor, representado por valores constantes inteiros positivos.

Exemplo:
float notas [5]; //notas é uma variável do tipo vetor composto por 5 componentes do tipo float.

Abstraindo, podemos imaginar o vetor notas graficamente como:


Índice
0 1 2 3 4
notas =

Componente

Supondo que o vetor notas armazene os valores 7, 10, 9.5, 8 e 6.5 teremos;
0 1 2 3 4
notas = 7 10 9.5 8 6.5

Observe que o acesso a cada componente do vetor é feito através de um índice. A indexação começa de
zero e vai até <dimensão> -1.

A referência é feita pelo nome do vetor seguido, entre colchetes, pelo índice do componente que se
deseja referenciar. No exemplo, o terceiro componente é referenciado por notas[2].

Um vetor pode ser inicializado na declaração como mostrado abaixo:


int v[5] = {15, 20, 25, 30, 35};

É possível ler o número de elementos de um vetor antes de sua declaração.

Exemplo:
main ()
{
int n;
do {
printf (“informe o número de elementos do vetor: “);

Centro Universitário Vila Velha


Disciplina: Programação I Centro Universitário Vila Velha
Espírito Santo
o
Professores: Elizabeth Klippel
Ester Maria Klippel
18

scanf (“%d”, &n);


if (n <= 0) printf (“\nValor inválido!\n”);
} while (n <= 0);
float vet[n];
}

Exercícios em Aula: exercícios 1 a 13 da lista “Vetores”.

13 - Pesquisa em Vetores

Na literatura existem diversos algoritmos capazes de localizar um valor dentre os componentes de um


vetor, cada um apresentando maior ou menor eficiência de acordo com os dados de entrada. Vamos
estudar dois destes algoritmos em particular: o Método de Pesquisa Seqüencial e o Método de Pesquisa
Binária.

13.1 - Método de Pesquisa Seqüencial

Normalmente utilizado em vetores desordenados, caracteriza-se pela busca exaustiva de um valor


dentre os componentes do vetor. O método compara cada componente do vetor com o valor procurado.
A busca termina quando o valor procurado é encontrado ou quando a comparação chega ao último
componente do vetor. A posição do valor procurado, quando encontrado, retorna como resultado da
pesquisa.

Exemplo: uso do Método de Pesquisa Seqüencial para localizar proc = 7 no vetor v abaixo.

0 1 2 3 4 VERIFICA:
v= 13 21 7 9 14 v[0] = proc? não
v[1] = proc? não
v[2] = proc? sim, a busca é encerrada, retorna 2

Método de Pesquisa Seqüencial:


main()
{
int tam; printf("Quantos elementos terá o vetor "); scanf ("%d", &tam);
int v[tam];
for (int i = 0; i < tam; i++)
scanf (“%d”, &v[i]);
int proc; printf("Digite o número a pesquisar: "); scanf ("%d", &proc);

int i = 0, pos = -1;


while ( (i < tam) && (pos == -1) )
{
if (v[i] == proc)
pos = i; // encerra o processo de pesquisa
else
i ++;
}

if (pos == -1) printf ("Valor não localizado\n");


else printf ("Valor localizado na posição %d\n", pos);
}

13.2 - Método de Pesquisa Binária

Utilizado exclusivamente em vetores ordenados, é mais eficiente que o Método de Pesquisa Seqüencial.
Trabalha com três índices:
limInf: indicando o início lógico do vetor
limSup: indicando o fim lógico do vetor
meio: indicando a posição pesquisada no vetor

Centro Universitário Vila Velha


Disciplina: Programação I Centro Universitário Vila Velha
Espírito Santo
Professores: Elizabeth Klippel
Ester Maria Klippel
19

No início do processo de pesquisa os índices recebem os seguintes valores:


limInf: índice do 1º elemento do vetor
limSup: índice do último elemento do vetor
meio: parte inteira da divisão (limInf + limSup) / 2

A cada iteração o método compara o valor procurado com o elemento do vetor apontado por meio. Caso
sejam iguais, o processo de pesquisa é encerrado. Caso contrário reposiciona os três índices e, em
seguida, realiza uma nova comparação descartando alguns componentes do vetor. Chamaremos este
novo vetor após o descarte de vetor lógico.

Para reposicionar os três índices devemos saber a forma de ordenação do vetor. A forma de
reposicionamento descrita a seguir supõe o vetor em ordem crescente. Caso este esteja em ordem
decrescente basta trocar menor por maior e maior por menor nas descrições abaixo.
• Se o valor procurado é menor que o valor no índice meio do vetor continue a pesquisa na metade inferior do
vetor lógico. Ou seja, faça limSup = meio – 1 e não altere limInf. Observe que a mudança em limSup causa
uma alteração em meio.
• Se o valor procurado é maior que o valor no índice meio do vetor continue a pesquisa na metade superior do
vetor lógico. Ou seja, faça limInf = meio + 1 e não altere limSup. Observe que a mudança em limInf causa
uma alteração em meio.

A busca termina quando o valor procurado é encontrado ou quando limInf ultrapassa limSup. O último
critério de parada indica que o valor procurado não existe no vetor. A posição do valor procurado,
quando encontrado, retorna como resultado da pesquisa.

Exemplo: Método de Pesquisa Binária para localizar proc = 10 no vetor v ordenado de forma crescente.
No início do processo os três índices são inicializados e posicionados como descrito anteriormente. As comparações se iniciam e
os devidos reposicionamentos dos ponteiros são realizados.

Primeira Comparação:
0 1 2 3 4 5 6 7 8 9
v= 2 3 5 6 7 10 11 15 20 32

limInf = 0 meio = 4 limSup = 9


Verifica:
proc = v[meio] ? NÃO
proc > v[meio], logo realiza uma nova pesquisa utilizando a metade superior do vetor lógico.
limInf = meio + 1 = 5
limSup = 9 (não muda)
meio = (limInf + limSup) / 2 = 7 (parte inteira da divisão)

Segunda Comparação:
0 1 2 3 4 5 6 7 8 9
v= 2 3 5 6 7 10 11 15 20 32

Verifica: limInf = 5 meio = 7 limSup = 9


proc = v[meio] ? NÃO
proc > v[meio], logo realiza uma nova pesquisa utilizando a metade inferior do vetor lógico.
limInf = 5 (não muda)
limSup = meio - 1 = 6
meio = (limInf + limSup) / 2 = 5 (parte inteira da divisão)

Terceira Comparação:
0 1 2 3 4 5 6 7 8 9
v= 2 3 5 6 7 10 11 15 20 32

limInf = 5 limSup = 6
Verifica: meio = 5
proc = v[meio] ? SIM - o processo de pesquisa é encerrado

Centro Universitário Vila Velha


Disciplina: Programação I Centro Universitário Vila Velha
Espírito Santo
o
Professores: Elizabeth Klippel
Ester Maria Klippel
20

Método de Pesquisa Binária (vetor em ordem crescente):


main()
{
int tam; printf("Quantos elementos terá o vetor "); scanf ("%d", &tam);
int v[tam];
for (int i = 0; i < tam; i++)
scanf (“%d”, &v[i]);
int proc; printf("Digite o número a pesquisar: "); scanf ("%d", &proc)

int limInf = 0, limSup = (tam-1), pos = -1, meio;


while ( (limInf <= limSup) && (pos == -1) )
{
meio = (limInf + limSup)/2; //divisão de inteiros retorna valor inteiro
if (v[meio] == proc)
pos = meio; // encerra o processo de pesquisa
else
if (v[meio] > proc)
limSup = meio - 1; // atualiza o limSup, mantém limInf
else
limInf = meio + 1; // atualiza o limInf, mantém limSup
}

if (pos == -1) printf ("Valor não localizado\n");


else printf ("Valor localizado na posição %d\n", pos);
}

14 - Ordenação de Vetores

Ordenar um vetor significa classificar seus elementos em ordem crescente ou decrescente. Na literatura
existem diversos algoritmos para este fim, cada um apresentando maior ou menor eficiência de acordo
com os dados de entrada. Vamos estudar um destes métodos em particular: o Método da Bolha ou
Bubble Sort.

14.1 - Método da Bolha

Uma iteração do Método da Bolha consiste em “varrer” o vetor comparando dois a dois os elementos
adjacentes. Caso estes estejam em posições invertidas o método efetua a troca de posições.

Durante todo o processo de ordenação o método trabalha com o índice limSup, que inicialmente aponta
para o último elemento do vetor e a cada iteração é decrementado de uma unidade, passando a apontar
para o elemento limSup -1 do vetor. As iterações se repetem até que o método perceba que o vetor está
completamente ordenado.

Exemplo: uso do Método da Bolha para classificar, em ordem crescente, o vetor v abaixo.
0 1 2 3 4 Início do Processo
v= 5 1 9 3 4

limSup = 4

0 1 2 3 4 Primeira Iteração
v= 1 5 9 3 4 Compara v[0] com v[1] e os troca de posição

limSup = 4
0 1 2 3 4 Primeira Iteração
v= 1 5 9 3 4 Compara v[1] com v[2] e não os troca de posição

limSup = 4
0 1 2 3 4 Primeira Iteração
v= 1 5 3 9 4 Compara V[2] com V[3] e os troca de posição

limSup = 4

Centro Universitário Vila Velha


Disciplina: Programação I Centro Universitário Vila Velha
Espírito Santo
o
Professores: Elizabeth Klippel
Ester Maria Klippel
21

0 1 2 3 4 Primeira Iteração
v= 1 5 3 4 9 Compara V[3] com V[4] e os troca de posição

limSup = 4

Observe que, após comparar os elementos adjacentes dois a dois, do índice 0 até o índice limSup, o
maior elemento está na última posição. Contudo o vetor continua desordenado.

Uma nova iteração se faz então necessária. No entanto, observe que o valor no último índice do vetor já
está em sua posição definitiva. Assim, o último elemento do vetor não precisa mais participar do
processo de comparação. Faz-se então limSup = limSup – 1.

0 1 2 3 4 Segunda Iteração
v= 1 5 3 4 9 Compara V[0] com V[1] e não os troca de posição

limSup = 3
0 1 2 3 4 Segunda Iteração
v= 1 3 5 4 9 Compara V[1] com V[2] e os troca de posição

limSup = 3

0 1 2 3 4 Segunda Iteração
v= 1 3 4 5 9 Compara V[2] com V[3] e os troca de posição

LimSup = 3

Novamente observe que, após comparar os elementos adjacentes dois a dois, do índice 0 até o índice
limSup, os dois maiores valores estão nas duas últimas posições. Como o segundo maior já se encontra
em sua posição definitiva faz-se limSup = limSup – 1.

Observe ainda que o vetor já está ordenado. Contudo, como o método ainda não percebeu este fato uma
nova iteração se faz necessária.

0 1 2 3 4 Terceira Iteração
v= 1 3 4 5 9 Compara V[0] com V[1] e não os troca de posição

limSup = 2

0 1 2 3 4 Terceira Iteração
v= 1 3 4 5 9 Compara V[1] com V[2] e não os troca de posição

limSup = 2
O método, após comparar os elementos adjacentes dois a dois, do índice 0 até o índice limSup, e não
conseguir realizar uma única troca percebe a ordenação do vetor e encerra o método.

Método de Ordenação Bubble Sort (ordem crescente):


main()
{
int tam; printf("Quantos elementos terá o vetor "); scanf ("%d", &tam);
int v[tam];
for (int i = 0; i < tam; i++)
scanf (“%d”, &v[i]);

int limSup = (tam-1), trocou, i, aux;


do {
trocou = 0;
//após execução dos passos abaixo o maior valor ainda não classificado vai para v[limSup]

Centro Universitário Vila Velha


Disciplina: Programação I Centro Universitário Vila Velha
Espírito Santo
o
Professores: Elizabeth Klippel
Ester Maria Klippel
22

for (i=0; i <= (limSup-1); i++)


{
if (v[i] > v[i+1])
{
aux = v[i]; v[i] = v[i+1]; v[i+1] = aux;
trocou = 1;
}
}
limSup = limSup – 1;
} while (trocou==1);

printf (“Vetor ordenado\n”);


for (int i = 0; i < tam; i++)
printf (“%d ”, v[i]);
}

Centro Universitário Vila Velha


Disciplina: Programação I Centro Universitário Vila Velha
Espírito Santo
Professores: Elizabeth Klippel
Ester Maria Klippel

Вам также может понравиться