-
Cadeias de caracteres (strings)
Uma string (ou cadeia de caracteres) na linguagem C um vetor de
caracteres em que o caractere nulo ('\0') interpretado como fim da
parte relevante do vetor. Exemplo:
char *s;
s = malloc( 10 * sizeof (char));
s[0] = 'A';
s[1] = 'B';
s[2] = 'C';
s[3] = '\0';
s[4] = 'D';
Depois da execuo desse fragmento de cdigo, o vetor s[0..3] contm
a string ABC. O caractere nulo marca o fim dessa string. A poro
s[4..9]do vetor ignorada.
Comprimento e endereo
O comprimento (= length) de uma string o seu nmero de
caracteres, sem contar o caractere nulo final.
O endereo de uma string o endereo do seu primeiro caractere, da
mesma forma que o endereo de um vetor o endereo de seu primeiro
elemento.
Em discusses informais, usual confundir uma string com o seu
endereo. Assim, a expresso considere a string s deve ser entendida
comoconsidere a string cujo endereo s.
Strings constantes
Para especificar uma string constante, basta embrulhar uma
sequncia de caracteres num par de aspas duplas. O caractere
nulo
-
final fica subentendido. Por exemplo, "ABC" uma string constante
e o fragmento de cdigo
char *s;
s = "ABC";
equivalente ao que aparece na introduo desta pgina (exceto pelo
fato de que a string "ABC" ocupa apenas 4 bytes na memria).
O primeiro argumento das funes printf e scanf, quase sempre uma
string constante. Por exemplo,
scanf( "%d", &n);
printf( "O valor de n %d", n);
Exerccios 1
1. Qual o efeito do seguinte fragmento de cdigo?
2. char *s;
3. s = "ABC";
4. printf( "%s\n", s);
5. O que h de errado com a seguinte variante do exerccio
anterior?
6. char s[20];
7. s = "ABC";
8. printf( "%s\n", s);
Exemplo: contagem de vogais
A seguinte funo conta o nmero de vogais (no acentuadas) em uma
string:
int contaVogais( char s[]) {
int numVogais, i;
char *vogais;
vogais = "aeiouAEIOU";
numVogais = 0;
-
for (i = 0; s[i] != '\0'; ++i) {
char ch = s[i];
int j;
for (j = 0; vogais[j] != '\0'; ++j) {
if (vogais[j] == ch) {
numVogais += 1;
break;
}
}
}
return numVogais;
}
Exerccios 2
1. Qual a diferena entre "A" e 'A'?
2. Qual a diferena entre "mno" e "m\no"? Qual a diferena entre
"MNOP" e "MN0P"? Qual a diferena entre "MN\0P" e "MN0P"?
3. Escreva uma funo que receba um caractere c e devolva uma
string cujo nico caractere c.
4. Escreva uma funo que receba uma string e imprima uma tabela
com o nmero de ocorrncias de cada caractere na string. Escreva um
programa para testar a funo.
5. PALNDROMOS. Escreva uma funo que decida se uma string ou no
um palndromo (ou seja, se o inverso da string igual a ela). Escreva
um programa para testar a funo.
6. Escreva uma funo que receba strings s e t e decida se s
segmento de t (ou seja, se s pode ser obtida apagando um nmero
arbitrrio de elementos do incio de t e um nmero arbitrrio de
elementos no fim de t). Escreva um programa que use a funo para
contar o nmero de ocorrncias de uma string s em uma string t.
7. Escreva uma funo que receba uma string e substitua cada
segmento de dois ou mais espaos em branco por um s espao em
branco.
8. Escreva uma funo que receba uma string de 0s e 1s, interprete
essa string como um nmero natural em notao binria e devolva o valor
desse nmero.
-
A biblioteca string
A biblioteca padro string da linguagem C contm vrias funes de
manipulao de strings. Para usar essas funes, o seu programa deve
incluir
#include
o arquivo-interface string.h. Eis as funes mais importantes da
biblioteca string:
A funo strlen (o nome uma abreviatura de string length) recebe
uma string e devolve o seu comprimento. O cdigo dessa funo poderia
ser escrito assim:
unsigned int strlen( char *s) {
int k;
for (k = 0; s[k] != '\0'; ++k) ;
return k;
}
A funo strcpy (o nome uma abreviatura de string copy) recebe
duas strings e copia a segunda (inclusive o caractere nulo final)
para o espao ocupado pela primeira. O contedo original da primeira
string perdido. Antes de chamar a funo, o programador deve
certificar-se de que o espao alocado para a primeira string
suficiente para acomodar a cpia da segunda. (Buffer overflow uma
das mais comuns origens de bugs de segurana!) O cdigo dessa funo
poderia ser escrito assim:
void strcpy( char *s, char *t) {
int i;
for (i = 0; t[i] != '\0'; ++i)
s[i] = t[i];
s[i] = '\0';
}
-
(Na verdade, a funo strcpy no do tipo void. Ela do tipo char * e
devolve o seu primeiro argumento. Isso til em algumas situaes, mas
em geral os usurios s esto interessados no efeito da funo e no no
que ela devolve.)
A funo strcpy pode ser usada da seguinte maneira para obter um
efeito semelhante ao do exemplo no incio desta pgina:
char s[10];
strcpy( s, "ABC");
A funo strcmp (o nome uma abreviatura de string compare) recebe
duas strings e compara as duas lexicograficamente. Ela devolve um
nmero negativo se a primeira string for lexicograficamente menor
que a segunda, devolve 0 se as duas strings so iguais e devolve um
nmero positivo se a primeira string for lexicograficamente maior
que a segunda.
Embora os parmetros da funo sejam do tipo char *, a funo se
comporta como se eles fossem do tipo unsigned char *. Assim, por
exemplo, "bb" considerada lexicograficamente menor que "bb" e "ba"
considerada lexicograficamente menor que "b". O cdigo da funo
poderia ser escrito assim:
int strcmp( char *s, char *t) {
int i;
unsigned char usi, uti;
for (i = 0; s[i] == t[i]; ++i)
if (s[i] == '\0') return 0;
usi = s[i]; uti = t[i];
return usi - uti;
}
Convm lembrar que o valor da expresso usi - uti calculado em
aritmtica int (e no mdulo 256).
-
A ordem lexicogrfica a que nos referimos acima anloga ordem das
palavras em um dicionrio. Ela se baseia na ordenao dos caracteres
estabelecida na tabela ISO8859-1, da mesma forma que a ordem das
palavras em um dicionrio se baseia na ordenao usual das letras no
alfabeto. Para comparar duas strings s e t, procura-se a primeira
posio, digamos k, em que as duas strings diferem. Se s[k]vem antes
de t[k] na tabela ISO ento s lexicograficamente menor que t. Se k
no est definido ento s e t so idnticas ou uma prefixo prprio da
outra; nesse caso, a string mais curta lexicograficamente menor que
a mais longa.
Poderamos tratar strings como um novo tipo-de-dados introduzindo
a definio
typedef char *string;
Feito isso, todas as ocorrncias de char * podem ser trocadas por
string.
Exerccios 3
1. Qual a diferena entre as expresses strcpy( s, t) e s = t?
2. Qual a diferena entre as expresses if (strcmp( s, t) < 0)
e if (s < t)?
3. Discuta as diferenas entre os trs fragmentos de cdigo a
seguir:
4. char a[8], b[8];
5. strcpy( a, "abacate");
6. strcpy( b, "banana");
7. char *a, *b;
8. a = malloc( 8); strcpy( a, "abacate");
9. b = malloc( 8); strcpy( b, "banana");
10. char *a, *b;
11. a = "abacate";
12. b = "banana";
13. O que h de errado com o seguinte trecho de cdigo?
-
14. char b[8], a[8];
15. strcpy( a, "abacate");
16. strcpy( b, "banana");
17. if (a < b)
18. printf( "%s vem antes de %s no dicionrio", a, b);
19. else
20. printf( "%s vem depois de %s no dicionrio", a, b);
21. O que h de errado com o seguinte trecho de cdigo?
22. char *b, *a;
23. a = "abacate";
24. b = "banana";
25. if (a < b)
26. printf( "%s vem antes de %s no dicionrio", a, b);
27. else
28. printf( "%s vem depois de %s no dicionrio", a, b);
29. O que h de errado com o seguinte trecho de cdigo?
30. char *a, *b;
31. a = "abacate";
32. b = "amora";
33. if (*a < *b)
34. printf( "%s vem antes de %s no dicionrio", a, b);
35. else
36. printf( "%s vem depois de %s no dicionrio", a, b);
37. Escreva uma funo que receba uma string s e um inteiro no
negativo i e devolva o (i-1)-simo caractere de s, ou seja, o
caractere s[i].
38. Escreva uma funo que receba uma string s e inteiros no
negativos i e j e devolva o segmento s[i..j]. Sua funo no deve
alocar novo espao e pode destruir a string s que recebeu.
-
39. Escreva uma funo que receba strings s e t e decida se s um
segmento de t. Escreva um programa que use a funo para contar o
nmero de ocorrncias de uma string s em uma string t.
40. Escreva uma funo que receba uma string s e um caractere c e
devolva o ndice da primeira posio de s que igual a c. Agora faa uma
verso mais completa da funo, que procura c a partir de uma dada
posio i.
41. Escreva uma funo que receba strings x e s e devolve o ndice
da posio a partir da qual x ocorre em s.
Matrizes e Vetores
Introduo
Uma matriz uma coleo de variveis de mesmo tipo, acessveis
com um nico nome e armazenados contiguamente na memria.
A individualizao de cada varivel de um vetor feita atravs do
uso
de ndices.
Os Vetores so matrizes de 1 s dimenso.
Declarao de Matrizes
int Vetor[5]; // declara um vetor de 5
posies
int Matriz[5][3]; // declara uma matriz de 5
linhas e 3 colunas
Acesso aos elementos do vetor
Para acessar os elementos de um vetor usa-se ndices. O ndice
define
a posio da varivel dentro do vetor.
-
Em todos os vetores tem o primeiro elemento na posio
0(zero).
Assim, se tomarmos "K" como sendo o tamanho do vetor a ltima
posio a
de ndice "K-1"
Vetor[0] = 4; // Coloca 4 na primeira posio de "Vetor"
Vetor[4] = 8; // Coloca 8 na ltima posio
de "Vetor"
Exemplos com Vetores
int Vetor[5]; // declara um vetor de 5 posies
int Matriz[5][3]; // declara uma matriz de 5
linhas e 3 colunas
Vetor[0] = 9; // coloca 9 na primeira
posio do vetor
Vetor[4] = 30 // coloca 30 na ltima posio
do vetor
Matriz[0][1] = 15; // coloca 15 na clula
que est na primeira linha
// e na segunda coluna da
matriz
Preenchimento de um vetor com um dado
for(i=0; i
-
#define TAM_MAX 10
double VetReais[TAM_MAX];
for(i=0; i
- for(i=0; i
-
if Vet1[i] > Vet1[PosMaior]
PosMaior = i; // acha a posio do maior
for(j=0; j
-
{
int Notas[TAM_MAX];
ImprimeVet(TAM_MAX, Notas); // Passa o vetor
'Notas' como
// parmetro
}
A passagem dos elementos de um vetor como parmetro idntica
passagem de uma varivel. Ou seja, quando a passagem for por
valor usa-
se vet[i] e quando for por referncia usa-se&vet[i].
void Imprime (int N) // funo com um parmetro
por valor
{
printf("%d", N);
}
void Incr (int *N) // funo com um parmetro por
referncia
{
*N = *N + 1;
}
void Incr (int *N)
{
int i;
for (i=0; i< Tam; i++)
{
Incr(&Vet[i]); // Note que preciso colocar o
'&' antes
// de Vet[i] pois a funo
'Incr' espera um
// parmetro por
REFERNCIA
Imprime(Vet[i]); // Note que NO se deve colocar
nada antes
// de Vet[i] pois a
funo 'Imprime' espera um
// parmetro por VALOR
}
}
-
Exemplos com Matrizes
#define NLIN 10
#define NCOL 10
int Matriz[NLIN][NCOL];
Preencher uma matriz com um dado
for(i=0; i < NLIN; i++)
for(j=0; j < NCOL; j++)
Matriz[i][j] = 30;
Somar um nmero a uma linha/coluna de uma matriz
void SomaValorNaColuna(int Valor, int
Matriz[NLIN][NCOL], int Coluna)
{
for(i=0; i < NLIN; i++) // para cada linha de
'Coluna'
Matriz[i][Coluna] = Matriz[i][Coluna] + 30;
}
Criar uma matriz identidade
void CriaIdent(int Colunas, int linhas, int
Matriz[NLIN][NCOL])
{
}
Criar uma matriz transposta
void CriaTransp(int Colunas, int linhas,
int Matriz[NLIN][NCOL], int
Trasposta[NLIN][NCOL])
{
}
Cria uma rotina que some duas matrizes
void SomaMatrizes(int Colunas, int linhas,
int MatrizA[NLIN][NCOL], int
-
MatrizB[NLIN][NCOL],
int MatrizSOMA[NLIN][NCOL])
{
}
Cria uma rotina que multiplique duas matrizes
void MultMatrizes(int Colunas, int linhas,
int MatrizA[NLIN][NCOL], int
MatrizB[NLIN][NCOL],
int MatrizMULT[NLIN][NCOL])
{
}
Exerccios
1. Dada uma seqncia de n nmeros, imprimi-la na ordem inversa
da
leitura.
#include
#include
#include
#define MAX 100
int main() {
int n, i, v[MAX];
printf("Digite o comprimento da seqncia: ");
scanf("%i", &n);
printf("Digite uma seqncia com %d nmeros inteiros: ", n);
for (i = 0; i < n; i++)
scanf("%i", &v[i]);
for (i = n-1; i >= 0; i--)
printf("%d ", v[i]);
printf("\n");
system(pause);
}