1. UNIVERSIDADE FEDERAL DO RIO DE JANEIRO
Coordena¸˜o dos Programas de P´s–gradua¸˜o em Engenharia
ca o ca
Programa de Engenharia Qu´
ımica
Laborat´rio de Termofluidodinˆmica
o a
Introdu¸˜o ` Programa¸˜o em C
ca a ca
Curso de Extens˜o
a
Luiz Fernando Lopes Rodrigues Silva, PEQ/COPPE/UFRJ
RIO DE JANEIRO, RJ — BRASIL
2005
4. Pref´cio
a
Atualmente em qualquer ´rea de atua¸˜o profissional, o computador se torna
a ca
uma ferramenta cada vez mais presente. Seja para montar um relat´rio para
o
a empresa, estruturar uma apresenta¸˜o sobre suas atividades e progressos,
ca
executar tarefas repetitivas de an´lise de dados em uma f´brica, entre muitas
a a
outras fun¸˜es. Mas o principal objetivo deste curso ´ mostrar os meios
co e
de uso do computador como ferramenta cient´ ıfica para realizar c´lculos de
a
modo eficiente. Em outras palavras, como analisar um problema qualquer e
estruturar uma metodologia de solu¸˜o de forma que o computador entenda
ca
o que o usu´rio quer, execute os comandos o mais r´pido poss´ e forne¸a
a a ıvel c
resultados confi´veis.
a
O objetivo desta apostila ´ apenas de colocar as informa¸oes b´sicas sobre
e c˜ a
a linguagem de programa¸˜o C de modo a auxiliar o treinamento do aluno
ca
durante o curso. Como alguns t´picos ser˜o colocados em sala de aula, eu
o a
coloquei alguns c´digos com espa¸o suficiente para que vocˆs possam anotar
o c e
as discuss˜es. A descri¸˜o da linguagem n˜o depende do sistema operacio-
o ca a
nal, seja Windows, Linux, DOS, MacOS, UNIX, desde que um compilador C
esteja instalado. Existem duas referˆncias sobre C que eu gostaria de passar
e
para vocˆs. A primeira ´ o livro de Brian W. Kernighan e Dennis M. Ritchie
e e
intitulado “C — A linguagem de programa¸˜o padr˜o ANSI”. Estes autores
ca a
foram os desenvolvedores da linguagem C e apesar do livro possuir um bom
conte´ do, seus exemplos s˜o mais voltados para manipula¸˜o de caracteres.
u a ca
J´ o livro “C++ and object-oriented numeric computing for scientists and
a
engineers” de Daoqi Yang ´ uma referˆncia excelente para programa¸˜o ci-
e e ca
ent´ıfica. Apesar de ser um livro de C++, muitos fundamentos b´sicos de C
a
s˜o usados e vale (muito!!) a pena dar uma olhada nele.
a
Espero que gostem do curso,
Luiz Fernando L. R. Silva
PEQ/COPPE/UFRJ
21/07/2005
5. Cap´
ıtulo 1
Introdu¸˜o ` Programa¸˜o
ca a ca
1.1 Interpreta¸˜o do Arquivo–fonte
ca
Os programas de computador s˜o formados por uma s´rie de instru¸˜es que
a e co
o computador executa. Quando vocˆ cria um programa, precisa especificar
e
as instru¸˜es que o computador precisar´ executar para realizar as opera¸˜es
co a co
desejadas. A defini¸˜o destas instru¸˜es ´ que vocˆ deve fazer e salvar em
ca co e e
um arquivo, chamado de arquivo ou c´digo fonte. O arquivo fonte de um
o
programa escrito em C deve possuir a extens˜o C (ex. arqfonte.c). O ar-
a
quivo fonte ´ o modo do programador montar a sua l´gica de programa¸˜o e
e o ca
comunicar isso ao computador. Mas o computador n˜o entende diretamente
a
o arquivo fonte e precisa de um tradutor, chamado de compilador. Para criar
programas, ´ imperativo e necess´rio que o compilador esteja instalado no
e a
computador. O compilador converte as instru¸˜es colocadas no arquivo fonte
co
para a linguagem de m´quina (bin´ria — 0 ou 1) que o computador compre-
a a
ende. Os arquivos gerados com a extens˜o EXE ou COM cont´m o c´digo
a e o
de m´quina e podem ser executados pelo computador. A Fig. 1.1 ilustra
a
esse processo de gera¸˜o do c´digo fonte, compila¸˜o e cria¸˜o do arquivo
ca o ca ca
execut´vel.
a
6. 1.2 Computa¸˜o Cient´
ca ıfica 3
Figura 1.1: Convers˜o do c´digo fonte para c´digo de m´quina.
a o o a
1.2 Computa¸˜o Cient´
ca ıfica
Em qualquer aplica¸˜o cient´
ca ıfica, a eficiˆncia computacional ´ muito impor-
e e
tante e o programador deve sempre ficar atento a esse detalhe. Mas como
montar um programa de forma eficiente? Bem, antes de pensar em pro-
grama¸˜o propriamente dita deve–se estruturar muito bem qual ´ o problema
ca e
e qual a melhor forma de resolvˆ–lo. Se isso n˜o estiver bem assentado na
e a
cabe¸a do programador, ´ melhor parar por a´ e come¸ar a ler o seu problema
c e ı c
novamente. Afinal de contas, como vocˆ vai resolver o seu problema de forma
e
eficiente, se nem sabe ainda como resolvˆ–lo?
e
Dica de programa¸˜o do L.F.
ca
Antes de pensar em programar, organize as id´ias no papel. Mes-
e
mo para os problemas mais simples. Sempre!! A princ´ ıpio
pode parecer perda de tempo, mas a facilidade de estruturar o
seu c´digo fonte ser´ recompensadora.
o a
As etapas necess´rias de solucionar o problema ´ o que vamos chamar de
a e
metodologia de algoritmo e a forma como estas etapas s˜o executadas est´
a a
inclu´ na l´gica de programa¸˜o. Estas defini¸˜es v˜o ficar mais claras ao
ıda o ca co a
analisarmos um exemplo.
1 Exemplo da distˆncia percorrida pelo carro com acelera¸ao constante.
a c˜
7. 1.3 Exerc´
ıcios 4
Bem, temos o problema nas m˜os, ou seja, um modelo matem´tico a ser
a a
resolvido.
1
S = S0 + v0 t − at2 (1.1)
2
Quais s˜o as perguntas que sempre devemos fazer para estruturar a me-
a
todologia do algoritmo?
• Qual o meu objetivo? Calcular S!!! ⇒ Ent˜o, essa ´ a ultima coisa
a e ´
com que devemos nos preocupar.
• O que eu preciso para calcular S? S0 , v0 , a e t. ⇒ Aaah, ent˜o eu
a
tenho que me preocupar em saber os valores dessas vari´veis antes de
a
calcular S...
- Atribuir valores para S0 , v0 , a e t.
- Existe alguma restri¸˜o num´rica e/ou f´
ca e ısica no meu modelo? ⇒
N˜o existe tempo negativo.
a
♦ Condi¸˜o para que o programa rejeite valores negativos de
ca
tempo.
• Calculamos S.
• Mostramos ao usu´rio o resultado. ⇒ Sen˜o, n˜o adianta nada, n´?
a a a e
Mesmo para um problema simples, algumas perguntas devem ser respon-
didas antes de tentar calcular qualquer coisa. Eu ficaria muito feliz se ao
longo do curso (e depois tamb´m) vocˆs sempre montassem o algoritmo de
e e
solu¸˜o. Vocˆs notar˜o que, com o tempo e a pr´tica, estruturar a solu¸˜o de
ca e a a ca
um problema ficar´ muito mais f´cil e poder´ at´ ser feita automaticamente.
a a a e
Podem confiar.
1.3 Exerc´
ıcios
I Monte a estrutura de solu¸˜o para os problemas abaixo.
ca
8. 1.4 Primeiro Programa em C 5
1) A troca de calor em um reator n˜o isot´rmico precisa ser otimizada.
a e
Vocˆ foi incumbido de calcular a quantidade de calor trocada entre o reator
e
e o meio ambiente. O modelo de troca t´rmica est´ colocado abaixo, onde Q
e a
´ a quantidade de calor trocada, UA ´ o coeficiente global de transferˆncia
e e e
de calor, Tr ´ a temperatura do reator e T∞ ´ a temperatura do ambiente.
e e
Q = UA(Tr − T∞ ) (1.2)
2) A Ba´ de Guanabara possui uma concentra¸˜o de petr´leo que est´
ıa ca o a
se dispersando com o passar do tempo. A dispers˜o de petr´leo na ba´ segue
a o ıa
o modelo descrito na Eq. 1.3 onde Cp ´ a concentra¸˜o de petr´leo no instante
e ca o
t, Cp0 ´ a concentra¸˜o inicial de petr´leo e A ´ a ´rea onde o petr´leo est´
e ca o e a o a
disperso. Contudo, a ´rea de dispers˜o do petr´leo varia devido ` condi¸˜es
a a o a co
clim´ticas e com o pr´prio tempo. Um modelo (Eq. 1.4) descreve a varia¸˜o
a o ca
o a a ¯ e
da ´rea em que o petr´leo est´ disperso, onde o parˆmetro M ´ uma m´dia
a e
dos efeitos clim´ticos.
a
Cp = Cp0 e−At (1.3)
¯
A = M e−t (1.4)
1.4 Primeiro Programa em C
Agora que j´ vimos como montar os nossos problemas de uma forma estru-
a
turada, j´ podemos ver um primeiro exemplo de programa¸˜o em C. Note
a ca
que ainda n˜o vimos nenhum comando desta linguagem e este exemplo ir´
a a
servir apenas como uma forma de come¸armos uma discuss˜o em torno da
c a
l´gica de programa¸˜o em C.
o ca
Um programa em C necessariamente deve conter a fun¸˜o main() que
ca
contˆm as instru¸˜es (ou comandos) entre entre { e }. Cada comando pode
e co
ser escrito em mais de uma linha e deve ser terminado por um ponto e
v´
ırgula (; — se n˜o tiver, vai dar erro na compila¸˜o do programa). Os
a ca
coment´rios no c´digo fonte est˜o entre /* e */ (todo o texto entre esses dois
a o a
s´
ımbolos ´ desconsiderado pelo compilador) ou precedidos por // (a linha
e
toda fica comentada). Os coment´rios podem conter v´rias informa¸˜es sobre
a a co
o problema (qual o problema a ser resolvido, qual a metodologia que vai ser
utilizada, quem programou o c´digo, quando, etc.), o c´digo fonte (o porquˆ
o o e
de usar um comando espec´ ıfico) ou mesmo detalhes de como usar o programa
9. 1.4 Primeiro Programa em C 6
depois de compilado. A princ´ıpio, comentar o arquivo fonte pode parecer uma
tarefa exaustiva, por´m estes s˜o muito uteis para o entendimento futuro do
e a ´
c´digo.
o
Dica de programa¸˜o do L.F.
ca
Sempre comente o seu c´digo. N˜o preciso colocar os porquˆs,
o a e
apenas comente!!!!!
O objetivo deste primeiro programa ´ simplesmente escrever uma mensa-
e
gem na tela para o usu´rio. O c´digo fonte est´ colocado a seguir.
a o a
/* Este ´ um simples programa para escrever na tela
e
uma mensagem de texto.
Programado por: Luiz Fernando L. R. Silva */
#include<stdio.h> // Biblioteca padr~o I/O em tela
a
main()
{
// Comando para escrever em tela.
printf("Eu adoro programar em C");
}
As trˆs primeiras linhas do c´digo s˜o coment´rios (est˜o entre /* e */) e
e o a a a
colocam algumas informa¸˜es sobre o programa. Os outros coment´rios desse
co a
programa s˜o menores e s˜o precedidos por duas barras //. As bibliotecas em
a a
C contˆm v´rios comandos e fun¸˜es padr˜es para auxiliar na programa¸˜o.
e a co o ca
Para habilitar esses comandos, ´ necess´rio declarar as bibliotecas no in´
e a ıcio
do programa. A biblioteca padr˜o que contˆm os comandos de entrada e
a e
sa´ de dados em tela chama-se <stdio.h> e est´ declarada logo ap´s o
ıda a o
primeiro coment´rio. Essa declara¸˜o habilita que o programador use todos
a ca
os comandos de entrada e sa´ padr˜o em tela. O comando printf efetua essa
ıda a
opera¸˜o mostrando ao usu´rio a seguinte mensagem: Eu adoro programar
ca a
em C. Pronto, o nosso primeiro programa est´ pronto.
a
10. Cap´
ıtulo 2
Tipos e Operadores B´sicos
a
2.1 Tipos de Vari´veis
a
Vamos considerar a seguinte express˜o matem´tica:
a a
z =y+i∗x (2.1)
Para que a Eq. 2.1 fa¸a sentido em no c´digo fonte, os identificadores 1
c o
x, y, z e i devem ser declarados de forma adequada. Todos os identificadores
devem ser declarados antes de serem usados. As declara¸˜es introduzem
co
entidades representadas por seus identificadores e seus tipos (ex. inteiro ou
caractere).
Os tipos das vari´veis fornecem propriedades diferentes tanto na forma
a
de armazenamento da vari´vel na mem´ria RAM quanto na pr´pria mani-
a o o
pula¸˜o e opera¸˜o da vari´vel. Existem opera¸˜es que s´ s˜o poss´
ca ca a co o a ıveis ou
s˜o muito mais eficientes se realizadas com um determinado tipo de vari´vel.
a a
if( i == 0 )
{ /* realiza os comandos aqui dentro */ }
1
Os identificadores s˜o as letras usadas para identificar as suas vari´veis.
a a
11. 2.1 Tipos de Vari´veis
a 8
2.1.1 Declara¸˜o de Vari´veis
ca a
A declara¸˜o das vari´veis no c´digo fonte indica que o programa deve re-
ca a o
servar um espa¸o na mem´ria RAM para cada vari´vel declarada. Vamos
c o a
considerar que a mem´ria RAM est´ distribu´ como na Fig. 2.1.1 e divi-
o a ıda
dida em bytes.
Figura 2.1: Representa¸˜o da mem´ria RAM subdividida em bytes.
ca o
Agora vamos considerar que no in´ do programa as vari´veis i e z este-
ıcio a
jam sendo declaradas e portanto, um espa¸o na mem´ria deve ser reservado.
c o
Este procedimento ´ o que chamamos de aloca¸˜o de espa¸o na mem´ria.
e ca c o
Deste modo, os valores que forem atribu´ ıdos nestas vari´veis ficam alocados
a
em um endere¸o espec´
c ıfico da mem´ria RAM. A quantidade de mem´ria que
o o
deve ser reservada depende do tipo da vari´vel.
a
Figura 2.2: Aloca¸˜o de vari´veis na mem´ria RAM.
ca a o
2.1.2 Vari´veis Inteiras
a
Cada vari´vel inteira ocupa 2 bytes de mem´ria e o valor armazenado na
a o
mem´ria n˜o inclui a parte fracion´ria. Um exemplo segue abaixo.
o a a
#include<stdio.h>
main()
{
int i; // Declara¸~o de i como inteira
ca
12. 2.1 Tipos de Vari´veis
a 9
int j,k; /* Declara¸~o de j e k como inteiros.
ca
´ poss´vel declarar mais de uma
E ı
vari´vel por linha */
a
int ii = 123; // Ao declarar ii, j´ atribuo um valor.
a
i = 2; // Atribui¸~o do valor 2 para a vari´vel i
ca a
j = i; // Atribui¸~o do valor contido em i para j
ca
k = 2.3; /* N~o considera a parte fracion´ria!
a a
k assume o valor de 2 */
/* Sa´da em tela das vari´veis*/
ı a
printf("O valor de i eh: %d n",i);
printf("O valor de j e k sao: %d %d n",j,k);
printf("%d mais %d igual a %d n",1,2,1+2);
}
2.1.3 Vari´veis de Caracteres
a
Cada vari´vel caractere ocupa 1 byte na mem´ria e armazena valores inteiros
a o
que s˜o convertidos em caracteres ASCII (o valor do inteiro 98 corresponde ao
a
caractere ’b’ no conjunto ASCII). Normalmente, o que se quer ´ uma vari´vel
e a
que armazene um conjunto de caracteres para que seja poss´ ıvel construir
palavras ou senten¸as. Alguns caracteres s˜o especiais e possuem algumas
c a
fun¸˜es espec´
co ıficas.
Caractere Fun¸˜o espec´
ca ıfica
n nova linha
t tabula¸˜o horizontal
ca
v tabula¸˜o vertical
ca
a alerta sonoro
r cursor volta para o in´ da linha
ıcio
b backspace
Tabela 2.1: Caracteres especiais para operar a sa´ de dados.
ıda
Um exemplo (extremamente idiota!) de aplica¸˜o de caracteres.
ca
#include <stdio.h>
#include <conio.h>
13. 2.1 Tipos de Vari´veis
a 10
main()
{
char ch1, ch2;
printf("Entre com 1 caracter: ");
/* le um caracter do console sem mostra-lo */
ch1 = getch();
printf("nEntre com 1 caracter: ");
/* le um caracter do console mostrando-o em seguida:
getche() = getch() and echo */
ch2 = getche();
/* Mostra os caracteres lidos na tela: */
printf("nO primeiro caracter lido foi: %c", ch1);
printf("nO ultimo caracter lido foi: %cn", ch2);
/* Mostra os caracteres lidos na tela usando putch(): */
printf("nCaracterres lidos:n");
putch(ch1);
putch(ch2);
printf("n");
/* A funcao getchar le um caracter da
entrada padrao (stdin): */
ch1 = getchar();
/* A funcao putchar mostra um caracter
na saida padrao (stdout): */
putchar(ch1);
printf("n");
}
2.1.4 Vari´veis de Ponto Flutuante
a
As vari´veis de ponto flutuante s˜o capazes de armazenar as casas decimais
a a
de um n´ mero. Existem duas classifica¸˜es para as vari´veis de ponto flutu-
u co a
14. 2.1 Tipos de Vari´veis
a 11
ante, com precis˜o simples (normalmente com 6 casas decimais) ou de dupla
a
precis˜o (normalmente com 15 casas decimais). Um exemplo quantifica bem
a
a diferen¸a entre esses dois tipos de vari´veis.
c a
#include<stdio.h>
#include<math.h>
int main()
{
float pi_float;
double pi_double;
pi_float = acos(-1.);
pi_double= acos(-1.);
printf("Valor com precisao simples: %21.19fn", pi_float);
printf("Valor com precisao dupla : %21.19fn", pi_double);
return(1);
}
Compilando e executando o c´digo acima em um AthlonXP 2.2GHz, os
o
resultados para π est˜o colocados abaixo.
a
Valor com precisao simples : 3.1415927410125732000
Valor com precisao dupla : 3.1415926535897931000
Obs.: executem o programa colocado acima mudando a referˆncia %21.19f
e
da vari´vel de ponto flutuante. Mude o n´ mero das casas decimais, o n´ mero
a u u
dos espa¸os reservados para a vari´vel e troque o f do ponto flutuante por
c a
%g, %e e %E. Vejam e analisem as mudan¸as.c
2.1.5 Vari´veis Booleanas
a
Um booleano, representado por bool, pode armazenar dois valores: true ou
false, e ´ usado para expressar os resultados de express˜es l´gicas.
e o o
15. 2.2 Tipos de Operadores 12
bool flag = true; // declara¸~o de flag como booleana
ca
double d;
/* Algum c´digo no meio do caminho, que pode
o
eventualmente mudar o valor de flag */
d = 3.14;
if(flag == false)
{ d = 2.718; }
/* E o programa continua... */
Algumas compara¸˜es est˜o descritas na tabela abaixo.
co a
true && true = true true || true = true
true && false = false true || false = true
false && true = false false || true = true
false && false = false false || false = false
Tabela 2.2: Compara¸˜es de booleanos — && significa E; || significa OU
co
Por defini¸˜o, false tem o valor 0 e true tem valor 1. Por isso, pessoal-
ca
mente, eu n˜o uso vari´veis booleanas, mas um inteiro com valor de 0 (falso)
a a
ou 1 (verdadeiro).
2.2 Tipos de Operadores
Pronto, j´ sabemos quais s˜o os tipos de vari´veis que existem e agora esta-
a a a
mos aptos a realizar opera¸˜es com elas.
co
2.2.1 Operadores Aritm´ticos
e
S˜o os operadores b´sicos de soma (+), subtra¸˜o (−), multiplica¸˜o (∗)
a a ca ca
a ´
e divis˜o (/). E muito importante entender o tipo de vari´vel que se est´
a a
operando, pois perda de informa¸˜o pode ocorrer. Veja o exemplo a seguir.
ca
16. 2.2 Tipos de Operadores 13
double m = 13/4; /* ´ uma opera¸~o entre dois inteiros, e vai
e ca
fornecer um resultado inteiro!!
m = 3, as casas decimais s~o ignoradas */
a
double n = 3/4; /* n = 0 */
double y = 3.0/4; /* Ao operar, o inteiro 4 ´ convertido para
e
double! y = 0.75 */
double y = 3/4.0; /* Idem, 3 ´ convertido em 3.0! y = 0.75 */
e
As opera¸˜es matem´ticas s˜o iniciadas da esquerda para a direita. A
co a a
multiplica¸˜o e a divis˜o possuem uma maior precedˆncia em rela¸˜o ` soma
ca a e ca a
e subtra¸˜o. Contudo, o que est´ contido nos parˆnteses possue uma pre-
ca a e
cedˆncia maior que a dos operadores. Vejamos as etapas de execu¸˜o das
e ca
express˜es colocadas no exemplo abaixo.
o
int m;
m = 1 + 2 + 3*4; /* m = 1 + 2 + 12;
m = 3 + 12;
m = 15; */
m = 1 + (2 + 3)*4; /* m = 1 + (5)*4;
m = 1 + 20;
m = 21; */
m = 5 + 10 + 15/3; /* m = 5 + 10 + 5;
m = 15 + 5;
m = 20; */
m = (5+10+15)/3; /* m = (15 + 15)/3;
m = 30/3;
m = 10; */
Dica de programa¸˜o do L.F.
ca
Sempre que vocˆ tiver d´vidas sobre a ordem das opera¸˜es, use
e u co
o parˆnteses sem medo de ser feliz.
e
int m;
m = ((5+3)*2) - 3; /* m = (8*2) - 3;
17. 2.2 Tipos de Operadores 14
m = 16 - 3;
m = 13; */
Os operadores de incremento (++) e decremento (−−) s˜o muito usados
a
em qualquer programa C, pois facilitam a leitura do c´digo (alguns dizem
o
quem n˜o...).
a
int conta = 0;
int m = 2;
conta++; /* Essa opera¸~o pode
ca ser substitu´da por:
ı
conta = conta + 1; (conta = 1) */
conta--; /* Essa opera¸~o pode
ca ser substitu´da por:
ı
conta = conta - 1; (conta = 0) */
++m; /* m = 3; */
m = conta++; /* m = 0; conta = 1;*/
Vamos analisar o seguinte c´digo (em aula).
o
#include<stdio.h>
int main()
{
int valor = 1;
printf("Usando depois da variavel : %dn", valor++);
printf("Valor apos incremento: %dn", valor);
valor = 1;
printf("Usando depois da variavel : %dn", ++valor);
printf("Valor apos incremento: %dn", valor);
return(1);
}
Ainda ´ poss´ realizar opera¸˜es de atribui¸˜o da seguinte maneira.
e ıvel co ca
total += 100; // Significa: total = total + 100;
conta -= 5; // Significa: conta = conta - 5;
metade /=2; // Significa: metade = metade/2;
18. 2.2 Tipos de Operadores 15
2.2.2 Operadores Relacionais
Os operadores relacionais s˜o > (maior que), < (menor que), >= (maior ou
a
igual a), <= (menor ou igual a), == (igual a) e ! = (n˜o igual). A nota¸˜o ! ´
a ca e
o operador de nega¸˜o. O resultado destas opera¸˜es ´ sempre um booleano.
ca co e
int x = 5;
bool b, c;
b = (x < 6); // b = true, j´ que x ´ menor que 6
a e
c = (x == 0); // b = false, j´ que x n~o ´ 0
a a e
if(b != c) // Se b n~o ´ igual a c, x = 17
a e
x = 17;
if(b) // Se b ´ true, ent~o fa¸a x = 19
e a c
x = 19;
if(!b) // Se b ´ false, ent~o fa¸a x = 221
e a c
x = 221;
Deve-se tomar muito cuidado ao usar essas opera¸˜es. Considere o exem-
co
plo abaixo.
int m = 7;
bool b, c;
b = 3 < m < 9; // b = true
m = 20;
c = 3 < m < 9; // c = true
Os operadores relacionais s˜o executados da esquerda para a direita, por
a
isso a express˜o 3 < m < 9 ´ equivalente ` (3 < m) < 9. Ent˜o, esta
a e a a
express˜o sempre ´ avaliada como true pois 3 < m pode ser tanto 1 (true)
a e
quanto 0 (false).
2.2.3 Operadores L´gicos
o
Os operadores l´gicos, assim como os relacionais, resultam em um valor bo-
o
oleano. Esses operadores s˜o && (e) e || (ou) e posuem uma precedˆncia
a e
19. 2.3 Exerc´
ıcios 16
maior que os operadores relacionais (s˜o executados antes). A Tabela 2.2
a
mostra as rela¸˜es com os booleanos. Veja os exemplos a seguir.
co
bool b =true, c = false;
bool d = b && c; // d = false
bool e = b || c; // e = true
bool f = (e == false) && c; // f = false
bool g = (d == true ) || c; // g = false
bool h = (d = true ) || c; // h = true
Vamos agora rever a express˜o 3 < m < 9. A maneira correta de progra-
a
mar esta express˜o em C seria
a
(3 < m) && (m < 9)
Como o operador < possue uma precedˆncia maior que o operador &&,
e
os dois pares de parˆnteses poderiam ser omitidos.
e
2.3 Exerc´
ıcios
I As vari´veis a, b, c, d, e, f e g foram inicializadas com os seguintes valores:
a
a = 3. b = 2. c = 5. d = 4. e = 10. f = 2. g = 3.
Efetue as seguintes express˜es em C :
o
1. saida = a*b+c*d+e/pow(f,g)
2. saida = a*(b+c)*d + pow(e/f,g)
3. saida = a*(b+c)*(d+e)/pow(f,g)
20. 2.3 Exerc´
ıcios 17
II Analise o c´digo abaixo para calcular a m´dia das notas de um aluno.
o e
Programe este c´digo e retire alguns dos coment´rios e comente alguns co-
o a
mandos para entender como o c´digo funciona.
o
/*C´lculo da m´dia dos alunos*/
a e
#include <stdio.h>
int main()
{
double M,P1,P2;
// Entrada de dados pelo c´digo
o
P1 = 5.0;
P2 = 7.5;
/* Entrada de dados em tela
printf("Digite o valor da primeira prova P1n");
printf("Digite o valor da segunda prova P2n");
scanf("%16le",&P1);
scanf("%16le",&P2);
*/
// C´lculo da m´dia
a e
// C´lculo direto
a
M=(P1+P2)/2.;
// C´lculo em duas etapas
a
//M = P1 + P2;
//M /= 2;
if(M >= 7.) { printf("O aluno esta aprovadon"); }
else { printf("O aluno devera fazer prova finaln"); }
printf("A media do aluno e: %.2fn",M);
return(1);
}
III Fa¸a um programa em C que calcule a velocidade em queda livre de
c
um corpo a 6 m de altura. Sabe-se que a f´rmula de queda livre ´ dada por
√ o e
v = 2gh, onde g = 9.81. Fa¸a um outro programa em que seja poss´ que
c ıvel
o usu´rio entre na tela com o valor da altura (cuidado, porque at´ onde eu
a e
21. 2.3 Exerc´
ıcios 18
sei e os limites da f´
ısica permitem, n˜o existe altura negativa).
a
IV Fa¸a um programa em C que leia uma temperatura em graus Farenheit,
c
converta-a para uma temperatura absoluta em kelvins, e escreva o resultado.
A f´rmula de convers˜o ´:
o a e
5.
T (K) = [T (F ) − 32.0] + 273.15 (2.2)
9.
V O coseno hiperb´lico ´ definido pela equa¸˜o:
o e ca
ex + e−x
cosh(x) = (2.3)
2.
Escreva um programa em C para calcular o coseno hiperb´lico para um
o
valor x fornecido pelo usu´rio. Use o programa para calcular o coseno hi-
a
perb´lico de 3.0. Compare a resposta que seu programa fornece com a res-
o
posta produzida pela fun¸˜o intr´
ca ınseca do C cosh(x), contida na biblioteca
<math.h>.
22. Cap´
ıtulo 3
Fluxos de Controle
3.1 Condicionais
3.1.1 Comando if–else if
A forma mais simples de um condicional ´ o comando if, cuja sintaxe ´:
e e
if(condi¸~o) express~o
ca a
onde condi¸˜o ´ uma express˜o l´gica que possui valor de true ou false, e
ca e a o
express˜o pode ser apenas um ou v´rios comandos. A express˜o ´ executada
a a a e
quando o valor de condi¸˜o ´ avaliado em true, sen˜o a express˜o n˜o ´
ca e a a a e
executada. A condi¸˜o deve estar entre parˆnteses.
ca e
if(n>10) x*=10; // Qdo n>10, fa¸a x*=10
c
if(n==0) { // Qdo n ´ 5, fa¸a x*=5
e c
x*=5;
}
if(n) y*=7; // Qdo n!=0, fa¸a y*=7
c
Os condicionais devem ser usados com cuidado quando a express˜o requer
a
a compara¸˜o de vari´veis n˜o inteiras. Considere x e y como vari´veis de
ca a a a
23. 3.1 Condicionais 20
ponto flutuante, a condi¸˜o if(x == y) deve ser substitu´ por if(fabs(x - y)
ca ıda
< erro) onde erro ´ um n´ mero muito pequeno definido pelo usu´rio e fabs ´
e u a e
a fun¸˜o matem´tica que retorna o valor absoluto de uma vari´vel de ponto
ca a a
flutuante.
Dica de programa¸˜o do L.F.
ca
Tome muito cuidado ao avaliar vari´veis em ponto flutuante.
a
Note ainda que existe diferen¸a entre == e =! Aqui, o pro-
c
gramador pode e deve “usar e abusar” dos parˆnteses e dos
e
operadores l´gicos e relacionais.
o
O condicional if pode ser acompanhado pela parte opcional else.
if(condi¸~o)
ca
express~o1
a
else
express~o2
a
onde, se a condi¸˜o for avaliada como true, a express˜o1 ´ executada
ca a e
enquanto a express˜o2 ´ desprezada. Se a condi¸˜o retornar um valor false,
a e ca
a express˜o1 ´ desprezada e a express˜o2 ´ executada. Ainda ´ poss´
a e a e e ıvel
combinar os condicionais if–else da seguinte maneira:
if(condi¸~o1)
ca
express~o1
a
else if(condi¸~o2)
ca
express~o2
a
else if(condi¸~o3)
ca
express~o3
a
else
express~o4
a
onde a express˜o1 ´ executada s´ e somente s´ se a condi¸˜o1 for true.
a e o o ca
Se for true, todo o resto do bloco ´ ignorado; e se for false a express˜o1 n˜o
e a a
´ executada e a condi¸˜o2 ´ testada. Se a ultima for true, a express˜o2 ´
e ca e ´ a e
24. 3.1 Condicionais 21
avaliada e o resto do bloco ´ desprezado, enquanto se a condi¸˜o2 for false o
e ca
resto do bloco ´ ignorado. Esse procedimento ´ repetido at´ o final do bloco,
e e e
onde se nenhuma das condi¸˜es forem true, a express˜o4 ser´ executada.
co a a
Note que a ultima express˜o ´ um caso que n˜o possui nenhuma restri¸˜o e
´ a e a ca
ser´ efetuado sempre que nenhuma das condi¸˜es anteriores forem satisfeitas.
a co
Vamos ver o exemplo abaixo. O programador quer montar uma estrutura
que retorne os parˆmetros f´
a ısicos da ´gua. Por´m, at´ onde eu sei e a f´
a e e ısica
explica, dependendo da temperatura, a ´gua pode se apresentar na forma
a
s´lida, l´
o ıquida ou gasosa e seus parˆmetros f´
a ısicos dependem de sua forma.
Como fazer isso?
// Usu´rio entra com T (em K)
a
printf("Entre com a temperatura da agua (K)");
scanf("%16le",&T);
printf("n");
if(T <= 273.15)
{ // Gelo!
// Calcula par^metros para gelo
a
}
else if((T >= 273.15) && (T <= 373.15))
{ // L´quido!
ı
// Calcula par^metros para ´gua l´quida
a a ı
}
else
{ // S´ sobrou o vapor (fora o plasma!!)
o
// Calcula par^metros para vapor d’´gua
a a
}
3.1.2 Comando switch
O comando switch ´ muito usado em situa¸˜es de m´ ltipla escolhas. Este
e co u
testa o valor da condi¸˜o, colocada entre parˆnteses ap´s a palavra chave
ca e o
switch. Ent˜o este valor ´ usado como um controle de escolha para os casos
a e
que satisfazem esse valor. Se o valor n˜o satisfaz nenhum caso, o controle ir´
a a
para o caso default. O comando break ´ usado para sair do comando switch.
e
25. 3.1 Condicionais 22
Vamos analisar o exemplo abaixo, onde o programador quer calcular o
coeficiente de transferˆncia de calor em alguns casos especificados. Sabe-se
e
que os modelos matem´ticos s˜o diferentes para cada situa¸˜o f´
a a ca ısica, ent˜o
a
devemos colocar restri¸˜es no usos destes ou deixar que o usu´rio especifique
co a
o caso que ele quer o resultado.
#include<stdio.h>
#include<conio.h>
#include<ctype.h>
#include<stdlib.h>
int main()
{
char letra;
// Tem q declarar os par^metros dos modelos, n´?
a e
// Se n~o j´ era!!!!
a a
printf("Lista de opcoes para calcular o coeficiente ");
printf("de transferencia de calor:n");
printf("A - Modelo para Conveccao Interna em tubosn");
printf("B - Modelo para Conveccao Externan");
printf("C - Modelo para Conveccao Naturaln");
printf("D - Modelo para Conveccao com condensacaon");
printf("Entre com sua opcao : ");
letra = getch();
// Transforma letra min´scula em mai´scula
u u
letra = toupper(letra);
printf("n");
// Vamos escolher qual modelo? Depende do q o usu´rio quer...
a
switch (letra)
{
case ’A’:
// Escreve aqui como calcula o h para conv. interna
// Comandos
printf("Fingi que calculei h por A.n");
break;
case ’B’:
// Escreve aqui como calcula o h para conv. externa
// Comandos
26. 3.2 La¸os
c 23
printf("Fingi que calculei h por B.n");
break;
case ’C’:
// Escreve aqui como calcula o h para conv. natural
// Comandos
printf("Fingi que calculei h por C.n");
break;
case ’D’:
// Escreve aqui como calcula o h para conv. com condensacao
// Comandos
printf("Fingi que calculei h por D.n");
break;
default :
// Entra aqui se nenhum das condi¸~es foram satisfeitas
co
printf("Esse caractere nao e valido. Foi mal...n");
};
return (1);
}
Dica de programa¸˜o do L.F.
ca
Vocˆ sabia que os condicionais s˜o um dos comandos mais com
e a
maior custo computacional que existem? Se quiser montar
um programa com menor custo de computa¸˜o, use o me-
ca
nor n´mero de condicionais poss´
u ıvel e somente quando for
necess´rio.
a
3.2 La¸os
c
3.2.1 Comando for
O la¸o for ´ muito utilizado e extremamente conveniente de ser usado. Sua
c e
forma geral est´ colocada abaixo.
a
for(inicia;condi¸~o;express~o)
ca a
comandos
27. 3.2 La¸os
c 24
A inicia representa a inicializa¸˜o da vari´vel de controle do la¸o, a
ca a c
condi¸˜o fornece um controle para determinar se o la¸o deve continuar a
ca c
ser executado e express˜o indica como a vari´vel inicializada deve ser ava-
a a
liada a cada vez que os comandos s˜o executados. O la¸o ´ continuamente
a c e
executado at´ que a condi¸˜o seja avaliada como false. Este processo de
e ca
repeti¸˜o ´ chamado itera¸˜o. Vamos ver o seguinte exemplo.
ca e ca
int i;
for(i=3;i<50;i*=2)
{ printf("%dn",i); }
O exemplo ir´ retornar na tela os inteiros 3, 6, 12, 24 e 48. O valor inicial
a
´ 3. Como a condi¸˜o i < 50 ´ true, 3 aparece na tela. Ent˜o, a express˜o
e ca e a a
i∗ = 2 fornece o segundo valor de i que ´ 6. Como i < 50 ainda ´ true, 6
e e
tamb´m ´ retornado na tela. Este processo ´ repetido at´ que i∗ = 2 forne¸a
e e e e c
96, one i < 50 ´ false.
e
O que acontece no exemplo abaixo?
int i;
for(i=3;i>5;i*=2)
{ printf("%dn",i); }
Nada!! A condi¸˜o n˜o ´ satisfeita quando i = 3 e portanto o la¸o n˜o ´
ca a e c a e
executado, muito menos a express˜o i∗ = 2.
a
O comando break pode ser usado para terminar a execu¸˜o do la¸o, e o
ca c
continue para a execu¸˜o da itera¸˜o atual e passa para a pr´xima. Para
ca ca o
deixar mais claro, vamos ver o exemplo.
int i;
for(i=3;i<50;i*=2)
{ if(i == 6) continue; // Passa para a pr´xima itera¸~o
o ca
printf("%dn",i);
if(i == 24) break; // P´ra a execu¸~o do la¸o qdo i ´ 24
a ca c e
}
28. 3.2 La¸os
c 25
Os inteiros 3, 12, 24 ir˜o aparecer na tela. Quando i for 6, o valor de i
a
n˜o ser´ retornado na tela j´ que o comando continue faz com que o controle
a a a
v´ para a pr´xima itera¸˜o com i = 6 ∗ 2 = 12. Quando i = 24, o la¸o ´
a o ca c e
terminado devido ao comando break.
Dica de programa¸˜o do L.F.
ca
Muito cuidado! Ao usar for, n˜o altere o valor do contador dentro
a
do la¸o, pois isso ´ uma alta fonte de erros.
c e
Um la¸o pode ser acoplado como qualquer outra express˜o. Por exemplo,
c a
int i,j;
double a = 0.;
for(i=0;i<100;i++)
{ for(j=200;j<=500;j++)
a+=i-j; // int s~o convertidos para double
a
}
computa a seguinte equa¸˜o
ca
99 500
(i − j) (3.1)
i=0 j=200
e
int i,j;
long double b = 5.;
for(i=1;i<5;i++)
for(j=27;j>=-3;j--)
b*=i+j*j;
computa a seguinte equa¸˜o (Putz!)
ca
4 27
5 (i + j 2 ) (3.2)
i=1 j=−3
29. 3.2 La¸os
c 26
Dica de programa¸˜o do L.F.
ca
Fa¸am a programa¸˜o de Chinˆs. Ao montarem um la¸o, exe-
c ca e c
cutem cada comando no papel e vejam se os resultados est˜o
a
chegando ao que vocˆ tinha em mente. Mas execute cada co-
e
mando mesmo! Vocˆs v˜o exercitar a vis˜o de programa¸˜o e
e a a ca
fica mais dif´ de deixar o programa com erros (pelo menos
ıcil
nessa parte que vocˆ fez o chinˆzinho).
e e
3.2.2 Comando while
O comando while possui a seguinte forma
while(condi¸~o)
ca
comandos
Os comandos s˜o executados at´ que a condi¸˜o seja avaliada em false.
a e ca
Se o valor inicial da condi¸˜o for falso, os comandos nunca ser˜o executados.
ca a
Por exemplo,
int i = 0;
while(i<=100)
{
printf("%d",i++);
}
O comando entre as chaves ser´ executado at´ que i <= 100 n˜o seja
a e a
mais true. O la¸o seguinte n˜o ir´ retornar para a tela nenhum valor j´ que
c a a a
sua condi¸˜o inicial ´ false.
ca e
int i = 10;
while(i>100) {
printf("Ainda bem que isso nao vai ser executado!! ");
printf("Eu ia escrever um monte de besteiras aqui!!n");
printf("%d",i++); }
30. 3.3 Exerc´
ıcios 27
O comando do-while ´ parecido com o la¸o while, por´m possui a seguinte
e c e
forma.
do
comandos
while(condi¸~o)
ca
A execu¸˜o dos comandos ´ continuada at´ que a condi¸˜o seja avali-
ca e e ca
ada como false. Neste caso, os comandos ser˜o executados pelo menos uma
a
vez. Os comandos continue e break tamb´m podem ser usados dentro dos
e
comandos while e do-while.
3.3 Exerc´
ıcios
I As linhas de comando seguintes implementadas em C tem a fun¸˜o de ca
alertar oralmente o usu´rio de perigosas leituras de temperatura em um sis-
a
tema de controle (valores em graus Fahrenheit). Este procedimento de aviso
est´ correto ou incorreto? Se estiver incorreto, explique porque e corrija-o
a
(n˜o programe!! Fa¸a no papel!!).
a c
if( temp < 97.5 )
{ printf("Temperatura abaixo do normal"); }
else if ( temp > 97.5 )
{ printf("Temperatura normal"); }
else if ( temp > 99.5 )
{ printf("Temperatura levemente alta"); }
else if ( temp > 103.0)
{ printf("Temperatura perigosamente alta"); }
II Use um la¸o acoplado para escrever o programa que computa a soma
c
100 300
cos(i2 + j) (3.3)
i=0 j=5
31. 3.3 Exerc´
ıcios 28
III Escreva um programa em C para calcular a fun¸˜o
ca
1
y(x) = ln( ) (3.4)
1−x
para qualquer valor de x pr´-especificado pelo usu´rio, onde ln ´ o loga-
e a e
ritmo natural ( logaritmo na base e). Escreva o programa com um la¸o while
c
de forma que o programa repita o c´lculo para cada valor legal de x aplicado
a
ao programa. Quando um valor ilegal de x for avaliado, termine o programa.
IV Escreva um programa em C para calcular y(t) vinda da Eq. 3.5 para
valores de t entre -9 a 9 em passos de 3.
−3t2 + 5, t≥0
y(t) = (3.5)
3t2 + 5, t>0
Escreva o resultado em tela e depois em um arquivo de sa´ (neste ultimo
ıda ´
caso, crie intervalos de 0.1 entre -9 e 9).
V Fa¸a um programa em C que calcule o resultado num´rico e anal´
c e ıtico da
seguinte s´rie, onde o usu´rio entra com o n´ mero de pontos N do somat´rio:
e a u o
N
1
Snum =
n=1 n
2
π2
Sana = (3.6)
6
Compare os resultados num´ricos fornecidos para diferentes valores de N
e
com o resultado anal´
ıtico.
VI O m´todo de Newton-Raphson ´ uma metodologia iterativa de solu¸˜o
e e ca
de equa¸˜es n˜o lineares. Ou seja, um m´todo num´rico que encontre o(s)
co a e e
32. 3.3 Exerc´
ıcios 29
valores de x que fa¸am com que f (x) = 0. Como estamos em um computa-
c
dor e trabalhando com vari´veis de ponto flutuante, deve-se assumir que o
a
objetivo de x foi atingido quando f (x) ´ menor que um erro pr´-definido. O
e e
m´todo de Newton-Raphson ´ colocado abaixo.
e e
f (x)
xk+1 = xk − , at´ que |xk+1 − xk | < erro
e (3.7)
f ′ (x)
O c´digo abaixo coloca o m´todo de Newton-Raphson da fun¸˜o f (x) =
o e ca
x
e + sen(x) utilizando um la¸o while. Modifique o programa de modo que
c
ele passe a usar o la¸o for e que o usu´rio possa entrar com o n´ mero de
c a u
itera¸˜es do m´todo. Existe diferen¸a entre usar um la¸o sem controle do
co e c c
n´ mero de itera¸˜es ou um que use? O que vocˆ acha?
u co e
#include<math.h>
#include<stdlib.h>
int main()
{
double x, xk, f, df, erro;
int i;
// Fun¸~o f(x) = exp(x) + sen(x)
ca
xk=10.; // Chute inicial
x = 0.; // Tem q inicializar a vari´vel
a
erro = 1.e-5; // Erro do m´todo
e
// Loop de converg^ncia
e
i = 1; // 1a Itera¸~o
ca
printf("It t Xn");
while(fabs(xk - x) > erro)
{
x = xk; // Atualiza a vari´vel
a
f = exp(x) + sin(x); // Calcula fun¸~o
ca
df= exp(x) + cos(x); // Calcula a derivada da fun¸~o
ca
xk= x - f/df; // M´todo de Newton-Raphson
e
printf("%d t %gn", i,xk);
i++;
}
printf("n Valor convergido!n");
printf(" x = %g n", xk);
34. Cap´
ıtulo 4
Tipos Derivados
4.1 Entrada e Sa´ em Arquivo
ıda
A biblioteca <stdio.h> possui fun¸˜es espec´
co ıficas para tratar a manipula¸˜o
ca
de arquivos em C. Assim ´ poss´ ler dados vindos de um arquivo ou escrever
e ıvel
os resultados do seu programa em outro (ou o mesmo) arquivo. Um arquivo
de controle deve ser declarado para que possa abrir um arquivo. Por exemplo,
int i,j,k;
FILE *stream;
A vari´vel stream ser´ como referˆncia em todas as manipula¸˜es de ar-
a a e co
quivo. Para manipular mais de um arquivo ao memso tempo, deve-se decla-
rar mais vari´veis do tipo F ILE. O comando fopen ´ usado para abrir um
a e
arquivo.
stream = fopen("NomeArquivo","Regra");
O comando fopen retorna para a vari´vel F ILE um valor indicando se o
a
processo de abertura do arquivo teve sucesso ou n˜o e ainda atribui ` F ILE
a a
as propriedades sobre o arquivo aberto (como as regras de I/O). O nome do
arquivo pode ser colocado diretamente ou usando uma vari´vel de caracteres
a
35. 4.1 Entrada e Sa´ em Arquivo
ıda 32
contendo o nome do arquivo. As regras definem as a¸˜es que podem ser
co
realizadas no arquivo (escrita, leitura, ambas, etc). O exemplo abaixo abre
um arquivo para escrever caracteres no arquivo at´ que o usu´rio entre com
e a
um caractere espec´ ıfico.As regras mais usuais para manipula¸˜o de arquivos
ca
est˜o listadas no exemplo abaixo.
a
/* Arquivos sao uma coletanea de bits armazenados
em algum tipo de midia.
Para abrir um arquivo:
FILE *fopen( const char *filename, const char *mode );
"r" - abre um arquivo somente para leitura. Se o arquivo
nao existe ou nao pode ser encontrado, a funcao
fopen retorna um ponteiro nulo.
"w" - abre um arquivo vazio para escrita. Se o arquivo
existe, seu conteudo e destruido.
"a" - abre um arquivo para escrita, a partir de seu final.
Se o arquivo nao existe, um novo arquivo e criado.
"r+" - abre um arquivo para escrita e leitura
(o arquivo deve existir).
"w+" - abre um arquivo para escrita e leitura.
Se o arquivo existe, seu conteudo e destruido.
"a+" - abre um arquivo para leitura e escrita, a partir de
seu final. Se o arquivo nao existe, um novo arquivo
e criado.
*/
#include <stdlib.h>
#include <stdio.h>
#include <conio.h>
main()
{
36. 4.1 Entrada e Sa´ em Arquivo
ıda 33
FILE *fp;
char ch;
fp = fopen("texto.txt","w");
while( (ch = getche()) != 13)
putc(ch, fp);
fclose(fp);
}
Ap´s usar o arquivo, o comando fclose fecha o arquivo. Os comandos
o
fprintf e fscanf() podem ser usados da mesma forma que os comandos para
tela, contudo ´ necess´rio indicar o F ILE nos comandos.
e a
#include<stdio.h>
int main()
{
FILE *arq;
arq = fopen("nome.txt", "w");
fprintf(arq,"Consegui escrevern");
fclose(arq);
return(0);
}
O exemplo a seguir cria um banco de dados de nome (char), idade (int) e
altura (float) em arquivo definido pelo usu´rio. A entrada no banco de dados
a
´ finalizada quando o nome contiver nenhum ou apenas 1 caractere.
e
#include <stdlib.h>
#include <stdio.h>
#include <conio.h>
#include <string.h>
int main()
{
37. 4.1 Entrada e Sa´ em Arquivo
ıda 34
FILE *fp;
char nomearq[40], nome[40];
int idade;
float altura;
/* Le o nome do arquivo na telea: */
printf("Entre o nome do arquivo: ");
gets(nomearq);
/* Abre o arquivo: */
fp = fopen(nomearq,"w");
/* Le os dados na tela e grava no arquivo: */
do
{
printf("Entre o nome, idade e altura: ");
scanf("%s %d %f", nome, &idade, &altura);
fprintf(fp, "%20s %5d %5.2fn", nome, idade, altura);
} while(strlen(nome) > 1);
/* Fecha o arquivo: */
fclose(fp);
return(0);
}
O exemplo a seguir lˆ os dados de nome (char), idade (int) e altura (float)
e
que est˜o dentro de um arquivo definido pelo usu´rio e mostra na tela seus
a a
valores at´ o final do arquivo (EOF — end of file).
e
#include <stdio.h>
#include <conio.h>
#include <string.h>
int main()
{
FILE *fp;
char nomearq[40], nome[40];
int idade;
float altura;
38. 4.2 Arrays - Vetores e Matrizes 35
/* Le o nome do arquivo na tela: */
printf("Entre o nome do arquivo: ");
gets(nomearq);
/* Abre o arquivo: */
fp = fopen(nomearq,"r");
/* Le os dados no arquivo e exibe na tela: */
while( fscanf(fp, "%s %d %f", nome, &idade, &altura) != EOF)
printf("%20s %3d %.2fn", nome,idade,altura);
/* Fecha o arquivo: */
fclose(fp);
return(0);
}
4.2 Arrays - Vetores e Matrizes
Sendo T uma vari´vel declarada, T [n] ´ um array unidimensional (vetor) de
a e
n elementos com o mesmo tipo de T . Os elementos s˜o indexados a partir
a
de 0 at´ n − 1 e s˜o armazenados de forma cont´
e a ınua na mem´ria, ou seja,
o
um elemento ap´s o outro. A Fig. 4.2 mostra como esse procedimento ´
o e
realizado na mem´ria RAM.
o
Figura 4.1: Aloca¸˜o do vetor v com n elementos na mem´ria.
ca o
A defini¸˜o de arrays ´ colocada a partir de exemplos.
ca e
int i,j;
float vec[3]; // array com 3 floats; vec[0], vec[1], vec[2]
39. 4.2 Arrays - Vetores e Matrizes 36
int st[30]; // array com 30 ints; st[0], ... st[29]
vec[0] = 1.0;
vec[2] = 2.0;
for(i=0;i<30;i++) st[i]=i*i+7;
j = st[29];
Os elementos dos arrays s˜o manipulados como se fossem vari´veis esca-
a a
lares e, portanto, todas as opera¸˜es que vimos at´ agora tamb´m se aplicam
co e e
aos arrays. Uma array bidimensional (matriz) com n linhas e m colunas pode
ser definido como T [n][m]. Os ´ ındices das linhas v˜o de 0 a n − 1 e os das
a
colunas v˜o de 0 a m − 1. Por exemplo,
a
int i,j;
double mt[2][5]; // array 2D c/ 2 linhas e 5 colunas
mt[0][0] = 5.0;
mt[1][4] = 5.0;
for(i=0;i<2;i++)
{ for(j=0;j<5;j++)
{ mt[i][j] = i + j; }
}
Um la¸o acoplado ´ muito usado para acessar todos os elementos de uma
c e
matriz. Um array bidimensional pode ser visto como um array unidimen-
sional de arrays unidimensionais. Por exemplo, mt pode ser visto como se
possu´ısse apenas 2 elementos: mt[0] e mt[1], onde mt[0] ´ um array uni-
e
dimensional de 5 elementos que representa a primeira linha de mt, e mt[1]
tamb´m ´ um array unidimensional de 5 elementos, mas que representa a
e e
segunda linha de mt. A Fig. 4.2 mostra como um array bidimensional ´ e
alocado na mem´ria.
o
Figura 4.2: Aloca¸˜o de matriz n por m na mem´ria.
ca o
40. 4.3 Ponteiros e Referˆncia
e 37
Arrays com trˆs ou mais dimens˜es podem ser usados de forma similar.
e o
Um array com k dimens˜es declarado como a[s1 ][s2 ] . . . [sk ] ir´ alocar espa¸o
o a c
para s1 × s2 × . . . × sk elementos que s˜o alocados contiguamente na mem´ria
a o
linha por linha
Os arrays podem ser inicializados ao serem declarados.
int v[] = {1, 2, 3, 4};
int a[3]= {2, 4, 5};
int u[][3] = { {1, 2, 3} , {4, 5, 8} };
char filename[30] = "output"; // Array de caracteres
Contudo, depois de declarados os valores dos elementos devem ser atri-
bu´
ıdos um por vez.
int v[4];
v = {2, 4, 5, 9}; // Erro!! N~o d´ para ser assim.
a a
/* A forma correta seria
v[0] = 2;
v[1] = 4;
v[2] = 5;
v[3] = 9; */
Ser´ que ´ poss´ inicializar uma matriz do seguinte modo??
a e ıvel
int v[2][3] = {1, 2, 0, 4, 0, 0};
4.3 Ponteiros e Referˆncia
e
Os ponteiros s˜o definidos da seguinte forma ∗T . Um ponteiro ∗T pode
a
armazenar o endere¸o ou local na mem´ria de uma vari´vel com o mesmo
c o a
tipo do ponteiro. Por exemplo,
41. 4.4 Exerc´
ıcios 38
int *p; // p ´ um ponteiro de um inteiro
e
declara a var´vel p como um ponteiro de inteiro. Este ponteiro pode ser
a
usado para armazenar o endere¸o na mem´ria de vari´veis inteiras. Sendo v
c o a
uma vari´vel, o seu endere¸o na mem´ria pode ser retornado usando &v. Se
a c o
p ´ uma vari´vel ponteiro, ∗p retorna o valor da vari´vel apontada por p.
e a a
int i = 5; // i ´ int, valor do objeto i ´ 5.
e e (a)
int* pi=&i; // p ´ um ponteiro de um inteiro
e (b)
// e atribui o endere¸o de i a pi
c
int j = *pi; // valor da vari´vel apontada por pi (c)
a
// ´ atribu´do a j, j = 5;
e ı
double* = &j; // Ilegal!!
Para uma vari´vel de ponteiro p, o valor em ∗p ao qual a vari´vel aponta
a a
pode ser alterado.
double d1 = 2.7, d2 = 3.1; (a)
double* p = &d1; // p aponta para d1, *p = 2.7 (b)
double a = *p; // a = 2.7
p = &d2; // p aponta para d2, *p = 3.1 (c)
double b = *p; // b = 3.1
*p = 5.5; // o valor para qual p aponta ´ 5.5
e (d)
double c = *p; // c = 5.5
double d = d2; // d = 5.5, j´ que *p = 5.5
a
4.4 Exerc´
ıcios
I Simples e direto. Qual o objetivo do c´digo abaixo? N˜o programe!!
o a
Leia e entenda o que est´ acontecendo!! Repare na identa¸ao do programa!!
a c˜
Tente usar uma identa¸˜o parecida nos seus programas! Depois, vocˆ pode
ca e
programar para ver a execu¸˜o do programa.
ca
42. 4.4 Exerc´
ıcios 39
#include<stdio.h>
#include<stdlib.h>
#include<math.h>
#define n 20
int main()
{
double Tc[n+1], Tf[n+1];
double Tci, Tfi;
double dT;
int i;
//Intervalo de 0 a 100oC
dT = (100. - 0.)/(double)n;
// C´lculo das Temperaturas em Celsius
a
Tc[0] = 0.;
for(i=1;i<=n;i++)
Tc[i] = Tc[i-1] + dT;
// C´lculo das Temperaturas em Farenheit
a
printf("TC t TFn");
for(i=0;i<=n;i++)
{
Tf[i] = 9.*Tc[i]/5. + 32.;
printf("%.5g t %.5gn", Tc[i], Tf[i]);
}
// Entrando com a temperatura a ser interpolada
printf("n Entre com a temperatura em C : ");
scanf("%le",&Tci);
// Testando limites da tabela
if((Tci < Tc[0]) || (Tci > Tc[n]))
{ printf("Oooopss... Temperatura fora da faixa.n");
exit(1);
}
// Interpolando a temperatura
for(i=0;i<=n;i++)
43. 4.4 Exerc´
ıcios 40
{
if(Tci <= Tc[i])
{
/*Interpola¸~o*/
ca
Tfi = Tf[i-1] + (Tci-Tc[i-1])*(Tf[i]-Tf[i-1])
/(Tc[i]-Tc[i-1]);
break;
}
}
// Sa´da em tela
ı
printf("n Temperatura em F interpolada : %.7f", Tfi);
Tfi = 9.*Tci/5.+32.;
printf("n Temperatura em F calculada : %.7f n", Tfi);
return(0);
}
II O comando #def ine ´ uma macro em C, ou seja, ´ uma forma de definir
e e
opera¸˜es ou vari´veis constantes. Veja o exemplo abaixo, onde SQ ´ uma
co a e
macro para calcular o quadrado de uma fun¸˜o.
ca
#include<stdio.h>
#define SQ(x) ((x) * (x))
int main()
{
double x, y;
// faz as opera¸~es usando SQ
co
return(0);
}
Ser´ que tem diferen¸a se eu programar SQ como colocado na sequˆncia?
a c e
#define SQ(x) (x * x)
44. 4.4 Exerc´
ıcios 41
III Existe a seguinte tabela de rela¸˜o entre κT /ǫ e ΩD,AB e deseja-se in-
ca
terpolar os valores de ΩD,AB ao entrar com κT /ǫ. Escreva um algoritmo
para a interpola¸˜o para ΩD,AB , sem esquecer de verificar a validade do valor
ca
fornecido em tela pelo usu´rio.
a
κT /ǫ ΩD,AB
0.30 2.662
0.35 2.476
0.40 2.318
0.45 2.184
0.50 2.066
0.55 1.966
0.60 1.877
0.65 1.798
0.70 1.729
0.75 1.667
0.80 1.612
0.85 1.562
0.90 1.517
0.95 1.476
1.00 1.439
IV Calcule o tempo necess´rio para calcular a multiplica¸˜o de duas ma-
a ca
trizes quadradas (n × n), como ilustrado no c´digo abaixo, onde n = 100,
o
200, 300, . . ., 1900, 2000. Gere as matrizes de forma randˆmica (valores en-
o
tre 0 e 1). Grave um arquivo guardando o tamanho n da matriz e o tempo
necess´rio para efetuar o c´lculo (procure na internet a biblioteca necess´ria
a a a
para marcar o tempo em C). Fa¸a dois testes de multiplica¸ao, trocando a
c c˜
ordem dos la¸os i—j por j—i. Fa¸a um gr´fico com os valores de tempo e
c c a
tamanho de matriz para as duas situa¸˜es. O que acontece e porque?
co
for(k=0;k<n;k++)
{ for(i=0;i<n;i++)
{ for(j=0;j<n;j++)
{ C[i,j] += A[i,k]*B[k,j]; }
}
}
45. Cap´
ıtulo 5
Sub-rotinas
5.1 Fun¸˜es
co
5.1.1 Declara¸˜o e Defini¸˜o de Fun¸˜o
ca ca ca
A fun¸˜o pode considerar uma entrada de dados, realizar algumas instru¸˜es
ca co
e retornar algum resultado. Os parˆmetros de entrada e sa´ devem ter
a ıda
seus tipos especificados. Por exemplo, uma das fun¸˜es sqrt() contidas em
co
<math.h> recebe um double na entrada, calcula sua raiz quadrada e retorna
um double como resultado. Esta fun¸˜o ´ declarada como
ca e
double sqrt(double); // recebe double, retorna double
Quando uma fun¸˜o n˜o retorna nenhum valor, usa-se void para represen-
ca a
tar isso. Quando o tipo da sa´ n˜o ´ especificado, o padr˜o do compilador
ıda a e a
´ assumi-la como int. Quando a entrada da fun¸˜o n˜o ´ especificada indica
e ca a e
que n˜o existe dado de entrada. Alguns exemplos,
a
int square(int); // recebe int, retorna int
double sum(double,double); // recebe 2 double, retorna 1 double
int f(); // n~o recebe nada, retorna int
a
void g(double,double); // recebe 2 double, n~o retorna nada
a
h(int); // recebe int, retorna int
46. 5.1 Fun¸˜es
co 43
Nas declara¸˜es acima, as vari´veis de entrada (chamadas de parˆmetros
co a a
ou argumentos) e de sa´ (chamadas de valores de retorno) possuem apenas
ıda
tipos, sem descri¸˜o dos nomes. Os nomes podem ser inclu´
ca ıdos para melhor
leitura do c´digo, mas ser˜o ignorados pelo compilador.
o a
int square(int i); // retorna i*i
double pow(double base, double exp);
// retorna a base elevado ao expoente
Todas essas declara¸˜es s˜o chamadas de prototypes e s´ os tipos s˜o
co a o a
importantes para ele.
Todas as fun¸˜es devem ser definidas em algum lugar do c´digo uma unica
co o ´
vez e com suas instru¸˜es entre chaves.O comando return ´ usado para que
co e
a fun¸˜o produza um retorno. A defini¸˜o da fun¸˜o pode servir como sua
ca ca ca
declara¸˜o tamb´m. Por exemplo, a fun¸˜o square() pode ser definida como
ca e ca
int square(int x)
{ return x*x; }
Ap´s a execu¸˜o da fun¸˜o no programa principal, a pr´xima linha ser´
o ca ca o a
executada.
int i = 5, j, k;
j = square(i); // chamada da fun¸~o com i = 5
ca
k = j; // ap´s execu¸~o, k = j;
o ca
5.1.2 Passagem de Argumentos
Existem dois mecanismos de passagem de argumentos em C: passagem por
valor ou por referˆncia. Na passagem por valor, o argumento ´ avaliado
e e
quando a fun¸˜o ´ chamada e seu valor se torna o valor do parˆmetro durante
ca e a
a sua execu¸˜o. O padr˜o ´ a passagem por valor, como mostrado no exemplo
ca a e
abaixo.
int pass_val(int x)
47. 5.1 Fun¸˜es
co 44
{
x = x*x;
return(x + 5);
}
int i = 5, j;
j = pass_val(i);
// i = 5, j = 30
Na chamada da fun¸˜o j = pass val(i), o valor do argumento i, que ´
ca e
5, ´ passado ao parˆmetro x. A fun¸˜o pass val() ´ iniciada com x = 5,
e a ca e
executa seu bloco de instru¸˜es e retorna o valor 30 para j. Ent˜o, ap´s a
co a o
execu¸˜o da fun¸˜o, i = 5 e j = 30.
ca ca
Na passagem por referˆncia, o argumento deve ser uma vari´vel com um
e a
endere¸o na mem´ria e o argumento ´ passado para a fun¸˜o como uma
c o e ca
referˆncia, de forma que o parˆmetro se torne apenas um “apelido” do argu-
e a
mento e as mudan¸as ocorridas no parˆmetro ocorrem no argumento tamb´m.
c a e
int pass_val(int& x)
{
x = x*x;
return(x + 5);
}
int i = 5, j;
j = pass_val(i);
// i = 25, j = 30
Na chamada de j = pass val(i), o argumento i ´ passado como uma
e
referˆncia ao parˆmetro x. Ou seja, as duas vari´veis se referem ao mesmo
e a a
espa¸o da mem´ria. Ent˜o qualquer mudan¸a realizada em x dentro da
c o a c
fun¸˜o, ir´ afetar i. No caso acima, x ´ alterado dentro da fun¸˜o e assume
ca a e ca
valor de 25. Ent˜o, ap´s a execu¸˜o da fun¸˜o, i = 25 e j = 30.
a o ca ca
Passagem para ponteiros possuem o mesmo efeito de uma passagem por
referˆncia, j´ que os dois ponteiros apontam para o mesmo local. Veja o
e a
exemplo de trˆs varia¸˜es da fun¸˜o swap().
e co ca
void swap(int& p, int& q) {
48. 5.1 Fun¸˜es
co 45
int tmp = p;
p = q;
q = tmp;
}
int i = 2, j = 3;
swap(i, j); // Agora i = 3 e j = 2
-----------------------------------
void swap(int* p, int* q) {
int tmp = *p;
*p = *q;
*q = tmp;
}
int i = 2, j = 3;
swap(&i, &j); // Agora i = 3 e j = 2
-----------------------------------
void swap(int p, int q) {
int tmp = p;
p = q;
q = tmp;
}
int i = 2, j = 3;
swap(i, j); // Agora i = 2 e j = 3
A passagem por valor n˜o muda o valor dos argumentos, enquanto a
a
passagem por referˆncia ou valor de ponteiros usualmente implica que o valor
e
dos argumentos ser˜o alterados durante a chamada da fun¸ao, a n˜o ser que
a c˜ a
seja explicitamente especificado para n˜o fazer isso usando a palavra-chave
a
const.
int g(int val, const int& ref) {
ref = 5; // Erro!!! Compilador vai reclamar!!
val++;
return(ref + val);
}
49. 5.1 Fun¸˜es
co 46
O nome de um array ´ um ponteiro const que aponta para o seu pri-
e
meiro elemento. Ent˜o, os argumentos em forma de array s˜o tratados como
a a
ponteiros e possuem o mesmo efeito de uma passagem por referˆncia.
e
double h(double* const d, int n) {
int i;
double sum = 0.;
for(i=0;i<n;i++)
sum += d[i];
d[n-1] = 1000.; // Mas pode alterar d!
return(sum);
}
double a[] = {1,2,8,20,-10,30};
double sum, d5;
sum = h(a,6); // Soma dos elementos de a
d5 = a[5]; // d5 = 1000
Ponteiros constantes apontam para locais constantes, ou seja, n˜o ´ per-
a e
metido alterar o local em que ele aponta. Mas tamb´m ´ poss´ n˜o permitir
e e ıvel a
que o array seja modificado.
double gh(const double* const d, int n) {
int i;
double sum = 0.;
for(i=0;i<n;i++)
sum += d[i];
d[n-1] = 1000.; // P´´´´!! Erro!!
eeee
return(sum);
}
Qualquer fun¸˜o que n˜o seja declarada como void deve retornar um valor
ca a
(com exce¸˜o de main). Por exemplo,
ca
int square(int& i)
{ i*=i; } // Erro!! Um valor precisa ser retornado!
50. 5.2 Exerc´
ıcios 47
5.2 Exerc´
ıcios
I O que est´ acontecendo no programa abaixo? Analise a passagem de
a
parˆmetros pelas fun¸˜es.
a co
#include<stdio.h>
// Prototypes
int swap(int* p, int q, double x, double* y)
{
int i; /* Vc pode definir vari´veis na sua
a
rotina q j´ foram definidas em main */
a
double f;
*p = 25; // Valor foi atualizado fora da subrotina
for(i=0;i<q;i++)
{ printf("%g - ", y[i]); y[i] = 0.; }
printf("n");
f = x;
return(0);
}
int main()
{
int i,j;
double z, v[5]= {0., 1.25, 2.55, 3.5, 4.};
i = 2;
j = 5;
z = 2.5;
// v = {0., 1.25, 2.55, 3.5, 4.};
swap(&i, j, z, v);
printf("%d - %d - %gn", i, j, z);
for(i=0;i<5;i++) { printf("%g - ", v[i]); }
printf("n");
return(0);
}
51. 5.2 Exerc´
ıcios 48
II Um algoritmo para encontrar a raiz quadrada de um n´ mero real positivo
u
´:
e
1 b
x0 = 1, xn+1 = 2
xn + xn
, n = 0, 1, 2, . . .
Escreva uma fun¸˜o que implemente este algoritmo. Observe uma r´pida
ca √ a
convergˆncia (quadr´tica) no resultado de xn → b. Compare a acur´cia da
e a a
fun¸˜o com a fun¸˜o intr´
ca ca ınseca sqrt() da biblioteca <math.h>.
III Considerando o polinˆmio de grau n
o
pn (x) = an xn + an−1 xn−1 + . . . + a1 x + a0
Considere os coeficientes do polinˆmio de grau 8 como um vetor (a[]={1,
o
-8, 28, -56, 70, -56, 28, -8, 1}).
a. Escreva uma fun¸˜o que avalie este polinˆmio.
ca o
b. O c´lculo direto de um polinˆmio n˜o ´ eficiente devido ` computa¸˜o
a o a e a ca
de cada expoente em x. Um m´todo eficiente ´ o algoritmo de Horner
e e
(ou multiplica¸˜es acopladas). A id´ia ´ reescrever pn (x) da seguinte
co e e
forma:
pn (x) = (. . . ((an x + an−1 )x + an−2 )x + . . . + a1 )x + a0
Isto introduz a seguinte nota¸˜o:
ca
un = an ;
un−1 = un x + an−1 ;
un−2 = un−1 x + an−2 ;
.
.
.
u1 = u2 x + a1 ;
u0 = u1 x + a0 ;
Assim, pn (x) = u0 . Em princ´
ıpio, parece necess´rio guardar un , un−1, . . . ,
a
e u0 em um array. Por´m, isso n˜o ´ preciso j´ que depois do c´lculo
e a e a a
de un−1 o valor de un n˜o ´ mais necess´rio. O algoritmo de Horner ´
a e a e
escrito na sequˆncia.
e
• Inicializa u = an
• for(i = n − 1, n − 2, . . . , 0)
u ← ux + ai ;
52. 5.2 Exerc´
ıcios 49
Construa uma outra fun¸˜o para calcular o polinˆmio usando o algo-
ca o
ritmo de Horner.
c. Compare os resultados fornecidos pelas duas fun¸˜es.
co
IV Exerc´ mais f´cil n˜o existe!! V´ no seguinte site:
ıcio a a a
http://www.gnu.org/software/gsl/manual/gsl-ref toc.html#TOC471
Este ´ o site das bibliotecas livres da GNU (distribui¸˜o livre — de gra¸a!)
e ca c
escritas em C e C++. S˜o todas as rotinas existentes para c´lculo cient´
a a ıfico
da GNU e s˜o residentes do sistema operacional linux (contudo, podem fun-
a
cionar em compiladores windows). Procure na lista de rotinas o m´todo dos
e
m´ınimos quadrados (Least-Squares Fitting) e estude os exemplos ali coloca-
dos.