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:

C
#include <string.h>

2. strcpy e strncpy

(1) strcpy

strcpy copia a string de origem para o vetor de destino, incluindo \0:

C
char dest[20];
strcpy(dest, "Hello World");
printf("%s\n", dest);

Protótipo: char *strcpy(char *dest, const char *src);

⚠️ Atenção: 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:

C
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.

💡 Dica: Sempre reserve espaço para \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:

C
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.

⚠️ Atenção: O vetor de destino deve ter espaço suficiente para 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:

TEXT 📖 Somente leitura
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:

C
int result = strcmp("abc", "abd");

Significado dos valores de retorno:

TEXT 📖 Somente leitura
if (strcmp(s1, s2) == 0) {
    printf("Equal\n");
}
⚠️ Atenção: Use 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:

C
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:

C
#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;
}
▶ Experimente

ext alice bob charlie david eve


5. strlen

strlen retorna o comprimento efetivo de uma string (não incluindo \0):

C
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:

TEXT 📖 Somente leitura
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:

C
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:

TEXT 📖 Somente leitura
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:

C
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:

TEXT 📖 Somente leitura
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

C
size_t my_strlen(const char *s) {
    size_t len = 0;
    while (s[len] != '\0') {
        len++;
    }
    return len;
}

(2) strcpy personalizado

C
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

C
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:

C
#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;
}
▶ Experimente

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 \0 automaticamente? R: strncpy foi originalmente projetada para preencher buffers de comprimento fixo (como campos de nome de arquivo): preenche com \0 quando menor que n, mas não adiciona \0 quando atinge n bytes. Quando usada como strcpy mais segura, você deve adicionar \0 manualmente.

P: O valor numérico específico retornado por strcmp importa? 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: Cada strcat percorre 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

📝 Exercícios

  1. Escreva uma função oid str_tolower(char *s) que converta todas as letras maiúsculas de uma string para minúsculas.
  2. Escreva uma função int str_count_char(const char *s, char ch) que conte quantas vezes o caractere ch aparece na string s.
  3. Sem usar nenhuma função de string.h, escreva my_strstr para implementar busca de substring.
Web-Tutorial.com

Equipe Técnica Web-Tutorial

Uma plataforma de tutoriais mantida por diversos desenvolvedores. Cada tutorial é escrito e revisado por profissionais da área correspondente. Trabalhamos para manter nosso conteúdo preciso e confiável — se encontrar algum problema, avise-nos.

100%