Pytanie w sprawie c – obudowa przełącznika nie działa poprawnie w C

2

W moim programie jest niewielki problem.

Po naciśnięciu 2 lub 3 lub 4 wyświetli się poprawnie, ale po naciśnięciu a lub b lub c itd. Wyświetli poprzedni wynik zamiast wydrukować opcję Nieprawidłowy.

Jak mogę to naprawić?

    #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;
}
Właściwie kod działa zgodnie z oczekiwaniami, o ile dodasz; poIn this add logic linia. Mike Kwan
Problem polega na tym, że używaszscanf(). Jest to diabelnie trudne, aby to zrobić dobrze. Gdy użytkownik wpisze literę,scanf() wybór nie powiedzie się (powinieneś sprawdzić wynik każdegoscanf() aby upewnić się, że zadziałało, i powinieneś poradzić sobie z błędami), aby wartość nie uległa zmianie. Drugiscanf() jest zaprojektowany do pobierania nowej linii, ale gdy pismo zostało wpisane, zamiast tego pobiera literę. Jeśli jesteś w systemie Windows,getch() to rozsądna opcja. Alternatywnie użyjfgets() czytać linię, a następniesscanf() analizować to. To zazwyczaj bardziej solidna strategia. Jonathan Leffler
@JonathanLeffler - Właściwie, ponieważ wydaje się, że OP chce wprowadzić pojedynczy znak. Chciałbym skorzystać z prostego rozwiązania oferowanego przez standard C:fgetc. ArjunShankar
@ArjunShankar:fgetc() nie przeczytam niczego, dopóki nie wpiszesz nowej linii, a potem będziesz musiał uporać się z pominięciem nowej linii. Z pewnością jest to możliwe; nie byłoby to, co polecam. Jonathan Leffler

Twoja odpowiedź

4   odpowiedź
1

scanf zwraca wartość, której nie sprawdzasz.

Gdy używany z%d specyfikator - powinien analizować liczbę całkowitą. Ponieważ wpisujesz wartość niecałkowitą -scanf zwraca kod błędu ichoice jest niezmieniony

ojej, masz rację valdo
scanf("%d" , &choice); Mat
2

Hmm, jedną z błędów w twoich kodach jest:

scanf("%c" , &c);

ponieważ funkcja scanf wymaga od użytkownika naciśnięcia klawisza enter, zanim będzie mógł zapisać znak w odpowiedniej zmiennej.

Więc jeśli kompilator czyta wiersz:

scanf("%c" , &c);

odczytuje twoje wejście, PLUS, ENTER.
Tak więc wymuszenie funkcji scanf do przechowywania danych wejściowych, PLUS, ENTER, w zmiennej znakowej.

Byłoby lepiej, gdybyś używał funkcji getche () lub getch () zamiast używać funkcji scanf () i nie używaj nigdy:

scanf("%c" , &c);

ponieważ spowodowałoby to błąd.

Przykład użycia funkcji getche () lub 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

Różnica między nimi polega na tym, że getche () wyświetla twoje naciśnięcie klawisza, podczas gdy getch () nie.

Uwaga: nie zapomnij umieścić

#include<conio.h>

Dodatkowe informacje: Jeśli nadal chcesz korzystać z funkcji scanf (), upewnij się, że deklarujesz swoją ulubioną zmienną jako:

char c[20];

wtedy możesz użyć:

scanf("%s", &c);

ale twoja zmienna może zawierać tylko 19 znaków, tak jak zadeklarowaliśmy na tablicy znaków.

A podsumowanie nie jest używane:

scanf("%c", &c);

ponieważ może to wpłynąć na inne funkcje scanf (). :)

ROZWIĄZANIE (Ostrzeżenie Spoilera):

#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;
}

Możesz także użyć przełącznika, aby porównać znaki. Po prostu zmień wartości

case 1:

do

case '1':
Hmm, nic dziwnego, że inni o tym nie wiedzą. Myślę, że jestem trochę prymitywny w tym języku. Zrobię inne rozwiązanie dla tego, ale byłoby znacznie dłużej. ChinoCarloSedilla
Chociaż OP może być w porządku z tą odpowiedzią, użycie „conio.h” jest zazwyczaj złym pomysłem. Jeśli chodzi o standard C, nie ma czegoś takiego jakconio.h. Wiele maszyn tego nie robimieć a conio.h. Ponadto definicje wconio.h mają też nieco inne zachowanie w zależności od tego, który kompilator je wysłał. Możesz przeczytać dlaczego tutaj:en.wikipedia.org/wiki/Conio.h ArjunShankar
@ArjunShankar dzięki za ten pomysł. Już zaktualizowałem go do znacznie lepszego rozwiązania. ChinoCarloSedilla
Właściwie może to być strasznie złe. Co jeśli użytkownik wprowadzi 100 znaków i użyjesz 20-znakowego bufora?scanf zapisze adresy pamięci, których nie wolno dotykać. Prawdopodobnie spowoduje to błąd wykonania. ArjunShankar
0

Dzieje się tak, ponieważ c, gdy czytasz znaki jako liczby całkowite (scanf („% d” i wybór);) przyjmuje kod ascii znaków, na przykład a = 97, b = 98 c = 99 d = 100, jeśli chcesz przeczytaj a jako 1 b jako 2 itd. będziesz musiał dodać dodatkowy kod, który powie programowi, czy liczba jest równa kodowi ASCII abcd lub e odejmij go od 96, więc otrzymasz 1,2,3 ..

Nie, wybór jest odczytywany jako „% d” i będzie liczbą całkowitą, problem istnieje gdzie indziej. Antti Haapala
2

Wygląda na to, że dostajesz liczby do Choice, a znaki do c. ale używasz tylko opcji Choice w przełączniku, nigdy nie sprawdzasz C var.

Zasadniczo, jeśli trafisz literę, zapisuje ją w C var, a następnie ponownie używa starej wartości w Choice.

To ma dla mnie sens. OP ma nieco dziwny program i wydaje się, że zrozumiałeś, czego chcą poprawnie. ArjunShankar

Powiązane pytania