Você está na página 1de 9

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 <string.h>
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-dedados 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]; //
int Matriz[5][3];
linhas e 3 colunas
Vetor[0] = 9;
posio do vetor
Vetor[4] = 30
do vetor

declara um vetor de 5 posies


// declara uma matriz de 5
// coloca 9 na primeira
// coloca 30 na ltima posio

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<5; i++)
for(i=0;
i<=4; i++)
Vetor[i] = 30;
Vetor[i]
= 30;
Colocar os nmeros de 1 a 5 em Vetor
for(i=0; i<5; i++)
Vetor[i] = i+1;
Colocar os nmeros de 5 a 1 em Vetor
for(i=0; i<5; i++)
Vetor[i] = 5-i;
Uso de Constantes para definir o tamanho de um vetor
#define TAM_MAX 10
double VetReais[TAM_MAX];
for(i=0; i<TAM_MAX; i++)
VetReais[i] = TAM_MAX - i; // coloca
5,4,3,2,1 no vetor
Copiar os dados de um vetor para outro
#define TAM_MAX 10
double VetReais[TAM_MAX], Copia[TAM_MAX];
for(i=0; i<TAM_MAX; i++)
VetCopia[i] = VetReais[i]; // Copia os dados
de um vetor
// para outro
Copiar os dados de um VET1 para as primeiras 5 posies de COPIA e
VET2 para as outras 5
#define TAM_MAX 10
// Note que a declarao do vetor "Cpia" cria o
dobro de posies
double Vet1[TAM_MAX], Vet2[TAM_MAX],
Copia[TAM_MAX*2];
for(i=0; i<TAM_MAX; i++)
VetCopia[i] = Vet1[i]; // Copia os dados do
primeiro vetor
for(i=0; i<TAM_MAX; i++)
segundo vetor

// Copia os dados do

VetCopia[i+TAM_MAX] = Vet2[i];
// ****** Pergunta: Como fazer a cpia usando um
nico comando for ?
Leitura dos dados de um um vetor
#define TAM_MAX 10
double Vet1[TAM_MAX];
for(i=0; i<TAM_MAX; i++)
scanf("%f",&Vet1[i]);
Encontrar o maior valor dentro de um vetor
#define TAM_MAX 10
double Vet1[TAM_MAX];
double Maior;
for(i=0; i<TAM_MAX; i++)
scanf("%f",&Vet1[i]);// le os dados
Maior = Vet1[0]; // assume que o primeiro o
maior
for(i=0; i<TAM_MAX; i++)
if Vet1[i] > Maior
Maior = Vet1[i];
printf("O maior elemento %f\n",Maior);
// ****** Pergunta: Como fazer a mesma busca e
imprimir tambm a
// ****** posio do dado dentro do vetor. Tente
fazer isto usando
// ****** apenas 1 varivel.
Crie um programa que copie para um vetor os elementos de outro em
ordem crescente.
// a idia aqui encontrar o menor elemento do vetor 1 e colocar no vetor 2.
Tirar este nmero de vet1, por exemplo,
// colocando no seu lugar, no vetor 1, um nmero grande e recomear a busca
pelo novo nmero menor.
#define TAM_MAX 10
double Vet1[TAM_MAX], VetOrdenado[TAM_MAX];
double Menor, Maior;
for(i=0; i<TAM_MAX; i++)
scanf("%f",&Vet1[i]);// le os dados
PosMaior = 0; // assume que o maior est na 1a.
posio
for(i=0; i<TAM_MAX; i++)
if Vet1[i] > Vet1[PosMaior]
PosMaior = i; // acha a posio do maior
for(j=0; j<TAM_MAX;j++)
{
PosMenor = 0; // assume que o primeiro o
menor
for(i=0; i<TAM_MAX; i++)
if Vet1[i] < Vet1[PosMenor]
PosDoMenor = i;
VetOrdenado[j]= Vet1[PosMenor]; // copia menor
para o novo vetor
// inutiliza a posio do menor colocando nela um
nmero grande
Vet1[PosMenor] = Vet1[PosMaior]; // no caso o
maior do vetor
}
for(i=0; i<TAM_MAX; i++)
print("%f\n",VetOrdenado[i]);// Imprime

os

dados

Passagem de Matrizes e Vetores como Parmetro


Para passar uma matriz ou vetor como parmetro, basta declarar o
parmetro da mesma forma que a matriz foi declarada.
Um vetor sempre passado por referncia, logo, qualquer alterao em
seus elementos altera a varivel usada como parmetro na chamada da rotina.
#define TAM_MAX 10
void ImprimeVet (int Tam, int Vet[TAM_MAX])
{
int i;
for (i=0; i< Tam; i++)
{
printf("%d", Vet[i]);
}
}
void main()
{
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 usase 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 <stdio.h>
#include <stdlib.h>
#include <stdio.h>
#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);
}

Você também pode gostar