C: Funções de String
Funções de string são como chaves e chaves de fenda em uma caixa de ferramentas — cada ferramenta resolve um problema específico: copiar, concatenar, comparar, buscar. Domine-as, e você lidará com texto com confiança.
1. Visão geral do string.h
<string.h> é o arquivo de cabeçalho principal para operações de string na biblioteca padrão C, fornecendo funções para copiar, concatenar, comparar e buscar. Você deve incluí-lo antes de usar:
#include <string.h>
2. strcpy e strncpy
(1) strcpy
strcpy copia a string de origem para o vetor de destino, incluindo \0:
char dest[20];
strcpy(dest, "Hello World");
printf("%s\n", dest);
Protótipo: char *strcpy(char *dest, const char *src);
strcpy não verifica o tamanho do buffer de destino. Se a string de origem for maior que o vetor de destino, ela escreve fora dos limites. Garanta que o vetor de destino seja grande o suficiente antes de usá-la.
(2) strncpy
strncpy limita o número máximo de bytes a copiar, tornando-a mais segura:
char dest[6];
strncpy(dest, "Hello World", sizeof(dest) - 1);
dest[sizeof(dest) - 1] = '\0';
printf("%s\n", dest);
Protótipo: char *strncpy(char *dest, const char *src, size_t n);
strncpy copia no máximo n bytes. Se a string de origem for menor que n, as posições restantes são preenchidas com \0; se a string de origem tiver n bytes ou mais, ela não adiciona \0 automaticamente. Portanto, você deve adicioná-lo manualmente.
\0 ao usar strncpy e adicione \0 manualmente após a cópia.
3. strcat e strncat
(1) strcat
strcat anexa a string de origem ao final da string de destino:
char buf[50] = "Hello";
strcat(buf, " World");
printf("%s\n", buf);
Protótipo: char *strcat(char *dest, const char *src);
O \0 existente no final da string de destino é sobrescrito, e um novo \0 é colocado após o resultado concatenado.
strcat não verifica o tamanho do buffer.
(2) strncat
strncat limita o número máximo de caracteres a anexar e adiciona \0 automaticamente:
char buf[10] = "Hi";
strncat(buf, " World!", sizeof(buf) - strlen(buf) - 1);
printf("%s\n", buf);
Protótipo: char *strncat(char *dest, const char *src, size_t n);
Ela anexa no máximo n caracteres, depois adiciona \0 automaticamente. É mais segura que strncpy porque garante terminação nula.
4. strcmp e strncmp
(1) strcmp
strcmp compara duas strings lexicograficamente, caractere por caractere:
int result = strcmp("abc", "abd");
Significado dos valores de retorno:
< 0: s1 é menor que s2= 0: s1 é igual a s2> 0: s1 é maior que s2
if (strcmp(s1, s2) == 0) {
printf("Equal\n");
}
strcmp para comparar strings, nunca ==. == compara endereços de ponteiros, não conteúdos de strings.
(2) strncmp
strncmp compara apenas os primeiros n caracteres:
if (strncmp(str, "GET ", 4) == 0) {
printf("GET request\n");
}
Útil para comparar prefixos ou limitar o escopo da comparação.
▶ Exemplo
Ordene um vetor de strings em ordem lexicográfica:
#include <stdio.h>
#include <string.h>
void sort_strings(char arr[][32], int n) {
int i, j;
char temp[32];
for (i = 0; i < n - 1; i++) {
for (j = 0; j < n - 1 - i; j++) {
if (strcmp(arr[j], arr[j + 1]) > 0) {
strcpy(temp, arr[j]);
strcpy(arr[j], arr[j + 1]);
strcpy(arr[j + 1], temp);
}
}
}
}
int main(void) {
char names[5][32] = {
"david",
"alice",
"charlie",
"bob",
"eve"
};
int i;
sort_strings(names, 5);
for (i = 0; i < 5; i++) {
printf("%s\n", names[i]);
}
return 0;
}
ext alice bob charlie david eve
5. strlen
strlen retorna o comprimento efetivo de uma string (não incluindo \0):
char s[] = "Hello";
printf("%zu\n", strlen(s));
printf("%zu\n", sizeof(s));
Saída: 5 e 6. strlen conta até \0; sizeof inclui \0.
strlen percorre a string para encontrar \0, com complexidade de tempo O(n). Se você usa o comprimento da mesma string múltiplas vezes, armazene o resultado em cache:
size_t len = strlen(s);
for (size_t i = 0; i < len; i++) {
}
Em vez de chamar strlen na condição do laço a cada iteração.
6. strchr e strrchr
strchr encontra a primeira ocorrência de um caractere em uma string:
const char *p = strchr("Hello World", 'o');
if (p != NULL) {
printf("Found: %s\n", p);
}
Saída: "o World". Retorna um ponteiro para aquele caractere, ou NULL se não encontrado.
strrchr encontra a última ocorrência de um caractere:
const char *p = strrchr("Hello World", 'o');
if (p != NULL) {
printf("Last occurrence: %s\n", p);
}
Saída: "orld".
7. strstr
strstr encontra a primeira ocorrência de uma substring em uma string:
const char *p = strstr("Hello World", "World");
if (p != NULL) {
printf("Substring at: %s\n", p);
}
Saída: "World". Retorna NULL se não encontrado.
Encontrando todas as ocorrências:
const char *text = "abababab";
const char *p = text;
while ((p = strstr(p, "ab")) != NULL) {
printf("Position %ld\n", (long)(p - text));
p++;
}
Após cada busca, avance o ponteiro em uma posição e continue procurando ocorrências subsequentes.
8. Implementações personalizadas de funções de string
Entender como as funções padrão funcionam internamente ajuda a dominar a essência das operações de string.
(1) strlen personalizado
size_t my_strlen(const char *s) {
size_t len = 0;
while (s[len] != '\0') {
len++;
}
return len;
}
(2) strcpy personalizado
char *my_strcpy(char *dest, const char *src) {
char *d = dest;
while ((*d++ = *src++) != '\0') {
}
return dest;
}
Esta forma compacta: *d++ = *src++ copia o caractere primeiro, depois ambos os ponteiros avançam, até que \0 seja copiado.
(3) strcmp personalizado
int my_strcmp(const char *s1, const char *s2) {
while (*s1 == *s2) {
if (*s1 == '\0') return 0;
s1++;
s2++;
}
return (unsigned char)*s1 - (unsigned char)*s2;
}
Compare caractere por caractere: continue enquanto forem iguais, pare ao encontrar uma diferença ou \0. Retorne a diferença para indicar a ordem. A conversão para unsigned char garante que valores negativos de caracteres não afetem o resultado da comparação.
▶ Exemplo
strcat personalizado e teste:
#include <stdio.h>
char *my_strcat(char *dest, const char *src) {
char *d = dest;
while (*d != '\0') {
d++;
}
while ((*d++ = *src++) != '\0') {
}
return dest;
}
int main(void) {
char buf[50] = "Hello";
my_strcat(buf, ", ");
my_strcat(buf, "World!");
printf("%s\n", buf);
return 0;
}
ext Hello, World!
Primeiro encontre o \0 no final de dest, depois copie o conteúdo de src a partir daquela posição.
❓ Perguntas Frequentes
P: Por que strncpy não adiciona
\0automaticamente? R:strncpyfoi originalmente projetada para preencher buffers de comprimento fixo (como campos de nome de arquivo): preenche com\0quando menor que n, mas não adiciona\0quando atinge n bytes. Quando usada comostrcpymais segura, você deve adicionar\0manualmente.
P: O valor numérico específico retornado por
strcmpimporta? R: Você deve apenas verificar se é positivo, negativo ou zero — não dependa do valor exato. Implementações diferentes retornam diferenças diferentes; código portátil usa apenas==0,<0,>0.
P:
strcaté ineficiente para múltiplas concatenações — o que fazer? R: Cadastrcatpercorre dest do início ao fim antes de anexar, tornando a eficiência total O(n^2) para múltiplas concatenações. Você pode rastrear manualmente a posição final atual e anexar diretamente a partir dela.
P: Qual o sentido de implementar funções de string você mesmo? R: Entender princípios internos, perguntas comuns em entrevistas, e desenvolvimento embarcado onde a biblioteca padrão pode não estar disponível. No entanto, prefira funções da biblioteca padrão em projetos reais — elas são testadas e otimizadas.
📖 Resumo
strcpy/strncpycopiam strings; strncpy é mais segura mas requer terminação\0manualstrcat/strncatconcatenam strings; strncat adiciona\0automaticamentestrcmp/strncmpcomparam strings; nunca use==para comparar conteúdo de stringsstrchr/strrchrbuscam caracteres;strstrbusca substrings- Implementações personalizadas ajudam a entender princípios internos; use a biblioteca padrão em projetos reais
📝 Exercícios
- Escreva uma função
oid str_tolower(char *s)que converta todas as letras maiúsculas de uma string para minúsculas. - Escreva uma função
int str_count_char(const char *s, char ch)que conte quantas vezes o caracterechaparece na strings. - Sem usar nenhuma função de string.h, escreva
my_strstrpara implementar busca de substring.