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.

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>

strcpy e strncpy

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.

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.

strcat e strncat

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.

strncat

strncat limita o número máximo de caracteres a anexar e adiciona \0 automaticamente:

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

strcmp e strncmp

strcmp

strcmp compara duas strings lexicograficamente, caractere por caractere:

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

Significado dos valores de retorno:

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

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

}

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

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:

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

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:

c const char *p = strrchr("Hello World", 'o'); if (p != NULL) { printf("Last occurrence: %s\n", p); }

Saída: "orld".

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:

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

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.

strlen personalizado

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

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.

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; } `

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.
100%