2012-03-27 14 views
15

Estoy intentando eliminar un carácter de una cadena en C. El problema que tengo con mi código es que elimina la primera instancia del carácter de la cadena, pero también lo limpia todo después de ese carácter en la cadena. Por ejemplo, la eliminación de 'L' de impresiones 'hola' 'él' en lugar de 'Heo'¿Cómo eliminar todas las apariciones de un carácter dado de una cadena en C?

int i; 
char str1[30] = "Hello", *ptr1, c = 'l'; 
ptr1 = str1; 
for (i=0; i<strlen(str1); i++) 
{ 
    if (*ptr1 == c) *ptr1 = 0; 
    printf("%c\n", *ptr1); 
    ptr1++; 
} 

necesito utilizar punteros para este y me gustaría mantenerlo tan simple como sea posible ya que soy un principiante en C. Gracias

+1

Sugerencia: durante la eliminación, desea desplazar las otras letras para cubrir las que quita. '* ptr1 = 0;' no es la forma de hacerlo. –

+0

También está utilizando un for/loop para direccionar el índice de cada char, pero nunca está utilizando el índice real (Valor de i) –

+0

Otra cosa para recordar, en CS, las cadenas terminan nulamente. –

Respuesta

20

Puede hacerlo de esta manera:

void remove_all_chars(char* str, char c) { 
    char *pr = str, *pw = str; 
    while (*pr) { 
     *pw = *pr++; 
     pw += (*pw != c); 
    } 
    *pw = '\0'; 
} 

int main() { 
    char str[] = "llHello, world!ll"; 
    remove_all_chars(str, 'l'); 
    printf("'%s'\n", str); 
    return 0; 
} 

La idea es mantener una lectura separada y escribir punteros (pr para la lectura y pw para la escritura), siempre avanzar el puntero de lectura, y hacer avanzar el puntero de escritura solo cuando no apunta a un personaje dado.

+0

Gracias por la respuesta simple y la descripción, eso lo resolvió. También gracias por la contribución de todos los demás. – boutrosc

+0

¿Por qué http://melpon.org/wandbox/permlink/qZPdItEH7hjg4sl3 produce un error de segmentación? ¿Cuál es la diferencia entre '* pw = * ptr ++;' y '* pw = (* ptr) ++;' – Destructor

+0

@Destructor '* pw = * ptr ++' incrementa el puntero (correcto), mientras que '(* ptr) ++' incrementa el caracter (incorrecto). – dasblinkenlight

-1

C define una cadena como "una secuencia contigua de caracteres terminados por e incluyendo la primera carácter nulo"

+1

Es cierto, pero apenas una respuesta explicativa a la pregunta. –

0

simplemente cambiar

if (*ptr1 == c) *ptr1 = 0; 

a

if (*ptr1 == c) continue; 

como @ouah Dicho esto, se rompe en el primer carácter NULL ..

+0

Eso no es una solución suficiente. –

1

El problema es que cuando se encuentra con el primer personaje que se adapte c, se inserta un carácter nulo justo ahí. Eso significa que esencialmente estás cortando el resto de la cadena.

Lo que debe hacer es cuando encuentre un carácter coincidente, mueva los siguientes caracteres hacia atrás una posición. Luego debe insertar el carácter nulo al final dependiendo de la cantidad de caracteres que haya eliminado.

2
char str1[30] = "Hello", *prt1, c = 'l'; 
char str2[30], *prt2; 
prt1 = str1; 
prt2 = str2; 
while(*prt1 != 0) 
{ 
    if(*prt1 != c) 
    { 
     *prt2 = *prt1; 
     prt2++; 
    } 
    prt1++; 
} 
*prt2 = '\0'; 
4

Si elimina los caracteres en el lugar que tendrá que pasar el resto de la cadena de un lugar a la izquierda, cada vez que se quita un carácter, esto no es muy eficiente. La mejor manera es tener una segunda matriz que tome la cadena filtrada. Por ejemplo, puedes cambiar tu código así.

int i; 
char str1[30] = "Hello", *ptr1, c = 'l'; 
char str2[30] = {0}, *ptr2; 
ptr1 = str1; 
ptr2 = str2; 
for (i=0; i<strlen(str1); i++) 
{ 
    if (*ptr1 != c) *ptr2++=*ptr1; 
    ptr1++; 
} 
printf("%s\n", str2); 
+1

Excepto que realmente no debería llamar 'strlen()' en la condición de un bucle como ese, esta es una buena respuesta. De acuerdo, es un error heredado del código en la pregunta, pero ... –

+0

@Jonathan Leffler, esta respuesta comete algunos errores fundamentales que evitan que sea una buena respuesta. No es necesario desplazar los restos de la cuerda hacia la izquierda cada vez que se elimina un carácter. Eso implicaría un bucle anidado, que la respuesta demuestra que no es necesario. Además, no importa si copia el carácter de una cadena a otra, porque es el mismo bloque de RAM. De hecho, probablemente sea más ineficiente utilizar una segunda cadena, porque corre el riesgo de perder una memoria caché utilizando un bloque de memoria distante. –

1

sé que es un tipo de respuesta duplicada, pero este código es la versión de la función para resolver el problema. Pensé que como el que preguntaba era un principiante, podría aprender mucho de la versión descompuesta del problema.

int del_x_char(char *p, int x) 
{ 
    char *q; 
    x=first_occurance(p, 'i')/*you can replace any character that you want delete with 'i'*/ 
    q=p+x; 
    while(*q=*(q+1)) 
     q++; 
    *q='\0'; 
    return 0; 
} 
int first_occurance(char *q, char phar) 
{ 
    int i=0; 
    while(*q) 
    { 
     if(*q++==phar) 
      return i; 
     i++; 
    } 
    return -1; 
} 
Cuestiones relacionadas