Upload
uarlei-souza
View
68
Download
0
Embed Size (px)
Citation preview
Introdução à Programação
Apresentação da Disciplina e
Conceitos Básicos de
Computadores
2
Objetivos
Aprender técnicas de programação que aumentem aqualidade de software e a produtividade nodesenvolvimento
Discutir conceitos de programação, ilustrando como osmesmos são representados na linguagem de programaçãoCDiscutir como programas podem ser adequadamenteescritos, estruturados e documentadosExplorar o ambiente de suporte a C, incluindo ferramentas ebibliotecasDiscutir princípios de engenharia e qualidade de software.Desenvolver, documentar e avaliar uma aplicação de médioporte em C
Resultados de Semestres Anteriores
3
2541%
23%
1017%
2439%
Resultados 2010-1
Reprovados
Reprovados por faltaAprovados
Aprovados por Media
Resultados de Semestres Anteriores
4
3548%
23%
2028%
1521%
Resultados 2010-2
Reprovados
Reprovados por faltaAprovados
Aprovados por Média
5
Análise de Resultados
No último ano, 133 alunos cursaram a disciplina69 aprovados (52% de aprovação)
Apenas 39 aprovados por média (29%)64 reprovados (48% de reprovação)
ConsequênciasDificuldade de conseguir vagas para cursar a disciplina denovoVária disciplinas dependem de IP
Atraso significativo no curso de ECPara os que conseguiram passar com dificuldade,problemas para acompanhar a disciplina de Algoritmos
Além de várias outras disciplinas que exigem que oaluno desenvolva programas (Infra de SW, Infra deComunicação, etc)
6
Como Ter Sucesso na Disciplina?
Estudo diárioSão 6 horas de aula por semana
Nenhuma disciplina tem tantas aulas por semana
Programação não se aprende somente olhando olivro e exemplos
Deve-se praticar exaustivamenteProgramação não é trivial para muitos, pois envolveraciocínio lógico para resolver problemas complexos ecodificar a solução em uma linguagem de programaçãoFacilidade de acesso a computadores
Aproveitar as aulas práticas e de exercíciosEscrever programas com alguém para esclarecer dúvidasajuda muito
7
Tópicos da Aula
Antes de aprender a programar, precisamos verconceitos básicos de Computação
Componentes de um computador
Como os diferentes componentes interagem
Representação das informações em computadores
8
Hardware e Software
Computador = Hardware + Software
Hardware
Parte física do computador
Chips, monitores, teclado, etc
Software
Programas (conjunto de instruções)
e dados
Editores de texto, navegadores,
sistemas operacionais, etc
9
Modelo de um computador
CPU
Unidade Central de Processamento
Memória Principal (RAM)
Armazenamento Secundário Dispositivos de
Entrada/Saída
Canal de Comunicação (Barramento)
Disco Rígido (HD), CD,DVD, PenDrive,etc Periféricos
10
CPU e RAM
CPU
Executa as instruções presentes nos programas
Memória Principal (RAM)
Armazena os programas e dados que estão sendo
usados pela CPU
CPU busca primeiramente programas e dados
residentes na memória
CPU também armazena dados na memória
11
Unidade Central de Processamento (1)
A CPU é o “cérebro do computador
Implementado em um chip chamado demicroprocessadorFaz continuamente 3 ações:
Busca
Busca instrução na
memória principal
Decodifica
Determina o que
é a instrução
Executa
Processa a
instrução
12
Unidade Central de Processamento (2)
Os componentes principais de uma CPU são:
Unidade de Lógica/Aritmética
Registradores
Unidade de Controle
Áreas pequenas de
armazenamento
Faz cálculos e toma
decisões
Coordena as etapas
do processamento
13
A velocidade de processamento de uma CPU é dado
pelo relógio (clock) do sistema
O clock gera um pulso eletrônico em intervalos
regulares
Estes pulsos coordenam as atividades da CPU
Velocidade da CPU é medida geralmente em Hertz
(Hz)
Unidade Central de Processamento (3)
14
Armazenando Dados (1)
Memórias são
divididas em várias
células de tamanhos
iguais
Cada célula é identificada
unicamente por um valor
numérico chamado de
endereço
9278
9279
9280
9281
9282
9283
9284
9285
9286
15
Armazenando Dados (2)
Cada célula pode
armazenar um valor de
tamanho máximo fixo
Valores que ultrapassam o
tamanho máximo de uma
célula são armazenados
em mais de uma célula
(células consecutivas)
9278
9279
9280
9281
9282
9283
9284
9285
9286
10011010
16
Também chamada de memória RAM
Random Access Memory
Acesso aos endereços de memória podem ser feita de
forma direta sem ter que passar por endereços
anteriores
Armazena dados e programas utilizados pelo
processador num dado instante
Quando o computador possui sistema operacional, este é
carregado na memória geralmente na hora em que o
computador é ligado
Memória Principal
17
Computadores atuais utilizam também pequenas memórias
cache para armazenar partes dos dados e programas que
estão na memória principal
Memória cache utiliza tecnologia que torna acesso aos
dados mais rápida
Evita acesso pelo barramento
Memória Principal
CPU Memória Principal (RAM)
Cache
18
Armazenamento Secundário
CPU
Memória Principal (RAM)
Armazenamento Secundário
CPU procura programa/dadosna RAM
Não encontrando, CPUprocura na memóriasecundária
Programa/dados sãotransferidos para RAM
Tipos de memória
para armazenamento
de longa duração de
dados/programas
19
Armazenamento Secundário
(Disco Rígido)
Dispositivo magnético
Partes que são gravadas são magnetizadas
20
Armazenamento Secundário
(Disco Rígido)
Informações são gravadas em setores
Uma trilha é composta por um conjunto de
setores
setor
trilha
21
Armazenamento Secundário
(CD/DVD )
Dispositivo óptico
Pequenos furos quando lidos por laser refletem
diferentemente do resto do CD
Furos representam 0´s e espaços representam 1´s
22
Memória RAM é mais rápida do que memórias
secundárias
Memória RAM é volátil
Informação é perdida quando não há corrente elétrica
Memórias secundárias não são voláteis
Memórias secundárias geralmente são mais baratas
que a memória RAM
Por serem mais baratas, geralmente a capacidade de
armazenamento é maior (Ex: Disco Rígido)
Memória RAM x Memória Secundária
23
Dispositivos de Entrada/Saída
CPU
Memória Principal (RAM)
Armazenamento Secundário Dispositivos de
Entrada/SaídaDispositivos para
facilitar a interação
do usuário
Interação do usuário pode mudar o fluxo de execução na CPU
24
Existem, basicamente, 2 formas de representar umainformação:Modo Analógico
Contínua, diretamente proporcional aos dados queconstituem a informaçãoTermômetro de mercúrio – Mercúrio sobe em um tuboproporcionalmente ao aumento da temperatura fora do tubo
Modo DigitalInformação é quebrada em pedaços e cada pedaço érepresentado separadamenteMúsica em um CD – o disco armazena números querepresentam amostras regulares (no tempo) de níveis devoltagens específicas do som
Representação de Informação
25
Analógico x Digital
Analógico
volt
tempo
3
8
11
74
1 2 3 4 5
Digital
8
11
7
43
1 2 3 4 5
26
Computadores armazenam toda informação deforma digital
NúmerosTextoGráficos e ImagensVídeoÁudioInstruções de programas
Para isto o computador digitaliza as informações, ouseja quebra a informação em pedaços
Informação Digital
27
Em um texto, cada caractere é armazenado comoum número, incluindo espaços, dígitos e pontuaçãoCaracteres maiúsculos e minúsculos têmnumerações diferentes
Representando Texto Digitalmente
O i , M u n d o!
79 105 44 32 77 117 110 100 111 33
28
Números Binários
Quando a informação é digitalizada, ela érepresentada e armazenada em memória usando osistema de numeração binária
Um dígito binário (0 ou 1) é chamado de bit
Um bit pode representar 2 estados possíveis (0 ou 1), assimcomo uma lâmpada que pode estar ligada (1) ou desligada(0)
Dispositivos que armazenam e manipulaminformação com representação binária (com 2estados possíveis) são mais confiáveis e baratos
29
Sistema de Numeração Binária (1)
No sistema de numeração decimal utilizamos osdígitos de 0 até 9 para representar qualquer número
No sistema binário, só podemos utilizar os dígitos 0 e1 para representar um número
Exemplo: Para representar o número nove emdecimal utilizamos o dígito 9, em binário ficaria 1001
1 0 0 11x 23 + 0 x 22 + 0 x 21 + 1 x 20
30
Sistema de Numeração Binária (2)
Sistema Decimal Sistema Binário (4 bits)10987654321
1010100110000111011001010100001100100001
31
Unidades de Medida
Um byte corresponde a 8 bits
Capacidade de armazenamento de dados de umamemória é medida em termos de bytes que ela podeguardar
KB 210
= 1024
MB 220
(>1 milhão)
GB 230
(>1 bilhão)
TB 240
(>1 trilhão)
Unidade Símbolo Número de Bytes
kilobyte
megabyte
gigabyte
terabyte
32
Categorias de Software
Sistema OperacionalControla todas as atividades do computadorFornece uma interface para que o usuário interaja com ocomputadorGerencia recursos computacionais tais como CPU,memória, dispositivos de E/S, etcWindows , Unix, Linux, Mac OS
AplicativosTermo genérico para qualquer outro tipo de softwareEditores de texto, jogos, navegadores, sistemas de controleaéreo, etc
Maioria dos softwares possuem uma interface gráfica(GUI)
33
Aplicativos e Sistema Operacional
CPU
Sistema OperacionalAplicativos Gerencia
recursos do
computador
34
Usuários e Sistema Operacional
CPU
Sistema OperacionalFornece uma
interface para que
o usuário acesse
os recursos de um
computador
35
Resumindo
Componentes básicos de um sistema computacionalHardware
CPU
Memória
Periféricos
Software
Categorias de software
Introdução à Programação
Conceitos Básicos de
Programação
2
Tópicos da Aula
Antes de aprender a programar, precisamos saber oque é um algoritmo
Definição de algoritmoUsando algoritmos para resolver problemas
Depois precisamos saber o que é programação
Definição de Programa
Linguagens de Programação
Como o computador consegue entender um programa
3
Conceito de Algoritmo
Um algoritmo é um conjunto ordenado finito de passos executáveis, não ambíguos , definindo um processo que tem um término
Um algoritmo representa a sequência de passosnecessários para realizar uma tarefa
Para realizar uma mesma tarefa podemos terdiferentes algoritmos
4
Algoritmo de Conversão de Celsius
para Farenheit
Um algoritmo é um conjunto ordenado finito de passosexecutáveis, não ambíguos , definindo um processo que tem um término
1. Divida o número 9 pelonúmero 5
2. Multiplique o resultado dopasso 1 pela temperatura emgraus Celsius dada
3. Some o número 32 aoresultado obtido no passo 2
1. Multiplique 9 pelatemperatura em grausCelsius dada
2. Divida o resultado do passo1 por 5
3. Some o número 32 aoresultado obtido no passo 2
Ordem diferente dos passos Algoritmos diferentes
5
Contra-exemplo de Algoritmo
1.Retire uma moeda do bolso e coloque sobre mesa2.Volte ao passo 1
Processo chega ao fim quando acaba as moedas do bolso
Um algoritmo é um conjunto ordenado finito de passos executáveis, não ambíguos , definindo um processo que tem um término
Nenhum passo indica sobre o procedimento a ser adotado quando acaba as moedas
Ambigüidade
6
Algoritmo para Preparar um Bolo
Misture os ingredientes
Unte forma com manteiga
Despeje a mistura na forma
Tem coco ralado?
Despeje coco na mistura
Deixe a forma no forno
Dourou?
Tire do forno
Sim
Não
Sim
Pode necessitar decisões ou repetir passos
Diferentes formas de apresentar um
algoritmo
Não
7
Usando Algoritmos para resolver
problemas
Problema: Torre de HanoiDeve-se transportar todos os discos da primeira haste até a
última obedecendo as seguintes regras:
1. Só pode ser deslocado um disco por vez (o do topo de uma haste)
2. Em nenhum momento um disco maior pode estar sobre um menor
8
Usando Algoritmos para resolver
problemas
Algoritmo para torre de Hanoi com 4 discos
9
Algoritmo para a Torre de Hanoi com 4
Discos
1 2 3
1.Mova disco 1 para haste 2
1 2 3
10
2.Mova disco 2 para haste 3
3.Mova disco 1 para haste 3
Algoritmo para a Torre de Hanoi com 4
Discos
11
4.Mova disco 3 para haste 2
5.Mova disco 1 para haste 1
Algoritmo para a Torre de Hanoi com 4
Discos
12
6.Mova disco 2 para haste 2
7.Mova disco 1 para haste 2
Algoritmo para a Torre de Hanoi com 4
Discos
13
8.Mova disco 4 para haste 3
9.Mova disco 1 para haste 3
Algoritmo para a Torre de Hanoi com 4
Discos
14
10.Mova disco 2 para haste 1
11.Mova disco 1 para haste 1
Algoritmo para a Torre de Hanoi com 4
Discos
15
12.Mova disco 3 para haste 3
13.Mova disco 1 para haste 2
Algoritmo para a Torre de Hanoi com 4
Discos
16
14.Mova disco 2 para haste 3
15.Mova disco 1 para haste 3
Algoritmo para a Torre de Hanoi com 4
Discos
17
Programação de Computadores
Programação consiste no ato de indicar como ocomputador (hardware) deve trabalhar ou realizarserviços
Quais são os serviços que um computador poderealizar?
Enviar mensagens eletrônicas, armazenar e recuperardados, realizar exames e cirurgias, jogar e muito outrascoisas
Para que o computador consiga realizar de fato estesserviços, deve-se escrever um programa
18
Programas
Programa pode ser definido como uma série deinstruções que indicam como o computador irárealizar os serviços
O programa deve definir a ordem em que asinstruções devem ser executadas pelo computador
Um computador, geralmente, possui muitosprogramas, que podem estar sendo executados aomesmo tempo
Como vimos, programas constituem o grupo desoftwares de um computador
Programa Software
19
Algoritmos X Programas
Algoritmo é abstrato
Independe de máquina e de linguagem deprogramação
Pode ser representado de várias formas
Pode ser feito por uma máquina ou um humano
Programa é uma implementação real doalgoritmo utilizando uma linguagem deprogramação
É executado por um computador
20
Algoritmos X Programas
Atores e computadores
Do mesmo jeito que um ator de cinema precisa do roteiro de um filme para
poder encená-lo, um computador precisa de um programa para poder realizar
algum serviço.
21
Fonte: http://whatisthematrix.warnerbros.com
Roteiro de Matrix
Personagens,papéis
Instruções, falas,a serem executadas pelos atores
22
Fonte: http://whatisthematrix.warnerbros.com
Um roteiro podeser executado mais de uma vez
Um ator pode exercer mais de um papel no mesmo filme, executando asinstruções de cada um deles
Roteiro de Matrix
23
Fonte: http://whatisthematrix.warnerbros.com
Roteiro de Matrix
Além do textoem linguagemnatural (inglês,português, etc.)o roteirista pode usar gravuras...
linguagemgráfica
24
Fonte: http://whatisthematrix.warnerbros.com
Roteiro de Matrix
...o queimportaé que a linguagemusada peloroteiristapossa ser entendida pelos atores
25
Fonte: http://whatisthematrix.warnerbros.com
Roteiro de Matrix
O roteiro definea ordem em queas ações, falas e instruções devemacontecer...
26
As observações sobre roteirosvalem também para programas...
Roteiros e programas
Um programa contém instruções a serem executadaspor um computadorQuando solicitado, um computador executa asinstruções de um dado programa
O computador executa o programa
Um programa pode ser executado mais de uma vezUm programa pode se comportar de maneira diferentenas várias execuções...
dependendo do comportamento dos usuários, outrosprogramas, hardware, etc.
27
Roteiros e programas
Um computador pode executar vários programas aomesmo tempoCópias de um mesmo programa podem serexecutadas em vários computadores ao mesmotempoPara executar um programa, o computador tem queter uma cópia do programa
O programa tem que ser instalado ou carregado nocomputador
Um programa define a ordem de execução das suasinstruções pelo computador
28
Roteiros e programas
Mas, na verdade, um roteiro pode ser visto como vários programas, um para cada personagem, deixando claro como os personagens devem interagir.
As observações sobre roteirosvalem também para programas...
29
Filmes e sistemas
Do mesmo jeito que a encenação de um roteiro por vários atores “gera” um filme,a execução de um ou mais programas que
interagem constitui, junto com o hardware associado, um sistema computacional.
Sistema = Programas em execução, interagindo + Hardware
30
Linguagens de Programação
Os programas têm que ser escritos em umalinguagem de programação:
uma linguagem que pode ser entendida pelo computador
31
uma linguagem que pode ser traduzida para a linguagem
entendida pelo computador
1001001010001110
a = 10;a = a + 1; ?
1001001010001110
Sintaxe e Semântica
Uma linguagem de programação define as palavras esímbolos que se pode usar para escrever um programa
Uma linguagem de programação emprega um conjuntode regras (sintaxe) que estabelece como palavras esímbolos podem ser agrupados de maneira a formarinstruções válidas de um programa
A semântica de uma instrução define o significadodesta instrução no programa
Um programa que é sintaticamente correto não énecessariamente logicamente (semanticamente)correto
32
Níveis de Abstração de Linguagens
Linguagens de programação variam de acordo com oseu nível de abstração
↑ conhecimento da máquina onde programa será executado↓nível de abstração
↓ conhecimento da máquina onde programa será executado↑nível de abstração
Linguagens podem ser classificadas em 4 níveis:
Linguagem de máquina
Linguagem de montagem (assembly)
Linguagem de alto nível (Java, C, Pascal, C++, etc)
Linguagem de 4ª geração (PL/SQL, NATURAL, MATLAB, etc)
33
Níveis de Abstração de Linguagens
Cada tipo de CPU tem sua linguagem de máquinaespecífica
Instruções codificadas em binário
Dependente da máquina
Linguagem assembly é dependente da máquina,porém utiliza palavras reservadas para codificarinstruções (mnemônicos)
Outros níveis são independentes de máquina efacilitam leitura e escrita dos programas por parte doser humano
Complexidade atual de programas exigem cada vez mais oemprego destas linguagens
34
Como o computador entende um
programa?
Cada tipo de CPU executa apenas uma linguagem demáquina particular
Deve-se traduzir um programa para a linguagem demáquina
Um compilador é um programa que traduz umprograma escrito (código fonte) em uma determinadalinguagem de programação para outra linguagem(linguagem destino)
Se a linguagem destino for a de máquina, o programa pode,depois de compilado, ser executado
Um interpretador é um programa que traduz instruçãopor instrução de um programa em linguagem demáquina e imediatamente executa a instrução 35
Compilação x Interpretação
36
Compilação
a = 10;a = a + 1; Compilador
1001001010001110
Código- fonte Código de máquina
a = 10;a = a + 1;
Interpretador10010010
Código- fonteCódigo de máquina
10001110
Interpretação
Compilação x Interpretação
Existem vários exemplos tanto de linguagensinterpretadas como de linguagens compiladas
A linguagem C é um exemplo de linguagem compilada
Java é uma linguagem de programação que utiliza umprocesso híbrido de tradução
O compilador Java traduz o código-fonte em um formatointermediário independente de máquina chamado bytecode
Interpretador Java específico da máquina onde irá rodar oprograma então traduz os bytecodes para linguagem demáquina e executa o código
37
Resumindo...
Conceitos Básicos de Programação
Algoritmos
Programa
Linguagens de Programação
Compilação x Interpretação
38
Introdução à Programação
Introdução a Linguagem C
Construções Básicas
2
Programa em C
#include <stdio.h>
int main ( ) {
float celsius ;float farenheit ;celsius = 30;farenheit = 9.0/5 *celsius + 32;printf (“30 graus celsius = %f graus farenheit”,farenheit);return 0;
}
#include
floatfloat
int mainPalavras
Reservadas
E ainda expressões...
celsiusfarenheit
printf
Identificadores criados pelo programador
Identificadores criados por terceiros (chamadas
de funções)
3
Tópicos da Aula
Hoje aprenderemos a escrever um programa em C,para isto veremos
Características da linguagemEstrutura de um programaCiclo de construção de um programa em CEstruturas básicas de uma linguagem de programação
Identificadores,Variáveis,Tipos de dados, Atribuição
Conceito de funções
Depois escreveremos um programa em um ambientede programação
Apresentação de um ambiente de programação
Executando um programa
4
Linguagem C - Características
Linguagem de programação de finalidadegeral criada por Dennis Ritchie em 1972
Criada para desenvolver o sistema operacionalUnixPadronizada em 1989 pela ANSITornou-se muito popular
Ela faz parte das linguagens denominadasimperativas
Ações que o computador deve executar sãoespecificadas como comandos que alteram oestado da memória
5
Linguagem C - Características
Combina o alto nível com o baixo nível,permitindo a manipulação direta de bits, bytese endereços de memória
Possui fluxos de controle e estruturas dedados presentes na maioria das linguagensimperativas
Agrupamento de comandosTomadas de decisões (if-else)Laços para permitir a repetição de comandos
6
Linguagem C - Características
Possui apenas 32 palavras-chaves(reservadas)Permite economia de expressão e geracódigos reduzidosPossibilita alocação dinâmica de memóriaPermite estruturar o software em módulos,arquivos fontes, bibliotecas
7
Linguagem C - Críticas
Dá-se muita liberdade ao programadorProgramas ininteligíveis, acesso direto àmemóriaNão há verificação de tipos e nem de limitesde arrays (veremos depois)
Simplifica o projeto do compilador CMensagens de erro muito vagas (limitação docompilador )
8
Estrutura de um Programa
Em C, a construção fundamental é a função:Um programa é constituído de uma ou mais funções
Uma destas funções deve ser a função main
O programa inicia sua execução na função main
Mas, o que é uma função?
É um conjunto de instruções para realizar uma ou mais tarefas que são agrupadas em uma mesma
unidade e que pode ser referenciada por um nome único
9
Estrutura de um Programa
Dentro de uma função pode haver:Declarações, expressões, chamadas de outras funções,comandos, etc
Uma função em C pode retornar algum valor, assim
como acontece com funções matemáticas
Inteiro, real, caractere, etc
Porém, uma função não precisa necessariamente
retornar um valor
Quando não retorna um valor, dizemos que a função é do
tipo void
10
Estrutura de um Programa
função 1
int main ()
{
}
Comandos,
declarações, chamada
de funções, etc
função 2
função n
return 0;
.
.
.
.
.
.
11
Exemplo de um Programa em C
#include <stdio.h>
int main()
{
int resultado;
resultado = 6 + 7;
printf(“%d”,resultado);
return 0 ;
} Chamada de função
Expressão aritmética
Declaração de variavel
Comando
12
Estrutura de uma Função
int multiplicacao (int p1, int p2)
{
int produto;
produto = p1 * p2;
return produto;
}
Assinatura da função
Corpo da
função
Uma função deve conter:Uma assinatura
Um corpo
13
Estrutura de uma Função
int multiplicacao (int p1, int p2)
{
int produto;
produto = p1 * p2;
return produto;
}
Lista de parâmetros
Assinatura de uma função deve informar:Tipo de valor retornado (se for o caso)
Nome
Lista de parâmetros formais (se houver)
Nome do parâmetro e tipo do parâmetro
Tipo retornado Nome
Parênteses
obrigatórios
14
Estrutura de uma Função
int multiplicacao (int p1, int p2)
{
int produto;
produto = p1 * p2;
return produto;
}
Corpo da
função
dentro das
chaves { }
Instruções devem ser separadas
por ponto e vírgula (;)
Corpo de uma função contém:Instruções
Declarações, comandos, expressões, etc
O comando return, caso o tipo de retorno seja diferente de
void
15
Funções de Bibliotecas
A linguagem C oferece um conjunto de funções jádefinidas que são organizadas em bibliotecas
Programador pode utilizar (chamar) estas funções no programaReduzem o tempo de desenvolvimento do programa
Algumas das funções oferecidas permitem:realizar operações de E/Smanipulação de caracteres (strings)aplicações matemáticas, etc.
16
Funções de Bibliotecas
Informações sobre as funções de bibliotecas sãoencontradas em vários arquivos
header files ou arquivos com extensão .h
Para usar estas bibliotecas, o programa deve indicar osnomes dos arquivos que as contêm
Estas bibliotecas são adicionadas ao programa usandoa diretiva de pré-processamento # include
Por exemplo: # include < stdio.h >Não possui ponto_e_vírgula ( ; )stdio.h é uma biblioteca que contém funções deentrada/saída, tal como a função printf que permitemostrar alguma mensagem no monitor
17
Outro Exemplo de Programa em C
#include <stdio.h>
int multiplicacao (int p1, int p2)
{
int produto;
produto = p1 * p2;
return produto;
}
int main ( )
{
int resultado;
resultado = multiplicacao(6,7);
printf(“6 vezes 7 eh %d”,resultado);return 0 ;
}
Inclui a biblioteca stdio
Chama função da biblioteca stdio
Chama a função multiplicacao
Argumentos da
função
18
Diretivas de Pré-Processamento
O pré-processador é um programa que examina oprograma fonte em C e executa certas modificaçõescom base em instruções chamadas de diretivas
Exemplos: include, define, etc
Uma diretiva deve vir precedida de #
Deve ser escrita em uma única linhaSe passar de uma linha deve-se usar a barra invertida (\) aofinal da linha e contiunuar na seguinte
Diretivas não fazem parte da linguagem CServem para auxiliar o desenvolvimento do programa fonte
19
Exemplo da Diretiva include
#include <stdio.h>
int multiplicacao (int p1, int p2)
{
int produto;
produto = p1 * p2;
return produto;
}
int main ( )
{
int resultado;
resultado = multiplicacao(6,7);
printf(“6 vezes 7 eh %d”,resultado);return 0 ;
}
Inclui a biblioteca stdio
Chama função da biblioteca stdio
20
Variáveis
Programas manipulam dados (valores) eesses dados são armazenados em variáveis
Uma variável é uma posição na memóriareferenciada por um identificador (nome)Uma variável deve ser declarada informandoo tipo de dado que ela armazenará e o nomedela
int total;
int count, temp, result;
Muitas variáveis podem ser criadas em uma declaração
tipo nome
21
Variáveis
Uma declaração de variável instrui ocompilador:
a reservar um espaço de memória suficiente paraarmazenar o tipo de dado declaradoo nome ao qual iremos referenciar esta posiçãode memória
Só após a declaração da variável, é que estapode ser referenciada (utilizada)Quando uma variável é referenciada noprograma, o valor armazenado nela éutilizado
22
Variáveis
Onde se declara variáveis?No corpo de uma função (variável local)
Recomenda-se que as declarações devariáveis sejam as primeiras instruções dafunção
Na lista de parâmetros de funçõesParâmetros formais
Fora das funções (variável global)
23
Declaração de Variáveis
#include <stdio.h>
int resultado;
int multiplicacao (int p1, int p2)
{
int produto;
produto = p1 * p2;
return produto;
}
int main () {
resultado = multiplicacao(6,7);
printf(“6 vezes 7 eh %d”,resultado);return 0 ;
}
Declaração de variáveis nos
parâmetros formais
Declaração de variável local
Declaração de
variável global
24
Atribuição
Um comando de atribuição modifica o valorarmazenado na variávelO operador de atribuição é o sinal de =
total = 55;
total = 65;
Variável total armazena
valor 55
Valor 65 sobrescreve o
valor armazenado antes
Só se deve atribuir a uma variável valores compatíveis com o tipo
declarado da variável
int total;
25
Inicialização de Variáveis
Uma variável pode ser inicializada com o comandode atribuição na hora de sua declaração
int total = 55; Inicializa total com valor
55
Declara variável total do tipo int
Em C, variáveis locais não são inicializadas automaticamente
26
Constantes
Uma constante é um identificador semelhante auma variável, exceto pelo fato de só poderarmazenar o mesmo valor durante toda suaexistênciaUma constante é declarada usando a palavrareservada const
Deve-se inicializar a constante no ato da suadeclaração
const float PI = 3.1416;
PI = 3.141618; Esse comando gera um
erro de compilação
Não se pode mudar o valor de uma constante
27
Constantes
São úteis para dar um significado maiscompreensível a determinados valores
Exemplo : PI é mais compreensível que o valor 3,1416
Facilitam a manutenção do programaCaso uma alteração no programa seja necessária queacarrete uma mudança no valor da constante e estaconstante seja referenciada em vários lugares do programa,só precisamos alterar o programa em um lugar
Explicitam formalmente que um determinado valornão pode ser alterado
Evitam erros de outros programadores
28
Constantes
É comum utilizar-se também a diretiva de pré-processamento define para definir constantes
#define PI 3.1416
int main() {
float raio = 5;
float area = PI*raio*raio;
float comp = 2*PI*raio;
return 0;
}
int main() {
float raio = 5;
float area = 3.1416*raio*raio;
float comp = 2*3.1416*raio;
return 0;
}
No pré-processamento, ocorre
a substituição
29
Linguagem C - Tipos de Dados
Cada dado possui associado a ele um tipo e podepossuir um qualificador
C possui 5 tipos básicos de dadochar: tipo caractere (tamanho de um byte)int: tipo inteiro (números sem parte decimal)float: tipo ponto flutuante de precisão simplesdouble: tipo ponto flutuante de precisão duplavoid: não possui valor
Mais utilizado para indicar que uma função não retornanenhum valor
Qualificadores: short, long, unsigned, signedPrecedem o tipo na declaração do tipo
Ex: unsigned int valor ;
30
Tipo Tamanho Representatividade
char 1 byte -128 a 127
unsigned char 1 byte 0 a 255
short int 2 bytes -32768 a 32767
unsigned short int 2 bytes 0 a 65535
long int (ou int) emambientes de 32 bits
4 bytes -2147483648 a 2147483647
unsigned long int 4 bytes 0 a 4294967295
Linguagem C - Tipos de Dados
O tipo de dado define o tamanho do dado e a formade armazenamento
Valores Inteiros e suas Representatividades
31
Tipo Tamanho Representatividade
float 4 bytes 3.4 X10-38 a 3.4 X1038
double 8 bytes 1.7 X 10-308 a 1.7X10308
long double 10 bytes 3.4 X 10-4932 a 3.4X104932
Valores Reais e suas Representatividades
Linguagem C - Tipos de Dados
32
Tipos de Dados Numéricos
Números com e sem sinalC permite que o programador defina se umavariável de tipo numérico deva ou não reservar obit de sinal (números negativos)Notação
signed tipo
unsigned tipo
Se nenhum modificador for indicado, o compiladorC reservará o bit de sinal
33
Tipo de Dados Caractere
Representado pelo tipo char
„a‟,‟b‟, „1‟, „\n‟ etcinternamente representa um código da tabelaASCIIASCII: na verdade aceita até 255 caracteres(unsigned char)
char letra = „A‟; char letra = 65;
Instrução equivalente
34
Identificadores
Identificadores são palavras que oprogramador utiliza em programasConsiste de um ou mais caracteres.
o primeiro caractere deve ser letra ou "_”demais são uma combinação de letras, números e"_"Identificadores não podem começar com umdígito
Exemplo de identificadores válidos: _a, a3_,bom_diaExemplo de identificadores inválidos: 2a, a-b, a_ b
C é “case-sensitive”Os identificadores casa e CASA são diferentes
35
Identificadores
Identificadores podem ser:Nomes que o programador escolheu
Exemplo: nome de uma variável, função, constante, etc
Nomes que terceiros escolheramExemplo: nome de uma função de uma bibliotecautilizada
Palavras reservadas da linguagemNão podem ser usadas de outra formaExemplo: main, const, int, etc
36
Identificadores em C
#include <stdio.h>
int main ( ) {
float celsius ;float farenheit ;celsius = 30;farenheit = 9.0/5 *celsius + 32;printf (“30 graus celsius = %f graus farenheit”,farenheit);return 0;
}
#include
floatfloat
int mainPalavras
Reservadas
E ainda expressões...
celsiusfarenheit
printf
Identificadores criados pelo programador
Identificadores criados por terceiros (chamadas
de funções)
37
Executando de um Programa em C
Escrever o programa em um arquivo texto(código fonte)
Salvar o arquivo com a extensão .c
Compilar o programa fonte para gerar ocódigo executável (*.exe)
Um programa em C pode ser composto de várioscódigos fontes (vários arquivos .c)É comum a geração de um código objeto (*.obj ou*.o) para cada código fonte e a posterior geraçãodo código executável (linkedição)
38
Construção de Programas em C
EditorCodigo,
Palavras reservadas
Programafonte
Edição
ProgramaFonte
Compilador ProgramaObjeto
Compilação
ProgramasObjeto
ProgramaExecutável
Link-Edição
Adição /Localização de códigos objetos das bibliotecas
ProgramaFonte
Pré-processador
ProgramaFonte
ModificadoPré-processamento
39
Ambiente de Programação
Para acelerar o desenvolvimento de programas, écomum utilizar ambientes de programação ou IDEs(Integrated Development Environment)
Integra várias ferramentas em um único ambienteEditores de textoCompiladoresBibliotecasE muito mais ...
CodeBlocks, DevC++, Visual Studio, Eclipse etc
39
40
Resumindo ...
Características da linguagemEstrutura de um programaCiclo de construção de um programa em CEstruturas básicas de uma linguagem deprogramação
Identificadores,Variáveis,Tipos de dados, Atribuição
Conceito de funções
Introdução à Programação
Operadores, Expressões
Aritméticas e Entrada/Saída de
Dados
2
Programa em C
#include <stdio.h>
int main ( ) {
float celsius ;float farenheit ;celsius = 30;farenheit = 9.0/5 *celsius + 32;printf (“30 graus celsius = %f graus farenheit”,farenheit);
}
#include
floatfloat
mainPalavras
Reservadas
E ainda expressões
aritméticas...
celsiusfarenheit
printf
Identificadores criados pelo programador
Identificadores criados por terceiros (chamadas
de funções)
3
Tópicos da Aula
Hoje aprenderemos a escrever um programa em C quepode realizar cálculos
Conceito de expressãoTipos de Operadores em COperador de atribuiçãoOperadores aritméticos
Operadores especiais
Depois aprenderemos como utilizar funções deentrada/saída para escrever um programa
Funções de entrada
Funções de saída
4
Expressões
Uma expressão é uma combinação de um ou maisoperadores e operandos que geralmente realizaum cálculoA avaliação ou cálculo da expressão se fazobedecendo regras de associação e precedênciaestabelecidas na linguagem
O valor calculado pode não ser necessariamente umnúmero
Pode ser um caractere, cadeia de caracteres, etc
int total = 3 + 4/2 ;Expressão é avaliada e
o resultado é atribuído a
total que armazena
agora o valor 5Divisão (/ ) tem precedência
sobre soma (+)
5
Operadores em C
Categorias de operadores em CAtribuiçãoAritméticosEspeciaisRelacionaisLógicos
Hoje veremos estes 3 tipos de
operadores
6
Operador de Atribuição
Operador de AtribuiçãoPode ser usado em qualquer expressão válida emCRepresentado por =Forma geral:
<nome_da_variável> = <expressão> ;Ex.: x = 5 ;
Ação é executada da direita para a esquerda
5
x 5
7
Operador de Atribuição
Atribuição (Cont.)É usado para atribuir valores às variáveisNão é igual ao operador = de matemática
5 = a não faz sentido em C!
Valor da expressão é armazenado fisicamenteem <nome_da_variável>Múltiplas atribuições
Ex: x = y = z = 0
xyz0 0 0 0
8
Operadores Aritméticos
Operadores aritméticos unáriosUm só operandooperador operando
Sinal Ação Precedência- Troca de sinal 1ª
Ex.: -(a)
++ Incremento de 1 1ª
-- Decremento de 1 1ª
9
Operadores Aritméticos
Operadores aritméticos bináriosDois operandos
operando operador operando
Sinal Ação Precedência+ Adição 3ª- Subtração 3ª* Multiplicação 2ª/ Divisão 2ª
% Resto da Divisão 2ª(só para inteiros)
Operadores de incremento e decremento sãooperadores unários (usam um só operando)
O operador de incremento (++) soma 1 ao seuoperando
O operador de decremento (--) subtrai 1 de seuoperando
A instrução
contador++;
é funcionalmente equivalente a
contador = contador + 1;
Operadores de Incremento e
Decremento
10
Estes operadores podem ser empregados deforma pós-fixada ou pré-fixada
contador++; ou ++ contador;
Quando isolados têm comportamentosequivalentes
Quando fazem parte de expressões
maiores, eles podem ter comportamentosdiferentes
Operadores de Incremento e
Decremento
11
12
Operadores de Incremento e
Decremento
Pré-fixado : ++a ou --a
Incrementa (decrementa) de 1 o valor de a. Seaparece em uma expressão, o valor éincrementado (decrementado) antes do cálculo daexpressão
Pré: int soma = ++a + b
+ =
a b soma
5 2 86
13
Operadores de Incremento e
Decremento
Pós-fixado: a++ ou a--
Incrementa (decrementa) de 1 o valor de a. Seaparece em uma expressão, o valor éincrementado (decrementado) após o cálculo daexpressão
Pós: int soma = a++ + b
+ =ab soma
52 7
6
( )
Devem ser utilizadas com cuidado emexpressões maiores!
Operadores de Incremento e
Decremento
14
int contador = 3;
contador++;
++contador;
int valor = contador++;
valor = ++ contador;
contador agora armazena 4
contador agora armazena 5
valor agora armazena 5 e
depois contador é
incrementado para 6
contador é incrementado
para 7 e agora valor armazena
7
1515
Divisão e Resto da Divisão
Se ambos operandos da expressão aritméticaforem valores inteiros, o resultado será uminteiro (a parte decimal será descartada)Portanto
14/3 4
8/12 0
14%3 2
8%12 8
16
Operadores Aritméticos de Atribuição
É comum fazermos algum tipo de operação com umavariável e depois armazenar o valor da operação naprópria variável
Operadores aritméticos de atribuição facilitam codificaçãode expressões do tipo a = a op bForma geral
variavel op = expressão
x += 1; x = x + 1;
x *= k; x = x * k;
x -= 2; x = x - 2;
x /= 3; x = x / 3;
x %= 3; x = x % 3;
1717
Expressões Aritméticas
Uma expressão aritmética computaresultados numéricos e utiliza operadoresaritméticos combinados com operandosnuméricos
Variáveis, constantes, funções numéricasOrdem de precedência
Operadores unários (- , -- , ++ ) e FunçõesMultiplicação ( *), Divisão ( / ) e Módulo (% )Adição ( + ) e Subtração ( - )
Comandos Equivalentesa = a + 1; a += 1 ; a++ ; ++a ;
18
Operadores Aritméticos
int a , r ;
double b , c ;
a = 3.5 ;
b = a / 2.0 ;
c = 1/2 + b ;
r = 10 % a ;
Quais serão os valores das variáveis declaradas após a avaliação das expressões abaixo?
a=3 b=1.5 c=1.5 e r=1
Atribuição de Expressões aritméticas
Numa atribuição, a expressão aritmética éavaliada primeiro, para depois se atribuir oresultado da expressão à variável
Primeiro, a expressão do lado direito
do operador = é avaliado
Depois, o resultado é armazenado na
variável
answer = sum / 4 + MAX * lowest;
14 3 2
19
O lado direito e esquerdo de um comando deatribuição podem conter a mesma variável
Primeiro, 1 é adicionado aovalor original de contador
Depois o resultado é armazenado em contador
(sobrescrevendo o seu valor original)
contador = contador + 1;
Atribuição de Expressões aritméticas
int contador = 3;
4
20
21
Operadores Especiais
O operador & é utilizado para se obter oendereço da memória que a variávelrepresenta
Forma geral&variável
Um endereço de memória é visto como umnúmero inteiro sem sinal
22
Conversão de Tipos
Existem conversões automáticas de valores em umaavaliação de uma expressão quando operandospossuem tipos diferentes
Operando de tipo de menor tamanho é convertidoautomaticamente para o tipo de maior tamanho
Conversão é feita em área temporária da memória antes daavaliação da expressãoResultado é novamente convertido para o tipo da variável aesquerda da atribuição
int a = 3/2.0 + 0.5;
1. O inteiro 3 é convertido para real
2. Expressão é avaliada como 2.0,
3. Valor é convertido para um inteiro e atribuído a variável
Valor de a é 2
23
Operadores Especiais (Cast)
Algumas vezes a conversão automática dá resultadosnão desejadosDevemos então usar o operador de cast
Forma geral(tipo desejado) variável ou (tipo desejado) (expressão)Armazenamento de um valor real em um tipo de dado inteirogera erro ou perde-se precisão
int a = 3/2 + 0.5;
printf("a = %d",a); int a = ((float)3)/2 +0.5;
printf("a = %d",a);
a = 1
Usando cast
a = 2
24
Entrada de Dados
A função scanf
Usada para a entrada formatada de dadosPara cadeia de caracteres, a leitura é feita até oprimeiro espaço em branco, ou o return, ou o tab.Está definida na biblioteca “stdio.h”
Forma Geral: Tem duas partes:scanf (“expressão de controle”, lista de argumentos)
Expressão de controleCódigos de formatação, precedidos por %
25
Entrada de Dados
Códigos de Formatação
Código Função
%c ler um único caractere
%d ler um número inteiro
%f %e %g ler um número real (tipo float)
%lf %le %lg ler um número real (tipo double)
%s ler uma cadeia de caracteres
%u ler um inteiro sem sinal
%l ler um inteiro longo
26
Entrada de Dados
Lista de ArgumentosCada código de formatação deve corresponder auma variável de entrada, que deve serrepresentada com o operador de endereço
Operador de EndereçoUtilizado para permitir que o dado lido dodispositivo de entrada seja armazenado navariável correspondente. Ele retorna o endereçoda variável.
int a ;&a endereço da variável ascanf ( “ % d ” , &a ) ;
27
Entrada de Dados
Exemplo:
int main() {
char a, b, c ;
int n ; double x ;
scanf (“%c%c%c%d%lf ”,&a,&b,&c,&n,&x);
}
28
Entrada de Dados
#include “stdio.h“int main ( ) /* ler um valor numérico */{ float a;
scanf(“%f”,&a);.....
}
15.2
15.2a
29
Saída de Dados
A Função printfPermite a impressão formatada de números ecadeias de caracteres
Forma Geralprintf(“estruturas de controle”, lista de parâmetros)
Estruturas de ControleCaracteres especiaisCódigos de formatação precedidos por %
30
Saída de Dados
Formato Significado%c caracter%d inteiro %u inteiro sem sinal%e notação científica com e (7.12300e+00)%E notação científica com E (7.12300E+00)%f ponto flutuante decimal (7.12300)%g escolhe %e ou %f ,o menor dos 2 formatos%G escolhe %E ou %f ,o menor dos 2 formatos%s cadeia de caracteres%% imprime o caracter ‘%’
31
Exemplo E/S de Dados
Escreva um programa em C para ler 2 valores para
as variáveis A e B, efetuar a troca dos valores de
forma que a variável A passe a possuir o valor da
variável B e que a variável B passe a possuir o
valor da variável A. Apresentar os valores
trocados.
32
Exemplo E/S de Dados
#include “stdio.h”
int main( ){
int a , b, aux;
printf (“\nTroca de valores entre variáveis\n”);
printf (“\nEntre com o valor de A: ” );
scanf (“%d”, &a );
printf (“\nEntre com o valor de B: ”) ;
scanf (“%d”, &b );
aux = a ;
a = b ;
b = aux ;
printf (“A variável A agora vale: %d”, a ) ;
printf (“ \n”) ;
printf ( “A variável B agora vale: %d”, b ) ;
}
33
Resumindo ...
Conceito de expressãoTipos de Operadores em COperador de atribuiçãoOperadores aritméticos
Operadores especiaisEntrada/Saída
Funções de entrada
Funções de saída
Introdução à Programação
Expressões Booleanas e Comandos Condicionais
2
Comandos CondicionaisMisture os ingredientes
Unte forma com manteiga
Despeje a mistura na forma
Tem coco ralado?
Despeje coco na mistura
Deixe a forma no forno
Sim
Comandos Condicionais
Algoritmo para preparação de bolo
Instrução é executada se
uma determinada
condição for verdadeira
33
Tópicos da Aula
Hoje vamos acrescentar comportamentos maiscomplexos a programas
Tomada de decisão e Mudança de fluxo de controle
Expressões booleanas (lógicas)
Comandos Condicionais
if-else
switch
Operador condicional
Instruções de Controle
Toda linguagem de programação precisaoferecer pelo menos três formas básicas decontrole:
executar uma sequência de instruçõesrealizar testes para decidir entre açõesalternativasrepetir uma sequência de instruções
Hoje, aprenderemos a realizar testes para decidir quais instruções executar
4
Modificando Fluxo de Controle
A ordem de execução de um programa édenominado fluxo de controleExceto quando especificado de outra forma, a ordemde execução é linear, isto é uma instrução após aoutra em seqüenciaAlguns comandos em programação nos permitem:
Decidir se a execução de uma instrução deve ounão ser feita
Útil para que certas instruções só sejam executadassob determinadas condiçõesEsta tomada de decisão é baseada em expressõesbooleanas
5
Expressão Booleana
O resultado da avaliação de uma expressãobooleana é ou verdadeiro ou falso
Em C, NÃO existe o tipo de dado booleanVerdadeiro é representado como 1Falso é representado como 0
Uma expressão booleana é composta deoperandos booleanos (lógicos) e operadoresrelacionais e/ou lógicos
6
7
Operador Ação< menor que
> maior que
<= menor ou igual que
>= maior ou igual que
== igual a
!= diferente de
Resultado de Comparação
Falso ou Verdadeiro
4 < 5 é verdadeiro ( valor 1)
3 >= 10 é falso (valor 0)
Operadores Relacionais
São usados para fazer comparações
8
Operadores Lógicos (Booleanos)
Operador Ação&& E
|| Ou
! Negação
Resultado da Avaliaçãoint a , b ; int c = 23 ;int d = 27 ;a = ( c < 20 ) || ( d > c ) ; b = (c < 20 ) && ( d< c ) ;
São usados para combinar comparaçõesOperam sobre valores booleanos (0 ou 1)
Qual será o valor de a e b?
a = 1
b = 0
Expressões Booleanas
Operadores lógicos e expressões:x && y
x || y
!x
Operadores && e || são ditos short-circuitedOperandos da direita só são avaliados, senecessárioExistem os operadores bit a bit & e I
x e y são expressões booleanas
As expressões resultantessão booleanas, gerando
verdadeiro (1) ou falso (0)como resultado
da avaliação 9
Tabela Verdade
Uma tabela verdade contém todas ascombinações verdadeiro-falso de umaexpressão booleana
10
a b a && b a || b !a
verdadeiro verdadeiro verdadeiro verdadeiro falso
verdadeiro falso falso verdadeiro falso
falso verdadeiro falso verdadeiro verdadeiro
falso falso falso falso verdadeiro
11
Expressões Booleanas
Exemplos3 < 4 && 5 > 2 ! (3 > 7)
v v
v
5 < 4 || 7 > 2 ! (7 >= 10)
f v
v
f
v
f
v
Expressões Booleanas
{ ...
int b, c;
b = 1;
c = !b;
c = !(1 || b) && c;
b = c || !(!b);
...
}
Parênteses são usados para
evitar ambigüidades
Qual o valor de b neste
ponto?12
1 (verdadeiro)
int b, c;
b = 1 || 0;
c = 1 && b;
b = b == c;
Qual o valorde b aqui?
131 (verdadeiro)
Expressões Booleanas
Comandos Condicionais
Um comando condicional nos permiteescolher qual deve ser a próxima instruçãoexecutada em um programaA execução de uma determinada instruçãodepende de uma condição (expressãobooleana)A linguagem C oferece 3 tipos de comandoscondicionais:
if – elseswitchcomando ternário
14
O comando if-else
if (expressaoBooleana) {
comandos
} else {
outros comandos
}
Se a avaliação de expressaoBooleanaretornar verdadeiro, comandos são
executados , caso contrário, executa-se outros comandos
15
16
Exemplo do if-else#include <stdio.h>
int main ( )
{ float n1, n2, n3, m;
printf (“\nEntre com 3 notas ” ) ;
scanf (“%f %f %f”, &n1, &n2, &n3);
m = (n1 + n2 + n3 ) / 3 ;
if (m >= 7.0) {
printf (“\n Aluno aprovado. ”) ;
printf (“ Média igual a %f “ , m) ;
}else {
printf (“\n Aluno reprovado. ”);
printf (“ Média igual a %f “ , m) ;
}
return 0;
}
Variações do comando if-else
if (expressaoBooleana) {
comandos
}
if (expressaoBooleana)
comando;
if (expressaoBooleana)
comando;
else outroComando;
Se a avaliação daexpressãoretornar falso,não executa-se nada
O uso do bloco sóé necessário casoqueira-se executarmais de um comando
17
18
Exemplo – if sem else
#include <stdio.h>
int main ( )
{ int resposta ;
printf (“\n Qual o valor de 10 + 14? ”);
scanf (“%d”, &resposta);
if (resposta == 10 + 14)
printf (“\n Resposta correta ! ”);
return 0;
}else não é obrigatório
19
Exemplo – if-else com único comando
#include <stdio.h>
int main ( )
{ int num ;
printf (“\nDigite um número: ”);
scanf (“%d”, &num);
if (num < 0)
printf (“\n Número é negativo ! ”);
else
printf (“\n Número é positivo ! ”);
return 0;
}
Aninhando if-else
if (expressaoBooleana)
if (expressaoBooleana)
comando;
else outroComando;
O comando dentro do if ou elsepode ser outro if
20
if-else aninhado
Num aninhamento, o else é associado ao maisrecente if sem else
21
Exemplo if-else AninhadoExercício: O que está errado neste programa?
#include <stdio.h >
int main ()
{ int temp ;
printf (“\n Digite a temperatura: ” ) ;
scanf (“%d”, &temp) ;
if (temp < 30)
if (temp > 20)
printf (“\n Temperatura agradável ” ) ;
else printf (“\n Temperatura muito quente ” ) ;
return 0 ;
}
22
Exemplo if-else AninhadoExercício: Corrigindo o programa
#include <stdio.h >
int main ()
{ int temp ;
printf (“\n Digite a temperatura: ” ) ;
scanf (“%d”, &temp) ;
if (temp < 30)
if (temp > 20)
printf (“\n Temperatura agradável ” ) ;
else printf (“\n Temperatura muito quente ” ) ;
return 0 ;
}
{
else associado ao if certo
}
Encadeando comandos if-else
if (expressaoBooleana) {
comandos
} else if (expressaoBooleana‟) {
comandos‟
} else {
comandos‟‟
}
23
Tomando Múltiplas Decisões
O comando if-else é útil para a escolha deuma entre duas alternativasQuando mais de duas alternativas sãonecessárias, pode ficar deselegante utilizarvários if-else encadeados
Para estes casos o comando switch pode ser amelhor opção
24
switch(expressao) {
case rotulo1:
Comandos1
break;
case rotulo2:
Comandos2
break;
...
default:
Comandos
}
O Comando switch
Para executar um switch
Avalia-se expressao
Executa-se os comandosdo case cujo rótulo éigual ao valor resultanteda expressão
Executa-se os comandosde default caso o valorresultante não seja igual anenhum rótulo
switch(expressao) {
case rotulo1:
Comandos1
break;
case rotulo2:
Comandos2
break;
...
default:
Comandos
}
Restrições do Comando switch
O tipo de expressao
só pode ser :Inteiro ou caractere
Os rótulos sãoconstantes diferentesExiste no máximo umacláusula default (éopcional)Os tipos dos rótulos têmque ser o mesmo deexpressao
switch(expressao) {
case rotulo1:
Comandos1
break;
case rotulo2:
Comandos2
break;
...
default:
Comandos
}
Variações do Comando switch
Vários rótulos podemestar associados aomesmo comandoOs comandos break
são opcionais:Sem o break aexecução dos comandosde um rótulo continua noscomandos do próximo,até chegar ao final ou aum break
28
Exemplo de switchCalcular a diferença, o produto, o quociente ou a somade dois números, dependendo da operação escolhida eimprimir o resultado.
# include “stdio.h“
int main ()
{
char x;
float a, b ;
float result = 0.0;
printf (“\n Informe os 2 números e a operação ”);
scanf (“%f %f %c”, &a, &b, &x);
29
Exemplo de switch (cont..)
switch (x) {
case „+‟: result = a + b;
break;
case „-‟: result = a - b;
break;
case „*‟: result = a * b;
break;
case „/‟: result = a / b;
break;
default : printf(“\nOperador invalido”);
}
printf (“\nResultado igual a %f ”, result);
return 0 ;
}
30
if ( a > b ) {
maximo = a;
}
else {
maximo = b;
}
condição ? expressão1 : expressão2
maximo = a > b ? a: b;
Operador Condicional - ?
Forma Geral do ?
Substitui construções do tipo:
31
char a = „a‟, b = „b‟ ;/* b tem valor 98*/
int i = 1, j = 2 ;
double x = 7.07 ;
Expressão Valor
i == j ? a - 1 : b + 1
j % 3 == 0 ? i + 4 : x
j > 1 ? j - 1 : j + 1j % 3 != 0 ? i + 4 : x
Exercício: Considere as seguintes declarações
Comando Ternário de Decisão - ?
‘c’
7.07
15
3232
Resumindo ...
Necessidade de Mecanismos de Tomadas deDecisão em um Programa
Mudança de Fluxo de Controle
Expressões Booleanas
Comandos Condicionais em Cif-elseswitchOperador Condicional
Introdução à Programação
Funções e Escopo de Variáveis
Funções em C
2
FunçõesFunções constituem programas em C
33
Tópicos da Aula
Hoje vamos detalhar funções em C
Importância
Escrevendo funções
Comando return
Passagem de argumentos por valor
Execução de uma função
Depois iremos discutir o escopo de variáveis
Conceito de escopo
Diferentes tipos de variáveis
Local, global e estática
Importância de Funções para
Desenvolver Programas
Desenvolvimento de uma solução se torna mais fácil
quando quebramos esta solução em módulos
gerenciáveis
Quando estamos programando, podemos desenvolver
módulos separados, onde cada um é responsável por
uma certa parte da solução
Programação Modular
Em C, um módulo pode representado por uma função
ou um grupo de funções logicamente relacionadas
4
5
Funções em C
Permitem a construção de programas constituídos demódulos independentes
São trechos de programas que podem ser ativados
Pelo programa principal (função main)
Por outra função
Relembrando...
Uma função é um conjunto de instruções para realizar uma ou mais tarefas que são agrupadas em
uma mesma unidade e que pode ser referenciada por um nome único
6
Estrutura de uma Função
int multiplicacao (int p1, int p2)
{
int produto;
produto = p1 * p2;
return produto;
}
Lista de parâmetros
(pode ser vazia)
Tipo retornado Nome
Corpo da
função
7
Omitindo o Tipo Retornado
multiplicacao (int p1, int p2)
{
int produto;
produto = p1 * p2;
return produto;
}
Em C, caso o tipo retornado seja omitido, o compilador assume que a função retorna o
tipo int
8
Omitindo o Tipo Retornado
multiplicacaoReal (float p1, float p2)
{
float produto;
produto = p1 * p2;
return produto;
}Não vai retornar uma
multiplicação de números reais!
Evitar omitir tipo retornado dificulta entendimento
9
Retorno de uma Função
Uma função em C pode retornar algum valor, assim
como acontece com funções matemáticas
Inteiro, real, caractere, etc
Porém, uma função não precisa necessariamente
retornar um valor
Quando não retorna um valor, dizemos que a função é do
tipo void
Funções que Retornam Valores
int segundos(int hora, int min) {return 60 *(min + hora*60);
}
double porcetagem(double val,double tx) { double valor = val*tx/100;return valor;
}
Funções que retornam valores comoresultado usam o comando return
10
Comando return
Uma função que não tem valor para retornar
tem o tipo de retorno void
Neste caso, o uso do comando return é opcional
return expressão
11
Para executar este comando o computador:
avalia expressão, obtendo um valor
devolve este valor como resultado, terminando a
execução da função no qual ele se encontra
void imprimir(int valor) {printf(“%d”,valor);return;
}Pode ser omitido
Considerações sobre Funções
Uma definição de uma função especifica a
seqüência de instruções que serão
executadas (fluxo de controle) quando esta
função for chamada (invocada)
Quando uma função é chamada, o fluxo de
controle do programa pula para a função e
executa o código que está nela
12
Considerações sobre Funções
Quando a função termina de ser executada,
o fluxo de controle do programa volta para a
instrução logo após a chamada da função
Uma chamada a uma função pode ou não
retornar um valor
Depende da definição da função
13
minhaFuncao();
minhaFuncaomain
Programa
Fluxo de Controle de uma Função
14
minhaFuncao outraFuncao
outraFuncao();
Programa
minhaFuncao();
main
Fluxo de Controle de uma Função
15
Parâmetros e argumentos
Os parâmetros são nomes que aparecem na
declaração de uma função
16
Os argumentos são expressões que
aparecem na expressão de invocação da
função
imprimir(10);
void imprimir(int valor)
Parâmetros de uma Função
Quando uma função é chamada por outra, os
argumentos da chamada são copiados para os
parâmetros (formais) presentes no assinatura da
função
17
float media (float num1, float num2)
{
float result = (num1 + num2)/2;
return result;
}
int main() {
float valor = media (30,40);
}
Passagem de Argumentos
C permite a passagem de argumento por valor: o valor da expressão é
avaliado primeiro e depois passado para a função chamada
18
Passagem de Argumento por Valor
void incrementa(int x) {x = x + 1;printf(“%d”,x);
}
int main() {
int y = 1;
printf(“%d”,y);
incrementa(y);
printf(“%d”,y);
...
}
não alterao valor de
y
saída:1
saída:2
saída:1
19
Comunicação de dados entre funções é feita através de passagem
de argumentos
20
Ordem de Definição das Funções
Antes da função main
OU
Depois da função main desde que se declaresua assinatura antes da main
Onde uma função deve ser definida?
21
Definindo a Função Antes da main
#include <stdio.h>
int segundos(int hora, int min) {return 60 *(min + hora*60);
}
int main() {
int minutos,hora, seg ;
printf(“Digite a hora:minutos\n”);
scanf (“%d:%d”,&hora,&minutos) ;
seg = segundos(hora,minutos);
printf(“\n%d:%d tem %d segundos.”,hora,minutos,seg);
return 0 ;
}
Definição antes da main
#include <stdio.h>
int segundos(int hora, int min);
int main() {
int minutos,hora, seg ;
printf(“Digite a hora:minutos\n”);
scanf (“%d:%d”,&hora,&minutos) ;
seg = segundos(hora,minutos);
printf(“\n%d:%d tem %d segundos.”,hora,minutos,seg);
return 0 ;
}
int segundos(int hora, int min) {return 60 *(min + horas*60);
}
22
Definindo a Função Depois da main
Definição depois da main
Deve-se declarar antes a assinatura da função – Modo
alternativoint segundos (int,int)
Escopo de Variáveis
O escopo de uma variável define a área do programa
onde esta variável pode ser referenciada
Variáveis que são declaradas fora das funções
(inclusive da função main), podem ser referenciadas
por todas as funções do programa
São chamadas de variáveis globais
Variáveis que são declaradas dentro de uma função
só podem ser referenciadas dentro desta função
São chamadas de variáveis locais
23
Escopo de Variáveis
Pode existir uma variável local a uma função com
mesmo nome e tipo de uma variável global, neste caso
ao se referir ao nome da variável dentro da função,
estar-se-á acessando a variável local
24
#include <stdio.h>
int numero = 10;
int main(){
int numero = 4;
printf(“%d”,numero);}
Declaração de
variável local
Referência à
variável local
Será impresso o valor 4
25
Variáveis Globais
Podem ser usadas em qualquer parte do
código
Se não inicializadas explicitamente, C
inicializa com valores padrões
0 para tipos numéricos
Existem durante todo o ciclo de vida do
programa (ocupando memória)
26
Variáveis Globais
Normalmente são declaradas no início do
programa ou em arquivos do tipo header (*.h)
São declaradas uma única vez
Deve-se evitar o uso abusivo delas
Pode penalizar o consumo de memória
Pode dificultar a legibilidade do código
27
Uso de Variáveis Globais
#include <stdio.h>
int minutos,hora;
int segundos() {return 60 *(minutos + horas*60);
}
int main() {
int seg ;
printf(“Digite a hora:minutos\n”);
scanf (“%d:%d”,&hora,&minutos) ;
seg = segundos();
printf(“\n%d:%d tem %d segundos.”,hora,minutos,seg);
return 0 ;
}
Todas as funções “enxergam” as
variáveis minutose hora
Comunicação de dados entre funções agora é
feita através de variáveis globais
Variáveis Locais
São declaradas dentro de uma função
Só existem durante a execução da função
Não ocupam a memória durante toda a execução do
programa
Não são inicializadas automaticamente
Só são visíveis dentro da função
Outras funções não podem referenciá-las
Têm a mesma capacidade de armazenamento que as variáveis globais mas
28
Variáveis Locais
Caso uma função declare uma variável local,esta é criada a cada execução da função
29
int funcao( )
{
int a= 100;
a = a + 23;
return a;
}
Sempre retorna 123
Modificador static
Caso a variável local venha com o modificadorstatic, a variável é criada uma única vez
Armazena seu valor em várias execuções da mesmafunção
Evita uso de variáveis globais
30
int funcao( )
{
static int a= 100;
a = a + 23;
return a;
}
Inicializa apenas uma vez
1ª vez que função for chamada retorna 123
2ª vez retorna 146
31
Armazenamento das Variáveis
Código do programa
Variáveis Globais e Estáticas
Memória livre
Pilha de execução de funções
Onde são armazenados na memória os diferentes tipos de variáveis?
Pilha de execução armazena variáveis locais das funções
Quando acaba a execução da
função, espaço ocupado pelas suas
variáveis é liberado
32
Pilha de Execução de Funções
#include <stdio.h>
int segundos(int hora, int min) {int seg;seg = 60 *(min + hora*60);return seg;
}
int main() {
int minutos = 30,hora = 1, seg ;
seg = segundos(hora,minutos);
printf(“\n%d:%d tem %d segundos.”,hora,minutos,seg);
return 0 ;
}
Considere o seguinte código:
33
1 – Início do programa:pilha vazia
2 – Declaração de variáveis: minutos,hora,seg
3 – Chamada da função:cópia do argumento
4 – Declaração da variávellocal: seg
5 – Final da avaliação da expressão
6 – Retorno da função:desempilha
Pilha de Execução de Funções
<mainminutos
hora301
seg -
<main <main30
1-
minutoshoraseg <segundos
min
hora 130
<main301-
minutoshoraseg <segundos
min
hora 130
-seg 4500
<main301-
minutoshoraseg <segundos
min
hora 130
seg
minutoshora
301
seg 4500
<main
34
Macros Semelhantes a Funções
Pré-processador e Macros
Diretiva de Definição com Parâmetros
São chamadas de Macros
Exemplo
define MAX(a,b) ((a) > (b) ? (a):(b))
int main() {
float v = 4.5 ;
float c = MAX(v,3.0) ;
O compilador verá:
int main() {
float v = 4.5 ;
float c = ((v)>(3.0)?(v):(3.0)) ;
35
Pré-processador e Macros
Macros definidas incorretamente
Uso de macros deve ser feito com cautela!
#define DIF(a,b) a - b
int main(){
printf(“%d”,4 * DIF(5,3));
return 0 ;
}
Saída é 17 e não 8
#define PROD(a,b)( a * b )
int main(){
printf(“%d”,PROD(3 + 4,2));
return 0;
}
Saída é 11 e não 14
Macros Semelhantes a Funções
3636
Resumindo ...
Funções
Importância
Escrevendo funções
Comando return
Passagem de argumentos por valor
Execução de uma função
Escopo de variáveis
Conceito de escopo
Diferentes tipos de variáveis
Local, global, estática
Introdução à Programação
Estruturas de Repetição
Repetição de Comandos…
int somatorio(int n) {
int soma = 0;
int i = 0;
soma = soma + i;
i++;
soma = soma + i;
i++;
soma = soma + i;
...
}
Faz esta seqüência de comandos n vezes
n
i
i0
E haja copy&paste!
2
33
Tópicos da Aula
Hoje, aprenderemos a usar estruturas derepetição para programas mais complexos
Necessidade de estruturas de repetição
Apresentação do conceito de laço (loop)
O comando for
O comando while
O comando do-while
Diferenças entre os comandos de repetição
Veremos também, como podemos alterar o
fluxo de laços
Comandos break e continue
44
Necessidade de Estruturas de Repetição
Na resolução de problemas em programação,
freqüentemente, precisamos repetir uma mesma
seqüência de comandos várias vezes
Na maioria dos casos, não sabemos de antemão
quantas vezes a seqüência de comandos será repetida
A linguagem de programação deve fornecer uma
estrutura (comando) que permita a execução repetida
de mesma seqüência de comandos
Evita esforço do programador
Permite que o programador não tenha que saber quantas
vezes o comando será executado
55
Estruturas de Repetição
Permite repetir diversas vezes um comando ou
seqüência de comandos
Cada repetição de um comando ou seqüência de comandos é
denominada de iteraçãoSão geralmente conhecidos como loops(laços)
Da mesma forma que comandos condicionais, são
controladas por expressões booleanas
C oferece 3 tipos de estruturas(comandos) de
repetição:O laço for
O laço while
O laço do-while
O Comando for
for (i = 0; i < valor; i = i+1)
corpo
Executa corpo um número específico de vezes:
valor vezes
Neste exemplo, na primeira execução de corpo, o
valor de i é 0
O valor de i é incrementado após cada execução de
corpo
Variável i deve ser declarada antes de se utilizar o
comando for
Variável de controle
6
A Forma Geral do Comando for
inicialização e incremento podem ser
praticamente quaisquer comandos
condição pode ser qualquer expressão booleana
inicialização geralmente inicializa a variável
de controle do for
incremento geralmente incrementa a variável for
for(inicialização;condição;incremento)
corpo
7
Fluxo de Controle do Laço for
comando
true
condiçãoavaliada
incremento
inicialização
false
8
for ( inicialização ; condição ; incremento )
comando;
Examinando o Comando for
A inicialização
é executada uma só vez
antes do laço começar
O comando é
executado enquantocondição for verdadeira
O incremento é executado ao fim de
cada iteração
9
Cabeçalho do for
Entendendo o Comando for
int somatorio(int n) {
int valor;
int soma = 0;
for (valor = 0; valor <= n; valor++)
soma = soma + valor;
return soma;
}
Variável valor é inicializada com 0
A cada iteração, valor é incrementado em 1
10
Comando será realizado enquanto valor for menor ou igual a n
int somatorio(int n) {
int valor;
int soma = 0;
for (valor = 0; valor <= n; valor++)
soma = soma + valor;
return soma;
}
Entendendo o Comando for
Se n for menor do que0, nãose executa o corpo do for
11
É executado depois do for
Entendendo o Comando for
int somatorio(int n) {
int soma = 0;
int valor;
for (valor = 0; valor <= n; valor++){
soma = soma + valor;
printf(“Soma Parcial:%d\n”,soma);
}
printf(“Soma Total:%d”,soma);
return soma;
}
Corpo do for pode ser composto por bloco de comandos
12
Modificando o Incremento do for
int somatorio(int n) {
int soma = 0;
int valor;
for (valor = n; valor>= 0; valor--){
soma = soma + valor;
printf(“Soma Parcial:%d\n”,soma);
}
printf(“Soma Total:%d”,soma);
return soma;
}
13
valor agora é decrementado
Modificando o Incremento do for
int somatorioPares(int n) {
int soma = 0;
int valor;
for (valor = 0; valor <= n; valor = valor + 2){
soma = soma + valor;
printf(“Soma Parcial:%d\n”,soma);
}
printf(“Soma Total:%d”,soma)
return soma;
}
14
valor agora é incrementado em 2
Pode-se colocar qualquer tipo de expressão na
parte de incremento do comando for
Variações do Comando for
Cada expressão no cabeçalho de um laço for loop
é opcional
Se a inicialização é omitida, nenhuma inicialização é
feita
Se a condição é omitida, a condição é considerada
sempre verdadeira e o laço continua para sempre
(laço infinito)
Se o incremento é omitido, nenhuma operação é
realizada ao final da iteração do laço
15
O Comando for sem Condição, etc.
for(;;valor++)
corpo
16
for(;valor < n; valor++)
corpo
for(;;)
corpo
Repetição infinita: cuidado!
17
Mais Variações do Comando for
Teste condicional não precisa ser baseado na variável
de controle
#include <stdio.h>
#include <conio.h>
int main ( ) {
int i ;
/* atribui um valor inicial a ch*/
char ch = „a‟ ;
for(i = 0; ch != „q‟;i++){
printf (“\nPasso:%d”,i) ;
ch = getche() ;
}
}
condição não é
baseada na
variável de
controle
18
Mais Variações do Comando for
Parte de incremento não precisa incrementar variável
de controle
Comando for pode vir sem corpo
#include <stdio.h>
#include <conio.h>
int main ( ) {
char ch;
for(ch = getche(); ch!=„q‟;ch = getche());
printf (“\nValor q encontrado”) ;
} Incremento
pode ser outro
tipo de
expressão
Não tem corpo
O comando while
Executa corpo várias vezes até que a
avaliação da expressão retorne falso
A condição é avaliada de novo após cadaexecução de corpo
Não executa corpo nenhuma vez, se de
início a avaliação da condição retorna falso
while (condição)
corpo
19
Fluxo de Controle do Laço while
comando
true
condiçãoavaliada
false
20
int somatorio(int n) {
int soma = 0;
int valor = 0;
while ( valor <= n ){
soma = soma + valor;
valor++;
}
return soma;
}
Entendendo o comando while
Se n for negativo, não seexecuta o corpo do while
21
É executado quando o while termina, quando a condição for falsa
int somatorio(int n) {
int soma = 0;
int valor = 0;
while ( valor <= n ){
soma = soma + valor;
valor++;
}
return soma;
}
Entendendo o comando while
Inicialização da variável de controle é feita fora do laço while
22
Incremento da variável de controle é feita no corpo do laço while
int somatorio(int n) {
int soma = 0;
int valor = 0;
while ( valor <= n ){
soma = soma + valor;
}
return soma;
}
Laço Infinito com o Comando while
23
Se valor não é incrementado, este comando será executado infinitas vezes
O Comando for e o Comando while
for(inicialização;condição;incremento)
corpo
inicialização;
while(condição) {
corpo;
incremento;
}
equivale a ...
24
O Comando for e o Comando while
for(;;)
corpo
while(1) {
corpo;
}
equivale a ...
25
do {
corpo
} while(condição)
O Comando do-while
Executa corpo, pelo menos uma vez, até
que a avaliação da condição retorne falso
A condição é avaliada de novo após cadaexecução de corpo
26
true
condição
avaliada
comando
false
Fluxo de Controle do Laço do-while
27
int somatorio(int n) {
int soma = 0;
int valor = n;
do {
soma = soma + valor;
valor--;
} while ( valor >= 0 )
return soma;
}
Entendendo o comando do-while
Se n for negativo, o corpodo do-while é executado pelo menos uma vez
28
É executado quando o do-while termina, quando a condição for falsa
Comportamento alterado: cuidado!
do {
corpo
} while(condição)
Os Comandos do-while e while
corpo;
while(condição)
corpo;
Equivalente a ...
29
3030
Laços Aninhados
Laços podem ser aninhados da mesma forma
que comandos condicionais
O corpo de um laço pode conter outro laço
Para cada iteração do laço externo, o laço
interno é completamente executado
3131
Laços Aninhadosint somatorioDoSomatorio(int n, int vezes) {
int soma = 0, somatorio =0;
int valExt;
for (valExt = 0; valExt < vezes; valExt++ ){
int valInt = 0;
while (valInt <= n) {
soma = soma + valInt;
valInt++;
}
somatorio = somatorio + soma;
}
return somatorio;
} A cada iteração do for,o laço while é executado
3232
Considerações sobre Laços
Os 3 tipos de laços são funcionalmente
equivalentes
Portanto podem ser usados indiscriminadamente
Os laços for e while são executados 0 ou
muitas vezes
O laço do-while é executado 1 ou muitas
vezes
33
O Comando breakForma Geral do comando break
Tem dois usos distintos
Para forçar o término de um laço de repetição (do-while, for
ou while)
Para terminar um case do comando switch
Quando o comando break é encontrado dentro de
um laço de repetição:
instrução é imediatamente finalizada
próxima instrução após a estrutura de repetição é executada
Deve ser usado com cautela
Reduz legibilidade
Pode levar a erros de lógica
break;
O Comando break
int somatorio(int n) {
int soma = 0;
int valor;
for (valor = 0; ; valor++){
soma = soma + valor;
if (valor == n)
break;
printf(“Soma Parcial:%d\n”,soma);
}
printf(“Soma Total:%d”,soma)
return soma;
}
Este comando não será executado quando valor = = n
34
O Comando continue
Termina a execução da iteração atual de umloop (for,while,do-while) e volta ao
começo deste loop
Todos os comandos que seriam executadosapós o continue são descartados
continue
Forma Geral do comando continue
35
36
Comando de Desvio - continuePara os comandos while e do-while, ocontinue causa:
a realização imediata do teste da condição
correspondente
continuidade do processo de repetição dependendo
do resultado do teste
Para o comando for , o continue causa:
incremento da variável de controle do laço de
repetição
execução do teste para verificação da condição
continuidade do processo de repetição dependendo
do resultado do teste
O Comando continue
void imprimeNumerosAteCinco() {
int valor;
for (valor = 0; valor <= 5; valor++){
if (valor == 4)
continue;
printf(“%d “,valor);
}
}
Controle pula para o incremento e este comando não será executado quando valor = = 4
37
A saída desta função será: 0 1 2 3 5
O Comando continue
void imprimeNumerosAteCinco() {
int valor = 0;
while (valor <= 5){
if (valor == 4)
continue;
printf(“%d”,valor);
valor++;
}
}
Controle pula para o teste e função tem execução infinita quando valor = = 4
38
A saída desta função será: 0 1 2 3 ...
laço infinito
3939
Resumindo ...
Estruturas de RepetiçãoNecessidade de estruturas de repetição
Conceito de laço (loop)
Tipos de laço em C
O comando for
O comando while
O comando do-while
Laços Aninhados
Diferenças entre os comandos de repetição
Comandos para alterar o fluxo de laços
break e continue
Introdução à Programação
Recursão
Recursão
decoraçãoSubstantivo feminino. 1.Ato ou efeito de decorar
Recursão
2
decorarVerbo transitivo direto. 1.Guarnecer com adorno(s); dispor formas e cores em; ornamentar, embelezar;2.Realçar, avivar, adornar;
Fonte: Dicionário Aurélio
33
Tópicos da Aula
Hoje, aprenderemos a usar uma técnica deprogramação chamada de recursão
Conceito de Recursão
Definições Recursivas
Casos Base e Geral
Programando Recursivamente
Recursão X Laço
44
Recursão
Uma definição recursiva de um conceito consiste emutilizar o próprio conceito na definição
Ex: fat(n) = n * fat(n-1)
Definições recursivas em linguagem natural não são,geralmente, muito úteis
Contudo, em outras situações, uma definição recursivapode ser a mais apropriada para explicar um conceito
Recursão é uma técnica de programação que podefornecer soluções elegantes para determinadosproblemas
Mas, antes, deve-se aprender a pensar recursivamente!
55
Definições Recursivas: Lista
Considere a seguinte lista de números
24, 88, 40, 37
Podemos definir uma lista de números como:
Uma LISTA é um: número
ou um: número vírgula LISTA
Resumindo: uma LISTA é definida ou como um único número, ou como um número seguido de
uma vírgula seguida de uma LISTA
Utilizamos LISTA para sua própria definição
66
Definições Recursivas: Lista
88, 40, 37
A parte recursiva da definição de LISTA é utilizada diversas vezes, até que se possa
utilizar a parte não recursiva
24
37
,
40, 3788,
3740,
número vírgula LISTA
Parte recursiva da definição de
LISTA
Parte não recursiva da definição de
LISTA
77
Definições Recursivas: Fatorial
Fatorial de um número N (N!), que é inteiro epositivo, é definido como a multiplicação detodos os inteiros compreendidos entre 1 e N(inclusive)
Podemos definir fatorial recursivamente:
0! = 1
N! = N x (N-1)!
Mais uma vez, utilizamos fatorial para sua própria definição
5!
5 * 4!
4 * 3!
3 * 2!
2 * 1!
1 * 0!
1
Definições Recursivas: Fatorial
2
6
24
120
1
8
99
Caso Base e Caso Geral
Toda definição recursiva deve ter uma parterecursiva e outra não recursiva
Se não houver a parte não recursiva, ocaminho recursivo nunca termina
Gera uma recursão infinita
Similar a um laço infinito
Denomina-se de caso base, a parte nãorecursiva da definição, enquanto o caso geralé a parte recursiva
Uma função em C pode chamar ela mesmaFunção recursiva
O código de uma função recursiva deve tratar o caso
base e o caso geral
Cada chamada da função cria novos parâmetros e
variáveis locaisCria-se uma nova instância da função
Como em qualquer chamada de função, assim que a
função termina sua execução, o controle retorna para a
função que a chamou (que neste caso, é outra
instância da mesma função)
Programação Recursiva
1111
Exemplo de Função Recursiva:
Fatorial
int fatorial(int n) {
int resultado;
if (n == 0)
resultado = 1;
else
resultado = n * fatorial(n - 1);
return resultado;
} Caso Geral
Caso Base
1212
Chamando Função Recursiva: Fatorial
int main() {
int fat = fatorial(2);
printf(“Fatorial de 2 é %d”,fat);
return 0;
}
13
1 – Chamada da função:cópia do argumento
4 – Retorno da 3a chamada:cálculo da expressão
Pilha de Execução de Funções
Recursivas
<main-2
-
fat
resultadon <fatorial
<main-2
-
fat
resultadon <fatorial
<fatorial’
resultado
n 1-
<main-2
-
fat
resultadon <fatorial
<fatorial’
resultado
n 1-
<fatorial’’
resultadon 0
1
<main-2
-
fat
resultadon <fatorial
<fatorial’
resultado
n 11
<main-2
2
fat
resultadon <fatorial
<main2fat
2 – Chamada recursiva:cópia do argumento
3 – Chamada recursiva:cálculo da expressão
5 – Retorno da 2a chamada:cálculo da expressão
5 – Retorno da 1a chamada
14
Usando Recursividade para resolver
problemas
Problema: Torre de HanoiDeve-se transportar todos os discos da primeira estaca até
a última obedecendo as seguintes regras:
1. Só pode ser deslocado um disco por vez (o do topo de uma estaca)
2. Em nenhum momento um disco maior pode estar sobre um menor
15
Resolvendo Recursividade o Problema
da Torre de Hanoi
Solução: Torre de Hanoi1. Mover n – 1 discos da estaca Origem para a Temporária2. Mover o disco n da estaca Origem para a Destino3. Mover n – 1 discos da estaca Temporária para a Destino
1616
Torre de Hanoi
void mover(int n, char orig, char temp, char dest) {
if (n == 1)
printf("Mova o disco 1 da estaca %c para a estaca
%c\n",orig,dest);
else {
mover (n-1,orig,dest,temp);
printf("Mova o disco %d da estaca %c para a estaca
%c\n",n,orig,dest);
mover(n-1,temp,orig,dest);
}
}
Caso Geral
Caso Base
1717
Pontos Chave de uma Solução
Recursiva
Definir o problema em termos recursivos
Definir o caso geral
Determinar o caso base
Definir uma solução de modo que a cada
chamada recursiva, podemos nos aproximar do
caso base
1818
Recursão x Laço
Não é porque existe uma solução recursiva, que
sempre devemos usá-la
Soluções iterativas (com laço) são geralmente mais
eficientes
Soluções recursivas geralmente demandam mais poder de
processamento e memória
Porém, soluções utilizando recursão podem ser mais
elegantes e mais compreensíveis que soluções
iterativas equivalentes
Programador deve analisar caso a caso qual é a melhor
técnica a aplicar para a resolução do problema
1919
Resumindo ...
Recursão
Conceito
Exemplos de definições recursivas
Casos Base e Geral
Programando Recursivamente
Recursão X Laço
Introdução à Programação
Armazenamento de Grande Quantidade de Informação –
Usando Vetores
Armazenando Grande Quantidade de
Informação
Como armazenar tanta
informação?
2
Vetores !
33
Tópicos da Aula
Hoje, aprenderemos como armazenar grandequantidade de informação
Necessidade de armazenamento
Utilização de muitas variaveis
Manipulação incremental das informações
Aprenderemos a utilizar vetoresConceito
Criação
Inicialização
Acesso
Limites de um vetor
Passagem de vetores como argumentos
Vetores bidimensionais (matrizes)
44
Necessidade de Armazenamento
Sistemas armazenam informações para que possamposteriormente acessá-las e manipulá-las
Maioria dos sistemas requer o armazenamento degrande quantidade de valores do mesmo tipo
Mesmas operações para manipular estes valores
Ex: processamento de imagens
Milhões de imagens e cada imagem composta de milhõesde pixels
No desenvolvimento de um programa, devemos definirestruturas e mecanismos para armazenar e manipularesta grande quantidade de informação
5
Calculando a Média Aritmética
n
x
m
n
i
i 1
A média aritmética de um conjunto de valores é
dada pela seguinte expressão
66
Como Armazenar Grande Quantidade
de Informações?
Até agora, vimos construções de programaçãoque permitem guardar uma única informaçãode cada vez
Variável e constante
Neste caso, a solução seria criar uma variávelpara cada valor que desejamos armazenar
Não é uma boa solução, porém hoje veremos comopodemos trabalhar com esta alternativa
77
Tentativa com Muitas Variáveis
#include <stdio.h>
int main() {
float numero1, numero2;
float media;
printf(“Digite 2 numeros:\n”);
scanf(“%f %f”, &numero1,&numero2);
media = (numero1 + numero2)/2;
printf(“\nA media eh %f\n”,media);
return 0;
}
2 variáveis para armazenar números
Limitação: Só permite média de 2 números
88
Tentativa com Muitas Variáveis
#include <stdio.h>
int main() {
float numero1, numero2, numero3;
float media;
printf(“Digite 3 numeros:\n”);
scanf(“%f %f %f”, &numero1,&numero2,&numero3);
media = (numero1 + numero2 + numero3)/3;
printf(“\nA media eh %f\n”,media);
return 0;
}Trecho de código depende da quantidade de números
suportados
3 variáveis para armazenar números
Limitação: Só permite média de 3 números
99
Problemas com Uso de Muitas
Variáveis
Dificuldade de lidar com mudança do númerode informações que devem ser armazenados
Acrescentar ou remover variável
Muitas vezes requer modificações em várias linhasde código
#include <stdio.h>
int main() {
int qtdNumeros;
int contador = 0;
float numero;
float media = 0.0;
printf(“Digite quantidade de numeros:\n”);
scanf(“%d”, &qtdNumeros);
while (contador < qtdNumeros) {
scanf(“%f”,&numero);
media = media + numero;
contador++;
}
media = media/qtdNumeros;
printf(“\nA media eh %f\n”,media);
return 0;
}
1010
Outra Estratégia: Manipulação
Incremental da Informação
Variável que guarda a quantidade de números
entrados
Permite média de quantidade variada de números
Cada número entrado é armazenado na variável numero
#include <stdio.h>
int main() {
int qtdNumeros;
int contador = 0;
float numero;
float media = 0.0;
printf(“Digite quantidade de numeros:\n”);
scanf(“%d”, &qtdNumeros);
while (contador < qtdNumeros) {
scanf(“%f”,&numero);
media = media + numero;
contador++;
}
media = media/qtdNumeros;
printf(“\nA media eh %f\n”, media);
return 0;
}
1111
Outra Estratégia: Manipulação
Incremental da Informação
Código independe da quantidadede números que serão utilizados
na média
Contudo perdemos informação sobre cada número digitado!
1212
Problemas com Manipulação
Incremental de Informação
Perda de informação sobre os valoresindividuais que foram armazenados
No exemplo, sabemos apenas qual foi o somatóriodos valores inseridos e não quais valores foraminseridos
Limita a utilização da informação armazenadaNo exemplo, se quiséssemos utilizar os mesmosdados para uma operação diferente (ex:multiplicação), não conseguiríamos
1313
Necessidade de Vetores
Precisamos de alguma estrutura dearmazenamento que:
armazene vários valores de um determinado tipo
permita que os valores sejam acessados de formasimples
9.0 7.5 6.3 8.8 9.8 10.0 Vetores !
Vetores
Vetor ou array é um tipo de dado utilizado para
representar um conjunto de valores
homogêneos utilizando um único nome
Define uma estrutura que armazena valores de
um determinado tipo
Um vetor é declarado usando
tipo nome[tamanho];
No ato da declaração, devemos especificar o
tamanho (dimensão) do vetor
Vetores têm tamanho fixo depois de criados
14
Vetores
0 1 2 3 4 5 6 7 8 9
notas
notas[0]notas[1]...notas[9]
float notas[10];
Índices do vetor
Cada elemento do vetor é referenciado através doíndice do vetor
Índice começa em 0 e vai até tamanho -1
4 9 8 6 3 7 8 2 9 5
Acessando Elementos de Vetores
Um determinado elemento do vetor pode ser
acessado usando o nome do vetor seguido do índice
do elemento entre colchetes ([ ])
A expressão notas[2] se refere ao valor 8 (3º
elemento do array)
16
A expressão notas[2] representa um local para
armazenar um inteiro e pode ser utilizada da mesmaforma que uma variável do tipo inteiro
notas
notas[2]
10 9 8 7
#include <stdio.h>
int main() {
int qtdNumeros,contador = 0;
float numeros[2000];
float media = 0.0;
do{
printf(“Quantidade de numeros? (< 2000):\n”);
scanf(“%d”, &qtdNumeros);
} while (qtdNumeros <= 0 || qtdNumeros > 2000);
while (contador < qtdNumeros) {
scanf(“%f”,&numeros[contador]);
media = media + numeros[contador];
contador++;
}
media = media/qtdNumeros;
printf(“\nA media eh %f\n”,media);
return 0;
} 17
Calculando a Média com Vetores
Vetor que guarda números entrados
Números podem ser acessados
individualmente
18
int v[10];
v 104
144 É reservado um espaço de memória
contínuo
Acessa o primeiro elemento de vv[0]
Acessa o último elemento de vv[9]
Vetores na Memória
Aloca espaço para 10 valores
inteiros, referenciados por v
v [10]Mas: Está errado !
Checando os Limites dos Vetores
Ao utilizar o índice para referenciar um elemento do
vetor, este índice deve permitir o acesso a um
elemento válido ( em um endereço da memória
alocado para o vetor)
Índice deve variar de 0 a tamanho -1
C não avisa quando o limite de um vetor é excedido!
Se o programador transpuser o fim do vetor durante a
operação de atribuição, os valores serão armazenados emoutros dados ou mesmo no código do próprio programa
19
O programador tem a responsabilidade de verificar o limite do vetor!
Checando os Limites dos Vetores
São comuns, erros de programação no uso
de vetores dentro de laços
Deve-se prestar atenção na parte de teste do laço
20
int main() {
int pares[20];
int i,somaPares = 0;
for (i = 0; i <= 20; i++) {
pares[i] = 2 * i ;
somaPares = somaPares + pares[i];
}
...
}Teste deveria ser i < 20
Por causa do teste errado, esta linha gerará um erro
21
Inicializadores de vetores são representados da
seguinte forma: {expressões},onde
expressões representam expressões de tipos
válidos separadas por vírgulas
Vetores podem ser inicializados na declaração
Inicializando Vetores
int v[5] = {5,10,15,20,25} ;
ou simplesmente:
int v[]= {5,10,15,20,25};
Vetores só podem ser inicializados no ato da declaração!
Opções de Inicialização de Vetores
22
No caso de utilizar inicializadores de vetores,note que:
Quando não especificado o tamanho, o compiladoraloca espaço suficiente para armazenar todos osvalores contidos na inicialização
Quando o tamanho for especificado e houver a listade inicialização
Se há menos inicializadores que o tamanhoespecificado, os outros serão zero
Mais inicializadores que o necessário implica emum warning
Quando o vetor não for inicializado, o tamanho deve ser especificado na
declaração !
Passando Vetores como Argumentos
de FunçõesUm vetor pode ser passado como argumentopara uma função
Parâmetro da função deve ser do tipo tipo[]
Ao passar um vetor para uma funçãopodemos modificar o conteúdo deste vetordentro da função
Passa-se na verdade o endereço do vetor namemória (veremos em breve!)Modificar um elemento do vetor ou incluir um novoelemento
Podemos passar também um elemento emparticular de um vetor para uma função
Parâmetro deve ser to tipo tipo
23
#include <stdio.h>
float media(int n, float num[]){
int i;
float s = 0.0;
for(i = 0; i < n; i++)
s = s + num[i] ;
return s/n ;
}
int main(){
float numeros[10] ;
float med;
int i ;
for(i = 0; i < 10; i++)
scanf (“%f”, &numeros[i]) ;
med = media(10, numeros ) ;
...
}24
Passando Vetores como Argumentos
para Funções
Parâmetro do tipo vetor de float
Passando o vetor numeroscomo argumento
#include <stdio.h>
void incrementar(int n,float num[], float valor){
int i;
for(i = 0; i < n; i++)
num[i] = num[i] + valor ;
}
int main(){
float numeros[10] ;
int i ;
for(i = 0; i < 10; i++)
scanf (“%f”, &numeros[i]) ;
incrementar( 10,numeros,1.5) ;
...
}
25
Passando Vetores como Argumentos
para Funções
Modificando o conteúdo do vetor passado como
argumento
#include <stdio.h>
int reprovado(float nota, float media){
if ( nota < media)
return 1;
else
return 0;
}
int main(){
float notas[] = {6.5,5.0,7.5,9.4,3.8};
int i ;
for(i = 0; i < 5; i++){
if (reprovado(notas[i],7.0) == 1)
printf(“Aluno %d: REPROVADO\n”,i);
else
printf(“Aluno %d: aprovado\n”,i);
}
...
}26
Passando Elementos de Vetores como
Argumentos
Passando um único elemento do vetor para
uma função
27
Um vetor unidimensional armazena uma lista deelementos
Um vetor bidimensional pode ser visto como umamatriz com linhas e colunas
Em C, um vetor bidimensional é um vetor de vetores
Vetores Bidimensionais
int matriz[9][6];
uma
dimensãoduas
dimensões
28
Inicializando Matrizes
A inicialização de uma matriz também pode ser
feita das seguintes formas:
float mat[4][3]={{5.0,10.0,15.0},{20.0,25.0,30.0} ,
{35.0,40.0,45.0},{50.0,55.0,60.0}}
float mat[4][3] = {5.0, 10.0, 15.0, 20.0, 25.0, 30.0,
35.0, 40.0,45.0, 50.0,55.0,60.0}
float mat [][3]= {5.0, 10.0, 15.0, 20.0, 25.0, 30.0,
35.0,40.0,45.0,50.0,55.0,60.0}
Deve ser passada a segunda dimensão
Percorrendo Matrizes
int main() {
int i,j;
int matriz[2][2]={{1,2},{5,6}};
for (i=0;i<2;i++){
for (j=0;j<2;j++){
printf("%d ",matriz[i][j]);
}
printf("\n");
}
return 0;
}Laços aninhados para
percorrer matriz
Saída: 1 2
5 6
Passando Matrizes como Argumentos
de Funções
Uma matriz pode ser passada como
argumento para uma função
Parâmetro da função deve ser do tipo
tipo[][tamanho colunas]
A linguagem C exige que a segundadimensão seja especificada
30
Passando Matrizes como Argumentos
void imprimeMatriz(int linhas, int mat[][2]) {
int i,j;
for (i=0; i < linhas; i++){
for (j=0;j < 2; j++){
printf("%d ",mat[i][j]);
}
printf("\n");
}
}
Deve ser especificada pelo menos a segunda dimensão
3232
Resumindo ...
Armazenamento de grande quantidade deinformação
Necessidade de armazenamento
Problemas
Utilização de muitas variaveis
Manipulação incremental das informações
VetoresConceito
Declaração
Inicialização
Acesso
Limites de um vetor
Passagem de vetores como parâmetros
Vetores bidimensionais (matrizes)
Introdução a Programação
Strings (Vetor de Caracteres)
2
Tópicos da Aula
Hoje aprenderemos a manipular vetores decaracteres (Strings)
Caracteres em CEntrada/Saída de caracteresFunções que manipulam caracteresVetores de caracteres (Strings)
InicializaçãoStrings constantesEntrada/Saída de StringsFunções de Manipulação de Strings
3
Caracteres
Em C, o tipo char :é usado para representar caracterespode armazenar valores inteiros (em 1 byte),representando assim, 256 valores distintosUma constante char é escrita entre aspas simples
char letraA = „A‟;
char letraC;
letraC = „C‟;
printf ( “ %c %c ”, letraA , letraC) ;
4
Caracteres
São representados internamente na memóriado computador por códigos numéricos
A correspondência entre os caracteres e os seuscódigos numéricos é feita por uma tabela ASCIINa tabela ASCII:
os dígitos são codificados em seqüênciaas letras minúsculas e maiúsculas tambémformam dois grupos sequenciais
char letraA = 65; /* letra A*/
char letraC;
letraC = 67;
printf ( “%c %c ”, letraA , letraC) ;
5
0 1 2 3 4 5 6 7 8 930 sp ! “ # $ % & ‘40 ( ) * + , - . / 0 150 2 3 4 5 6 7 8 9 : ;60 < = > ? @ A B C D E70 F G H I J K L M N O80 P Q R S T U V W X Y90 Z [ \ ] ^ _ ` a b c100 d e f g h i j k l m110 n o p q r s t u v w120 x y z { | } ~
Tabela ASCII
6
Impressão de CaracteresPodem ser impressos de duas formasdiferentes usando o printf:
char lc = 97 ;
printf(“%d %c”,lc,lc);
char la = „a‟ ;
printf(“%d %c”,la,la );
Saída: 97 c Saída: 95 a
Existe a função putchar da biblioteca stdio.hque permite a impressão de um caractere
char la = „a‟; /* ou la = 97; */
putchar(la);
7
Leitura de CaracteresLeitura de caracteres com a função scanf
char a ;
scanf(“%c”,&a );
char a ;
/* sem brancos */
scanf(“ %c”,&a );
OU
Existe a função getchar da biblioteca stdio.hque permite a leitura de um caractere
char a ;
a = getchar();
8
Leitura de CaracteresFunção scanf e getchar obriga que a tecla <enter> sejapressionada após a entrada dos dadosExistem funções para ler dados sem esperar pelo<enter> em C para ambientes Windows:
Função getche – definida em conio.h
Lê um caractere e o exibe na tela
char letra ;
letra = getche();
Função getch – definida em conio.hLê um caractere e não o exibe na tela (invisível)
char letra ;
letra = getch();
9
Escrevendo Funções que Manipulam Caracteres
Pode-se tirar proveito da codificação seqüencialda tabela ASCII
Escrevendo programas que usam a tabelaA função abaixo verifica se um dado caractere é umdígito entre ‘ 0 ’ e ‘ 9 ’
int digito (char c){
int ehDigito;
if(( c >= „0‟)&&(c <= „9‟)) {
ehDigito = 1;
} else{
ehDigito = 0;
}
return ehDigito;
}
10
Função para converter uma letra em maiúscula
char maiuscula(char c){
char maiusc;
if((c >= „a‟)&&(c <= „z‟)) {
maiusc = c – „ a ‟ + ‟ A ‟ ;
}
return maiusc ;
}
Escrevendo Funções que Manipulam Caracteres
Testa se é minúscula
Diferença entre qualquer caracter minúsculo e a letra ‘a’ é a mesma do equivalente maiúsculo e a
letra ‘A’
11
Vetor de Caracteres (String)É representada por um vetor do tipo char e terminadaobrigatoriamente, pelo caractere nulo ‘ \0 ’O especificador de formato %s da função printf permiteimprimir uma cadeia de caracteresA partir do endereço para o primeiro caractere, asfunções processam caractere a caractere até que ‘\0’seja encontrado
int main(){
char cidade[4];
cidade[0]=„R‟;
cidade[1]=„I‟;
cidade[2]=„O‟;
cidade[3]=„\0‟;
printf(“%s”,cidade);
}
12
Inicialização de StringsInicialização do vetor de caracteres na declaração
int main(){
char cidade[]={´R‟,‟I‟,‟O‟,„\0‟} ;
printf (“%s\n”,cidade );
}
Inicialização do vetor na declaração através da escritados caracteres entre aspas duplas
int main(){
char cidade[]= “RIO”;
printf(“%s\n”,cidade);
}
Caractere nulo é representado implicitamente
13
Declarando Strings
char s2[] = “Rio de Janeiro”;
Representa um vetor com 15 elementos
char s3[81];
Representa um vetor de no máximo, 80 elementos
char s4[81] = “Rio”;
Representa um vetor de no máximo 80 elementos,mas com um valor inicial já atribuído
printf("Uma string constante!\n");
printf(“Eu moro em %s ",“Recife");
Constantes do Tipo String
São criados strings contantes na memória
R
e
c
i
f
e
\0
100
101
102
103
104
105
106
Constantes do Tipo String
ERRADOchar capital[7];
capital = “Recife";
Declaração da constante do tipo vetor de caracteres capital
Já foi atribuido um endereco à constante capital (endereço inicial do vetor)
Tentativa de atribuir endereço da constante “Recife”à constante capital
Constantes do Tipo String
CORRETOchar capital[7] = “Recife";
Declaração da constante do tipo vetor de caracteres capital
Vetor de caracteres inicializado com as letras que fazem parte de Recife
R
e
c
i
f
e
\0
100
101
102
103
104
105
106
A constante capital armazena o valor inicial da String (100)
17
Impressão de StringsEspecificador %s na função printf deve serutilizado
char cidade [81] = “Recife”;
printf(“%s”, cidade );
Função puts de stdio.h pode ser utilizadotambém para imprimir strings
char cidade [81] = “Recife”;
puts(cidade);
18
Leitura de StringsEspecificador %s na função scanf capturasomente uma seqüência de caracteres nãobrancos
Limitação: somente nomes simples podem ser lidos
char cidade [81];
scanf (“%s”, cidade );
Um caracter branco pode ser um:espaço ( ‘ ’ )caractere de tabulação ( ‘ \ t ’ )caractere de nova linha ( ‘ \ n ’ )
& não é necessário pois cidade já armazena um
endereço (endereço inicial do vetor)
19
Permitindo Ler Mais de um Nome com o scanf
A função acima lê uma seqüência de caracteresaté que seja digitado um <enter>A inclusão do espaço antes de % descartamespaços em brancos que precedem o nome
char cidade [81] ;
scanf(“ %[^\n]”, cidade) ;
O caracter ^ informa que o caracter \n não
pode ser lido
20
Limitando Tamanho da String com o scanf
Para limitar o número máximo de caracterescapturados:char cidade [81] ;
scanf (“ %80[^\n]”, cidade ) ;
No máximo, 80 caracteres são lidos
Cuidado!
Leitura de uma string maior do que a capacidade declarada invadirá espaço de
memória não reservada
21
Usando gets para Leitura A função gets de stdio.h pode também serutilizada para ler strings
Lê a string até encontrar um ‘\n’
VantagensLê nomes compostosSintaxe mais simples
DesvantagemNão tem como limitar quantidade de caractereslidos
char cidade [81];
gets(cidade);
22
Funções de Manipulação de Strings
void imprime (char s[]) {
int i;
for (i = 0; s[i] != „\0‟; i++) {
printf (“%c“,s[i]) ;
}
printf (“\n”);
}
Função análoga
void imprime (char s[]) {
printf ("%s“,s);
printf (“\n”);
}
Imprime caracter a caracter
23
Calcula o comprimento da cadeia
int comprimento (char s[]) {
int i ;
int n = 0 ;
for (i = 0 ; s[i] != „\0‟; i++) {
n++ ;
}
return n ;
}
Função análoga definida em string.h:strlen (char* str) ;
Funções de Manipulação de Strings
Equivalente a char[]
24
void copia (char dest[], char orig[] ){
int i;
for ( i = 0 ; orig[i] != „\0‟; i++) {
dest[i] = orig[i];
}
/* fecha a cadeia copiada */
dest[i] = „\0‟;
}
Função análoga definida em string.h:strcpy (char* dest , char* orig) ;
Copia os elementos do 2º parâmetro no 1ºSupõe que o 2º parâmetro tem espaço suficiente
Funções que Fazem Cópias de Strings
Funções que manipulam Strings assumem que toda String
termina com o „\0‟
Copiando Strings
CORRETOchar capital[7];
char cidade[7];
strcpy(capital,”Recife”);
strcpy(cidade,capital);
Para copiar Strings deve-se utilizar uma função que faz a cópia!
ERRADOchar capital[7];
capital = “Recife";
Não se usa atribuição para copiar uma String na constante do tipo String capital
26
Cadeia de Caracteres
void concatena (char dest[], char orig[]) {
int i = 0 ; int j ;
while (dest[i] != „\0‟){
i++ ;
}
for (j = 0; orig[j] != „ \0 ‟; j++){
dest[i] = orig[j];
i++;
}
dest[i] = „\0‟;
}
Função análoga definida em string.h:strcat (char* dest , char* orig) ;
Concatena as duas cadeias e o resultado é atribuído ao1º parâmetro
Funções que Concatenam Strings
Acha o final da String destino
Copia elementos
Fecha a String destino
Outras Funções para Strings
Definidas em string.h:strcmp(char *str1,char *str2);
Retorna um inteiro positivo se str1 é lexicamenteposterior que str2; zero se as duas são idênticas; enegativo se str1 é lexicamente anterior que str2
strncpy(char *dest,char *origem, int n)
Copia n caracteres de origem para destinostrncat(char *dest,char *origem, int n);
Concatena n caracteres da origem em destino
2828
Vetor de Strings
Vetor de Strings equivale a um vetor de vetoresMatrizCada linha da matriz corresponde a uma string
Útil quando queremos armazenar uma coleçãode strings
2929
Exemplo de Vetor de Strings#define MAX 50 ;
int main (){
int i , numAlunos ;
char alunos[MAX][121] ;
do {
printf( “Digite o numero de alunos:\n”) ;
scanf (“%d”,&numAlunos);
} while ( numAlunos > MAX );
for (i = 0; i < numAlunos; i++) {
gets(alunos[i]) ;/* Lê uma string*/
}
return 0 ;
} Cada posição do vetor guarda uma String
30
Resumindo ...
Caracteres em CEntrada/SaídaFunções que manipulam caracteres
Vetores de caracteres (Strings)InicializaçãoStrings constantesEntrada/SaídaFunções de Manipulação de Strings
Introdução à Programação
Programação e Fatores de
Qualidade
22
Qualidade de Software
Quero que você escrevarapidamente um sistema defolha de pagamento quefuncione corretamente, que sejarobusto e que seja rápido. Ah!Pretendo lançar uma outraversão deste mesmo programa,daqui a uns 6 meses.
Sem problema,chefe.
Ferrou!
33
Tópicos da Aula
Hoje aprenderemos alguns fatores dequalidade de software
Fatores de qualidade externosFatores de qualidade internos
Depois aprenderemos algumas técnicas paramelhorar alguns fatores de qualidade de umprograma
ComentáriosPadrões de CodificaçãoPapel da endentação em um programaAlgumas dicas para melhorar a eficiência de umprograma
4
Impacto econômico e social do
software de qualidade
Disponibilidade de serviços essenciaishome banking
telefoniaSegurança de pessoassistemas de monitoramento de pacientessistemas de controle de tráfego aéreofreios ABS
5
Competitividade das empresasMelhores produtos a um menor custoAtração de novas empresas para a regiãoInvestimentos na regiãoArrecadação de impostos
O impacto na prática
66
Crise de Software
Nas 3 primeiras décadas da Computação, apreocupação maior era hardware
Custo de processamento e armazenamento de dadosDesafio atual é melhorar qualidade e custo dosoftwareProblemas
25% dos projetos são canceladosO tempo e custo de desenvolvimento é bem maior do que oestimado
em 53% dos projetos75% dos sistemas não funcionam como planejadoA manutenção e reutilização são difíceis e custosasA produtividade dos profissionais da área de software nãotem acompanhado a demanda por seus serviços
7
Causas da Crise de Software
EssênciasComplexidade crescente dos sistemasDificuldade e custos de formalização
Uma linha de código do sistema de controle delançamento do ônibus espacial da NASA custa1.000 dólares!
Essências não podem ser evitadas
8
Dificuldade de Formalização
9
Causas da Crise de Software
AcidentesMá qualidade das linguagens, ferramentas emetodologiasProblemas gerenciais (pessoas, riscos, etc.),políticos, e organizacionaisPouca comunicação entre o cliente e odesenvolvedorManutenção de software, geralmente não éconsiderada como parte do ciclo de software
Acidentes PODEM ser evitados!!!
1010
Fatores de Qualidade de Software
Qualidade de software é uma combinação devários fatoresEstes fatores podem ser classificados em:
Fatores ExternosQualidades percebidas pelos usuários de um softwareUsuários incluem: usuário final e aquela pessoa quecontratou o desenvolvimento do softwareEx: corretude, eficiência, reusabilidade, etc
Fatores InternosQualidades percebidas somente por profissionais desoftware que têm acesso ao código do softwareEx: modularidade, legibilidade, etc
11
Robustez
11
Alguns Fatores Externos
Corretude é a capacidade do software executar deforma correta todas as tarefas que foram pedidasnos requisitos e especificação do software
Especificação
Corretude
Robustez é a capacidade do software funcionar,mesmo em situações não previstas na especificação
É o complemento de corretude
1212
Alguns Fatores Externos
Extensibilidade é a facilidade em que o softwarepode ser alterado para que atenda novas exigênciasda especificação
Software está em constante mudança≈70% de custo do software é a fase de manutençãoMudanças de requisitos são responsáveis por ≈ 50% dasatividades de manutenção
Reusabilidade é a capacidade que o software temde ser usado em novas aplicações.
Este uso pode ser de partes do software ou dele todoGrande impacto no tempo de desenvolvimento de softwareMenor tempo de desenvolvimento é importante parasucesso do software
1313
Alguns Fatores Externos
Eficiência é a capacidade do software de otimizar autilização dos recursos de hardware
Muitas vezes requer um bom conhecimento do hardwareonde o software será executadoPode tornar a implementação do software dependente demaisda plataforma alvo
Facilidade de Uso é uma qualidade que diz respeito afacilidade com que usuários com diferentes perfisconseguem aprender a utilizar o software e resolver osproblemas desejados
Engloba também o aprendizado de instalação, operação emonitoramentoRepresenta economia para a empresa que utiliza o softwareem relação aos custos de treinamento
14
Outros Fatores Externos
PortabilidadeEscalabilidadeIntegridade e segurançaCompatibilidadeTestabilidade
1515
Alguns Fatores Internos
Um software é modular se ele é construído àpartir de elementos autônomos conectados
Modularidade Reusabilidade e Extensibilidade
Legibilidade de um programa é a facilidadecom que profissionais de software conseguementender o código do programa
Documentação é importantePadrões de codificação devem ser seguidosLegibilidade Reusabilidade e Extensibilidade
1616
Algumas Considerações sobre
Qualidade
Fatores internosFatores externosSoftwares são utilizados em aplicações dos maisdiversos domíniosFreqüentemente, não se pode obter todos os fatoresde qualidade
Diferentes fatores podem ser conflitantesEx: Freqüentemente para aumentar a eficiência, código doprograma deve ser mais específico a uma plataforma, oque diminui a reusabilidade e/ou portabilidade do código
1717
Algumas Considerações sobre
Qualidade
Cabe ao desenvolvedor avaliar quais
fatores são mais importantes
de acordo com a aplicação
O que foi que aconteceu? Eu pisei no freio e ele demorou um século para ser acionado
Eu ouvi dizer que este sistema novo de controle de freio, pelo menos, é mais reusável
1818
Comentando um Programa
Um programa deve ser bem documentadoDocumentação externa para usuáriosDocumentação no próprio programa
Aumenta a legibilidade
Comentário é um mecanismo oferecido pelas linguagens de programação que permite que o programador expresse em linguagem natural a lógica pensada para escrever um programa ou
um trecho de programa
1919
Comentando um Programa
Usa-se o termo inline documentation paracomentários em um programaDevem ser incluídos para explicar o propósitodo programa e algumas partes deleComentários não afetam o funcionamento doprograma
São ignorados na hora da execução
Dica: Comente o código enquanto o estiver escrevendo, senão há uma forte probabilidade
de não o fazer depois
2020
Comentários em C
Em C para incluir comentários:Usa-se /* e */
Pode conter múltiplas linhas
/* Este tipo de comentário só termina
quando o asterisco barra é encontrado */
Não se pode colocar os símbolos decomentário dentro de um comentário
/* Este tipo de comentário /*só termina*/
quando o asterisco barra é encontrado */
2121
Comentários em C
// Este é um comentário de uma linha
Precedido de //
Isto ocorre porque a maioria das IDEs suportamC++
Este tipo de comentário é aceito em C++
Comentários de uma linha usando // sãoaceitos pela maioria dos ambientes deprogramação (IDEs)
2222
Reuso de Código
Reusabilidade é um fator importante paraacelerar o desenvolvimento de um sistemaReuso pode se dar de várias formas:
Função inteiraUma função chama outra função
Trechos de programa ou funções
2323
Reuso de Código
Existem muitas técnicas existentes parareutilizar código ou pelo menos aumentar opotencial de reusoUma “técnica” infelizmente muito difundida é ocopy & paste
Solução rápida e “boa” para quem não quer pensarSolução péssima para a manutenção do sistema
Se uma alteração for requerida, esta também deverá serpropagada por todos os trechos repetidosSe um bug for encontrado, terá de ser corrigido em todosos outros códigos repetidos
Melhor do que isto é usar Refactoring
2424
Refactoring
Refactoring consiste em uma série de técnicas quereestruturam o código do software, aumentando opotencial de reuso, extensibilidade e legibilidade
O comportamento do software continua o mesmo, só muda aestruturaMuito difundido entre metodologias de desenvolvimento desoftware orientadas a objetos
Porém, muitas técnicas podem ser aplicadas a programasdesenvolvidas em linguagens como C
Exemplos de refactoring:Generalizar uma função com parâmetrosTransformar um trecho de codigo em uma função
25
Padronização de Codificação
Quanto mais fácil for o entendimento(legibilidade) do código do sistema, maisprodutiva será a equipe de desenvolvimentoFreqüentemente as pessoas que escrevem ocódigo não são as mesmas que o mantém
Pode haver dificuldades de entendimento entre asdiferentes pessoas que trabalham sobre o mesmocódigo
Atrasa o desenvolvimento do sistema
26
Padronização de Codificação
Um padrão de codificação visa minimizar essesproblemas
Estabelece regras, definindo como o código deveser escrito para favorecer a impessoalidade doprogramaFacilita a integração de novos desenvolvedores aoambiente de desenvolvimento
Em C, não existe um padrão internacionalaceito de codificação
Empresas geralmente estabelecem um próprio
Porém, veremos os padrões mais utilizados em C
27
Nomenclatura de Contantes e
Variáveis
A princípio, identificadores não devem serabreviados
Quando o fizer, usar bom senso para que não seperca expressividadeUsar bom senso para que nome da variável ouconstante não fique grande demais
Focar no que a variável ou a constanterepresentam
Recomenda-se colocar o identificador de umaconstante em letras maiúsculas
Se houver mais de uma palavra, as palavrasseguintes devem ser separadas com o caracter deunderscore ( _)
28
Nomenclatura de Contantes e
Variáveis
Recomenda-se colocar o identificador de umavariável começando com letra minúscula
Se houver mais de uma palavra, as palavrasseguintes devem começar com maiúscula ouserem separadas com o caracter de underscore (_)
Para nome de variáveis locais querepresentam contadores, pode-se colocarapenas uma letra do alfabetofor (i = 0; i < 5; i++) /*Aceitável */
Exemplos de Constantes e Variáveis
quantidadeAutores /*Bom */
Variável para representar a quantidade de autores deum livro
qtdAutores /* Aceitável */
qtdAut /* Inaceitável */
variavelQueArmazenaQuantidadeDeAutores /*Ruim*/
29
Constante para representar o número de vagas dadisciplina de IP
VAGAS_IP = 60 /*Bom */
Vg_Ip = 60 /*Inaceitável */
30
Nomenclatura de Funções
Identificadores não devem ser abreviadosRecomenda-se colocar o nome começando letraminúscula
Se houver mais de uma palavra, as palavras seguintes devemcomeçar com maiúscula ou serem separadas com o caracterde underscore (_)
Não se deve colocar nomes misturando palavras delínguas diferentesMuitas vezes, coloca-se na primeira palavra um verbono infinitivo representando a utilidade da função
Ex: imprimirPrimos(int comeco, int fim)
Muitas vezes se coloca um nome igual ao nome deuma função matemática
Ex: fatorial(int n)
31
Importância da Endentação
Como sabemos, o compilador C ignora espaços etabulaçõesPorém, para aumentar a legibilidade do código é muitoimportante se preocupar com sua endentação
Torna mais claro o que será feito dentro de comandoscondicionais e laçosTorna mais claro o limite de funções
if (total > MAX)
printf ("Erro!!");
contador++;
if (total > MAX)
printf ("Erro!!");
contador++;
32
Que trecho de código é mais claro?int divisao(int dividendo, int divisor){int i, resultado = 0;
if (divisor != 0)
for(i = dividendo; i >= divisor ; i = i - divisor)
resultado++;
return resultado;
}
int divisao(int dividendo, int divisor){
int i, resultado = 0;
if (divisor != 0)
for(i = dividendo; i >= divisor ; i = i - divisor)
resultado++;
return resultado;
}
33
Algumas Dicas para Melhorar
Eficiência
Evitar o uso de variáveis globaisOcupam memória durante toda a execução doprograma
Não declarar variaveis que não serãoutilizadasNão declarar variáveis com tipos que ocupammais memória quando a aplicação nãotrabalha com valores muito grandes
Aritmética de inteiros é mais rápida do quearitmética de ponto flutuante (reais)
34
Algumas Dicas para Melhorar
Eficiência
Sempre que puder privilegiar soluçõesiterativas sobre as recursivas
Pode diminuir uso da memóriaPode economizar tempo de processamento
Evitar executar todas as iterações de um laçoquando não é necessário
Economiza tempo de processamento
35
Exemplo de Melhoria de Eficiência
Evita um teste desnecessario
se o numero for
maior do que 100
int existeNumeroPrimoEntre(int inicio, int fim){
int i, existe = 0;
for(i = inicio; i <= fim;i++){
/*Considere que exista uma função que diz se um num é primo*/
if (numeroPrimo(i) == 1) {
existe = 1;
}
}
return existe;
}
Mesmo achando um numero
primo, continua laço
36
Exemplo de Melhoria de Eficiênciaint existeNumeroPrimoEntre(int inicio, int fim){
int i, existe = 0;
for(i = inicio; i <= fim && existe == 0;i++){
/*Considere que exista uma função que diz se um num é primo*/
if (numeroPrimo(i) == 1) {
existe = 1;
}
}
return existe;
}Evita continuação do laço
quando encontra numero primo
37
Algumas Dicas para Melhorar
Eficiência
Quando usar comandos condicionais, analisarse certos caminhos podem realmente serexecutados
Elimine caminhos que nunca podem serexecutados
Quando o programa tiver muitos if testandouma mesma variavel, verificar se não émelhor colocar alguns else para evitar testesdesnecessários
38
Exemplo de Melhoria de Eficiênciavoid maiorQue100(int numero){
if (numero > 100){
printf(“%d eh maior que 100”,numero);
}
if (numero <= 100) {
printf(“%d nao eh maior que 100”,numero);
}
}
void maiorQue100(int numero){
if (numero > 100){
printf(“%d eh maior que 100”,numero);
} else {
printf(“%d nao eh maior que 100”,numero);
}
}
Evita um teste desnecessario
se o numero for
maior do que 100
3939
Referências Adicionais
Crise do softwareSoftware„sChronic Crisishttp://www.cin.ufpe.br/~if669/files/MaterialDeEnsino/Referencias/SoftwareChronicsCrisis/SciAmSept1994.html
Fatores de QualidadeBertrand Meyer. Object-Oriented Software Construction.Segunda Edição. Prentice Hall, 1988
Otimização de código Chttp://www.abarnett.demon.co.uk/tutorial.html#ARRAY
Práticas que NÃO devem ser seguidasProgramação Orientada a Gambiarrahttp://desciclo.pedia.ws/wiki/Programação_Orientada_a_Gambiarras
4040
Resumindo ...
Fatores de qualidade de softwareFatores de qualidade externosFatores de qualidade internos
Técnicas para melhorar alguns fatores de qualidade deum programa
Comentários
Refactoring
Endentação
Melhorando a eficiência
Introdução a Programação
Ponteiros e Passagem de Argumentos por Referência
Tópicos da Aula
Hoje aprenderemos a manipular endereços de
memória ou ponteiros
Variáveis e Endereços
Conceito de Ponteiro
Operadores de Ponteiros
2
Ponteiros e Funções
Passagem de Argumentos por Referência
Importância de uso de ponteiros
Aritmética de Ponteiros
Variáveis e Endereços
Memória abstrata (Como vemos a memória):
{x→→→→5, y→→→→9, z→→→→‘a’}
Memória concreta:
Associações:
Id→→→→Valor
Associações:
{x→→→→13, y→→→→72, z→→→→00}
Memória de fato:
{00→→→→‘a’,...,13→→→→5,
72→→→→9,...,99→→→→undefined}
Id→→→→Endereço
Endereço→→→→Valor
Ponteiros
Toda variável tem um endereço ou uma
posição associados na memória
Este endereço é visto como um ponteiro
(ou apontador), uma referência para a(ou apontador), uma referência para a
posição de memória de uma variável
Ponteiros fornecem um modo de acesso à
variável sem referenciá-la diretamente
Um endereço pode ser armazenado em
uma variável do tipo ponteiro (ponteiro
variável)
Ponteiro Variável
Um ponteiro variável é uma variável que contém
o endereço de outra variável
valor1V endereço4
endereço5
Memória
P = endereço da variável V
valor1
endereço4P
V
endereço1
endereço2
endereço3
endereço4
P aponta para V
Declarando Variáveis do Tipo Ponteiroem C
int b; Declara uma variável de nome b que pode armazenar
valores inteiros
Para declarar uma variável do tipo ponteiro:
6
int* p; Declara uma variável de nome p que pode armazenar um endereço de memória
para um inteiro
Forma Geral:tipo* variavel
Operador &
Operador unário que fornece o endereço deuma variável
Forma Geral:&variavel
Variável de tipo ponteiro para int *p;
int v;
p = &v;
ERRADO!
Não pode ser aplicado a expressões ouconstantes
Ex: x = &3;
Variável p de tipo ponteiro para inteiro recebe endereço da variável v de tipo inteiro
Operador de Indireção *
Quando aplicado a uma variável do tipo
ponteiro, acessa o conteúdo do endereço
apontado por ela
Forma Geral:*variavel
3
endereço4p
v
endereço1
endereço2
endereço3
endereço4
endereço5
int *p;
int v = 3;
p = &v;
*p = 4;
*variavel
4
Usando Ponteiros
int i, j;
int *ip;
i = 12;
A variável ip armazena um ponteiro para um inteiro
O endereço de i é armazenado em i = 12;
ip = &i;
j = *ip;
*ip = 21;
O endereço de i é armazenado em ip
O conteúdo da posição apontada por ip é armazenado em j
O conteúdo da posição apontada por ip passa a ser 21
Usando Ponteiros
int i,j ;
int *ip ;112
12
ip
1)
j
i
108
104---
i = 12 ;
2)
112ip
j
i
108
104
--
ip = &i ;
112ip
3)
j
i
108
10412
-104
12
j = *ip;
*ip = 21;112ip
4)
j
i
108
10412
104
21
Manipulando Ponteiros
int main () { /* função principal */
int a , *p ;
p = &a ;
*p = 2 ;
printf (“%d”,a);
return 0 ;
}Imprime o valor 2
int main () { /* função principal*/
int a,b,*p ;
a = 2 ;
*p = 3 ;
b = a +( *p );
printf(“%d”,b);
return 0;
}
Imprime o valor 2
Erro típico de manipulação de ponteiros –ponteiro não inicializado!
Funções e Ponteiros
Retorno explícito de valores não permite transferir
mais de um valor para a função que chama
# include <stdio.h>
void somaprod(int a, int b, int c, int d) {
c = a + b ;
d = a * b ;
}
12
int main () {
int s,p ;
somaprod(3,5,s,p) ;
printf(“Soma = %d e Produto = %d \n”,s,p);
return 0 ;
}
Esse código não funciona como esperado !
A Passagem de Argumentos em C é por valor...
int a,b;
a = 8;
b = 12;
swap(a,b);
A chamadada funçãonão afeta os valores de a e b
Copia os valores que estão em a e b para parâmetros x e y
void swap(int x, int y){
int temp;
temp = x;
x = y;
y = temp;
}
parâmetros x e y
int a,b;
a = 8;
b = 12;
swap(&a,&b);
A chamadada funçãoafeta os valores de a e b
Copia os endereços de a e b para parâmetros px e py
Mas C Permite a Passagem por Referência
void swap(int* px, int* py){
int temp;
temp = *px;
*px = *py;
*py = temp;
}
parâmetros px e py
Passagem por Referência em C
int a,b ;
a = 8;
b = 12
112
1)
b
a
108
1048
12
-
main>
104
108swap(&a,&b) ;
2)
112swap>
b
a
108
104main>
px
py
temp
8
12
-
8
*px = *py;
*py = temp;
4)
112swap>
b
a
108
104main>
px
py
temp
104
108
8
8
128
temp = *px;
3)
112swap>
b
a
108
104main>
px
py
temp
8
12
104
108
12
Como uma função pode alterar variáveis de
quem a chamou?
1) função chamadora passa os endereços dos
valores que devem ser modificados
Passando endereços para uma função
2) função chamada deve declarar os endereços
recebidos como ponteiros
16
Usando Passagem por Referência para Função SomaProd
# include “stdio.h”
void somaprod(int a,int b,int* p, int* q){
*p = a + b ;
*q = a * b ;
}
Passagem por
17
int main (){
int s , p ;
somaprod (3 , 5 , &s , &p) ;
printf(“Soma= %d e Produto = %d \n”,s,p);
return 0 ;
}
Passagem por Referência
Por que ponteiros são usados ?
Possibilitar que funções modifiquem os
argumentos que recebem
Manipular vetores e strings - útil para passar
vetores como parâmetrovetores como parâmetro
Criar estruturas de dados mais complexas,
como listas encadeadas, árvores binárias etc.
18
Operações com Ponteiros
int main( ) {
int x=5, y=6;
int *px, *py;
px = &x;
py = &y;
if (px < py)
printf(“py-px = %u\n”,py-px);
else
px e py armazenam endereços para
inteiros
else
printf(“px-py = %u\n”,px-py);
return 0;
} Resultado: diferença entre endereços
dividido pelo tamanho em bytes de um
inteiro
Saída será:
Se px = 65488 e py = 65484
Testes relacionais >=,<=, <, >, ==, sãoaceitos em ponteiros
A diferença entredois ponteiros será
Operações com Ponteiros
Saída será:px - py = 1
A diferença entredois ponteiros serádada na unidade dotipo de dado apontado
Operações com Ponteiros
int main( ) {
int x=5, y=6;
int *px, *py;
px = &x;
py = &y;
printf(“px = %u\n”,px);
printf(“py = %u\n”,py);
py++;
Podemos utilizar operador de
incremento com py++;
printf(“py = %u\n”,py);
py = px+3;
printf(“py = %u\n”,py);
}
incremento com ponteiros
Podemos fazer aritmética de ponteiros
Operações com ponteiros
O incremento de um ponteiro acarreta na
movimentação do mesmo para o próximo
valor do tipo apontado
Ex: Se px é um ponteiro para int com valor 3000,
depois de executada a instrução px++, o valor dedepois de executada a instrução px++, o valor de
px será 3004 e não 3001 !!!
Obviamente, o deslocamento varia de
compilador para compilador dependendo do
número de bytes adotado para o referido tipo
22
Resumindo...
Ponteiros
Conceito
Operadores de Ponteiros
Ponteiros e Funções
Passagem de Argumentos por Referência
23
Quando usar ponteiros
Operações com Ponteiros
Introdução a Programação
Ponteiros e Vetores
2
Tópicos da Aula
Hoje aprenderemos que existe uma forte
relação entre ponteiros e vetores
Associação entre ponteiros e vetores
Ponteiros constantes x Ponteiros variáveis
Passagem de ponteiros invés de vetores para
funções
Comando sizeof
3
Considere a declaração:
O símbolo v
Representa o vetor
É uma constante que representa seu endereço
inicial
Aponta para o primeiro elemento do vetor
Associação entre Vetores e Ponteiros
int v [10] ;
4
Ponteiros e Vetores (matrizes)
Em C existe um relacionamento muito forte
entre ponteiros e vetores
O compilador entende todo vetor e matriz como
ponteiros, pois a maioria dos computadores é capaz
de manipular ponteiros e não vetores
Qualquer operação que possa ser feita com índices
de um vetor pode ser feita com ponteiros
O identificador de um vetor representa um endereço,
ou seja, um ponteiro
5
Como vimos, C permite aritmética de ponteiros
Se tivermos a declaração
Podemos acessar elementos do vetor através
de aritmética de ponteiros
Ponteiros e Vetores
Aponta para (igual ao endereço do) primeiro
elemento do vetorv + 0
Aponta para o segundo elemento do vetorv + 1
Aponta para o último elemento do vetorv + 9
Portanto: &v[i]↔(v + i) v[i]↔ *(v + i)
int v [10] ;
6
Representando Ponteiros e Vetores na Memória
100
101
102
103
104
105
106
107
108
109
110
111
6
10
7
v + 2 &v[2] 108
*(v + 2) v[2] 7
Memória int v[] = {6,10,7};
v + 1 &v[1] 104
*(v + 1) v[1] 10
v &v[0] 100
*v v[0] 6
7
Ponteiros e Vetores
int a[10];
int *pa;
pa = &a[0];
pa = a;
Vetores podem ser tratadoscomo ponteiros em C!
*pa a[0] pa[0]
*(pa+i) a[i]
pa[i] *(a+i)
a+i &a[i]
Expressões Equivalentes!
pa = &a[0];
pa = a;
8
Usando Notação de Ponteiros para Vetores
int main( ) {
int nums[ ] = {1, 4, 8};
int cont;
for(cont=0; cont < 3; cont++) {
printf(“%d\n,nums[cont]);
}
}
int main( ) {
int nums[ ] = {1, 4, 8};
int cont;
for(cont=0; cont < 3; cont++) {
printf(“%d\n,*(nums + cont));
}
}
Versão com Ponteiro
Versão com Vetor
9
Ponteiros Constantes x Ponteiros Variáveis
int main( ) {
int nums[ ] = {1, 4, 8};
int cont;
for(cont=0; cont < 3; cont++) {
printf(“%d\n,*(nums++));
}
}
Declaração de uma constante do tipo ponteiro para inteiros (ponteiro constante)
Tenta incrementar endereço armazenado na constante nums e atualizar a constante com
novo endereço
Errado!
10
Ponteiros Constantes x Ponteiros Variáveis
int main( ) {
int nums[ ] = {1, 4, 8};
int* pnums = nums;
int cont;
for(cont=0; cont < 3; cont++) {
printf(“%d\n,*(pnums++));
}
}
Declaração de uma variável do tipo ponteiro para inteiros (ponteiro variável)
Incrementa endereço armazenado na variável pnums e atualiza a variável com
novo endereço
Certo!
11
int a[10];
int *pa;
pa = a;
Ponteiros Constantes x Ponteiros Variáveis
int a[10];
int *pa;
a = pa;
Atribui a uma variável um novo
endereço: CERTO!
Atribui a uma constante um novo endereço: ERRADO!
#include <stdio.h>
float media(int n, float num[]){
int i;
float s = 0.0;
for(i = 0; i < n; i++)
s = s + num[i] ;
return s/n ;
}
int main(){
float numeros[10] ;
float med;
int i ;
for(i = 0; i < 10; i++)
scanf (“%f”, &numeros[i]) ;
med = media(10, numeros ) ;
...
}12
Passando Vetores como Argumentos para Funções
Parâmetro do tipo vetor de float
Endereço inicial do vetor é passado como argumento
#include <stdio.h>
float media(int n, float* num){
int i;
float s = 0.0;
for(i = 0; i < n; i++)
s = s + num[i] ;
return s/n ;
}
int main(){
float numeros[10] ;
float med;
int i ;
for(i = 0; i < 10; i++)
scanf (“%f”, &numeros[i]) ;
med = media(10, numeros ) ;
...
}13
Passando Ponteiros invés de Vetores como Argumentos para Funções
Parâmetro do tipo ponteiro para float
Endereço inicial (ponteiro) do vetor é passado como
argumento
14
Passando Ponteiros como Argumentos de Funções
Considere a seguinte assinatura de função:
void incrementa(int n, int* v)
Pergunta: Parâmetro v é um ponteiro para um vetor de inteiros ou para uma variável do tipo inteiro?
Resposta 1: Não tem como saber
Resposta 2: É indiferente. Podemos considerar um ponteiro para uma variável do tipo inteiro como um ponteiro para um vetor com um só elemento
15
Comando sizeof
Forma Geral:
Informa o número de bytes de um dado tipo ou variável
em tempo de compilaçãoExemplo:
int d = sizeof(float); d armazena o valor 4
sizeof(tipo) ou sizeof(variavel)
16
Usando sizeof para Determinar Tamanho de Ponteiros e Vetores
int main() {
int num[ ]={1,2,3};
int numElementos = sizeof(num)/sizeof(int);
printf ("Tamanho = %d\n", sizeof(num));
printf ("Num elementos = %d\n", numElementos);
}
int main() {
int num[ ]={1,2,3};
int* num2 = num;
int numElementos = sizeof(num2)/sizeof(int);
printf ("Tamanho = %d\n", sizeof(num2));
printf ("Num elementos = %d\n", numElementos);
}
Qual é o o numero de elementos?
Qual é o o numero de elementos?
3
1
17
Resumindo ...
Relação entre ponteiros e vetores
Ponteiros constantes x Ponteiros variáveis
Passagem de ponteiros invés de vetores para
funções
Comando sizeof
Introdução a Programação
Ponteiros e Strings, Alocação
Dinâmica
2
Tópicos da Aula
Hoje aprenderemos que a relação entre
ponteiros e strings
Ponteiros para strings X Vetores de Caracteres
Vetores de ponteiros para strings
Também veremos como alocar espaço de memória em
tempo de execução
Conceito de Alocação Dinâmica
Importância
Funções em C para alocação dinâmica
Usando alocação dinâmica para criar vetores e
matrizes dinâmicas
3
Ponteiros e Strings
Uma string é um vetor de caracteres
Vimos que s armazena o endereço inicial do
vetor
Portanto, podemos manipular strings com
ponteiros
char s [10] ;
4
Ponteiros e Strings
ERRADOchar capital[7];
capital = “Recife";
Declaração da constante do tipo vetor de caracteres capital
Já foi atribuido um endereco à constante capital (endereço inicial do vetor)
Tentativa de atribuir endereço da constante “Recife”à constante capital
5
Ponteiros e Strings
CORRETOchar capital[7] = “Recife";
char* cidade;
cidade = “Recife”;
Declaração da constante do tipo vetor de caracteres capital
Vetor de caracteres inicializado com as letras que fazem parte de Recife
Atribuição do endereço da constante “Recife”à variável cidade
6
Inicialização de Strings Através de
Ponteiros
int main() {
char *salute=“saudacoes”;
puts(++salute);
return 0;
}
int main() {
char salute[] =“saudacoes”;
puts(++salute);
return 0;
}
Estes dois códigos executariam da mesma forma?
Imprime audacoes (sem s): ponteiro
variável
Erro de compilação: tentativa de modificar
ponteiro constante
7
Passando Ponteiros para Strings para
FunçõesNa biblioteca string.h, existem várias funções que
têm como parâmetros ponteiros para strings
Exemplos:
char* strcpy(char* dest, char* origem);
int strcmp(char* s1, char* s2);
Podemos passar como argumentos, tanto ponteiros
para strings ou vetores de caracteres(strings)
int main() {
char *salute=“saudacoes”;
char saudacao[10];
strcpy(saudacao,salute);
return 0;
}
8
Vetores de Strings x Vetores de
Ponteiros para Strings
Quando queremos armazenar um conjunto de
strings podemos:
Usar um vetor de strings
Vetor bidimensional (matriz) de caracteres
Usar um vetor de ponteiros para strings
Usando Vetor de Strings (Matriz de
Caracteres)
int main(){
int cont;
int entra=0;
char nome[40];
char list[4][7]= {“Carlos”, “Ana”, “Pedro”, “Andre”};
printf (“Digite seu nome:”);
gets(nome);
for (cont=0; cont < 4; cont++){
if (strcmp(list[cont],nome) == 0)
entra=1;
}
if (entra == 1)
printf (“Você pode entrar.”);
else
printf (“Você não pode entrar.”);
return 0;
}
Programa verifica se um nome entrado pelo usuário pertence a um
vetor inicializado de strings
Cuidado para que as strings não excedam as
colunas da matriz!
Usando Vetores de Ponteiros para
Strings
int main(){
int cont;
int entra=0;
char nome[40];
char* list[4]= {“Carlos”, “Ana”, “Pedro”, “Andre”};
printf (“Digite seu nome:”);
gets(nome);
for (cont=0; cont < 4; cont++){
if (strcmp(list[cont],nome) == 0)
entra=1;
}
if (entra == 1)
printf (“Você pode entrar.”);
else
printf (“Você não pode entrar.”);
return 0;
}
Programa verifica se um nome entrado pelo usuário pertence a um vetor
inicializado de ponteiros para strings
Despreocupação com tamanho das strings
11
Inicialização de um Vetor de Strings x
Vetor de ponteiros para Strings
C a r l o s\0A n a\0P e d r o\0A n d r e\0
0 1 2 3 4 5 6list[0]
list[1]
list[2]
list[3]
Versão Vetor de Strings
list[0]
list[1]
list[2]
list[3]
Versão Vetor de Ponteiros
C a r l o s\0A n a\0P e d r o\0A n d r e\0
Desperdício de Memória!
int main(){
int cont;
int entra=0;
char nome[40];
char list[4][10];
for (cont=0; cont < 4; cont++){
printf(“\nEntre com mais um convidado:\n”);
gets(list[cont]);
}
return 0;
}
Programa pede para o usuário preencher um vetor de strings
Cuidado para que as strings não excedam as
colunas da matriz!
Outro Exemplo Usando Vetor de
Strings
int main(){
int cont;
int entra=0;
char nome[40];
char* list[4];
for (cont=0; cont < 4; cont++){
printf(“\nEntre com mais um convidado:\n”);
gets(list[cont]);
}
}
Programa pede para o usuário prencher um vetor de ponteiro para
strings
ERRADO!
Outro Exemplo Usando Vetor de
Ponteiro de Strings
Tenta armazenar string em endereço (INVÁLIDO)
apontado por list[cont]
14
Alocação de Memória
Quando declaramos uma variável, o compilador
reserva (aloca) um espaço na memória
suficiente para armazenar valores do tipo da
variável
Alocação estática (em tempo de compilação)
int var ;
char s1 [10];
char* s2;
Aloca espaço para 1 int
Aloca espaço para 10 char
Aloca espaço para 1 endereço
15
Modos de alocar espaço em memória:
Estaticamente
Variáveis globais (e estáticas): O espaço reservado
para a variável existe enquanto o programa estiver
sendo executado
Variáveis locais: O espaço existe enquanto a
função, que declarou a variável, estiver sendo
executada.
Dinamicamente
Requisitar memória em tempo de execução: O
espaço alocado dinamicamente permanece
reservado até que seja explicitamente liberado
pelo programa
Alocação Dinâmica
16
Função básica para alocar memória é malloc
presente na biblioteca stdlib.h
Recebe como argumento um número inteiro sem
sinal que representa a quantidade de bytes que se
deseja alocar
Retorna o endereço inicial da área de memória
alocada.
Alocação Dinâmica em C
void* malloc(unsigned qtdBytes);
17
Aloca somente a quantidade de memórianecessária
Exemplo:
Alocação Dinâmica em C com malloc
int *v ;
v = malloc (10 * 4) ;
Se a alocação for bem sucedida, v armazenará o endereço inicial de uma área contínua de memória suficiente para armazenar 10 valores inteiros (4O
bytes)
18
Uso do comando sizeof para ter independência de
plataforma de desenvolvimento
Exemplo:
int *v ;
v = malloc(10 * sizeof (int)) ;
Função malloc retorna um ponteiro genérico, para
qualquer tipo, representado por *void
Faz-se a conversão para o tipo apropriado usando o operador
de molde de tipo (cast)
v = (int *) malloc(10 * sizeof(int));
Alocação Dinâmica em C com malloc
19
Erro na Alocação
Se não houver espaço livre suficiente pararealizar a alocação, a função malloc retorna
um endereço nulo
É representado pelo símbolo NULL
É uma boa prática de programação testar se a
alocação foi bem sucedida para evitar erros de
execução
20
Liberando Espaço Alocado
Uso da função free para liberar espaço de
memória alocada dinamicamente
Recebe como parâmetro o ponteiro da memória a
ser liberada
O espaço de memória fica livre para ser alocado
futuramente pelo próprio programa ou outro
programa
Recomenda-se liberar espaço de memória
previamente alocado que não é mais necessário
Evita desperdício
void free(void* endereco);
21
Memória e Alocação Dinâmica
Código do programa
Variáveis Globais e Estáticas
Memória livre
1) Declaração: int *v ;
v -
Código do programa
Variáveis Globais e Estáticas
Memória livre
2) v=(int*)malloc(10*sizeof (int));
v 504
40 bytes504
Abre-se espaço na pilha para o ponteiro (variável local)
Reserva-se o espaço de memória da área livre e atribui o endereço à v
#include <stdio.h>
int main() {
int qtdNumeros,contador = 0;
float numeros[2000];
float media = 0.0;
do{
printf(“Quantidade de numeros? (< 2000):\n”);
scanf(“%d”, &qtdNumeros);
} while (qtdNumeros <= 0 || qtdNumeros > 2000);
while (contador < qtdNumeros) {
scanf(“%f”,&numeros[contador]);
media = media + numeros[contador];
contador++;
}
media = media/qtdNumeros;
printf(“\nA media eh %f\n”);
return 0;
} 22
Usando Alocação Estática para
Calcular Média com Vetores
Declaração estática do tamanho do vetor limita
aplicação
Tamanho pode ser insuficiente ou grande demais (desperdício)
23
Vetores Dinâmicos
Declaração de vetores implicam em alocação estática
de memória
Com alocação dinâmica, podemos criar algo como
um vetor cujo tamanho é decidido em tempo de
execução, ou seja um vetor dinâmico
Para tal, usaremos variáveis do tipo ponteiro que
receberão os endereços iniciais do espaço alocado
dinamicamente
Com o endereço inicial, podemos navegar pelo vetor
int main() {
int qtdNumeros,contador = 0;
float* numeros;
float media = 0.0;
do{
printf(“Quantidade de numeros?:\n”);
scanf(“%d”, &qtdNumeros);
} while (qtdNumeros <= 0);
numeros = (float*) malloc(qtdNumeros*sizeof(float));
if (numeros == NULL) {
printf(“Memoria insuficiente”);exit(1);
}
while (contador < qtdNumeros) {
scanf(“%f”,&numeros[contador]);
media = media + numeros[contador];
contador++;
} /* continua */
} 24
Usando Alocação Dinâmica para
Calcular Média com Vetores Dinâmicos
Ponteiro recebe endereço de espaço
alocado dinamicamente (vetor dinâmico)
Tamanho do vetor é determinado pelo usuário
25
Podemos mudar o espaço de memória alocado
previamente de forma dinâmica
Para isso, podemos utilizar a função realloc
Recebe endereço do bloco de memória alocado previamente
Recebe como argumento um número inteiro sem sinal que
representa a quantidade de bytes que se deseja alocar
Retorna o endereço inicial da área de memória alocada
Se endereço retornado for diferente do passado como
parâmetro, conteúdo do bloco original é copiado para
novo endereço
Função Realloc
void* realloc(void* ptr,unsigned qtdBytes);
int main() {
int qtdNumeros = 5,contador = 0;
char resposta;
float media = 0.0;
float* nums;
nums = (float*) malloc(qtdNumeros*sizeof(float));
if (nums == NULL) {
printf(“Memoria insuficiente”);exit(1);
}
printf(“Programa calcula media de 5 numeros.”);
printf(“Deseja mais/menos? (s/n)\n”);
scanf(“%c”,&resposta);
if (resposta == „s‟) {
do {
printf(“Quantidade de numeros?:\n”);
scanf(“%d”, &qtdNumeros);
} while (qtdNumeros <= 0);
nums = (float*) realloc(nums,qtdNumeros*sizeof(float));
/* continua */
} 26
Usando Realloc
Vetor é alocado dinamicamente
Tamanho do vetor muda dinamicamente
27
Vetores e Alocação Dinâmica
Vetores Locais e Funções
float* prod_vetorial (float* u , float* v) {
float p[3] ;
p[0] = u [ 1 ] * v [ 2 ] – v [ 1 ] * u [ 2 ] ;
p[1] = u [ 2 ] * v [ 0 ] – v [ 2 ] * u [ 0 ] ;
p[2] = u [ 0 ] * v [ 1 ] – v [ 0 ] * u [ 1 ] ;
return p ;
}
A variável retornada é declarada localmente. Por isso, sua área de memória deixa de ser válida
quando a função termina.
ERRADO! – Endereço local é retornado
28
Vetores e Alocação Dinâmica
Vetores Locais e Funções
Forma Correta:
float* prod_vetorial (float* u , float* v) {
float* p = (float*) malloc(3 * sizeof(float)) ;
p[0] = u [ 1 ] * v [ 2 ] – v [ 1 ] * u [ 2 ] ;
p[1] = u [ 2 ] * v [ 0 ] – v [ 2 ] * u [ 0 ] ;
p[2] = u [ 0 ] * v [ 1 ] – v [ 0 ] * u [ 1 ] ;
return p ;
}
CERTO! – Endereço alocado dinamicamente fica disponível até que
seja liberado explicitamente
29
Criando Matrizes Dinâmicas
Deve-se usar um ponteiro para ponteiro
Pode-se pensar em uma matriz dinâmica comoum vetor de ponteiros
Cada elemento do vetor contém o endereço inicial deuma linha da matriz (vetor-linha)
Para alocar uma matriz com malloc, é preciso fazer aalocação do vetor de ponteiros e, em seguida, decada vetor-linha
Da mesma forma, a liberação da memória é feita empartes
int** matriz;
Ponteiro para ponteiro
30
31
Representando Matrizes Dinâmicas na
Memória
100
101
102
103
104
105
106
107
300
408
Memória
int** m;
6
300
10
304
7
408
11
412
Vetor Linha
m
Ponteiro (endereço inicial do vetor linha)
100
6 10
7 11
Matriz m
Alocando uma Matriz Dinâmica
int main () {
int linhas, colunas,i,j;
printf(“Numero de linhas e colunas da matriz:\n");
scanf("%d %d",&linhas,&colunas);
float** mat ;
mat = (float**) malloc(linhas * sizeof(float*));
for (i = 0 ; i< linhas ; i++) {
mat[i]= (float*) malloc(colunas * sizeof(float)) ;
}
printf("\n Digite os elementos da matriz:\n");
for(i=0; i< linhas; i++) {
for(j=0; j< colunas; j++) {
printf("Elemento [%d][%d] = ",i,j);
scanf("%f",&mat[i][j]);
printf("\n");
}
}
/* continua */
Alocando vetor de ponteirosAlocando
vetores-linha
Liberando uma Matriz Dinâmica
void liberaMatriz (int** mat, int linhas) {
int i,j;
for(i=0; i< linhas; i++) {
free(mat[i]);
}
free(mat);
}
Libera primeiro cada vetor
linha
Libera depois vetor de ponteiros
void imprimeMatriz(int linhas, int** mat) {
int i,j;
for (i=0; i < linhas; i++){
for (j=0;j < 2; j++){
printf("%d ",mat[i][j]);
}
printf("\n");
}
}
Parâmetro do tipo ponteiro para ponteiro de int
Acesso usando notação de ponteiro:
*(*(mat+i)+j)
Passando Matrizes Dinâmicas como
Argumentos
Cuidado na Assinatura da Função
void imprimeMatriz(int linhas, int** mat) {
int i,j;
for (i=0; i < linhas; i++){
for (j=0;j < 2; j++){
printf("%d ",mat[i][j]);
}
printf("\n");
}
}
int main() {
int matriz[][2] = {{6,10},{7,11}};
imprimeMatriz(2,matriz);
return 0;
}
Parâmetro do tipo ponteiro de ponteiro de int
Endereço da matriz estática passada como argumento
Erro de Execução!
Cuidado na Assinatura da Função
void imprimeMatriz(int linhas, int mat[][2]) {
int i,j;
for (i=0; i < linhas; i++){
for (j=0;j < 2; j++){
printf("%d ",mat[i][j]);
}
printf("\n");
}
}
int main() {
int matriz[][2] = {{6,10},{7,11}};
imprimeMatriz(2,matriz);
return 0;
}
Parâmetro do tipo vetor de vetores de int
Parâmetro deve indicar número de colunasCerto!
37
Resumindo ...
Relação entre ponteiros e strings
Ponteiros para strings X Vetores de
Caracteres
Vetores de ponteiros para strings
Alocação Dinâmica
Uso
Funções em C para alocação dinâmica
Usando alocação dinâmica para criar vetores
e matrizes dinâmicas
Introdução a Programação
Tipos Estruturados de Dados
2
Tópicos da AulaHoje aprenderemos a trabalhar com tipos dedados mais complexos
Tipos Primitivos x Tipos EstruturadosConceito de Tipos EstruturadosImportânciaTipos Estruturados em C (struct)Declaração de structsVariáveis do tipo structOperações com estruturasComando typedefPassando Estruturas para FunçõesEstruturas Aninhadas
3
Tipos Estruturados
C oferece tipos primitivos que servem pararepresentar valores simples
Reais (float, double), inteiros (int), caracter(char)
C oferece também mecanismos para estruturardados complexos nos quais as informações sãocompostas por diversos campos
Tipos Estruturados !
Tipos Estruturados
NomeEndereçoTelefone
IdadeData de Nascimento
Peso Altura
stringstringinteirointeirointeirofloatfloat
Cadastro Pessoal
Agrupa conjunto de tipos de dados distintos sob umúnico nomePodemos criar varios objetos na memória de umdeterminado tipo estruturado
Estruturas ou Registros Nome do tipo estruturado
Membro do tipo estruturado
Tipos Estruturados em C (struct)
NomeEndereçoTelefone
IdadeData de Nascimento
Peso Altura
Cadastro Pessoalstruct cadastro_pessoal {
char nome[50];
char endereço[100];
int telefone;
int idade;
int nascimento;
float peso;
float altura;
};
Forma Geral:
struct nome_do_tipo {
declaração de variável 1 ;
declaração de variável n ;
};
6
Importância de Tipos EstruturadosConsidere um ponto representado por duascoordenadas: x e ySem mecanismos para agrupar as duascoordenadas:
int main() {
float x ;
float y ;
…
}
Não dá para saber que estas variáveis
representam coordenadas de um
ponto
7
Importância de Tipos Estruturados
Uma estrutura em C serve para agrupar diversas variáveis dentro de um único contexto
struct ponto {
float x ;
float y ;
};
8
Declarando Variáveis do Tipo Ponto
A estrutura ponto passa a ser um tipoEntão, podemos declarar uma variável destetipo da seguinte forma:
struct ponto {
float x ;
float y ;
};
int main() {
struct ponto p ;
...
}
A variável é do tipo struct ponto
9
Acessando Membros do Tipo Ponto
Membros de uma estrutura são acessados via o operador de acesso ( “.” )
Para acessar as coordenadas:
p . x = 10.0 ;p . y = 5.0 ;
struct ponto {
float x ;
float y ;
};
int main() {
struct ponto p ;
p.x = 0.0;
p.y = 7.5;
...
}
O nome da variável do tipo struct ponto deve vir antes do “.”
10
Utilizando oTipo Estruturado Ponto
*/ programa que captura e imprime coordenadas*/
#include <stdio.h>
struct ponto {
float x ;
float y ;
} ;
int main (){
struct ponto p ;
printf(“\nDigite as coordenadas do ponto (x,y)”) ;
scanf (“%f %f”, &p.x , &p.y ) ;
printf(“O ponto fornecido foi:(%f,%f)\n”,p.x, p.y);
return 0 ;
} variável p não precisa de parênteses
11
Onde Declarar um Tipo Estruturado?
Geralmente, declara-se um tipo estruturado foradas funções
Escopo da declaração engloba todas as funções nomesmo arquivo fonte
Pode-se, também, declarar tipos estruturadosdentro de funções
Neste caso, escopo do tipo estruturado é na função
12
Declarando oTipo Estruturado Fora das Funções
struct ponto {
float x ;
float y ;
} ;
struct ponto alteraPonto(float x, float y){
struct ponto q;
q.x = x;
q.y = y;
return q;
}
int main (){
struct ponto p ;
printf(“\nDigite as coordenadas do ponto (x,y)”) ;
scanf (“%f %f”, &p.x , &p.y ) ;
p = alteraPonto(8,9);
...
}
Funções podem usar o tipo estruturado
declarado acima
Declarado fora das funções
13
Declarando oTipo Estruturado Dentro de uma Função
void leCoordenadas(float* x, float* y){
struct ponto {
float x ;
float y ;
};
struct ponto q;
scanf (“%f %f”, &q.x , &q.y ) ;
*x = q.x;
*y = q.y;
}
int main (){
struct ponto p ;
printf(“\nDigite as coordenadas do ponto (x,y)”) ;
leCoordenadas(&p.x , &p.y ) ;
...
}
Outra função NÃOenxerga a
declaração do tipo estruturado
Declarado dentro da função
alteraPonto
Errado !
14
Outras Formas de Declarar Tipos Estruturados e Variáveis
Pode-se declarar um tipo estruturado e umavariável deste tipo de diferentes formasstruct ponto {
float x ;
float y ;
} p;
struct {
float x ;
float y ;
} p;
Declara-se tipo e variável numa expressão só
Declara-se tipo SEM NOME e variável numa
expressão só
Cuidado com legibilidade !
15
Inicializando Variáveis de TiposEstruturados
Uma variável de um tipo estruturado pode ser inicializada com uma estrutura com o auxílio do abre-fecha parênteses( “{” e “}” )
struct pessoa {
char nome[60] ;
int idade ;
};
int main() {
struct pessoa p = {“Ana”, 30};
...
}
Inicialização da variável p do tipo struct pessoa
Deve-se inicializar os membros na ordem correta
16
Atribuição de EstruturasA estrutura armazenada por uma variável de um tipo estruturado pode ser atribuída a outra variável deste mesmo tipo estruturado
struct pessoa {
char nome[60] ;
int idade ;
};
int main() {
struct pessoa p1,p2;
p1 = {“Ana”, 30};
p2 = p1;
...
}
Atribuição de uma estrutura para a
variável p1 (Errado)
Atribuição da estrutura contida em p1 para p2
17
Outras Operações com Estruturas
struct ponto {
float x ;
float y ;
};
int main() {
struct ponto p3;
struct ponto p1 = {0.0, 4.5};
struct ponto p2 = {1.0,2.5};
p3 = p1 + p2;
printf(“O x e y do novo ponto é:%f,%f,p3.x,p3.y);
return 0;
}
Não podemos somar estruturas inteiras
Como escrever um programa que imprime a soma das coordenadas de dois pontos?
Errado !
18
Outras Operações com Estruturas
struct ponto {
float x ;
float y ;
};
int main() {
struct ponto p3;
struct ponto p1 = {0.0, 4.5};
struct ponto p2 = {1.0,2.5};
p3.x = p1.x + p2.x;
p3.y = p1.y + p2.y;
printf(“O x e y do novo ponto é:%f,%f”,p3.x,p3.y);
return 0;
}
Temos que somar membro a membro
Como escrever um programa que imprime a soma das coordenadas de dois pontos?
Certo !
19
Usando typedef
O comando typedef permite criar novosnomes para tipos existentes
Criação de sinônimos para os nomes de tiposÉ útil para abreviar nomes de tipos ou tiposcomplexos
Forma Geral:
typedef tipo_existente sinonimo;
20
Usando typedef
struct pessoa {
char nome[60] ;
int idade ;
};
typedef struct pessoa Pessoa;
int main() {
Pessoa p = {“Ana”, 30};
...
}
Tipo existente
Novo nome
Simplificou declaração do tipo de variável
Após a definição de novos nomes para os tipos, pode-se declarar variáveis usando estes nomes
21
Usando typedef
Podemos combinar typedef com declaraçãodo tipo estruturado
typedef struct pessoa {
char nome[60] ;
int idade ;
} Pessoa;
int main() {
Pessoa p = {“Ana”, 30};
...
} Criação de tipo e criação de sinônimo
22
Passagem de Estruturas para Funções
Considere a função abaixo:
void imprimePonto ( struct ponto p ){
printf(“O ponto fornecido foi:(%f,%f)\n”,p.x,p.y);
}
Assim como podemos passar tipos primitivos comoargumentos para uma função, podemos passarestruturas
23
Passagem de Estruturas para Funções
*/ programa que captura e imprime coordenadas*/
#include <stdio.h>
typedef struct ponto {
float x ;
float y ;
} Ponto;
void imprimePonto(Ponto q) {
printf(“O ponto fornecido foi:(%f,%f)\n”,q.x, q.y);
int main (){
Ponto p ;
printf(“\nDigite as coordenadas do ponto (x,y)”) ;
scanf (“%f %f”, &p.x , &p.y ) ;
imprimePonto(p);
return 0 ;
}
Passa a estrutura armazenada em pcomo argumento
24
Retornando Estruturas
Considere a função abaixo:struct ponto alteraPonto(float x, float y ){
struct ponto q;
q.x = x;
q.y = y;
return q;
}
Assim como uma função pode retornar um valor de umtipos primitivo, uma função pode retornar umaestrutura
25
Retornando Estruturastypedef struct ponto {
float x ;
float y ;
} Ponto;
Ponto alteraPonto(float x, float y){
Ponto q;
q.x = x;
q.y = y;
return q;
}
int main (){
Ponto p ;
printf(“\nDigite as coordenadas do ponto (x,y)”) ;
scanf (“%f %f”, &p.x , &p.y ) ;
p = alteraPonto(8,9);
...
}
Variável p recebe a estrutura
retornada por alteraPonto
26
Tipos Estruturados Mais Complexos
Aninhamento de estruturasMembros de uma estrutura podem ser outrasestruturas previamente definidasExemplo:
typedef struct ponto {
float x ;
float y ;
} Ponto;
typedef struct circulo {
Ponto centro;
float raio;
} Circulo;
Tipo estruturado Circulo tem como um dos membros um
Ponto
27
Usando os Tipos Ponto e Circulo
float distancia ( Ponto p , Ponto q ){
float d = sqrt((q.x – p.x )*(q.x – p.x)+
(q.y – p.y)*(q.y – p.y)) ;
return d ;
}
int interior ( Circulo c , Ponto p ){
float d = distancia ( c.centro , p ) ;
return ( d <= c.raio ) ;
}
Função que calcula a distância entre 2 pontos
2
12
2
12 )()( yyxxd
Função que determina se um ponto está no círculo
Passa para distancia uma estrutura Ponto que é membro da estrutura
Circulo
28
Resumindo …
Tipos EstruturadosStructsOperações com EstruturasComando typedefPassando Estruturas para FunçõesEstruturas Aninhadas
Introdução a Programação
Ponteiros para Estruturas,
Outros Tipos de Estruturas
2
Tópicos da AulaHoje aprenderemos a trabalhar com ponteirospara estruturas
Ponteiros para estruturasAlocação dinâmica de estruturasPassagem por referência de estruturasVetores de estruturas x Vetores de ponteiros paraestruturas
Aprenderemos também que existe outrosformas de tipos estruturados em C
Tipo União (Union)Tipos Enumerados (Enum)
3
Usando Ponteiro para EstruturasPodemos ter variáveis do tipo ponteiro paraestruturas
struct ponto {
float x ;
float y ;
};
int main() {
struct ponto q;
struct ponto* p ;
p = &q
...
}
A variável p armazena o
endereço de uma estrutura
Acessando os Membros Através do Ponteiro
Os membros de uma estrutura são acessadosusando seu nome seguido do operador ponto
Podemos acessar os membros do mesmo jeito utilizando ponteiros?
struct ponto {
float x ;
float y ;
};
int main() {
struct ponto q;
struct ponto* p = &q;
p.x = 7.0;
...
}
Não !
Não podemos acessar membros de uma estrutura via ponteiro desta
forma
5
Para acessar os membros de uma estrutura por meio de um ponteiro, existem 2 formas:
Usando o operador * seguido da variável dentro de parênteses
Precisa de parênteses para variável p, senão o compilador entenderia como*(p.x)- Errado!
Acessando os Membros Através do Ponteiro
(*p).x = 7.0;
Usando o operador ->
p->x = 7.0;
6
A alocação dinâmica de estruturas é feita de forma similar a como é feito com tipos primitivos
Alocação Dinâmica de Estruturas
struct pessoa {
char nome[32] ;
int idade ;
double peso;
};
int main() {
struct pessoa* p;
p = (struct pessoa*) malloc(sizeof(struct pessoa));
strcpy(p->nome,”Ana”);
p->idade = 30;
...
}
Aloca espaço na memória para uma estrutura que contém um vetor de 32 caracteres (32
bytes), um inteiro (4 bytes) e um double (8 bytes)
7
Alocação Dinâmica de Estruturas
struct paciente {
float* vTemperatura ;
struct pessoa individuo;
};
typedef struct paciente Paciente;
int main() {
Paciente* p;
p = (Paciente*) malloc(sizeof(Paciente));
p->individuo.idade = 30;
strcpy(p->individuo.nome,”Ana”);
p->vTemperatura = (float*) malloc(5 * sizeof(float));
p->vTemperatura[0] = 37.5;
} Aloca espaço na memória para uma estrutura que contém um ponteiro para float (4 bytes), e
uma estrutura pessoa (44 bytes)
Aloca espaço na memória para um vetor
com 5 inteiros
8
Passagem de Estruturas para Funções
Cópia da estrutura na pilha não é eficienteÉ mais conveniente passar apenas o ponteiro daestrutura
void captura ( struct ponto p ) {
printf( “Digite as coordenadas do ponto (x,y):” ) ;
scanf ( “%f %f ”, &p.x, &p.y ) ;
}
int main() {
struct ponto p;
captura(p);
...
}
Valores da estrutura não podem ser modificados
9
Uma função para imprimir as coordenadas
Uma função para ler as coordenadasvoid captura ( struct ponto *p ) {
printf( “Digite as coordenadas do ponto (x,y):” ) ;
scanf ( “%f %f ”, &p->x, &p->y ) ;
}
Passagem de Ponteiros para Estruturas para Funções
void imprime ( struct ponto* p ){
printf(“O ponto fornecido foi:(%f,%f)\n”,p->x,p->y);
}
Permite modificar o valor da variável p
10
struct ponto {
float x ;
float y ;
} ;
void imprime ( struct ponto* p ){
printf(“O ponto fornecido foi:(%f,%f)\n”,p->x,p->y);
}
void captura ( struct ponto* p ) {
printf( “Digite as coordenadas do ponto (x,y):” ) ;
scanf ( “%f %f ”, &p->x, &p->y ) ;
}
int main (){
struct ponto p ;
captura(&p);
imprime(&p);
}
Passagem de Ponteiros para Estruturas para Funções
11
Vetores de EstruturasPodemos utilizar vetores de estruturasConsidere o cálculo de um centro geométrico de umconjunto de pontos
n
y
yn
x
x
n
i
i
n
i
i 11 e
struct ponto centrogeometrico(int n,struct ponto* v){
int i ;
struct ponto p = { 0.0 , 0.0 } ;
for ( i = 0 ; i < n ; i++ ){
p.x += v[i].x ;
p.y += v[i].y ;
}
p.x /= n ;p.y /= n ;
return p ;
}
Endereço inicial do vetor de pontos
Acessando coordenada x do i-ésimo ponto do vetor v
12
Vetores de Ponteiros para EstruturasSão úteis quando temos de tratar um conjuntode elementos complexos
Exemplo: Vetores de alunos
Matricula: número inteiro ;Nome: cadeia com 80 caracteres ;Endereço: cadeia com 120 caracteres ;Telefone: cadeia com 20 caracteres ;
Em C podemos representar aluno:
struct aluno {
int mat ;
char nome [81] ;
char end [121] ;
char tel [ 21 ] ; } ;
typedef struct aluno ALUNO ;
13
Se usarmos um vetor com um número máximode alunos:
#define MAX 100
ALUNO tab[MAX];
Tipo ALUNO ocupa pelo menos 227(=4+81+121+21)bytesSe for usado um número de alunos inferior aomáximo estimado, a declaração de um vetor dessaestrutura representa um desperdício significativo dememóriaUma solução é:
Vetores de Ponteiros para Estruturas
#define MAX 100
ALUNO* tab[MAX];
14
#define MAX 100
struct aluno {
int mat ;
char nome [81];
char end [121] ;
char tel [21] ;
} ;
typedef struct aluno ALUNO;
ALUNO* tab[MAX];
void inicializa (int n,ALUNO** tab){
int i ;
for(i=0 ;i< n;i++)
tab [i] = NULL ;
}
Usando Vetores de Ponteiros para Estruturas
Todas as posições do vetor de ponteiros guardam endereços nulos
15
void preenche(int n,ALUNO **tab ){
int i;
for ( i = 0; tab[i]!= NULL && i < n; i++ );
if (i < n) {
tab[i]= ( ALUNO*) malloc (sizeof(ALUNO));
printf (“\nEntre com a matricula:”);
scanf (“%d”, &tab[i]->mat) ;
printf (“\nEntre com o nome:”) ;
scanf (“%80[^\n]”, tab[i]->nome) ;
printf (“\nEntre com o endereco:”) ;
scanf (“%120[^\n]”, tab[i]->end) ;
printf (“\nEntre com o telefone:”) ;
scanf (“%20[^\n]”, tab[i]->tel) ;
} else {
printf(“Vetor cheio\n”);
}
}
Usando Vetores de Ponteiros para Estruturas
Espaço alocado para um novo aluno e endereço é armazenado no vetor
16
void retira(int n,ALUNO** tab,int i ) {
if ( i >= 0 && i < n) {
if (tab[i] != NULL) {
free(tab[i]);
tab[i] = NULL;
}
} else {
printf(“Indice fora do limite do vetor\n”);
}
}
Usando Vetores de Ponteiros para Estruturas
17
void imprime(int n,ALUNO** tab,int i ){
if ( i >= 0 && i < n) {
if (tab[i]!= NULL){
printf (“Matricula: %d\n”,tab[i]->mat);
printf (“Nome: %s\n”,tab[i]->nome);
printf (“Endereço: %s\n”,tab[i]->end);
printf (“Telefone: %s\n”,tab[i]->tel);
}
} else {
printf(“Indice fora do limite do vetor\n”);
}
}
Usando Vetores de Ponteiros para Estruturas
18
void imprime_tudo(int n,ALUNO** tab){
int i;
for(i = 0; i < n; i++)
imprime(n,tab,i);
}
Usando Vetores de Ponteiros para Estruturas
19
int main(){
ALUNO *tab[10];
inicializa(10,tab);
preenche(10,tab);
preenche(10,tab);
preenche(10,tab);
imprime_tudo(10,tab);
retira(10,tab,0);
retira(10,tab,1);
retira(10,tab,2);
return 0 ;
}
Usando Vetores de Ponteiros para Estruturas
20
Tipos Estruturado enum
O tipo estruturado enum (enumeração) consistede um conjunto de constantes inteiras, em quecada uma delas é representada por um nomeUma enumeração é uma forma mais elegantede organizar constantes
Dá-se um contexto ao conjunto de constantesUma variável de um tipo enumerado pode assumirqualquer valor listado na enumeração
21
Definindo uma enum
Forma Geral :
enum dias_semana {
domingo, segunda, terca, quarta,
quinta, sexta, sabado };
Exemplo:
enum nome_do_tipo {
constante1, constante2,constante n
};
22
Valores das Constantes Definidas em uma enum
Internamente, o compilador atribui valoresinteiros a cada constante seguindo a ordem emque elas são definidas, começando de 0, depois1, etc
Portanto:enum dias_semana {
domingo, segunda, terca, quarta,
quinta, sexta, sabado };
sabado == 6
segunda == 1
domingo == 0
23
Valores das Constantes Definidas em uma enum
No entanto, o programador pode atribuirdiretamente os valores inteiros desejados
enum dias_semana {
domingo = 1, segunda, terca, quarta,
quinta, sexta, sabado };
sabado == 7
segunda == 2
domingo == 1
24
Usando enums
enum dias_semana {
domingo, segunda, terca, quarta, quinta, sexta,
sabado
};
typedef enum dias_semana DIAS;
int dia_util(DIAS dia) {
int ehUtil = 0;
if (dia >= segunda && dia <= sexta) {
ehUtil = 1;
}
return ehUtil;
} Função verifica se um dia passado como
argumento é útil ou não
25
Tipo Estruturado UnionAssim como uma struct, uma union agrupa umconjunto de tipos de dados (que podem ser distintos)sob um único nome
Diferentemente de uma struct, uma union
armazena valores heterogêneos em um mesmo espaçode memória
Apenas um único membro de uma union pode estararmazenado em um determinado instante
A atribuição a um membro da union sobrescreve o valoranteriormente atribuído a qualquer outro membro
Utiliza-se em casos onde se quer otimizar uso de memória
26
Definindo uma Union
Forma Geral :
union numero {
char str[32];
int inteiro ;
double real;
};
Exemplo:
union nome_do_tipo {
declaração de variável 1 ;
declaração de variável n ;
};
27
Union x Structunion numero {
char str[32];
int inteiro ;
double real;
};
struct pessoa {
char nome[32];
int idade ;
double peso;
};
4 bytes
nome -32 bytes
idade -4 bytespeso - 8 bytes
44 bytes na memória (soma
do tamanho das variáveis)
str, inteiro
e real -32 bytes
32 bytes na memória (maior variável - str)
28
Manipulando uma Union
Declaração de variável
union numero num;
Acesso aos membros de uma unionDiretamente ( Operador “ . ” ):
Via um ponteiro (Operador “ -> ” ):
num.inteiro = 60;
union numero num;
union numero* pnum = #
pnum->real = 60.5;
29
Cuidado ao Acessar Membros de Unions
union numero {
char str[32];
int inteiro ;
double real;
};
typedef union numero NUMERO;
int main(){
NUMERO num;
strcpy(num.str,"Joao");
num.real = 45.7;
num.inteiro = 70;
printf("num.inteiro = %d\n",num.inteiro);
printf("num.real = %lf\n",num.real);
printf(“num.str = %s\n",num.str);
return 0;
}
num.inteiro = 70
num.real = ?????
num.str = ??????
O que será impresso nas 3 linhas da área demarcada?
Comportamento imprevisível!
Introdução a Programação
Arquivos
2
Tópicos da Aula
Hoje aprenderemos a persistir dadosConceito de arquivosImportância de persistênciaModos de acesso de arquivos em COperações em arquivosFunções de leitura/escrita em modo binário
2
3
Arquivos
Um arquivo representa um elemento deinformação armazenado em memóriasecundária (disco)
Características:Informações são persistidasAtribui-se nomes aos elementos de informação(arquivos e diretórios),em vez de endereços dememóriaAcesso às informações são mais lentos
4
Persistência... pra quê?
Não perder os dados no fim da execução deum programa
Memória temporária(volatil)principalMais rápida e cara
Memória permanentesecundáriamais lenta e barata
Para melhorar velocidade de acesso, a cadaacesso, transfere-se trechos maiores doarquivo para espaços da memória (buffers)
4
55
Modos de Acesso a Arquivos em C
Dois modos de acesso:Texto e Binário
Arquivo Texto:
0 1 2 3 4
Arquivo Binario:
0 1 2 3 4
Informação persistidaString
Inteiros
66
Modo Texto
É interpretado como uma seqüência decaracteres agrupadas em linhasLinhas são separadas por um caractere denova linha
Vantagens:Pode ser lido facilmente por uma pessoaEditado por editores de texto convencionais
DesvantagensCodificação dos caracteres pode variar (ASCII, UTF-8, ISSO-8859, etc)Arquivos tendem a ser maiores (todas os dados sãoconvertidos para caracteres)
77
Modo Binário
Dados são armazenados da mesma forma quesão armazenados na memória principal
Vantagens:Facilmente interpretados por programasMaior velocidade de manipulaçãoArquivos são, geralmente, mais compactos
Desvantagens:Difícil de serem entendidos por pessoasDependentes da máquina onde foram gerados
88
Operações em Arquivos
AberturaSistema Operacional (SO) encontra arquivo pelonomePrepara buffer na memória
LeituraSO recupera trecho solicitado do arquivoParte ou todo trecho pode vir do buffer
99
Operações em Arquivos
EscritaSO altera conteúdo do arquivoAlteração é feita primeiro no buffer para depois sertransferida para o disco
FechamentoInformação do buffer é atualizada no discoÁrea do buffer utilizada na memória é liberada
1010
Abertura de Arquivos em C
Operações de manipulação de arquivos em Cse encontram, geralmente, na stdio.hFunção de Abertura
Nome
Nome do arquivoFILE
Tipo estruturado que representa uma abstração doarquivo
modo
r - Indica leituraw – Indica escritaa – Indica escrita ao final do existentet – Indica modo textob – Indica modo binário
FILE* fopen(char* nome,char* modo);
11
Abrindo arquivos
FILE *fptr; /* ponteiro para arquivo */
fptr = fopen(“arqtext.txt”, “w”);
nome do arquivo
Tipo de abertura
“r” Abrir arquivo texto para leitura. O arquivo deve estar presente no disco
“w” Abrir arquivo texto para gravação. Se o arquivo existir ele será destruído e reinicializado. Se não existir, será criado
“a” Abrir um arquivo texto para gravação. Os dados serãoadicionados no fim do arquivo existente, ou cria um novo
Modo t pode ser omitido
12
Abrindo arquivos
FILE *fptr; /* ponteiro para arquivo */
fptr = fopen(“arqtext.txt”, “w+”);
Tipo de abertura
“r+” Abrir arquivo texto para leitura e gravação. O arquivo deve existir e pode ser atualizado.
“w+” Abrir arquivo texto para leitura e gravação. Se o arquivo existir ele será destruído e reinicializado. Se não existir, será criado.
“a+” Abrir um arquivo texto para atualização e para adicionar dados no fim do arquivo existente, ou cria um novo
13
Abrindo arquivos
FILE *fptr; /* ponteiro para arquivo */
fptr = fopen(“arqtext.txt”, “wb”);
Tipo de abertura“rb” Abrir arquivo binário para leitura. O arquivo deve
estar presente no disco“wb” Abrir arquivo binário para gravação. Se o arquivo existir
ele será destruído e reinicializado. Se não existir, serácriado
“ab” Abrir um arquivo binário para gravação. Os dados serãoadicionados no fim do arquivo existente, ou cria um novo
14
Abrindo arquivos
FILE *fptr; /* ponteiro para arquivo */
fptr = fopen(“arqtext.txt”, “wb+”);
Tipo de abertura“rb+” Abrir arquivo binário para leitura e gravação. O
arquivo deve existir e pode ser atualizado.“wb+” Abrir arquivo binário para leitura e gravação. Se o
arquivo existir ele será destruído e reinicializado. Se não existir, será criado.
“ab+” Abrir um arquivo binário para atualização e para adicionar dados no fim do arquivo existente, ou cria umnovo
1515
Observações sobre Abertura de
Arquivos em C
SO mantém um “cursor” que indica a posiçãode trabalho no arquivoSe não for possível a abertura, a função fopenretorna NULL
1616
Fechamento de Arquivos
Após leitura/escrita do arquivo, devemos fechá-loFunção de fechamento
Retorna 0 se o arquivo foi fechado com sucesso
int fclose(FILE* fp);
1717
Leitura (Modo Binário)
p é o endereço de memória em que vai ser armazenado oque for lidotam é o tamanho em bytes de cada elemento lidonelem é o número de elementos de tamanho tam lidosRetorna a quantidade de bytes lidos com sucesso (tam *nelem)
int fread(void* p,int tam,int nelem,FILE* fp);
1818
Escrita (Modo Binário)
p é o endereço de memória cujo conteúdo deseja-se salvarem arquivotam é o tamanho em bytes de cada elemento escritonelem é o número de elementos de tamanho tam escritosRetorna a quantidade de bytes escritos com sucesso (tam *nelem)
int fwrite(void* p,int tam,int nelem,FILE* fp);
1919
Verificando o Final do Arquivo
Em operações de leitura do arquivo, é comumverificarmos se o final do arquivo já foi atingidoFunção de verificação de fim de arquivo
Retorna 1 se o fim do arquivo foi atingidoRetorna 0 caso contrário
int feof(FILE* fp);
2020
Usando fwrite na Escrita
#include <stdio.h>
typedef struct ponto {
float x,y;
} Ponto;
int main () {
int i,n;
Ponto p;
FILE* fp = fopen(“arquivo”, “wb”);
if (fp == NULL) {
printf(“Erro na abertura do arquivo.\n”);
exit(1);
}
printf(“Digite numero de pontos a gravar\n”);
scanf(“%d”,&n);
for (i = 0; i < n; i++) {
scanf(“%d %d”,&p.x,&p.y);
fwrite(&p, sizeof(Ponto), 1, fp);
}
fclose(fp);
}
Programa que salva n pontos em um arquivo binário
Gravando cada ponto entrado pelo usuario usando fwrite
2121
Usando fread na Leitura
#include <stdio.h>
int main () {
int i,n;
Ponto p;
FILE* fp = fopen(“arquivo”, “rb”);
if (fp == NULL) {
printf(“Erro na abertura do arquivo.\n”);
exit(1);
}
while(!feof(fp)){
fread(&p, sizeof(Ponto), 1, fp);
printf(“Ponto lido: (%d,%d)”,p.x,p.y);
}
fclose(fp);
}
Programa que lê todos os pontos armazenados em um arquivo binário
Lê cada ponto e guarda na variável p
Testa se o fim do arquivo já foi atingido
2222
Leitura/Escrita de Blocos de Dados
As funções fread/fwrite permitem ler/escrevergrandes blocos de dados em um arquivo
Um dos parâmetros indica qual é a quantidade dedados de um determinado tipo a ser lido/escrito
Portanto podem ser úteis para ler/escreverestruturas ou vetores em um arquivo numaúnica chamada de função
2323
Usando fwrite na Escrita
#include <stdio.h>
typedef struct ponto {
float x,y;
} Ponto;
void salva (char* arquivo, int n, Ponto* vet) {
FILE* fp = fopen(arquivo, “wb”);
if (fp == NULL) {
printf(“Erro na abertura do arquivo.\n”);
exit(1);
}
fwrite(vet, sizeof(Ponto), n, fp);
fclose(fp);
} Função que salva um vetor de pontos em um arquivo binário
Número de pontos do vetor
2424
void carrega (char* arquivo, int n, Ponto* vet) {
FILE* fp = fopen (arquivo, “rb”);
if (fp == NULL) {
printf(“Erro na abetura do arquivo.\n”);
exit(1);
}
fread (vet, sizeof(Ponto), n, fp);
fclose(fp);
}
Função que recupera um vetor de pontos de um arquivo binário
Usando fread na Leitura
2525
Usando as Funções Definidas
Anteriormenteint main() {
Ponto *entrada, *saida; int nPontos, cont,pos ;
FILE *arquivo;
char nome_arquivo[121];
printf(“Digite o nome do arquivo:\n”);
scanf(“%120s”,nome_arquivo);
printf(“\nDigite o número de pontos:\n”);
scanf(“%d”,&nPontos);
entrada = (Ponto *) malloc(nPontos*sizeof(Ponto));
for (cont = 0; cont < nPontos;cont++) {
printf(“Digite coordenadas x,y:\n”);
scanf(“%f%f”,&entrada[cont].x,&entrada[cont].y);
}
/* continua */ Programa que salva e recupera um vetor de pontos em um arquivo binário
2626
salva(nome_arquivo, nPontos, entrada);
do {
printf(“Digite agora a posição do ponto que
deseja ver: \n”);
scanf(“%d”,&pos);
} while (pos > nPontos || pos<=0 );
saida = (Ponto *) malloc (nPontos*sizeof(Ponto));
carrega(nome_arquivo, nPontos, saida);
printf(“O ponto na posicao %d é {%f,%f}\n”, pos,
saida[pos-1].x, saida[pos-1].y);
}
Usando as Funções Definidas
Anteriormente
Gravando os pontos no arquivo
Lendo os pontos do arquivo
Introdução a Programação
Manipulando Arquivos em
Modo Texto
2
Tópicos da Aula
Hoje aprenderemos funções de manipulaçãode arquivos texto
Funções de leitura em modo textoFunções de escrita em modo textoConsiderações sobre a utilização de operaçõesde leitura/escrita em modo texto e binário
Aprenderemos também algumas funções queservem para posicionar o cursor no arquivo
Exemplos de uso
2
33
Leitura (Modo Texto)
A cada operação de leitura, os dadoscorrespondentes são transferidos para amemória e o cursor avança e aponta para opróximo dadoExiste em C a função fscanf para leituraformatada de dados de um arquivo modo texto
Similar a scanfLê de um arquivo passado como parâmetro em vezde somente da entrada padrão (teclado)Pode ler também da entrada padrão (arquivo stdin)
44
Leitura com fscanf
Retorna número de dados lidos com sucessofp é o ponteiro para o arquivoformato equivale aos códigos de formatação (iguais aodo scanf)end_variaveis corresponde a lista de endereços devariáveis que armazenarão os dados lidos do arquivo
int fscanf(FILE* fp, char* formato,end_variaveis)
55
Leitura com fscanf
A cada operação de leitura, os dadoscorrespondentes são convertidos de caracterespara o tipo (formato) especificado em fscanf
Portanto, arquivo deve ter sido previamentegravado em modo texto
Se gravado em modo binário, a função tenta mapearos dados lidos para caracteres para depois fazer aconversão para o tipo especificado
66
Usando fscanf para Leitura (Modo
Texto)
#include <stdio.h>
int main() {
FILE *fp;
char primeiraPalavra[121];
fp = fopen(“teste.txt”,”r”);
if (fp == NULL) {
printf(“Impossível abrir arquivo”);
exit(1);
}
fscanf(fp, “%120s”,primeiraPalavra);
printf(“A primeira palavra do arquivo teste.txt
é: %s\n”,primeiraPalavra);
fclose(fp);
return 0;
}
Lê uma string do arquivo apontado por fp de até 120 caracteres e armazena
em primeiraPalavra
77
Constante EOF
A constante (simbólica) EOF indica o fim dearquivo
Definida no arquivo stdio.h
Ela NÃO é um caracterÉ um inteiro que indica fim de arquivoGeralmente um valor negativo
NÃO é um valor presente no arquivoÉ um valor retornado por funções de leituraindicando fim de arquivo ou erro de leitura
88
Outras Funções de Leitura (Modo Texto)
Lê um caractere de um arquivoRetorna o código do caractere lidoRetorna EOF se fim do arquivo for alcançado
s é a cadeia de caracteres que armazenará o que for lidon é o número máximo de caracteres a serem lidosLê uma seqüencia de caracteres até que ‘\n’ sejaencontrado ou que n caracteres tenham sido lidosRetorna ponteiro para a cadeia s
int fgetc(FILE* fp);
char* fgets(char* s, int n, FILE* fp);
99
Usando fgetc para a Leitura
#include <stdio.h>
int main() {
FILE *fp; int c;int nCaracteres = 0, nLinhas = 0;
fp = fopen(“teste.txt”,”r”);
if (fp == NULL) {
printf(“Impossível abrir arquivo”);
exit(1);
}
while ((c = fgetc(fp)) != EOF) {
if (c == „\n‟) nLinhas++;
else nCaracteres++;
}
printf(“Caracteres:%d,Linhas:%d\n”,nCaracteres,nLinhas);
fclose(fp);
return 0;
}
Programa conta número de caracteres e conta o número de
linhas de um arquivo
Lê caractere e ainda verifica se chegou no
fim do arquivo
1010
int main() {
FILE *fp;
int achou = linhaOcorrencia = 0;
char palavra[121], linha [121];
printf (“Digite a palavra:\n”);
scanf(“ %120[^\n]”,palavra);
fp = fopen(“teste.txt”,”r”);
if (fp == NULL) {
printf(“Impossível abrir arquivo”);exit(1);
}
while (fgets(linha,121,fp) != NULL && !achou) {
linhaOcorrencia++;
if (strstr(linha,palavra) != NULL)
achou = 1;
}
fclose(fp);
printf(“Ocorrências de %s = %d\n”, palavra,nOcorrencias);
}
Programa informa linha da ocorrência de uma palavra em um arquivo com linhas (maximo 120 caracteres)
Usando fgets para a Leitura
Lê uma linha e armazena em linha
Utiliza função strstr de string.h para saber se palavra é substring de linha
1111
Escrita (Modo Texto)
A cada operação de escrita, os dados sãogravados na memória e posteriormente nodisco, e o cursor avança apontando para aproxima posição do arquivo:Existe em C a função fprintf para escritaformatada de dados em um arquivo modo texto
Similar a printfEscreve em um arquivo passado como parâmetroem vez de somente na saída padrão (monitor)Pode escrever também na saída padrão (arquivostdout)
1212
Escrita com fprintf
Retorna número de dados escritos com sucessofp é o ponteiro para o arquivoformato equivale aos códigos de formatação (iguais aodo printf)variaveis corresponde a lista de variáveis, cujosconteúdos serão escritos no arquivo
int fprintf(FILE* fp, char* formato,variaveis)
1313
Escrita com fprintf
A cada operação de escrita, os dadoscorrespondentes são convertidos do tipo(formato) especificado em fprintf paracaracteresSe arquivo aberto em modo binário , dados sãogravados também como caracteres
1414
#include <stdio.h>
int main() {
FILE *fp;
char palavra[121];
fp = fopen(“teste.txt”,”w”);
if (fp == NULL) {
printf(“Impossível abrir arquivo”);
exit(1);
}
printf (“Digite a palavra:\n”);
scanf(“ %120[^\n]”,palavra);
fprintf(fp,“%s\n”,palavra);
fclose(fp);
return 0;
}
Usando fprintf para Escrita (Modo
Texto)Programa escreve uma palavra de no
máximo 120 caracteres em um arquivo
1515
Outras Funções de Escrita (Modo Texto)
Escreve um caractere em um arquivoRetorna o código do caractere escrito
s é a cadeia de caracteres que será escritaRetorna ponteiro para a cadeia s
int fputc(FILE* fp, char c);
char* fputs(char* s,FILE* fp);
1616
int main() {
FILE *e; FILE *s;
int caractere; char nome_entrada[121];
printf (“Digite o nome do arquivo de entrada:\n”);
scanf(“%120s”, nome_entrada);
e = fopen(nome_entrada,”r”);
if (e== NULL) {
printf(“Impossível abrir arquivo de entrada”);exit(1);
}
s = fopen(strcat(nome_entrada,”_maiuscula”),”w”);
if (s== NULL) {
printf(“Impossível abrir arquivo de saida”);exit(1);
}
while ((caractere = fgetc(e)) != EOF)
fputc(toupper(caractere),s);
fputs(“\nArquivo Convertido!”,s);
fclose(e); fclose(s);
return 0;}
Programa lê um arquivo e gera outro com todas as letras convertidas para maiusculas
Usando fputs e fputc para Escrita
Usuário fornece o nome do arquivo
Converte caractere a caractere e escreve no
arquivo
1717
Operações de Leitura/Escrita
(Modo Texto x Modo Binário)
As operações de leitura/escrita em modo textopermitem uma visualização melhor do resultadoPara operações que envolvem estruturas ouvetores, operações em modo binário sãomenos trabalhosasConsidere a estrurura abaixo:
struct aluno {
char nome [60];
int mat;
char sexo;
};
1818
int main() {
FILE *arq;
struct aluno aluno1, copia;
strcpy(aluno1.nome,”Jose”);
aluno1.mat = 1;
aluno1.sexo = „M‟;
arq = fopen(“arquivoAluno1.txt”,”w+”);
if (arq== NULL) {
printf(“Impossível abrir arquivo de entrada”);exit(1);
}
fprintf(arq,“%s\n%d\n%c”,aluno1.nome,aluno1.mat,aluno1.sexo);
rewind(arq);
fscanf(arq,"%s %d %c", copia.nome,&copia.mat,&copia.sexo);
return 0;
}
Usando Operações de Leitura/Escrita
(Modo Texto)
Escreve membro a membro da estrutura
Lê membro a membro da estrutura
Programa escreve e lê uma estrutura em/de um arquivo
Volta para inicio do arquivo
1919
int main() {
FILE *arq;
struct aluno aluno1, copia;
strcpy(aluno1.nome,”Jose”);
aluno1.mat = 1;
aluno1.sexo = „M‟;
arq = fopen(“arquivoAluno1.bin”,”wb+”);
if (arq== NULL) {
printf(“Impossível abrir arquivo de entrada”);
exit(1);
}
fwrite(&aluno1,sizeof(Aluno),1,arq);
rewind(arq);
fread(&copia,sizeof(Aluno),1,arq);
return 0;
}
Usando Operações de Leitura/Escrita
(Modo Binário)
Escreve toda a estrutura
Lê toda a estrutura
Programa escreve e lê uma estrutura em/de um arquivo
2020
Funções Utilitárias
Retorna a posição atual do cursor do arquivoCorresponde a distancia em bytes em relação ao começodo arquivo
long ftell(FILE* fp);
Devem ser utilizadas com cautela em arquivos no modotexto, pois nem sempre o posicionamento do cursor vaiser o desejado
Certas plataformas podem colocar caracteres de formataçãonão visíveis que podem alterar o tamanho do arquivo (númerode bytes)
2121
Funções Utilitárias
Utilizada para posicionamento do cursor em um arquivodist é o número de bytes em relação a origemorigem é uma posição do cursor do arquivo em bytes(SEEK_CUR – posição corrente; SEEK_SET – início doarquivo; SEEK_END – final do arquivo)Retorna a nova posição do cursor
long fseek(FILE* fp,long dist,int origem);
void rewind(FILE* fp);
Utilizada para posicionamento do cursor no início doarquivo
2222
Funções Utilitárias
Ponto le_ponto (FILE* fp, int i) {
Ponto p;
fseek (fp, i*sizeof(Ponto), SEEK_SET);
fread(&p, sizeof(Ponto), 1, fp);
return p;
}
int tamanho_arquivo (FILE *fp) {
int tamanho;
fseek (fp, 0, SEEK_END);
tamanho =ftell (fp);
return tamanho;
}
Função que recupera o i-ésimo ponto armazenado em um arquivo
Função que retorna o tamanho do arquivo em bytes
23
Resumindo ...
Funções de leitura em modo textofscanffgetsfgetc
Funções de escrita em modo textofprintffputsfputc
Quando utilizar operações de leitura/escrita em modotexto e binárioPosicionamento dos cursores em arquivos
23
Introdução a Programação
Listas Encadeadas
Tópicos da Aula
Hoje aprenderemos que existem, além de
vetores, estruturas de dados dinâmicas que
podem armazenar coleções de dados
Estruturas Dinâmicas e Vetores
Conceito de listas encadeadas
Listas Encadeadas x Vetores
Funções de manipulação de listas encadeadas
Variações de listas encadeadas
2
3
Vetores
Declaração de vetor implica na especificação de seu
tamanho
Não se pode aumentar ou diminuir tamanho
Outra alternativa no uso de vetores é alocar
dinamicamente o espaço necessário e guardar
endereço inicial do vetor
Porém, depois de determinado o tamanho do vetor,
não podemos liberar posição de memória arbitrária
Possível desperdício ou falta de memória!
4
Estruturas Dinâmicas
Uma estrutura de dado dinâmica consiste em
uma estrutura que pode aumentar ou diminuir
de tamanho de acordo com a necessidade da
aplicação (do programador)
Evita desperdício e/ou falta de memória
Programador é encarregado de requisitar e
liberar espaços de memória explicitamente
Uso de alocação dinâmica
Requer mais esforço por parte do programador!
5
Listas Encadeadas
Uma lista encadeada é uma estrutura dinâmica que
pode ser utilizada para armazenar um conjunto de
dados
Junto a cada elemento deve-se armazenar o
endereço para o próximo elemento (elementos
encadeados)
Elemento + ponteiro = nó da lista
Diferentemente de vetores, elementos geralmente não são
armazenados em espaços contíguos de memória
Caso não exista próximo elemento, o ponteiro para o
próximo elemento é NULL
6
Listas Encadeadas
Para cada novo elemento inserido na lista, aloca-se
um espaço de memória para armazená-lo
Para remover elemento deve-se liberar o endereço
de memória reservado para armazenar o elemento
O acesso aos elementos é sempre seqüencial
Não se pode garantir que os elementos ocuparão um
espaço de memória contíguo (não se pode localizar
elementos com base em um deslocamento constante)
7
Listas Encadeadas x Vetores
Listas Encadeadas
+ Uso eficiente da memória
- Complexidade de manipulação da estrutura
- Informação deve ser guardada em uma estrutura
que guarda também um endereço (requer mais
memoria por informação armazenada)
Vetores
+Simplicidade no acesso (manipulação) aos
elementos da estrutura
- Desperdício ou falta de memória
- Menor Flexibilidade
8
Representação de Listas Encadeadas
info1
primeiro
struct lista {
int info ; /* info pode ser de qualquer tipo */
struct lista* prox;
} ;
typedef struct lista Lista ;
p
r
o
x
info2
p
r
o
x
info3
Informação armazenada no nó da
lista
Armazena o endereço do próximo nó
Armazena endereço
nulo
fim
9
Representando Listas Encadeadas na
Memória
info3
NULL
info2
112
124
info1100
104
108
112
116
120
124
128
Memória
Lista* inicio;
inicio
100
info
prox
info1
inicio
p
r
o
x
info2
p
r
o
x
info3
10
Inserção de Elementos em Listas
Encadeadas
Diferentes formas de inserir um elemento na
lista:
No começo
Mais simples
No fim
Neste caso deve-se percorrer a lista toda
11
Inserindo Elementos no Início de
Listas Encadeadas
/* inserção início da lista */
Lista* lst_insere(Lista* inicio,int i){
Lista* novo = (Lista*) malloc(sizeof(Lista));
novo->info = i ;
novo->prox = inicio ;
return novo ;
}
info1
inicio
info2 info3 info4
Novo
Endereço do começo da
listaRetorna endereço inicial atualizado
12
Inserindo Elementos no Fim de Listas
Encadeadas
/* inserção fim da lista */
Lista* lst_insere(Lista* inicio,int i){
Lista* novo = (Lista*) malloc(sizeof(Lista));
novo->info = i ;
novo->prox = NULL ;
if (inicio == NULL){
inicio = novo;
} else {
Lista* p = inicio;
while (p->prox != NULL){
p = p->prox;
}
p->prox = novo;
}
return inicio ;
}
Se lista estiver vazia, inicio vai guardar endereço de novo
Senão temos que percorrer lista até último nó, para fazê-lo
apontar para novo
13
Usando Função de Inserção de Listas
Encadeadas
int main() {
Lista* inicio;
inicio = NULL;
inicio = lst_insere(inicio,23); /* insere 23 */
inicio = lst_insere(inicio,45); /* insere 45 */...return 0 ;
}
Não esquecer de atualizar a variável que guarda endereço
inicial da lista a cada inserção!
Variavel que armazena endereço inicial da lista deve ser inicializada com NULL!
14
Imprimindo Listas Encadeadas
void lst_imprime(Lista* inicio){
Lista* p; /*variável auxiliar para percorrer a
lista */
for(p = inicio; p != NULL; p = p->prox){
printf ( “info = %d\n ”, p->info ) ;
}
}
Laço para percorrer todos os nós da lista
15
Verificando se a Lista Está Vazia
/* função vazia: retorna 1 se vazia ou 0 se não
vazia */
int lst_vazia(Lista* inicio){
if (inicio == NULL)
return 1;
else
return 0;
}
/* versão compacta da função lst_vazia */
int lst_vazia ( Lista* inicio ){
return(inicio == NULL) ;
}
16
Buscando um Elemento em Listas
Encadeadas
Lista* lst_busca(Lista* inicio,int v){
int achou = 0;
Lista* p = inicio ;
while (p != NULL && !achou) {
if (p->info == v)
achou = 1 ;
else
p = p->prox;
}
return p;
}
Retorna o endereço do primeironó que contém o elemento
buscado
Se não achou elemento, retorna o endereço nulo!
17
Removendo Elementos de Listas
Encadeadas
Dois casos devem ser tratados para a remoção de
um elemento da lista
info1
inicio
info2 info3 info4
Remoção do primeiro elemento da lista
info1
inicio
info2 info3 info4
Remoção de um elemento no meio da lista
18
Removendo Elementos de Listas
EncadeadasLista* lst_retira(Lista* inicio,int v){
Lista* ant = NULL; /* guarda elemento anterior */
Lista* p = inicio;
while(p != NULL && p->info != v){
ant = p ;
p = p->prox ;
}
/* verifica se achou o elemento */
if (p != NULL) {
if (ant == NULL)
inicio = p->prox;
else
ant->prox = p->prox;
free(p) ;
}
return inicio ;
}
Procura elemento na lista,guardando
endereço do anterior
Retorna endereço inicial da lista
Elemento no inicio, retira elemento do início
Retira elemento do meio
19
Liberando Listas Encadeadas
void lst_libera(Lista* inicio){
Lista* p = inicio ;
while(p != NULL ) {
Lista* t = p->prox;
free(p); /* libera a memória apontada por “p”*/
p = t; /* faz “p” apontar para o próximo */
}
}
Guarda o endereço do próximonó para poder libera-lo na
próxima iteração
20
Comparando Listas Encadeadas
int lst_igual(Lista* lst1,Lista* lst2){
Lista* p1 ;
Lista* p2 ;
int igual = 1
for(p1 = lst1,p2 = lst2; p1!=NULL && p2!=NULL && igual;
p1=p1->prox,p2=p2->prox){
if(p1->info!= p2->info )
igual = 0;
}
return(p1 == p2 && igual) ;
}
Se os elementos testados forem iguais, deve-se ainda ver se p1 e p2 apontam para NULL (tamanhos
das listas iguais)
21
Utilizando Funções de Manipulação de
Lista de Inteiros
#include <stdio.h>
#include “lista.h“
int main() {
Lista * ls ; /* declara uma lista não iniciada */
ls = NULL; /*inicia lista vazia */
ls = lst_insere(ls,23); /* insere o elemento 23 */
ls = lst_insere(ls,45); /* insere o elemento 45 */
ls = lst_insere(ls,56); /* insere o elemento 56 */
ls = lst_insere(ls,78); /* insere o elemento 78 */
lst_imprime(ls); /* imprime: 78 56 45 23 */
ls = lst_retira(ls,78);
lst_imprime(ls); /* imprime: 56 45 23 */
ls = lst_retira(ls,45);
lst_imprime(ls); /* imprime: 56 23 */
lst_libera(ls);
return 0 ;
}
22
Listas podem variar quanto ao:Tipo de encadeamento
Simples
Circulares
Duplas
Circulares e Duplas
Conteúdo
Tipos Primitivos
Tipos Estruturados
Variações de Listas Encadeadas
Já vimos anteriormente
2323
Listas Circulares
lista
info1 info3info2
Estrutura do nó da lista é idêntica a da lista
simplesmente endadeada
Não há noção de primeiro e último nó da lista
Para saber se toda lista foi percorrida deve-se
guardar o endereço do primeiro nó a ser lido e
comparar com o endereço do nó que está sendo lido
2424
Imprimindo uma Lista Circular
void lcirc_imprime (Lista* inicio) {
Lista* p = inicio; /* faz p apontar para o nó inicial */
/* testa se lista não é vazia*/
if (p != NULL){
do {
printf(“%d\n”,p->info);
p = p->prox;
} while (p != inicio);
}
A condição de parada do laço é quando o nó a ser percorrido for igual ao nó
inicial
25
Lista duplamente encadeada
inicio
info1 info3info2
Permite percorrer a lista em dois sentidos
Cada elemento deve guardar os endereços do
próximo elemento e do elemento anterior
Facilita percorrer a lista em ordem inversa
Retirada de elemento cujo endereço é conhecido se
torna mais simples
Acesso ao nó anterior para ajustar encadeamento não
implica em percorrer a lista toda
info4
26
Estrutura de Listas Duplamente
Encadeadas
inicio
struct lista2 {
int info ;
struct lista2* prox;
struct lista2* ant;
} ;
typedef struct lista2 Lista2 ;
Armazena o endereço do próximo nó fim
info1
p
r
o
x
a
n
t
info1
p
r
o
x
info1
a
n
t
Armazena o endereço do nó anterior
2727
inicio
info1 info3info2
novo
Inserindo Elementos no Início de
Listas Duplamente Encadeadas
Lista2* lst2_insere (Lista2* inicio, int v) {
Lista2* novo = (Lista2*) malloc(sizeof(Lista2));
novo->info = v; novo->prox = inicio;
novo->ant = NULL;
/* verifica se lista não está vazia */
if (inicio != NULL)
inicio->ant = novo;
return novo;
}
Inserção no começo da lista
2828
inicio
info1 info3info2
novo
Inserção no fim da lista
Inserindo Elementos no Fim de Listas
Duplamente Encadeadas
2929
Inserindo Elementos no Fim de Listas
Duplamente Encadeadas
Lista2* lst2_insere (Lista2* inicio, int v) {
Lista2* novo = (Lista2*) malloc(sizeof(Lista2));
novo->info = v; novo->prox = NULL;
if (inicio == NULL) {
novo->ant = NULL;
inicio = novo
} else {
Lista2* p;
while (p->prox != NULL) [
p = p->prox;
}
p->prox = novo;
novo->ant = p;
}
return inicio;
}
Se lista estiver vazia, endereço do nó anterior a
novo é NULL
Senão temos que fazer com que o último nó aponte para novo e nó anterior de
novo seja o antigo último nó
30
Lista2* lst_busca (Lista2* lista, int v)
{
Lista2* p;
int achou = 0
for (p = lista; p != NULL && !achou; p = p->prox)
if (p->info == v)
achou = 1;
return p;
}
Buscando um Elemento em Listas
Duplamente Encadeadas
Mesma lógica aplicada a listas simplesmenteencadeadas
31
Removendo Elementos de Listas
Duplamente EncadeadasTrês casos devem ser tratados para a remoção de
um elemento da lista
Remoção de um elemento no meio da lista
info1
inicio
info2 info3 info4
info1
inicio
info2 info3 info4
Remoção de um elemento do fim da lista
info1
inicio
info2 info3 info4
Remoção do primeiro elemento da lista
32
Lista2* lst2_retira (Lista2* inicio, int v) {
Lista2* p = busca(inicio, v);
if (p != NULL){
if (inicio == p)
inicio = p->prox;
else
p->ant->prox = p->prox;
if (p->prox != NULL)
p->prox->ant = p->ant;
free(p);
}
return inicio;
}
Removendo Elementos de Listas
Duplamente Encadeadas
Usando a função de busca
Retira elemento do começo da lista
Retira do meio
Só acerta o encadeamento do ponteiro para o anterior se NÃO for o último
elemento
33
lista
info1 info3info2
Lista Circular Duplamente
Encadeada
Permite percorrer a lista nos dois sentidos, a
partir de um ponteiro para um elemento
qualquer
3434
void l2circ_imprime_inverso (Lista2* lista){
Lista2* p = lista;
if (p != NULL)
do {
p = p->ant;
printf(“%d\n”, p->info);
} while (p != lista);
}
Imprimindo no Sentido Inverso com
um Lista Circular Duplamente
Encadeada
Avança para o nó anterior
35
typedef struct retangulo {
float b; /* base */
float h; /* altura */
} Retangulo;
Lista de Tipos Estruturados
Uma lista pode ser composta de elementos estruturados
Considere o tipo Retangulo
OU
typedef struct lista {
Retangulo info;
struct lista *prox;
} Lista;
Podemos definir uma lista cujos nós contenham ou um
retângulo ou um ponteiro para um retângulo
typedef struct lista {
Retangulo* info;
struct lista *prox;
} Lista;
36
Lista* insere (Lista* inicio,float b, float h) {
Lista *novo;
novo = (Lista*)malloc(sizeof(Lista));
novo->info.b = b;
novo->info.h = h;
novo->prox = inicio
return novo;
}
Inserindo um Nó em uma Lista de
Tipos Estruturados
Nó da lista contém um retângulo
37
Inserindo um Nó de uma Lista de Tipos
Estruturados
Lista* insere (Lista* inicio,float b, float h){
Retangulo *r;
r = (Retangulo*) malloc(sizeof(Retangulo));
Lista* novo = (Lista*)malloc(sizeof(Lista));
r->b = b;
r->h = h;
novo->info = r;
novo->prox = inicio;
return novo;
}
Nó da lista contém um ponteiro para um retângulo
Espaço para a estrutura Retangulo deve também ser
alocado
Introdução a Programação
Tipos Abstratos de Dados –Implementando Pilha e Fila
Abstração
2
Abstração é o processo ou resultado
de generalização por redução do
conteúdo da informação de um
conceito ou fenômeno observável,
normalmente para reter apenas a
informação que é relevante para um
propósito particular.
Fonte: Wikipedia
Tópicos da Aula
Hoje aprenderemos que existe uma forma dedefinir um tipo de dado pelas suas operações
Conceito de Tipo Abstrato de DadoDois Tipos Abstratos de Dados: Pilha e Fila
Depois aprenderemos como implementar Pilhas eFilas
Implementação de Pilha usando VetorImplementação de Pilha usando ListaImplementação de Fila usando Lista
3
44
Tipo Abstrato de Dado
Um Tipo Abstrato de Dado (TAD) é umconjunto organizado de informações e asoperações que podem atuar sobre estasinformações
Define um novo tipo de dado
Um TAD é definido indiretamente pelasoperações que podem atuar nele e os efeitosdestas operações
Exemplo de TAD: Pilha
Operações sobre Pilha (Livros) : inserção no topo eremoção no topoTipo é definido pelo comportamento
Conjunto de operações sobre o tipo
5
InserçãoRemoção
Exemplo de TAD: Fila
Operações sobre Fila (Pessoa) : inserção no fim eremoção no começo
6
RemoçãoInserção
77
TAD x Estrutura de Dado
O TAD é a descrição lógica de um dado e a estruturade dado é a descrição real
TAD (Tipo Abstrato de Dados) é a “figura lógica” dosdados e operações que manipulam os elementoscomponentes dos dados
Estrutura de Dados é a implementação real dos dadose algoritmos que manipulam os elementos dos dados
TAD descrição das funcionalidades
Estrutura de Dado implementação
8
Objetivos deTADs
Abstrair (esconder) de quem usa um determinado tipo,a forma concreta com que ele foi implementado
O cliente utiliza o TAD de forma abstrata, apenas com basenas funcionalidades oferecidas pelo tipo (interface)
Desacoplar a implementação do uso, facilitando amanutenção e aumentando o potencial de reuso do tipocriado
99
Implementando um TAD
As operações definem a interface de um TAD
Um código implementa corretamente um TADdesde que obedeça o que está sendo definidona interface do TAD
10
Tipos Abstratos de Dados em C
Em C:Arquivos-fontes que agrupam funções afins sãogeralmente denominados de MódulosEm programas modulares, cada módulo deve sercompilado separadamente e depois “linkados” paragerar executávelQuando módulo define um novo tipo de dado e oconjunto de operações para manipular dados destetipo, dizemos que o módulo representa um TipoAbstrato de Dado (TAD)
11
Implementando TADs em C
Geralmente a interface de um TAD é descrita em Cnos arquivos .hO cliente só precisa dar um “include” no .h quecontém a interface do TAD
Ao cliente também é dado o arquivo objeto (.o) com aimplementação do TAD
Esconde (Abstrai) a implementaçãoA interface de um TAD contém as assinaturas dasfunções que ele oferece e contém a definição do tipode dado
Funciona como um “manual de uso” do tipo que está sendodefinido
1212
Pilha é um tipo abstrato de dados onde:Inserção e remoção de elementos no topo dapilhaO primeiro elemento que sai é o último que entrou(LIFO)Operações básicas: push (empilhar) e pop(desempilhar)
Definição de Pilha
1313
Funcionamento da pilha
topotopo
topotopo
empilha(a)
a
empilha(b)
ab
empilha(c)
ab
c
desempilha()
ab
cc
1414
Exemplo de Uso: Pilha de Execução de Funções
#include “stdio.h”
int fat ( int n ) ;
int main () {
int n = 5, r ;
r = fat(n) ;
printf ( “ Fatorial = %d \n ”, r ) ;
return 0 ;
}
int fat ( int n ){
int f=1 ;
while(n != 0) {
f *= n ;
n-- ;
}
return f ;
}
1515
1 – Início do programa:pilha vazia
main>
2 – Declaração de variáveis: n,r
main>5n
r -
3 – Chamada da função:empilha variáveis
main>5n
r -5fat>
n
4 – Final do laço
main>5n-0fat> n
r
f 120
5 – Retorno da função:desempilha
main>5n
120fat>
r
Pilha de Execução
Acesso às variáveis queestão na função do topo
1616
Interface do tipo Pilha
Criar pilha vazia;Inserir elemento no topo(push)Remover elemento dotopo (pop)Verificar se a pilha estávaziaLiberar a estrutura depilha
Em C/* pilha.h */
typedef struct pilha Pilha;
Pilha* pilha_cria();
void pilha_push(Pilha* p,float v);
float pilha_pop(Pilha* p);
int pilha_vazia(Pilha* p);
void pilha_libera(Pilha* p);
1717
Implementação do tipo Pilha
Existem várias implementações possíveis deuma pilha. Podem diferir da natureza doselementos, maneira como são armazenadose operações disponíveisIremos estudar 2 tipos de implementação:
Utilizando VetorUtilizando Lista Encadeada
1818
Implementando Pilha com Vetor
Estrutura que representa pilhadeve ser composta por um vetorpara armazenar os elementos eo número de elementosarmazenadosVantagem
Simplicidade
DesvantagensDeve-se saber de antemão onúmero máximo de elementosDesperdício de espaço de memória
#define N 50
struct pilha {
int n;
float vet[N];
};
1919
Pilha* pilha_cria ()
{
Pilha* p = (Pilha*) malloc(sizeof(Pilha));
p->n = 0;
return p;
}
Implementando Pilha com Vetor
Função de CriaçãoAloca estrutura dinamicamente
Inicializa com 0 elementos
2020
void pilha_push (Pilha* p, float v) {
if (p->n < N) {
p->vet[p->n] = v;
p->n++;
} else {/* capacidade esgotada */
printf(“Capacidade da pilha estourou.\n”);
}
}
Implementando Pilha com Vetor
Função de Inserção Verifica se tem espaço disponível
Insere na próxima posição livre e incrementa o número
de elementos da pilha
2121
float pilha_pop (Pilha* p)
{
float v;
if (pilha_vazia(p)) {
printf(“Pilha vazia.\n”);
exit(1);
}
v = p->vet[p->n-1];
p->n--;
return v;
}
Implementando Pilha com Vetor
Função de Remoção Verifica se a pilha está
vazia
Topo está na posição n - 1
Remoção se dá pelo decremento do número de elementos (próximo push
sobrescreverá antigo topo)
2222
int pilha_vazia (Pilha* p) {
return (p->n==0);
}
Implementando Pilha com Vetor
Função que testa se pilha está vazia
void pilha_libera (Pilha* p) {
free(p);
}
Função que libera memória alocada para apilha
2323
/* Função que informa o elemento do topo */
float pilha_topo (Pilha* p) {
return (p->vet[p->n – 1]);
}
Implementando Pilha com Vetor
Outras Funções Utilitárias
/* Função que imprime os elementos da pilha
void pilha_imprime (Pilha* p) {
int i;
for (i=p->n-1; i>=0; i--)
printf(“%f\n”, p->vet[i]);
}
2424
Implementando Pilha com Lista
Estrutura que representa pilhadeve ser composta por umponteiro para o primeiro nó dalista que armazena oselementosVantagens
Otimização da memóriaTamanho irrestrito
DesvantagemComplexidade na manipulação delistas
typedef struct lista{
float info;
struct lista *prox;
} Lista;
struct pilha {
Lista *topo;
};
2525
Pilha* pilha_cria () {
Pilha* p = (Pilha*) malloc(sizeof(Pilha));
p->topo = NULL;
return p;
}
Implementando Pilha com Lista
Função de CriaçãoLista(topo) é inicializada com NULL
2626
void pilha_push (Pilha* p, float v) {
Lista* novo = (Lista*) malloc(sizeof(Lista));
novo->info = v;
novo->prox = p->topo;
p->topo = novo;
}
Implementando Pilha com Lista
Função de Inserção
Elemento é inserido no começo da lista – topo
aponta para o começo da lista
2727
float pilha_pop (Pilha* p) {
Lista* t;
float v;
if (pilha_vazia(p)) {
printf(“Pilha vazia.\n”);
exit(1); /* aborta programa */
}
t = p->topo;
v = t->info;
p->topo = t->prox;
free(t);
return v;
}
Implementando Pilha com Lista
Função de Remoção
Elemento é realmente removido, topo é
atualizado
2828
int pilha_vazia (Pilha* p) {
return (p->topo == NULL);
}
Implementando Pilha com Lista
Função que testa se pilha está vazia
void pilha_libera (Pilha* p) {
Lista* q = p->topo;
while (q!=NULL) {
Lista* t = q->prox;
free(q);
q = t;
}
free(p);
}
Função que libera memória alocada para apilha
Deve-se liberar todos os elementos da lista primeiro
2929
/* Função que informa o elemento do topo */
float pilha_topo (Pilha* p) {
return (p->topo->info);
}
Implementando Pilha com Lista
Outras Funções Utilitárias
/* Função que imprime os elementos da pilha
void pilha_imprime (Pilha* p) {
Lista* q;
for (q=p->topo; q!= NULL; q = q->prox)
printf(“%f\n”, q->info);
}
30
Definição de Fila
Fila é um tipo abstrato de dados onde:Inserção de elementos se dá no final e aremoção no inícioO primeiro elemento que entra é o primeiroque sai (FIFO)Ex de uso : fila de impressão
31
Funcionamento da Fila
início
1- insere(a)
2- insere(b)
a
b
c
fim
a
início
fim
3- insere(c)fim
ba
início
4- retira( )
início
b
fim
ca
32
Interface do tipo Fila
Em C/* fila.h */
typedef struct fila Fila;
Fila* fila_cria();
void fila_insere(Fila* f,float v);
float fila_retira(Fila* f);
int fila_vazia(Fila* f);
void fila_libera(Fila* f);
Criar uma fila vaziaInserir um elemento nofimRetirar o elemento doinícioVerificar se a fila estávaziaLiberar a fila
33
Implementando Fila com ListaEstrutura que representa filadeve ser composta por 2ponteiros para a lista quearmazena os elementos.
Um aponta para o primeiroelemento e o outro para o últimoelemento
typedef struct lista{
float info;
struct lista *prox;
} Lista;
struct fila {
Lista *ini;
Lista *fim
};
info1 info3info2
ini fim
34
Fila* fila_cria ( ) {
Fila* f = (Fila*) malloc(sizeof(Fila));
f->ini = f->fim = NULL;
return f;
}
Implementando Fila com Lista
Função de Criação
ini e fim são inicializados com NULL
35
void fila_insere (Fila* f, float v) {
Lista* novo = (Lista*) malloc(sizeof(Lista));
novo->info = v;
novo->prox = NULL; /* novo nó passa a ser o
último */
if (!fila_vazia(f)) /* verifica se a fila não
estava vazia */
f->fim->prox = novo;
else
f->ini = novo;
f->fim = novo;
}
Implementando Fila com Lista
Função de Inserção
Se a fila estava vazia novo elemento passa a ser o começo da fila
Novo elemento sempre é o último da fila
36
float fila_retira (Fila* f) {
Lista* t;
float v;
if (fila_vazia(f)) {
printf("Fila vazia.\n"); exit(1);
}
t = f->ini;
v = t->info;
f->ini = t->prox;
if (f->ini == NULL)
f->fim = NULL;
free(t);
return v;
}
Implementando Fila com ListaFunção de Remoção
Se a fila ficou vazia, deve-se atualizar
ponteiro para o fim
37
int fila_vazia (Fila* f) {
return (f->ini == NULL);
}
Implementando Fila com Lista
Função que testa se a fila está vazia
void fila_libera (Fila* f) {
Lista* q = f->ini;
while (q!=NULL) {
Lista* t = q->prox;
free(q);
q = t;
}
free(f);
}
Função que libera memória alocada para afila
Deve-se liberar todos os elementos da lista primeiro
38
/* Função que informa o primeiro elemento da fila
*/
float fila_primeiro (Fila* f) {
return (f->ini->info);
}
Implementando Fila com Lista
Outras Funções Utilitárias
/* Função que imprime os elementos da fila
void fila_imprime (Fila* f) {
Lista* q;
for (q=f->ini; q!=NULL; q =q->prox)
printf(“%f\n”, q->info);
}
Introdução à Programação
Conceitos Básicos de
Orientação a Objetos
2
Tópicos da Aula
Aprenderemos fundamentos do paradigma orientado
a objetos, mas antes veremos o que é paradigma
Conceito de paradigma
Diferentes paradigmas na computação
Depois veremos o que é orientação a objetos
Conceitos de orientação a objetos
Programação orientada a objetos x Programação imperativa
Estrutura de um programa orientado a objetos em C++
Construtores
Criação de objetos
Exemplo de aplicação orientada a objetos
Paradigmas de Programação
Linguagens de programação são baseadas em
vários conceitos:
Tipos de dados, variáveis e armazenamento, controle,
abstração de dados, abstração procedural, sistema de
tipos,etc
Diferentes seleções dos conceitos definem o estilo
de programação ou Paradigma
Afeta a forma de pensar em como escrever um programa
A forma como estes conceitos são agrupados em
uma linguagem de programação definem que
paradigma é suportado por esta linguagem
Paradigmas de Programação
Podemos encontrar 6 grandes paradigmassuportados pelas linguagens de programação:
Imperativo
Uso de comandos, variáveis e procedimentos
Primeiras linguagens de programação são desteparadigma
Ex: Fortran, Pascal, C, etc
Orientação a Objetos
Uso de classes, objetos, herança, polimorfismo,maior abstração de dados, encapsulamento(implementação)
Evolução do paradigma imperativo
Ex: Smalltalk, C++, Eiffel, Java, C#, etc
Paradigmas de Programação
Funcional
Uso de expressões e funções, ausência de
variáveis e comandos
Ex: ML, Haskell
-- Exemplo em Haskell
-- type
factorial :: Integer -> Integer
-- using recursion
factorial 0 = 1
factorial n = n * factorial (n - 1)
Paradigmas de Programação
Lógico
Relações lógicas entre entradas e saídas,
asserções
Ex: Prolog, Mercury
/* Exemplo em Prolog */
mother_child(trude, sally). /* fato */
father_child(tom, sally).
father_child(tom, erica).
sibling(X, Y) :- parent_child(Z, X), parent_child(Z, Y).
parent_child(X, Y) :- father_child(X, Y). /* clausula*/
parent_child(X, Y) :- mother_child(X, Y).
?- sibling(sally, erica).
Yes
Paradigmas de Programação
Concorrente
Execução concorrente de processos, abstração de
controle de sincronização (inter-processos, acesso
a recursos, etc)
Ex: Occam, Java, Concurrent C, etc
Scripting
Sistema de tipos dinâmica, abstração de
processamento de Strings, suporte a interfaces
gráficas
Ex: Python, Java Script, Tcl, HTML
O que é Orientação a Objetos?
É considerar que tudo é um objeto:
Os sistemas são objetos
Os dados manipulados e comunicados entre os
sistemas são objetos
Cada parte de um sistema (sub-sistema) é um objeto
Os dispositivos eletrônicos são objetos
A interface com o usuário é um objeto, composto de
vários outros objetos...
8
Objeto
Podemos definir objeto como uma entidade
que possui:
Estado
Características ou propriedades do objeto
Comportamento
Operações que o objeto pode realizar
O comportamento pode examinar ou alterar o
estado de um objeto
9
Objeto DVD
Fonte: http://www.amazon.com
O estado atual do DVD; o que eleestá fazendo...
As operações que oDVD pode executar
10
ComportamentoNúmeroSaldo
21.342-7875,32
Crédito
Débito
Operações que umaconta pode executar
O estado atual da conta
11
Objeto Conta Bancária
Estados do Objeto Conta
NúmeroSaldo
21.342-7875,32
Crédito
NúmeroSaldo
21.342-7875,32
Crédito
Débito
Crédito(20)
12
NúmeroSaldo
21.342-7875,32
Crédito
NúmeroSaldo
21.342-7895,32
Crédito
Débito
Comportamento neste caso mudou o estado do
objeto conta
Classe
Classe é um agrupamento de objetos que têm
propriedades comuns e podem realizar as
mesmas operações
É uma definição que descreve como objetos
pertencentes à classe são estruturados
internamente (quais propriedades e operações
o objeto possui)
Classe é um conceito e o objeto é uma
instância deste conceito
Portanto, podemos ter vários objetos
pertencentes a mesma classe
13
Classe x Objeto
NúmeroSaldo
21.342-7875,32
Crédito
NúmeroSaldo
11.056-x1000,32
Crédito
Débito 14
Múltiplos objetos podem ser criados à partir da mesma
classe
NúmeroSaldo
Crédito Débito
NúmeroSaldo
21.342-7875,32
Crédito
NúmeroSaldo
875,32
Crédito
Débito
21.342-7
Classe Conta
Objeto conta1 Objeto conta2
Classe e Tipo
Tipo é um conjunto de valores relacionados que
são capazes de realizar as mesmas operações
Ex: inteiro, caractere, Conta, Banco, etc
Uma classe define um tipo: o tipo cujos
elementos são objetos com as mesmas
propriedades e comportamento
15
Atributo e Método (1)
Atributo representa alguma propriedade do
objeto
O conjunto de atributos de um objeto determina
o estado do objeto
Um atributo pode conter um valor simples tal
como um número real ou até outro objeto
Método representa uma operação que um
objeto pode fazer
O conjunto de métodos de um objeto determina
o comportamento do objeto
16
NúmeroSaldo
21.342-7875,32
Crédito
Débito
17
Atributo e Método (2)
Atributosda conta
Comportamento
Métodos de umaconta
Relações entre Objetos
Geralmente, um software é construído a partir de vários
objetos (classes) que se relacionam
As relações de Cliente e Herança são essenciais para
a construção de programas
Classe B é Cliente de classe A, se todo objeto de tipo B
contiver informação sobre um ou mais objetos do tipo A
Classe B é Herdeira de classe A, se B representa uma
versão especializada de A
Métodos e os atributos da classe A se tornam, também, parte
da classe B
Características e comportamento de A são passadas para B
18
Relação Cliente
NúmeroSaldo
21.342-7875,32
CréditoCria nova Conta
Transferência
Objeto Banco1
19
NúmeroSaldo
21.342-7875,32
Crédito
NúmeroSaldo
21.342-7895,32
Crédito
Débito
Objeto do tipo Banco têm vários objetos do tipo
Conta Banco é cliente de Conta
Banco do Brasil
Nome
Conta1
Conta
Conta1
Conta
Conta1
Conta
Objeto Conta1
Relação Herança
20
Classe Poupança é uma versão especializada de Conta
Métodos e atributos são herdados
Classe Conta
Saldo
Crédito Débito
Número
Saldo
Crédito Débito
Número Juros
Classe Poupança
Utilizando OO para Desenvolver
Programas
Desenvolvimento de uma
solução se torna mais fácil
quando quebramos esta solução
em módulos gerenciáveis
Quando estamos programando,
podemos desenvolver módulos
separados, onde cada um é
responsável por uma certa parte
da solução
Programação Modular
OO facilita a programação
modular
Módulos são as classes e objetos21
Algumas Considerações sobre OO
Orientação a Objetos Modularidade
Reusabilidade
Extensibilidade
Classe é uma entidade que combina 2 conceitos:
Módulo e Tipo
Módulo é um conceito sintático, pois a decomposição do
sistema em módulos afeta somente a forma como o programa
é escrito, não a funcionalidade dele
Tipo é um conceito semântico, pois o tipo influencia
diretamente a execução do sistema, definindo a forma dos
objetos que são criados e manipulados pelo sistema em tempo
de execução
22
OO e Linguagens de Programação
Linguagens OO têm em objetos e classes seus
elementos fundamentais para construção de programas
Estruturas da linguagem permitem mapeamento direto dos
conceitos de OO
Porém, é possível fazer um programa OO em uma
linguagem não OO
É possível, também, fazer um programa que não seja OO em
uma linguagem OO
23
Conceito de Orientação a Objetos é independente da linguagem de
programação
Linguagem C++
Criada por Bjarne Stroustrup em 1983
Pode ser vista quase como uma extensão da linguagem
C para dar suporte a OO
Embora quase tudo escrito em C seja compatível com C++,
certos comandos podem ter comportamento diferente em C++
Dá suporte a vários conceitos de OO:
Classe, Herança,Polimorfismo, Encapsulamento
Ainda oferece suporte a tratamento de exceções e tipos
genéricos
Sintaxe da linguagem Java foi inspirada em C++
24
Um Programa Imperativo...
Contém
Uma função principal, por onde começa aexecução do programa
Várias funções auxiliares, para modularizar, dividir
o código em partes
Importação de bibliotecas de funções
Pode ainda conter:
Definição de tipos estruturados
26
Um Programa Orientado a Objetos ...
Tem a classe como a sua construçãofundamental :
Um programa é constituído de uma ou mais classes
Que podem ter sido importadas de uma bibliotecade classes
Uma classe contém um ou mais atributos e métodos
Um método é composto de instruções
Ao Invés de Estruturas, Classes!
Define um tipo, com funções que
operam sobre este tipo
Estrutura
Função 1
Função 2
Função 3
Estrutura
Função 1
Função 2
Função 3
Classe
Programação Imperativa x
Programação OO
Programação Imperativa tem como elementos
principais os procedimentos (funções)
Programação OO tem como elementos
principais as classes
Estrutura + funções = classe
Programação OO ainda utiliza :
Herança
Encapsulamento
Polimorfismo
28
Veremos depois!
Implementando o Tipo Conta com
Programação Imperativa
Primeiro passo é definir um tipo estruturado
Conta
29
struct Conta{
double saldo;
char numero[11];
char agencia[11];
};
Implementando as Funções do Tipo
Conta
Depois se define as funções que operam sobre
o tipo Conta
creditar
debitar
getSaldo
criaConta 30
void creditar(struct Conta *c ,double v){
c->saldo = c->saldo + v;
}
Passa-se estrutura (ou endereço de estrutura) como parâmetro
Implementando as Funções do Tipo
Conta
31
void debitar(struct Conta *c,double v){
if (v <= c->saldo)
c->saldo = c->saldo - v;
}
double getSaldo(struct Conta *c){
return c->saldo;
}
Implementando as Funções do Tipo
Conta
32
struct Conta* criaConta(char *num, char* ag) {
struct Conta *retorno;
retorno = (struct Conta *)
malloc (sizeof(struct Conta));
if (retorno == NULL){
printf(“Erro na alocação de memória!”)
} else {
strcpy(retorno->numero, num);
strcpy(retorno->agencia, ag);
retorno->saldo = 0;
}
return retorno;
}
Alocando dinamicamente uma estrutura
Usando o Tipo Conta em Programação
Imperativa
33
int main() {
struct Conta *conta1;
conta1 = criaConta(“1234-5”,”007-x”);
if (conta1 == NULL){
printf(“Erro na alocação de memória!”)
} else {
creditar(conta1,300);
printf(“Saldo da conta = %lf\n”,getSaldo(conta1));
debitar(conta1,200);
printf(“Saldo da conta = %lf\n”,getSaldo(conta1));
}
return 0;
}
Implementando o Tipo Conta com
Programação OO (C++)
Primeiro passo é definir a classe Conta
Atributos e Métodos34
class Conta{
private:
double saldo;
char numero[11];
char agencia[11];
public:
void creditar(double v);
void debitar(double v);
double getSaldo();
Conta(char* num, char* ag);
};
Atributos
Métodos
Construtor
Implementando os Métodos do Tipo
Conta
35
void Conta::creditar(double v){
saldo = saldo + v;
}
Indica que método faz parte da classe Conta
Não precisa passar objeto como parâmetro!
saldo é um atributo que foi definido na classe Conta
Implementando os Métodos do Tipo
Conta
36
void Conta::debitar(double v){
if (v <= saldo)
saldo = saldo - v;
}
double Conta::getSaldo(){
return saldo;
}
Construtor
Tipo especial de método que é chamado no ato de
criação de um objeto da classe desejada
Importante para fazer algumas inicializações no objeto
Uma classe pode ter mais de um construtor
O que diferencia um construtor do outro é a ordem e/ou tipo
e/ou quantidade de parâmetros
Em C++, deve ter o mesmo nome da classe
Não possui tipo de retorno
Não é obrigatório definir um construtor
Existe em C++ um construtor default sem parâmetros
37
Implementando o Construtor do Tipo
Conta
38
Conta::Conta(char *num, char* ag) {
strcpy(numero, num);
strcpy(agencia, ag);
saldo = 0;
}
Usando o Tipo Conta em Programação
OO
39
#include <iostream>
using namespace std;
int main() {
Conta *c;
c = new Conta(“1234-5”,”007-x”);
if (c == NULL){
printf(“Erro na criação do objeto!”)
} else {
c->creditar(300);
cout<<"Conta tem saldo = " << c->getSaldo() << endl;
c->debitar(200);
cout<<"Conta tem saldo = " << c->getSaldo() << endl;
}
return 0;
}
Comando para criar objeto de uma classe em tempo de execução (dinamicamente)
Para chamar método a partir de uma referência para um objeto
Comando para imprimir na
tela
40
Criação Dinâmica de Objetos
Em linguagens OO, escrevemos programas
utilizando objetos
Mas, primeiro, temos que criá-los...
Para criar um objeto em C++ dinamicamente
utilizamos o comando new
new Conta(...);
Palavra reservada
ordenando a criação
de um objeto
Construtor do objeto a ser
criado
Avaliação do operador new
Cria um objeto da classe NomeDaClasse e
armazena na sua memória
Inicializa os atributos deste objeto usando o
construtor desta classe
Devolve como resultado da avaliação uma referência
(endereço da memória) para o objeto criado
Para avaliar uma expressão do tiponew NomeDaClasse();
o computador...
41
Criando um objeto dinamicamente...
new Conta(“12-3”,11-2”);
4. Devolve o endereço
como resultado da avaliação42
1. Cria o objeto
na memória
2. Inicializa o
objeto
12-3 11-2
id275
3. Associa um
endereço ao
objeto
12-3 11-2
Construtores e new
new NomeDaClasse(argumentos)
O número, ordem e tipos dos argumentos
determina o construtor 43
Podemos ter mais de um construtor para um
determinado objeto
A escolha do construtor para inicializar os atributos é
determinada pela lista de argumentos, entre
parênteses
Referências para objetos
A referência funcionacomo a identidade do objeto
O objeto
id305
A referênciapara o objeto
44
Todo acesso e manipulação é feito indiretamente,
através de uma referência (endereço) para o objeto
Quando declaramos uma variável do tipo de um
determinado objeto, ela não armazena o objeto e sim
uma referência para um objeto daquele tipo
Conta* conta1 = new Conta(“12-3”,”11-2”);
conta1 armazena este valor
Referências e identidade de um objeto
id305
id309
id312
Objetos diferentes, mas com o mesmoconteúdo (clones)
Referênciasdiferentes objetos diferentes
45
12-3 11-2
12-3 11-2
11-5 12-4
46
Considerações sobre Criação de
Objetos
Os valores dos atributos (estado) de um
objeto podem mudar durante a execução de
um programa, mas isso não afeta a
identidade do objeto
O ato de criar um objeto é chamado de
instanciar um objeto de uma determinada
classe
47
Criação Estática de Objetos
C++ permite também a criação estática (em tempo
de compilação) de objetos
No ato da declaração de uma variável do tipo de uma
classe, objeto é criado
Na declaração deve-se passar argumentos do construtor
Conta c(“12-3”,”11-2”);
Tipo da variável c é Conta
Argumentos do construtor
Usando Criação Estática de Objetos do
Tipo Conta
48
#include <iostream>
using namespace std;
int main() {
Conta c(“1234-5”,”007-x”);
c.creditar(300);
cout<<"Conta tem saldo = " << c.getSaldo() << endl;
c.debitar(200);
cout<<"Conta tem saldo = " << c.getSaldo() << endl;
return 0;
}
Declaração para instanciar objeto em tempo de compilação
Utiliza-se operador “.” para utilizar os métodos do objeto
criado estaticamente
Introdução à Programação
Encapsulamento e Herança
2
Tópicos da Aula
Hoje, aprenderemos conceitos mais avançadosde Orientação a Objetos
EncapsulamentoUsando modificadores de acesso em C++
HerançaImportânciaUtilização em C++Herança múltipla
Um objeto pode ser visto de duas formasdiferentes:
InternamenteDetalhes de atributos e métodos da classe que odefine
ExternamenteServiços que um objeto fornece e como esteobjeto interage com o resto do sistema (ainterface do objeto)
Encapsulamento (Information Hiding)
A visão externa de um objeto encapsula omodo como são fornecidos os serviços
Isto é, esconde os detalhes (internos) deimplementação do objeto (information hiding)
Encapsulamento (Information Hiding)
Um objeto (chamado neste caso de cliente) pode usaros serviços fornecidos por um outro objeto
Contudo, um cliente não deve precisar saber os detalhes deimplementação destes métodos
Mudanças no estado (atributos) de um objeto devemser feitas pelos métodos do objeto
Para permitir uma maior independência entre osobjetos,o acesso direto aos atributos de um objeto porum outro objeto deve ser restrito ou quase impossível
Encapsulamento (Information Hiding)
Um objeto pode ser visto como uma “caixa preta”,onde os detalhes internos são escondidos dosclientesClientes acessam o estado do objeto, através dosmétodos oferecidos
Métodos
Dados
Cliente
Encapsulamento (Information Hiding)
Em C++, o encapsulamento é possível através do usoapropriado de modificadores de acesso
Modificadores são palavras reservadas que especificamcaracterísticas particulares de um conjunto de métodos ou deatributos
Modificadores de acesso variam de acordo com avisibilidade que se quer oferecer ao clientePodem ser:public,protected ,private,friend
Modificadores de Acesso
Membros da classe que recebem o modificador public,podem ser acessados por qualquer outra classe
Devem ser utilizados para métodos que definem a interface daclasseNão deve ser utilizado para os atributos, excetuando-se o casoonde queremos declarar uma constante
Membros que recebem o modificador private, sópodem ser acessados por membros da classe ou classes(ou funções) “amigas” (friends)
Devem ser utilizados para atributos e métodos auxiliares
Modificadores de Acesso
public private
Atributos
MétodosFornecem serviços
para os clientesAuxiliam outros
métodos da classe
Preservam
encapsulamento
Violam
encapsulamento
Modificadores de Acesso
class Conta {
private:
string numero;
string agencia;
double saldo;
public:
void creditar (double valor);
void debitar(double valor);
double getSaldo();
string getNumero();
string getAgencia();
Conta(string num, string ag);
protected:
void setSaldo(double valor);
}
Classe Conta e Modificadores de
Acesso
10
Parte privada
Parte pública
Parte protegida
Membros de uma superclasse que recebem omodificador private, não podem ser acessadosnem pelas subclasses
Se colocar public e o membro for um atributo, o princípiodo encapsulamento é violado
Membros com o modificador protected são visíveispelas subclasses e pelas classes (ou funções)“amigas”
Modificadores de Acesso
Em C++, o modificador friend pode ser colocadoantes de um método ou (uma classe) declaradodentro de uma classe
O método “amigo” (ou classe “amiga”) não pertence a classena qual está declaradoInforma que o método “amigo” (ou classe “amiga”) podeacessar os membros privados e protegidos da classe naqual está declarado
Modificadores de Acesso
void creditarBonus(Conta* c, double v) {
if (c->saldo > 10000)
c->saldo = c->saldo + v;
}
class Conta {
private:
string numero;
string agencia;
double saldo;
public:
void creditar (double valor);
...
friend void creditarBonus(Conta* c,double v);
};
Classe Conta e Modificador de Acesso
Friend
13
Parte privada
Função (método) amiga
Função amiga que não pertence à classe acessa parte privada da classe
Membros de uma classe, que não recebem modificadorde acesso, tem visibilidade private
Na redefinição de métodos herdados, o modificador deacesso não deve ser trocado por um mais restrito
No entanto, podem ser trocados por modificadoresmenos restritos
Modificadores de Acesso
class PoupancaD {
private:
string numero;
string agencia;
double saldo;
public:
void creditar (double valor);
void debitar(double valor);
void renderJuros(double taxa);
}
Classes de Poupanças e Contas:
Descrições
class Conta{
private:
string numero;
string agencia;
double saldo;
public:
void creditar (double valor);
void debitar(double valor);
}
Parte diferente das descrições
Partes idênticas das descrições
15
Classe de Bancos: Assinatura
class BancoD {
public:
void cadastrarConta(Conta* c){}
void cadastrarPoupanca(PoupancaD* p){}
...
} Métodos diferentes para manipular contas e poupanças
16
Problemas
Duplicação desnecessária de código:A definição de PoupançaD é uma simplesextensão da definição de ContaClientes de Conta que precisam trabalhar tambémcom PoupançaD terão que ter código especialpara manipular poupanças
Falta refletir relação entre tipos do “mundoreal”
17
Subtipos e Subclasses
Poupança
Conta
18
Herança
Necessidade de estender classesAlterar classes já existentes e adicionarpropriedades ou comportamentos pararepresentar outra classe de objetosCriar uma hierarquia de classes que “herdam”propriedades e comportamentos de outra classe edefinem novas propriedades e comportamentos
19
Herança
Herança permite que novas classes possam serderivadas de classes existentesA classe existente é chamada de classe pai (mãe) ousuperclasseA classe derivada é chamada de classe filha ousubclasseSubclasse herda as características da superclasse
Herda os atributos e métodos
Estabelece a relação de é- um
A subclasse é uma versão especializada da superclasse
20
Importância de Herança
ComportamentoObjetos da subclasse comportam-se como os objetos dasuperclasse
SubstituiçãoObjetos da subclasse podem ser usados no lugar de objetosda superclasse
Reuso de CódigoDescrição da superclasse pode ser usada para definir asubclasse
Extensibilidadealgumas operações da superclasse podem ser redefinidasna subclasse
21
#include “Conta.h”
class Poupanca: public Conta {
public:
void renderJuros(double taxa);
Poupanca(string num,string ag):Conta(num,ag){}
}
22
Classe de Poupanças: Assinatura
Indica que a classe Poupanca herda de
Conta
Indica que o construtor de Poupanca utiliza o construtor de Conta
para inicializar atributos
#include “Poupanca.h”
void Poupanca::renderJuros(double taxa) {
creditar(getSaldo() * taxa);
}
23
Classes de Poupanças:
Implementação
So precisa implementar o método renderJuros, o resto é
herdado!
Herança e Construtores
Construtores não são herdadosEmbora, freqüentemente, precisamos doconstrutor da superclasse para a definição dosconstrutores das subclassesNecessários para inicializar os atributos que sãoherdados da superclasse
Devemos portanto definir construtores paraas subclasses
24
Herança Múltipla
Herança múltipla permite que uma classeseja derivada de mais de uma classe
25
Carro
puxarFreiodeMao()
acelerar()
Barco
jogarAncora()
acelerar()
CarroAnfibio
Qual versão do método acelerar é herdada por CarroAnfibio?
Herança múltipla faz com que subclassesherdem atributos e métodos das suassuperclasses
Pode haver colisões de nomes de atributos emétodos
Ao contrário de Java, C++ dá suporte aherança múltipla
Na hora de utilizar o método, usamos o operador
de resolução de escopo para dizer a qualmétodo estamos nos referindo
26
Herança Múltipla e C++
int main() {
CarroAnfibio ca;
ca.Carro::acelerar();
ca.Barco::acelerar();
...
}
class CarroAnfibio: public Carro,Barco {
...
};
Herança Múltipla em C++
27
Herda das superclasses Carro e Barco
Usando operador de resolução de escopo para determinar qual versão do método
acelerar deve ser usado
Introdução à Programação
Polimorfismo, Cast e Dynamic
Binding
2
Tópicos da Aula
Hoje, aprenderemos conceitos mais avançadosde Orientação a Objetos
PolimorfismoConceitoObtendo polimorfismo através de HerançaCastRedefinição e sobregarga de métodos
Dynamic Binding (Ligação Dinâmica)
Polimorfismo
A palavra polimorfismo significa “assumirmuitas formas”
Uma referência polimórfica é uma variávelque pode armazenar referências (ponteiros)para objetos de tipos diferentes em intervalosde tempo diferentes
3
Polimorfismo
Um método chamado através de umareferência polimórfica pode tercomportamentos diferentes entre umachamada e outra
Polimorfismo em C++ pode se dar através deherança
4
Polimorfismo via Herança
PolimorfismoUma conta pode ser
Uma poupançaUma conta especial
Herança permite a substituição do supertipo pelosubtipo no código
Onde é permitido o supertipo, o subtipo pode serutilizadoVariável de supertipo pode em um determinado instantedo tempo guardar uma referência (ponteiro) para umainstância de um subtipo
5
public class Banco {
...
public:
void cadastrar(Conta* conta);
...
}
6
Classe de Bancos: Assinatura
Subtipos: Substituição
...
Banco banco;
banco.cadastrar(new Conta("21.345-7“,”123-4”));
banco.cadastrar(new Poupanca("1.21.345-9“,”123-4”));
7
Podemos cadastrar poupanças
Podemos cadastrar contas
Mesmo método pode ser aplicado a Conta e Poupanca
Subtipos: Substituição
...
Conta* conta;
conta = new Poupanca(“21.342-7”,”123-4”);
conta->creditar(500.87);
conta->debitar(45.00);
...
8
Herança permite a substituição do supertipopelo subtipo no código
Onde é permitido o supertipo, o subtipo pode serutilizado
Subtipos: Substituição
...
Poupanca* p;
p = new Conta(“21.342-7”,”123-4”);
p->creditar(500.87);
p->debitar(45.00);
...
9Cuidado! A recíproca não é verdadeira.
Substituição e Casts
Nos contextos onde objetos do tipo Contasão usados pode-se usar objetos do tipoPoupancaNos contextos onde objetos do tipoPoupanca são usados pode-se usar variáveisdo tipo Conta que armazenam referências(endereços) para objetos do tipo Poupanca,desde que se faça o uso explícito de casts
dinâmicos
10
Subtipos: Utilizando Casts Dinâmicos
...
Conta* c;
c = new Poupanca("21.342-7“,”123-4”);
...
c->renderJuros(0.01);
...(dynamic_cast<Poupanca*>(c))->renderJuros(0.01);
11
Cast
Gera erro de compilação
Redefinição de Métodos
Uma subclasse pode redefinir (override) ummétodo herdado da superclasse
O novo método deve ter a mesma assinaturado método da superclasse, mas pode ter umcorpo diferente
Semântica dos métodos redefinidos deve serpreservada
12
class ContaEspecial: public Conta {
private:
double limiteCredito;
public:
void debitar(double valor);
ContaEspecial(string num,string ag, double taxa):
Conta(num,ag){limiteCredito = taxa;}
...
};
void ContaEspecial::debitar(double valor) {
double saldo = getSaldo();
if (valor <= (saldo + limiteCredito)) {
setSaldo(saldo – valor);
}
} 13
Classe ContaEspecial: Redefinindo debitar
Método existente em Conta é redefinido em
ContaEspecial
Redefinição de Métodos
Visibilidade dos métodos redefinidos deve serpreservada
Em C++, é possível aumentar a visibilidade de um métodoDiminuir a visibilidade pode gerar um erro de compilação
É possível acessar a definição dos métodos dasuperclasse usando operador de resolução deescopo
14
class Pai {
public:
void x(){
...
};
}
class Filha:public Pai{
public:
// Redefinindo x
void x(){
Pai::x();
...
};
}
Sobrecarga de Métodos
Sobrecarga (overloading) de método é oprocesso de dar a um método múltiplasdefiniçõesIsto quer dizer que somente o nome dométodo não é suficiente para determinar qualo método que se deseja utilizarA assinatura de cada método overloaded
deve ser únicaO que vai diferenciar os métodos é o número, tipoe ordem dos parâmetros
Não podem somente ser diferenciados pelo tipo deretorno 15
Sobrecarga de Métodos
Construtores são comumente overloaded
Útil para permitir várias formas de inicialização de um objeto
O compilador checa qual é o método que está sendochamado, analisando os parâmetros
16
class Conta{
...
public:
Conta(string num, string ag, double valor);
Conta(string num, string ag);
}
Conta::Conta(string num, string ag) {
numero = num;
agencia = ag;
}
Conta::Conta(string num,string ag, double valor) {
numero = num; agencia = ag;
saldo = valor;
}
Conta* conta = new Conta(“2”,”3”, 50);
Chamada
Sobrecarga x Redefinição
Sobrecarga trata múltiplos métodos com omesmo nome, mas assinaturas diferentesRedefinição trata de dois métodos, um nasuperclasse e outro na subclasse, quepossuem a mesma assinaturaSobrecarga permite que se defina umaoperação similar em diferentes formas paradiferentes parâmetrosRedefinição permite que se defina umaoperação similar em diferentes formas paradiferentes tipos de objeto
17
class Conta {
...
public:
void debitar(double valor);
...
};
void Conta::debitar(double valor) {
if (valor <= saldo) {
saldo – valor;
}
}
Binding de Métodos: debitar de
Conta e ContaEspecial
18
class ContaEspecial: public Conta {
...
public:
void debitar(double valor);
};
void ContaEspecial::debitar(double valor) {
double saldo = getSaldo();
if (valor <= (saldo + limiteCredito)) {
setSaldo(saldo – valor);
}
}
Duas versões de debitar
...
Conta* ca;
ca = new ContaEspecial(“21.342-7”,”123-4”,1000);
ca->creditar(500);
ca->debitar(600);
cout << ca->getSaldo()<<endl;
ca = new Conta(“21.111-7”,”123-4”);
ca->creditar(500);
ca->debitar(600);
cout << ca->getSaldo()<<endl;
...
19
Binding de Métodos
Qual versão de debitar é utilizada?
Binding
Uma chamada de um método dentro docódigo deve ser ligada (associada) àdefinição do método chamadoAssocia-se o método chamado aoendereço de memória que contém adefinição do método
Se esta ligação (binding) é feita em tempode compilação, então sempre a chamada dométodo será ligada ao mesmo método
Static Binding
20
Se a ligação da chamada de método a suadefinição correspondente for em tempo deexecução, então o método chamado dependedo objeto referenciado
Dynamic Binding ou Late Binding
Portanto, se existir dois métodos com o mesmonome e tipo(definição e redefinição), em Java, ocódigo é escolhido dinamicamente
Escolha é feita com base na classe do objetoassociado à variável destino da chamada do método
Linguagens como Java, Eiffel e Smalltalkutilizam dynamic binding como padrão
21
Dynamic Binding
Binding em C++
C++, C# e Delphi utilizam static binding comopadrão
Para se utilizar dynamic binding deve-se informarexplicitamente que um método pode ser ligado emtempo de execução
22
...
Conta* ca;
ca = new ContaEspecial(“21.342-7”,”123-4”,1000);
ca->creditar(500);
ca->debitar(600);
cout << ca->getSaldo()<<endl;
ca = new Conta(“21.111-7”,”123-4”);
ca->creditar(500);
ca->debitar(600);
cout << ca->getSaldo()<<endl;
...
23
C++: Padrão Static Binding
Qual versão de debitar é utilizada?
Será utilizada o método debitar definido em Conta
class Conta {
...
public:
virtual void debitar(double valor);
...
};
void Conta::debitar(double valor) {
...
}
Dynamic Binding em C++
24
class ContaEspecial: public Conta {
...
public:
void debitar(double valor);
};
void ContaEspecial::debitar(double valor) {
...
}
Deve-se utilizar a palavra virtual antes do método
da superclasse que vai ter dynamic
binding
...
Conta* ca;
ca = new ContaEspecial(“21.342-7”,”123-4”,1000);
ca->creditar(500);
ca->debitar(600);
cout << ca->getSaldo()<<endl;
ca = new Conta(“21.111-7”,”123-4”);
ca->creditar(500);
ca->debitar(600);
cout << ca->getSaldo()<<endl;
...
25
Dynamic Binding em C++
Qual versão de debitar é utilizada?
Em tempo de execução é decidida qual versão de debitar deve ser utilizada