Sunteți pe pagina 1din 52

UNIVERSIDADE FEDERAL DO RIO DE JANEIRO

Coordenacao dos Programas de Posgraduacao em Engenharia


Programa de Engenharia Qumica
Laboratorio de Termofluidodinamica

Introduc
ao `
a Programac
ao em C

Curso de Extens
ao

Luiz Fernando Lopes Rodrigues Silva, PEQ/COPPE/UFRJ

RIO DE JANEIRO, RJ BRASIL


2005

Sum
ario
1 Introdu
c
ao `
a Programa
c
ao
1.1 Interpretacao do Arquivofonte
1.2 Computacao Cientfica . . . . .
1.3 Exerccios . . . . . . . . . . . .
1.4 Primeiro Programa em C . . . .

.
.
.
.

.
.
.
.

.
.
.
.

.
.
.
.

.
.
.
.

.
.
.
.

.
.
.
.

.
.
.
.

.
.
.
.

.
.
.
.

.
.
.
.

.
.
.
.

.
.
.
.

.
.
.
.

.
.
.
.

.
.
.
.

.
.
.
.

2
2
3
4
5

2 Tipos e Operadores B
asicos
2.1 Tipos de Variaveis . . . . . . . . . .
2.1.1 Declaracao de Variaveis . . .
2.1.2 Variaveis Inteiras . . . . . . .
2.1.3 Variaveis de Caracteres . . . .
2.1.4 Variaveis de Ponto Flutuante
2.1.5 Variaveis Booleanas . . . . . .
2.2 Tipos de Operadores . . . . . . . . .
2.2.1 Operadores Aritmeticos . . .
2.2.2 Operadores Relacionais . . . .
2.2.3 Operadores Logicos . . . . . .
2.3 Exerccios . . . . . . . . . . . . . . .

.
.
.
.
.
.
.
.
.
.
.

.
.
.
.
.
.
.
.
.
.
.

.
.
.
.
.
.
.
.
.
.
.

.
.
.
.
.
.
.
.
.
.
.

.
.
.
.
.
.
.
.
.
.
.

.
.
.
.
.
.
.
.
.
.
.

.
.
.
.
.
.
.
.
.
.
.

.
.
.
.
.
.
.
.
.
.
.

.
.
.
.
.
.
.
.
.
.
.

.
.
.
.
.
.
.
.
.
.
.

.
.
.
.
.
.
.
.
.
.
.

.
.
.
.
.
.
.
.
.
.
.

.
.
.
.
.
.
.
.
.
.
.

.
.
.
.
.
.
.
.
.
.
.

7
7
8
8
9
10
11
12
12
15
15
16

3 Fluxos de Controle
3.1 Condicionais . . . . . . . .
3.1.1 Comando ifelse if
3.1.2 Comando switch .
3.2 Lacos . . . . . . . . . . . .
3.2.1 Comando for . . .
3.2.2 Comando while . .
3.3 Exerccios . . . . . . . . .

.
.
.
.
.
.
.

.
.
.
.
.
.
.

.
.
.
.
.
.
.

.
.
.
.
.
.
.

.
.
.
.
.
.
.

.
.
.
.
.
.
.

.
.
.
.
.
.
.

.
.
.
.
.
.
.

.
.
.
.
.
.
.

.
.
.
.
.
.
.

.
.
.
.
.
.
.

.
.
.
.
.
.
.

.
.
.
.
.
.
.

.
.
.
.
.
.
.

19
19
19
21
23
23
26
27

.
.
.
.
.
.
.

.
.
.
.
.
.
.

.
.
.
.
.
.
.

.
.
.
.
.
.
.

.
.
.
.
.
.
.

.
.
.
.
.
.
.

4 Tipos Derivados
31
4.1 Entrada e Sada em Arquivo . . . . . . . . . . . . . . . . . . . 31
4.2 Arrays - Vetores e Matrizes . . . . . . . . . . . . . . . . . . . 35


SUMARIO
4.3
4.4

ii

Ponteiros e Referencia . . . . . . . . . . . . . . . . . . . . . . 37
Exerccios . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 38

5 Sub-rotinas
5.1 Funcoes . . . . . .
5.1.1 Declaracao e
5.1.2 Passagem de
5.2 Exerccios . . . . .

. . . . . . . . . . . .
Definicao de Funcao
Argumentos . . . .
. . . . . . . . . . . .

.
.
.
.

.
.
.
.

.
.
.
.

.
.
.
.

.
.
.
.

.
.
.
.

.
.
.
.

.
.
.
.

.
.
.
.

.
.
.
.

.
.
.
.

.
.
.
.

42
42
42
43
47

Pref
acio
Atualmente em qualquer area de atuacao profissional, o computador se torna
uma ferramenta cada vez mais presente. Seja para montar um relatorio para
a empresa, estruturar uma apresentacao sobre suas atividades e progressos,
executar tarefas repetitivas de analise de dados em uma fabrica, entre muitas
outras funcoes. Mas o principal objetivo deste curso e mostrar os meios
de uso do computador como ferramenta cientfica para realizar calculos de
modo eficiente. Em outras palavras, como analisar um problema qualquer e
estruturar uma metodologia de solucao de forma que o computador entenda
o que o usuario quer, execute os comandos o mais rapido possvel e forneca
resultados confiaveis.
O objetivo desta apostila e apenas de colocar as informacoes basicas sobre
a linguagem de programacao C de modo a auxiliar o treinamento do aluno
durante o curso. Como alguns topicos serao colocados em sala de aula, eu
coloquei alguns codigos com espaco suficiente para que voces possam anotar
as discussoes. A descricao da linguagem nao depende do sistema operacional, seja Windows, Linux, DOS, MacOS, UNIX, desde que um compilador C
esteja instalado. Existem duas referencias sobre C que eu gostaria de passar
para voces. A primeira e o livro de Brian W. Kernighan e Dennis M. Ritchie
intitulado C A linguagem de programacao padrao ANSI. Estes autores
foram os desenvolvedores da linguagem C e apesar do livro possuir um bom
conte
udo, seus exemplos sao mais voltados para manipulacao de caracteres.
Ja o livro C++ and object-oriented numeric computing for scientists and
engineers de Daoqi Yang e uma referencia excelente para programacao cientfica. Apesar de ser um livro de C++, muitos fundamentos basicos de C
sao usados e vale (muito!!) a pena dar uma olhada nele.
Espero que gostem do curso,
Luiz Fernando L. R. Silva
PEQ/COPPE/UFRJ
21/07/2005

Captulo 1
Introdu
c
ao `
a Programa
c
ao
1.1

Interpreta
c
ao do Arquivofonte

Os programas de computador sao formados por uma serie de instrucoes que


o computador executa. Quando voce cria um programa, precisa especificar
as instrucoes que o computador precisara executar para realizar as operacoes
desejadas. A definicao destas instrucoes e que voce deve fazer e salvar em
um arquivo, chamado de arquivo ou codigo fonte. O arquivo fonte de um
programa escrito em C deve possuir a extensao C (ex. arqfonte.c). O arquivo fonte e o modo do programador montar a sua logica de programacao e
comunicar isso ao computador. Mas o computador nao entende diretamente
o arquivo fonte e precisa de um tradutor, chamado de compilador. Para criar
programas, e imperativo e necessario que o compilador esteja instalado no
computador. O compilador converte as instrucoes colocadas no arquivo fonte
para a linguagem de maquina (binaria 0 ou 1) que o computador compreende. Os arquivos gerados com a extensao EXE ou COM contem o codigo
de maquina e podem ser executados pelo computador. A Fig. 1.1 ilustra
esse processo de geracao do codigo fonte, compilacao e criacao do arquivo
executavel.

1.2 Computac
ao Cientfica

Figura 1.1: Conversao do codigo fonte para codigo de maquina.

1.2

Computac
ao Cientfica

Em qualquer aplicacao cientfica, a eficiencia computacional e muito importante e o programador deve sempre ficar atento a esse detalhe. Mas como
montar um programa de forma eficiente? Bem, antes de pensar em programacao propriamente dita devese estruturar muito bem qual e o problema
e qual a melhor forma de resolvelo. Se isso nao estiver bem assentado na
cabeca do programador, e melhor parar por a e comecar a ler o seu problema
novamente. Afinal de contas, como voce vai resolver o seu problema de forma
eficiente, se nem sabe ainda como resolvelo?
Dica de programac
ao do L.F.
Antes de pensar em programar, organize as ideias no papel. Mesmo
para os problemas mais simples. Sempre!! A princpio pode
parecer perda de tempo, mas a facilidade de estruturar o seu
codigo fonte ser
a recompensadora.
As etapas necessarias de solucionar o problema e o que vamos chamar de
metodologia de algoritmo e a forma como estas etapas sao executadas esta
includa na logica de programacao. Estas definicoes vao ficar mais claras ao
analisarmos um exemplo.

1 Exemplo da distancia percorrida pelo carro com aceleracao constante.

1.3 Exerccios

Bem, temos o problema nas maos, ou seja, um modelo matematico a ser


resolvido.
1
S = S0 + v0 t at2
(1.1)
2
Quais sao as perguntas que sempre devemos fazer para estruturar a metodologia do algoritmo?
Qual o meu objetivo? Calcular S!!! Entao, essa e a u
ltima coisa
com que devemos nos preocupar.
O que eu preciso para calcular S? S0 , v0 , a e t. Aaah, entao eu
tenho que me preocupar em saber os valores dessas variaveis antes de
calcular S...
- Atribuir valores para S0 , v0 , a e t.
- Existe alguma restricao numerica e/ou fsica no meu modelo?
Nao existe tempo negativo.
Condicao para que o programa rejeite valores negativos de
tempo.
Calculamos S.
Mostramos ao usuario o resultado. Senao, nao adianta nada, ne?
Mesmo para um problema simples, algumas perguntas devem ser respondidas antes de tentar calcular qualquer coisa. Eu ficaria muito feliz se ao
longo do curso (e depois tambem) voces sempre montassem o algoritmo de
solucao. Voces notarao que, com o tempo e a pratica, estruturar a solucao de
um problema ficara muito mais facil e podera ate ser feita automaticamente.
Podem confiar.

1.3

Exerccios

I Monte a estrutura de solucao para os problemas abaixo.

1.4 Primeiro Programa em C

1) A troca de calor em um reator nao isotermico precisa ser otimizada.


Voce foi incumbido de calcular a quantidade de calor trocada entre o reator
e o meio ambiente. O modelo de troca termica esta colocado abaixo, onde Q
e a quantidade de calor trocada, U A e o coeficiente global de transferencia
de calor, Tr e a temperatura do reator e T e a temperatura do ambiente.
Q = U A(Tr T )

(1.2)

2) A Baa de Guanabara possui uma concentracao de petroleo que esta


se dispersando com o passar do tempo. A dispersao de petroleo na baa segue
o modelo descrito na Eq. 1.3 onde Cp e a concentracao de petroleo no instante
t, Cp0 e a concentracao inicial de petroleo e A e a area onde o petroleo esta
disperso. Contudo, a area de dispersao do petroleo varia devido `a condicoes
climaticas e com o proprio tempo. Um modelo (Eq. 1.4) descreve a variacao
e uma media
da area em que o petroleo esta disperso, onde o parametro M
dos efeitos climaticos.
Cp = Cp0 eAt
(1.3)
et
A=M
(1.4)

1.4

Primeiro Programa em C

Agora que ja vimos como montar os nossos problemas de uma forma estruturada, ja podemos ver um primeiro exemplo de programacao em C. Note
que ainda nao vimos nenhum comando desta linguagem e este exemplo ira
servir apenas como uma forma de comecarmos uma discussao em torno da
logica de programacao em C.
Um programa em C necessariamente deve conter a funcao main() que
contem as instrucoes (ou comandos) entre entre { e }. Cada comando pode
ser escrito em mais de uma linha e deve ser terminado por um ponto e
vrgula (; se nao tiver, vai dar erro na compilacao do programa). Os
comentarios no codigo fonte estao entre /* e */ (todo o texto entre esses dois
smbolos e desconsiderado pelo compilador) ou precedidos por // (a linha
toda fica comentada). Os comentarios podem conter varias informacoes sobre
o problema (qual o problema a ser resolvido, qual a metodologia que vai ser
utilizada, quem programou o codigo, quando, etc.), o codigo fonte (o porque
de usar um comando especfico) ou mesmo detalhes de como usar o programa

1.4 Primeiro Programa em C

depois de compilado. A princpio, comentar o arquivo fonte pode parecer uma


tarefa exaustiva, porem estes sao muito u
teis para o entendimento futuro do
codigo.
Dica de programac
ao do L.F.
Sempre comente o seu codigo. Nao preciso colocar os porques,
apenas comente!!!!!
O objetivo deste primeiro programa e simplesmente escrever uma mensagem na tela para o usuario. O codigo fonte esta colocado a seguir.

/* Este
e um simples programa para escrever na tela
uma mensagem de texto.
Programado por: Luiz Fernando L. R. Silva
*/
#include<stdio.h> // Biblioteca padr~
ao I/O em tela
main()
{
// Comando para escrever em tela.
printf("Eu adoro programar em C");
}
As tres primeiras linhas do codigo sao comentarios (estao entre /* e */) e
colocam algumas informacoes sobre o programa. Os outros comentarios desse
programa sao menores e sao precedidos por duas barras //. As bibliotecas em
C contem varios comandos e funcoes padroes para auxiliar na programacao.
Para habilitar esses comandos, e necessario declarar as bibliotecas no incio
do programa. A biblioteca padrao que contem os comandos de entrada e
sada de dados em tela chama-se <stdio.h> e esta declarada logo apos o
primeiro comentario. Essa declaracao habilita que o programador use todos
os comandos de entrada e sada padrao em tela. O comando printf efetua essa
operacao mostrando ao usuario a seguinte mensagem: Eu adoro programar
em C. Pronto, o nosso primeiro programa esta pronto.

Captulo 2
Tipos e Operadores B
asicos
2.1

Tipos de Vari
aveis

Vamos considerar a seguinte expressao matematica:

z =y+ix

(2.1)

Para que a Eq. 2.1 faca sentido em no codigo fonte, os identificadores 1


x, y, z e i devem ser declarados de forma adequada. Todos os identificadores
devem ser declarados antes de serem usados. As declaracoes introduzem
entidades representadas por seus identificadores e seus tipos (ex. inteiro ou
caractere).
Os tipos das variaveis fornecem propriedades diferentes tanto na forma
de armazenamento da variavel na memoria RAM quanto na propria manipulacao e operacao da variavel. Existem operacoes que so sao possveis ou
sao muito mais eficientes se realizadas com um determinado tipo de variavel.

if( i == 0 )
{ /* realiza os comandos aqui dentro */ }
1

Os identificadores s
ao as letras usadas para identificar as suas vari
aveis.

2.1 Tipos de Vari


aveis

2.1.1

Declarac
ao de Vari
aveis

A declaracao das variaveis no codigo fonte indica que o programa deve reservar um espaco na memoria RAM para cada variavel declarada. Vamos
considerar que a memoria RAM esta distribuda como na Fig. 2.1.1 e dividida em bytes.

Figura 2.1: Representacao da memoria RAM subdividida em bytes.


Agora vamos considerar que no incio do programa as variaveis i e z estejam sendo declaradas e portanto, um espaco na memoria deve ser reservado.
Este procedimento e o que chamamos de alocacao de espaco na memoria.
Deste modo, os valores que forem atribudos nestas variaveis ficam alocados
em um endereco especfico da memoria RAM. A quantidade de memoria que
deve ser reservada depende do tipo da variavel.

Figura 2.2: Alocacao de variaveis na memoria RAM.

2.1.2

Vari
aveis Inteiras

Cada variavel inteira ocupa 2 bytes de memoria e o valor armazenado na


memoria nao inclui a parte fracionaria. Um exemplo segue abaixo.

#include<stdio.h>
main()
{
int i;

// Declara
c~
ao de i como inteira

2.1 Tipos de Vari


aveis

int j,k; /* Declara


c~
ao de j e k como inteiros.

E poss
vel declarar mais de uma
vari
avel por linha */
int ii = 123; // Ao declarar ii, j
a atribuo um valor.
i = 2;
// Atribui
c~
ao do valor 2 para a vari
avel i
j = i;
// Atribui
c~
ao do valor contido em i para j
k = 2.3; /* N~
ao considera a parte fracion
aria!
k assume o valor de 2 */
/* Sa
da em tela das vari
aveis*/
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
aveis de Caracteres

Cada variavel caractere ocupa 1 byte na memoria e armazena valores inteiros


que sao convertidos em caracteres ASCII (o valor do inteiro 98 corresponde ao
caractere b no conjunto ASCII). Normalmente, o que se quer e uma variavel
que armazene um conjunto de caracteres para que seja possvel construir
palavras ou sentencas. Alguns caracteres sao especiais e possuem algumas
funcoes especficas.
Caractere
\n
\t
\v
\a
\r
\b

Fun
c
ao especfica
nova linha
tabulacao horizontal
tabulacao vertical
alerta sonoro
cursor volta para o incio da linha
backspace

Tabela 2.1: Caracteres especiais para operar a sada de dados.


Um exemplo (extremamente idiota!) de aplicacao de caracteres.
#include <stdio.h>
#include <conio.h>

2.1 Tipos de Vari


aveis

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: %c\n", 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
aveis de Ponto Flutuante

As variaveis de ponto flutuante sao capazes de armazenar as casas decimais


de um n
umero. Existem duas classificacoes para as variaveis de ponto flutu-

2.1 Tipos de Vari


aveis

11

ante, com precisao simples (normalmente com 6 casas decimais) ou de dupla


precisao (normalmente com 15 casas decimais). Um exemplo quantifica bem
a diferenca entre esses dois tipos de variaveis.

#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.19f\n", pi_float);
printf("Valor com precisao dupla : %21.19f\n", pi_double);
return(1);
}
Compilando e executando o codigo acima em um AthlonXP 2.2GHz, os
resultados para estao colocados abaixo.

Valor com precisao simples : 3.1415927410125732000


Valor com precisao dupla
: 3.1415926535897931000
Obs.: executem o programa colocado acima mudando a referencia %21.19f
da variavel de ponto flutuante. Mude o n
umero das casas decimais, o n
umero
dos espacos reservados para a variavel e troque o f do ponto flutuante por
%g, %e e %E. Vejam e analisem as mudancas.

2.1.5

Vari
aveis Booleanas

Um booleano, representado por bool, pode armazenar dois valores: true ou


false, e e usado para expressar os resultados de expressoes logicas.

2.2 Tipos de Operadores

bool flag = true;


double d;

12

// declara
c~
ao de flag como booleana

/* Algum c
odigo no meio do caminho, que pode
eventualmente mudar o valor de flag */
d = 3.14;
if(flag == false)
{ d = 2.718; }
/* E o programa continua... */
Algumas comparacoes estao descritas na tabela abaixo.
true && true = true
true && false = false
false && true = false
false && false = false

true || true = true


true || false = true
false || true = true
false || false = false

Tabela 2.2: Comparacoes de booleanos && significa E; || significa OU


Por definicao, false tem o valor 0 e true tem valor 1. Por isso, pessoalmente, eu nao uso variaveis booleanas, mas um inteiro com valor de 0 (falso)
ou 1 (verdadeiro).

2.2

Tipos de Operadores

Pronto, ja sabemos quais sao os tipos de variaveis que existem e agora estamos aptos a realizar operacoes com elas.

2.2.1

Operadores Aritm
eticos

Sao os operadores basicos de soma (+), subtracao (), multiplicacao ()


muito importante entender o tipo de variavel que se esta
e divisao (/). E
operando, pois perda de informacao pode ocorrer. Veja o exemplo a seguir.

2.2 Tipos de Operadores

13

double m = 13/4;

/*
e uma opera
c~
ao entre dois inteiros, e vai
fornecer um resultado inteiro!!
m = 3, as casas decimais s~
ao ignoradas */
double n = 3/4;
/* n = 0 */
double y = 3.0/4; /* Ao operar, o inteiro 4
e convertido para
double! y = 0.75 */
double y = 3/4.0; /* Idem, 3
e convertido em 3.0! y = 0.75 */
As operacoes matematicas sao iniciadas da esquerda para a direita. A
multiplicacao e a divisao possuem uma maior precedencia em relacao `a soma
e subtracao. Contudo, o que esta contido nos parenteses possue uma precedencia maior que a dos operadores. Vejamos as etapas de execucao das
expressoes colocadas no exemplo abaixo.

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 programac
ao do L.F.
Sempre que voce tiver d
uvidas sobre a ordem das operacoes, use
o parenteses sem medo de ser feliz.

int m;
m = ((5+3)*2) - 3;

/* m = (8*2) - 3;

2.2 Tipos de Operadores

14

m = 16 - 3;
m = 13; */
Os operadores de incremento (++) e decremento () sao muito usados
em qualquer programa C, pois facilitam a leitura do codigo (alguns dizem
quem nao...).
int conta = 0;
int m = 2;
conta++; /* Essa opera
c~
ao pode
conta = conta + 1;
conta--; /* Essa opera
c~
ao pode
conta = conta - 1;
++m;
/* m = 3; */
m = conta++; /* m = 0; conta =

ser substitu
da por:
(conta = 1) */
ser substitu
da por:
(conta = 0) */
1;*/

Vamos analisar o seguinte codigo (em aula).


#include<stdio.h>
int main()
{
int valor = 1;
printf("Usando depois da variavel : %d\n", valor++);
printf("Valor apos incremento: %d\n", valor);
valor = 1;
printf("Usando depois da variavel : %d\n", ++valor);
printf("Valor apos incremento: %d\n", valor);
return(1);
}
Ainda e possvel realizar operacoes de atribuicao da seguinte maneira.
total += 100;
conta -= 5;
metade /=2;

// Significa: total = total + 100;


// Significa: conta = conta - 5;
// Significa: metade = metade/2;

2.2 Tipos de Operadores

2.2.2

15

Operadores Relacionais

Os operadores relacionais sao > (maior que), < (menor que), >= (maior ou
igual a), <= (menor ou igual a), == (igual a) e ! = (nao igual). A notacao ! e
o operador de negacao. O resultado destas operacoes e sempre um booleano.
int x = 5;
bool b, c;
b = (x < 6);
c = (x == 0);
if(b != c)
x = 17;
if(b)
x = 19;
if(!b)
x = 221;

// b = true, j
a que x
e menor que 6
// b = false, j
a que x n~
ao
e 0
// Se b n~
ao
e igual a c, x = 17
// Se b
e true, ent~
ao fa
ca x = 19
// Se b
e false, ent~
ao fa
ca x = 221

Deve-se tomar muito cuidado ao usar essas operacoes. Considere o exemplo abaixo.
int m =
bool b,
b = 3 <
m = 20;
c = 3 <

7;
c;
m < 9; // b = true
m < 9; // c = true

Os operadores relacionais sao executados da esquerda para a direita, por


isso a expressao 3 < m < 9 e equivalente `a (3 < m) < 9. Entao, esta
expressao sempre e avaliada como true pois 3 < m pode ser tanto 1 (true)
quanto 0 (false).

2.2.3

Operadores L
ogicos

Os operadores logicos, assim como os relacionais, resultam em um valor booleano. Esses operadores sao && (e) e || (ou) e posuem uma precedencia

2.3 Exerccios

16

maior que os operadores relacionais (sao executados antes). A Tabela 2.2


mostra as relacoes com os booleanos. Veja os exemplos a seguir.

bool
bool
bool
bool
bool
bool

b
d
e
f
g
h

=true, c = false;
= b && c;
= b || c;
= (e == false) && c;
= (d == true ) || c;
= (d = true ) || c;

//
//
//
//
//

d
e
f
g
h

=
=
=
=
=

false
true
false
false
true

Vamos agora rever a expressao 3 < m < 9. A maneira correta de programar esta expressao em C seria

(3 < m) && (m < 9)


Como o operador < possue uma precedencia maior que o operador &&,
os dois pares de parenteses poderiam ser omitidos.

2.3

Exerccios

I As variaveis a, b, c, d, e, f e g foram inicializadas com os seguintes valores:


a = 3.

b = 2.

c = 5.

d = 4.

e = 10.

Efetue as seguintes expressoes em C :


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)

f = 2.

g = 3.

2.3 Exerccios

17

II Analise o codigo abaixo para calcular a media das notas de um aluno.


Programe este codigo e retire alguns dos comentarios e comente alguns comandos para entender como o codigo funciona.

/*C
alculo da m
edia dos alunos*/
#include <stdio.h>
int main()
{
double M,P1,P2;
// Entrada de dados pelo c
odigo
P1 = 5.0;
P2 = 7.5;
/* Entrada de dados em tela
printf("Digite o valor da primeira prova P1\n");
printf("Digite o valor da segunda prova P2\n");
scanf("%16le",&P1);
scanf("%16le",&P2);
*/
// C
alculo da m
edia
// C
alculo direto
M=(P1+P2)/2.;
// C
alculo em duas etapas
//M = P1 + P2;
//M /= 2;
if(M >= 7.) { printf("O aluno esta aprovado\n"); }
else { printf("O aluno devera fazer prova final\n"); }
printf("A media do aluno e: %.2f\n",M);
return(1);
}

III Faca um programa em C que calcule a velocidade em queda livre de


um corpo
a 6 m de altura. Sabe-se que a formula de queda livre e dada por

v = 2gh, onde g = 9.81. Faca um outro programa em que seja possvel que
o usuario entre na tela com o valor da altura (cuidado, porque ate onde eu

2.3 Exerccios

18

sei e os limites da fsica permitem, nao existe altura negativa).

IV Faca um programa em C que leia uma temperatura em graus Farenheit,


converta-a para uma temperatura absoluta em kelvins, e escreva o resultado.
A formula de conversao e:

T (K) =

5.
[T (F ) 32.0] + 273.15
9.

(2.2)

V O coseno hiperbolico e definido pela equacao:

cosh(x) =

ex + ex
2.

(2.3)

Escreva um programa em C para calcular o coseno hiperbolico para um


valor x fornecido pelo usuario. Use o programa para calcular o coseno hiperbolico de 3.0. Compare a resposta que seu programa fornece com a resposta produzida pela funcao intrnseca do C cosh(x), contida na biblioteca
<math.h>.

Captulo 3
Fluxos de Controle
3.1
3.1.1

Condicionais
Comando ifelse if

A forma mais simples de um condicional e o comando if, cuja sintaxe e:


if(condi
c~
ao) express~
ao
onde condicao e uma expressao logica que possui valor de true ou false, e
expressao pode ser apenas um ou varios comandos. A expressao e executada
quando o valor de condicao e avaliado em true, senao a expressao nao e
executada. A condicao deve estar entre parenteses.
if(n>10) x*=10;
if(n==0) {
x*=5;
}
if(n) y*=7;

// Qdo n>10, fa
ca x*=10
// Qdo n
e 5, fa
ca x*=5

// Qdo n!=0,

fa
ca y*=7

Os condicionais devem ser usados com cuidado quando a expressao requer


a comparacao de variaveis nao inteiras. Considere x e y como variaveis de

3.1 Condicionais

20

ponto flutuante, a condicao if(x == y) deve ser substituda por if(fabs(x - y)


< erro) onde erro e um n
umero muito pequeno definido pelo usuario e fabs e
a funcao matematica que retorna o valor absoluto de uma variavel de ponto
flutuante.
Dica de programac
ao do L.F.
Tome muito cuidado ao avaliar vari
aveis em ponto flutuante.
Note ainda que existe diferenca entre == e =! Aqui, o programador pode e deve usar e abusar dos parenteses e dos
operadores l
ogicos e relacionais.
O condicional if pode ser acompanhado pela parte opcional else.

if(condi
c~
ao)
express~
ao1
else
express~
ao2
onde, se a condicao for avaliada como true, a expressao1 e executada
enquanto a expressao2 e desprezada. Se a condicao retornar um valor false,
a expressao1 e desprezada e a expressao2 e executada. Ainda e possvel
combinar os condicionais ifelse da seguinte maneira:

if(condi
c~
ao1)
express~
ao1
else if(condi
c~
ao2)
express~
ao2
else if(condi
c~
ao3)
express~
ao3
else
express~
ao4
onde a expressao1 e executada so e somente so se a condicao1 for true.
Se for true, todo o resto do bloco e ignorado; e se for false a expressao1 nao
e executada e a condicao2 e testada. Se a u
ltima for true, a expressao2 e

3.1 Condicionais

21

avaliada e o resto do bloco e desprezado, enquanto se a condicao2 for false o


resto do bloco e ignorado. Esse procedimento e repetido ate o final do bloco,
onde se nenhuma das condicoes forem true, a expressao4 sera executada.
Note que a u
ltima expressao e um caso que nao possui nenhuma restricao e
sera efetuado sempre que nenhuma das condicoes anteriores forem satisfeitas.
Vamos ver o exemplo abaixo. O programador quer montar uma estrutura
que retorne os parametros fsicos da agua. Porem, ate onde eu sei e a fsica
explica, dependendo da temperatura, a agua pode se apresentar na forma
solida, lquida ou gasosa e seus parametros fsicos dependem de sua forma.
Como fazer isso?

// Usu
ario entra com T (em K)
printf("Entre com a temperatura da agua (K)");
scanf("%16le",&T);
printf("\n");
if(T
{ //
//
}
else
{ //
//
}
else
{ //
//
}

<= 273.15)
Gelo!
Calcula par^
ametros para gelo
if((T >= 273.15) && (T <= 373.15))
L
quido!
Calcula par^
ametros para
agua l
quida

S
o sobrou o vapor (fora o plasma!!)
Calcula par^
ametros para vapor d
agua

3.1.2

Comando switch

O comando switch e muito usado em situacoes de m


ultipla escolhas. Este
testa o valor da condicao, colocada entre parenteses apos a palavra chave
switch. Entao este valor e usado como um controle de escolha para os casos
que satisfazem esse valor. Se o valor nao satisfaz nenhum caso, o controle ira
para o caso default. O comando break e usado para sair do comando switch.

3.1 Condicionais

22

Vamos analisar o exemplo abaixo, onde o programador quer calcular o


coeficiente de transferencia de calor em alguns casos especificados. Sabe-se
que os modelos matematicos sao diferentes para cada situacao fsica, entao
devemos colocar restricoes no usos destes ou deixar que o usuario especifique
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^
ametros dos modelos, n
e?
// Se n~
ao j
a era!!!!
printf("Lista de opcoes para calcular o coeficiente ");
printf("de transferencia de calor:\n");
printf("A - Modelo para Conveccao Interna em tubos\n");
printf("B - Modelo para Conveccao Externa\n");
printf("C - Modelo para Conveccao Natural\n");
printf("D - Modelo para Conveccao com condensacao\n");
printf("Entre com sua opcao : ");
letra = getch();
// Transforma letra min
uscula em mai
uscula
letra = toupper(letra);
printf("\n");
// Vamos escolher qual modelo? Depende do q o usu
ario quer...
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

3.2 La
cos

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
c~
oes foram satisfeitas
printf("Esse caractere nao e valido. Foi mal...\n");
};
return (1);
}
Dica de programac
ao do L.F.
Voce sabia que os condicionais s
ao um dos comandos mais com
maior custo computacional que existem? Se quiser montar
um programa com menor custo de computacao, use o menor n
umero de condicionais possvel e somente quando for
necess
ario.

3.2
3.2.1

La
cos
Comando for

O laco for e muito utilizado e extremamente conveniente de ser usado. Sua


forma geral esta colocada abaixo.

for(inicia;condi
c~
ao;express~
ao)
comandos

3.2 La
cos

24

A inicia representa a inicializacao da variavel de controle do laco, a


condicao fornece um controle para determinar se o laco deve continuar a
ser executado e expressao indica como a variavel inicializada deve ser avaliada a cada vez que os comandos sao executados. O laco e continuamente
executado ate que a condicao seja avaliada como false. Este processo de
repeticao e chamado iteracao. Vamos ver o seguinte exemplo.

int i;
for(i=3;i<50;i*=2)
{ printf("%d\n",i); }
O exemplo ira retornar na tela os inteiros 3, 6, 12, 24 e 48. O valor inicial
e 3. Como a condicao i < 50 e true, 3 aparece na tela. Entao, a expressao
i = 2 fornece o segundo valor de i que e 6. Como i < 50 ainda e true, 6
tambem e retornado na tela. Este processo e repetido ate que i = 2 forneca
96, one i < 50 e false.
O que acontece no exemplo abaixo?

int i;
for(i=3;i>5;i*=2)
{ printf("%d\n",i); }
Nada!! A condicao nao e satisfeita quando i = 3 e portanto o laco nao e
executado, muito menos a expressao i = 2.
O comando break pode ser usado para terminar a execucao do laco, e o
continue para a execucao da iteracao atual e passa para a proxima. Para
deixar mais claro, vamos ver o exemplo.

int i;
for(i=3;i<50;i*=2)
{ if(i == 6) continue;
printf("%d\n",i);
if(i == 24) break;
}

// Passa para a pr
oxima itera
c~
ao
// P
ara a execu
c~
ao do la
co qdo i
e 24

3.2 La
cos

25

Os inteiros 3, 12, 24 irao aparecer na tela. Quando i for 6, o valor de i


nao sera retornado na tela ja que o comando continue faz com que o controle
va para a proxima iteracao com i = 6 2 = 12. Quando i = 24, o laco e
terminado devido ao comando break.
Dica de programac
ao do L.F.
Muito cuidado! Ao usar for, n
ao altere o valor do contador dentro
do laco, pois isso e uma alta fonte de erros.
Um laco pode ser acoplado como qualquer outra expressao. Por exemplo,
int i,j;
double a = 0.;
for(i=0;i<100;i++)
{ for(j=200;j<=500;j++)
a+=i-j; // int s~
ao convertidos para double
}
computa a seguinte equacao
500
99 X
X

i=0 j=200

(i j)

(3.1)

(i + j 2 )

(3.2)

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 equacao (Putz!)
5

27
4 Y
Y

i=1 j=3

3.2 La
cos

26

Dica de programac
ao do L.F.
Facam a programacao de Chines. Ao montarem um laco, executem cada comando no papel e vejam se os resultados est
ao
chegando ao que voce tinha em mente. Mas execute cada comando mesmo! Voces vao exercitar a vis
ao de programacao e
fica mais difcil de deixar o programa com erros (pelo menos
nessa parte que voce fez o chinezinho).

3.2.2

Comando while

O comando while possui a seguinte forma

while(condi
c~
ao)
comandos
Os comandos sao executados ate que a condicao seja avaliada em false.
Se o valor inicial da condicao for falso, os comandos nunca serao executados.
Por exemplo,

int i = 0;
while(i<=100)
{
printf("%d",i++);
}
O comando entre as chaves sera executado ate que i <= 100 nao seja
mais true. O laco seguinte nao ira retornar para a tela nenhum valor ja que
sua condicao inicial e false.

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++); }

3.3 Exerccios

27

O comando do-while e parecido com o laco while, porem possui a seguinte


forma.

do
comandos
while(condi
c~
ao)
A execucao dos comandos e continuada ate que a condicao seja avaliada como false. Neste caso, os comandos serao executados pelo menos uma
vez. Os comandos continue e break tambem podem ser usados dentro dos
comandos while e do-while.

3.3

Exerccios

I As linhas de comando seguintes implementadas em C tem a funcao de


alertar oralmente o usuario de perigosas leituras de temperatura em um sistema de controle (valores em graus Fahrenheit). Este procedimento de aviso
esta correto ou incorreto? Se estiver incorreto, explique porque e corrija-o
(nao programe!! Faca no papel!!).

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 laco acoplado para escrever o programa que computa a soma


300
100 X
X

i=0 j=5

cos(i2 +

j)

(3.3)

3.3 Exerccios

28

III Escreva um programa em C para calcular a funcao

y(x) = ln(

1
)
1x

(3.4)

para qualquer valor de x pre-especificado pelo usuario, onde ln e o logaritmo natural ( logaritmo na base e). Escreva o programa com um laco while
de forma que o programa repita o calculo para cada valor legal de x aplicado
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.

3t + 5,

y(t) =

3t + 5,

t0

(3.5)

t>0

Escreva o resultado em tela e depois em um arquivo de sada (neste u


ltimo
caso, crie intervalos de 0.1 entre -9 e 9).

V Faca um programa em C que calcule o resultado numerico e analtico da


seguinte serie, onde o usuario entra com o n
umero de pontos N do somatorio:

Snum =

N
X
1

n=1

Sana =

n2

2
6

(3.6)

Compare os resultados numericos fornecidos para diferentes valores de N


com o resultado analtico.

VI O metodo de Newton-Raphson e uma metodologia iterativa de solucao


de equacoes nao lineares. Ou seja, um metodo numerico que encontre o(s)

3.3 Exerccios

29

valores de x que facam com que f (x) = 0. Como estamos em um computador e trabalhando com variaveis de ponto flutuante, deve-se assumir que o
objetivo de x foi atingido quando f (x) e menor que um erro pre-definido. O
metodo de Newton-Raphson e colocado abaixo.

xk+1 = xk

f (x)
,
f (x)

ate que |xk+1 xk | < erro

(3.7)

O codigo abaixo coloca o metodo de Newton-Raphson da funcao f (x) =


ex + sen(x) utilizando um laco while. Modifique o programa de modo que
ele passe a usar o laco for e que o usuario possa entrar com o n
umero de
iteracoes do metodo. Existe diferenca entre usar um laco sem controle do
n
umero de iteracoes ou um que use? O que voce acha?

#include<math.h>
#include<stdlib.h>
int main()
{
double x, xk, f, df, erro;
int i;
// Fun
c~
ao f(x) = exp(x) + sen(x)
xk=10.;
// Chute inicial
x = 0.;
// Tem q inicializar a vari
avel
erro = 1.e-5; // Erro do m
etodo
// Loop de converg^
encia
i = 1; // 1a Itera
c~
ao
printf("It \t X\n");
while(fabs(xk - x) > erro)
{
x = xk;
// Atualiza a vari
avel
f = exp(x) + sin(x); // Calcula fun
c~
ao
df= exp(x) + cos(x); // Calcula a derivada da fun
c~
ao
xk= x - f/df;
// M
etodo de Newton-Raphson
printf("%d \t %g\n", i,xk);
i++;
}
printf("\n Valor convergido!\n");
printf(" x = %g \n", xk);

3.3 Exerccios

return (0);
}

30

Captulo 4
Tipos Derivados
4.1

Entrada e Sada em Arquivo

A biblioteca <stdio.h> possui funcoes especficas para tratar a manipulacao


de arquivos em C. Assim e possvel ler dados vindos de um arquivo ou escrever
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 variavel stream sera como referencia em todas as manipulacoes de arquivo. Para manipular mais de um arquivo ao memso tempo, deve-se declarar mais variaveis do tipo F ILE. O comando fopen e usado para abrir um
arquivo.
stream = fopen("NomeArquivo","Regra");
O comando fopen retorna para a variavel F ILE um valor indicando se o
processo de abertura do arquivo teve sucesso ou nao e ainda atribui `a F ILE
as propriedades sobre o arquivo aberto (como as regras de I/O). O nome do
arquivo pode ser colocado diretamente ou usando uma variavel de caracteres

4.1 Entrada e Sada em Arquivo

32

contendo o nome do arquivo. As regras definem as acoes que podem ser


realizadas no arquivo (escrita, leitura, ambas, etc). O exemplo abaixo abre
um arquivo para escrever caracteres no arquivo ate que o usuario entre com
um caractere especfico.As regras mais usuais para manipulacao de arquivos
estao listadas no exemplo abaixo.

/* 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()
{

4.1 Entrada e Sada em Arquivo

33

FILE *fp;
char ch;
fp = fopen("texto.txt","w");
while( (ch = getche()) != 13)
putc(ch, fp);
fclose(fp);
}
Apos usar o arquivo, o comando fclose fecha o arquivo. Os comandos
fprintf e fscanf() podem ser usados da mesma forma que os comandos para
tela, contudo e necessario indicar o F ILE nos comandos.
#include<stdio.h>
int main()
{
FILE *arq;
arq = fopen("nome.txt", "w");
fprintf(arq,"Consegui escrever\n");
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 usuario. A entrada no banco de dados
e finalizada quando o nome contiver nenhum ou apenas 1 caractere.
#include
#include
#include
#include

<stdlib.h>
<stdio.h>
<conio.h>
<string.h>

int main()
{

4.1 Entrada e Sada em Arquivo

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.2f\n", nome, idade, altura);
} while(strlen(nome) > 1);
/* Fecha o arquivo: */
fclose(fp);
return(0);
}
O exemplo a seguir le os dados de nome (char), idade (int) e altura (float)
que estao dentro de um arquivo definido pelo usuario e mostra na tela seus
valores ate o final do arquivo (EOF end of file).

#include <stdio.h>
#include <conio.h>
#include <string.h>
int main()
{
FILE *fp;
char nomearq[40], nome[40];
int
idade;
float altura;

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 %.2f\n", nome,idade,altura);
/* Fecha o arquivo: */
fclose(fp);
return(0);
}

4.2

Arrays - Vetores e Matrizes

Sendo T uma variavel declarada, T [n] e um array unidimensional (vetor) de


n elementos com o mesmo tipo de T . Os elementos sao indexados a partir
de 0 ate n 1 e sao armazenados de forma contnua na memoria, ou seja,
um elemento apos o outro. A Fig. 4.2 mostra como esse procedimento e
realizado na memoria RAM.

Figura 4.1: Alocacao do vetor v com n elementos na memoria.


A definicao de arrays e colocada a partir de exemplos.
int i,j;
float vec[3]; // array com 3 floats; vec[0], vec[1], vec[2]

4.2 Arrays - Vetores e Matrizes

int st[30];

36

// 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 sao manipulados como se fossem variaveis escalares e, portanto, todas as operacoes que vimos ate agora tambem se aplicam
aos arrays. Uma array bidimensional (matriz) com n linhas e m colunas pode
ser definido como T [n][m]. Os ndices das linhas vao de 0 a n 1 e os das
colunas vao de 0 a m 1. Por exemplo,
int i,j;
double mt[2][5];
mt[0][0] = 5.0;
mt[1][4] = 5.0;

// array 2D c/ 2 linhas e 5 colunas

for(i=0;i<2;i++)
{ for(j=0;j<5;j++)
{ mt[i][j] = i + j; }
}
Um laco acoplado e muito usado para acessar todos os elementos de uma
matriz. Um array bidimensional pode ser visto como um array unidimensional de arrays unidimensionais. Por exemplo, mt pode ser visto como se
possusse apenas 2 elementos: mt[0] e mt[1], onde mt[0] e um array unidimensional de 5 elementos que representa a primeira linha de mt, e mt[1]
tambem e um array unidimensional de 5 elementos, mas que representa a
segunda linha de mt. A Fig. 4.2 mostra como um array bidimensional e
alocado na memoria.

Figura 4.2: Alocacao de matriz n por m na memoria.

4.3 Ponteiros e Refer


encia

37

Arrays com tres ou mais dimensoes podem ser usados de forma similar.
Um array com k dimensoes declarado como a[s1 ][s2 ] . . . [sk ] ira alocar espaco
para s1 s2 . . . sk elementos que sao alocados contiguamente na memoria
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 atriudos


um por vez.

int v[4];
v = {2, 4, 5, 9}; // Erro!! N~
ao d
a para ser assim.
/* A forma correta seria
v[0] = 2;
v[1] = 4;
v[2] = 5;
v[3] = 9; */
Sera que e possvel inicializar uma matriz do seguinte modo??

int v[2][3] = {1, 2, 0, 4, 0, 0};

4.3

Ponteiros e Refer
encia

Os ponteiros sao definidos da seguinte forma T . Um ponteiro T pode


armazenar o endereco ou local na memoria de uma variavel com o mesmo
tipo do ponteiro. Por exemplo,

4.4 Exerccios

int *p;

38

// p
e um ponteiro de um inteiro

declara a varavel p como um ponteiro de inteiro. Este ponteiro pode ser


usado para armazenar o endereco na memoria de variaveis inteiras. Sendo v
uma variavel, o seu endereco na memoria pode ser retornado usando &v. Se
p e uma variavel ponteiro, p retorna o valor da variavel apontada por p.
int i = 5;
int* pi=&i;
int j = *pi;
double* = &j;

//
//
//
//
//
//

i
e int, valor do objeto i
e 5.
(a)
p
e um ponteiro de um inteiro
(b)
e atribui o endere
co de i a pi
valor da vari
avel apontada por pi (c)

e atribu
do a j, j = 5;
Ilegal!!

Para uma variavel de ponteiro p, o valor em p ao qual a variavel aponta


pode ser alterado.

double d1 = 2.7, d2 = 3.1;


double* p = &d1; // p aponta para d1, *p = 2.7
double a = *p;
// a = 2.7

(a)
(b)

p = &d2;
double b = *p;

// p aponta para d2, *p = 3.1


// b = 3.1

(c)

*p = 5.5;
double c = *p;
double d = d2;

// o valor para qual p aponta


e 5.5
// c = 5.5
// d = 5.5, j
a que *p = 5.5

(d)

4.4

Exerccios

I Simples e direto. Qual o objetivo do codigo abaixo? Nao programe!!


Leia e entenda o que esta acontecendo!! Repare na identacao do programa!!
Tente usar uma identacao parecida nos seus programas! Depois, voce pode
programar para ver a execucao do programa.

4.4 Exerccios

#include<stdio.h>
#include<stdlib.h>
#include<math.h>
#define

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
alculo das Temperaturas em Celsius
Tc[0] = 0.;
for(i=1;i<=n;i++)
Tc[i] = Tc[i-1] + dT;
// C
alculo das Temperaturas em Farenheit
printf("TC \t TF\n");
for(i=0;i<=n;i++)
{
Tf[i] = 9.*Tc[i]/5. + 32.;
printf("%.5g \t %.5g\n", 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++)

39

4.4 Exerccios

40

{
if(Tci <= Tc[i])
{
/*Interpola
c~
ao*/
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 e uma macro em C, ou seja, e uma forma de definir


operacoes ou variaveis constantes. Veja o exemplo abaixo, onde SQ e uma
macro para calcular o quadrado de uma funcao.

#include<stdio.h>
#define SQ(x) ((x) * (x))
int main()
{
double x, y;
// faz as opera
c~
oes usando SQ
return(0);
}
Sera que tem diferenca se eu programar SQ como colocado na sequencia?

#define

SQ(x) (x * x)

4.4 Exerccios

41

III Existe a seguinte tabela de relacao entre T / e D,AB e deseja-se interpolar os valores de D,AB ao entrar com T /. Escreva um algoritmo
para a interpolacao para D,AB , sem esquecer de verificar a validade do valor
fornecido em tela pelo usuario.
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 necessario para calcular a multiplicacao de duas matrizes quadradas (nn), como ilustrado no codigo abaixo, onde n = 100, 200, 300,
. . . , 1900, 2000. Gere as matrizes de forma randomica (valores entre 0 e 1).
Grave um arquivo guardando o tamanho n da matriz e o tempo necessario
para efetuar o calculo (procure na internet a biblioteca necessaria para marcar o tempo em C). Faca dois testes de multiplicacao, trocando a ordem dos
lacos ij por ji. Faca um grafico com os valores de tempo e tamanho de
matriz para as duas situacoes. O que acontece e porque?
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]; }
}
}

Captulo 5
Sub-rotinas
5.1
5.1.1

Fun
c
oes
Declarac
ao e Definic
ao de Func
ao

A funcao pode considerar uma entrada de dados, realizar algumas instrucoes


e retornar algum resultado. Os parametros de entrada e sada devem ter
seus tipos especificados. Por exemplo, uma das funcoes sqrt() contidas em
<math.h> recebe um double na entrada, calcula sua raiz quadrada e retorna
um double como resultado. Esta funcao e declarada como
double sqrt(double); // recebe double, retorna double
Qunado uma funcaao nao retorna nenhum valor, usa-se void para representar isso. Quando o tipo da sada nao e especificado, o padrao do compilador e assumi-la como int. Quando a entrada da funcao nao e especificada
indica que nao existe dado de entrada. Alguns exemplos,
int square(int);
double sum(double,double);
int f();
void g(double,double);

//
//
//
//

recebe int, retorna int


recebe 2 double, retorna 1 double
n~
ao recebe nada, retorna int
recebe 2 double, n~
ao retorna nada

5.1 Fun
c
oes

h(int);

43

// recebe int, retorna int

Nas declaracoes acima, as variaveis de entrada (chamadas de parametros


ou argumentos) e de sada (chamadas de valores de retorno) possuem apenas
tipos, sem descricao dos nomes. Os nomes podem ser includos para melhor
leitura do codigo, mas serao ignorados pelo compilador.
int square(int i);
// retorna i*i
double pow(double base, double exp);
// retorna a base elevado ao expoente
Todas essas declaracoes sao chamadas de prototypes e so os tipos sao
importantes para ele.
Todas as funcoes devem ser definidas em algum lugar do codigo uma u
nica
vez e com suas instrucoes entre chaves.O comando return e usado para que
a funcao produza um retorno. A definicao da funcao pode servir como sua
declaracao tambem. Por exemplo, a funcao square() pode ser definida como
int square(int x)
{ return x*x; }
Apos a execucao da funcao no programa principal, a proxima linha sera
executada.
int i = 5, j, k;
j = square(i);
// chamada da fun
c~
ao com i = 5
k = j;
// ap
os execu
c~
ao, k = j;

5.1.2

Passagem de Argumentos

Existem dois mecanismos de passagem de argumentos em C: passagem por


valor ou por referencia. Na passagem por valor, o argumento e avaliado
quando a funcao e chamada e seu valor se torna o valor do parametro durante
a sua execucao. O padrao e a passagem por valor, como mostrado no exemplo
abaixo.

5.1 Fun
c
oes

44

int pass_val(int x)
{
x = x*x;
return(x + 5);
}
int i = 5, j;
j = pass_val(i);
// i = 5, j = 30
Na chamada da funcao j = pass val(i), o valor do argumento i, que e
5, e passado ao parametro x. A funcao pass val() e iniciada com x = 5,
executa seu bloco de instrucoes e retorna o valor 30 para j. Entao, apos a
execucao da funcao, i = 5 e j = 30.
Na passagem por referencia, o argumento deve ser uma variavel com um
endereco na memoria e o argumento e passado para a funcao como uma
referencia, de forma que o parametro se torne apenas um apelido do argumento e as mudancas ocorridas no parametro cocrrem no argumento tambem.
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 e passado como uma
referencia ao parametro x. Ou seja, as duas variaveis se referem ao mesmo
espaco da memoria. Entao qualquer mudanca realizada em x dentro da
funcao, ira afetar i. No caso acima, x e alterado dentro da funcao e assume
valor de 25. Entao, apos a execucao da funcao, i = 25 e j = 30.
Passagem para ponteiros possuem o mesmo efeito de uma passagem por
referencia, ja que os dois ponteiros apontam para o mesmo local. Veja o
exemplo de tres variacoes da funcao swap().

5.1 Fun
c
oes

45

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 = 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 nao muda o valor dos argumentos, enquanto a
passagem por referencia ou valor de ponteiros usualmente implica que o valor
dos argumentos serao alterados durante a chamada da funcao, a nao ser que
seja explicitamente especificado para nao fazer isso usando a palavra-chave
const.

int g(int val, const int& ref) {


ref = 5; // Erro!!! Compilador vai reclamar!!
val++;
return(ref + val);
}

5.1 Fun
c
oes

46

O nome de um array e um ponteiro const que aponta para o seu primeiro elemento. Entao, os argumentos em forma de array sao tratados como
ponteiros e possuem o mesmo efeito de uma passagem por referencia.

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, nao e permetido alterar o local em que ele aponta. Mas tambem e possvel nao permitir
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
e
e
e
e!! Erro!!
return(sum);
}
Qualquer funcao que nao seja declarada como void deve retornar um valor
(com excecao de main). Por exemplo,

int square(int& i)
{ i*=i; } // Erro!! Um valor precisa ser retornado!

5.2 Exerccios

5.2

47

Exerccios

I O que esta acontecendo no programa abaixo? Analise a passagem de


parametros pelas funcoes.

#include<stdio.h>
// Prototypes
int swap(int* p, int q, double x, double* y)
{
int i; /* Vc pode definir vari
aveis na sua
rotina q j
a foram definidas em main */
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
j
z
//

=
=
=
v

2;
5;
2.5;
= {0., 1.25, 2.55, 3.5, 4.};

swap(&i, j, z, v);
printf("%d - %d - %g\n", i, j, z);
for(i=0;i<5;i++) { printf("%g - ", v[i]); }
printf("\n");
return(0);

5.2 Exerccios

48

II Um algoritmo para encontrar a raiz quadrada de um n


umero real positivo
e:
x0 = 1,

xn+1 =

1
2

xn +

b
xn

n = 0, 1, 2, . . .

Escreva uma funcao que implemente este algoritmo.


Observe Uma rapida

convergencia (quadratica) no resultado de xn b. Compare a acuracia da


funcao com a funcao intrnseca sqrt() da biblioteca <math.h>.

III Considerando o polinomio de grau n


pn (x) = an xn + an1 xn1 + . . . + a1 x + a0
Considere os coeficientes do polinomio de grau 8 como um vetor (a[]={1,
-8, 28, -56, 70, -56, 28, -8, 1}).
a. Escreva uma funcao que avalie este polinomio.
b. O calculo direto de um polinomio nao e eficiente devido `a computacao
de cada expoente em x. Um metodo eficiente e o algoritmo de Horner
(ou multiplicacoes acopladas). A ideia e reescrever pn (x) da seguinte
forma:
pn (x) = (. . . ((an x + an1 )x + an2 )x + . . . + a1 )x + a0
Isto introduz a seguinte notacao:
un = a n ;
un1 = un x + an1 ;
un2 = un1 x + an2 ;
..
.
u1 = u 2 x + a 1 ;
u0 = u 1 x + a 0 ;
Assim, pn (x) = u0 . Em princpio, parece necessario guardar un , un1 , . . . ,
e u0 em um array. Porem, isso nao e preciso ja que depois do calculo
de un1 o valor de un nao e mais necessario. O algoritmo de Horner e
escrito na sequencia.

5.2 Exerccios

49

Inicializa u = an

for(i = n 1, n 2, . . . , 0)
u ux + ai ;

Construa uma outra funcao para calcular o polinomio usando o algoritmo de Horner.
c. Compare os resultados fornecidos pelas duas funcoes.

IV Exerccio mais facil nao existe!! Va no seguinte site:


http://www.gnu.org/software/gsl/manual/gsl-ref toc.html#TOC471
Este e o site das bibliotecas livres da GNU (distribuicao livre de graca!)
escritas em C e C++. Sao todas as rotinas existentes para calculo cientfico
da GNU e sao residentes do sistema operacional linux (contudo, podem funcionar em compiladores windows). Procure na lista de rotinas o metodo dos
mnimos quadrados (Least-Squares Fitting) e estude os exemplos ali colocados.

S-ar putea să vă placă și