Este documento apresenta o plano de ensino para a disciplina de Algoritmos e Estruturas de Dados I ministrada no curso de Engenharia de Computação da Pontifícia Universidade Católica de Minas Gerais. O curso será dividido em nove unidades temáticas avaliadas por três provas. Os alunos serão avaliados por meio de provas, trabalhos e frequência.
Este documento apresenta o plano de ensino para a disciplina de Algoritmos e Estruturas de Dados I ministrada no curso de Engenharia de Computação da Pontifícia Universidade Católica de Minas Gerais. O curso será dividido em nove unidades temáticas avaliadas por três provas. Os alunos serão avaliados por meio de provas, trabalhos e frequência.
Este documento apresenta o plano de ensino para a disciplina de Algoritmos e Estruturas de Dados I ministrada no curso de Engenharia de Computação da Pontifícia Universidade Católica de Minas Gerais. O curso será dividido em nove unidades temáticas avaliadas por três provas. Os alunos serão avaliados por meio de provas, trabalhos e frequência.
Campus Belo Horizonte Ncleo Universitrio So Gabriel Curso: Engenharia de Computao Disciplina: Algoritmos e Estruturas de Dados I Professor: Jlio Csar Dillinger Conway
ALGORITMOS E ESTURTURAS DE DADOS I
PROFESSOR: JLIO C. D. CONWAY, D.Sc. 2
UNIDADES DE ENSINO
UNIDADE 1 - INTRODUO PROGRAMAO DE COMPUTADORES............... 4 AULAS
CRITRIOS DE AVALIAO Provas escritas, individuais e sem consulta.
Avaliao:Prova 1: 25 pontos Prova 2: 25 pontos Prova 3: 25 pontos Trab1: 10 pontos Trab2: 15 pontos ________________ Total : 100 pontos
Obs1: Os alunos que ao final do semestre no obtiverem o total de 60 pontos podero realizar uma prova de reavaliao, presencial e individual, que substituir o menor valor obtido em uma das provas.
Obs2: Abono de faltas somente de acordo com os casos previstos no estatuto da PUC. Portanto, verifique a chamada do seu nome.
Obs4: Esta apostila constitui-se no material bsico da disciplina e est disponibilizado no SGA. As aulas seguem o contedo desta apostila, mas no possvel seguir linha a linha todo este contedo, devido s restries de tempo. Portanto, o aluno deve dedicar horas extras para estudar todo o contedo desta apostila, bem como fazer todos os exerccios. Alm disso, imprescindvel que o aluno tambm estude pelos livros recomendados na bibliografia.
Obs5: No permitido o uso de aparelho celular ou similar durante a realizao das provas. Qualquer ato que caracterize copia ou cola a prova ser automaticamente cancelada.
4
Bibliografia Bsica ASCENCIO, Ana Fernanda Gomes; CAMPOS, Edilene Aparecida Veneruchi de. Fundamentos da programao de computadores: algoritmos, Pascal e C/C++. So Paulo: Prentice Hall, 2002. 355p. ISBN 8587918362 Consta no acervo da PUC Minas
CORMEN, Thomas H. et al. Algoritmos: teoria e prtica. Rio de Janeiro: Campus, 2002. 916p. ISBN 8535209263 Consta no acervo da PUC Minas FARRER, Harry. Algoritmos estruturados. 3. ed. Rio de Janeiro: LTC Livros Tcnicos e Cientficos, c1999. 284p. ISBN 8521611803 Consta no acervo da PUC Minas
Bibliografia Complementar DEITEL, Harvey M. C++ : como programar. So Paulo: Pearson Prentice Hall, 2006. 1 CD-ROM Consta no acervo da PUC Minas DEITEL, Harvey M.; DEITEL, Paul J. C++: como programar. So Paulo: Pearson Prentice Hall, 2006. xxlii, 1163 p. ISBN 8576050560 Consta no acervo da PUC Minas FORBELLONE, Andr Luiz Villar; EBERSPACHER, Henri Frederico. Lgica de programao: a construo de algoritmos e estruturas de dados. 3. ed. So Paulo: Prentice Hall, 2005. xii, 218 p. ISBN 8576050242 Consta no acervo da PUC Minas GUIMARES, ngelo de Moura; LAGES, Newton Alberto de Castilho. Algoritmos e estruturas de dados. Rio de Janeiro: LTC - Livros Tcnicos e Cientficos, c1994. 216p. ISBN 8521603789 Consta no acervo da PUC Minas KERNIGHAN, Brian W.; RITCHIE, Dennis M. C: a linguagem de programao. Porto Alegre: EDISA; Rio de Janeiro: Campus, c1986. 208p. ISBN 8570014104 Consta no acervo da PUC Minas MANZANO, Jos Augusto N. G; OLIVEIRA, Jayr Figueiredo de. Algoritmos: lgica para desenvolvimento de programao de computadores. 14. ed. So Paulo: rica, 2002. [6]p. ISBN 857194718X Consta no acervo da PUC Minas SCHILDT, Herbert. C: completo e total. 3. ed. rev. atual. So Paulo: Pearson Education do Brasil, c1997. 827p. ISBN 8534605955 Consta no acervo da PUC Minas
5
1. INTRODUO PROGRAMAO DE COMPUTADORES
1.1 DESENVOLVIMENTO DE PROGRAMAS: ETAPAS
ANLISE Nesta etapa estuda-se o enunciado do problema para definir a entrada de dados, o processamento e a sada de dados.
ALGORITMO Ferramentas do tipo descrio narrativa, fluxograma ou pseudocdigo, so utilizadas para descrever o problema com suas solues. Pode-se definir algoritmo como: Uma seqencia de passos que deve ser seguida para a realizao de uma tarefa ou uma seqencia finita de instrues ou operaes, descritas de uma maneira exata, cuja execuo, em tempo finito, resolve um problema computacional, qualquer que seja sua instncia
CODIFICAO O algoritmo ento transformado em cdigos da linguagem de programao escolhida para se trabalhar.
. EXEMPLO DE ALGORITMO: IR PARA A PUC FAZER PROVA DE AED1
Passo 1 Acordar cedo Passo 2 Ir ao banheiro Passo 3 Abrir o armrio e escolher uma roupa Passo 4 Se o tempo estiver quente, pegar uma camiseta e uma cala jeans; seno, pegar um agasalho e uma cala jeans Passo 5 Vestir a roupa escolhida Passo 6 Se tem caf, tomar caf, seno, ir para ponto de nibus Passo 7 Enquanto nibus no vem, ler matria de AED1 Passo 8 Entrar no nibus Passo 9 Se tem carto de passe, pagar com carto, seno, pagar com dinheiro Passo 10 Repetir mentalmente 5 vezes a matria da prova Passo 11 Enquanto no chegar na escola, ouvir msica para relaxar Passo 12 Descer do nibus Passo 13 Entrar na escola Passo 14 Entrar na sala de aula Passo 15 Escolha a carteira vazia caso carteira 1 vazia, senta caso carteira 2 vazia, senta caso carteira 3 vazia, senta caso carteira 4 vazia, senta se no houver carteira vazia, procura em outra sala. Passo 16 Faz a prova.
Nesta seqencia de passos que levaram a soluo do problema (sair de casa e ir fazer a prova) pode-se observar diversas estruturas que podem ser usadas na construo de algoritmos. So elas. I. Passos 1, 2, 3, 5, 8, 12, 13, 14, 16: comandos diversos II. Passos 4, 6, 9: estrutura condicional (se ... seno) III. Passos 7, 11: estrutura de repetio sem nmero definido de repeties IV. Passo 10: estrutura de repetio com nmero definido de repeties (repetir 5 vezes) V. Passo 16: estrutura condicional mltipla (determina uma dentre vrias opes)
Obs: Para cada uma das estruturas identificadas no algoritmo acima, existem construes nas linguagens que fazem as mesmas funes.
6
1.2 TIPOS DE ALGORITMOS
1.1.1 Descrio Narrativa
Consiste em analisar o enunciado do problema e escrever, utilizando uma linguagem natural (por exemplo, portugus), os passos a serem seguidos para sua resoluo. Vantagem: no necessrio aprender nenhum conceito novo, pois uma linguagem natural, neste ponto, j bem conhecida. Desvantagem: a lngua natural abre espao para vrias interpretaes, o que posteriormente dificultar a transcrio desse algoritmo para programa.
1.1.2 Fluxograma
Consiste em analisar o enunciado do problema e escrever, utilizando smbolos grficos predefinidos, os passos a serem seguidos para sua resoluo Vantagem: o entendimento de elementos grficos mais simples que o entendimento de textos. Desvantagem: necessrios aprender a simbologia dos fluxogramas e, alm disso, o algoritmo resultante no apresenta muitos detalhes, dificultando sua transcrio para um programa.
Os smbolos utilizados podem ser vistos na Tabela 1.1.
Tabela 1.1
1.1.3 Pseudocdigo (ou Portugol)
Consiste em analisar o enunciado do problema e escrever por meio de regras predefinidas, os passos a serem seguidos para sua resoluo
Vantagem: a passagem do algoritmo para qualquer linguagem de programao quase imediata, bastando conhecer as palavras reservadas dessa linguagem que sero utilizadas. Desvantagem: necessrio aprender as regras do pseudocdigo, como se fosse uma nova linguagem (bem mais simples).
Obs: Qual tcnica utilizar? A descrio narrativa pode levar a imprecises. Fluxogramas so bons, mas so trabalhosos para desenhar e no mostram muitos detalhes. Portugol em geral mais fcil de escrever e passar o algoritmo para a 7
linguagem muito fcil. A seguir mostra-se um exemplo de algoritmo descrito nos trs tipos. Utilize o que melhor descreve o problema.
Exemplo: Fazer um algoritmo para mostrar o resultado da diviso de dois nmeros.
Descrio narrativa: Passo 1 Receber os dois nmeros que sero divididos. Passo 2 Se o segundo nmero for igual a zero, no poder ser feita a diviso, pois no existe diviso por zero; caso contrrio, dividir os nmeros e mostrar o resultado da diviso. Fluxograma:
Figura1.1 Portugol:
INICIO_ALGORITMO
DECLARE N1, N2, D NUMRICO ESCREVA Digite dois nmeros LEIA N1, N2 SE N2 == 0 ENTO ESCREVA Impossvel dividir SENO INCIO D N1 /N2 ESCREVA Diviso = , D FIM_SENO
FIM_ALGORITMO
As setas no Portugol marcam o incio e fim dos diversos blocos existentes.
8
EXEMPLOS DE ALGORITMOS
1. Fazer um algoritmo para calcular a mdia aritmtica entre duas notas de um aluno. Se esta mdia for maior ou igual a 7, o aluno est aprovado, caso contrrio, estar reprovado. Mostrar esta situao.
FLUXOGRAMA
Figura 1.2
PORTUGOL
INICIO_ALGORITMO
DECLARE N1, N2, M NUMRICO ESCREVA Digite as duas notas LEIA N1, N2 M (N1+N2)/2; ESCREVA Media = , M SE M 7 ENTO ESCREVA Aprovado SENO ESCREVA Reprovado
FIM_ALGORITMO
9
2. Fazer um algoritmo para calcular o novo salrio de um funcionrio. Sabe-se que os funcionrios que recebem atualmente um salrio de at R$500,00 tero um aumento de 20%; os demais tero um aumento de 10%.
FLUXOGRAMA
Figura 1.3 PORTUGOL
INICIO_ALGORITMO
DECLARE SAL _ATUAL, NOVO_SAL NUMRICO ESCREVA Digite o salrio atual do funcionrio: LEIA SAL_ATUAL SE SAL_ATUAL 500 ENTO NOVO_SAL NOVO_SAL * 1.2 SENO NOVO_SAL NOVO_SAL * 1.1 ESCREVA Novo Salario = , NOVO_SAL
FIM_ALGORITMO
10
1.3 LINGUAGEM DE PROGRAMAO
Aps a elaborao dos algoritmos, o prximo passo a escrita do programa. O programa ento nada mais do que a reescrita do algoritmo em uma linguagem de programao.
Uma linguagem de programao um mtodo padronizado para comunicar instrues para um computador. um conjunto de regras sintticas e semnticas usadas para definir um programa de computador. Assim, linguagens de programao podem ser usadas para expressar algoritmos com preciso.
O conjunto de palavras, composto de acordo com essas regras, constitui o cdigo fonte de um software. Esse cdigo fonte depois traduzido para cdigo de mquina (seqncias de 0s e 1s), que executado pelo processador.
1.3.1. HISTRICO DE LINGUAGENS DE PROGRAMAO
A primeira linguagem de programao de alto nvel amplamente usada foi Fortran, criada em 1954. Em 1957 foi criada B-0, sucessora da A-0, que daria origem a Flow-Matic (1958), antecessor imediato de COBOL, de 1959. O COBOL foi uma linguagem de ampla aceitao para uso comercial. A linguagem ALGOL foi criada em 1958-1960. O ALGOL-60 teve grande influncia no projeto de muitas linguagens posteriores.
A linguagem Lisp foi criada em 1958 e se tornou amplamente utilizada na pesquisa na rea de cincia da computao, mais proeminentemente na rea de Inteligncia Artificial. Outra linguagem relacionada ao campo da IA que surge em 1972 a linguagem Prolog, uma linguagem do paradigma lgico.
A linguagem C uma linguagem de programao compilada de propsito geral, estruturada, imperativa, procedural, padronizada pela ISO. Foi criada em 1972 por Dennis Ritchie, no AT&T Bell Labs, para desenvolver o sistema operacional Unix (que foi originalmente escrito em Assembly).
C uma das linguagens de programao mais populares e existem poucas arquiteturas para as quais no existem compiladores para C. C tem influenciado muitas outras linguagens de programao, mais notavelmente C++, que originalmente comeou como uma extenso para C.
A orientao a objetos outro marco importante na histria das linguagens de programao. A linguagem Simula 67 introduz o conceito de classes. A linguagem Smalltalk expande o conceito de classes e se torna a primeira linguagem de programao que oferecia suporte completo programao orientada a objetos. A linguagem C++ (originalmente conhecida como C com classes) populariza a orientao a objetos.
Diversas linguagens de programao surgiram desde ento, grande parte orientadas a objetos. Entre estas incluem-se C, VB.NET, Java, Object Pascal, Objective-C, PHP, Python, SuperCollider e Ruby.
1.3.2. TRADUTOR
programa que traduz outro, escrito em uma linguagem de programao (programa fonte), para um terceiro, escrito em linguagem de mquina, ou outra qualquer (programa objeto) (Figura 1.4).
11
Figura 1.4
O processo de traduo pode ser feito por:
COMPILAO: cada comando de alto nvel convertido em uma srie de instrues em linguagem da mquina.
INTERPRETAO: cada comando da linguagem diretamente executado, produzindo um resultado imediato. Economiza memria, mas a rapidez de execuo comprometida; e tem depurao mais simples.
RESUMO
Basicamente o que faremos no restante do curso :
1. Ser submetido a um problema computacional; 2. Analisar o problema e escrever um algoritmo para resolv-lo; 3. Testar o algoritmo; 4. Escrever o programa em linguagem C correspondente (Etapa de Edio). a. Para tanto ser utilizado o ambiente Code Blocks. b. O Code Blocks um ambiente de desenvolvimento integrado de cdigo aberto e multiplataforma, muito usado para o desenvolvimento em C/C++. c. No programaremos em C++, mas utilizaremos alguns recursos do C++ (cin, cout, referncia). 5. Compilar o programa usando o Code Blocks (Etapa de Compilao); 6. Testar o programa (Etapa de Depurao, debbug);.
12
1.4 VARIVEIS
Nos pseudocdigos mostrados anteriormente, encontramos locais para guardarmos os valores do salrio atual e do novo salrio. Estes locais so SAL_ATUAL e NOVO_SAL, e so as variveis do algoritmo.
As variveis so posies de memria RAM alocadas na hora que as variveis so criadas. Uma varivel possui nome e tipo e seu contedo pode variar ao longo do tempo, durante a execuo do programa. Embora possa assumir diferentes valores, ela s pode armazenar um valor a cada instante.
A Figura 1.5 ilustra o conceito de varivel em memria (RAM). Cada varivel ocupa uma posio de memria. A varivel SAL_ATUAL est na posio 101 e NOVO_SAL est na posio 102.
Existem diversos tipos diferentes de variveis, como por exemplo, variveis que representam nmeros inteiros (int), nmeros reais (float, double), textos (string) e caractere (char). Todas ocupam posies de memria (endereos), como mostra a Figura 1.8. Alm do endereo, cada varivel tem seu valor, de acordo com o seu tipo. Estes valores que ficam armazenados nas posies de memria.
Figura 1.5
1.5 TIPOS DE DADOS
1.5.1 NUMRICOS
INTEIROS Os nmeros inteiros podem ser positivos ou negativos e no possuem parte fracionria. Exemplo: 2, -10, 234, 0, -1234
REAIS Os nmeros reais podem ser positivos ou negativos e possuem parte fracionria. Exemplo: 12.56, 345,67, -2.45, 56.987
1.5.2 LGICOS So tambm chamados dados booleanos (por causa da lgebra de Boole). Podem assumir os valores verdadeiro (TRUE) ou falso (FALSE).
SAL_ATUAL NOVO_SAL X Y Z ... A 100
101
102
103
104
200 MEMRIA RAM 13
1.5.3 CARACTERE So dados formados por um nico caractere. Podem ser letras maisculas, minsculas, nmeros (no podem ser usados para clculos) e caracteres especiais (&, #,@,?, +, etc) . No programa, devemos colocar um caractere ou uma varivel do tipo caractere entre apstrofes.
1.5.4 TEXTO ou STRING So dados formados por mais de um caractere. Por exemplo: Isto e uma string, Joao da Silva, (031)22334455.
1.6 IDENTIFICADORES
Identificadores so os nomes das variveis, dos programas, das constantes, das rotinas, das unidades etc. Os identificadores possuem regras bsicas para sua formao:
1. Os caracteres que podem ser utilizados so: os nmeros, as letras (maisculas e minsculas) e o caractere sublinhado (underline). 2. .O primeiro caractere deve ser sempre uma letra ou caractere sublinhado (underline). 3. No so permitidos espaos em branco e caracteres especiais (@, $, %, &, !, ?). 4. No podem ser usadas palavras reservadas nos identificadores, ou seja, palavras que pertenam a uma linguagem de programao. Utilize nomes que dizem respeito funo da varivel. Por exemplo, uma varivel usada para contar nmeros digitados poderia ser identificada por contNum. Seria bem melhor do que Xy??zZ4.
EXERCCIOS RESOLVIDOS - ALGORITMOS
1. Escreva um programa para mostrar o resultado da multiplicao de dois nmeros.
Descrio narrativa: Passo 1 - Inicializar dois nmeros que sero multiplicados Passo 2 - Multiplicar os nmeros Passo 3 - Mostrar o resultado obtido na multiplicao
Fluxograma:
14
Pseudocdigo:
ALGORITMO DECLARE n1, n2, result NUMRICO INICIALIZE n1 INICIALIZE n2 result n1 * n2 ESCREVA O resultado da multiplicacao e: , result FIM_ALGORITMO
Codificao em Linguagem C++:
#include <iostream> // biblioteca que contm os camandos cin, cout
using namespace std;
int main() { int x, y, resp; // declarao das variveis cout << "Multiplicando dois numeros." << endl; // impresso de mensagem na tela
x=5; // atribuio do valor 5 varivel x y=7; // atribuio do valor 7 varivel y resp = x*y; // o valor x*y atribudo resp
cout << "O resultado da multiplicacao e: " << resp << endl; return 0; } Sada do Programa:
2. Faa um algoritmo para mostrar o resultado da diviso de dois nmeros.
Descrio narrativa:
Passo 1 - Receber os dois nmeros que sero divididos Passo 2 - Se o segundo nmero for igual a zero, no poder ser feita a diviso, pois no existe diviso por zero; caso contrrio, dividir os nmeros e mostrar o resultado da diviso
Fluxograma:
15
Pseudocdigo:
ALGORITMO DECLARE n1, n2, result NUMRICO INICIALIZE n1 INICIALIZE n2 Se n2 = 0 ESCREVA IMPOSSIVEL DIVIDIR POR ZERO Senao result n1 / n2 ESCREVA O resultado da diviso e: , result FIM_SENAO FIM_ALGORITMO
Codificao em Linguagem C++:
#include <iostream>
using namespace std;
int main() { int x, y, resp; cout << "Dividindo dois numeros." << endl;
x=10; y=2;
cout << "x = " << x << " y = " << y << endl;
if (y==0) // se y=0 no imprime cout << "Impossivel dividir por zero." << endl; else // seno,calcula a divisao e imprime { resp = x/y; cout << "O resultado da multiplicacao e: " << resp << endl; }
return 0; }
Sada do Programa para x=10 e y=2:
Sada do Programa para x=10 e y=0:
16
EXERCCIOS - ALGORITMOS
Para cada problema abaixo, escreva o algoritmo correspondente (usando fluxograma ou Portugol). Tente tambm, de acordo com seus conhecimentos adquiridos no laboratrio, codificar em linguagem C++.
1. Escreva um algoritmo que calcule e mostre a rea de um crculo.
2. Faa um algoritmo que leia um nmero positivo e maior que zero, calcule e mostre: a) o nmero digitado ao quadrado; b) o nmero digitado ao cubo; c) a raiz quadrada do nmero digitado d) a raiz cbica do nmero digitado
Faa um algoritmo que receba uma medida em ps, faa as converses e mostre os resultados em polegada, jardas e milhas. Por exemplo:
Digite o valor em ps: foi digitado 100 Valor em polegadas: 1200 Valor em jardas : 33.3 Valor em milhas : 0.018
4. Faa um algoritmo que receba o ano de nascimento de uma pessoa e o ano atual, calcule e mostre: a) A idade dessa pessoa; b) quantos anos ela ter em 2050;
5. Cada degrau de uma escada tem X de altura. Faa um algoritmo que leia essa altura e a altura que o usurio deseja alcanar, subindo a escada. Calcule e mostre quantos degraus ele dever subir para atingir seu objetivo, sem se preocupar com a altura do usurio. Todas as medidas podem estar em metros.
6. Faa um algoritmo que leia o custo de um espetculo teatral e o preo do convite desse espetculo. Esse programa dever calcular e mostrar a quantidade de convites que devem ser vendidos para que pelo menos o custo do espetculo seja alcanado.
17
1.7 OPERADORES E FUNES PREDEFINIDAS EM C, C++
A linguagem C++ possui operadores e funes predefinidas destinadas a clculos matemticos e manipulao de caracteres. Um operador muito utilizado o de atribuio:
18
19
EXERCCIOS
1. Faa um programa que calcule e mostre a rea de um tringulo.
2. Faa um programa que calcule e mostre a rea de um crculo.
3. Faa um programa que receba um nmero positivo e maior que zero, calcule e mostre: a. o nmero digitado ao quadrado; b. o nmero digitado ao cubo; c. a raiz quadrada do nmero digitado; d. a raiz cbica do nmero digitado.
4. Faa um programa que receba dois nmeros maiores que zero, calcule e mostre um elevado ao outro.
20
2. ESTRUTURAS SEQUNCIAIS
2.1- Estrutura Seqencial
Bibliotecas so arquivos contendo vrias funes que podem ser incorporadas aos programas escritos em C/C++. A diretiva # include faz com que o texto contido dentro da biblioteca especificada seja inserido no programa.
As bibliotecas iostream.h e conio.h permitem a utilizao de diversos comandos de entrada e sada.
A linguagem C/C++ sensvel a letras maisculas e minsculas, ou seja, considera que letras maisculas so diferentes de minsculas (por exemplo, a diferente de A).
Todos os comandos devem, obrigatoriamente, ser escritos com letras minsculas.
2.2- Comandos de Atribuio
Utilizado para atribuir valores ou operaes a variveis.
ALGORITMO
DECLARE X NUMERICO DECLARE Y, Z REAL DECLARE RESP LOGICO Bloco de Comandos
FIM_ALGORITMO C++ #include <biblioteca>
int main() { int x; float y,z; boolean resp; Bloco de Comandos } ALGORITMO
DECLARE X NUMERICO DECLARE Y, Z REAL DECLARE RESP LOGICO X 4 Y 4.5 Z 100.56 RESP true Bloco de Comandos
FIM_ALGORITMO C++ int main() { int x; float y,z; boolean RESP; x=4; y=4.5; resp = true; Bloco de Comandos } 21
As variveis so declaradas aps a especificao de seus tipos. Alguns compiladores C++ no possui dados do tipo booleano, pois considera qualquer valor diferente de zero como sendo verdadeiro. O CodeBlocks possui o tipo bool. C++ no possui tipo especial para armazenar cadeias de caracteres (strings).
2.3 - Comando de entrada
Utilizado para receber dados digitados pelo usurio. Os dados recebidos so armazenados em variveis. Os comandos de entrada mais utilizados na linguagem C++ so: cin e gets.
2.4 - Comando de sada
Utilizado para receber dados digitados pelo usurio. Os dados recebidos so armazenados em variveis. O comando de sada mais utilizado na linguagem C++ : cout. Um outro comando, chamado printf oriundo do C padro, mas bastante utilizado. Alm disso, os compiladores C para microcontroladores utilizam o printf, e no o cout, para sada de dados.
2.5 Comentrios em C++
Comentrios so textos que podem ser inseridos em programa com o objetivo de document-lo. Os comentrios no so analisados pelo compilador. Os comentrios podem ocupar uma ou vrias linhas, devendo ser inseridos nos programas utilizando /* */ para mais de uma linha ou // para um comentrio de uma linha. Exemplo: /* Linhas de comentrios... Linhas de comentrios... */ Ou
// Linha de comentrio ALGORITMO
LEIA X LEIA NOME Bloco de Comandos
FIM_ALGORITMO C++ int main() { int x; char nome[40]; cin >> x; gets(nome); Bloco de Comandos } ALGORITMO
ESCREVA X Bloco de Comandos
FIM_ALGORITMO C++ int main() { int x; cout << x; Bloco de Comandos } 22
EXEMPLO: CLCULO DA REA DE UM TRIANGULO
Pseudocdigo
ALGORITMO DECLARE base, altura, area NUMRICO ESCREVA "Digite o valor da base do tringulo: " LEIA base ESCREVA "Digite o valor da altura do tringulo: " LEIA altura area <- (base * altura)/2 ESCREVA "A area do tringulo e: ", area FIM_ALGORITMO
Fluxograma
Codificao em Linguagem C++:
#include <iostream>
using namespace std;
int main() { float base, altura, area; cout << "Calculo da area de um triangulo ." << endl;
cout<<"Digite a base do triangulo: "; cin>>base; cout<<"Digite a altura do triangulo: "; cin>>altura; area = (base * altura)/2; cout<<"A area do triangulo e: "<<area << endl;
return 0; }
Sada do Programa:
23
EXERCCIOS
1. Faa um programa em C++ para somar dois nmeros e multiplicar o resultado pelo primeiro nmero. Dever ser impresso na tela o resultado final das operaes.
2. Faa um programa em C++ que receba trs notas, calcule a soma das notas e mostre na tela a mdia aritmtica dessas notas.
3. Faa um programa em C++ que receba trs notas e seus respectivos pesos, calcule e mostre a mdia ponderada dessas notas.
4. Faa um programa em C++ que receba o salrio de um funcionrio, calcule e mostre o novo salrio, sabendo-se que este sofreu um aumento de 25%.
5. Faa um programa em C++ que receba a base e a altura e calcule a rea de um triangulo.
6. Faa um programa em C++ que receba um nmero positivo maior que zero, calcule e mostre: a. O nmero digitado ao quadrado; b. O nmero digitado ao cubo; c. A raiz quadrada do nmero digitado.
24
3. ESTRUTURAS CONDICIONAIS
3.1. ESTRUTURA CONDICIONAL SIMPLES
Na forma de Algoritmos
Caso 1: deve ser executado apenas um comando
Se condio Ento comando
O comando s ser executado se a condio for verdadeira, Uma condio uma comparao que possui dois valores possveis, verdadeiro ou falso.
Caso 2: devem ser executados vrios comandos
Se condio Ento INCIO comando1 comando2 ... comandon FIM
Obs: Os comandos 1, 2 ... n s sero executados se a condio for verdadeira. As palavras INCIO e FIM sero necessrias apenas quando dois ou mais comandos forem executados.
3.2. ESTRUTURA CONDICIONAL COMPOSTA
Se condio Ento comando1 Seno comando2
Se a condio for verdadeira, ser executado o comando1, caso contrrio, se a condio for falsa, ser executado o comando2.
Na forma de Algoritmos
Se condio Ento INCIO comando1 comando2 FIM Seno INCIO comando3 comando4 FIM
Se a condio for verdadeira, o comando1 e o comando2 sero executados; caso contrrio, se a condio for falsa, o comando3 e o comando4 sero executados.
25
EXEMPLOS
1. Faa um algoritmo (pseudocdigo e fluxograma) que receba um nmero como entrada. Verifique se o nmero maior ou igual a 2 e mostre na tela uma mensagem.
Algoritmo:
ALGORITMO DECLARE num NUMERICO ESCREVA "Digite um numero: " LEIA num SE (num >= 2) ENTO ESCREVA "O numero digitado maior ou igual a 2" SENO ENTO ESCREVA "O numero digitado menor que 2" FIM_ALGORITMO
Fluxograma:
Cdigo em C++
//Bibliotecas... int main() { float num1; cout<<"Digite um numero: "; cin>> num1; if (num1 >=2) { cout<<"o numero "<<num1<<" O numero digitado e maior ou igual a dois"; } else { cout<<"o numero "<<num1<<" O numero digitado e menor que dois"; } getch(); }
26
2. Faa um algoritmo (pseudocdigo e fluxograma) que receba dois nmeros como entrada e mostre na tela o maior. Algoritmo:
ALGORITMO DECLARE num1, num2 NUMERICO ESCREVA "Digite o primeiro numero" LEIA num1 ESCREVA "Digite o segundo numero" LEIA num2 SE (num1 > num2) ENTO ESCREVA "O maior numero " , num1 SENO SE (num2 > num1) ENTO ESCREVA "O maior numero " , num2 SENO ENTO ESCREVA "Os nmeros so iguais !" FIM_ALGORITMO
Fluxograma:
Cdigo em C++
int main() { float num1, num2; cout<<"Digite um numero: "; cin>> num1; cout<<"Digite outro numero: "; cin>> num2; if (num1 > num2) { cout<<"o numero "<<num1<<" e maior que o numero "<<num2; } else { if (num1 < num2) { cout<<"o numero "<<num2<<" e maior que o numero "<<num1; } else { cout<<"os numeros sao iguais"; } } getch(); } 27
Podem ocorrer casos em que uma varivel pode assumir vrios valores, e seja necessrio escolher uma opo e desconsiderar as outras. Nestes casos, utilizando a estrutura se ento seno, poderiam ocorrer vrios nveis, tornando o cdigo confuso e difcil de entender. Por exemplo:
if (numero == 10) { cout<<" numero = 10 "; } else { if (numero == 20) { cout<<" numero = 20 "; } else { if (numero == 30) { cout<<" numero = 30 "; } else { if (numero == 40) { cout<<" numero = 40 "; } else { if (numero == 50) { cout<<" numero = 50 "; } ... }
}
} }
Para estes casos, existe uma estrutura apropriada e mais clara. a estrutura switch-case, mostrada abaixo:
switch(varivel) { case valor1: lista de comandos; break; case valor2: lista de comandos; break; ... default: lista de comandos; }
Em situaes mutuamente exclusivas, isto , se uma situao for executada, as demais no sero, um comando seletivo o mais indicado (estrutura CASE) O comando switch avalia o valor da varivel para decidir qual caseser executado Cada caseest associado a UM possvel valor da varivel, que deve ser obrigatoriamente, do tipo char ou int O comando break; deve ser utilizado para impedir a execuo dos comandos definidos nos cases subsequentes O comando default: executado quando o valor da varivel no coincidir com nenhum dos especificados nos cases
28
Exemplo de Fluxograma
Exemplo de cdigo em C++
//Bibliotecas... int main() { int num1; cout<<"Digite um numero: "; cin>> num1; switch (num1) { case 1: cout<<\n Numero 1"; break; case 2: cout<<\n Numero 2"; break; default: cout<<\n Numero diferente de 1 e 2"; } getch(); }
29
Exemplo de Aplicao
Elaborar um fluxograma que simule uma calculadora simples que some, subtraia, multiplique e divida dois nmeros.
Fluxograma:
30
Implementao em C++ usando o Code Blocks
#include <iostream> #include <conio.h> using namespace std;
int main() { int num1, num2, result; char operador; cout << "Exemplo do Switch Case!" << endl;
switch (operador) { case '+': result = num1+num2; break; case '-': result = num1-num2; break; case '*': result = num1*num2; break; case '/': result = num1/num2; break; default: cout<<"\n Operador invalido!"; } cout << "Resultado: " << result; getch(); return 0; } Sada do Programa
31
EXERCCIOS - ESTRUTURAS CONDICIONAIS
1. A nota final de um estudante calculada a partir de trs notas atribudas, respectivamente, a um trabalho de laboratrio, a uma avaliao semestral e a um exame final. A mdia das trs notas mencionadas obedece aos pesos a seguir.
Faa um programa que receba as trs notas, calcule e mostre a mdia ponderada e o conceito, de acordo com a Tabela 3.2.
Tabela 3.2.
2. Faa um programa que receba trs nmeros e os mostre em ordem crescente. Sempre sero digitados nmeros diferentes.
3. Faa um programa que receba trs nmeros obrigatoriamente em ordem crescente e um quarto nmero que no siga esta regra. Mostre, em seguida, os quatro nmeros em ordem decrescente. .Sempre sero digitados nmeros diferentes.
4. Faa um programa que recebe duas datas fornecidas pelo usurio. Cada data composta por trs valores inteiros, para dia, ms e ano. O programa deve determinar qual data cronologicamente maior e imprimir: a maior data : dd/mm/aaaa
5. Faa um programa que receba um valor inteiro de 1 a 12, e imprima o nome do ms correspondente. Se for digitado um nmero fora desta faixa, imprimir a mensagem valor de ms incorreto.
32
4. ESTRUTURAS DE REPETIO
Como imprimir os 5 primeiros nmeros a partir do nmero 1? Fcil, vamos imprimir de 1 em 1. Veja:
Obviamente no uma boa soluo. Para tanto, usamos as estruturas de repetio. So elas:
PARA (FOR)
ENQUANTO (CONDIO) ... FAA (WHI LE)
FAA ... ENQUANTO (CONDIO) (DO ... WHI LE)
4.1. FOR Utilizamos a estrutura for quando sabemos exatamente quantas repeties (loops) vamos necessitar. Por exemplo, no exemplo acima se sabe que sero 5000 repeties da ao de imprimir um inteiro. Dizemos que o loop ser executado exatamente 5000 vezes.
Em geral usamos uma varivel inteira para fazer a contagem das repeties. A varivel i tradicionalmente usada, mas qualquer nome pode ser usado, por exemplo: cont, contador, ct, etc.
Na forma de algoritmos o for fica:
PARA i = valor inicial at valor final FAA INCIO comando1 comando2 .... comandon FIM
Em linguagem C tem-se:
LOOP 33
for (i = valor inicial; condio; incremento ou decremento de k) { comando1; comando2 .... comandon }
Deve se enfatizado que essa estrutura utilizada quando se sabe o nmero de vezes em que um trecho do programa deve ser repetido.
Um exemplo prtico:
#include <iostream> #include <stdio.h>
using namespace std;
int main() { for ( int i=1; i <= 10; i++ ) // i++ o mesmo que i=i+1, o mesmo para ai-- { cout<< "\n O valor de i e: " << i; } cout << endl; }
Este programa ento repetir 10 vezes o que est entre as chaves. Assim ser impresso 10 vezes o valor da varivel i. A sada do programa ser:
34
Outro exemplo: Impresso dos nmeros pares de 0 a 50.
#include <iostream> #include <stdio.h>
using namespace std;
int main() { printf("Impressao dos numeros pares de 0 ate 50.\n\n"); for ( int i=0; i <= 50; i=i+2 ) // i++ o mesmo que i=i+1, o mesmo para ai-- { printf("%d ", i); } printf("\n"); return 0; }
A sada do programa ser:
4.2. WHI LE
Estrutura de repetio para um nmero indefinido de repeties, onde o teste da condio feito no incio. Neste caso no se sabe quantas repeties sero executadas. Quando a condio tornar-se falsa, o programa vai para o prximo comando depois do fim enquanto.
Na forma de algoritmos o while fica:
ENQUANTO(CONDIO VERDADEIRA) FAA INCIO comando1 comando2 .... comandon FIM LOOP O teste feito no incio do LOOP. 35
Deve se enfatizado que nessa estrutura o teste da condio feito no incio do loop. Caso a condio seja falsa antes da execuo do while, nenhum comando dentro do whileser executado.
int x, y; x = 1; y = 10; while (x < y) { x=x+1; printf("x= %d \ty= %d\n", x,y); if(x==y) printf("\nAgora x e igual a y.\n"); }
return 0; }
36
4.3. DO ... WHI LE
Estrutura de repetio para um nmero indefinido de repeties, onde o teste da condio feito no final. Neste caso tambm no se sabe quantas repeties sero executadas. Quando a condio tornar-se falsa, o programa vai para o prximo comando depois do fim enquanto.
Deve se enfatizado que nessa estrutura o teste da condio feito no final do loop. Caso a condio seja falsa antes da execuo do do ... while, pelo menos uma vez os comandos 1 a n sero executados.
Um exemplo prtico:
#include <iostream> #include <stdio.h>
using namespace std;
int main() { int x=0;
printf("Uso do do ... while.\n\n"); do { printf("x = %d\n", x); x = x + 1; } while (x <= 10);
return 0; }
LOOP O teste feito no final do LOOP. 37
EXERCCIOS - ESTRUTURAS DE REPETIO
1. Faa um programa em C++ para somar 10 notas e apresentar a mdia aritmtica das notas na tela. Use estrutura de repetio.
2. Faa um programa em C++ para receber 15 nmeros digitados por um usurio, identificar o maior e o menor nmero digitado. Mostre na tela o maior e o menor nmero.
3. Faa um programa em C++ que leia um nmero N e mostre na tela o valor lido e o fatorial desse valor.
4. Faa um programa em C++ que receba duas notas de seis alunos, calcule e mostre: a) A mdia aritmtica das duas notas de cada aluno; b) A mensagem que est na tabela a seguir:
c) O total de alunos aprovados; d) O total de alunos de exame; e) O total de alunos reprovados; f) A mdia da classe.
38
5. ARRANJO UNIDIMENSIONAL - VETORES
Da mesma forma que a teoria de conjuntos: o Uma varivel pode ser considerada como um elemento. o Uma estrutura de dados como um conjunto. Quando uma estrutura de dados for composta de variveis do mesmo tipo primitivo, tem-se um conjunto homogneo de dados, ou um vetor.
DECLARANDO VETORES EM C
Quando se declara um vetor, um espao em bytes reservado na memria e que se encontra linearmente disposto a partir de um endereo base. Por exemplo:
int nota[4];
nota um vetor de inteiros de tamanho 4, ou seja, cabem 4 inteiro no vetor, cujas posies vo de 0 a 3. So elas: nota[0], nota[1], nota[2], nota[3]
Obs.: vetor de tamanho m -> ndice 0 a (m-1)
Declarando uma varivel do tipo vetor:
tipo nome [tamanho_do_vetor];
tipo: indica do tipo de cada elemento do vetor nome: indica o nome da coleo de variveis tamanho_do_vetor: indica o tamanho do vetor de elementos, onde o menor valor 1. Declarando vetores em C: Exemplos:
int peso[10] peso um vetor de 10 elementos, onde cada elemento do tipo int float nota[41] Nota um vetor de 41 elementos, onde cada elemento do tipo float char nome[80] nome um vetor de 80 elementos, onde cada elemento do tipo char 39
Acessando elementos de um vetor
Para acessar os elementos do vetor, deve utilizar o valor do ndice desejado, juntamente com o nome da varivel, por exemplo, peso[2] est associado ao terceiro elemento do vetor pois o primeiro elemento est relacionado ao ndice 0.
Atribuindo valores a um vetor
Atribui o valor 3 ao primeiro elemento do vetor => vet[0] =3;
Atribui o valor 10 ao elemento de ndice 10 (dcimo primeiro elemento do vetor ) => vet[10] =10;
Inicializando um vetor na declarao: int valores[5] ={100, 200, 300, 400, 500};
Preenchendo e Imprimindo um Vetor
Preenchendo um vetor:
for (int i = 0; i < 10; i++) { cin >> num[i]; }
Imprimindo um vetor:
for (int i = 0; i < 10; i++) { cout << num[i]; }
Exemplo de utilizao de um Vetor
Faa um algoritmo para armazenar as 5 notas de um aluno. Em seguida calcular a mdia aritmtica das notas das 5 notas. Em seguida, escreva o programa em C++.
Pseudocdigo
ALGORITMO DECLARE notas[5], soma, media NUMRICO PARA i 1 AT 5 FAA INCIO ESCREVA "Digite a nota do aluno ",(i+1) LEIA notas[i] soma soma + notas[i] FIM media soma/5 ESCREVA "A media das notas e: ", media FIM_ALGORITMO Repare a Identao 40
Implementao C++
int main() { float notas[5], soma, media; soma = 0; media =0; for(int i = 0; i<5; i++) { cout<<"\n Digite a nota do aluno "<<(i+1)<<" : "; cin >> notas[i]; soma = soma + notas[i]; } media = soma/5; system("cls"); //usado para apagar o que est na tela cout<<"\n A media das notas e: "<<media; getchar(); }
Resultado:
Digite a nota do aluno 1: 15 Digite a nota do aluno 2: 15 Digite a nota do aluno 3: 15 Digite a nota do aluno 4: 15 Digite a nota do aluno 5: 15
Dadas as declaraes e inicializaes: int A[ ] = {12,13,14,15}; char B[ ] = ENGENHARIA ELTRICA;
Estas declaraes e inicializaes equivalem a: int A[4] = {12,13,14,15}; char B[20] = ENGENHARIA ELTRICA;
So duas notaes diferentes para a mesma coisa.
Observao sobre Vetores
O clculo do tamanho em bytes de um vetor est diretamente relacionado ao tamanho do vetor e do tipo do vetor. Tamanho em bytes = tamanho do tipo * tamanho do vetor. Na linguagem C no existe verificao dos limites de um vetor. Pode-se ultrapassar os limites e escrever dados no lugar de uma outra varivel ou mesmo no cdigo do programa. responsabilidade do programador prover a verificao dos limites onde for necessrio, de modo que nunca invada o espao de memria, de uma outra varivel.
EXERCCIOS - VETORES
1. Faa um programa que leia um vetor de 100 posies de nmeros inteiros e, em seguida, mostre somente os nmeros positivos.
2. Em uma cidade, sabe-se que, de janeiro ao final de fevereiro de 2012, no ocorreu temperatura inferior a 15C, nem superior a 40C. Faa um programa em C++ que armazene as temperaturas de cada dia em um vetor (de 30 posies), calcule e imprima: a) A menor e a maior temperatura ocorrida b) A temperatura mdia c) O nmero de dias nos quais a temperatura foi inferior a temperatura mdia
3. Faa um programa que leia 6 nmeros, armazene em um vetor. Calcular e exibir qual o maior nmero armazenado.
4. Faa um programa que leia 20 nmeros, armazene em um vetor. Calcular e exibir: a) A quantidade de nmeros mltiplos de 2; b) A quantidade de nmeros mltiplos de 3; c) A quantidade de nmeros NO mltiplos de 2 ou 5;
5. Faa um programa que leia a nota de 15 alunos e armazene em um vetor. Calcular e exibir: a) A menor nota e a posio do vetor em que est armazenada; b) A maior nota e a posio do vetor em que est armazenada; c) A mdia das notas da turma;
43
5.1 VETOR DE CARACTERES: STRINGS
String uma das mais teis e importantes formas de dados em C e usada para armazenar e manipular textos como palavras, nomes e sentenas. Em C e C++ string no um tipo de dados formal como em outras linguagens como Pascal, Basic e C#. String uma matriz do tipo char terminada pelo caractere null (\0). Cada caractere de uma string pode ser acessado como um elemento de um vetor do tipo char. A linguagem C++ utiliza vetores para armazenar uma cadeia de caracteres, onde cada posio representa um caractere . importante ressaltar que os compiladores identificam o fim de uma cadeia por meio do caractere nulo, ou seja, por meio de \0
5.1.1. CRIANDO STRINGS EM C++
Deve-se declarar sempre o vetor com uma posio a mais para armazenar o caractere nulo (\0). O nulo no precisa ser armazenado manualmente, isso feito automaticamente pelo compilador.
Ex.: Para armazenar a palavra CADEIA deve-se declarar um vetor do tipo char com 7 posies (que ocuparo posies contguas na memria). Veja a Figura abaixo.
char palavra[7]=CADEIA;
A varivel palavra, quando declarada pode ocupar qualquer posio na memria Entretanto, todas as posies do vetor ocupam espaos de memria adjacentes, sendo que cada caractere ocupa 1 byte. Note que q posio 6 reservado para o caractere nulo (\0).
A string palavra conhecida como uma string constante.
Exemplo 1: Criar a string CADEIA e imprimir.
No cdigo abaixo mostrado que pode-se inicializar uma string no momento que ela criada. Desse modo no necessrio se preocupar com o \0. Pode-se imprimir a string usando puts, printf ou cout.
using namespace std; int main() { puts("Inicializando uma string com o alfabeto.");
char alfabeto[27]; // 26 letras mais o NULL char letra; int i; for (letra='A', i=0; letra<='Z'; letra++, i++) { alfabeto[i] = letra; } alfabeto[i] = NULL; cout << "\nAs letras do alfabeto sao: " << alfabeto;
getchar(); return 0; }
45
5.1.2. INICIALIZANDO STRINGS EM C++.
1. INICIALIZAO NO MOMENTO DA DECLARAO COM CARACTERES ISOLADOS:
A varivel nome1 recebeu as letras separadamente (inclusive o caractere nulo). Por isso, cada uma das letras est envolvida por apstrofos (' ') essa a maneira de identificar um caractere isoladamente.
2. INICIALIZAO NO MOMENTO DA DECLARAO COM TEXTO:
A varivel nome2 recebeu uma palavra, recebendo automaticamente o caractere nulo. Por isso, a palavra Programa est entre aspas (" ") esta a maneira de identificar uma cadeia de caracteres.
3. INICIALIZAO POR MEIO DA ATRIBUIO (DEPOIS DA DECLARAO):
A varivel vet1 recebeu um valor constante (a palavra Programa). A funo strcpy (string copy) copia PROGRAMA em vet1, e ser vista posteriormente.
46
4. INICIALIZAO POR MEIO DA ATRIBUIO (DEPOIS DA DECLARAO):
Nesse caso, o contedo da varivel vet2 foi copiado na varivel vet1.
5. INICIALIZAO POR MEIO DO TECLADO:
O comando cin consegue armazenar valores vindos do teclado na varivel frase. No caso de uma cadeia de caracteres , esse comando consegue armazenar todos os smbolos digitados at a primeira ocorrncia do espao em branco. Veja o cdigo abaixo:
using namespace std; int main() { system("cls"); char frase[30];
puts("Inicializando uma string do teclado."); cout<<"Digite um texto: "; cin>> frase; puts(frase);
getchar(); return 0; }
A sada do programa deveria ser: Testando a entrada de string pelo teclado. Entretanto, somente foi impresso: Testando. Por que?
Porque tanto o cin quanto o scanf quando encontram o espao em branco, depois da palavra Testando, retornam e no lem a string completa. Como resolver este problema? 47
Use a funo GETS (pega string).
A funo gets armazena na varivel frase todos os smbolos digitados at a ocorrncia do ENTER. Esta funo exige a utilizao da biblioteca stdio.h. Assim o programa anterior, usando gets, ficaria como abaixo:
using namespace std; int main() { system("cls"); frase[30]; puts("Inicializando uma string do teclado usando gets."); cout<<"Digite um texto: "; gets(frase); puts(frase);
getchar(); return 0; }
A funo puts() usada para imprimir uma cadeia de caracteres inicializada com o uso da funo gets(). Pode-se usar tambm o cout ou o printf para imprimir avarivel frase.
Listagem completa do cdigo de teste usado na teoria acima:
int main() { // inicializando uma string char palavra[7]="CADEIA";
// escrevendo uma string puts("usando puts para imprimir a string: "); puts(palavra);
// veja que o printf poderia ser usado printf("\nUsando printf para imprimir a string: %s",palavra);
// veja que o cout tambem poderia ser usado cout << "\n\nUsando cout para imprimir a string: "; cout << palavra; getchar();
48
system("cls"); puts("Inicializando uma string com o alfabeto.");
char alfabeto[27]; // 26 letras mais o NULL char letra; int i; for (letra='A', i=0; letra<='Z'; letra++, i++) { alfabeto[i] = letra; } alfabeto[i] = NULL; cout << "\nAs letras do alfabeto sao: " << alfabeto;
getchar();
system("cls"); char frase[30];
puts("Inicializando uma string do teclado."); cout<<"Digite um texto: "; cin>> frase; puts(frase); fflush(stdin); // para limpar o buffer de teclado, lembra?
getchar();
system("cls"); puts("Inicializando uma string do teclado usando gets."); cout<<"Digite um texto: "; gets(frase); puts(frase);
getchar(); return 0; }
49
5.2. A BIBLIOTECA STRING.H
A biblioteca string.h contm vrias funes de manipulao de strings que facilitam muito o tratamento deste tipo de dado. A seguir so analisadas as principais funes desta biblioteca.
1. strcpy (str1, str2) A funo strcpy copia a cadeia str2 na cadeia str1 Sendo assim, a cadeia str1 ser substituda pela cadeia str2
2. strncpy (str1, str2,n) A funo strncpy copia os n primeiros caracteres da cadeia str2 na cadeia str1
3. strcat (str1, str2), stnrcat (str1, str2, n) A funo strcat concatena a str2 na cadeia str1, ou seja, acrescenta a str1 a cadeia str2 A funo strncat concatena os n primeiros caracteres da str2 na cadeia str1
4. resultado = strcmp(str1, str2) Compara duas cadeias de caracteres e retorna um nmero inteiro para a varivel resultado, que pode ser: a. Zero: se as duas cadeias forem iguais b. Um nmero menor que 0: se str1 for alfabeticamente menor que str2 c. Um nmero maior que 0: se str1 for alfabeticamente maior que str2 d. Obs: Essa funo considera letras maisculas como sendo smbolos diferentes de letras minsculas
5. resultado = stricmp (cadeia1, cadeia2), resultado = strcmpi (cadeia1, cadeia2) Compara duas cadeias de caracteres e retorna um nmero inteiro para a varivel resultado, que pode ser: a. Zero: se as duas cadeias forem iguais b. Um nmero menor que 0: se str1 for alfabeticamente menor que str2 c. Um nmero maior que 0: se str1 for alfabeticamente maior que str2 d. Obs: Essa funo considera letras e minsculas iguais
6. resultado = strncmp(str1, str2, n) Compara duas cadeias de caracteres da posio 0 at a posio n, e retorna um nmero inteiro para a varivel resultado, que pode ser: e. Zero: se as duas cadeias forem iguais f. Um nmero menor que 0: se str1 for alfabeticamente menor que str2 g. Um nmero maior que 0: se str1 for alfabeticamente maior que str2 h. Obs: Essa funo considera letras maisculas como sendo smbolos diferentes de letras minsculas
50
7. resultado = strnicmp(str1, str2, n) , resultado = strncmpi(str1, str2, n) Compara duas cadeias de caracteres da posio 0 at a posio n, e retorna um nmero inteiro para a varivel resultado, que pode ser: i. Zero: se as duas cadeias forem iguais j. Um nmero menor que 0: se str1 for alfabeticamente menor que str2 k. Um nmero maior que 0: se str1 for alfabeticamente maior que str2 l. Essa funo considera letras e minsculas iguais
8. tamanho = strlen (str1) A funo strlen retorna para a varivel tamanho o nmero de caracteres da cadeia str1.
9. valor = toascii(caractere) A funo toascii retorna para a varivel valor o valor numrico que representa o caractere na tabela ASCII. Essa funo exige a utilizao da biblioteca ctype.h.
10. caractere = int(valor) A funo int retorna para a varivel caractere o caractere ASCII que representado pelo nmero.
int main() { char texto1[]="PROGRAMA COMPUTADOR"; char texto2[]="PARA "; int tam;
tam = strlen(texto1); // retorna o tamanho da string em texto1 = 19 printf("\n tam = %d", tam);
tam = strlen(texto2); // retorna o tamanho da string em texto1 = 5 printf("\n tam = %d", tam); }
A sada ser: tam = 19 tam = 5
5.2. VETOR DE STRINGS
Se fizermos um vetor de strings estaremos construindo um vetor de vetores. Esta estrutura uma aranjo bidimensional de chars. Podemos ver a forma geral de uma vetor de strings como sendo:
A surge a pergunta: como acessar uma string individual? Fcil. s usar apenas o primeiro ndice. Ento, para acessar uma determinada string faa:
nome_da_varivel [ndice]
Exemplo: O programa a seguir declara um vetor de strings, o inicializa com strings fornecidas atravs teclado e no final de seu processamento mostra o resultado.
#include <iostream> #include <stdio.h> using namespace std;
int main() { char strings [5][100]; int count;
for (count=0;count<5;count++) { printf ("\n\nDigite a string %d: ", count+1); scanf ("%s",strings[count]); fflush(stdin); } printf ("\n\nAs strings que voce digitou foram:\n"); for (count=0;count<5;count++) printf ("%s\n",strings[count]);
return 0; } 52
EXERCCIOS
1. Faa um programa que receba uma frase, calcule e mostre a quantidade de palavras da frase digitada. 2. Faa um programa que inverta os caracteres de uma string. Seu programa deve fazer isso atravs de um procedimento que recebe uma string como parmetro e coloca a string invertida na mesma varivel recebida como parmetro.
3. Faa um programa que receba uma frase e uma palavra. Caso a frase contenha a palavra ESCOLA, substitua pela palavra digitada. Ex.: Frase: EU MORO PERTO DE UMA ESCOLA. MAS ESSA ESCOLA NO A MELHOR. Palavra: PADARIA Resposta: EU MORO PERTO DE UMA PADARIA. MAS ESSA PADARIA NO A MELHOR.
53
6. ARRANJO BIDIMENSIONAL - MATRIZES
Em C++ , possvel tambm definir arrays com 2 ou mais dimenses. Eles so arrays de arrays. Um array de duas dimenses podem ser imaginado como uma matriz (ou uma tabela). Para definir e acessar arrays de dimenses maiores, usamos colchetes adicionais ([ e ]).
Por exemplo: int tabela[3][5];
define um array bidimensional chamado tabela que uma matriz de 3 linhas por 5 colunas, onde cada valor do tipo inteiro. A matriz possui 3*5 = 15 elementos no total.
Os ndices da primeira dimenso vo de 0 a 2, e os ndices da segunda dimenso vo de 0 a 4, como mostra a Figura 6.1. Assim, para cada linha, temos 5 colunas.
Matrizes unidimensionais (mais conhecidas como vetores, visto no slide anterior) Matrizes bidimensionais e multidimensionais
Obs.: o limite de dimenses fica por conta da quantidade de recurso disponvel pelo compilador. Entretanto, as matrizes mais utilizadas possuem duas dimenses.
Onde: nome_varivel: o nome da varivel do tipo matriz [dimenso1, ..., dimenso2]: representam as possveis dimenses da matriz Tipo_dos_dados: o tipo de dados que poder ser armazenado
Por Exemplo, a matriz mostrada na Figura 6.2 tem 3 linhas por 5 colunas.
54
Figura 6.2.
Outro exemplo:
Figura 6.3.
ATRIBUINDO VALORES A MATRIZES
Semelhante a vetores, sempre se inicia com 0 os ndices das linhas e colunas. Ao referenciarmos um elemento, sempre comeamos pela linha. Por exemplo,
tabela[2][3] = 10; Significa que se est inicializando com 10 a posio da matriz tabela cuja linha 2 e a coluna 3. Exemplo 1:
int mat [2][6]; // declarao da matriz mat 2x6 mat [0][3] = 5 // acesso posicao(0,3), onde e colocado o valor 5
Atribui o valor 5 posio referente linha 0 coluna 3 da matriz MAT. Lembre-se que os ndices comeam por zero. Veja como fica esta inicializao na Figura 6.4.
0 1 2 3 4
0 1 2
55
Figura 6.4.
Exemplo 2:
mat [1][4] = 5 // acesso posicao(1,4), onde e colocado o valor 5
Atribui o valor 5 posio referente linha 1 coluna 4 da matriz MAT. Lembre-se que os ndices comeam por zero. Veja como fica esta inicializao na Figura 6.5.
Figura 6.5..
Exemplo 3:
char mat [4][3]; // declarao de uma matriz de caracteres mat 4x3 mat [3][2] = D; // acesso posicao(0,3), onde e colocado o valor 5
A Figura 6.6 mostra como fica a matriz mat:
Figura 6.6.
0
1
0 1 2 3 4 5 56
PREENCHENDO UMA MATRIZ
Para caminha-se em uma matriz, ou preencher as posies da matriz, basta fazer um for para linhas e outro for interno para colunas. O primeiro for varre as linhas, e o for interno, as colunas de cada linha. Assim, para acessar uma matriz basta fazer um for para as linhas e outro para as colunas, conforme mostra o trecho de cdigo abaixo, que coloca em cada posio da matriz tabela[5][10] o produto dos respectivos ndices de linha e coluna.
// preenche a tabela com a multiplicao dos ndices
for (l=0; l < 5; l++) for(c=0; c < 10; c++) tabela[l][c] = l*c;
O exemplo acima mostra que para preencher uma matriz, necessrio identificar todas as suas posies. Isto exige a utilizao de um ndice para cada dimenso da matriz, como mostra o exemplo abaixo:
... int mat[2][3];
for (int i=0; i < 2; i++) for(int j=0; j < 3; j++) { cout << Digite um valor; cin >> mat[i][j]; } Neste caso a matriz mat preenchida com os valores digitados pelo usurio. Fazendo o zinho, a Tabela 6.1 mostra passo a passo a evoluo dos ndices i e j e os valores digitados. Note para cada valor de i (0 e 1), j varia de 0 a 2.
Tabela 6.1
I J Tela Valor Digitado 0 0 Digite um valor: 3 0 1 Digite um valor: 9 0 2 Digite um valor: 10 1 0 Digite um valor: 15 1 1 Digite um valor: 6 1 2 Digite um valor: 1
A Figura 6.7 mostra como fica a matriz mat:
3 9 10 15 6 1
Figura 6.7.
57
IMPRIMINDO O CONTEDO DE UMA MATRIZ
Para mostrar os valores armazenados dentro de uma matriz, basta percorrer a matriz e imprimir o contedo de cada posio.Por exemplo:
float X[10][6];
for (i=0; i<10; i++) { for (j=0; j<6; j++) { cout<< X[i][j] ; } }
ARRAYS MULTIDIMENSIONAIS
Arrays multidimensionais podem ser inicializados usando listas aninhadas de elementos entre chaves. Por exemplo, um array bidimensional tabela com trs linhas e duas colunas pode ser inicializado da seguinte forma:
double tabela[3][2] = { {1.0, 0.0}, // linha 0 {-7.8, 1.3}, // linha 1 {6.5, 0.0} // linha 2 };
Quando o array inicializado, o tamanho da primeira dimenso pode ser omitido. A definio de array abaixo equivalente a dada anteriormente.
double tabela[][2] = { {1.0, 0.0}, // linha 0 {-7.8, 1.3}, // linha 1 {6.5, 0.0} // linha 2 };
Arrays Multidimensionais arrays de arrays
O formato da definio de um array de dimenso k, onde o nmero de elementos em cada dimenso n0; n1; : : : ; nk1, respectivamente, :
nome_tipo nome_array[n0][n1]:::[nk1];
Isto define um array chamado nome_array consistindo de um total de n0 x n1 x ..x nk -1 elementos, sendo cada elemento do tipo nome_tipo . Arrays multidimensionais so armazenados de forma que o ltimo subscrito varia mais rapidamente. Por exemplo, os elementos do array
int tabela[2][3];
so armazenados (em endereos consecutivos de memria) como
Um array de dimenso k, onde o nmero de elementos em cada dimenso n0; n1; ... n k-1 , respectivamente, pode ser imaginado como um array de dimenso n0 cujos elementos so arrays de dimenso k-1.
Por exemplo, o array bidimensional tabela, com 20 elementos do tipo int
pode ser imaginado como um array unidimensional de 4 elementos do tipo int[], ou seja, arrays de int; cada um dos 4 elementos um array de 5 elementos do tipo int:
O cdigo abaixo, que mostra a manipulao uma matriz de inteiros de tamanho 10x10.:
#define LIN 10 #define COL 10
int main() { int l; // numero da coluna int c; // numero da linha
int tabela[LIN] [COL]; // define a matriz tabela
cout << "Manipulacao de Matrizes!" << endl << endl;
// preenche a tabela com a multiplicao dos ndices
for (l=0; l < LIN; l++) for(c=0; c < COL; c++) tabela[l][c] = l*c;
// mostra colunas for (c=0; c < COL; c++) cout << " " << c << " ";
cout << endl ;
// mostra linhas for (l=0; l < LIN; l++) cout << l << endl;
getch(); return 0; }
Sada do programa: imprime os ndices da matriz tabela:
Figura 6.8 59
A Figura 6.9 mostra como ficaria a impresso dos contedos da matriz.
Figura 6.9
Note que existe uma formatao que mostra os contedos da multiplicao da linha pela coluna na sua posio correta. Assim, na linha 5, coluna 3, est o valor 15, que o valor de 5*3. Como colocar este valor na posio correta, ou seja, como produzir esta tabela, com todos os valores alinhados?
Precisa-se de uma funo que posicione o curso onde se deseja, ou seja, uma funo que coloque o cursor na linha e coluna desejadas. Alguns compiladores possuem a funo gotoxy(linha, coluna). Infelizmente o Code Blocks no possui esta funo. Para tanto, deve-se simular esta funo. O cdigo abaixo, que utiliza a biblioteca windows.h, implementa a funo gotoxy().
#include <windows.h> // necessaria para inicializar a posio do cursor
COORD coord = {0,0};
void gotoxy(int l, int c) { coord.X = c; coord.Y = l;
A para posicionar o cursor na linha 5, coluna 4, basta chamar a funo e imprimir o texto desejado naquela posio.
gotoxy(5,4); cout << texto posicionado;
60
EXERCCIOS SOBRE MATRIZ
1. O que ser impresso pelo cdigo abaixo:
int main () { int t, i, M[3][4]; for (t=0;t<3;t++) { for (i=0;i<4;i++) { M[t][i] = (t*4)+i+1; } }
for (t=0;t<3;t++) { cout<<"\n"; for (i=0;i<4;i++) { cout<<M[t][i]<<" - "; } } getch();
2. Faa um programa para preencher uma matriz M (2 x 3) cujos valores so lidos do teclado. Calcule e mostre a matriz R, resultante da multiplicao dos elementos de M pelo seu maior elemento.
3. Faa um programa que preencha uma matriz 5x 10 com nmeros inteiros lidos do teclado ou preenchidos aleatoriamente. Some cada uma das linhas, armazenando o resultado das somas em um vetor. A seguir, o programa dever multiplicar cada elemento da matriz pela soma da linha correspondente e mostrar a matriz resultante.
4. Na teoria dos sistemas, define-se o elemento MINMAX de uma matriz como o maior elemento da linha em que se encontra o menor elemento da matriz. Faa um programa que crie uma matriz 4x7 e a preencha com nmeros reais. A seguir calcule e mostre o seu MINMAX e sua posio (linha e coluna).
5. Crie um programa que preencha uma matriz M (4 x 5) e uma matriz N (5 x 2) com valores quaisquer. A seguir calcular o produto de M por N, armazenando em uma matriz O (4 x 2). Em seguida imprimir a matriz O.
61
7. FUNES
Um importante recurso apresentado nas linguagens de programao a modularizao. Um programa pode ser particionado em sub-rotinas bastante especficas. A linguagem C++ possibilita a modularizao por meio de funes.
Funes so blocos de instrues (pequenos trechos de programa, contendo algumas linhas de cdigo), que realizam tarefas especficas. Assim, programas grandes podem ser divididos em pequenas tarefas, atravs de funes, e tendem a ficarem menores e mais organizados.
Os programas em geral so executados seqencialmente, uma linha aps a outra. Quando uma funo chamada, o programa desviado para a funo. Todas as linhas de cdigo desta funo so executadas e ao final o programa volta para a linha imediatamente aps a chamada original da funo.
Um programa em C, C++ tem, no mnimo, uma funo chamada main, onde comea a execuo. Existem tambm outras funes predefinidas, que j foram usadas, tais como: gets(), printf(), scanf(), strcmp(), strcpy(), strlen(), entre outras.
Essas funes so adicionadas aos programas pela diretiva #include. O desenvolvedor tambm pode criar suas prprias funes, e mais de uma, dependendo do problema que est sendo resolvido pelo programa.
Uma das vantagens na utilizao de funes que elas podem ser utilizadas (chamadas) quantas vezes se desejar dentro de um programa. Assim, qualquer seqncia de instrues que aparea no programa mais de uma ma vez candidata a ser uma funo.
Cada funo pode receber vrios valores (parmetros) e pode devolver um valor (retorno). Sendo assim, quando se especifica uma funo deve-se deixar claro qual ser o tipo de retorno e quais os parmetros necessrios para a execuo da funo. Chama-se a sub-rotina que no retorna valores de procedimento.
Exemplo 1:
Veja o programa abaixo, que soma dois nmeros lidos do teclado:
#include <iostream> #include <conio.h> using namespace std;
int main() { int a, b, soma_num; cout << "Introducao a Funcoes" << endl; cout<<"Digite o primeiro numero: "; cin >> a; cout<< "Digite o segundo numero: "; cin >> b; soma_num = a + b; cout << "O valor da soma e : "<< soma_num;
getch(); return 0; } A sada do programa :
62
Imagine agora que esta soma de dois nmeros ser utilizada vrias vezes no programa, por exemplo 10 vezes. Assim, o cdigo dever ser repetido 10 vezes. Transformando est cdigo em uma funo, chamada funcaoSoma, pode-se escrev-lo apenas uma vez e utiliz-lo no programa quantas vezes forem necessrias.
Veja o cdigo abaixo, onde funcaoSoma e chamada duas vezes. Note a palavra reservada void antes do nome da funo. Esta palavra significa nulo e mostra que funcaoSoma no retorna nada. Note tambm os parntesis vazios depois do nome da funo. Isto significa que funcaoSoma no recebe parmetros.
#include <iostream> #include <conio.h>
using namespace std;
void funcaoSoma() { int a, b, soma;
cout<<"Digite o primeiro numero: "; cin >> a; cout<< "Digite o segundo numero: "; cin >> b; soma = a + b; cout << "O valor da soma e : "<< soma; }
int main() { cout << "Introducao a Funcoes" << endl;
// chamando a funo soma a primeira vez funcaoSoma(); cout << "\n\n";
// chamando a funo soma a segunda vez funcaoSoma();
getch(); return 0; } Sada do programa:
Assim, pode-se chamar funcaoSoma quantas vezes seja necessrio dentro do programa principal. A funo acima no recebe dados e no retorna nenhum dados. Uma forma bem conveniente de usar funes passando dados para a funo. Estes dados so chamados de parmetros. Alm disso, a funo tambm pode retornar o resultado do processamento. A forma geral de uma funo genrica :
tipo de retorno nome_da_funcao(lista de parametros)
63
Pode-se reescrever a funcaoSoma para receber dois parmetros e retornar o resultado, que a soma. Veja funcaoSoma reescrita recebendo parmetros e devolvendo o resultado. Logicamente, pode-se escrever vrias funes dentro de um mesmo programa. Note a varivel soma, dentro da funo. Esta varivel local e s conhecida dentro da funo.
cout<<"Digite o primeiro numero: "; cin >> a; cout<< "Digite o segundo numero: "; cin >> b;
// chamando a funcao soma revisada passando dois parametros: a e b // a funao retorna a soma. Para isto, utilizado a palavra reservada "return"
resultado = funcaoSomaRevisada(a, b);
printf("A soma de a = %d e b = %d e %d ", a, b, resultado);
getch(); return 0; } Sada do Programa:
Pode-se tambm imprimir diretamente o retorno da funo, sem a necessidade da varivel resultado. Veja o exemplo abaixo:
Obs: A declarao de uma funo chamada prottipo e uma instruo, geralmente colocada no incio do programa, que estabelece o tipo da funo e os argumentos que ela recebe. Assim o prottipo de funcaoSomaRevisada :
cout<<"Digite o primeiro numero: "; cin >> a; cout<< "Digite o segundo numero: "; cin >> b;
resultado = funcaoSomaRevisada(a, b);
printf("A soma de a = %d e b = %d e %d ", a, b, resultado);
int v1 = 20; int v2 = 30;
printf("\n\nA soma de v1 = %d e v2 = %d e %d.", v1, v2, funcaoSomaRevisada(v1, v2));
getch(); return 0; }
Assim, uma funo pode ter diversas caractersticas, quanto passagem de parmetros e ao retorno:
1. Funes sem passagem de parmetros e sem retorno 2. Funes com passagem de parmetros e sem retorno 3. Funes sem passagem de parmetros e com retorno 4. Funes com passagem de parmetro e com retorno
Outro exemplo de funo. Ela recebe uma temperatura em graus Farenheight e devolve a temperatura em graus Celsius.
int celsius(int fahr) { int c; c =(fahr - 32)* 5/9; return c; }
int main() { f, c;
cout << "\n Digite a temperatura em graus Fahrenheit: "; cin >> f; c = celsius(f); //chamada funo celsius cout << "\n Celsius = " << c;
getch(); return 0; } Sada do programa:
O cdigo abaixo comtm todas as funes mencionadas em um nico programa. Execute-o e veja o resultado. Ele mostra tambm que dentro de um programa, pode-se ter quantas funes se desejar e pode-se fazer quantas chamadas forem necessrias.
Alm disso, uma funo pode chamar outra, o quanto se desejar.
cout<<"Digite o primeiro numero: "; cin >> a; cout<< "Digite o segundo numero: "; cin >> b; soma = a + b; cout << "O valor da soma e : "<< soma; }
int funcaoSomaRevisada(int x, int y) { int soma;
soma = x + y; return soma; }
int celsius(int fahr) { int c; c =(fahr - 32)* 5/9; return c; }
int main() { int a, b, resultado, f, c;
cout<<"Digite o primeiro numero: "; cin >> a; cout<< "Digite o segundo numero: "; cin >> b;
// chamando a funcao soma revisada passando dois parametros: a e b // a funao retorna a soma. Para isto, utilizado a palavra reservada "return" resultado = funcaoSomaRevisada(a, b);
printf("A soma de a = %d e b = %d e %d ", a, b, resultado);
int v1 = 20; int v2 = 30;
printf("\n\nA soma de v1 = %d e v2 = %d e %d.", v1, v2, funcaoSomaRevisada(v1, v2)); getch();
// usanda a funcao celcius system("cls"); cout << "\n Digite a temperatura em graus Fahrenheit: "; cin >> f; c = celsius(f); //chamada funo cout << "\n Celsius = " << c;
getch(); return 0; } 67
O exemplo a seguir mostra uma calculadora que tem as quatro operaes bsicas: soma, subtrao, multriplicao e diviso. Cada uma das operaes realizada atravs de uma funo. No programa principal estas funes so chamadas.
// Corpo das funcoes: podem vir aqui ou depois do main. Deve-se tambm comentar as funcoes. // Abaixo segue um modelo.
/* -------------------------------------------------------------------------------------- * Nome: soma * Funo: soma dois numeros em ponto flutuante * Entradas: operandos a e b * Saida: a+b --------------------------------------------------------------------------------------- */ float soma(float a, float b) { float s; s = a + b; return s; }
/* -------------------------------------------------------------------------------------- * Nome: subtracao * Funo: subtrai dois numeros em ponto flutuante * Entradas: operandos a e b * Saida: a-b --------------------------------------------------------------------------------------- */ float subtracao(float a, float b) { float s; s = a - b; return s; }
/* -------------------------------------------------------------------------------------- * Nome: divisao * Funo: divide dois numeros em ponto flutuante * Entradas: operandos a e b * Saida: a/b --------------------------------------------------------------------------------------- */ float divisao(float dividendo, float divisor) { float q; q = dividendo / divisor; return q; }
68
/* -------------------------------------------------------------------------------------- * Nome:multiplicacao * Funo: multiplica dois numeros em ponto flutuante * Entradas: operandos a e b * Saida: a*b --------------------------------------------------------------------------------------- */ float multiplicacao(float num, float num2) { float total; total = num * num2; return total; }
int main() { system("cls"); cout << "Calculadora Basica" << endl;
do{ cout<<"\nDigite o primeiro valor: "; cin>>valor1; cout<<"\nDigite o segundo valor: "; cin>>valor2;
// chamada da funcao soma som = soma(valor1, valor2);
// chamada da funcao subtracao subt = subtracao(valor1, valor2);
// chamada da funcao multiplicacao mult = multiplicacao (valor1, valor2);
// chamada da funcao divisao div = divisao(valor1, valor2);
// imprimindo os resultados cout<<"\nO valor da soma de "<<valor1<<" e "<<valor2<<" eh: "<<som; cout<<"\nO valor da subtracao de "<<valor1<<" e "<<valor2<<" eh: "<<subt; cout<<"\nO valor da multiplicacao de "<<valor1<<" e "<<valor2<<" eh: "<<mult; cout<<"\nO valor da divisao de "<<valor1<<" e "<<valor2<<" eh: "<<div;
cout<<"\n\nDeseja sair (S/N)? "; cin>>opcao; } while (opcao == 'N' || opcao == 'n');
return 0; } Sada do Programa:
69
EXERCCIOS
1. Escreva uma funo chamada potencia ( ) que aceite dois parmetros inteiros e positivos i e j. A funo dever retornar o valor de i elevado potncia j . Lembre-se que uma potncia um produto de fatores iguais.
2. Escreva uma funo chamada le_numeros() e uma funo imprime_numeros(). A funo le_numeros() tem como objetivo solicitar que o usurio digite dois nmeros e ler do teclado. A funo imprime_numeros() tem como objetivo receber dois nmeros como parmetros e imprimir esses nmeros na tela.
3. Faa uma funo que receba dois nmeros positivos por parmetro e retorne a soma dos N nmeros inteiros existentes entre eles.
4. Faa uma funo que receba um nico valor representando segundos. Essa funo deve convert-lo para horas, minutos e segundos. Todas as variveis devem ser passadas como parmetros, no havendo variveis globais.
5. Elabore um programa contendo uma funo que recebe as trs notas de um aluno como parmetros e uma letra. Se a letra for A, a funo deve calcular a mdia aritimtica das notas do aluno; se for P, a funo dever calcular a mdia ponderada, com pesos 5, 3 e 2. A mdia calculada dever ser devolvida ao programa principal para ento, ser mostrada.
6. Foi realizada uma pesquisa sobre algumas caractersticas fsicas de dez habitantes de uma regio. Foram coletados os seguintes dados de cada habitante: sexo, cor dos olhos (A azuis, C - castanhos), cor dos cabelos (L louros, P pretos, C castanhos) e idade. Faa uma funo que leia esses dados, armazenando-os nos vetores sexo, olhos, cabelos e idades. Faa uma funo que determine e devolva ao programa principal a mdia de idade das pessoas com olhos castanhos e cabelos pretos. Faa uma funo que determine e devolva ao programa principal a maior idade entre os habitantes. Faa uma funo que determine e devolva ao programa principal a quantidade de indivduos do sexo feminino com idade entre 18 e 35 anos (inclusive) e que tenham olhos azuis e cabelos louros.
70
7.1. PASSAGEM DE PARMETROS POR VALOR E POR REFERNCIA
Considere o exemplo da funo troca(), mostrada abaixo.
void troca(int x, int y) { int temp; temp = x; x = y; y = temp; }
No main, troca() chamada passando duas variveis declaradas no main, por exemplo a e b. ... int a = 10, b = 5; troca(a, b);
Quando a e b so passados como argumentos para troca(), na verdade, somente seus valores so passados. A funo no pode alterar os valores de a e b porque ela no conhece os endereos de a e b.
Mas se referncias para a e b forem passados como argumentos ao invs dos valores de a e b, a funo troca() ser capaz de alterar seus valores, pois ela sabe ento em que endereo de memria escrever. Na verdade, a funo no sabe que os endereos de memria so associados com a e b, mas ela pode modificar o contedo destes endereos. Portanto, passando uma varivel por referncia (ao invs da varivel), habilitamos a funo a alterar o contedo destas variveis na funo chamadora.
A definio da funo troca() deve ser alterada, e a lista de parmetros formais deve ter argumentos no do tipo int, mas referncias para int, ou seja, int & .
Quando chamamos a funo troca(), ns continuamos passando parmetros reais a e b, mas desta vez, o compilador sabe que o que ser passado para a funo troca() so as referncias a estas variveis, e no seus valores. Dentro da funo troca() no dever haver mudanas.
Uma vez que agora os parmetros formais so referncias, o acesso aos objetos deve ser escrito normalmente, mas deve-se ter em mente que qualquer alterao nos valores dos parmetros formais da funo implica em alterar o valor dos argumentos passados para a funo no momento de sua chamada. Assim, a funo troca() capaz de alterar os valores de a e b remotamente.
O programa abaixo a verso correta do problema enunciado para a funo troca():
void troca(int &x, int &y) { int temp; temp = x; x = y; y = temp; }
No main, troca() chamada passando duas variveis declaradas no main, por exemplo a e b. ... int a = 10, b = 5; troca(a, b);
Agora os valores de a e bsero trocados, pois sero passados os endereos destas variveis para a funo troca(), e no mais seus valores. Para tanto, basta colocar o operador & antes do nome de x e y, indicando que estas variveis recebem os endereos de a e b, e no mais seus valores. Assim, alterando x, altera-se o valor armazenado no endereo 200 (varivel a), e alterando y, altera-se o valor armazenado no endereo 300 (varivel b). Veja na memria:
Repare que agora so passados os endereos de x e y, e no seus valores, usando &. 71
void troca(int &x, int &y) { int temp; temp = x; x = y; y = temp; }
int a = 10, b = 5; O cdigo abaixo mostra a passage de parmetros por referncia em C++.
#include <iostream> #include <stdio.h> #include <conio.h> using namespace std;
/* -------------------------------------------------------------------------------------- * Nome: troca * Funo: recebe a referencia (endereo) de duas variaveis e troca seus valores * Entradas: enderecos das variaveis originais, armazenados em px e py * Saida: valores alterados retornados por referencia --------------------------------------------------------------------------------------- */ void troca(int &px, int &py) { int temp; temp = px; px = py; py = temp; }
/* -------------------------------------------------------------------------------------- * Nome: naoTroca * Funo: recebe os valores de duas variaveis e troca seus valores localmente * Entradas: valores das variaveis originais, armazenados em px e py * Saida: nenjuma --------------------------------------------------------------------------------------- */ void naoTroca(int px, int py) { int temp; temp = px; px = py; py = temp; }
int main() { int a, b, c, d;
cout << "Passando parametros por Referencia." << endl; cout << "Entre dois numeros: "; cin >> a >> b; printf("\nValores antes de chamar a funcao troca: a = %d b = %d", a , b); troca(a, b); printf("\nValores depois de chamar a funcao troca: a = %d b = %d", a , b);
cout << "\n\nPassando parametros por Valor." << endl; cout << "Entre dois numeros: "; cin >> c >> d; printf("\nValores antes de chamar a funcao naoTroca: c = %d d = %d", c , d); naotroca(c, d); printf("\nValores depois de chamar a funcao naoTroca: c = %d d = %d", c , d);
getch(); return 0; } 100 200 300 400 500 ... 10
a
b ... 5
10 72
Sada do Programa:
Este resultado tambm mostra que agora, podemos retornar mais de um parmetro de uma funo. Na verdade podemos retornar quantos parmetros desejarmos, bastando para isso passar os parmetros por referncia. Os valores alterados dentro da funo sero alterados tambm no main.
7.2. VETORES COMO PARMETROS
Em algumas situaes precisamos passar um vetor para uma funo como um parmetro. Em C++ no possvel passar todo o vetor como parmetro. O que se passa o endereo (referncia) do vetor. Na prtica como se passssemos todo o vetor, mais esta uma operao muito mais rpida e eficiente.
Tudo o que preciso fazer para passar um vetor como parmetro especificar no prottipo da funo que vai receber o vetor um elemento do tipo vetor, com um identificador (nome) e a seguir um par de colchetes em branco [ ]. Por exemplo, a funo:
void recebeVet(int vet[]);
aceita um parmetro do tipo vetor de inteiros chamado vet. Para passar para esta funo um vetor chamado meuVetor, com 40 elementos, tem-se:
int main () { int primVetor[] = {5, 10, 15}; int segVetor [] = {2, 4, 6, 8, 10}; imprVetor(primVetor,3); imprVetor(segVetor,5); return 0; } 73
Sada do Programa:
5 10 15 2 4 6 8 10
Como pode ser visto, o primeiro parmetro int vet[] recebe qualquer vetor de inteiros, no importanto seu tamanho, pois na verdade passado o endereo do vetor. Por isto existe o segundo parmetro, length, que informa o tamanho do vetor.
Exemplo 2
#include <iostream> using namespace std;
void display(int num[]);
int main() { int t[10], i;
for(i=0; i < 10; ++i) t[i]=i;
display(t); // passagem de vetor para a funo display
return 0; }
void display(int num[]) { int i;
for(i=0; i < 10; i++) cout << num[i] << ' '; }
Sada do programa:
0 1 2 3 4 5 6 7 8 9
Exemplo 3
#include <iostream.h>
const int SIZE = 10;
float Total(float a[],int num) // recebe um vetor de floats e um inteiro { int i; float soma = 0; for (i=0; i < num ; i++) soma += a[i]; // o mesmo que soma = soma+ a[i] return soma; }
main() { float vet[SIZE]; // declara um vetor de 10 elementos
for (int i=0;i < SIZE; i++) // preenche o vetor vet[i]=i+i;
cout <<"Soma = " << Total( vet,SIZE) <<endl; // imprime a soma dos elem. de vet
cout << "Media = " << Total(vet,SIZE)/SIZE; // imprime a media dos elem. de vet return 0 ; }
/* -------------------------------------------------------------------------------------- * Nome: geraVetRandom * Funo: recebe um vetor de inteiros e preenche com numeros aleatorios * Entradas: vetor original (nao inicializado) * Saida: vetor preenchido com numeros aleatorios --------------------------------------------------------------------------------------- */ void geraVetRandon(int vet[]) { // inicializa gerador de numeros aleatorios int random; srand(time(NULL));
// preenche a matriz original com numeros aleatorios (<10) for (int i=0; i<TAM; i++) { random=rand()%10; vet[i]= random; } }
/* -------------------------------------------------------------------------------------- * Nome: imprVetor * Funo: recebe um vetor de inteiros e imprime * Entradas: vetor original * Saida: nenhuma --------------------------------------------------------------------------------------- */ void imprVetor(int vet[]) { printf("\n\nImprimindo o vetor:\n"); for(int i=0; i < TAM; i++) { if((i%30)==0) printf("\n"); // imprime 30 numeros por linha printf("%d ", vet[i]);
} }
75
int main() { int n; float soma=0;
cout << "Manipulacao de Vetores usando funcoes!" << endl;
// declara o vetor int vetor[TAM];
// preenche vet com numeros aleatorios geraVetRandon(vetor);
// imprime o vetor imprVetor(vetor);
printf("\n\n");
return 0; }
Sada do Programa:
EXERCCIOS
1. Escreva as funes descritas a seguir, utilizando um vetor de inteiros: a) geraVetRandom: recebe um vetor e seu tamanho e o preenche com nmeros aleatrios; b) imprVet: recebe um vetor e seu tamanho e o imprime; c) pesqVet: recebe uma vetor, seu tamanho e um valor inteiro. Pesquisa o valor. Se o valor est no vetor, devolve a posio da primeira ocorrncia do valor, caso contrrio, devolve -1; d) maiorVet: recebe um vetor e seu tamanho e devolve o seu maior valor; e) menorVet: recebe um vetor e seu tamanho e devolve o seu menor valor;
Utilizando as funes acima, faa um programa main que teste cada uma das funes acima, atravs de um menu de opes.
Dica para gerar nmeros aleatrios no Code Blocks: int num; srand(time(NULL)); // inicializa gerador de numeros aleatorios num=rand(); // gera numero aleatorio 76
7.3. MATRIZES COMO PARMETROS
O mesmo raciocnio utilizado para passar vetores para funes pode ser usado com matrizes. A nica diferena que pelo menos a segunda dimenso da matriz deve obrigatoriamente ser declarada no prottipo da funo. possvel passar matrizes (ou arranjos de dimenses maiores) como parmetros. Por exemplo, uma funo que recebe um arranjo tridimensional de inteiros pode ser declarada como:
void funTrid(int meuVetor[ ][3][4]);
Note que o primeiro par de colchetes so deixados em branco enquanto que os seguintes recebem as outras dimenses. Isto porque o compilador deve ser capaz de determinar dentro da funo qual a profundidade de cada dimenso adicional. Analise o cdigo abaixo.
/* -------------------------------------------------------------------------------------- * Nome: geraMatRandom * Funo: recebe uma matriz a preenche com numeros aleatorios * Entradas: matriz original * Saida: matriz preenchida com numeros aleatorios --------------------------------------------------------------------------------------- */ void geraMatRandom(int mat[][10]) { // inicializa gerador de numeros aleatorios int random; srand(time(NULL));
// preenche a matriz original com numeros aleatorios (<10) for (int linha=0; linha<10; linha++) { for(int coluna=0; coluna<10; coluna++) { random=rand()%10; mat[linha][coluna]= random; } } }
/* -------------------------------------------------------------------------------------- * Nome: imprMat * Funo: recebe uma matriz e imprime (sem formatacao) * Entradas: matriz original * Saida: nenhuma --------------------------------------------------------------------------------------- */ void imprMat(int mat[][10]) { for (int linha=0; linha<10; linha++) { for(int coluna=0; coluna<10; coluna++) { printf("%d ",mat[linha][coluna]); } printf("\n"); } }
77
/* -------------------------------------------------------------------------------------- * Nome: matTransp * Funo: recebe uma matriz e devolve sua transposta * Entradas: matriz original * Saida: matriz transposta --------------------------------------------------------------------------------------- */ void matrizTransposta(int matOrg[][10], int matTransp[][10]) { for (int linha=0; linha<10; linha++) { for(int coluna=0; coluna<10; coluna++) { matTransp[coluna][linha]=matOrg[linha][coluna]; } } }
int main() { int matOriginal[10][10]; int matTransposta[10][10]; int linha, coluna, numeroimpressao, nume;
// preenche a matriz original com numeros aleatorios geraMatRandom(matOriginal);
// imprime a matriz original imprMat(matOriginal);
// gera matriz transposta matrizTransposta(matOriginal, matTransposta);
printf("\n\n");
// imprime a matriz transposta imprMat(matTransposta);
printf("\n\n"); return 0; }
Sada do programa: 78
EXERCCIOS
1. Escreva a s funes descritas a seguir, utilizando uma matriz de inteiros: a) geraMatRandom: recebe uma matriz e seu tamanho (linhas e colunas) e a preenche com nmeros aleatrios; b) imprMat: recebe uma matriz e seu tamanho e a imprime; c) pesqMat: recebe uma matriz, seu tamanho e um valor inteiro. Pesquisa o valor. Se o valor est na matriz, devolve a posio (linha, coluna) da primeira ocorrncia do valor, caso contrrio, devolve -1; d) maiorMat: recebe uma matriz e seu tamanho e devolve o seu maior valor; e) menorMat: recebe uma matriz e seu tamanho e devolve o seu menor valor;
Utilizando as funes acima, faa um programa main que teste cada uma das funes, atravs de um menu de opes.
Dica para gerar nmeros aleatrios no Code Blocks: int num; srand(time(NULL)); // inicializa gerador de numeros aleatorios num=rand(); // gera numero aleatorio
2. Faa uma funo que recebe 3 valores inteiros por parmetro e retorna-os ordenados em ordem crescente.
3. Faa um programa que leia N conjuntos de 3 valores e os imprima ordenados, aps acionar o procedimento. (N deve ser lido do teclado).
4. Crie uma funo quad que recebe um vetor de inteiros e seu tamanho, e devolve o vetor com o quadrado de cada elemento. Faa um programa que leia 10 nmeros e armazene-os em um vetor. Imprima o vetor. A seguir,utilize a funo quad para imprimir no main, o vetor original com o quadrado dos elementos digitados.
79
8. REGISTROS EM C: STRUCT
Conceito de struct
Vetores e matrizes
Estruturas de dados homogneas Armazenam vrios valores, mas todos de um mesmo tipo (todos int, todos double, todos float, todos char)
Problemas reais
Temos colees de dados que so de tipos diferentes. Exemplo: ficha de um cadastro de cliente: Nome: string Endereo: string Telefone: string Salrio: float Idade: int
Caractersticas:
O registro um conjunto de dados logicamente relacionados; Utiliza vrios dados de tipos diferentes em uma mesma estrutura; Por isso considerado heterogneo; Cada elemento pode ser referenciado de forma nica pelo seu nome, ou seja, os elementos no so referenciados por um ndice como em uma matriz.
Conceito de struct
Campo (Field) Conjunto de caracteres com o mesmo significado Exemplo: nome
Registro (Struct ou Record) Conjunto de campos relacionados Exemplo: nome, endereo, telefone, salrio e idade de uma pessoa
80
Sintaxe na Linguagem C
A palavra reservada struct indica ao compilador que est sendo criada uma estrutura; Uma estrutura deve ser declarada aps incluir as bibliotecas e antes da main.
Se o compilador C for compatvel com o padro C ANSI:
Informao contida em uma struct pode ser atribuda a outra struct do mesmo tipo. No necessrio atribuir os valores de todos os elementos/campos separadamente: Por exemplo: <var1> = <var2> Todos os campos de <var1> recebero os valores correspondentes dos ampos de <var2>
Para acessar os campos da struct: Utiliza-se o nome da varivel struct, seguido de ponto, seguido do nome do campo. Por exemplo: <var1>.<nome_varivel_campo2>;
Por exemplo um struct endereo que guarda os elementos nome, rua, cidade, estado e cep:
struct endereo { char nome[30]; char rua[40]; long int cep; };
Foi feita apenas a declarao da struct, ainda no foi criada nenhuma varivel da struct endereo; O comando para declarar uma varivel com esta struct :
struct endereco meuEndereo;
obs: A palavra struct pode ser omitida. Assim a declarao pode ser:
endereco meuEndereo; // o compilador sabe que meuEndereo uma estrutura do tipo endereo
Portanto, considerando o exemplo anterior:
Para inicializar o cep da varivel meuEndereo que uma varivel da struct endereo se faria:
meuEndereo.cep = 123456;
Para obter o nome da pessoa e colocar na string nome da struct se poderia utilizar:
gets meuEndereo.nome);
Para imprimir o endereo seria:
printf(%s, meuEndereo.rua);
81
Na verdade existem diferentes formas de se declarar uma struct em C:
O uso mais comum de struct em vetores. Para declarar um vetor de struct: o Define-se a struct o Declara-se o vetor do tipo struct criado o Exemplos: (Lembre-se que a palavra struct pode ser omitida na declarao da varivel.)
aluno turmaAED1[55]; // turmaAED1 um vetor de 55 elementos, onde cada elemento // do tipo struct aluno
endereco endProf[25]; // endProf um um vetor de 25 elementos, onde cada elemento // do tipo struct endereco
Para manipular os dados do vetor, devem ser fornecidos o ndice e o campo
Tomemos como exemplo de Estrutura a estrutura que representa um pequeno cadastro:
struct cadastro // atribuindo um nome a estrutura { int idade; // int e um membro da estrutura do tipo int char nome[30]; // nome e um membro da estr. do tipo string float peso; // peso e um membro da estrutura do tipo float };
Se quizermos declarar uma varivel do tipo cadastro, poderamos ter:
struct cadastro cadastro_maria;
Como sabemos, esta declarao cria uma varivel do tipo estrutura, chamada cadastro_maria, contendo trs membros, idade (int), nome(string) e peso(float).
Cada membro dessa varivel pode ser acessado, especificando-se o nome da varivel e o identificador do membro, separados por um ponto. Assim, a instruo:
cout << cadastro_maria.idade;
ir imprimir o primeiro membro da estrutura, que a idade.
Aprendemos tambm que podemos declarar um ponteiro para uma estrutura. Podemos acessar os membros da estrutura atravs deste ponteiro, ao invs de acessar pelo nome da estrutura. Para tanto, usamos (->) para acessar membros da estrutura atravs de ponteiros. Assim, poderamos ter:
struct cadastro *ptr_cadastro; // ptr_cadastro e um pont. p/ estrutura cadastro
ptr_cadastro = &cadastro_maria; // ptr_cadastro recebe o end. de cadastro_maria
cout << ptr_cadastro-> idade; // acessa o membro idade e imprime
cout << (*ptr_cadastro).idade; // outra forma de acessar o membro idade
Assim, podemos acessar os membros da estrutura cadastro_maria de duas maneiras diferentes: Diretamente atravs da varivel cadastro_maria Indiretamente, atravs de um ponteiro para a varivel cadastro_maria
Agora, imagine que desejamos fazer um cadastro para 50 pessoas, onde cada registro de pessoa do tipo estrutura cadastro. Como podemos declarar esta coleo de estruturas? Uma soluo poderia ser utilizar um vetor com 50 elementos, onde cada elemento do tipo estrutura. A figura abaixo ilustra esta idia.
idade nome peso idade nome peso idade nome peso idade nome peso idade nome peso idade nome peso idade nome peso idade nome peso 0 1 2 3 4 47 48 49 84
Este vetor tem 50 elementos (de 0 a 49), onde cada elementos uma estrutura do tipo cadastro, e como sabemos, a estrutura cadastro contm trs membros: idade, nome e peso. Ok, mas, como declaramos este vetor de estruturas, e alm disto, como acessamos os seus membros?
Declare o vetor do mesmo jeito que voc declara um vetor para int. Por exemplo:
tipo_de_cada_elemento nome_do_vetor[quantidade de elementos]. Assim:
struct cadastro cadastro_geral [50];
cadastro_geral um vetor de 50 elementos, onde cada elemento do tipo estrutura cadastro.
1. Para acessar os membros de cada elemento do vetor de estruturas, acesse primeiramente o elemento do vetor. Para isto use o ndice do elemento dentro do vetor. Para acessar cada membro da estrutura, utilize o ponto (.). Por exemplo:
cadastro_geral[45].idade
acessa o membro idade da estrutura de ndice 45. O ndice 45 poderia ser a matrcula de um aluno, por exemplo.
2. Mas agora sabemos usar ponteiros. Ento vamos acessar o vetor utilizando um ponteiro. Primeiro declaramos um ponteiro para estrutura cadastro e fazemos este ponteiro apontar para o primeiro elemento do vetor (elemento zero). A partir da, podemos usar a seta (->) ou a forma usando (*). Assim:
struct cadastro cadastro_geral[50];/* declara vetor de 50 estruturas */
struct cadastro *prt_cadastro; /* ponteiro para estrutura */
prt_cadastro = &cadastro_geral[0]; /* ptr_cadastro aponta para a estrutura cadastro_geral[0] */
prt_cadastro->idade = 30; /* acessa a idade da primeira estrutura */
prt_cadastro++; /* aponta para a segunda estrutura */
prt_cadastro->peso = 65.8; /* acessa o membro peso da segunda estrutura */
EXERCCIOS
1. Implementar um registro para representar um aluno. Este registro dever ter os seguintes campos:
NOME: string SEXO: char NOTAS: vetor de 3 valores reais MEDIA: real
Faa: a) Implementar uma funo que receba trs notas e devolva a mdia dessas notas; b) Ler os dados de 5 estudantes e em seguida, imprimir: o O nome, sexo e a mdia de notas de cada estudante; o Quantos homens e quantas mulheres obtiveram mdia acima de 60 pontos
85
2. Dada a estrutura mda (ms, dia, ano) abaixo, complete a funo fimEvento abaixo recebe a data de incio de um evento e a durao do evento em dias. Ela devolve a data de fim do evento.
Fazer no main o exemplo de utilizao da funo fimEvento:
int main( void) { struct dma a, b; int dias;
printf(Digite o dia, mes e ano); scanf( "%d %d %d", &a.dia, &a.mes, &a.ano);
printf(Digite a duracao do evento em dias); scanf( "%d", &dias);
b = fimEvento( a, d); // chama fimEvento passando a struct a e a duracao e dias
// fimEvento retorna uma struct dma, que atribuda a struct b printf( "%d %d %d\n", b.dia, b.mes, b.ano); return 0; }
86
8.1. ESTRUTURAS COMO PARMETROS
O item 7.1 mostrou com passar valores para uma funo por valor e por referncia. Vimos que quando passamos um parmetro para uma funo por referncia, o que estamos passando nada mais do que o endereo do parmetro. Assim, tudo o que for alterado no parmetro dentro da funo, ser refletido no valor original, passado no main (ou na funo chamadora).
Pode-se agora introduzir mais um conceito importante em C (linguagens como J ava e C#evitam este termo e uso, pois fonte de muitos erros em programao):
P O N T E I R O S
Embora fonte de muitos erros em programao, principalmente para iniciantes, seu conceito simples: Sabemos que quando passamos um parmetro por referncia, na verdade estamos passando o endereo da varivel original, e no seu valor. Um ponteiro seria onde este endereo armazenado. Assim podemos definir:
PONTEIRO UMA VARIVEL QUE CONTM O ENDEREO DE OUTRA VARIVEL
Porque ponteiros so usados?
Fornecem maneiras com as quais as funes podem realmente modificar os argumentos que recebem. Para passar matrizes e strings mais convenientemente de uma funo para outra. Para manipular matrizes mais facilmente atravs da movimentao de ponteiros para elas, em vez da prpria matriz. Para criar estruturas de dados complexas, como listas encadeadas e rvores binrias, onde uma estrutura de dados deve conter referncias sobre outra (ser visto em AEDII). Para retornar informaes sobre memria, como na funo malloc e new, que retorna a localizao de memria livre atravs do uso de ponteiro.
Entretanto, ponteiros tem um inconveniente muito grande. A sua aritmtica onde usado o operador *. Veja abaixo um exemplo.
Veja o mapa de memria ao lado:
int a=10; int b=5;
O endereo de a 200 &a=200 O endereo de b 200 &b=300
int *pa, *pb; // declara dois ponteiros para int, no inicializados pa = &a; // pa agora aponta para a pb = &b; // pb agora aponta para b
200
300
400
500 ... 10
a
b ... 5
10 87
Esta aritmtica um tanto confusa, quando usamos em structs, fica ainda mais confusa. Como nas disciplinas de Algortimos e Estruturas de Dados, trabalha-se muito com structs e o acesso aos seus membros, vamos pular esta parte bsica de aritmtica de ponteiros e ver diretamente como o acesso a membros de estruturas de dados usando ponteiros.
Para tanto, foi criado o operador (seta), que liga uma estrutura aos seus membros, via um ponteiro para a estrutura. Assim, a seta simplesmente um atalho que substitui o asterisco e os parntesis ( fcil esquecer e se confundir com estes), e com o a coisa se torna bem bvia. Por exemplo, em vez de: *(ponteiro). Escrevemos: ponteiro
Por exemplo, usando ponteiros normalmente poderamos ter a seguinte expresso:
(*carro).anoFabricacao;
Usando a seta simplesmente teramos:
carroanoFabricacao;
Fica bem fcil de entender o: carroanoFabricacao; carro a estrutura, anoFabricacao um membro da estrutura. A seta construda com os smbolos e >, no CodeBlocks.
Obs1: Incrementando um ponteiro: Se px um ponteiro para int com valor 3000, depois de executada a instruo px++, o valor de px ser 3004, e no 3001, pois o tipo int, que ocupa quatro bytes na memria.
Obs2: Se tivermos um vetor de estruturas, e um ponteiro px apontar para o incio do vetor, depois de executada a instruo px++, px apontar para a prxima estrutura, no importando quantos bytes ela ocupa na memria.
O exemplo abaixo mostra como montar um vetor de estruturas e caminhar no vetor, usando ponteiros. Podemos usar esta tcnica para fazer um pequeno banco de dados.
#include <iostream> #include <stdio.h>
using namespace std;
struct lista { char titulo[30]; char autor[30]; int regnum; double preco; };
int main() { cout << "Trabalhando com Ponteiros para Estruturas!" << endl << endl;
struct lista livro[3] = { {"Helena", "Machado de Assis", 102, 70.50 }, {"Iracema", "Jose de Alencar", 105, 63.25 }, {"Gabriela", "Jorge Amado", 234, 95.56}, };
struct lista *ptr; /* ponteiro para estrutura */
printf("Veja abaixo que os ponteiros guardam os enderecos de cada estrutura na memoria:\n");
Agora podemos ver como realmente passar uma estrutura para uma funo e melhor ainda, como passar um vetor inteiro de estruturas para uma funo: basta usar ponteiros.
Com ponteiros, ao invs de passar toda a estrutura, passamos somente o endereo da estrutura. Veja o exemplo de cdigo abaixo, que est todo comentado e auto-explicativo.
/* cria a estrutura aluno composta por tres membros */ struct aluno { char nome[40]; int mat; float peso; };
/* Funo: cadastrar um aluno Entreda: O endereco da estrutura original, chamada no main. al e o ponteiro que recebe este endereco. Assim, tudo o que for alterado usando al, sera refletido na variavel original no main. al e um ponteiro para estrutura aluno Saida: a estrutura original alterada. Repare que o tipo de retorno e void.
*/ void cadastraAluno(struct aluno *al) { puts("Digite o nome do aluno: "); fflush(stdin); gets(al->nome); puts("Digite a matricula do aluno: "); fflush(stdin); cin >> al->mat; puts("Digite o peso do aluno: "); fflush(stdin); cin >> al->peso; puts("\n"); }
/* Funo: imprimir o cadastro de um aluno Entreda: O endereco da estrutura original, chamada no main. al e o ponteiro que recebe este endereco. Assim, tudo o que for impresso usando al, ira imprimir o valor da variavel original do main. Saida: nenhuma. Repare que o tipo de retorno e void. */ void imprimeAluno(struct aluno *al) { printf("Nome do aluno: %s\n", al->nome); printf("Matricula do aluno: %d\n", al->mat); printf("Peso do aluno: %.2f", al->peso); puts("\n"); }
90
/* Funo: imprimir a turma inteira Entreda: o endereco do vetor original Saida: nenhuma. Repare que o tipo de retorno e void. */ void imprimeTurma(struct aluno turma[], int tam) { struct aluno *ptr; // declara um ponteiro para estrutura aluno // note que ptr nao aponta para nada ainda
ptr = &turma[0]; // faz ptr apontar para o inicio do vetor puts("Imprimindo toda a turma: "); for(int i=0; i < tam; i++) { puts("\n\n"); printf("Nome do aluno: %s\n", ptr->nome); printf("Matricula do aluno: %d\n", ptr->mat); printf("Peso do aluno: %.2f", ptr->peso); ptr++; } }
int main() { cout << "Passagem de struct como parametro via ponteiro!" << endl;
struct aluno Larissa; // declara uma estrutura do tipo aluno // chamada Larrisa
cadastraAluno(&Larissa); // chama a funcao cadastraAluno passando // o endereco da estrutura Larissa
imprimeAluno(&Larissa); // chama a funcao imprimeAluno passando
fflush(stdin) ; // o endereco da estrutura Larissa getchar();
system("cls"); puts("Poderiamos ter tambem um vetor de estruturas.\n");
aluno turmaAED1[3]; // turmaAED1 e um vetor de tres elementos // onde cada elemento e uma estrutura aluno
// aqui e passado para cadastraAluno o endereco de cada ima // das cico estruturas do vetor turmaAED1.Poderia ser o vetor // inteiro, como no exemplo abaixo puts("\n");
// aqui epassado o vetor inteiro, pois o nome de um vetor // representa o seu endereco puts("\n"); imprimeTurma(turmaAED1, 3);
puts("\n"); return 0; }
Sada da primeira parte do programa: 91
Sada da segunda parte do programa:
Sada da terceira parte do programa:
92
EXERCCIO
Adaptar o programa anterior, para que a estrutura contenha os seguintes dados de um aluno:
Matrcula Nome Endereo Telefone Peso Altura
Considere uma turma com 10 alunos. Faa um programa que tenha um menu com as seguintes opes:
1. Cadastra um aluno na turma; 2. Pesquisa um aluno na turma por matrcula; 3. Mostra a turma toda: imprime o cadastro completo de cada aluno na turma;
93
9. ARQUIVOS EM C
9.1 MANIPULAO DE ARQUIVOS EM MODO TEXTO
At agora, os dados que foram trabalhados ficaram em memria RAM. Ao terminar a execuo do programa, no era possvel recuperar esses dados.
Para suprir a necessidade de armazenamento de dados, arquivos podem ser utilizados.
ARQUIVO
Um arquivo recurso manipulado pelo sistema operacional ao qual a linguagem de programao tem acesso.
A entrada e sada de arquivos em C feita por streaming; Streams - fluxos de dados e podem ser de dois tipos: Streams de texto Streams binrios Linguagem C - biblioteca stdio.h Esta biblioteca possui um conjunto de funes para manipulao de arquivos; Todas as funes trabalham com o conceito de ponteiro de arquivo:
FILE *f;
FUNES DA BIBLIOTECA STDIO
1. fopen abertura de arquivo
FILE *p; p = fopen (nome_do_arquivo, modo_de_abertura);
p uma varivel que poder armazenar o endereo inicial de memria ocupado por um arquivo; nome_do_arquivo representa o nome do arquivo que se deseja abrir, podendo conter, inclusive o caminho (path) da pesquisa; modo_de_abertura representa como o arquivo ser aberto.
Modos de Abertura de Arquivo
94
fopen() retorna NULL caso ocorra algum erro ao acessar o arquivo. Exemplo:
FILE *f; // Declarao da estrutura f=fopen ("c:\\teste.txt","w");
/* o arquivo se chama Teste.txt e est localizado no diretrio c:\ */ if (f == NULL) { cout<<"Erro na abertura do arquivo. "; }
fclose() fecha o arquivo aps a sua utilizao. A funo fclose() retorna 0 no caso de sucesso.
Obs.: qualquer problema que ocorra com a execuo de um programa poder corromper, ou seja, danificar os arquivos que estiverem abertos. Assim aconselhvel que sejam abertos o menor tempo possvel.
Exemplo:
FILE *f; f=fopen ("c:\\teste.txt","w"); if (f == NULL) { cout<<"Erro na abertura do arquivo."; } else {... fclose(f); } fputc () escreve um caractere no arquivo.
int fputc (int ch, FILE *f);
Retorna o caractere escrito, caso no ocorra erro; ch o caractere que ser escrito no arquivo; arq a referncia para o arquivo onde o caractere ser escrito.
Exemplo1 : Escrever a palavra FIM, caractere por caractere, em um arquivo texto:
int main() { FILE *fp; fp = fopen("teste.txt","w"); if(fp == NULL) { cout<< "Erro na abertura do arquivo\n"; system( "pause"); exit(1); // termina a execuo do programa, liberando recursos }
fputc('F', fp); // Grava o caractere F fputc('I', fp); // Grava o caractere I fputc('M', fp); // Grava o caractere M fputc('\n', fp); // Grava o caractere fim de linha
fclose(fp); cout<<"\nFim do programa\n"; system("pause"); return 0; } 95
Exemplo2: Ler uma string do teclado e escrev-la em um arquivo texto, caractere por caractere:
int main() { FILE *fp; char string[100]; int i; fp = fopen("teste.txt","w"); if(fp == NULL) { printf( "Erro na abertura do arquivo"); system("pause"); exit(1); // termina a execuo do programa, liberando recursos } printf("Digite a string a ser gravada no arquivo:"); gets(string); for(i=0; string[i]; i++) { fputc(string[i], fp); // Grava a string, caractere a caractere fputc('\n', fp); }
fclose(fp); printf("\nFim do programa\n"); system("pause"); return 0; }
EXERCCIO2
1. Implemente um programa que abra um arquivo texto e conte a quantidade de caracteres a presentes nele. Imprima o nmero de caracteres na tela.
2. Implemente um programa que leia um arquivo texto e imprima, linha a linha, o seu contedo na tela. Imprima tambm a quantidade de linhas que este arquivo possui.
96
BIBLIOGRAFIA
ASCENCIO, Ana Fernanda Gomes e CAMPOS, Edilene A. Veneruchi. Fundamentos da Programao de Computadores Algoritmos, Pascal e C/C++. 2 Edio - So Paulo: Pearson Prentice Hall, 2007. Captulo 4. SOUZA, A. Furlan; GOMES, Marcelo Marques; SOARES, Marcio Vieira e CONCILIO, Ricardo. Algoritmos e Lgica de Programao. 2 ed. Ver. e ampl. So Paulo: Cengage Learning 2011. Captulo 4.
GUIMARES, ngelo de Moura; LAGES, Newton Alberto de Castilho. Algoritmos e estruturas de dados. Rio de Janeiro: LTC - Livros Tcnicos e Cientficos, c1994. 216p. ISBN 8521603789
MANZANO, Jos Augusto N. G; OLIVEIRA, Jayr Figueiredo de. Algoritmos: lgica para desenvolvimento de programao de computadores. 14. ed. So Paulo: rica, 2002. [6]p. ISBN 857194718X
SCHILDT, Herbert. C: completo e total. 3. ed. rev. atual. So Paulo: Pearson Education do Brasil, c1997. 827p. ISBN 8534605955
Apostila Algoritmos e Estruturas de dados 1 Parte. Prof.: Ivre Marjorie R. Machado, PUCMINAS, 2012