Eliminar espacios de una cadena en C?

¿Cuál es la forma más fácil y más eficiente de eliminar espacios de una cadena en C?

    Lo más fácil y eficiente no suele ir de la mano …

    Aquí hay una posible solución (no probada):

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

    Aquí hay una versión muy compacta, pero totalmente correcta:

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

    Y aquí, solo para mi diversión, hay versiones de código de golf que no son del todo correctas, y molestan a los comentaristas.

    Si puede poner en riesgo un comportamiento indefinido y nunca tiene cadenas vacías, puede deshacerse del cuerpo:

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

    Diablos, si por espacio te refieres al carácter de espacio:

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

    No lo use en producción 🙂

    Como podemos ver en las respuestas publicadas, sorprendentemente esta no es una tarea trivial. Cuando se enfrenta a una tarea como esta, parece que muchos progtwigdores eligen tirar el sentido común por la ventana, para producir el fragmento más oscuro que posiblemente se les ocurra.

    Cosas para considerar:

    • Querrá hacer una copia de la cadena, con espacios eliminados. La modificación de la cadena pasada es una mala práctica, puede ser una cadena literal. Además, a veces hay beneficios de tratar cadenas como objetos inmutables .
    • No puede suponer que la cadena fuente no está vacía. Puede contener nada más que un solo carácter de terminación nula.
    • El búfer de destino puede contener cualquier basura no inicializada cuando se llama a la función. Comprobar que la terminación no sea nula no tiene ningún sentido.
    • La documentación del código fuente debe indicar que el almacenamiento intermedio de destino debe ser lo suficientemente grande para contener la cadena recortada. La forma más fácil de hacerlo es hacerlo tan grande como la cadena sin recortar.
    • El búfer de destino debe contener una cadena terminada nula sin espacios cuando se realiza la función.
    • Considere si desea eliminar todos los caracteres de espacio en blanco o solo espacios ' ' .
    • La progtwigción en C no es una competencia sobre quién puede involucrar a tantos operadores en una línea como sea posible. Es más bien lo contrario, un buen progtwig de C contiene código legible (siempre la cualidad más importante) sin sacrificar la eficiencia del progtwig (algo importante).
    • Por este motivo, no obtiene puntos de bonificación por ocultar la inserción de la terminación nula de la cadena de destino, permitiéndole que forme parte del código de copia. En su lugar, haga que la inserción de terminación nula sea explícita, para mostrar que no ha logrado hacerlo bien por accidente.

    Que haría yo:

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

    En este código, la cadena de origen “str_untrimmed” queda intacta, lo que está garantizado al usar la corrección de const correcta. No se bloquea si la cadena de origen no contiene nada más que una terminación nula. Siempre nulo termina la cadena de destino.

    La asignación de memoria se deja a la persona que llama. El algoritmo solo debe enfocarse en hacer su trabajo previsto. Elimina todos los espacios en blanco.

    No hay trucos sutiles en el código. No trata de meter tantos operadores como sea posible en una sola línea. Será un candidato muy pobre para el IOCCC . Sin embargo, producirá prácticamente el mismo código de máquina que las versiones más oscuras de una sola línea.

    Sin embargo, al copiar algo, puede optimizar un poco declarando ambos punteros como restrict , que es un contrato entre el progtwigdor y el comstackdor, donde el progtwigdor garantiza que el destino y la fuente no son la misma dirección (o más bien, que los datos que señalar a solo se accede a través de ese mismo puntero y no a través de otro puntero). Esto permite una optimización más eficiente, ya que el comstackdor puede copiar directamente desde el origen al destino sin memoria temporal en el medio.

    En C, puede reemplazar algunas cadenas en el lugar, por ejemplo, una cadena devuelta por strdup ():

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

    Otras cadenas son de solo lectura, por ejemplo, aquellas declaradas en código. Tendría que copiarlos en un área de memoria recientemente asignada y completar la copia omitiendo los espacios:

     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); 

    Puedes ver por qué las personas inventaron otros idiomas;)

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

    Notas;

    • Esto no maneja Unicode.

    si todavía está interesado, esta función elimina espacios del principio de la cadena, y acabo de tenerlo funcionando en mi código:

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

    La manera más fácil y eficiente de eliminar espacios de una cadena es simplemente eliminar los espacios del literal de la cadena. Por ejemplo, use su editor para ‘buscar y reemplazar’ "hello world" con "helloworld" , ¡y listo!

    De acuerdo, sé que eso no es lo que querías decir. No todas las cadenas provienen de literales de cadena, ¿verdad? Suponiendo que esta cadena de la que desea eliminar los espacios no proviene de un literal de cadena, debemos considerar el origen y el destino de su cadena … Tenemos que considerar todo su algoritmo, qué problema real está tratando de resolver, en para sugerir los métodos más simples y óptimos.

    Tal vez su cadena proviene de un archivo (por ejemplo, stdin ) y está destinada a ser escrita en otro archivo (por ejemplo, stdout ). Si ese es el caso, me preguntaría por qué necesita convertirse en una cadena en primer lugar. Solo trátalo como si fuera un flujo de personajes, descartando los espacios a medida que te encuentres con ellos …

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

    Al eliminar la necesidad de almacenar una cadena, no solo el progtwig completo se vuelve mucho, mucho más corto, sino que teóricamente también es mucho más 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)); } 

    Supongo que la cadena C está en una memoria fija, por lo que si reemplazas espacios tienes que cambiar todos los caracteres.

    Lo más fácil parece ser crear una nueva cadena e iterar sobre la original y copiar solo caracteres que no sean espacios.

    ¡Es lo más fácil que pude pensar (PROBADO) y 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 tomado de la 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; } 

    Ejemplo 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 

    Si tiene un error en el código zString, puede que le resulte útil https://github.com/fnoyanisi/zString

    Encontré una variación de esta pregunta en la que necesitas reducir los espacios múltiples en un espacio para “representar” los espacios.

    Esta es mi solución:

     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 eso ayude 🙂