2010-11-29 9 views
5

Soy nuevo en C, y estoy tratando de escanear una línea de stdin y extraer la enésima palabra de ella. Ahora he modificable donde pueda almacenar la primera, segunda o tercera entrada, en la oración, y esto es lo que parece:sscanf: obtener la enésima palabra en una oración

int set_to_nth_word(char* word, char* input, int n) 
{ 
    char word1[20]; 
    char word2[20]; 
    char word3[20]; 
    if(sscanf(input, "%s %s %s", word1, word2, word3) < n) 
    { 
     printf("You didn't enter enough values\n"); 
     return 0; 
    } 
    else 
    { 
     if(n == 1) strcpy(word, word1); 
     else if(n == 2) strcpy(word, word2); 
     else if(n == 3) strcpy(word, word3); 
     return 1; 
    } 
} 

El código que llama a este método es:

char *input = (char *) malloc (1); 
if(getline(&input, (size_t)0, stdin) != -1) 
{ 
    char word[20]; 
    if(set_to_nth_word(word, input, 1)) 
    { 
     printf("Success"); 
    } 
} 

Además de encontrar una solución a este problema, me alegra que alguien señale un mal estilo o malas prácticas de codificación.

+2

Tenga en cuenta que getline() aquí hay una función de GNU y no es en todas las plataformas POSIX. (Mac OS X no lo tiene, por ejemplo.) – chrisaycock

Respuesta

9

Puede utilizar el especificador de conversión %n compatible con sscanf(). Requiere un parámetro int * y devuelve el número de caracteres consumidos de la entrada en ese int.

int set_to_nth_word(char *word, const char *input, int n) 
{ 
    int chars_used; 

    word[0] = '\0'; /* In case n < 1 */ 

    while (n > 0 && sscanf(input, "%s%n", word, &chars_used) > 0) 
    { 
     input += chars_used; 
     n--; 
    } 

    if (n > 0) 
    { 
     printf("You didn't enter enough values\n"); 
     return 0; 
    } 

    return 1; 
} 

En cuanto al estilo se va, usted debe hacer que el parámetro inputconst char *, ya que los personajes a los que hacen modificados en la función.

En términos de seguridad, word debe asignarse con una longitud de strlen(input) + 1, en lugar de declararse como una matriz de tamaño fijo, ya que las palabras pueden ser de esa longitud.

+0

¡Funcionó muy bien (también tiene sentido)! – Petwoip

2

Aquí hay algunos consejos:

  • en lugar de escanear un número fijo de palabras, n bucle de tiempo de análisis una sola palabra

  • uso strtok en lugar de sscanf para esto; se le hará la vida mucho más fácil

  • tratar de evitar límites compilados dentro de cuánto tiempo puede ser una palabra (20), sobre todo cuando no se está comprobando si se exceden estos límites

  • evite copiar innecesariamente datos de cadena al escanearlo, especialmente (como se indicó anteriormente) cuando no está imponiendo límites de longitud en sus llamadas Strcpy. El uso de strtok ubicará las palabras dentro de la entrada con cero copias.

0

¿Deberes? A medida que avanzan las asignaciones de tarea, es un poco interesante, ya que tienta a uno a implementar una solución cruda y limitada, pero que permite una verdadera solución bastante fácil.

De todos modos, aquí está mi tiro en él ...

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

int set_to_nth_word(char *word, const char *input, int n) { 
    int i; 
    size_t used = 0; 
    char convert[1000]; 
    static const char convertPattern[] = " %*s"; 
    static const char convertReal[] = " %s"; 

    if((unsigned)n > sizeof convert/sizeof convertPattern - 1) 
    return 0; 
    for(i = 1; i < n; ++i) 
    used += sprintf(convert + used, "%s", convertPattern); 
    sprintf(convert + used, "%s", convertReal); 
    return sscanf(input, convert, word) == 1; 
} 

int main(int ac, char **av) { 
    static char space[1000]; 
    static char wordn[1000]; 

    if (ac > 1) { 
    fgets(space, sizeof space, stdin); 
    if(set_to_nth_word(wordn, space, atoi(av[1]))) 
     printf("%s\n", wordn); 
    } 
    return 0; 
} 
Cuestiones relacionadas