Uma string de caracteres em C é apenas uma matriz de caracteres. A seguinte linha declara uma matriz que pode conter uma string de até 99 caracteres.
char str[100];
Ela contém caracteres, como você pode esperar: str[0] é o primeiro caractere da string, str[1] é o segundo caractere e assim por diante. Mas por que uma matriz de 100 elementos não é capaz de suportar 100 caracteres? Porque a linguagem C utiliza strings de caracteres de terminação nula, significando que o final de qualquer string de caracteres é marcado por um valor ASCII de 0 (o caractere nulo), também representado em C como ''.
A terminação nula é muito diferente do modo que outras linguagens lidam com strings de caracteres. Por exemplo, em Pascal, cada string de caracteres consiste em uma matriz de caracteres, com byte de extensão que mantém a contagem do número de caracteres armazenada na matriz. Esta estrutura dá ao Pascal uma vantagem definitiva ao indagar a extensão de uma string de caracteres. O Pascal pode simplesmente devolver o byte de extensão, enquanto a linguagem C precisa contar os caracteres até encontrar. Este fato torna a linguagem C muito mais lenta do que a Pascal em alguns casos, mas mais rápida em outros, como veremos nos exemplos a seguir.
Visto que a linguagem C não oferece qualquer apoio explícito para strings de caracteres na própria linguagem, todas as funções de manipulação de strings de caracteres são implementadas em bibliotecas. As operações de I/O de strings de caracteres (gets, puts, etc.) são implementadas em <stdio.h> e um conjunto de funções de manipulação de strings de caracteres bastante simples é implementado em <string.h>
O fato das strings de caracteres não serem nativas em C força a criação de alguma codificação indireta. Por exemplo, suponha que você queira atribuir uma string de caracteres a outra, ou seja, deseja copiar o conteúdo de uma string de caracteres para outra. Em C, como vimos no último artigo, você não pode simplesmente atribuir uma matriz à outra. Você precisa copiar elemento por elemento. A biblioteca de strings (<string.h> ou <strings.h>)
char s[100]; strcpy(s, "olá");
Depois que estas duas linhas são executadas, o seguinte diagrama mostra o conteúdo de s:
O diagrama acima mostra a matriz com seus caracteres. O diagrama inferior mostra os valores em ASCII equivalentes aos caracteres e é assim que a linguagem C vê uma string de caracteres (como uma matriz de bytes contendo valores inteiros). Veja Como funcionam os bits e os bytes para uma explicação sobre os códigos ASCII.
O seguinte código mostra como usar strcpy em C:
#include<string.h> int main() { char s1[100],s2[100]; strcpy(s1,"Olá"); /* copy "Olá" em s1 */ strcpy(s2,s1); /* copy s1 em s2 */ return 0; }
strcpy é usado sempre que uma string de caracteres é inicializada em C. Você utiliza a ação strcmp na biblioteca de strings de caracteres para comparar duas seqüências. Ela retorna um inteiro que indica o resultado da comparação. Zero significa duas strings de caracteres iguais, um valor negativo significa que s1 é menor que s2 e um valor positivo significa que s1 é maior que s2.
#include <stdio.h>#include <string.h> int main() { char s1[100],s2[100]; gets(s1); gets(s2); if (strcmp(s1,s2)==0) printf("igual\n"); else if (strcmp(s1,s2)<0) printf("s1 menor que s2\n"); else printf("s1 maior que s2\n"); return 0; }
Outras funções comuns na biblioteca de strings de caracteres incluem strlen, que retorna a extensão de uma string, e strcat, que concatena duas strings. A biblioteca de strings de caracteres contém várias outras funções que você pode usar lendo a página principal.
Para começar a criar funções de strings de caracteres e ajudá-lo a compreender o código de outro programador (cada um tem seu próprio conjunto de funções para fins especiais em um programa), veremos 2 exemplos, strlen e strcpy. Veja a seguir uma versão estritamente em Pascal de strlen:
int strlen(char s[])
{
int x;
x=0;
while (s[x] != '\0')
x=x+1;
return(x);
}
A maioria dos programadores de C evita esta abordagem por parecer ineficiente. Em vez disso, quase sempre usam uma abordagem com base em ponteiros:
int strlen(char *s)
{
int x=0;
while (*s != '\0')
{
x++;
s++;
}
return(x);
}
Você pode abreviar esta codificação da seguinte maneira:
int strlen(char *s)
{
int x=0;
while (*s++)
x++;
return(x);
}
Acredito que um verdadeiro especialista em C encurtaria ainda mais esta codificação.
Quando compilo estes três trechos de código em um MicroVAX com gcc, sem qualquer otimização, e executo cada um 20 mil vezes em uma string de 120 caracteres, a primeira parte do código gera um tempo de 12,3 segundos, a segunda 12,3 segundos e a terceira 12,9 segundos. O que isso significa? Para mim, significa que você deve escrever o código do modo mais fácil para o seu entendimento. Os ponteiros em geral produzem um código mais rápido, porém o código strlen acima mostra que nem sempre isso ocorre.
Podemos passar pela mesma evolução com strcpy:
strcpy(char s1[],char s2[])
{
int x;
for (x=0; x<=strlen(s2); x++)
s1[x]=s2[x];
}
Observe aqui que <= é importante no loop for porque a codificação copia o ''. Certifique-se de copiar ''. Os bugs importantes ocorrem mais tarde se você não os excluir, pois a string de caracteres não tem fim e, portanto, tamanho desconhecido. Observe também que este código é muito ineficiente, pois strlen é sempre invocado pelo loop for. Para resolver este problema, você pode usar a seguinte codificação:
strcpy(char s1[],char s2[])
{
int x,len;
len=strlen(s2);
for (x=0; x<=len; x++)
s1[x]=s2[x];
}
A versão de ponteiro é similar.
strcpy(char *s1,char *s2)
{
while (*s2 != '\0')
{
*s1 = *s2;
s1++;
s2++;
}
}
Você pode abreviar esta codificação ainda mais:
strcpy(char *s1,char *s2)
{
while (*s2)
*s1++ = *s2++;
}
Se quiser, pode até mesmo dizer while (*s1++ = *s2++);. A primeira versão de strcpy leva 415 segundos para copiar uma string de 120 caracteres 10 mil vezes, a segunda versão leva 14,5 segundos, a terceira versão 9,8 segundos e a quarta 10,3 segundos. Como você pode ver, aqui os ponteiros oferecem um aumento significativo de desempenho.
O protótipo para a função strcpy na biblioteca de strings indica que ele foi projetado para retornar um ponteiro para uma string:
char *strcpy(char *s1,char *s2)
A maioria das funções de strings de caracteres retorna um ponteiro de seqüência como resultado, e strcpy retorna o valor de s1 como resultado.
Às vezes, usar ponteiros com strings de caracteres pode resultar em melhorias definidas em velocidade, e você pode tirar vantagem dela se pensar um pouco a respeito. Por exemplo, suponha que queira remover os espaços em branco iniciais de uma string. Você talvez queira transferir os caracteres para cima das partes em branco para removê-las. Em C, você pode evitar o movimento completamente:
#include <stdio.h> #include <string.h>int main() { char s[100],*p; gets(s); p=s; while (*p==' ') p++; printf("%s\n",p); return 0; }
Isto é muito mais rápido do que a técnica de transferência, especialmente para strings de caracteres longas.
Você aprenderá muitos outros truques com strings de caracteres, à medida que praticar e ler outras codificações. Praticar é a chave.