Funções de string: strlen, strcpy, strcat, strcmp
1. Introdução às funções de string na biblioteca <string.h>
Em linguagem C, strings são representadas como vetores de caracteres terminados pelo caractere nulo (\0). O cabeçalho <string.h> fornece um conjunto de funções essenciais para manipulação dessas sequências. Entre as mais utilizadas estão strlen, strcpy, strcat e strcmp, que permitem medir, copiar, concatenar e comparar strings, respectivamente.
O correto funcionamento dessas funções depende inteiramente da presença do terminador nulo. Sem ele, as operações podem ler ou escrever além dos limites da memória alocada, causando comportamentos indefinidos. Compreender o papel do \0 é fundamental para usar essas funções com segurança.
2. strlen: medindo o comprimento de uma string
A função strlen tem a seguinte sintaxe:
size_t strlen(const char *str);
Ela retorna o número de caracteres em str até (mas não incluindo) o terminador nulo. O tipo size_t é um tipo inteiro sem sinal definido em <stddef.h>, projetado para armazenar tamanhos de objetos.
Exemplo prático:
#include <stdio.h>
#include <string.h>
int main() {
char mensagem[] = "Olá, mundo!";
size_t tam = strlen(mensagem);
printf("String: \"%s\"\n", mensagem);
printf("strlen: %zu caracteres\n", tam);
printf("sizeof: %zu bytes (inclui \\0)\n", sizeof(mensagem));
return 0;
}
Saída esperada:
String: "Olá, mundo!"
strlen: 11 caracteres
sizeof: 12 bytes (inclui \0)
A diferença crucial: strlen conta apenas os caracteres visíveis, enquanto sizeof retorna o total de bytes ocupados pelo array, incluindo o \0. Essa distinção é vital ao alocar buffers dinamicamente.
3. strcpy: copiando strings
Sintaxe:
char *strcpy(char *dest, const char *src);
strcpy copia o conteúdo de src para dest, incluindo o terminador nulo. A função retorna o ponteiro para dest.
Perigo comum - estouro de buffer:
#include <stdio.h>
#include <string.h>
int main() {
char destino[5]; // Pequeno buffer
char origem[] = "Mensagem muito longa";
strcpy(destino, origem); // Estouro de buffer! Comportamento indefinido
printf("Destino: %s\n", destino);
return 0;
}
Para evitar esse problema, use strncpy, que limita a cópia a n caracteres:
#include <stdio.h>
#include <string.h>
int main() {
char destino[10];
char origem[] = "Seguro";
strncpy(destino, origem, sizeof(destino) - 1);
destino[sizeof(destino) - 1] = '\0'; // Garante terminação
printf("Destino: %s\n", destino);
return 0;
}
4. strcat: concatenando strings
Sintaxe:
char *strcat(char *dest, const char *src);
strcat localiza o final de dest (onde está o \0), remove esse terminador e anexa o conteúdo de src a partir daquele ponto. O resultado é uma única string terminada por \0.
Exemplo com verificação de tamanho:
#include <stdio.h>
#include <string.h>
int main() {
char nome[50] = "João";
char sobrenome[] = " Silva";
if (strlen(nome) + strlen(sobrenome) + 1 <= sizeof(nome)) {
strcat(nome, sobrenome);
printf("Nome completo: %s\n", nome);
} else {
printf("Buffer insuficiente para concatenação.\n");
}
return 0;
}
A concatenação segura requer que dest tenha espaço suficiente para armazenar ambas as strings mais o \0. Sem essa verificação, o programa pode corromper dados adjacentes na memória.
5. strcmp: comparando strings
Sintaxe:
int strcmp(const char *str1, const char *str2);
A função compara lexicograficamente duas strings com base nos valores ASCII dos caracteres. Retorna:
- Valor negativo se
str1for menor questr2 - Zero se forem iguais
- Valor positivo se
str1for maior questr2
Exemplo de comparação:
#include <stdio.h>
#include <string.h>
int main() {
char senha_correta[] = "C0d1g0#2024";
char entrada[50];
printf("Digite a senha: ");
fgets(entrada, sizeof(entrada), stdin);
entrada[strcspn(entrada, "\n")] = '\0'; // Remove newline
if (strcmp(entrada, senha_correta) == 0) {
printf("Acesso concedido.\n");
} else {
printf("Senha incorreta.\n");
}
return 0;
}
Para comparações parciais, use strncmp, que compara apenas os primeiros n caracteres:
if (strncmp(entrada, "C0d", 3) == 0) {
printf("Começa com C0d\n");
}
6. Boas práticas e armadilhas comuns
Verificação de ponteiros nulos:
#include <stdio.h>
#include <string.h>
size_t strlen_segura(const char *str) {
if (str == NULL) {
return 0;
}
return strlen(str);
}
Alocação adequada de buffers:
#include <stdio.h>
#include <string.h>
#include <stdlib.h>
int main() {
char *origem = "String dinâmica";
size_t tam = strlen(origem) + 1;
char *destino = (char *)malloc(tam);
if (destino != NULL) {
strcpy(destino, origem);
printf("Copiado: %s\n", destino);
free(destino);
}
return 0;
}
Código vulnerável vs. robusto:
Vulnerável:
char nome[10];
strcpy(nome, "Nome muito extenso");
Robusto:
char nome[10];
strncpy(nome, "Nome muito extenso", sizeof(nome) - 1);
nome[sizeof(nome) - 1] = '\0';
7. Exemplo integrado: um programa prático
O programa a seguir lê nome e sobrenome, realiza operações com as quatro funções e trata possíveis erros:
#include <stdio.h>
#include <string.h>
#include <stdlib.h>
int main() {
char primeiro[30], ultimo[30];
char nome_completo[100];
printf("Digite o primeiro nome: ");
fgets(primeiro, sizeof(primeiro), stdin);
primeiro[strcspn(primeiro, "\n")] = '\0';
printf("Digite o sobrenome: ");
fgets(ultimo, sizeof(ultimo), stdin);
ultimo[strcspn(ultimo, "\n")] = '\0';
// Verifica tamanhos
size_t tam_necessario = strlen(primeiro) + strlen(ultimo) + 2; // + espaço e \0
if (tam_necessario > sizeof(nome_completo)) {
printf("Erro: nome muito longo.\n");
return 1;
}
// Copia primeiro nome
strcpy(nome_completo, primeiro);
// Concatena espaço e sobrenome
strcat(nome_completo, " ");
strcat(nome_completo, ultimo);
printf("Nome completo: %s\n", nome_completo);
printf("Tamanho: %zu caracteres\n", strlen(nome_completo));
// Comparação com nome armazenado
char armazenado[] = "Maria Silva";
if (strcmp(nome_completo, armazenado) == 0) {
printf("Nome idêntico ao armazenado.\n");
} else {
printf("Nome diferente do armazenado.\n");
}
return 0;
}
Este exemplo demonstra o uso seguro de todas as quatro funções, com validações que previnem estouros de buffer e garantem terminação correta das strings.
Referências
- C string handling - cppreference.com — Documentação completa das funções de string em C, incluindo strlen, strcpy, strcat e strcmp com exemplos e notas sobre segurança.
- The GNU C Library - String and Array Utilities — Manual oficial da glibc com descrição detalhada de todas as funções de manipulação de strings e arrays.
- Beej's Guide to C Programming - Strings — Tutorial prático e acessível sobre strings em C, cobrindo as funções fundamentais com exemplos comentados.
- C Programming/String manipulation - Wikibooks — Livro colaborativo com explicações claras sobre as funções de string e armadilhas comuns.
- Secure Coding in C and C++ - String Handling — Guia da SEI CERT sobre práticas seguras de manipulação de strings, com recomendações para evitar vulnerabilidades.
- IBM Documentation - string.h functions — Documentação técnica da IBM sobre as funções do cabeçalho string.h, com sintaxe e exemplos para ambientes mainframe.