Criado: 19/04/2026 00:03 -03
Nesse post eu vou lhe ensinar a como implementar passo a passo o que está no título e vou explicar em detalhes o funcionamento dela. O que quero é uma função que quando recebe um argumento como por exemplo " isac " , retorne "isac". Muito simples. Vamos ver como fazer isso usando C.
Primeiro, qual deve ser a lógica? Começando no ínicio da string, enquanto o caractere for um espaço ou qualquer outro escape code semelhante é pra remover esse caractere. Depois é para ir até o fim da string e fazer o mesmo processo porém percorrendo a string de trás para frente.
Strings em C são arrays de caracteres, e quando passamos um array de char como argumento ele decai para char *, então estaremos o tempo todo lidando com ponteiros o que facilita muito o nosso trabalho.
// Parte 1
char *
trim(char *str)
{
if (str == NULL) return NULL; // Erro
return NULL; // Será substituído depois
}
Primeiro de tudo, precisamos saber onde fica o começo e o fim da string. O começo é fácil. O próprio ponteiro aponta para o começo da string, por exemplo:
char *text = "isac";
printf("'%c'", *text); // Saída -> 'i'
Mas e o fim da string? Também é simples. Basta lembrar que a função strlen() retorna o comprimento da string e que a posição do último caractere será sempre o comprimento da string menos 1.
char *text = "isac";
printf("%zd", strlen(text) - 1); // Saída -> 3 que é justamente a posição da letra 'c'
Então vamos definir dois ponteiros, um para o começo e outro para o final da string.
// Parte 2
#include <string.h>
char *
trim(char *str)
{
if (str == NULL) return NULL;
char *start = str;
char *end = str + strlen(str) - 1; // Estamos mudando o endereço do ponteiro
return NULL;
}
Agora vamos implementar a lógica de remover caracteres. O que na verdade vamos fazer é simplemente mover o ponteiro para frente ou para trás. No fundo no fundo não estaremos apagando algo da memória. Vamos começar do início. Enquanto houver um caractere que seja espaço ou semelhante, mova o ponteiro para frente. Vamos usar o while para isso. A forma mais neat que conheço é essa:
// Parte 2
#include <string.h>
#include <stdbool.h>
char *
trim(char *str)
{
if (str == NULL) return NULL;
char *start = str;
char *end = str + strlen(str) - 1;
while (*start) {
bool remove = false;
remove = (*start == ' ' || *start == '\n' || *start == '\t' ||
*start == '\r' || *start == '\f' || *start == '\v');
if (!remove) break;
start++;
}
return NULL;
}
Vamos por partes. Primeiro, o loop while executa o que o segue enquanto a sua condição for diferente de 0. Um char também é um número(que vai de -128 a 127)(e.g. você pode usar tanto 'a' quanto 97 para representar a mesma coisa), então enquanto o caractere for diferente de 0(ou '\0') que indica o fim da string ele vai executar o que o segue.
O operador unário * quando usado em um ponteiro ele retorna o valor que o ponteiro aponta. Nesse casso *start retornará um char.
As seguintes linhas:
remove = (*start == ' ' || *start == '\n' || *start == '\t' ||
*start == '\r' || *start == '\f' || *start == '\v');
Poderiam ser implementadas como um gigante if, mas ficaria muito feio:
if (*start == ' ' || *start == '\n' || *start == '\t' || start == '\r' || *start == '\f' || *start == '\v') {
remove = true;
}
Se remove = true o statement if (!remove) break; será ignorado não saindo do loop e posteriormente irá incrementar o ponteiro em 1 com start++;, 'removendo' o caráctere atual.
A lógica para remover os caracteres do final é semelhante. A principal diferença está na condição do loop while.
// Parte 3
#include <string.h>
#include <stdbool.h>
char *
trim(char *str)
{
if (str == NULL) return NULL;
char *start = str;
char *end = str + strlen(str) - 1;
while (*start) {
bool remove = false;
remove = (*start == ' ' || *start == '\n' || *start == '\t' ||
*start == '\r' || *start == '\f' || *start == '\v');
if (!remove) break;
start++;
}
while (end > start) {
bool remove = false;
remove = (*end == ' ' || *end == '\n' || *end == '\t' ||
*end == '\r' || *end == '\f' || *end == '\v');
if (!remove) break;
end--;
}
return NULL;
}
Um ponteiro é um endereço de memória, e esse endereço por sua vez é um número, então podemos fazer comparações entre ponteiros. O bloco while (end > start) end--; em outras palavras significa 'a partir do final, enquanto não estivermos a uma unidade de distância do começo, volte uma unidade'.
Certo, agora temos dois ponteiros. Um aponta para o primeiro caractere legível e outro para o último caractere legível. E o que fazemos com eles? Precisamos de três coisas para criar uma nova string. Vamos marcar com ✓ o que temos e com ✗ o que não temos ainda.
O comprimento da nova string será end - start + 1. Para entender isso basta executar o seguinte exemplo:
#include <stdio.h>
#include <stdlib.h>
#include <string.h>
int
main(void)
{
char *str = "isac";
char *start = str;
char *end = str + strlen(str) - 1;
size_t len = end - start + 1;
printf("string: %s\n", str);
printf("start: %p -> '%c'\n", start, *start);
printf("end: %p -> '%c'\n", end, *end);
printf("end - start: %d\n", (end - start));
printf("length: %zd\n", len);
return EXIT_SUCCESS;
}
Cuja saída será, por exemplo:
string: isac start: 0x402000 -> 'i' end: 0x402003 -> 'c' end - start: 3 length: 4
Certo, sabemos como calcular o comprimento da nova string. Agora, vamos adicionar isso ao código.
// Parte 4
#include <stdbool.h>
#include <stdlib.h>
#include <string.h>
char *
trim(char *str)
{
if (str == NULL) return NULL;
char *start = str;
char *end = str + strlen(str) - 1;
while (*start) {
bool remove = false;
remove = (*start == ' ' || *start == '\n' || *start == '\t' ||
*start == '\r' || *start == '\f' || *start == '\v');
if (!remove) break;
start++;
}
while (end > start) {
bool remove = false;
remove = (*end == ' ' || *end == '\n' || *end == '\t' ||
*end == '\r' || *end == '\f' || *end == '\v');
if (!remove) break;
end--;
}
/* Testamos se end >= start para que caso o cálculo venha
* a produzir um número negativo esse calculo não seja realizado
* mas sim substituido por zero.
*/
size_t len = (end >= start) ? (end - start + 1) : 0;
return NULL;
}
Agora, as última coisa que precisamos fazer é arranjar um lugar para colocar a nova string, colocar a nova string nesse espaço e retornar esse espaço. Primeiro vamos alocar memória manualmente. É bem simples. Precisamos apenas de espaço suficiente para a string e o caractere nulo; malloc(len + 1) vai servir. Agora, precisamos mover a string em si para esse espaço. Vamos usar a função memcpy() para isso. Essa função copia o tanto de bytes que queremos de um endereço para outro. memcpy(new_str, start, len) servirá. Em resumo, copiará para new_str len bytes a partir de start
#include <stdbool.h>
#include <stdlib.h>
#include <string.h>
/*
* Function to remove spaces and similar characters around a string
*/
char *
trim(char *str)
{
if (str == NULL) return NULL;
char *start = str;
char *end = str + strlen(str) - 1;
while (*start) {
bool remove = false;
remove = (*start == ' ' || *start == '\n' || *start == '\t' ||
*start == '\r' || *start == '\f' || *start == '\v');
if (!remove) break;
start++;
}
while (end > start) {
bool remove = false;
remove = (*end == ' ' || *end == '\n' || *end == '\t' ||
*end == '\r' || *end == '\f' || *end == '\v');
if (!remove) break;
end--;
}
size_t len = (end >= start) ? (end - start + 1) : 0;
char *new_str = malloc(len + 1);
if (new_str == NULL) return NULL;
if (len > 0) memcpy(new_str, start, len);
new_str[len] = '\0';
return new_str;
}
Eu apenas adicionei uma condição extra para não realizar uma cópia desnecessária de 0 caracteres. E para finalizar adicionei o caractere nulo na última posição da string. Vejamos a função em ação:
#include <stdio.h>
#include <stdbool.h>
#include <stdlib.h>
#include <string.h>
char *
trim(char *str)
{
--- Código da função aqui ---
}
int
main(void)
{
char *name = " isac ";
char *trimmed = trim(name);
printf("'%s' -> '%s'\n", name, trimmed);
free(trimmed); // MUITO IMPORTANTE, NÃO ESQUEÇA
// DE LIBERAR A MEMÓRIA ALOCADA PARA A NOVA STRING
return EXIT_SUCCESS;
}
Saída:
' isac ' -> 'isac'