Vous êtes sur la page 1sur 60

Linguagem e Tcnica de Programao I

Ivan Mathias Filho Pgina 1 16/05/00



2. Pseudo-Linguagem

2.1 Consideraes Preliminares

Os computadores convencionais se baseiam no conceito de uma memria principal
que consiste de clulas elementares, cada qual identificada por um endereo. O
contedo de uma clula o valor da mesma. O valor de uma clula pode ser lido e/ou
modificado. Esta modificao feita pela substituio de um valor por outro. Alm
disso, circuitos permitem o acesso a uma clula de cada vez. Com poucas excees, as
linguagens de programao podem ser consideradas como abstraes, em nveis
diferentes, do comportamento destes computadores convencionais. Em particular, o
conceito de varivel introduzido como uma abstrao de clulas de memria, e o
conceito de comando de atribuio como uma abstrao destrutiva destas clulas.
Uma varivel caracterizada por um nome e dois atributos bsicos: valor e tipo. O
nome usado para identificar e fazer referncia varivel. O valor de uma varivel
representado, de forma codificada, na rea de memria amarrada varivel. Este
cdigo interpretado de acordo com o tipo da varivel. O tipo de uma varivel pode
ser considerado como uma especificao da classe de valores que podem ser
associados varivel, bem como das operaes que podem ser usadas para criar,
acessar e modificar estes valores.
A amarrao entre uma varivel e o valor armazenado na rea de memria
correspondente , em geral, dinmica, j que este valor pode ser modificado por
operaes de atribuio. Uma atribuio como b a causa o armazenamento de uma
cpia do valor da varivel a na rea de memria amarrada varivel b.
Algumas linguagens, entretanto, permitem o congelamento da amarrao entre uma
varivel e o seu valor quando a amarrao estabelecida. A entidade resultante , sob
qualquer aspecto, uma constante simblica definida pelo programador.
Por exemplo, em Pascal se pode escrever:

const
pi = 3.1416;

e ento usar pi em uma expresso como circunferncia:= 2 * pi * raio;.
A varivel pi est amarrada ao valor 3.1416, e este valor no pode ser modificado;
isto , o compilador acusa erro se existir uma atribuio pi.
Poderamos usar o valor 3.1416 diretamente na expresso acima, dispensando o uso
da constante simblica pi (circunferncia:= 2 * 3.1416 * raio;). Neste caso,
chamamos 3.1416 de constante literal.

2.2 A Pseudo-linguagem LPE

Nos itens subseqentes iremos descrever as regras sintticas e semnticas de uma
linguagem de construo de algoritmos chamada Linguagem de Programao
Estruturada (LPE). Esta linguagem tem por objetivo permitir a elaborao de um
algoritmo sem termos que nos preocupar com as regras rgidas de uma linguagem de
Linguagem e Tcnica de Programao I

Ivan Mathias Filho Pgina 2 16/05/00

programao real. Apesar da LPE possuir um certo formalismo, nos permitido
"afrouxar" as suas regras sintticas quando for conveniente. Isto pode ser feito pelo
fato da LPE no ser uma linguagem de programao real; isto , no existe nenhum
tradutor de LPE que nos permita executar um programa escrito nesta linguagem em
um computador real.
Um programa em LPE ter o seguinte lay-out:

constantes
<nome> = <valor>;

<nome> = <valor>;
variveis
<nome> : <tipo>;

<nome> : <tipo>;
incio
<comando>;

<comando>;
fim.

No lay-out acima, tudo o que estiver em negrito faz parte da sintaxe da linguagem;
e o que estiver entre < > ser posteriormente substitudo por construes dos
programadores. Esta construes, porm, tero tambm que obedecer s regras da
LPE.

2.2.1 Nomes

Um nome de uma varivel, ou de uma constante simblica, uma seqncia de no
mximo 32 caracteres alfanumricos, alm do caracter sublinhado ( _ ). O primeiro
caracter tem que ser obrigatoriamente alfabtico. A linguagem LPE no faz distino
entre caracteres maisculos e minsculos.

Exemplo:

a
nome_aluno
c8
valor
xyz

2.2.2 Tipos

2.2.2.1 Inteiro

O tipo inteiro usado para representar valores inteiros positivos e negativos. As
operaes disponveis para o tipo inteiro so representadas pelos operadores +
Linguagem e Tcnica de Programao I

Ivan Mathias Filho Pgina 3 16/05/00

(soma), - (subtrao), * (multiplicao), div (quociente da diviso inteira), e mod
(resto da diviso inteira).

2.2.2.2 Real

O tipo real usado para representar valores decimais com representao finita. As
operaes disponveis para o tipo real so representadas pelos operadores + (soma), -
(subtrao), * (multiplicao), / (diviso).

2.2.2.3 Lgico

O tipo lgico usado para representar os valores lgicos verdadeiro e falso. As
operaes disponveis para o tipo lgico so representadas pelos operadores (e),
(ou), e ~ (no).

2.2.2.4 Caracter

O tipo caracter usado para representar qualquer cadeia de caracteres tais como
nomes, endereos e etc.
A LPE no oferece nenhuma operao sobre os valores do tipo caracter.

2.2.3 Constantes Literais

Uma constante literal uma constante cujo nome a representao escrita do seu
valor. Por exemplo, 21 a representao decimal de um objeto de dados cujo valor
21.

Exemplo:

12.450 -0.5 1.0 /* tipo real */
verdadeiro falso /* tipo lgico */
1 -12 234 /* tipo inteiro */
'PUC-Rio' 'A' '123' ' ' /* tipo caracter */

2.2.4 Comandos e Expresses

2.2.4.1 Expresses

Uma expresso uma frmula ou regra de computao que sempre determina um
valor ou resultado. Uma expresso consiste de operandos e operadores. Os operadores
da LPE j foram apresentados nos itens relativos aos tipos de dados. Os operandos so
constantes e variveis. Se vrios operadores ocorrem em uma expresso, a ordem de
execuo das operaes precisa ser especificada; quer seja pelo emprego explcito de
parnteses, quer seja pelas regras implcitas da linguagem (veja a tabela abaixo).
Linguagem e Tcnica de Programao I

Ivan Mathias Filho Pgina 4 16/05/00


Exemplo:

3 /* uma constante uma expresso */
abc /* uma varivel uma expresso */
n mod 2
salrio * 1.25
(renda_bruta - desconto) * 0.15

Neste ponto iremos apresentar os operadores relacionais. Os operadores
relacionais so amplamente usados na matemtica e dispensam apresentaes. Estes
operadores so usados para relacionar duas expresses; criando uma nova expresso.
O valor desta nova expresso sempre uma valor lgico; isto , verdadeiro ou falso.
Os operadores relacionais so os seguintes:

= (igual)
(diferente)
> (maior)
< (menor)
>= (maior ou igual)
<= (menor ou igual)

As regras implcitas de precedncia dos operadores da LPE so mostradas na tabela
abaixo (do maior para o menor):

1. Parnteses
2. Operadores Aritmticos
2.1. +, - (unrios)
2.2. *, /, div, mod
2.3. +, - (binrios)
3. Operadores Relacionais
4. ~ (no)
5. (e)
6. (ou)

2.2.4.2 Comando de Atribuio

O comando de atribuio tem a seguinte sintaxe:

<varivel> <expresso>;

onde o termo <varivel> dever ser substitudo por uma varivel declarada na seo
variveis, e o termo <expresso> deve ser substitudo por uma expresso vlida na
linguagem LPE. Esta expresso tem que ser de um tipo que seja compatvel com o tipo
da varivel esquerda do operador de atribuio ().
O comando de atribuio ir avaliar a expresso direita do operador de atribuio,
e substituir o valor da varivel esquerda do operador pelo valor da expresso.
Linguagem e Tcnica de Programao I

Ivan Mathias Filho Pgina 5 16/05/00


Exemplo:

idade 3; /* uma constante uma expresso */
x n mod 2;
salrio salrio * 1.25;
imposto (renda_bruta - desconto) * 0.15;
endereo 'Rua JK, 23';

2.2.4.3 Comando de Leitura

O comando de leitura tem a seguinte sintaxe:

leia(<var1>,<var2>,,<varN>);

onde os termos <varK> devem ser substitudos por variveis declaradas na seo
variveis, exceto por variveis do tipo lgico.
O comando de leitura tem por objetivo transferir dados de um perifrico, por
exemplo o teclado, e armazen-los nas variveis fornecidas no comando.

Exemplo:

leia(matrcula,nome,idade,sexo);

2.2.4.4 Comando de Escritura

O comando de escritura tem a seguinte sintaxe:

escreva(<exp1>,<exp2>,,<expN>);

onde os termos <expK> devem ser substitudos por expresses vlidas na
linguagem LPE, exceto por expresses que tm valor do tipo lgico.
O comando de escritura tem por objetivo transferir dados da memria principal para
um perifrico; por exemplo um monitor de vdeo.

Exemplo:

escreva('O Nome do Aluno e ',nome);
escreva('Salrio - ',salrio,' Imposto - ',salrio*0.1);

2.2.5 Estrutura de Controle

2.2.5.1 Bloco

Linguagem e Tcnica de Programao I

Ivan Mathias Filho Pgina 6 16/05/00

Um bloco consiste de um conjunto de comandos delimitados pelas palavras incio e
fim. Um bloco pode ser interpretado como sendo um comando composto por vrios
outros comandos, e cuja a execuo tem efeito igual ao obtido pela execuo dos
vrios comandos nele inseridos.
Na sintaxe da LPE, todas as vezes que aparecer o smbolo <comando>, indicando a
obrigatoriedade de se codificar um comando; este poder se substitudo por um bloco.

Exemplo:

variveis
i, j, k : inteiro;
abc: real;
incio
i 0;
j 0;
incio
k (i + j) * 3;
abc k * 8.5;
escreva(abc);
fim;
escreva(i,j,k);
fim.

2.2.5.2 Seleo

O comando de seleo tem duas formas:

se <expresso lgica> ento
<comando>;

nesta forma a <expresso lgica> avaliada inicialmente. Se o valor da expresso
for verdadeiro, o <comando> executado. Se o valor da expresso for falso, o
<comando> no executado.

Exemplo

variveis
mdia, nota1, nota2, nota3 : real;
incio
escreva('Informe as notas do aluno');
leia(nota1, nota2, nota3);
mdia (nota1+nota2+nota3)/3;
se mdia >= 5.0 ento
escreva('Aluno Aprovado');
escreva(mdia);
fim.

Linguagem e Tcnica de Programao I

Ivan Mathias Filho Pgina 7 16/05/00




se <expresso lgica> ento
<comando1>;
seno
<comando2>;

nesta forma a <expresso lgica> avaliada inicialmente. Se o valor da expresso
for verdadeiro, o <comando1> executado e o <comando2> no. Se o valor da
expresso for falso, o <comando2> executado e o <comando1> no.

Exemplo

variveis
mdia, nota1, nota2, nota3 : real;
incio
escreva('Informe as notas do aluno');
leia(nota1, nota2, nota3);
mdia (nota1+nota2+nota3)/3;
se mdia >= 5.0 ento
escreva('Aluno Aprovado');
Incio
escreva('Informe as notas do aluno');
leia(nota1,nota2,nota3);
media <- (nota1+nota2+nota3)/3;
media>=5.0? escreva('Aluno aprovado);
escreva(media);
sim
no
Fim

Linguagem e Tcnica de Programao I

Ivan Mathias Filho Pgina 8 16/05/00

seno
escreva('Aluno Reprovado');
escreva(mdia);
fim.



2.2.5.3 Repetio

O comando de repetio tem a seguinte sintaxe:

enquanto <expresso lgica> faa
<comando>;

neste comando a <expresso lgica> avaliada inicialmente. Se o valor da
expresso for verdadeiro, o <comando> executado e a <expresso lgica>
avaliada novamente. Este ciclo repetido at que a <expresso lgica> seja avaliada
como falso. importante notar que se a <expresso lgica> for avaliada inicialmente
como falso o <comando> no ser executado nenhuma vez. Outra observao
importante que o <comando> dever alterar de alguma forma as variveis presentes
na <expresso lgica>. Se isto no ocorrer, a <expresso lgica> ser sempre avaliada
como verdadeiro (supondo que a <expresso lgica> seja avaliada como verdadeiro
na primeira avaliao) e o <comando> ser executado continuamente. Diremos ento
que o "programa entrou em um looping infinito".
Incio
escreva('Informe as notas do aluno');
leia(nota1,nota2,nota3);
media <- (nota1+nota2+nota3)/3;
media>=5.0? escreva('Aluno aprovado);
escreva(media);
sim
Fim
escreva('Aluno reprovado); no

Linguagem e Tcnica de Programao I

Ivan Mathias Filho Pgina 9 16/05/00


Exemplo

O exemplo a seguir exibir no monitor de vdeo todos os nmeros inteiros entre 0 e
99.

variveis
cont : inteiro;
incio
cont 0;
enquanto cont < 100 faa
incio
escreva(cont);
cont cont + 1;
fim;
fim.



Incio
cont<-0;
cont<100? sim
Fim
no
escreva(cont);
cont<-cont+1;;

Linguagem e Tcnica de Programao I

Ivan Mathias Filho Pgina 10 16/05/00

3. A Linguagem C

3.1 Tipos de Dados

Os tipos das variveis e das constantes de um programa escrito na lingugem C so
baseados em um dos cinco tipos bsicos de dados existentes:

char uma varivel ou uma constante do tipo char pode armazenar um nico
caracter ASCII, ou um nmero inteiro entre 128 e 127.
int - uma varivel ou uma constante do tipo int pode armazenar um nmero inteiro
entre 32768 e 32767.
float - uma varivel ou uma constante do tipo float pode armazenar um nmero
decimal com seis a sete dgitos de preciso, na faixa de 3.4E-38 a 3.4E+38.
double - uma varivel ou uma constante do tipo double pode armazenar um
nmero decimal com quatorze a quinze dgitos de preciso, na faixa de 1.7E-308
a 1.7E+308.
void o tipo void ser descrito posteriormente.

3.2 Nomes de Identificadores

O padro ANSI C define os nomes de variveis, funes, constantes e vrios outros
objetos definidos pelo programador como identificadores. Tais identificadores so
compostos por um ou mais caracteres. O primeiro caracter deve ser um caracter
alfabtico ou o caracter sublinhado ( _ ), e os demais caracteres podem ser quaisquer
caracteres alfanumricos ou o caracter sublinhado ( _ ).

Exemplo

salario (correto)
aluno01 (correto)
1ano (incorreto)
_x (correto)
nota!01 (incorreto)
nota 01 (incorreto)

O padro ANSI determina que os identificadores podem ter qualquer tamanho, mas
pelo menos os primeiros seis caracteres devem ser significativos. Porm, o nmero
mximo de caracteres significativos pode variar de compilador para compilador. Por
exemplo, se o seu compilador reconhece apenas os primeiros 31 caracteres de um
identificador como significativos, identificadores diferentes mas com os 31 caracteres
iniciais iguais sero tratados como sendo o mesmo identificador.
Uma outra caracterstica da linguagem C que as letras maisculas e minsculas
so tratadas como sendo distintas. Logo, os identificadores nome, Nome e NOME,
so trs identificadores distintos.

Linguagem e Tcnica de Programao I

Ivan Mathias Filho Pgina 11 16/05/00

3.3 Variveis

As variveis so declaradas em trs lugares bsicos em um programa C: dentro das
funes, na definio dos parmetros das funes, e fora de todas as funes. Estas
so variveis locais, parmetros formais e variveis globais, respectivamente.
Todas as variveis usadas em um programa C devem ser declaradas antes de serem
usadas. A forma geral de uma declarao de variveis :

<tipo> <var1>,<var2>,<var3>,...,<varN>;

Exemplo

int i,j,k;
float salario;
char letra,ch;

Uma varivel pode ser inicializada no momento da sua declarao. A forma geral de
uma inicializao :

<tipo> <var1>=<constante>;

Exemplo

int i=0,j,k=6;
float salario=600.25;
char letra='G',ch='@';

As variveis globais so inicializadas apenas no comeo do programa, enquanto as
variveis locais so inicializadas todas as vezes que a funo na qual elas foram
declaradas for ativada.

3.4 Constantes

A linguagem C permite o uso tanto de constantes literais como de constantes
simblicas. A maneira como cada constante representada depende do seu tipo. As
constantes do tipo char so envolvidas por aspas simples. Por exemplo, 'a' e '%' so
constantes do tipo char.
As constantes dos tipos numricos (int, float ou double) so representadas por uma
seqncia de dgitos decimais, sinalizada ou no, podendo ter ou no um ponto
decimal (se o tipo for float ou double). Por exemplo, +123, 15, -16.25 e 8.0 so
constantes numricas.
Uma constante simblica em C representada antravs do uso do modificador de
tipo de acesso const. Isto feito precedendo-se a declarao de uma varivel com a
palavra reservada const.
Linguagem e Tcnica de Programao I

Ivan Mathias Filho Pgina 12 16/05/00


Exemplo

const int i=0,k=6;
const float salario=600.25;

Envolver todas as constantes do tipo char com aspas simples funciona para a
maioria dos caracteres que podem ser impressos. Uns poucos, porm, so impossveis
de entrar pelo teclado. Por essa razo, a linguagem C possui constantes especiais de
caracter de barra invertida. Alguns desses caracteres so listados abaixo.

Cdigo Significado

\n Nova linha (LF)
\r Retorno do carro (CR)
\" Caracter "
\' Caracter '
\0 Caracter nulo (zero binrio)
\\ Caracter barra invertida

3.5 Expresses

As expresses combinam operandos e operadores pra produzir um nico resultado.
Os operandos podem ser constantes, variveis ou valores retornados pelas funes.
Assim como as variveis e as constantes, o resultado de uma expresso possui um
tipo, que o mesmo dos operandos envolvidos na expresso. Quando constantes e
variveis de tipos diferentes so misturadas em uma mesma expresso, devemos levar
em conta tambm a converso de tipos. Essa converso segue algumas regras bsicas:

a) char e short so sempre convertidos para int;
b) float sempre convertido para double;
c) A converso de tipos segue a seguinte precedncia:
double ou float
long
unsigned
int, char ou short

Isto , se, por exemplo, um dos operandos for do tipo float, toda a expresso ser
convertida e o resultado ser do tipo double.
As expresses so avaliadas de acordo com o que se denomina precedncia dos
operadores. A introduo de operadores com precedncias distintas altera a ordem de
avaliao da expresso, sendo que os de maior precedncia so avaliados antes do que
os de menor precedncia.
Linguagem e Tcnica de Programao I

Ivan Mathias Filho Pgina 13 16/05/00


3.6 Operadores

3.6.1 Operador de Atribuio

O primeiro operador a se visto o operador de atribuio ( = ). A forma geral de
uma operao de atribuio :

<var>=<expresso>;

Nesta operao, a expresso direita do operador de atribuio avaliada, e o
resultado da avaliao passa a ser o novo valor da varivel esquerda do operador.

Exemplo

soma=a+b;
fator=3.0;
circunf=2*pi*raio;

A linguagem C permite que mltiplas atribuies sejam feitas em uma nica linha de
cdigo.

Exemplo

a=b=c=3.0;

Aps a execuo do cdigo acima, a trs variveis tero o mesmo valor (3.0).

Quando em uma operao de atribuio a expresso direita do operador de um
tipo diferente do tipo da varivel esqueda do operador, ocorre uma converso de
tipos. Isto , o valor da expresso convertido para o tipo da varivel esquerda do
operador.
O processo de converso de tipos pode resultar em perda de informao, como
pode ser visto na tabela abaixo.

Tipo Destino Tipo Expresso Possvel Informao Perdida

signed char char Se valor > 127, o destino negativo
char short int Os 8 bits mais significativos
char int Os 8 bits mais significativos
char long int Os 24 bits mais significativos
int long int Os 16 bits mais significativos
int float A parte fracionria e possivelmente mais
float double Preciso, o resultado arredondado
double long double Preciso, o resultado arredondado
Linguagem e Tcnica de Programao I

Ivan Mathias Filho Pgina 14 16/05/00


3.6.2 Operadores Aritmticos

A linguagem C suporta os operadores aritmticos usuais:

* (multiplicao)
/ (diviso)
% (resto da diviso inteira)
+ (adio)
- (subtrao)

O operador % no pode ser aplicado a operandos do tipo float e do tipo double.
A precedncia dos operadores aritmticos a usual.

Em C, qualquer atribuio entre parnteses e considerada uma expresso que tem o
valor da atribuio que est sendo feita.

Exemplo

a=3+2*(b=x/2);
Esta construo equivalente a:
b=x/2;
a=3+2*b;

3.6.3 Relacionais e Lgicos

A linguagem C suporta os seguintes operadores relacionais:

> (maior)
>= (maior ou igual)
< (menor)
<= (menor ou igual)
== (igual)
!= (diferente)

E os seguintes operadores lgicos:

&& (e)
|| (ou)
! (no)

A tabela abaixo mostra a precedncia dos operadores lgicos e relacionais (do
maior para o menor):
Linguagem e Tcnica de Programao I

Ivan Mathias Filho Pgina 15 16/05/00


Maior !
> >= < <=
== !=
&&
Menor ||

Uma caracterstica bastante peculiar da linguagem C o seu conceito de
verdadeiro e falso. A linguagem C no possui um tipo de dados lgico (ou booleano).
Em C, qualquer expresso cujo valor seja diferente de zero avaliada como
verdadeira. Em contrapartida, qualquer expresso cujo valor seja igual a zero
avaliada como falsa.
As expresses que usam operadores lgicos e relacionais devolvem zero quando o
resultado falso, e um quando o resultado verdadeiro.

3.7 Comandos de Controle

3.7.1 Bloco de Comandos

Um bloco de comandos simplesmente um grupo de comandos relacionados que
so tratados como uma unidade. Os comandos que constituem um bloco esto
logicamente conectados. Um bloco comea com um { e termina com um }
correspondente. Os programadores normalmente usam blocos de comandos para criar
estruturas multicomandos associadas com um outro comando como, por exemplo, um
if. No entanto, podemos inserir um bloco de comandos em qualquer ponto do
programa onde seja possvel colocar um outro comando qualquer.

Exemplo

#include <stdio.h>
void main(void)
{
int i;
{ /* bloco de comandos */
i=120;
printf("%d",i);
}
}

3.7.2 Comando if

Um desvio condicional usado quando se deseja escolher um dentre dois comandos
ou bloco de comandos a ser executado, dependendo de uma condio.
A linguagem C possui duas formas para o desvio condicional:
Linguagem e Tcnica de Programao I

Ivan Mathias Filho Pgina 16 16/05/00


if(<expresso>)
<comando>;

A expresso avaliada. Se o seu valor for verdadeiro, comando executado. O
processamento continua no primeiro comando aps o if.

Exemplo

#include <stdio.h>
void main(void)
{
int i;
printf("Entre com o valor de a");
scanf("%d",&a);
if(a>0)
printf("a e maior que zero\n");
}

if(<expresso>)
<comando1>;
else
<comando2>;

A expresso avaliada. Se o seu valor for verdadeiro, comando1 executado; seno,
comando2 executado. O processamento continua no primeiro comando aps o if.

Exemplo

#include <stdio.h>
void main(void)
{
int i;
printf("Entre com o valor de a");
scanf("%d",&a);
if(a>0)
printf("a e maior que zero\n");
else
printf("a e menor ou igual a zero\n");
}

Nas duas formas acima, comando pode ser tanto um comando simples quanto um
bloco de comandos.

3.7.3 Comando while

O comando while usado quando se deseja repetir um comando ou bloco de
comandos equanto uma dada condio permanecer verdadeira. A forma do comando
while :
Linguagem e Tcnica de Programao I

Ivan Mathias Filho Pgina 17 16/05/00


while(<expresso>)
<comando>;

A execuo do while segue os seguintes passos:

a) a <expresso> avaliada;
b) se a expresso for verdadeira o comando executado e o fluxo de execuo
retorna para o passo a). Caso no seja, o fluxo da execuo prosseguir do
comando seguinte ao while.

Exemplo

#include <stdio.h>
void main(void)
{
int i=0;
while(i<10)
{
printf("%d\n",i);
i=i+1;
}
}

Na sintaxe descrita acima, comando pode ser tanto um comando simples quanto
um bloco de comandos.

3.8 Funes de E/S pelo Console

As funes printf() e scanf() realizam entrada e sada formatada; isto , elas podem
ler e escrever dados em vrios formatos. A funo printf() escreve dados no vdeo,
equanto a funo scanf() l dados do teclado. As duas funes podem operar sobre
quaisquer dos tipos de dados primitivos fornecidos pela linguagem C, incluindo
carcteres, nmeros inteiros e nmeros decimais (ponto flutuante).
Como os cabealhos das funes printf() e scanf() esto no arquivo STDIO.H,
necessrio incluir a diretiva de compilao #include <stdio.h> no incio de todos os
programas C que utilizam estas duas funes.

3.8.1 Funo de Sada printf()

O prottipo da funo printf()

int printf(<string_de_controle>,<lista_de_argumentos>);

O string_de_controle consiste de trs tipos de dados. O primeiro tipo formado
por caracteres que sero exibidos no monitor. O segundo contm comandos de
formato, que definem a maneira pela qual os argumentos subseqentes sero
mostrados. O terceiro composto por caracteres como o \n (caracter de mudana de
Linguagem e Tcnica de Programao I

Ivan Mathias Filho Pgina 18 16/05/00

linha), que no podem ser digitados diretamente pelo teclado, e que so escritos em C
utilizando a combinao do carater \ (barra invertida) com outros caracteres.
Um comando de formato comea com o caracter % (percentagem) seguido pelo
cdigo do formato. Deve haver o mesmo nmero de argumentos, na
lista_de_argumentos, que o nmero de comandos de formato. A associao entre um
comando de formato e o argumento correspondente feita pela ordem que ambos
ocupam, da esquerda para a direita.
Por exemplo, o comando

printf(A nota do aluno %d e %5.2f ,1234,8.5);

exibir no vdeo

A nota do aluno 1234 e 8.50

Abaixo so mostrados alguns comandos de formato da funo printf().

Cdigo Formato
%c Caracter
%d Inteiro com sinal
%i Inteiro com sinal
%e Notao cientfica (e minsculo)
%E Notao cientfica (E maisculo)
%f Ponto flutuante
%s String de caracteres
%u Inteiro sem sinal
%% Escreve o caracter %

Um nmero inteiro colocado entre o sinal de percentagem e o comando de formato
atua como um especificador de largura mnima do campo. Por exemplo, %5d e %05d.
Para especificar o nmero de casas decimais a ser escrito em um nmero em ponto
flutuante, coloque um ponto decimal seguido do nmero de casas decimais desejado
aps o especificador de largura mnima do campo. Por exemplo %8.4f.

3.8.2 Funes de Entrada scanf()

O prottipo da funo scanf()

int scanf(<string_de_controle>,<lista_de_argumentos>);

O string_de_controle usa a maioria dos cdigos de formatao utilizados em
printf(). Logo, usa-se %d para ler um nmero inteiro, %f para ler um nmero em
ponto flutuante, %c para ler um caracter, e etc. Os espaos em branco no
string_de_controle so ignorados.
A lista_de_argumentos composta por uma lista de variveis; cada uma das quais
precedida pelo caracter &. Deve haver o mesmo nmero de variveis, na
lista_de_argumentos, que o nmero de comandos de formato. A associao entre um
Linguagem e Tcnica de Programao I

Ivan Mathias Filho Pgina 19 16/05/00

comando de formato e a varivel correspondente feita pela ordem que ambos
ocupam, da esquerda para a direita.
Por exemplo, o comando

scanf(%d %f,&matricula,&nota);

faz com que o programa pare a execuo e espere que sejam digitados um nmero
inteiro e um nmero decimal. Os nmeros podem ser separados por um ou mais
espaos em branco, Tab, ou Enter. O primeiro nmero lido ser atribuido varivel
matricula, e o segundo varivel nota.
A funo scanf() interrompe a sua execuo quando todos os dados forem lidos, ou
quando um dado no for compatvel com o comando de formato correspondente.

3.9 Funes de E/S de Caracteres

Ao escrevermos um programa aplicativo qualquer, freqentemente nos deparamos
com a necessidade de ler do teclado (ou exibir no vdeo) dados que so compostos
exclusivamente por caracteres. Por exemplo:

opes de menu;
respostas (s (sim) ou n (no));
cadeias de caracteres.

Para tal, a linguagem C nos fornece um conjunto de funes que sero vistas a
seguir.

3.9.1 A Funo getchar()

O prottipo da funo getchar()

#include <stdio.h>
int getchar(void);

A funo getchar() l um caracter do teclado. Se for executada com sucesso ela
retornar o caracter lido (cdigo ASCII). Se ocorrer falha ou for detectado o fim-de-
arquivo, ela retornar EOF.
Outro aspecto importante que ela suporta o redirecionamento de STDIN.

Exemplo

#include <stdio.h>
#include <ctype.h>
void main(void)
{ char letra;
printf("Digite S ou N para continuar e tecle ENTER\n");
do{
Linguagem e Tcnica de Programao I

Ivan Mathias Filho Pgina 20 16/05/00

letra=getchar();
letra=toupper(letra);
}while ((letra!='S')&&(letra!='N'));
}

3.9.2 A Funo putchar()

O prottipo da funo putchar()

#include <stdio.h>
int putchar(int letra);

A funo putchar() exibe um caracter no monitor. Se for executada com sucesso
ela retornar o caracter exibido (cdigo ASCII). Se ocorrer falha ela retornar EOF.
Outro aspecto importante que ela suporta o redirecionamento de STDOUT.

Exemplo

#include <stdio.h>
void main(void)
{ char letra;
letra='a';
while(letra<='z')
{
putchar(letra);
letra++;
}
}

3.9.3 Entrada Bufferizada

A funo getchar() armazena os caracteres lidos do teclado em um buffer at que
se tecle Enter. Nesse momento os caracteres digitados ficam disponveis para o
programa. Pode-se usar a tecla de Backspace para alterar uma entrada incorreta.
O "sistema" acrescenta o caracter de new line (\n) cadeia de caracteres quando for
detectado que um Enter foi teclado.

Exemplo

#include <stdio.h>
void main(void)
{ char letra;
letra='a';
do{
letra=getchar();
putchar(letra);
}while (letra!='\n');
}

Linguagem e Tcnica de Programao I

Ivan Mathias Filho Pgina 21 16/05/00

3.9.4 Entrada Direta pelo Teclado

As funes getche() e getch() fazem entrada direta pelo teclado. Nesta modalidade
os caracteres so disponibilizados para o programa assim que eles forem digitados, no
sendo obrigatrio teclar Enter. Desta forma, no se pode usar a tecla de Backspace
para alterar uma entrada incorreta, sendo necessrio implementar a correo atravs de
programao.
O "sistema" acrescenta o caracter de retorno de carro (\r) cadeia de caracteres
quando for detectado que um Enter foi teclado.

3.9.5 A Funo getche()

O prottipo da funo getche()

#include <conio.h>
int getche(void);

A funo getche() l um caracter do teclado. Se for executada com sucesso ela
retornar o caracter lido (cdigo ASCII). Se ocorrer falha ela retornar EOF.
Outro aspecto importante que ela no suporta o redirecionamento de STDIN.

Exemplo

#include <stdio.h>
#include <conio.h>
#include <ctype.h>
void main(void)
{ char letra;
printf("Voce quer Continuar? S ou N?\n");
do{
letra=toupper(getche());
}while ((letra!='S')&&(letra!='N'));
if (letra=='S')
printf("\nSua resposta foi SIM\n");
else
printf("\nSua resposta foi NAO\n");
}

3.9.6 A Funo getch()

O prottipo da funo getch()

#include <conio.h>
int getch(void);

A funo getch() semelhante funo getche(), porm, os caracteres lidos do
teclado no so exibidos automaticamente no vdeo. Uma boa utilizao para getch()
na digitao de senhas.
Linguagem e Tcnica de Programao I

Ivan Mathias Filho Pgina 22 16/05/00


Exemplo

#include <stdio.h>
#include <ctype.h>
#include <conio.h>
void main(void)
{ char letra;
printf("Digite uma cadeia de caracteres e tecle
ENTER\n");
do{
letra=toupper(getche());
}while ((letra!='\r');
}

3.9.7 Sada Direta

O prottipo da funo putch()

#include <conio.h>
int putch(int letra);

A funo putch() exibe um caracter no monitor. Se for executada com sucesso ela
retornar o caracter exibido (cdigo ASCII). Se ocorrer falha ela retornar EOF.
A funo putch() se comunica diretamente com o BIOS (ou diretamente com a
memria de vdeo) do PC. Por outro lado, putchar() se comunica com o sistema de
arquivos do sistema operacional, deixando para este a comunicao com o BIOS (ou
com a memria de vdeo).
A funo putch() no converte um caracter de new line (\n) em uma seqncia de
retorno de carro e alimentao de linha.

3.9.8 Funes Adicionais de Caracteres

Abaixo esto relacionadas algumas funes teis na manipulao de caracteres. Os
cabealhos destas funes esto definidos no arquivo CTYPE.H.

Cabealho Descrio

int isalnum(int ch); Devolve um valor diferente de zero se o
argumento for uma letra ou um dgito; caso
contrrio devolve zero.
int isalpha(int ch); Devolve um valor diferente de zero se o
argumento for uma letra; caso contrrio
devolve zero.
int isdigit(int ch); Devolve um valor diferente de zero se o
argumento for um dgito; caso contrrio
devolve zero.
int islower(int ch); Devolve um valor diferente de zero se o
Linguagem e Tcnica de Programao I

Ivan Mathias Filho Pgina 23 16/05/00

argumento for uma letra minscula; caso
contrrio devolve zero.
int isupper(int ch); Devolve um valor diferente de zero se o
argumento for uma letra maiscula; caso
contrrio devolve zero.
int tolower(int ch); Devolve o equivalente minsculo se o
argumento for uma letra; caso contrrio o
argumento devolvido sem alterao.
int toupper(int ch); Devolve o equivalente maisculo se o
argumento for uma letra; caso contrrio o
argumento devolvido sem alterao.

3.10 O Comando switch

A linguagem C possui um comando de seleo mltipla, switch, que testa
sucessivamente o valor de uma expresso contra uma lista de constantes inteiras ou de
caracter. Quando o valor coincide, os comandos associados quela constante so
executados. A forma geral do switch

switch(<expresso>)
{
case <constante1>:
<seqncia de comandos>
break;
case <constante2>:
<seqncia de comandos>
break;
.
.
.
default:
<seqncia de comandos>
}

A execuo deste comando segue os seguintes passos:

1. A <expresso> avaliada;
2. se o valor da expresso for igual a uma das constantes, a seqncia de comandos
associada a esta constante ser executada. Os comandos seguintes continuaro a
ser executados at o fim do switch, ou at que um comando break seja
encontrado;
3. se o valor da expresso no for igual a nenhuma das constantes presentes no
comando, e a opo default tiver sido includa no comando switch, os comandos
associados ao default sero executados. Caso a opo default no esteja presente,
o processamento prosseguir a partir do comando seguinte ao switch.

Exemplo
Linguagem e Tcnica de Programao I

Ivan Mathias Filho Pgina 24 16/05/00


#include<stdio.h>
void main(void)
{
char ch;
int i=0;

while((i<=10) && (ch=getch())!='#')
{
switch(ch)
{
case 'A':
case 'O':
i++;
putchar('E');
break;
case ' ':
putchar('!');
case 'L':
i+=2;;
putchar('$');
break;
default:
i++;
putchar('?');
}
}
printf("\nAcabou");
}

Observaes:

a) Pode haver um ou mais comandos seguindo o case. Estes comandos no precisam
estar escritos entre chaves;
b) a expresso em switch(<expresso>) deve ter um valor compatvel com um inteiro;
isto , podem ser usadas expresses dos tipos char e int com todas as suas
variaes. O uso de expresses do tipo float ou double ir causar erro na
compilao;
c) o comando break provoca a sada imediata do switch. Se no existir um break
seguindo os comandos associados a um case, o programa prosseguir executando
todos os comandos associados ao case abaixo. Esta caracterstica pode ser
interessante em algumas circunstncias.

3.11 O Comando for

O formato geral do comando for da linguagem C encontrado, de uma forma ou de
outra, em todas as linguagens de programao baseadas em procedimentos. Contudo,
em C, ele fornece maior flexibilidade. A forma geral do comando for

Linguagem e Tcnica de Programao I

Ivan Mathias Filho Pgina 25 16/05/00

for(<expresso1>;<expresso2>;<expresso3>)
<comando>;

O comando for permite muitas variaes. Entretanto, a <expresso1> ,
geralmente, um comando de atribuio que usado para colocar um valor na varivel
de controle do lao. A <expresso2> uma expresso relacional que determina
quando o lao acaba. A <expresso3> o incremento que define como a varivel de
controle do lao varia a cada vez que o lao repetido. As trs sees principais do
comando for devem ser separadas por pontos-e-vrgulas. Uma vez que a <expresso2>
seja avaliada como falso, a execuo do programa continua no comando seguinte ao
for.

Exemplo

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

for(i=1;i<=10;i++)
printf("%d \n",i)
}

4. Funes

Freqentemente, uma certa seqncia de comandos deve ser repetida em vrios
lugares de um programa. A fim de economizar o tempo gasto com o trabalho de copiar
estas seqncias, vrias linguagens de programao, entre elas a linguagem C, incluem
o conceito de subprograma (ou subrotina): atribui-se um nome uma seqncia de
comandos, e faz-se referncia a este nome nos vrios lugares do programa onde a
seqncia em questo deveria ser repetida.
O uso das funes tem por objetivo tambm dividir grandes tarefas de computao
em tarefas menores, facilitando assim o gerenciamento de grandes sistemas e
aumentando a confiabilidade dos mesmos. Funes apropriadas podem freqentemente
esconder detalhes de operao de partes de um programa que no necessitam ser
conhecidas por outras partes do mesmo programa. Isto facilita a evoluo dos sistemas
atravs do tempo j que as mudanas nos requisitos dos sistemas no so
necessariamente propagadas por todas as sees de cdigo dos programas. Alm
disso, o uso de funes aumenta a confiabilidade dos sistemas na medida em que mais
e mais programadores usem o mesmo cdigo em seus programas, aumentando assim a
probabilidade de descobrir eventuais erros, e facilitando a correo dos mesmos nos
diverso programas que fazem uso do cdigo em questo.

4.1 Estrutura das Funes em C

Linguagem e Tcnica de Programao I

Ivan Mathias Filho Pgina 26 16/05/00

A estrutura de uma funo na linguagem C bastante semelhante da funo
main(). A nica diferena que main() a primeira funo a ser chamada quando o
programa executado.
Todas as funes em C comeam com um nome seguido de parnteses (que envolve
ou no uma lista de argumentos) e, aps isto, chaves que envolvem o corpo da funo.

4.2 Chamando Funes

As funes por ns desenvolvidas so chamadas do mesmo modo que as funes da
biblioteca C (printf(), getchar(), scanf() e etc): minhaFuncao(). Os parnteses que
seguem o nome so necessrios para que o compilador possa diferenciar a chamada de
uma funo de uma varivel que no foi declarada.
Visto que a chamada de uma funo constitui um comando de programa, esta deve
ser encerrada por ponto-e-vrgula.

minhaFuncao();

Porm, na definio de uma funo o ponto-e-vrgula no pode ser usado.

minhaFuncao()

Exemplo

#include <stdio.h>

int fatorial(int num)
{
int fat=1;

for(;num>1;num--)
fat*=num;
return fat;
}

void main(void)
{
int num;

printf("Informe um Numero >= 0\n");
scanf("%d",&num);
if(num<0)
printf("O Numero num nao e um numero natural\n");
else
printf("O fatorial de %d e %d\n",num,fatorial(num));
}

interessante notar no exemplo acima que a funo fatorial() foi definida antes da
funo main(), de onde ela chamada. Isto se deve ao fato de o compilador ter que
conhecer o nome, o nmero e os tipo dos parmetros, e o tipo do valor a ser retornado
Linguagem e Tcnica de Programao I

Ivan Mathias Filho Pgina 27 16/05/00

pela funo no momento em que for encontrada uma chamada funo. Se a funo
no tiver sido declarada, o compilador acusar um erro.
Podemos alternativamente declarar apenas o cabealho da funo (nome, nmero e
tipo dos parmetros, e o tipo do valor a ser retornado pela funo) antes de referenci-
la, postergando assim a sua definio. Quando da definio da funo, o cabealho
anteriormente declarado no pode ser modificado.

Exemplo

#include <stdio.h>

int fatorial(int);

void main(void)
{
/* Os mesmos comandos do exemplo anterior */
}

int fatorial(int num)
{
int fat=1;

for(;num>1;num--)
fat*=num;
return fat;
}

4.3 Variveis Locais

As variveis declaradas dentro de uma funo so chamadas variveis locais, e so
conhecidas somente dentro da funo onde so declaradas. Por exemplo, a varivel fat
do exemplo acima conhecida somente dentro do escopo da funo fatorial(), sendo
invisvel s demais funes, incluindo main(). Se inclussemos em main() a instruo

printf(%d,fat);

teramos um erro de compilao, pois main() no conhece a varivel fat.
Uma varivel local conhecida em C como varivel automtica, pois ela
automaticamente criada quando a funo ativada e destruda na sada da funo.

4.4 Variveis Globais

Uma varivel dita global quando for declarada fora do escopo de qualquer funo.
Com isto, ela torna-se acessvel a todas as funes, desde o ponto da declarao da
varivel at o fim do programa.
Como as variveis globais so acessveis por todas as funes do programa fonte,
elas se constituem em uma alternativa para a troca de informaes entre funes. No
Linguagem e Tcnica de Programao I

Ivan Mathias Filho Pgina 28 16/05/00

exemplo a seguir, ao invs de passarmos um nmero como parmetro para a funo
fatorial() iremos declarar a varivel num como global. Iremos declarar tambm a
varivel fat como global; dessa forma a funo no retornar nenhum valor
explicitamente.

Exemplo

#include <stdio.h>

int num,fat;

void fatorial(void)
{
fat=1;

for(;num>1;num--)
fat*=num;
}

void main(void)
{
printf("Informe um Numero >= 0\n");
scanf("%d",&num);

if(num<0)
printf("O Numero num nao e um numero natural\n");
else
{
fatorial();
printf("O fatorial de %d e %d\n",num,fat);
}
}

As variveis globais devem ser usadas com muita cautela pois, por serem acessveis
a todas as funes, aumentam a interdependncia entre as mesmas (acoplamento),
dificultando o reuso das funes e propagando eventuais modificaes em uma funo
por todo o cdigo, o que algo indesejvel. Desse modo, no ser aceito durante o
curso o uso de variveis globais.

4.5 Passando Dados Para a Funo Chamada

O mecanismo usado para transmitir informaes para uma funo chamado
parmetro. No exemplo que est sendo usado, a funo fatorial(), a definio da
funo a seguinte:

int fatorial(int num)

nela informamos ao compilador que a funo fatorial() requer um parmetro,
chamado num, que do tipo int. A varivel num na verdade uma nova varivel e
Linguagem e Tcnica de Programao I

Ivan Mathias Filho Pgina 29 16/05/00

chamada de parmetro formal, funcionando exatamente como uma varivel local da
funo; isto , criada quando a funo inicia sua execuo e destruda quando a
funo retorna.

4.6 Passando Dados Para a Funo Chamada - Passagem por Valor

Quando uma funo chamada devemos fornecer os argumentos (ou parmetros
reais) para a funo. Os argumentos podem ser variveis, constantes ou quaisquer
expresses, desde que os tipos dos argumentos sejam compatveis com os tipos dos
parmetros. Em C, todos os argumentos de funes so passados por valor. Isto
significa que funo chamada dada uma cpia dos valores dos argumentos. Os
valores dos argumentos so armazenados em reas de memria temporrias, alocadas
quando a funo ativada, e so acessveis atravs das variveis declaradas como
parmetros no cabealho da funo. Desta forma, em C, uma funo no pode alterar
o valor de uma varivel passada como parmetro pela funo chamadora; ela s pode
alterar a cpia.

4.7 O Valor Retornado por uma Funo

J vimos funes da biblioteca C que retornam um valor. Por exemplo:

ch=getchar();

para que uma funo retorne um valor explicitamente necessrio usar o comando
return, cuja sintaxe :

return expresso;

O comando return tem dois usos importantes. Primeiro, voc pode us-lo para
devolver um valor e retornar imediatamente para a instruo seguinte (dentro da
funo chamadora) instruo que causou a chamada da funo em questo. Segundo,
voc pode us-lo, sem a expresso, para causar a sada imediata da funo na qual ele
se encontra; isto , o return far com que a execuo do programa volte para a funo
chamadora assim que for executado, o que ocorre, em geral, antes da ltima instruo
da funo. Pode-se escrever quantos return forem necessrios dentro de uma funo.
Existe um return implcito aps o ltimo comando de uma funo. Logo, mesmo que
no se escreva nenhum comando return em uma funo, o fluxo de execuo do
programa retornar para a funo chamadora aps a execuo do ltimo comando de
uma funo.

4.8 O Tipo do Valor Retornado por uma Funo

O tipo de uma funo determinado pelo tipo de valor que ele retorna e no pelo
tipo dos seus argumentos. Uma funo pode retornar um nico valor de qualquer tipo
Linguagem e Tcnica de Programao I

Ivan Mathias Filho Pgina 30 16/05/00

primitivo da linguagem C, isto : char, int e float. Porm, como devemos declarar
funes que no retornam valor algum?
O comit de padro do American National Standards Institute (ANSI) batizou as
funes que no retornam valores como tendo o tipo void. O tipo void tambm
usado no cabealho das funes que no recebem parmetros. O melhor exemplo de
tais funes a funo main(). A funo main(), que pode receber parmetros e
retornar um valor, tem sido at agora usada nos nossos exemplos como

void main(void);

Isto que dizer que a funo main(), nos nossos exemplos, no recebe nenhum
parmetro e no retorna nenhum valor.

4.9 Passando Dados Para a Funo Chamada - Passagem por Referncia

Apesar de a linguagem C suportar apenas a passagem de parmetros por valor,
podemos simular a passagem de parmetros por referncia passando o endereo de
uma varivel como argumento para uma funo. Na funo chamada, o parmetro
correspondente ao argumento em questo declarado como sendo um ponteiro para
uma rea de memria. Uma referncia ao parmetro, na unidade chamada, tratada
como uma referncia posio de memria cujo endereo passado como argumento.
A varivel usada como argumento ento compartilhada; isto , pode ser modificada
pela funo chamada.
O exemplo abaixo mostra uma funo que troca os valores de duas variveis inteira.

Exemplo

#include <stdio.h>

void troca(int *x, int *y)
{
int aux;

aux=*x;
*x=*y;
*y=aux;
}

void main(void)
{
int a=10,b=20;
troca(&a,&b);
}

No exemplo acima, vamos supor que o compilador tenha alocado as reas de
memria $1000 e $2000 para as variveis a e b respectivamente. Desta maneira, ao
chamarmos a funo troca() com os argumentos (as variveis a e b) sendo precedidos
Linguagem e Tcnica de Programao I

Ivan Mathias Filho Pgina 31 16/05/00

pelo operador & (o operador & retorna o endereo de uma varivel), os endereos
$1000 e $2000 so passados como argumentos.
Os parmetros x e y declarados na funo troca() tambm ocupam reas de
memria; por exemplo, $6000 e $7000 respectivamente. Porm, estes parmetros no
armazenam valores inteiros, como o caso das variveis a e b. Ao invs disso, eles
armazenam endereos de memria. Estas reas de memria, por sua vez, armazenam
valores inteiros. Isto indicado na declarao dos parmetros ao preced-los com o
operador * (o operador * informa que uma varivel um ponteiro; isto , armazena
um endereo de memria). Logo, no exemplo acima, aps a chamada da funo
troca(), os parmetros x e y iro armazenar os endereos $1000 e $2000.
Nas instrues da funo troca(), todas as vezes que os parmetros x e y forem
precedidos pelo operador *, estaremos acessando as reas de memria cujos os
endereos esto armazenados nos parmetros x e y. Neste exemplo, os endereos so
$1000 e $2000, endereos das variveis a e b respectivamente. Desta maneira, ao
alterarmos os contedos das reas de memria apontadas pelos parmetros x e y
($1000 e $2000), estaremos alterando o contedo das variveis a e b, definidas na
funo main(). As figuras abaixo ilustram o que foi dito acima.
Linguagem e Tcnica de Programao I

Ivan Mathias Filho Pgina 32 16/05/00




10
$1000
20
$2000
$1000
$6000
$2000
$7000
Logo Aps a Chamada da Funo
troca()
20
$1000
20
$2000
$1000
$6000
$2000
$7000
Logo Aps a Execuo da Instruo
*x=*y;
20
$1000
10
$2000
$1000
$6000
$2000
$7000
Logo Aps a Execuo da Instruo
*y=aux;
Linguagem e Tcnica de Programao I

Ivan Mathias Filho Pgina 33 16/05/00


5 Vetores

Nem sempre os tipos bsicos (int, char e float) so suficientes para exprimir
estruturas de dados em algoritmos. Por exemplo, considere o problema no qual se
deseja calcular a mdia das notas dos alunos de uma turma e exibir no vdeo aquelas
que forem menores do que a mdia. Para calcular a mdia so necessrias duas
variveis: uma para armazenar o somatrio das notas e outra para armazenar o nmero
de alunos da turma. Porm, para exibir as notas maiores do que a mdia necessrio
armazen-las para posterior comparao com a mdia, pois o clculo da mdia s
poder ser feito aps a leitura de todas as notas. A alternativa de ler os dados de
entrada (neste caso, as notas) duas vezes est fora de questo. Com as estruturas de
dados de que dispomos at o momento, na verdade apenas variveis de tipos bsicos,
seria necessrio criar tantas variveis quantas fossem as notas a serem processadas.
Para um nmero pequeno de alunos, digamos 5, no haveria muitos inconvenientes.
Porm, para um nmero muito grande de alunos esta abordagem tornaria impraticvel
a redao do algoritmo. A partir do que dito, fica clara a necessidade de se dipor de
novos tipos de dados para modelar problemas como o que foi descrito acima. Um
destes tipos, o vetor, ser estudado nesta unidade.

5.1 Usando Vetores

Para o problema sendo abordado, seria ideal uma estrutura de dados que
armazenasse todas as notas, e que pudesse ser referenciada pelo conjunto ou por cada
nota individualmente:

Exemplo:

notas

Um vetor um tipo de dado usado para representar uma certa quantidade de
valores homogneos. Podemos imaginar um vetor como uma srie de variveis do
mesmo tipo referenciadas por um nico nome, onde cada varivel diferenciada
atravs de um nmero chamado de ndice. Colchetes so usados para conter o ndice.
A declarao int notas[5] aloca memria para armazenar 5 inteiros, e informa que
notas um vetor de 5 elementos.
Uma vez declarado o vetor, precisamos de um modo para referenciar seus
elementos individualmente. Isto feito atravs de um nmero entre colchetes seguindo
o nome do vetor. Observe que este nmero tem significados (semntica) diferentes
quando referencia um elemento do vetor e na declarao do mesmo; onde indica o seu
tamanho.
5,0 3,0 8,0 .......... 9,5

1 2 3 100
Linguagem e Tcnica de Programao I

Ivan Mathias Filho Pgina 34 16/05/00

Quando referenciamos um elemento do vetor, este nmero especifica a posio do
elemento na lista. Os elementos do vetor so sempre numerados por ndices iniciados
por zero. O elemento referenciado pelo nmero 2, notas[2], no o segundo elemento
do vetor, e sim o terceiro, pois a numerao comea em zero. Assim,o ltimo elemento
do vetor possui um ndice que uma unidade menor do que o tamanho do vetor.
Nos nossos programas utilizaremos uma varivel inteira, por exemplo i, como
ndice de um vetor. Esta possibilidade, associada ao uso de estruturas de repetio,
como while e for, torna os vetores verdadeiramente teis.

Exemplo:

notas[i]=2.5;

O programa abaixo a implementao do problema das notas abordado acima.

Exemplo:

#include <stdio.h>
#define AND &&
#define MAXALUNO 10

void main(void)
{
int qtdAlunos=0,i;
float soma=0.0,media,nota,notas[MAXALUNO];

printf("Informe uma Nota - Nota Negativa Termina\n");
scanf("%f",&nota);
while(nota>=0 AND qtdAlunos<MAXALUNO)
{
notas[qtdAlunos]=nota;
soma+=nota;
qtdAlunos++;
printf("Informe uma Nota - Nota Negativa Termina\n");
scanf("%f",&nota);
}

if(qtdAlunos>0)
{
media=soma/qtdAlunos;
printf("Media da Turma - %5.2f\n",media);

printf("\nNotas Menores do que a Media\n\n");

for(i=0;i<qtdAlunos;i++)
if(notas[i]<media)
printf("%5.2f\n",notas[i]);
}
}

Linguagem e Tcnica de Programao I

Ivan Mathias Filho Pgina 35 16/05/00

5.2 Busca em Tabelas

A necessidade de procurar uma informao em uma tabela, em um vetor, ou em um
catlogo uma tarefa muito comum na rea da computao. Por exemplo, procurar o
telefone de uma pessoa em um catlogo telefnico, procurar o valor do IPVA em uma
tabela que fornea o valor do imposto em funo do modelo e do ano de fabricao do
veculo, consultar a quantidade existente em estoque de uma determinada mercadoria
em uma tabela que armazena a quantidade de itens da mercadoria e o cdigo da
mesma.
Como esta funo muito utilizada, importante utilizarmos algoritmos que a
executem de maneira eficiente; ou seja, no menor tempo possvel.

5.2.1 Busca Seqencial

Neste mtodo, o processo de busca pesquisa a tabela seqencialmente desde o seu
incio. A chave de cada elemento da tabela comparado com a chave de busca. Se
houver igualdade entre a chave de busca e a chave do elemento da tabela a busca
termina, sendo que o ndice do elemento na tabela geralmente a informao de que se
necessita. Se o final da tabela for atingido e a chave no for encontrada, temos a
condio na qual nenhum elemento da tabela tem uma chave igual a chave de busca.

Exemplo

#include <stdio.h>
#define MAX 10

void main(void)
{
int i,cod,
int tabCod[MAX]={145,567,84,27,300,432,13,608,913,47};
int qtd,tabQtd[MAX];

for(i=0;i<MAX;i++)
{
printf("Informe a Qtd do Produto %3d\n",tabCod[i]);
scanf("%d",&tabQtd[i]);
}

printf("Informe o Codigo do Produto\n");
scanf("%d",&cod);

while(cod)
{
for(i=0;i<MAX && tabCod[i]!=cod;i++);

if(i==MAX)
printf("Produto Inexistente\n");
else
Linguagem e Tcnica de Programao I

Ivan Mathias Filho Pgina 36 16/05/00

{
printf("Informe a Quantidade\n");
scanf("%d",&qtd);
if(qtd>tabQtd[i])
printf("Estoque Insuficiente - %3d\n",tabQtd[i]);
else
{
tabQtd[i]-=qtd;
printf("Venda Efetuada\n");
}
}
printf("Informe o Codigo do Produto\n");
scanf("%d",&cod);
}

printf("POSICAO DO ESTOQUE\n\n");
printf("CODIGO QTD\n\n");
for(i=0;i<MAX;i++)
printf(" %3d %3d\n",tabCod[i],tabQtd[i]);
}

Uma empresa possui dez tipos de parafusos em estoque, onde cada um dos tipos
possui um cdigo de identificao (145, 567, 84, 27, 300, 432, 13, 608, 913, 047). No
incio do dia o programa de controle de estoque pede ao estoquista que fornea a
quantidade em estoque (em Kg) de cada um dos tipos de parafusos, armazenando-as
em um vetor. Da em diante, o programa em ir ler continuamente cdigos de
parafusos do teclado e consultar a tabela para verificar se existe o tipo de parafuso
com o cdigo fornecido pelo vendedor. Caso o cdigo exista, o programa ir solicitar
ao vendedor a quantidade de parafusos a ser vendida. Se a quantidade existente no
estoque for suficiente para atender ao pedido, a mensagem Venda Efetuada ser
exibida no monitor e o estoque ser atualizado. Caso contrrio, a mensagem a ser
exibida ser Estoque Insuficiente, juntamente com a quantidade em estoque do
produto solicitado. No final do programa, que ser detectado quando o cdigo
digitado for zero, dever ser exibida no monitor a listagem dos produtos com os seus
respectivos nveis de estoque.

5.2.2 Busca Seqencial com Sentinela

O algoritmo anterior pode ser otimizado inserindo-se a chave procurada no final do
vetor (este deve, portanto, poder armazenar um elemento a mais). A busca termina
quando a chave for encontrada, o que certamente ocorrer. Porm, se a chave for
encontrada na ltima posio da tabela saberemos que ela no se encontra na tabela
original (sem o ltimo elemento, inserido artificialmente). O programa abaixo tem a
mesma funcionalidade do exemplo anterior, porm o algoritmo de busca implementado
o de busca seqencial com sentinela. As diferenas para o algoritmo de busca
seqencial, visto anteriormente, est assinalada em negrito.
Linguagem e Tcnica de Programao I

Ivan Mathias Filho Pgina 37 16/05/00


Exemplo

#include <stdio.h>
#define MAX 10

void main(void)
{
int i,cod,int
int tabCod[MAX+1]={145,567,84,27,300,432,13,608,913,47};
int qtd,tabQtd[MAX+1];

for(i=0;i<MAX;i++)
{
printf("Informe a Qtd do Produto %3d\n",tabCod[i]);
scanf("%d",&tabQtd[i]);
}

printf("Informe o Codigo do Produto\n");
scanf("%d",&cod);

while(cod)
{
tabCod[MAX]=cod;
for(i=0;tabCod[i]!=cod;i++);

if(i==MAX)
printf("Produto Inexistente\n");
else
{
printf("Informe a Quantidade\n");
scanf("%d",&qtd);
if(qtd>tabQtd[i])
printf("Estoque Insuficiente - %3d\n",tabQtd[i]);
else
{
tabQtd[i]-=qtd;
printf("Venda Efetuada\n");
}
}
printf("Informe o Codigo do Produto\n");
scanf("%d",&cod);
}

printf("POSICAO DO ESTOQUE\n\n");
printf("CODIGO QTD\n\n");
for(i=0;i<MAX;i++)
printf(" %3d %3d\n",tabCod[i],tabQtd[i]);
}

Linguagem e Tcnica de Programao I

Ivan Mathias Filho Pgina 38 16/05/00

Nos dois casos descritos acima, partimos da premissa de que a distribuio das
chaves na tabela no obedece a nenhuma ordem preestabelecida. Desta forma,
podemos esperar que, ao encontrarmos uma determinada chave, esta possa estar na
primeira posio, ou na ltima posio, ou em qualquer outra posio da tabela com
igual probabilidade. Assim, estes algoritmos executaro, em mdia, n/2 comparaes,
onde n o nmero de elementos da tabela. Diz-se ento que a complexidade destes
algoritmos da ordem de n e escreve-se O(n).

5.2.3 Busca em Vetores Ordenados

Quando uma tabela estiver ordenada segundo uma chave (chave de ordenao), que
seja a mesma chave usada em uma busca, podemos usar um algoritmo mais eficiente
do que os algoritmos vistos anteriormente. Neste caso, no ser necessrio examinar
todos os elementos de uma tabela para constatar que nenhum elemento da tabela
atende ao critrio de busca. Para isso, basta que encontremos um elemento da tabela
cujo valor da chave de ordenao seja maior do que valor da chave de pesquisa.

Exemplo

int busca(int vet[],int tam, int chave, int *pos)
{
*pos=0;
while(*pos<tam)
if(vet[*pos]==chave)
return 1;
else
if(vet[*pos]>chave)
return 0;
else
(*pos)++;
return 0;
}
Linguagem e Tcnica de Programao I

Ivan Mathias Filho Pgina 39 16/05/00


5.2.3.1 Busca Binria

O mtodo mais ficiente para uma busca em uma tabela ordenada a busca binria.
Basicamente, o algoritmo da busca binria consiste em compararmos a chave de busca
com a chave de ordenao do elemento "central" da tabela. Se elas forem iguais, a
busca termina com sucesso; caso contrrio, se a chave de busca for maior do que o
valor da chave de ordenao do elemento "central", o mesmo mtodo de busca ser
aplicado aos elementos direita do elemento "central". Caso a chave de busca seja
menor do que o valor da chave de ordenao do elemento "central", o mesmo mtodo
de busca ser aplicado aos elementos esquerda do elemento central. Em ambas as
situaes, os elementos restantes so desprezados.


A cada iterao, o algoritmo de busca binria reduz o tamanho da tabela metade
do tamanho da iterao anterior. Logo, o nmero mximo de comparaes que sero
feitas ser log
2
n. Diz-se ento que a complexidade deste algoritmos da ordem de
log n e escreve-se O(log n).
20 30 40 50 60 70 80 90 10 100
incio fim meio
Chave de Busca = 60
1a. Iterao
20 30 40 50 60 70 80 90 10 100
incio fim meio
2a. Iterao
20 30 40 50 60 70 80 90 10 100
incio fim meio
3a. Iterao
Linguagem e Tcnica de Programao I

Ivan Mathias Filho Pgina 40 16/05/00


Exemplo

int buscaBin(int vet[],int tam,int chave,int *meio)
{
int fim=tam-1,ini=0;

while(ini<=fim)
{
*meio=(ini+fim)/2;
if(vet[*meio]==chave)
return 1;
else
if(vet[*meio]>chave)
fim=*meio-1;
else
ini=*meio+1;
}
*meio=ini;
return 0;
}

5.3 Classificao de Dados

A classificao ou ordenao de dados constitui uma das tarefas mais freqentes e
importantes em processamento de dados, sendo, normalmente, auxiliar ou
preparatria, visando tornar mais simples e eficiente as demais. A emisso de
relatrios, por exemplo, usualmente feita usando como entrada um ou mais arquivos
classificados.
O processo de classificao de um conjunto de dados inteiramente contido na
memria principal chamado de classificao interna, ao passo que a classificao de
um conjunto de dados no inteiramente armazenado na memria principal chamada
de classificao externa.

5.3.1 Classificao por Troca Mtodo da Bolha

No algoritmo que ser visto a seguir iremos classificar uma tabela composta por
duas colunas. Cada uma das colunas ser implementada atravs de um vetor de um
tipo de dados compatvel com a natureza dos dados armazenados nas colunas da
tabela. A classificao ser feita em relao aos valores armazenados em uma nica
coluna da tabela (chave de ordenao). Porm, quando trocarmos dois elementos de
posio entre si no vetor de chaves de ordenao, a mesma troca ser efetuada nos
outros vetores que implementam as demais colunas da tabela, para que o
relacionamento entre os campos de uma mesma linha da tabela seja preservado.
O Mtodo da Bolha um dos mtodos mais simples de classificao de dados. A
cada passo, cada elemento do vetor de chaves comparado com o seu sucessor, sendo
os dois trocados de posio caso estejam fora de ordem.
Considere o seguinte vetor de chaves:
Linguagem e Tcnica de Programao I

Ivan Mathias Filho Pgina 41 16/05/00



As seguintes comparaes so feitas ao percorremos o vetor pela primeira vez (1
a

passagem):

vet1[1] com vet1[2] (25 com 57) sem troca
vet1[2] com vet1[3] (57 com 48) troca
vet1[3] com vet1[4] (57 com 37) troca
vet1[4] com vet1[5] (57 com 12) troca
vet1[5] com vet1[6] (57 com 92) sem troca
vet1[6] com vet1[7] (92 com 86) troca
vet1[7] com vet1[8] (92 com 33) troca

Logo, aps a 1
a
passagem o vetor ter a seguinte configurao:


Note que aps a 1
a
passagem o maior elemento (nesse caso 92) ocupa a sua devida
posio no vetor. Aps a 2
a
passagem a configurao ser:


Note que o elemento 86 foi colocado na segunda maior posio dentro do vetor.
Logo, desde que cada iterao coloca um novo elemento na sua devida posio, um
vetor com n elementos ir requerer no mais que n-1 iteraes para estar
completamente ordenado.
A funo abaixo implementa o algoritmo acima descrito para uma tabela com duas
colunas.

Exemplo


void ordena(int vet1[],float vet2[],int tam)
{
int aux1,i,j,trocou=1;
float aux2;

for(i=0;trocou;i++)
{
trocou=0;
for(j=0;j<tam-i-1;j++)
if(vet1[j]>vet1[j+1])
{
aux1=vet1[j+1];
vet1[j+1]=vet1[j];
57 48 37 12 92 86 33 25
48 37 12 57 86 33 92 25
37 12 48 57 33 86 92 25
Linguagem e Tcnica de Programao I

Ivan Mathias Filho Pgina 42 16/05/00

vet1[j]=aux1;
aux2=vet2[j+1];
vet2[j+1]=vet2[j];
vet2[j]=aux2;
trocou=1;
}
}
}


Apesar de ser um mtodo de ordenao bastante simples, o Mtodo da Bolha
muito ineficinte devido, principalmente, ao excessivo nmero de trocas executado. A
complexidade deste algoritmos da ordem de n
2
e escreve-se O(n
2
).

6 Matrizes

No Captulo 5 pudemos verificar a utilidade dos vetores na soluo de diversos problemas que
envolviam arranjos homogneos unidimensionais. No entanto, podemos encontrar diversos problemas
que envolvam na sua soluo arranjos homogneos multidimensionais, particularmente de duas
dimenses. Por exemplo, considere o problema no qual se deseja calcular as mdias das turmas de
uma escola e exibir no vdeo as notas dos alunos da turma com a maior mdia. Para calcular as
mdias das turmas e armazen-las para posterior processamento necessrio apenas um vetor do tipo
float. Porm, para exibir as notas dos alunos da turma que obteve a maior mdia necessrio
armazenar as notas de todos os alunos de todas as turmas (agrupados por turma), pois a seleo da
turma com a maior mdia s poder ser feita aps a leitura de todas as notas de todas as turmas da
escola, e o clculo das mdias das turmas.

6.1 Usando Matrizes

Para representar os dados do problema descrito acima poderamos usar tantos
vetores quanto fosse o nmero de turmas existentes no colgio. Porm, seria ideal uma
estrutura de dados que armazenasse todas as notas de todas as turmas, e que pudesse
ser referenciada pelo conjunto, pelo conjunto das notas de uma turma, ou por cada
nota individualmente:
Linguagem e Tcnica de Programao I

Ivan Mathias Filho Pgina 43 16/05/00

Exemplo:

notas

Uma matriz um tipo de dados usado para representar uma certa quantidade de
valores homogneos de natureza bidimensional. Podemos imaginar uma matriz como
sendo um vetor, onde cada elemento deste vetor tambm um vetor. Logo, para
referenciarmos um elemento em uma matriz precisamos de dois ndices: o primeiro
para selecionar o vetor (linha) e o segundo para selecionar o elemento do vetor
previamente selecionado (coluna).

Exemplo:

notas[4][3]=7.5;

A declarao float notas[5][50] aloca memria para armazenar as notas de 5 turmas (linhas), cada
uma das quais com 50 alunos (colunas).
Neste momento importante diferenciarmos as tabelas, vistas no captulo anterior, das matrizes.
Embora normalmente representadas em um forma tabular (linhas e colunas), as matrizes diferem das
tabelas por serem estruturas de dados homogneas, tanto em relao aos tipos de dados quanto
natureza da informao. Isto , as linhas e as colunas de uma matriz so formadas por elementos do
mesmo tipo de dados, e armazenam informaes de mesmo contedo semntico (no exemplo acima
cada elemento da matriz armazena uma nota do tipo float). As tabelas, por outro lado, so
representadas tambm na forma tabular porm as suas colunas (implementadas atravs de vetores)
so heterogneas entre si, armazenando informaes que podem ser at homogneas quanto ao tipo de
dados, mas que so heterogneas quanto natureza da informao.

6.2 Percorrendo uma Matriz

Para percorrermos uma matriz so necessrias duas estruturas de repetio aninhadas. A estrutura
de repetio mais externa percorrer as linhas da matriz, enquanto a estrutura de repetio mais
interna percorrer os elementos (colunas) da linha corrente.
O cdigo C a seguir permite que a matriz de notas do nosso problema seja "carregada" a partir do
teclado:

Exemplo

for(i=0;i<5;i++)
for(j=0;j<50;j++)
{
printf("Forneca a nota %d da turma %d\n",j+1,i+1);
5,0 3,0 8,0 .......... 9,5
7,3 2,2 5,6 .......... 8,0
5,7 1,8 6,4 ........... 5,9
2,4 4,9 6,0 .......... 3,8
10,0 9,5 3,0 .......... 4,0

1 2 3 ......... 50
Linguagem e Tcnica de Programao I

Ivan Mathias Filho Pgina 44 16/05/00

scanf("%f",&notas[i][j]);
}

O cdigo C a seguir permite que a matriz de notas do nosso problema seja exibida no vdeo na
forma matricial. Para isso, os elementos de uma mesma linha so exibidos uns aps os outros sem
que seja dados um salto de linha (note que no existe \n no string de controle do printf). Aps a
exibio de uma linha da matriz emitido um comando para saltar para a prxima linha do vdeo.

Exemplo

for(i=0;i<5;i++)
{
for(j=0;j<50;j++)
printf("%5.2f ",notas[i][j]);
printf("\n");
}

7 Strings

At aqui, quando desejamos indicar o nmero de elementos existentes em um vetor
qualquer, usamos uma varivel inteira, digamos tam, para tal. Logo, quando
necessrio verificar se um dado valor est presente em um vetor executamos um trecho
de cdigo semelhante ao descrito abaixo:

Exemplo

int vet[10],i,tam,valor;

for(i=0;i<tam && vet[i]!=valor;i++);
if(i==qtd)
/* cdigo executado quando o valor */
/* foi encontrado no vetor */
else
/* cdigo executado quando o valor */
/* no foi encontrado no vetor */

Uma outra abordagem possvel seria indicarmos o trmino do vetor lgico atravs
da presena de um valor que no pertena ao domnio dos valores presentes no vetor.
Seja, por exemplo, um vetor de inteiros que armazene as idades dos alunos de uma
turma. A presena de um valor negativo poderia ser usada para indicar o fim do vetor
de idades, j que no h sentido em uma idade negativa. Note que para esssa
abordagem funcionar necessrio que definamos o vetor de idades com pelo menos
um elemento a mais do que seria necessrio para armazenar todas as idades dos alunos
da turma.
Logo, se quisrmos verificar se uma dada idade existe em uma turma de no mximo
30 alunos, o trecho de cdigo a ser executado ser o seguinte:

Exemplo
Linguagem e Tcnica de Programao I

Ivan Mathias Filho Pgina 45 16/05/00


int vetIdade[31],i,idade;

for(i=0;vetIdade[i]>=0 && vetIdade[i]!=idade;i++);
if(vetIdade[i]>=0)
/* cdigo executado quando o valor */
/* foi encontrado no vetor */
else
/* cdigo executado quando o valor */
/* no foi encontrado no vetor */

7.1 Strings em C

A linguagem C no possui nenhum tipo primitivo que permita a manipulao de
cadeias de caracteres (strings). Desta forma, um string em C implementado atravs
do uso de um vetor de caracteres terminado pelo caracter nulo. O caracter nulo tem
configurao binria 00000000 (o seu cdigo ASCII 0), e representado pela
seqncia '\0' ou pela macro NULL.
Para armazenarmos um string de at 10 caracteres escrevemos o comando

char str[11];

O vetor str pode ser inicializado de duas maneiras distintas:

1) listando os caracteres um a um, e acrescentando o caracter nulo no final.

char str[11]={'a','l','o',
' ','m','u','n','d','o','\0'};
2) usando uma constante do tipo string. Neste caso, o compilador acrescenta o
caracter nulo automaticamente.

char str[11]="alo mundo";

7.2 Lendo e Escrevendo Strings

A biblioteca padro de E/S, stdio.h, fornece duas funes para E/S com strings. A
funo gets() l um string de caracteres do teclado e o coloca no endereo apontado
pelo argumento passado (ponteiro para caracter). Os caracteres digitados so
transferidos para a memria aps um Enter. O Enter no se torna parte do string; em
seu lugar colocado o caracter nulo (\0).

char *gets(char *str);

Neste prottipo str um vetor de caracteres (ou um ponteiro qualquer para
caracteres) que recebe os caracteres digitados pelo usurio. A funo gets() retorna
um ponteiro para o string lido se a leitura for feita corretamente; ou retorna NULL
caso algum erro tenha ocorrido, ou o fim-de-arquivo tenha sido atingido.
Linguagem e Tcnica de Programao I

Ivan Mathias Filho Pgina 46 16/05/00


A funo puts() escreve o seu argumento (um string) na tela, seguida por um
caracter de nova linha.

int puts(char *str);

A funo puts() reconhece os mesmos caracteres de controle que a funo printf()
(por exemplo, \n). Uma chamada puts() requer bem menos tempo do que a mesma
chamada printf(), porque puts() pode escrever apenas strings de caracteres, no
podendo escrever nmeros ou fazer converses de formato. Portanto, puts() ocupa
menos espao na memria, e executada mais rapidamente do que printf().

A funo puts() devolve EOF se ocorrer algum erro. Caso contrrio, ela devolve
um valor diferente de zero. No entanto, quando a escrita feita no console, pode-se
normalmente assumir que no ocorrer nenhum erro.

O comando a seguir exibe a frase Alo Mundo! no monitor.

puts(Alo Mundo!);

A funo scanf() pode ser utilizada para ler um string da stream de entrada, usando
o especificador de formato %s. O %s faz com que scanf() leia caracteres at que seja
encontrado um caracter de espao em branco. Os caracteres lidos so colocados em
um vetor de caracteres apontado pelo argumento correspondente, e o resultado tem
terminao nula (\0). Para scanf(), um caracter de espao em branco um espao,
um retorno de carro (Enter), ou uma tabulao. Logo, um string como Alo Mundo!
no pode ser lido com scanf() (apenas o substring Alo ser carregado no vetor).

A funo printf() escreve uma string atravs do %s. Ao contrrio da funo
puts(), no existe mudana automtica de linha na exibio de um string no vdeo.

Podemos tambm ler um string, caracter a caracter, atravs das funes getchar(),
getch() ou getche(). Neste caso, funo do programador acrescentar um caracter
\0 aps o string.

O cdigo a seguir exemplifica o que foi dito acima.
Linguagem e Tcnica de Programao I

Ivan Mathias Filho Pgina 47 16/05/00


Exemplo

#include <stdio.h>

void main(void)
{
char nome[81];
int i=0;

printf("Informe um Nome\n");
nome[i]=getchar();
while(i<80 && nome[i]!='\n')
{
i++;
nome[i]=getchar();
}
nome[i]=NULL;
puts(nome);
}

importante lembrar que as funes gets() e scanf() recebem como parmetro um
ponteiro para uma rea de memria. Logo, no temos controle sobre a quantidade de
caracteres que ser digitada pelos usurios, e sobre a rea de memria que ser
utilizada para armazenar os caracteres lidos; j que o tamanho do vetor estabelecido
estaticamente.

7.3 Algumas Funes de Strings

A biblioteca de funes de strings, string.h, fornece uma gama variada de funes
para a manipulao de strings. As mais comuns so fornecidas pela maioria dos
compiladores C. So elas:

7.3.1 strlen()

A funo strlen() retorna o nmero de caracteres em um string (o caracter NULL
no contado). O cabealho da funo strlen() o seguinte:

int strlen(char *str);

Exemplo

#include<stdio.h>
#include<string.h>

void main(void)
{
char nome[]="Joao da Silva";
Linguagem e Tcnica de Programao I

Ivan Mathias Filho Pgina 48 16/05/00

printf("%s contem %d caracteres",nome,strlen(nome));
}

Ao ser executado, este programa exibir no monitor o texto

Joao da Silva contem 13 caracteres

7.3.2 strcpy()

A funo strcpy() usada para copiar o contedo de um string (fonte) para outro
string (destino). O cabealho da funo strcpy() o seguinte:

char *strcpy(char *destino,char *fonte);

A funo strcpy() retorna um ponteiro para o string de destino.

Exemplo

#include<stdio.h>
#include<string.h>

void main(void)
{
char nome[]="Joao da Silva",aluno[50];
strcpy(aluno,nome);
printf("O nome do aluno e %s",aluno);
}

Ao ser executado, este programa exibir no monitor o texto

O nome do aluno e Joao da Silva

7.3.3 strcmp()

A funo strcmp() usada para comparar lexicograficamente dois strings. O
cabealho da funo strcmp() o seguinte:

int strcmp(char *str1,char *str2);

Se os strings forem iguais, isto , se str1 e str2 forem do mesmo comprimento e
possurem caracteres iguais nos elementos de mesmo ndice, strcmp() retornar zero.
Se str1 for lexicograficamente maior do que str2, a funo strcmp() retornar um
valor maior do que zero. Se str2 for lexicograficamente maior do que str1, a funo
strcmp() retornar um valor menor do que zero.
Linguagem e Tcnica de Programao I

Ivan Mathias Filho Pgina 49 16/05/00


Exemplo

#include<stdio.h>
#include<string.h>

void main(void)
{
char nome1[]="Joao da Silva",nome2[]="Maria Fernanda";

if(!strcmp(nome1,nome2))
printf("%s e igual a %s",nome1,nome2);
else
if(strcmp(nome1,nome2)>0)
printf("%s vem depois de %s",nome1,nome2);
else
printf("%s vem depois de %s",nome2,nome1);
}

Ao ser executado, este programa exibir no monitor o texto

Maria Fernanda vem depois de Joao da Silva

7.3.4 strcat()

A funo strcat() anexa o contedo de um string (fonte) no final de outro string
(destino). Este processo chamado de concatenao de strings. importante lembrar
que o tamanho fsico do string de destino ter que ser suficiente para armazenar os
caracteres dos dois strings.
O primeiro caracter do string de origem copiado para a posio do string de
destino que contm o caracter NULL. O processo repetido at que o ltimo caracter
do string de origem seja copiado para o string de destino. O string de destino ter
apenas um caracter NULL no final do processo.
O cabealho da funo strcat() o seguinte:

char *strcat(char *destino,char *origem);

A funo strcat() retorna um ponteiro para o string de destino.

Exemplo

#include<stdio.h>
#include<string.h>

void main(void)
{
char nome[30]="Joao",sobreNome[]=" da Silva";

printf("O nome do aluno e %s",strcat(nome,sobreNome));
Linguagem e Tcnica de Programao I

Ivan Mathias Filho Pgina 50 16/05/00

}

Ao ser executado, este programa exibir no monitor o texto

O nome do aluno e Joao da Silva

7.3.5 strstr()

A funo strstr() procura um substring de um string. Se o string contiver o
substring em questo, a funo retornar um ponteiro para o primeiro caracter do
substring no string. Caso contrrio, a funo retornar NULL.
O cabealho da funo strstr() o seguinte:

char *strstr(char *string,char *substring);

Exemplo

#include<stdio.h>
#include<string.h>

void main(void)
{
char nome[30]="Joao da Silva",sobreNome[]="da Silva";

if(strstr(nome,sobreNome))
printf("Achou");
else
printf("Nao achou");
}

Ao ser executado, este programa exibir no monitor o texto

Achou

8 Arquivos

Antes de comearmos a discutir o sistema de arquivos do C ANSI importante
entendermos a diferena entre os termos streams e arquivos. O sistema de E/S do C
fornece ao programador uma interface consistente, independente do dispositivo real
sendo acessado. Isto , o sistema de E/S do C fornece um nvel de abstrao entre o
programador e o dispositivo utilizado. Essa abstrao chamada de stream e o
dispositivo real chamado de arquivo.
O sistema de arquivos do C ANSI foi projetado para trabalhar com uma grande
variedade de dispositivos de E/S, incluindo terminais, acionadores de discos e
acionadores de fita. Embora cada um dos dispositivos seja muito diferente, o sistema
de arquivos com buffer transforma-os em um dispositivo lgico chamado stream.
Todos os streams se comportam de maneira semelhante. Pelo fato dos streams serem
Linguagem e Tcnica de Programao I

Ivan Mathias Filho Pgina 51 16/05/00

independentes dos dispositivos reais, a mesma funo pode escrever dados em um
arquivo em disco ou em algum outro dispositivo, como o console.
Em C um arquivo pode ser qualquer coisa, desde um arquivo em disco at um
terminal ou uma impressora. Um stream associado com um arquivo especfico
atravs de uma operao de abertura. Uma vez aberto o arquivo, informaes podem
ser trocadas entre ele e o programa. Quando no for mais necessrio trocar
informaes com o arquivo, geralmente no final do processamento, devemos
desassociar o stream do arquivo atravs de uma operao de fechamento.
Nem todos os arquivos apresentam os mesmos recursos. Por exemplo, um arquivo
em disco pode suportar acesso aleatrio enquanto um teclado no pode. Isso revela
um ponto importante sobre o sistema de E/S do C: todos os streams so iguais, mas
no todos os arquivos.

8.1 Fundamentos do Sistema de Arquivos

O sistema de arquivos ANSI composto de diversas funes para a manipulao de
arquivos, algumas das quais sero vistas no decorrer deste captulo. Essas funes
exigem que o cabealho STDIO.H seja includo nos programas que as utilizem.
O arquivo STDIO.H fornece prottipos para as funes de E/S e define tambm os
tipos size_t e FILE. O tipo size_t essencialmente o mesmo que um unsigned,
enquanto o tipo FILE ser discutido na prxima seo. Em STDIO.H definida
tambm a macro EOF (geralmente definida como 1), sendo tal valor devolvido
quando uma funo de entrada tenta ler alm do final de um arquivo.

8.1.1 O Ponteiro de Arquivo

Um ponteiro de arquivo uma varivel do tipo FILE que aponta para informaes
que definem vrios atributos de um arquivo, tais como o seu nome, status e posio
atual do cursor. Basicamente, o ponteiro de arquivo identifica um arquivo especfico
em disco, sendo usado pela stream associada para direcionar as operaes das funes
de E/S. Para ler (escrever) dados de (em) um arquivo, um programa precisa definir um
ponteiro de arquivo da seguinte maneira:

FILE *arq;

8.1.2 Abrindo um Arquivo

Usamos a funo fopen() para abrirmos uma stream para uso e associarmos um
arquivo a ela. Esta funo retorna um ponteiro para uma estrutura do tipo FILE
associada ao arquivo em questo. A funo fopen() tem o seguinte prottipo:

FILE *fopen(char *nomeArq,char *modo);

Neste prottipo, nomeArq um ponteiro para um string que forma um nome
vlido de arquivo, podendo incluir uma especificao de caminho (path). O string
Linguagem e Tcnica de Programao I

Ivan Mathias Filho Pgina 52 16/05/00

apontado por modo determina como o arquivo ser aberto. A tabela abaixo mostra os
strings vlidos para modo.


Modo Significado

r abre um arquivo texto para leitura
w cria um arquivo texto para escrita
a anexa dados no final de um arquivo texto
rb abre um arquivo binrio para leitura
wb cria um arquivo binrio escrita
ab anexa dados no final de um arquivo binrio
r+ abre um arquivo texto para leitura/escrita
w+ cria um arquivo texto para leitura/escrita
a+ anexa ou cria um arquivo texto para leitura/escrita
rb+ abre um arquivo binrio para leitura/escrita
wb+ cria um arquivo binrio para leitura/escrita
ab+ anexa ou cria um arquivo binrio para leitura/escrita


Se ocorrer um erro quando o arquivo estiver sendo aberto, fopen() devolve um
ponteiro nulo. Logo, antes de prosseguirmos com a leitura (escrita) de (em) um
arquivo devemos testar esta condio. Para isso comparamos o ponteiro de arquivo
com a macro NULL, que definida em STDIO.H como '\0'.
O seguinte trecho de programa ser normalmente visto nos programas que
manipulam arquivos:

FILE *arq;

if((arq=fopen("c:\\dir\\arquivo.x","w"))==NULL)
{
printf("O arquivo nao pode ser aberto\n");
exit(1);
}

8.1.3 Fechando um Arquivo

A funo fclose() fecha um stream que foi aberto atravs de uma chamada
fopen(). Ela escreve qualquer dado que ainda esteja no buffer e, ento, fecha
normalmente o arquivo em termos de sistema operacional. Uma falha no sistema antes
que um stream seja fechado pode causar perda de dados ou destruio do arquivo. A
funo fclose() tem o seguinte prottipo:

int *fopen(FILE *arq);

Onde arq um ponteiro devolvido pela chamada fopen().

Linguagem e Tcnica de Programao I

Ivan Mathias Filho Pgina 53 16/05/00

Exemplo

fclose(arq);

8.2 Arquivos (Streams) de Texto

Um arquivo de texto armazenado como uma seqncia de caracteres ASCII. Isto
permite que os arquivos de texto possuam grande portabilidade entre plataformas de
hardware/software, j que o texto ter que ser convertido para a configurao de
memria da plataforma alvo quando da sua manipulao por um programa. Esta
converso, porm, impe um custo adicional aos usurios dos arquivos de texto
atravs de uma sobrecarga nos sistemas que manipulam tais arquivos. Isto ocorre,
principalmente, na converso de seqncias de dgitos decimais para dados dos tipos
int e float. Logo, devemos sempre comparar os ganhos obtidos com a portabilidade
dos arquivos de texto com a perda de performance imposta aos sistemas que
manipulam dados numricos armazenados como texto.
Os arquivos de texto podem ser classificados como sendo compostos por texto
formatado e texto no-formatado. Os arquivos de texto no-formatado podem ser
vistos como um seqncia de caracteres que no possui nem tamanho nem tipo pr-
estabelecido. Os textos no-formatados so manipulados geralmente por editores de
texto, e so lidos (ou gravados) caracter a caracter.
Os textos formatados so compostos por seqncias de caracteres que possuem
formato (tipo e tamanho) e semntica pr-estabelecidos. Por exemplo, os dados de um
aluno podem ser armazenados em um arquivo texto onde a matrcula seria
representada por uma seqncia de dgitos decimais, o nome por uma seqncia de
caracteres alfabticos de comprimento menor ou igual a 40, o endereo por uma
seqncia de caracteres alfa-numricos de comprimento menor ou igual a 50, e o seu
CR por uma seqncia de dgitos decimais (alm no ponto decimal).

8.2.1 Escrevendo um Caracter

A funo fputc() escreve um caracter em um arquivo que foi previamente aberto
para escrita. A funo fputc() tem o seguinte prottipo:

int fputc(char ch,FILE *arq);

Onde arq um ponteiro devolvido pela chamada fopen() e ch o caracter a ser
escrito. Se a operao for bem sucedida, a funo devolve o caracter escrito. Caso
contrrio, ela devolve EOF.

8.2.2 Lendo um Caracter

A funo fgetc() l um caracter de um arquivo que foi previamente aberto para
leitura. A funo fgetc() tem o seguinte prottipo:

Linguagem e Tcnica de Programao I

Ivan Mathias Filho Pgina 54 16/05/00

char fgetc(FILE *arq);

Onde arq um ponteiro devolvido pela chamada fopen(). Se a operao for bem
sucedida, a funo devolve o caracter lido. Quando o final do arquivo for alcanado a
funo devolve EOF.

Exemplo

ch=fgetc(arq);
while(ch!=EOF)
{
ch=fgetc(arq);
}

8.2.3 Escrevendo Strings

A funo fputs() escreve um string em um arquivo que foi previamente aberto para
escrita. A funo fputs() tem o seguinte prottipo:

int fputs(char *str,FILE *arq);

Onde arq um ponteiro devolvido pela chamada fopen() e str o string a ser
escrito. Se a operao for bem sucedida, a funo devolve um inteiro positivo. Caso
contrrio, ela devolve EOF.

8.2.4 Lendo Strings

A funo fgets() l um string de um arquivo que foi previamente aberto para leitura
at encontrar um caracter de nova linha ('\n'), ou at que tam-1 caracteres sejam
lidos. De maneira diferente de gets(), se um caracter de nova linha for lido ele far
parte do string resultante. O caracter nulo ser inserido no final do string resultante. A
funo fgets() tem o seguinte prottipo:

char *fgets(char *str, int tam, FILE *arq);

Onde arq um ponteiro devolvido pela chamada fopen() e str o string
resultante. Se a operao for bem sucedida, a funo devolve um ponteiro para str. Se
ocorrer algum tipo de erro um ponteiro nulo ser devolvido.

8.2.5 Usando fprintf() e fscanf()

As funes fprintf() e fscanf() so extenses das funes printf() e scanf() para
operar com arquivos. Os seus prottipos so os seguintes:

int fprintf(FILE *arq,char *controle,<lista de parmetros>);
int fscanf(FILE *arq,char *controle,<lista de parmetros>);
Linguagem e Tcnica de Programao I

Ivan Mathias Filho Pgina 55 16/05/00


Onde arq um ponteiro devolvido pela chamada fopen(). Se a operao fprint()
for bem sucedida, a funo devolve o nmero de caracteres escritos. Caso contrrio,
um nmero negativo devolvido.
Se a operao fscanf() for bem sucedida, a funo devolve o nmero de
argumentos que receberam valores. Quando o final do arquivo for alcanado a funo
devolve EOF.

8.2.6 Exemplo de Programa de Escrita

#include<stdio.h>
#include<conio.h>
#include<string.h>

void main(void)
{
FILE *arq;
char nome[41];
float nota;
int tam;

arq=fopen("c:\\ltp1\\arquivos\\nomes.txt","w");
if(arq==NULL)
{
printf("Erro na abertura do arquivo");
exit();
}

clrscr();
printf("Forneca o nome do aluno\n");
gets(nome);
tam=strlen(nome);
while(tam)
{
printf("Forneca a nota do aluno\n");
scanf("%f",&nota);
fprintf(arq,"%d %s %5.2f ",tam,nome,nota);
getchar();
printf("Forneca o nome do aluno\n");
gets(nome);
tam=strlen(nome);
}

fclose(arq);

}

8.2.7 Exemplo de Programa de Leitura

#include<stdio.h>
Linguagem e Tcnica de Programao I

Ivan Mathias Filho Pgina 56 16/05/00

#include<conio.h>
#include<string.h>

void main(void)
{
FILE *arq;
char nome[41],nomeMaior[41];
float nota,notaMaior=-1.0,soma=0.0;
int tam,qtd=0;

arq=fopen("c:\\ltp1\\arquivos\\nomes.txt","r");
if(arq==NULL)
{
printf("Erro na abertura do arquivo");
exit();
}

clrscr();
while(fscanf(arq,"%d",&tam)!=EOF)
{
qtd++;
fgetc(arq);
fgets(nome,tam+1,arq);
fscanf(arq,"%f",&nota);
printf("%-40s %5.2f\n",nome,nota);
soma+=nota;
if(nota>notaMaior)
{
notaMaior=nota;
strcpy(nomeMaior,nome);
}
}
printf("A media da turma e %5.2f\n",soma/qtd);
printf("A maior nota e %5.2f -
%s\n",notaMaior,nomeMaior);
fclose(arq);
}

8.3 Arquivos (Streams) Binrios

Os dados armazenados em um arquivo binrio tm o mesmo formato das suas
respectivas representaes na memria principal (RAM). Isto leva a um enorme
aumento no desempenho das operaes de E/S quando comparado ao desempenho das
operaes de E/S com arquivos texto, dado que nesse caso no necessrio converter
a representao interna de um dado numrico (int ou float) para uma representao
textual (e vice-versa). Dessa forma, os dados podem se lidos (escritos) diretamente
para (da) a memria principal (RAM) sem que haja necessidade de converso. Alm
disso, muito mais fcil tratar dados numricos armazenados na forma binria, j que
os tipos numricos tm tamanhos fixos.
Linguagem e Tcnica de Programao I

Ivan Mathias Filho Pgina 57 16/05/00

A grande vantagem dos arquivos binrios em comparao aos arquivos texto,
tambm o seu principal ponto fraco quando se trata de portabilidade. Ou seja, como os
arquivos binrios representam "imagens da memria principal", eles so dependentes
do hardware para (de) onde sero lidos (escritos) e da forma como as diversas
linguagens implementam os tipos numricos. Por exemplo, um dado do tipo ponto
flutuante escrito por um programa compilado com o Turbo Pascal (real), que tem seis
bytes de comprimento, no poder ser posteriormente lido para uma varivel de um
programa compilado com Turbo C, j que no existe neste compilador nenhum tipo de
dado que represente um ponto flutuante com seis bytes.

8.3.1 Funes de E/S para Arquivos Binrios

As funes fread() e fwrite() permitem, respectivamente, a leitura e a escrita de
uma seqncia de bytes de qualquer tipo de dado. Os seus prottipos so os seguintes:

size_t fread(void *mem, size_t numBytes, size_t cont, FILE *arq);
size_t fwrite(void *mem, size_t numBytes, size_t cont, FILE *arq);

Na funo fread(), mem um ponteiro para uma regio de memria que
armazenar os dados lidos do arquivo. Na funo fwrite(), mem um ponteiro para
uma regio de memria que armazena os dados que sero escritos no arquivo. O
nmero de bytes que sero lidos, ou escritos, dado por numBytes. O argumento
cont determina quantos itens de dados (cada um dos quais de comprimento
numBytes) sero lidos, ou escritos (o tipo size_t est definido em STDIO.H e
geralmente o mesmo que unsigned int). Finalmente, arq um ponteiro devolvido pela
chamada fopen().
A funo fread() devolve o nmero de itens lidos. Esse valor pode ser menor do
que cont se o final do arquivo for atingido, ou se ocorrer um erro. A funo fwrite()
devolve o nmero de itens escritos. Esse valor ser igual a cont, a no ser que ocorra
um erro.
Quando um arquivo for aberto no modo binrio, fread() e fwrite() podem ler e
escrever qualquer tipo de informao. Desse modo, devemos usar o operador de
tempo de compilao sizeof para determinarmos o comprimento de cada tipo de dado.

8.3.2 Exemplo de Programa de Escrita

#include<stdio.h>
#include<conio.h>
#include<string.h>

void main(void)
{
FILE *arq;
char nome[41];
float nota;
int tam;

Linguagem e Tcnica de Programao I

Ivan Mathias Filho Pgina 58 16/05/00

arq=fopen("c:\\ltp1\\arquivos\\nomes.dat","wb");
if(arq==NULL)
{
printf("Erro na abertura do arquivo");
exit();
}

clrscr();
printf("Forneca o nome do aluno\n");
gets(nome);
tam=strlen(nome);
while(tam)
{
printf("Forneca a nota do aluno\n");
scanf("%f",&nota);
fwrite(&tam,sizeof(int),1,arq);
fwrite(nome,sizeof(char),tam,arq);
fwrite(&nota,sizeof(float),1,arq);
getchar();
printf("Forneca o nome do aluno\n");
gets(nome);
tam=strlen(nome);
}

fclose(arq);
}
Linguagem e Tcnica de Programao I

Ivan Mathias Filho Pgina 59 16/05/00


8.3.3 Exemplo de Programa de Leitura

#include<stdio.h>
#include<conio.h>
#include<string.h>

void main(void)
{
FILE *arq;
char nome[41],nomeMaior[41];
float nota,notaMaior=-1.0,soma=0.0;
int tam,qtd=0;

arq=fopen("c:\\ltp1\\arquivos\\nomes.dat","rb");
if(arq==NULL)
{
printf("Erro na abertura do arquivo");
exit();
}

clrscr();
while(fread(&tam,sizeof(int),1,arq))
{
qtd++;
fread(nome,sizeof(char),tam,arq);
nome[tam]=NULL;
fread(&nota,sizeof(float),1,arq);
printf("%-40s %5.2f\n",nome,nota);
soma+=nota;
if(nota>notaMaior)
{
notaMaior=nota;
strcpy(nomeMaior,nome);
}
}
printf("A media da turma e %5.2f\n",soma/qtd);
printf("A maior nota e %5.2f -
%s\n",notaMaior,nomeMaior);
fclose(arq);
}

8.4 Usando a Funo feof()

Quando um arquivo aberto para entrada no modo binrio, um valor inteiro igual
marca EOF pode ser lido. Isso poderia fazer com que a rotina de entrada indicasse o
fim do arquivo apesar do final fsico do mesmo no ter sido alcanado. Para resolver
esse problema foi introduzida uma funo, feof(), que determina quando o final do
arquivo foi atingido em um processo de leitura. A funo feof() tem o seguinte
prottipo (incluso em STDIO.H):
Linguagem e Tcnica de Programao I

Ivan Mathias Filho Pgina 60 16/05/00


int feof(FILE *arq);

Essa funo devolve verdadeiro se o final do arquivo foi atingido; caso contrrio,
ela devolve falso (0). O exemplo abaixo mostra a leitura de um arquivo texto at que o
seu final seja atingido.

Exemplo

ch=fgetc(arq);
while(!feof(arq))
{
ch=fgetc(arq);
}

Obviamente, podemos aplicar esse mtodo tanto para arquivos texto como para
arquivos binrios.

Vous aimerez peut-être aussi