C función que sale antes de la entrada

Actualmente estoy haciendo un proyecto para una clase de progtwigción para principiantes en la que se supone que debo hacer un sistema de pedidos básico para una empresa. Tengo un problema con una de mis funciones, funciona bien como un progtwig separado, pero como una función en el progtwig de pedidos no me permite ingresar un nuevo elemento antes de salir de la función. Sin embargo, parece que se ejecuta a través de todo después de obtener (item); a medida que obtengo el \ n agregado cada vez que lo ejecuto.

Aquí está mi código:

do{ printf("Menu here"); scanf("%c", &menu); switch(menu) { case 'A': listItem(); break; case 'B': addItem(); break; ... case 'X': break; } printf("Press Enter to continue."); scanf("%c%c", &enter, &enter); system("cls"); }while(menu != 'X'); void addItem() { char item[30]; printf("\nAdd new item: "); gets(item); FILE * output; output = fopen("items.txt", "a"); fputs(item, output); fprintf(output, "\n"); fclose(output); } 

lo que sucedió después del cambio es lo que mi maestro pensó que sería una manera fea pero efectiva de resolver el hecho de que no profundizamos en lo que él llamó las “peculiaridades de la entrada de C” en este curso.

Estoy agradecido por los consejos y respuestas, y proporcionaré más de mi código si es necesario.

Lo que está pasando es esto:

  1. Progtwig imprime el menú.
    • Tipos de usuario “B “.
    • scanf lee el carácter B El todavía está esperando en el flujo de entrada.
    • Se llama addItem .
    • Se llama a gets() , lee el que aún está en espera y devuelve una línea vacía.

Puede corregirlo leyendo y descartando todo hasta e incluyendo la próxima nueva línea después de leer el carácter de selección de menú con scanf :

 int c; printf("Menu here"); scanf("%c", &menu); do { c = getchar(); } while (c != EOF && c != '\n'); 

Estás leyendo un carácter a la vez, y scanf() está haciendo algo de búfer. Si escribo “ABC” y presiono enter, su progtwig leerá ‘A’, hará la acción para ‘A’, imprima “hit enter para continuar”, leyendo ‘B’ y ‘C’ en el scanf que sigue inmediatamente. Así que, por supuesto, va a volver temprano; ya le has dado algún comentario, a saber, ‘B’ y ‘C’.

Te sugiero que utilices otro método para tomar información. Por ejemplo, podría cambiar a comandos basados ​​en líneas (tal vez utilizando fgets() ), que requieren que fgets() enter en cada paso. O puede usar curses o cualquier cosa específica de la plataforma que necesite para hacer una entrada sin búfer, de modo que reaccione a las teclas presionadas y no al búfer provisto por stdio .

Una cosa inmediata que noté. El bucle do while while está comprobando que val "X" mientras que ese valor está realmente en el menu .

Aparte de esa posibilidad (para empezar, val puede ser "X" , lo que podría causar la salida del bucle sin importar el valor ingresado), nada salta, lo que obviamente causa una salida prematura de una función o bucle. Creo que será mejor que publiques tu código base completo para que no estemos adivinando demasiado.

Actualizar:

No use lo siguiente para hacer la tarea: es casi seguro que se le fallará por plagio (ya que sus educadores, asumiendo que no son tontos, estarán atentos al trabajo tomado de estos sitios).

Solo quería darle una idea de lo que puede usar para la E / S de usuario para hacer que sus progtwigs sean un poco más sólidos. Como señaló una persona útil, nunca debe usar las rutinas de entrada que no tienen la protección contra sobrecargas del búfer como una opción, ya que es casi seguro que la entrada maliciosa pueda bloquear su código (ese es el mejor de los casos, el peor de los casos es que se hará cargo de su computadora).

Eso significa que no se gets , necesita usar fgets ya que puede limitar la cantidad de información que se ingresa. Además, tiendo a evitar el uso de scanf y fscanf ya que cualquier falla en esas funciones en realidad deja al puntero del archivo de entrada en una ubicación indeterminada.

Me parece que es mucho mejor usar fgets para obtener una línea completa, verifique que en realidad tenga una línea completa, luego use sscanf en esa línea. De esa manera, puede estar seguro de que está en un límite de línea, de que tiene una línea completa y de que luego puede sscanf esa línea hasta el contenido de su corazón hasta que coincida con algo.

Para ese fin, es posible que desee revisar el siguiente código:

 #include  #define FSPEC "file.txt" // Skip to the end of the line. This is used in some // places to ensure there's no characters left in the // input buffer. It basically discards characters // from that buffer until it reaches the end of a line. static void skipLine (void) { char ch = ' '; while ((ch != '\n') && (ch != EOF)) ch = getchar(); } 

 // Get a line of input from the user (with length checking). static char *getLine (char *prompt, char *line, int sz) { // Output prompt, get line if available. // If no line available (EOF/error), output newline. printf ("%s", prompt); if (fgets (line, sz, stdin) == NULL) { printf ("\n"); return NULL; } // If line was too long (no '\n' at end), throw away // rest of line and flag error. if (line[strlen (line) - 1] != '\n') { skipLine(); return NULL; } // Otherwise line was complete, return it. return line; } 

 // Output the menu and get a choice from the user. static char doMenu (void) { char cmd[1+2]; // need space for char, '\n' and '\0'. // Output the menu. printf ("\n"); printf ("\n"); printf ("Main menu\n"); printf ("---------\n"); printf ("1. Input a line\n"); printf ("2. Output the file\n"); printf ("3. Clear the file\n"); printf ("\n"); printf ("x. Exit\n"); printf ("\n"); // Get the user input and return it. if (getLine ("Enter choice (1,2,3,x): ", cmd, sizeof(cmd)) == NULL) return '\n'; printf ("\n"); return cmd[0]; } 

 static void doOption1 (void) { FILE *fh; char *ln; char buff[15+2]; // need space for line, '\n' and '\0'. // Get and check line, add to file if okay. if ((ln = getLine ("Enter line: ", buff, sizeof(buff))) == NULL) { printf ("Bad input line\n"); } else { fh = fopen (FSPEC, "a"); if (fh != NULL) { fputs (ln, fh); fclose (fh); } } } 

 static void doOption2 (void) { FILE *fh; int intch; // Output the file contents. printf ("=====\n"); fh = fopen (FSPEC, "r"); if (fh != NULL) { while ((intch = fgetc (fh)) != EOF) putchar (intch); fclose (fh); } printf ("=====\n"); } 

 static void doOption3 (void) { FILE *fh; // Clear the file. fh = fopen (FSPEC, "w"); if (fh != NULL) fclose (fh); } 

 // Main program basically just keeps asking the user for input // until they indicate they're finished. int main (void) { char menuItem; // Get asking for user input until exit is chosen. while ((menuItem = doMenu()) != 'x') { switch (menuItem) { case '1': doOption1(); break; case '2': doOption2(); break; case '3': doOption3(); break; default: printf ("Invalid choice\n"); break; } } return 0; }