2010-09-21 61 views
9

Problema: Necesito poder identificar cuándo se producen dos espacios en blanco consecutivamente.¿Cómo leo el espacio en blanco usando scanf en c?

He leído las siguientes preguntas:

how to read a string from a \n delimited file

how to read scanf with spaces

y soy consciente de los problemas scanf: http://c-faq.com/stdio/scanfprobs.html

entrada será en el siguiente formato:

1 5 3 2 4 6 2 1 9 0 

Dos espacios en blanco indican que el siguiente conjunto de datos debe manejarse y compararse consigo mismo. La longitud de la línea es desconocida y se desconoce el número o enteros en cada grupo. Dos espacios en blanco es lo máximo que separará el siguiente conjunto de datos.

Aunque puedo usar los fgets y varias funciones integradas para resolver este problema, estoy en el punto en que es más fácil resolver el problema con scanf en este momento. Sin embargo, si ese no es el caso, usar fgets, strtok y atoi hará la mayor parte del trabajo, pero aún necesito identificar dos espacios en blanco seguidos.

Lo siguiente tomará enteros hasta que se ingrese un entero no entero.

 
while (scanf ("%d", &x) == 1) 

Lo que necesito que hacer es leer los espacios en blanco, así y si hay dos espacios en blanco consecutivos que va el programa para hacer algo diferente con el siguiente conjunto de datos.

Y una vez que me pongo un espacio en blanco que no sé cómo decir:

 
if ((input == "whitespace") && (previousInput == "whitespace")) 
    ya da ya da 
else (input == "whitespace") 
    ya da ya da 
else 
    ya da ya da 

Gracias por su tiempo y gracias por su ayuda.

lección aprendida: Mientras que una solución para scanf se publica a continuación por Jonathan Leffler, la solución fue un poco más directo con getc (a modo de requerir menos conocimiento íntimo de la scanf interior, las expresiones regulares y carbón de leña). En retrospectiva, un mejor conocimiento de las expresiones regulares, scanf y char facilitaría el problema y, por supuesto, conocería qué funciones están disponibles y cuál de ellas habría sido la mejor para usar desde el principio.

+2

Eso es un formato de entrada bastante espantosa. Si estás a cargo de ello, rediseña. Si, como sospecho, se te ha asignado una tarea, mala suerte, son un grupo sádico, tus profesores. –

+3

Tenga en cuenta que 'espacio en blanco' es diferente de 'dos ​​espacios'; 'espacio en blanco' significa convencionalmente una variedad de caracteres posibles, que incluyen tabulación y espacio en blanco (y espacio), y algunas veces forman alimentación, tabulación vertical o nueva línea; y ocasionalmente retrocede también. –

+0

@Jonathan Leffler: al menos no está tratando de analizar Whitespace (http://compsoc.dur.ac.uk/whitespace/) – ninjalj

Respuesta

6

getcungetc y son sus amigos

#include <stdio.h> 

int main(void) { 
    int ch, spaces, x; 
    while (1) { 
    spaces = 0; 
    while (((ch = getc(stdin)) != EOF) && (ch == ' ')) spaces++; 
    if (ch == EOF) break; 
    ungetc(ch, stdin); 
    if (scanf("%d", &x) != 1) break; 
    printf("%d was preceded by %d spaces\n", x, spaces); 
    } 
    return 0; 
} 

demo en http://ideone.com/xipm1

Editar Rahhhhhhhhh ...Lo cargué como C++. Aquí está exactamente lo mismo, pero ahora C99 strict (http://ideone.com/mGeVk)

+0

scanf, sscanf, fscanf, fgets, get, getc ... lol tantas opciones. Tendré que leer sobre getc y ungetc. Gracias por la respuesta. – MykC

+0

+1 porque 'getc()' y 'ungetc()' son una mejor manera de hacerlo que tratar de usar simplemente 'scanf()' - pero evade la pregunta un poco. –

+4

@MykC: ** ¡No, NO se consigue! NO USE NUNCA, NUNCA ** – pmg

1
while (scanf ("%c", &x) == 1) 

Usando %c se puede leer caracteres de espacio en blanco, sólo tiene que leer todos los datos que se almacenan en la matriz. A continuación, asigne char* cptr y configure cptr para comenzar la matriz, luego analice la matriz y si desea leer números decimales, puede usar simplemente sscanf en cptr mientras desea leer el decimal, pero debe tener el puntero en una posición correcta en la matriz (en número wany lo lea)

if (((*(cptr + 1)) == ' ') && ((*cptr)== ' ')) 
    ya da ya da 
else ((*cptr)== ' ')) 
    ya da ya da 
    sscanf(++cptr, "%d", &x); 
else 
    ya da ya da 
+0

Se ve bien. Evito el uso de punteros y matrices si puedo. Nota: Aunque usaré punteros y matrices cuando tenga sentido. – MykC

+0

Me mentiné en comentarios de alguien más que parece que si hubiera uno o más espacios en blanco, todos serían almacenados en un único carácter, por lo que no pudo funcionar el método anterior. – MykC

0

¿Cuál es su definición de 'espacio en blanco'?

Francamente, no creo que me gustaría intentar usar scanf() para identificar espacios blancos dobles; casi cualquier otro método sería mucho más fácil.

Sin embargo, si insiste en hacer el no desesperadamente sensible, entonces es posible que desee utilizar código derivado de los siguientes:

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

int main(void) 
{ 
    int d; 
    char sp[3] = ""; 
    int n; 

    while ((n = scanf("%d%2[ \t]", &d, sp)) > 0) 
    { 
     printf("n = %d; d = %d; sp = <<%s>>", n, d, sp); 
     if (n == 2 && strlen(sp) == 2) 
      printf(" end of group"); 
     putchar('\n'); 
    } 
    return 0; 
} 

Los corchetes encierran una clase de caracteres y el 2 antes de que insiste en por lo la mayoría de los 2 personajes de la clase. Puede que tenga que preocuparse por la lectura de la nueva línea e intentar obtener más datos para satisfacer la clase de caracteres, lo que podría resolverse eliminando la nueva línea de la clase de caracteres. Pero luego depende de su definición de espacio en blanco, y de si los grupos terminan automáticamente con una nueva línea o no. No estaría de más reajustar sp[0] = '\0'; al final del ciclo.

Puede que sea mejor invertir los campos para detectar dos espacios antes de un número. Pero eso fallaría en el caso ordinario, entonces recurrirías a un formato simple "%d" para leer el número (y si eso falla, sabes que no tienes ni espacios ni un número - error). Tenga en cuenta que %d mastica el espacio en blanco inicial (como lo define el estándar), todos ellos.

Cuanto más lo miro, menos me gusta 'scanf() solamente. Recuérdame que no tome una clase en tu universidad, por favor.

+1

Creo que solo tengo que preocuparme por un espacio en blanco que sea una sola ranura de caracteres en blanco o ''. No estoy apegado a scanf, solo estoy apegado a hacerlo de la manera más fácil, asumiendo que tengo que hacerlo de nuevo y no solo hacer el trabajo. Solo quería ver si había una expresión regular o un truco con scanf que podría pasarse por alto que resolvería el problema de manera muy fácil ya que la entrada está formateada. – MykC

+0

He estado buscando su respuesta y parece que scanf en su ejemplo siempre devolverá 2. Actualmente estoy investigando qué rango de valores puede devolver scanf y por qué. – MykC

+0

Me corrigieron, no siempre devuelve 2. – MykC

0

Si realmente quiere scanf funcionalidad tipo, puede utilizar fgets y sscanf, y utilizar el especificador %n para obtener scanf para darle a su programa de los desplazamientos para el inicio y final de cada período de espacios en blanco al mismo tiempo que lo hace el resto de su trabajo.

De lo contrario, abandone toda la familia scanf. Es posiblemente la parte más inútil de la biblioteca estándar, en mi opinión.

+0

Es útil, pero generalmente malo. Si desea agregar la entrada equivalente a una declaración de impresión de depuración a un programa, entonces es genial. Si desea agregar una entrada simple para una prueba o programa de demostración (donde las buenas prácticas de entrada no son lo que está demostrando), entonces es bastante bueno. Si quieres ingresar para el código de producción, es realmente malo. – nategoose

+0

En realidad, hay un uso para 'scanf': una versión portátil de' getline' (o 'getdelim'), que incluye el manejo limpio de caracteres NUL incrustados, se puede lograr con algo como' scanf ("% 99 [^ \ n] % n ", buf, &cnt);' (donde 99 se reemplaza por el tamaño del búfer). –

+0

'scanf ("% 99 [^ \ n]% n ", buf, &cnt);' tiene el problema de que no guarda nada en 'buf' y 'cnt' si la entrada comienza con' '\ n'' y deja ese '' \ n'' en stdin. Esto no es como' getline() '. – chux

0

Aquí hay una solución que usa solo la función scanf(). Usé sscanf() en esta muestra para obtener la misma funcionalidad.

#include <stdio.h> 


int p_1_cnt = 0, p_2_cnt = 0; 

void process_1(int x) 
{ 
    p_1_cnt++; 
} 


void process_2(int x) 
{ 
    p_2_cnt++; 
} 


char * input_line = "1 5 3 2 4 6 2 1 9 0"; 

int main(void) 
{ 
    char * ip = input_line; 

    int x = 0, ws_0 = 0, ws_1 = 0, preceding_spaces = 1, fields = -2; 

    while (sscanf (ip, "%d%n %n", &x, &ws_0, &ws_1) > 0) 
    { 
     ip += ws_0; 

     if ((preceding_spaces) == 1) 
      process_1(x); 
     else 
      process_2(x); 

     preceding_spaces = ws_1 - ws_0; 
    } 

    printf("\np_1_cnt = %d, p_2_cnt = %d", p_1_cnt, p_2_cnt); 
    _fgetchar(); 

    return 0; 
} 
Cuestiones relacionadas