Uma string é uma sequência de caracteres, usada para representar palavras, textos, etc em um programa. Várias linguagens de programação têm strings como um dos tipos de dados básicos da linguagem, como números inteiros ou em ponto flutuante.
A linguagem C não tem esse tipo de dados, e oferece algumas (poucas) facilidades para sua implementação. As strings em C são geralmente colocadas em vetores de char. Como qualquer vetor em C, vetores de char são de tamanho invariável, e esse tamanho não é facilmente acessável (uma função que recebe um vetor não tem como saber seu tamanho por métodos diretos, por exemplo). Strings são tipicamente mais dinâmicas que vetores de char (em geral se pode alterar seu valor, e alterações no valor de uma string comumente alteram o número de caracteres da string ou seu tamanho. O casamento dessas incompatibilidades é tarefa que a linguagem não resolve, seu controle deve ser realizado externamente, diretamente pelo programador e com a ajuda de funções de biblioteca. Felizmente, a biblioteca padrão da linguagem oferece um grande conjunto de operações com string que facilitam seu manuseio.
Uma dessas padronizações é a forma de se representar uma string de tamanho que pode variar, sendo essa string colocada em um vetor que tem tamanho fixo. A forma escolhida foi colocar, logo após o fim da string (e para marcar esse final), um caractere especial que informa que a string terminou. Foi escolhido para isso o caractere com código 0. Como esse caractere serve para informar o final da string, essa representação tem a limitação de que não é possível ter esse caractere no interior de uma string. Essa limitação não é considerada muito importante, porque o caractere de código 0 (que é usado para indicar uma operação nula a um dispositivo) tem um uso bastante infrequente.
Para chamar a atenção para o fato que se está tratando do caractere que tem o código 0 e não de um zero qualquer, é comum se representar esse caractere como '\0'.
Para ser armazenada em um vetor, uma string necessita portanto que o vetor tenha tamanho suficiente para conter todos os caracteres que constituem a string mais um para o caractere que representa o seu final. Como o estouro de vetor (o acesso além dos limites do vetor) não é controlado pela linguagem, esse controle no caso de strings deve ser uma preocupação constante do programador, que sempre deve certificar-se que seus vetores têm capacidade suficiente para as strings que armazenam. Essa é uma das principais fontes de erro em programas feitos na linguagem, e considerado um dos principais defeitos de projeto do C.
A linguagem oferece strings constantes, que são representadas entre aspas duplas. Uma sequência de caracteres entre aspas duplas é colocada na memória pelo compilador da forma esperada pelas funções, com um caractere extra de código 0 após o último caractere pertencente à string. Um vetor de char pode ser inicializado por uma string constante, tomando-se cuidado para que o tamanho do vetor seja suficiente para todos os seus caracteres mais o '\0'.
char a[8] = "12345"; // ok, o vetor a tem 8 char, a string ocupa 6 (5+1); os dois char restantes serão preenchidos com 0
char b[] = "12345"; // ok, o vetor b será alocado com 6 posicoes
char c[5] = "12345"; // nao ok, o vetor de 5 posições será inicializado com os caracteres, mas não será uma string porque nao terá o 0 final
char d[4] = "12345"; // não ok, e será detectado como um erro pelo compilador, inicialização de mais elementos do que cabe no vetorAs funções printf e scanf têm suporte a strings, com o formato %s.
No caso do printf, ele imprimirá todos os caracteres encontrados no vetor que recebe como argumento, até encontrar um caractere de código 0 (que não é impresso por não pertencer à string).
No caso do scanf, ele pula caracteres espaço (e fim de linha, tabulação), e coloca na string os caracteres não espaço da entrada, até encontrar um caractere espaço. O scanf não tem como fazer verificação do tamanho do vetor, então pode escrever fora do vetor caso tenha na entrada mais caracteres que a capacidade do vetor. Por causa desse problema, não é recomendado usar scanf para ler strings.
Pode-se limitar o número de caracteres a serem lidos pelo scanf, com um formato como %29s; nesse caso, o scanf lerá no máximo 29 caracteres, e não causará estouro ao ler uma string para um vetor com tamanho para 30 char.
O scanf tem também o formato %[, que lê uma string composta pelos caracteres da entrada que são iguais aos caracteres dentro dos colchetes, até encontrar um que não pertença a esse conjunto. Por exemplo, %[abc, ] vai ler caracteres até encontrar um que não seja abc nem vírgula nem espaço. O conjunto de caracteres pode ser invertido, se começar com ^, %[^\n] é comum, para dizer qualquer caractere exceto \n, ou para ler até o fim da linha.
Uma outra função padrão para a leitura de strings é a função fgets. Essa função recebe 3 argumentos, o primeiro é o vetor onde colocar a string, o segundo é o tamanho desse vetor (ou quantos caracteres no máximo a função pode escrever), e o terceiro representa de onde se quer ler (a entrada padrão, que é de onde todas as funções de entrada que usamos até agora lêm é representada por stdin). Os caracteres da entrada são lidos e armazenados no vetor (sem pular espaços no início), até que tenham sido lidos n-1 caracteres ou até que chegue no final da linha na entrada; a função põe então um caractere de código 0 no final. Se chegar ao final da linha, o caractere de final de linha ('\n') será o último caractere colocado por fgets na string.
Tem uma função mais simples também para imprimir strings, que é puts. Abaixo um exemplo de uso das duas.
char nome[20];
puts("Qual seu nome? ");
fgets(nome, 20, stdin);
printf("Seu nome é %s.\n", nome);Outro cuidado a tomar no caso de usar scanf é que como se está passando um vetor como argumento, não se deve colocar o & antes do nome do vetor, diferente dos demais tipos de dados:
scanf("%19s", nome);Incluindo <string.h>, se tem acesso a um conjunto de funções para o manuseio de strings.
Entre elas:
strlen: recebe uma string (o vetor que contém a string) e retorna o tamanho dessa string (o número de caracteres que ela contém). Para isso, conta todos os caracteres antes do '\0'.strcpy: recebe dois vetores, e copia para o primeiro a string que está no segundo. Equivale a uma atribuição de strings, já que não existe atribuição de vetores na linguagem. Copia caractere a caractere, até copiar o '\0'. É responsabilidade do programador garantir que o vetor que recebe a string tem o espaço necessário.strcat: recebe duas strings, e concatena a segunda string à primeira (acrescenta os caracteres da segunda string ao final da primeira. É responsabilidade do programador garantir que tem espaço no vetor.
- Implemente as funções acima, mudando o nome para não dar conflito com as funções originais. Abaixo está o programa visto em aula, para completar com a implementação dessas funções. Altere para incluir
string.he para usar as funções oficiais, para ver se o resultado é o mesmo.
#include <stdio.h>
int mstrlen(char v[]) { // retorna o número de caracteres da string em v
}
void mstrcpy(char d[], char o[]) { // copia a str em o para d
}
void mstrcat(char d[], char o[]) { // copia a str em o para o final da em d
}
void imprime_str(char s[])
{
for (int i = 0; s[i] != '\0'; i++) {
putchar(s[i]);
}
}
int main()
{
char s[30] = "Abacaxi";
char s2[10] = " é bom";
char s3[10];
printf("%s tem %d caracteres\n", s, mstrlen(s));
printf("%s tem %d caracteres\n", s2, mstrlen(s2));
mstrcpy(s3, s2);
printf("%s tem %d caracteres\n", s3, mstrlen(s3));
mstrcat(s, s2);
printf("%s tem %d caracteres\n", s, mstrlen(s));
imprime_str(s);
}- Implemente uma função que recebe um vetor de char que contém uma string, e retorna um bool que diz se essa string é ou não um palíndromo (se a sequência de caracteres é a mesma, lida da esquerda para a direita ou da direita pra esquerda).
"AS SATAS SA"é um palíndromo,"OS SOTOS SA"não é. Faça um programa para testar sua função. - Faça uma função que copia uma string para um vetor, copiando somente as letras, e transformando minúsculas em maiúsculas. Usando essa função, o resultado da cópia de "Socorram-me, subi no onibus em Marrocos" deve ser um palíndromo.
- Faça uma função que compara duas strings. A função deve receber duas strings e retornar um int, que deve ser 0 se as strings são iguais, um número negativo se a primeira string vem antes da segunda em um dicionário e positivo caso contrário. Uma forma simples de calcular é subtraindo o primeiro caractere diferente das duas strings (sem esquecer de parar no primeiro
'\0'). A biblioteca padrão tem uma função para fazer isso, chamadastrcmp, e é a forma de se comparar strings.