Removendo espaços de uma string em C?

Qual é a maneira mais fácil e eficiente de remover espaços de uma string em C?

Mais fácil e eficiente não costuma ir junto …

Aqui está uma possível solução (não testada):

void RemoveSpaces(char* source) { char* i = source; char* j = source; while(*j != 0) { *i = *j++; if(*i != ' ') i++; } *i = 0; } 

Aqui está uma versão muito compacta, mas totalmente correta:

 do while(isspace(*s)) s++; while(*d++ = *s++); 

E aqui, apenas para minha diversão, são versões de código-golfe que não são inteiramente corretas e deixam os comentadores chateados.

Se você pode arriscar algum comportamento indefinido e nunca ter cordas vazias, você pode se livrar do corpo:

 while(*(d+=!isspace(*s++)) = *s); 

Heck, se pelo espaço você quer dizer apenas caráter de espaço:

 while(*(d+=*s++!=' ')=*s); 

Não use isso na produção 🙂

Como podemos ver pelas respostas postadas, essa não é uma tarefa trivial. Quando confrontados com uma tarefa como essa, parece que muitos programadores optam por lançar o senso comum pela janela, a fim de produzir o fragment mais obscuro que possam surgir.

Coisas a considerar:

  • Você vai querer fazer uma cópia da string, com espaços removidos. Modificar a string passada é uma prática ruim, pode ser uma string literal. Além disso, às vezes há benefícios de tratar strings como objects imutáveis .
  • Você não pode assumir que a string de origem não está vazia. Pode conter apenas um caractere de terminação nula.
  • O buffer de destino pode conter qualquer lixo não inicializado quando a function é chamada. Verificá-lo por terminação nula não faz qualquer sentido.
  • A documentação do código-fonte deve indicar que o buffer de destino precisa ser grande o suficiente para conter a string aparada. A maneira mais fácil de fazer isso é torná-lo tão grande quanto a string não aparada.
  • O buffer de destino precisa manter uma cadeia terminada nula sem espaços quando a function estiver concluída.
  • Considere se você deseja remover todos os caracteres em branco ou apenas espaços ' ' .
  • A programação em C não é uma competição sobre quem pode include tantos operadores em uma única linha quanto possível. Ao contrário, um bom programa C contém código legível (sempre a qualidade mais importante) sem sacrificar a eficiência do programa (algo importante).
  • Por esse motivo, você não recebe pontos de bônus para ocultar a inserção da terminação nula da cadeia de destino, permitindo que ela faça parte do código de cópia. Em vez disso, torne explícita a inserção de terminação nula, para mostrar que você não conseguiu acertar por acaso.

O que eu faria:

 void remove_spaces (char* restrict str_trimmed, const char* restrict str_untrimmed) { while (*str_untrimmed != '\0') { if(!isspace(*str_untrimmed)) { *str_trimmed = *str_untrimmed; str_trimmed++; } str_untrimmed++; } *str_trimmed = '\0'; } 

Nesse código, a seqüência de caracteres de origem “str_untrimmed” é deixada intacta, o que é garantido pelo uso da correta const const. Não falha se a cadeia de origem contiver apenas uma terminação nula. Ele sempre anula a string de destino.

A alocação de memory é deixada para o chamador. O algoritmo deve se concentrar apenas em fazer o trabalho pretendido. Remove todos os espaços em branco.

Não há truques sutis no código. Ele não tenta include tantos operadores quanto possível em uma única linha. Será um candidato muito pobre para o IOCCC . No entanto, ele produzirá praticamente o mesmo código de máquina que as versões mais obscuras de uma linha.

Ao copiar algo, você pode otimizar um pouco declarando os dois pointers como restrict , que é um contrato entre o programador e o compilador, onde o programador garante que o destino e a origem não são o mesmo endereço (ou melhor, que os dados ponto para só são acessados ​​através desse ponteiro muito e não através de algum outro ponteiro). Isso permite uma otimização mais eficiente, já que o compilador pode copiar diretamente da origem para o destino sem memory temporária no meio.

Em C, você pode replace algumas strings in-place, por exemplo, uma string retornada por strdup ():

 char *str = strdup(" abc "); char *write = str, *read = str; do { if (*read != ' ') *write++ = *read; } while (*read++); printf("%s\n", str); 

Outras strings são somente leitura, por exemplo, aquelas declaradas no código. Você teria que copiá-los para uma área recém-alocada de memory e preencher a cópia pulando os espaços:

 char *oldstr = " abc "; char *newstr = malloc(strlen(oldstr)+1); char *np = newstr, *op = oldstr; do { if (*op != ' ') *np++ = *op; } while (*op++); printf("%s\n", newstr); 

Você pode ver porque as pessoas inventaram outros idiomas;)

 #include  char * remove_spaces(char * source, char * target) { while(*source++ && *target) { if (!isspace(*source)) *target++ = *source; } return target; } 

Notas;

  • Isso não manipula Unicode.

Se você ainda estiver interessado, esta function remove espaços do início da string, e eu apenas a tenho trabalhando no meu código:

 void removeSpaces(char *str1) { char *str2; str2=str1; while (*str2==' ') str2++; if (str2!=str1) memmove(str1,str2,strlen(str2)+1); } 

A maneira mais fácil e eficiente de remover espaços de uma string é simplesmente remover os espaços da string literal. Por exemplo, use seu editor para “localizar e replace” "hello world" com "helloworld" e pronto!

Ok, eu sei que não é o que você quis dizer. Nem todas as strings vêm de literais de string, certo? Supondo que essa string que você quer que espaços removidos não venha de uma string literal, precisamos considerar a origem e o destino de sua string … Precisamos considerar todo o seu algoritmo, qual problema real você está tentando resolver, em para sugerir os methods mais simples e ideais.

Talvez sua string venha de um arquivo (por exemplo, stdin ) e esteja destinada a ser gravada em outro arquivo (por exemplo, stdout ). Se for esse o caso, eu questionaria por que ele precisa se tornar uma string em primeiro lugar. Basta tratá-lo como se fosse um stream de caracteres, descartando os espaços como você se deparar com eles …

 #include  int main(void) { for (;;) { int c = getchar(); if (c == EOF) { break; } if (c == ' ') { continue; } putchar(c); } } 

Ao eliminar a necessidade de armazenamento de uma string, o programa inteiro não apenas se torna muito, muito mais curto, mas teoricamente também é muito mais eficiente.

 #include #include main() { int i=0,n; int j=0; char str[]=" Nar ayan singh "; char *ptr,*ptr1; printf("sizeof str:%ld\n",strlen(str)); while(str[i]==' ') { memcpy (str,str+1,strlen(str)+1); } printf("sizeof str:%ld\n",strlen(str)); n=strlen(str); while(str[n]==' ' || str[n]=='\0') n--; str[n+1]='\0'; printf("str:%s ",str); printf("sizeof str:%ld\n",strlen(str)); } 

Eu suponho que a string C está em uma memory fixa, então se você replace os espaços você tem que mudar todos os caracteres.

O mais fácil parece ser criar uma nova string e iterar sobre a original e copiar apenas caracteres não espaciais.

Isso é o mais fácil que eu poderia pensar (TESTADO) e funciona !!

 char message[50]; fgets(message, 50, stdin); for( i = 0, j = 0; i < strlen(message); i++){ message[ij] = message[i]; if(message[i] == ' ') j++; } message[i] = '\0'; 

Código retirado da biblioteca zString

 /* search for character 's' */ int zstring_search_chr(char *token,char s){ if (!token || s=='\0') return 0; for (;*token; token++) if (*token == s) return 1; return 0; } char *zstring_remove_chr(char *str,const char *bad) { char *src = str , *dst = str; /* validate input */ if (!(str && bad)) return NULL; while(*src) if(zstring_search_chr(bad,*src)) src++; else *dst++ = *src++; /* assign first, then incement */ *dst='\0'; return str; } 

Exemplo de código

  Exmaple Usage char s[]="this is a trial string to test the function."; char *d=" ."; printf("%s\n",zstring_remove_chr(s,d)); Example Output thisisatrialstringtotestthefunction 

Ter um llok no código zString, você pode achar útil https://github.com/fnoyanisi/zString

Eu me deparei com uma variação para esta questão, onde você precisa reduzir os espaços multiplicados em um espaço “representar” os espaços.

Esta é minha solução:

 char str[] = "Put Your string Here....."; int copyFrom = 0, copyTo = 0; printf("Start String %s\n", str); while (str[copyTo] != 0) { if (str[copyFrom] == ' ') { str[copyTo] = str[copyFrom]; copyFrom++; copyTo++; while ((str[copyFrom] == ' ') && (str[copyFrom] !='\0')) { copyFrom++; } } str[copyTo] = str[copyFrom]; if (str[copyTo] != '\0') { copyFrom++; copyTo++; } } printf("Final String %s\n", str); 

Espero que ajude 🙂