2009-10-03 20 views

Respuesta

14

Esto funciona en mis pruebas rápidas y sucias. Lo hace en su lugar:

#include <stdio.h> 

void strip(char *s) { 
    char *p2 = s; 
    while(*s != '\0') { 
     if(*s != '\t' && *s != '\n') { 
      *p2++ = *s++; 
     } else { 
      ++s; 
     } 
    } 
    *p2 = '\0'; 
} 

int main() { 
    char buf[] = "this\t is\n a\t test\n test"; 
    strip(buf); 
    printf("%s\n", buf); 
} 

Y para apaciguar a Chris, aquí es una versión que hará una copia de primera y devolverlo (por lo tanto que va a trabajar en los literales). Necesitará free el resultado.

char *strip_copy(const char *s) { 
    char *p = malloc(strlen(s) + 1); 
    if(p) { 
     char *p2 = p; 
     while(*s != '\0') { 
      if(*s != '\t' && *s != '\n') { 
       *p2++ = *s++; 
      } else { 
       ++s; 
      } 
     } 
     *p2 = '\0'; 
    } 
    return p; 
} 
+0

No es seguro realizar esta operación en su lugar. ¿Qué ocurre si la primera línea de 'main()' cambia a 'char * buf = ...;'? ¿Qué pasaría si esto se usara en un código más intrincado y los codificadores hubieran olvidado qué argumentos eran almacenamientos intermedios grabables y cuáles no? –

+0

si necesita hacerlo en una copia, siempre puede hacer primero una copia. Tal código es aún bastante simple. –

+0

@Lutz, no veo cómo pasar 'char *' o 'char []' hace la diferencia. Además, hay un error en 'strip': la cadena no termina en nulo. – strager

3

Básicamente, usted tiene dos maneras de hacer esto: se puede crear una copia de la cadena original, menos todos los '\t' y '\n' caracteres, o se puede despojar a la cadena "in situ". Sin embargo, apuesto a que la primera opción será más rápida y te prometo que será más seguro.

así que haremos una función:

char *strip(const char *str, const char *d); 

Queremos usar strlen() y malloc() para asignar un nuevo char * la memoria intermedia del mismo tamaño que nuestro buffer str. Luego pasamos por str carácter por personaje. Si el carácter es no contenido en d, lo copiamos en nuestro nuevo búfer. Podemos usar algo como strchr() para ver si cada carácter está en la cadena d. Una vez que hayamos terminado, tenemos un nuevo buffer, con el contenido de nuestros viejos caracteres de buffer menos en la cadena d, así que solo devolvemos eso. Yo no le dará código de ejemplo, ya que esto podría ser la tarea, pero aquí está el uso de muestra para mostrarle cómo resuelve su problema:

char *string = "some\n text\t to strip"; 

char *stripped = strip(string, "\t\n"); 
+0

+1 para proporcionar toda la información necesaria para aprender ** cómo ** hacerlo. Las probabilidades son que él es un principiante y esta información será útil. –

4

Si desea reemplazar \ no \ t con otra cosa, puede usar la función strstr(). Devuelve un puntero al primer lugar en una función que tiene una cierta cadena. Por ejemplo:

// Find the first "\n". 
char new_char = 't'; 
char* pFirstN = strstr(szMyString, "\n"); 
*pFirstN = new_char; 

Puede ejecutar eso en un bucle para encontrar todos \ ns y \ t's.

Si desea "pelarlos", es decir, eliminarlos de la cadena, tendrá que utilizar el mismo método que el anterior, pero copie el contenido de la cadena "volver" cada vez que encuentre una \ n o \ t, de modo que "esto es una prueba" se convierte en "esto es una prueba".

Usted puede hacer eso con memmove (no establecimiento de memoria, ya que el src y dst están apuntando a la memoria superpuestas), así:

char* temp = strstr(str, "\t"); 
// Remove \n. 
while ((temp = strstr(str, "\n")) != NULL) { 
// Len is the length of the string, from the ampersand \n, including the \n. 
    int len = strlen(str); 
memmove(temp, temp + 1, len); 
} 

Tendrá que repetir este bucle de nuevo para eliminar los \ t de .

Nota: Ambos métodos funcionan en el lugar. ¡Esto podría no ser seguro! (Lea los comentarios de Evan Teran para obtener más información.. Además, estos métodos no son muy eficientes, aunque sí utilizan una función de biblioteca para algunos códigos en lugar de los propios.

+0

esto parece que sería muy ineficiente para una cadena larga. Está buscando la cadena (desde el principio) una y otra vez. Además, estás haciendo un strlen cada vez que se encuentra un char). Finalmente, está copiando el final de la cadena cada vez que se encuentra un carácter ... –

+0

Tiene razón, la eficiencia definitivamente no era una gran preocupación (esto es en realidad un levantador directamente del código que tenía por ahí, que solo funcionaba) con cuerdas pequeñas). El strlen realmente se puede mover fuera de la cadena, creo, y la búsqueda puede comenzar cada vez desde la última ubicación encontrada en lugar del comienzo, anulando el "problema de búsqueda cada vez". Sin embargo, no veo ninguna forma de eliminar la necesidad de memmove, si él quiere que se haga en su lugar. ¿Alguna sugerencia? –

+0

Si quiere ver una tira eficiente en el lugar, entonces mire mi respuesta :-P. –

1

Esta es una función de cadena de caracteres que encontrará carácter en accept y devolver un puntero a esa posición o NULL si no se encuentra.

#include <string.h> 

char *strpbrk(const char *s, const char *accept); 

Ejemplo:

char search[] = "a string with \t and \n"; 

char *first_occ = strpbrk(search, "\t\n"); 

first_occ apuntará a la \ t, o el carácter 15 en search. Puede reemplazar y luego volver a llamar para pasar al siguiente ciclo hasta que todos hayan sido reemplazados.

0

Me gusta hacer que la biblioteca estándar haga la mayor parte del trabajo posible, así que usaría algo similar a la solución de Evan pero con strspn() y strcspn().

#include <stdio.h> 
#include <stdlib.h> 
#include <string.h> 

#define SPACE " \t\r\n" 

static void strip(char *s); 
static char *strip_copy(char const *s); 

int main(int ac, char **av) 
{ 
    char s[] = "this\t is\n a\t test\n test"; 
    char *s1 = strip_copy(s); 
    strip(s); 
    printf("%s\n%s\n", s, s1); 
    return 0; 
} 

static void strip(char *s) 
{ 
    char *p = s; 
    int n; 
    while (*s) 
    { 
     n = strcspn(s, SPACE); 
     strncpy(p, s, n); 
     p += n; 
     s += n + strspn(s+n, SPACE); 
    } 
    *p = 0; 
} 

static char *strip_copy(char const *s) 
{ 
    char *buf = malloc(1 + strlen(s)); 
    if (buf) 
    { 
     char *p = buf; 
     char const *q; 
     int n; 
     for (q = s; *q; q += n + strspn(q+n, SPACE)) 
     { 
      n = strcspn(q, SPACE); 
      strncpy(p, q, n); 
      p += n; 
     } 
     *p++ = '\0'; 
     buf = realloc(buf, p - buf); 
    } 
    return buf; 
} 
Cuestiones relacionadas