Você está na página 1de 13

1/13

6
Bibliotecas estandardizadas




Sumrio:

Introduo
Funes de manipulao de strings <string.h>
Funes de ordenao <stdlib.h>
Funes matemticas <math.h>
Funes de entrada/ sada de alto-nvel <stdio.h>
Funes de entrada/ sada de baixo-nvel <stdio.h> <fcntl.h>
Funes de memria <memory.h>
Funes de temporizao <sys/ types.h> <time.h>




Este captulo objectiva fazer:

reviso e aprofundamento da linguagem C;
aquisio de competncias bsicas na utilizao de bibliotecas de C/Unix.

NOTA: Este captulo no ser alvo de debate ou prtica nas aulas. S serve para
revises de matria supostamente leccionada em semestres anteriores.


2/13
Introduo


Existe uma relao estreita entre a linguagem C e o sistema Unix/Linux . O sistema operativo Unix/Linux est
escrito em grande parte em C e a histria do SO Unix tambm a histria da linguagem C.

A utilizao das bibliotecas estandardizadas aquando da unificao (linkage) do cdigo objecto requer a
incluso prvia e criteriosa dos seguintes ficheiros (.h) nos ficheiros fonte:

1. string.h (strings)
2. stdlib.h (ordenao)
3. math.h (matemtica)
4. stdio.h (I/O)
5. memory.h (memria)
6. time.h (tempo)
7. unistd.h (acesso a ficheiros e directorias)

A incluso dum ficheiro (.h) faz-se atravs da directiva #i ncl ude ao pr-processador.
Por exemplo, #i ncl ude <st di o. h> faz a incluso dos prottipos das funes de entrada/sada cujo cdigo
objecto se encontra na biblioteca libC, que a biblioteca estandardizada da linguagem C.

A biblioteca libC a nica que no precisa ser explicitamente especificada durante a compilao. O cdigo
objecto de libC automaticamente unificado com o cdigo objecto de qualquer programa escrito em C.
Normalmente o cdigo est contido numa biblioteca esttica libc.a e outro dinmica libc.so

A utilizao de qualquer outra funo pertencente a outra biblioteca torna obrigatria a especificao da
respectiva biblioteca no acto da compilao. Por exemplo, se um programa chamado myp. c usa funes
matemticas, ento h que fazer:
a incluso do ficheiro mat h. h neste programa atravs da directiva #include , i.e. a linha de cdigo
#i ncl ude <mat h. h>tem de ser escrita no incio de myp. c, e depois
explicitar a biblioteca libm no comando de compilao, i.e.
$ cc myp.c o myp lm
onde lm uma indicao para o unificador (linker) fazer a unificao do cdigo objecto do programa
com a bliblioteca libm.

Existe um manual on-line para as funes da linguagem C. Por exemplo, para saber a informao disponvel
sobre a funo r and, s necessrio escrever o seguinte na linha de comando do Bash :
$ man rand

Algumas funes existe duas ou mais vezes nas paginas de manual por exemplo write (bash shell) e write
(low-level I/O da linguagem C). As vezes necessrio especificar o manual que pretende pesquisar. Compare
os seguintes por exemplo

$ man write (bash shell)
$ man 2 write (low level sytem calls)
$ man 3 fwrite (c standard library) ser equivalente a man fwrite porque fwrite ocorre
apenas uma vez nas paginas manual.

Ou mesmo acontece com printf

$ man printf (bash shell)
$ man 2 printf (no existe)
$ man 3 printf (c standard library
3/13
Strings <string.h>

O cdigo objecto das funes declaradas em st r i ng. h encontra-se na biblioteca libC.

Uma string uma sequncia de zero ou mais caracteres que termina com o carcter NULL (\0). Uma
string representado por um vector (array) unidimensional de caracteres, um apontador para uma zona
de memria que contm caracteres ASCII.

Funes bsicas:

Compara st r i ng1 com st r i ng2:
i nt strcmp( const char *st r i ng1, const char *st r i ng2)

Compara n caracteres do st r i ng1 com st r i ng2:
i nt strncmp( const char *st r i ng1, const char *st r i ng2, i nt n)

Copia st r i ng2 para st r i ng1:
char *strcpy( const char *st r i ng1, const char *st r i ng2)

Devolve mensagem de erro correspondente ao nmero er r num:
char *strerror( i nt er r num)

Determina o comprimento duma string:
i nt strlen( const char *st r i ng)

Concatena n caracteres da st r i ng2 st r i ng1:
char *strncat( const char *st r i ng1, char *st r i ng2, si ze_t n)

Funes de pesquisa:

Determina a primeira ocorrncia do carter c na string:
char * strchr( const char *st r i ng, i nt c)

Determina a ltima ocorrncia do carter c na string:
char * strrchr( const char *st r i ng, i nt c)

Localiza a primeira ocorrncia da substring s2 na string s1:
char *strstr( const char *s1, const char *s2)

Funes de Repartio

String Tokenizer . Divide uma string numa sequencia de sub-strings denominados tokens. A diviso
feita usando qualquer dos caracteres dos delimiters

char * st r t ok ( char * st r , const char * del i mi t er s ) ;

Exemplo
char *str1 ="ola esta tudo bem?";
char *t1;
for ( t1 =strtok(str1," "); t1 !=NULL; t1 =strtok(NULL, " ") )
printf("token: %s\n",t1);

Explicao do ciclo for :
Inicializao chamada da funo strtok( ) e carregamento com o string st r 1
Terminao do ciclo quando t1 igual a NULL
Continuao : os tokens do str1 so atribudos ao apontador t1 com uma chamada a strtok() com o primeiro
argumento NULL
4/13

Exerccio 6.1 Faa uma listagem do ficheiro <st r i ng. h>

Exerccio 6.2 Imprima o ficheiro <st r i ng. h>

Exerccio 6.3 Faa um programa que:

leia duas strings x e y;
faa a sada dos respectivos comprimentos;
faa a sada da string x est dentro de y, no caso de x ser uma sub-string de y;
faa a sada da sub-string de y que antecede x, no caso de x ser uma sub-string de y.

Exemplo:
Input: x=abc
y=lisboaabc123
Output: comprimento x=4 comprimento y=12
x est dentro de y sub-string que anteced: lisboa


Ordenao <stdlib.h>


O cdigo objecto das funes declaradas em st dl i b. h encontra-se na biblioteca libC, a qual
implementa algoritmos de pesquisa e ordenao tais como, por exemplo, o quicksort e o bublesort.

O algoritmo quicksort tem o seguinte prottipo:

voi d qsort( voi d *base, si ze_t nel em, si ze_t wi dt h,
i nt ( _USERENTRY *f cmp) ( const voi d *el em1, const voi d *el em2) ) ;

onde:

base aponta para o elemento base (0-simo) da tabela a ordenar;
nelem o nmero de elementos da tabela;
width o tamanho em bytes de cada elemento da tabela;
fcmp a funo de comparao que obrigatoriamente usada com a conveno _USERENTRY.
Fcmp aceita dois argumentos, elem1 e elem2, cada um dos quais um aponatdor para um elemento
da tabela. A funo de comparao compara os dois elementos apontados e devolve um inteiro como
resultado, a saber:
*elem1 < *elem2 fcmp devolve um inteiro < 0
*elem1 == *elem2 fcmp devolve 0
*elem1 > *elem2 fcmp devolve um inteiro > 0

Exemplo da Utilizao:
Seja x um vector de 30 inteiros e cmp uma funo de compariso, o simples <. Para chamar o qsort para
ordenar os dez elementos do vector entre as posies 10..20
int x [30]
int cmp( void *a, void *b) { r et ur n ( ( i nt *) a < ( i nt *) b ) ; }

qsor t ( &x[ 10] , 10, si zeof ( i nt ) , cmp) ;







5/13
Exemplo 6.1:

Escreva e execute o pequeno programa a seguinte para mostrar o funcionamento do quicksort.

#i ncl ude <st di o. h>
#i ncl ude <st dl i b. h>
#i ncl ude <st r i ng. h>

i nt sor t _f unct i on( const voi d *a, const voi d *b) ;
char l i st [ 5] [ 4] ={cat , car , cab, cap, can};


i nt mai n( voi d)
{
i nt x;

f or ( x=0; x<5; x++) pr i nt f ( %s\ n, l i st [ x] ) ; / * ant es */

qsort( ( voi d*) l i st ,
5,
si zeof ( l i st [ 0] ) ,
sor t _f unct i on
) ;

f or ( x=0; x<5; x++) pr i nt f ( %s\ n, l i st [ x] ) ; / * depoi s */

r et ur n 0;
}

i nt sor t _f unct i on( const voi d *a, const voi d *b)
{
r et ur n( st r cmp( ( char *) a, ( char *) b) ;
}


Exerccio 6.4 Faa um programa que:
leia dinamicamente um vector de n inteiros;
preencha este vector com nmeros aleatrios, para o que deve usar a funo r and;
ordene o vector usando a funo qsor t ;
e, finalmente, mostre o vector ordenado no cran.
6/13
Matemtica <math.h>

A utilizao de qualquer funo matemtica da biblioteca libm num dado programa mpg. c requer a
declarao da directiva #i ncl ude <mat h. h>em mpg. c.

Alm disso, necessrio incluir explicitamente a biblioteca libm na compilao do programa mpg. c
de modo a que a unificao (linkage) das funes matemticas usadas em mpg. o e o seu cdigo
existente em libm se concretize. Isto , na linha de comando do Unix deve escrever-se o seguinte:

$ cc o mpg mpg.c lm

absolutamente essencial no esquecer a incluso do ficheiro <mat h. h>no programa mpg. c. Caso
contrrio, o compilador no servir de grande ajuda.


Algumas funes:

Calcula o coseno dum ngulo em radianos:
doubl e cos( doubl e x)

Calcula o ngulo do coseno de x:
doubl e acos( doubl e x)

Calcula o ngulo da tangente de y/x:
doubl e atan2( doubl e y, doubl e x)

Calcula o valor inteiro mais pequeno que excede x:
doubl e ceil( doubl e x)


Algumas constantes pr-definidas:

HUGE O valor mximo dum nmero de vrgula flutuante com preciso simples.
M_E A base do logaritmo natural (e).
M_LOG2E O logaritmo de base 2 de e.
M_LOG10E O logaritmo de base 10 de e.
M_LN2 O logaritmo natural de 2.
M_LN10 O logaritmo natural de 10.
M_PI Valor de .



Exerccio 6.5
Edite, compile e execute um programa que utilize algumas funes e constantes matemticas.

7/13
I/ O de alto-nvel <stdio.h>

Bibliografia utilizada:
Cap.12 (P. Darnell e P. Margolis. C: a software engineering approach)
Cap. 5 (W. Stevens. Advanced Programming in the Unix environment)
Caps. 7, 13 (B. Forouzan, R. Gilberg. Computer Science: a structured programming approach using C)

As funes descritas nesta subseco so conhecidas como funes estandardizadas (ou de alto-
nvel) de entrada/sada. So funes de entrada/sada com entrepsito (ou buffer). Isto significa que a
escrita/leitura feita primariamente para/do entrepsito (ou buffer), e s depois ocorre a escrita/leitura
para/a partir de um ficheiro a partir/para o entrepsito (ou buffer).

A entrada/sada directa (ou de baixo nvel) de dados para/de um ficheiro feita por funes de
entrada/sada sem entrepsito. Cada funo directa de entrada/sada (e.g. r ead e wr i t e) invoca uma
chamada ao sistema.

O ficheiro <stdio.h>

A utilizao de qualquer funo estandardizada de I/O obriga incluso do ficheiro st di o. h no
ficheiro (.c) onde a funo est a ser usada.
O ficheiro st di o. h contm:
Os cabealhos (prottipos ou declaraes) de todas as funes estandardizadas de I/O.
A declarao da estrutura FILE.
Vrias macros, entre as quais se conta:
a) st di n (dispositivo estandardizado de entrada)
b) st out (dispositivo estandardizado de sada)
c) st der r (dispositivo estandardizado de erro)
d) EOF (marcador de end-of-line)

Entreposio (buffering)

Um entrepsito (ou buffer) uma rea de memria temporria para ajudar a transferncia de dados
entre dispositivos ou programas que operam a diferentes velocidades. Alm disso, qualquer entrepsito
usado pelas funes estandardizada de I/O permite-nos usar um nmero mnimo de chamadas r ead e
wr i t e.

Ou seja, um entrepsito no mais do que uma rea de memria onde os dados so armazenados
temporariamente antes de serem enviados para o seu destino. Entreposio um mecanismo mais
eficiente de transferncia de dados porque permite a um sistema operativo minimizar o nmero de
acessos ao dispositivos de I/O.

De facto, estremamente importante reduzir o mais possvel o nmero de operaes fsicas de
escrita e leitura, dado que, por contraposio memria, os dispositivos de memria secundria (e.g.
discos rgidos e cassetes de fita magntica) so bastante lentos.

Todos os sistemas operativos usam entrepsitos (buffers) para ler/escrever de/para dispositivos de
I/O. Isto significa que qualquer sistema operativo acede a dispositivos de I/O em fatias (chunks) de
tamanho fixo, chamados blocos (blocks). Normalmente, um bloco tem 512 ou 1024 octetos (bytes).
Portanto, mesmo se ns quisermos ler s um carcter a partir dum ficheiro, o sistema operativo l o bloco
inteiro no qual o carcter se encontra. Isto parece no ser muito eficiente, mas imagine-se que se
pretendia ler 1000 caracteres dum ficheiro. No caso da I/O sem entrepsito, o sistema ter de realizar
1000 operaes de procura e leitura. Em contrapartida, com I/O com entrepsito, o sistema l um bloco
inteiro para a memria, e depois procura cada carcter em memria se for necessrio. Isto poupa 999
operaes de I/O.


8/13

Streams

A linguagem C no faz qualquer distino entre dispositivos tais como um terminal (monitor e
teclado) ou um controlador de fita magntica e ficheiros lgicos no disco rgido, represente tudo como um
ficheiro (ver directrio /proc num sistema Linux)

A independncia relativamente ao dispositivo de I/O, portanto a virtualizao do I/O, consegue-se
usando streams. Cada stream est associado a um ficheiro ou dispositivo. Um stream consiste numa
sequncia ordenada de bytes. Um stream pode ser visto como um array unidimensional de caracteres.
Ler/escrever de/para um ficheiro ou dispositivo faz-se lendo/escrevendo de/para a corrente que lhe est
associada.

Para realizar operaes estandardizadas de I/O, h que associar um stream a um ficheiro ou a um
dispositivo. Isto faz-se atravs da declarao dum ponteiro para um estrutura do tipo FILE. A estrutura
FILE contm vrios campos:
nome do ficheiro,
descritor do ficheiro
modo de acesso,
bloco de memoria (buffer)
ponteiro para o prximo carcter na corrente.

Streams estandardizados e redireccionamentos

H trs streams que so abertos automaticamente para qualquer programa:
st di n (entrada estandardizada, que por defeito o teclado)
st out (sada estandardizada, que por defeito o cran)
st der r (sada estandardizada de erros, que por defeito o cran)

Os streams estandardizados podem ser redireccionados para outros ficheiros ou dispositivos.
H duas formas de fazer um redireccionamento dum stream:
atravs de opes em comandos Unix,
atravs dos operadores <, <<, >, >> em comandos Unix.

Por exemplo:
a) comando > f i ch redirecciona a sada estandardizada para o ficheiro f i ch
b) comando >> f i ch redirecciona e concatena a sada estandardizada ao o ficheiro f i ch
c) comando >& f i ch redirecciona a sada estandardizada de erros para o ficheiro f i ch
d) comando >>& f i ch redirecciona e concatena a sada estandardizada de erros ao o ficheiro f i ch
e) comando < f i ch redirecciona a entrada estandardizada para o ficheiro f i ch

Funes bsicas de I/ O:

L um carcter do st di n:
i nt getchar( voi d)

Escreve um carcter para o st dout :
i nt putchar( char ch)

L uma string de caracteres (terminada por um newline) a partir do st di n e coloca-a em s,
substituindo o newline por um carcter nulo (\0):
char *gets( char *s)

Funes de sada e entrada formatadas:
i nt printf( const char *format, )
i nt scanf( const char *format, )

9/13

Funes de I/ O para/ de ficheiros:

Para usar um ficheiro h que primeiro abri-lo com a funo:

Abre um ficheiro:
FI LE *fopen( char *name, char *mode)

O argumento name o nome do ficheiro em disco que se pretende aceder. O argumento mode indica
o tipo de acesso ao ficheiro.

H dois conjuntos de modos de acesso. O primeiro serve para streams de texto, ao passo que o
segundo adequado para streams binrias.

Os modos bsicos para streams textuais so os seguintes:
r (read) leitura
w (write) escrita
a (append) concatenao

Os modos binrios so exactamente os mesmos, excepto que um b tem de ser concatenado direita
do nome do modo. Temos assim:
rb (read) leitura
wb (write) escrita
ab (append) concatenao

Exemplo 6.2:

#i ncl ude <st def . h>
#i ncl ude <st di o. h>

i nt mai n( voi d)
{
FI LE *st r eam;

st r eam= f open( t est . t xt , r ) ;
i f ( st r eam== NULL)
pr i nt f ( Er r o na aber t ur a do f i chei r o t est . t xt \ n) ;
exi t ( 1) ;
}


Outras funes de I/ O para/ de ficheiros:

fclose() Fecha um stream associado a um ficheiro;
fgetc() L um carcter a partir dum stream;
fgets() L uma string a partir dum stream;
fputc() Escreve um carcter para um stream;
fputs() Escreve uma string para um stream;
fscanf()O mesmo que scanf (), mas agora os dados so lidos a partir dum dado ficheiro;
fprintf()O mesmo que pr i nt f (), mas agora os dados so escritos para um dado ficheiro;
fflush()Transcreve os dados para o ficheiro associado com um dado stream, esvaziando-o;
fread() L um bloco de dados binrios a partir dum stream.





10/13
Inquiries ao estado duma stream

Existem algumas funes para saber o estado dum ficheiro, nomeadamente:

Devolve o valor t r ue se a corrente est na posio EOF:
i nt feof( FI LE *st r eam)

Devolve o valor t r ue se um erro ocorreu:
i nt ferror( FI LE *st r eam)

Limpa a indicao de erro que tenha ocorrido anteriormente:
i nt clearerr( FI LE *st r eam)

Devolve o descritor inteiro do ficheiro associado com o st r eam:
i nt fileno( FI LE *st r eam)


Granularidade da I/ O :

Uma vez aberto um stream, pode escolher-se entre trs tipos diferentes de I/O sem formatao:
I/ O carcter-a-carcter. Um carcter de cada vez lido ou escrito, tal que as funes
estandardizadas de I/O manipulam a entreposio (ou buffering), no caso de o stream ser entreposto
(ou buffered).
I/ O linha-a-linha. Se quisermos ler ou escrever uma linha de cada vez, ento usamos as funes
f get s e f put s. Cada linha termina com um carcter newl i ne. Alm disso, temos que especificar o
comprimento mximo da linha quando a funo f get s chamada.
I/ O directa. suportada pelas funes f r ead e f wr i t e. Uma operao de I/O directa permite ler
ou escrever um conjunto de objectos, cada um dos quais tem um tamanho que deve ser especificado.
Estas duas funes so muitas vezes aplicadas a ficheiros binrios, tal que cada operao de I/O
realiza a leitura ou a escrita duma estrutura.

11/13

Memria <memory.h>

As operaes de memria esto implementadas atravs de funes cujos cabealhos ou prottipos
esto declarados no ficheiro string.h. , no entanto, conveniente considerar o ficheiro memory.h onde
tradicionalmente as funes seguintes foram especificadas..

Algumas funes de memria:

Procura :
voi d *memchr( voi d *s, i nt c, si ze_t n)

Compara dois blocos de memria com n bytes de tamanho :
i nt memcmp( voi d *s1, voi d *s2, si ze_t n)

Copia um bloco de memria com n bytes de tamanho :
Voi d *memcpy( voi d *dest , voi d *sr c, si ze_t n)

Move um bloco de memria com n bytes de tamanho :
i nt memmove( voi d *dest , voi d *sr c, si ze_t n)

Inicializa um bloco de memria de n bytes com o carcter c :
i nt memset( voi d *s, i nt c, si ze_t n)

Exemplo 6.3:
O seguinte exemplo ilustra a utilizao da funo memcpy.

#include <stdio.h>
#include <memory.h>

int x[]={5,4,3,2,1};
int y[10]={1,2,3,4,5,6,7,8,9,10};
int *z;
int i;

main()
{
for (i=0; i<10; i++) /* a situacao ANTES */
printf(%d,y[i]);
putchar(\n);
z=(int *)memcpy(y+1, x, sizeof(x));

z=y;
for (i=0; i<10; i++) /* a situacao DEPOIS */
printf(%d,*z++);
putchar(\n);
for (i=0; i<10; i++)
printf(%d,y[i]);
putchar(\n);
return 0;
}

Exerccio 6.5:
Escreva uma funo que inverta o contedo dum bloco de n octetos de memria. Isto significa existe uma
troca de valores entre o 0-simo e o n-simo octeto, entre o 1-simo e o (n-1)-simo octetos, etc. De
seguida, escreva um programa que usa aquela funo para inverter uma cadeia de caracteres.

12/13
Temporizao <time.h>

As funes de temporizao so teis por vrias razes, nomeadamente para saber a data e a hora
correntes, medir o tempo de execuo duma operao, inicializar geradores de nmeros aleatrios, etc.

Funes bsicas:

Devolve o tempo em segundos desde 00:00:00 GMT, J an 1, 1970 :
t i me_t time( t i me_t *t l oc)

Preenche uma estrutura apontada por tp de acordo com a definio em <sys/ t i meb. h> :
i nt ftime( st r uct t i meb *t p)

Converte um long integer referente ao tempo do relgio numa string de 26 caracteres na forma Sun
Sep 16 01:03:52 1999 :
ctime( )

t i me_t provavelmente um t ypedef para um unsigned l ong i nt . A definio encontra-se no
ficheiro <time.h>

A estrutura t i meb tem 4 campos:

struct timeb {
time_t time; /* em segundos */
unsigned short millitm; /* ate 1000 milisegundos para intervalos mais precisos */
short timezone; /* em minutos a oeste de Greenwich */
short dstflag; /* se flag nao-nula, indica que a mudana de hora aplicvel */
}

Exemplo 6.4:
Um programa para medir o tempo duma operao.

#include <stdio.h>
#include <sys/types..h>
#include <time.h>

main()
{
long i;
time_t t1, t2;
time(&t1);
for (i=1; i<=100000; i++)
printf(%ld %ld %ld %f\n,i,i*i, i*i*i, (float)i*i*i);
time(&t2);
printf(Tempo para 1000 quadrados, cubos e duplos quadrados=%ld segundos\n,(long)(t2-t1));
}
13/13
Exemplo 6.5:
Um programa para inicializar um gerador de nmeros aleatrios.

#include <stdio.h>
#include <stdlib.h>
#include <sys/types..h>
#include <time.h>

main()
{
int i;
time_t t1=0;
printf(5 numeros aleatorios sem seed\n, (int)t1);

for (i=0;i<5;++i)
printf(%d,rand());
printf(\n\n);

time(&t1);
srand((long)t1); /* use tempo em segundos para activar seed */
printf(5 numeros aleatorios (Seed = %d):\n, (int)t1);
for (i=0;i<5;++i)
printf(%d,rand());

printf(\n\n Agora corre o programa outra vez\n);
}

Exerccio 6.6:
Altere o penltimo programa (6.5) para determinar o tempo utilizado pela CPU (veja cl ock no manual
on-line).

Exerccio 6.7:
Veja tambm o ficheiro time.h. Escreva um programa que devolva a data e hora actuais, assim como o
tempo que falta at ao incio do prximo fim-de-semana (sexta-feira, 19.00).

Você também pode gostar