Pregunta sobre c – la caja del interruptor no funciona correctamente en C

2

En mi programa hay un problema menor.

Cuando presiono 2 o 3 o 4, se mostrará correctamente, pero después de eso, cuando presiono a o b o c, etc., mostrará un resultado anterior en lugar de imprimir la opción No válida.

¿Cómo puedo arreglar esto?

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

    typedef struct vehicle
    {
    char name[100];
    char lice_no[25];
    int vehicle_type;
    char cmpny_name[100];
    int menu_year;
     }record;

    int main(void)
    {
    int i,choice;
    FILE *fp1,*fp2;
    char oname[100];
    record det,det1;
    int recsize;
    char c;

    fp1 = fopen("record.dat" , "r+");
    if(fp1 == NULL)
    {
        fp1 = fopen("record.dat" , "w+");
        if(fp1 == NULL)
        {
            printf("error in opening file : \n");
            return -1;
        }
    }
    recsize = sizeof(det);

    do
    {
        printf("\t\"enter the choice\"\n");

        printf("1 : adding the record\n");
        printf("2 : delete the record\n");
        printf("3 : editing the record\n");
        printf("4 : display the record\n");
        printf("5 : exit the program\n");


        fflush(stdin);
        scanf("%d" , &choice);
        scanf("%c" , &c);

        switch(choice)
        {
            case 1 :
            {
                    printf("In this add logic\n")
                break;
            }
            case 2 :
            {
                printf("In this case delete logic\n");
                break;
            }
            case 3 :
            {
                printf("In this case edit logic\n");
                                break;
            }
            case 4 :
            {
                printf("display logic\n");
                break;
            }
            case 5 :
            {
                printf("exit logic\n");
                break;
            }
            default :
            {
                printf("\"Invalid option\"\n");
                break;
            }
        }
    }
    while(1);
    return 0;
}
@ArjunShankar:fgetc() no leerá nada hasta que escriba nueva línea, y luego tendrá que lidiar con omitir la nueva línea. Ciertamente, es factible; No sería lo que yo recomendaría. Jonathan Leffler
fflush(stdin); túno poder Haz eso.fflush no es para flujos de entrada. No se puede "vaciar" una secuencia de ENTRADA.fflush es para transmisiones de SALIDA (por ejemplo, para asegurarse de que todo lo que imprima se envíe al terminal) ArjunShankar
@MikeKwan - Definitivamente hay algo extraño en el programa. Yahora que sé lo que es, he publicado una respuesta. Buena captura sin embargo, el punto y coma! ArjunShankar
El problema es que estas usandoscanf(). Es diabólicamente difícil hacer las cosas bien. Cuando el usuario escribe una letra,scanf() para la elección falla (debe comprobar el resultado de cadascanf() para asegurarse de que funcionó, y debe manejar los errores) para que el valor no se modifique. El segundoscanf() está diseñado para recoger la nueva línea, pero cuando se escribe una letra, en su lugar, recoge la letra. Si estás en Windows,getch() Es una opción razonable. Alternativamente, usefgets() leer una línea y luegosscanf() para analizarlo Esa suele ser la estrategia más robusta. Jonathan Leffler

Tu respuesta

4   la respuesta
2

c. pero solo está utilizando la var. Choice en el conmutador, nunca está marcando la var.

Esencialmente, si golpea una letra, la almacena en la variante C y luego vuelve a utilizar el valor antiguo en Opción.

Esto tiene sentido para mí. El OP tiene un programa ligeramente extraño, y parece que has entendido lo que quieren correctamente. ArjunShankar
0

% d", & choice);) toma el código ASCII de los caracteres, por ejemplo, a = 97, b = 98 c = 99 d = 100 si desea lea a como 1 b como 2, etc. tendrá que agregar algún código adicional que le diga al programa si el número es igual al código ascii de abcd o e restarlo con 96 para que obtenga 1,2,3.

No, la opción se lee como "% d", y será un entero, el problema existe en otra parte. Antti Haapala
1

scanf Te devuelve un valor que no verificas.

Cuando se utiliza con%d Especificador - debe analizar un entero. Dado que usted ingresa un valor no entero -scanf le devuelve un código de error, ychoice no ha cambiado

Uy, tienes razón valdo
scanf("%d" , &choice); Mat
2

Hmm, una de las cosas mal en tus códigos es la:

scanf("%c" , &c);

porque, la función scanf requiere que el usuario presione la tecla enter antes de que pueda almacenar el carácter en su variable respectiva.

Así que si el compilador lee la línea:

scanf("%c" , &c);

lee tu entrada, MÁS, el ENTER.
De este modo, obliga a la función scanf a almacenar su entrada, PLUS, el ENTER, en su variable de carácter.

Sería mejor si usara getche () o getch () en lugar de usar la función scanf (), y nunca use:

scanf("%c" , &c);

Porque generaría un error.

Muestra de uso de la función getche () o getch ():

c=getche(); //waits for a keypress and stores it on a variable
c=getch();  //waits for a keypress and stores it on a variable

la diferencia entre los dos es que el getche () muestra su pulsación de tecla mientras que el getch () no lo hace.

Nota: No te olvides de poner.

#include<conio.h>

Información adicional: si aún desea seguir usando la función scanf (), asegúrese de declarar su variable favorita como:

char c[20];

entonces puedes usar:

scanf("%s", &c);

pero su variable, solo puede contener hasta 19 caracteres, como lo declaramos en su matriz de caracteres.

Y el resumen es no usar:

scanf("%c", &c);

porque, puede afectar tus otras funciones de scanf (). :)

SOLUCIÓN (Spoiler Warning):

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

typedef struct vehicle
{
    char name[100];
    char lice_no[25];
    int vehicle_type;
    char cmpny_name[100];
    int menu_year;
}record;

int main(void)
{
    int i; //removed choice from int
    FILE *fp1,*fp2;
    char oname[100];
    record det,det1;
    char choice; //made the variable choice a character
    int recsize;
    char c;

fp1 = fopen("record.dat" , "r+");
if(fp1 == NULL)
{
    fp1 = fopen("record.dat" , "w+");
    if(fp1 == NULL)
    {
        printf("error in opening file : \n");
        return -1;
    }
}
recsize = sizeof(det);

do
{
    printf("\t\"enter the choice\"\n");

    printf("1 : adding the record\n");
    printf("2 : delete the record\n");
    printf("3 : editing the record\n");
    printf("4 : display the record\n");
    printf("5 : exit the program\n");


    fflush(stdin);
    choice = getche(); // or getch()

    switch(choice) //changed the target character
    {
        case '1' : //changed the case from 1 to '1'
        {
                printf("In this add logic\n");
                break;
        }
        case '2' : //changed the case from 2 to '2'
        {
            printf("In this case delete logic\n");
            break;
        }
        case '3' : //changed the case from 3 to '3'
        {
            printf("In this case edit logic\n");
                            break;
        }
        case '4' : //changed the case from 4 to '4'
        {
            printf("display logic\n");
            break;
        }
        case '5' : //changed the case from 5 to '5'
        {
            printf("exit logic\n");
            break;
        }
        default :
        {
            printf("\"Invalid option\"\n");
            break;
        }
    }
}
while(1);
return 0;
}

También puedes usar el interruptor para comparar caracteres. Solo cambia los valores

case 1:

a

case '1':
Hmm, no es de extrañar que otros no lo sepan. Creo que soy un poco primitivo en este idioma. Haré otra solución para esta, pero sería mucho más larga. ChinoCarloSedilla
En realidad, esto puede salir terriblemente mal. ¿Qué pasa si el usuario ingresa 100 caracteres y usted usa un búfer de 20 caracteres?scanf escribirá en las direcciones de memoria que no se deben tocar. Esto probablemente causará un error de tiempo de ejecución. ArjunShankar
Si bien el OP puede estar de acuerdo con esta respuesta, el uso de 'conio.h' suele ser una mala idea. En lo que respecta al estándar C, no existe tal cosa comoconio.h. Muchas máquinas notener a conio.h. Además, las definiciones enconio.h También tienen un comportamiento ligeramente diferente según el compilador que lo envió. Puedes leer por qué aquí:en.wikipedia.org/wiki/Conio.h ArjunShankar
@ArjunShankar gracias por esa idea. Ya lo actualicé a una solución mucho mejor. ChinoCarloSedilla

Preguntas relacionadas