2012-12-04 11 views
5

Nowe tutaj i mam bardzo proste pytanie. Robię prosty program w C, który wymaga od użytkownika wprowadzenia wyboru, co zrobić z char. Po wprowadzeniu wyniku program powraca do menu. Jednak wydaje się, że przyjmuje on trochę wejścia ducha tak, jakby znak miał jakąś nieznaną wartość. Muszę ustawić char z powrotem na domyślny stan.C - dane wejściowe dla pojedynczego char użytkownika wyświetlają dziwne wyniki.

Kod:

/* display menu for user */ 
void menu() { 

    printf("\n- - - Phone Book Database - - -\n"); 
    printf("\nSelect an action:\n\n"); 
    printf("\tc:\tCreate a database entry.\n"); 
    printf("\ts:\tSearch the database entries.\n"); 
    printf("\td:\tDelete a database entry.\n"); 
    printf("\tq:\tQuit program.\n\n"); 

    printf("Enter choice: "); 
    menu_choice = getchar(); 

    if(menu_choice != 'c' && menu_choice != 's' 
     && menu_choice != 'd' && menu_choice != 'q') { 
      printf("\n\n\tInvalid choice.\n"); 
      menu(); 
    } 
    //fflush(stdin); 
} 

Oto przykładowe wyjście:

- - - Phone Book Database - - - 

Select an action: 

    c: Create a database entry. 
    s: Search the database entries. 
    d: Delete a database entry. 
    q: Quit program. 

Enter choice: c 

Enter name: test 

Enter address: test 

Enter number: 3 

- - - Phone Book Database - - - 

Select an action: 

    c: Create a database entry. 
    s: Search the database entries. 
    d: Delete a database entry. 
    q: Quit program. 

Enter choice: 
    Invalid choice. 

- - - Phone Book Database - - - 

Select an action: 

    c: Create a database entry. 
    s: Search the database entries. 
    d: Delete a database entry. 
    q: Quit program. 

Enter choice: q 

Wprowadzanie c jako wejście wywołuje następującą funkcję

/* creates a new record in array */ 
void create_record() { 
    char name[MAX]; 
    char address[MAX]; 
    int number; 

    rec_num++; /* add 1 to marker for record placement */ 

    printf("\nEnter name: "); 
    scanf("%s", name); 

    printf("\nEnter address: "); 
    scanf("%s", address); 

    printf("\nEnter number: "); 
    scanf("%d", &number); 

    strcpy(record[rec_num].name, name); 
    strcpy(record[rec_num].address, address); 
    record[rec_num].number = number; 
} 
+0

Co robisz po wybraniu "c"? – Xymostech

+0

@Xymostech Po wybraniu c wywołuje inną funkcję, aby utworzyć wpis w bazie danych. Używam tablicy struktur dla każdego pola. Działa to dobrze, ale po powrocie do funkcji menu() umieszcza coś jako odpowiedź i wyświetla "Niepoprawny wybór". jak widzisz. –

+0

Wygląda na to, że inna funkcja nie bierze poprawnie wejścia, więc w buforze pozostało dodatkowe wejście, a po powrocie do menu coś jest już wybrane. Czy możemy zobaczyć kod funkcji, o której mówiliście? – Xymostech

Odpowiedz

4

Wygląda na to, że masz już odpowiedź i jej sprawdzenie jest poprawne; stosując getchar() odczytuje jeden znak z stdin

printf("Enter choice: "); 
menu_choice = getchar(); 

Kiedy dostać się do tego wiersza na konsoli i wpisz c<enter key> to jest przyczyną dwóch char, aby przejść do stdin: 'c' i '\n'

po raz pierwszy getchar(); uruchomiony, odbiera tylko 'c', pozostawiając znak nowej linii. W drugiej iteracji '\n' jest odbierany bez czekania na nic od użytkownika; w ten sposób wydaje się, że istnieje "wejście ducha".

Chciałem tylko wskazać, że gdy użytkownik otrzymuje dane od użytkownika, a wyniki nie są zgodne z oczekiwaniami, nie zaszkodzi po prostu zrzucić go z powrotem, aby sprawdzić, co się dzieje, coś takiego:

if(menu_choice != 'c' && menu_choice != 's' 
    && menu_choice != 'd' && menu_choice != 'q') { 
     printf("\n\n\tYou entered %c (%d).\n", menu_choice, menu_choice); 
     printf("\tThat's an invalid choice.\n"); 
     menu(); 
} 

wykazałaby Ci:

You entered 
(10). 
That's an invalid choice. 

Między rzeczywistości było na innej linii, i sprawdzenie, czy wynik dziesiętny przeciwko tabeli ASCII chcesz zobaczyć, że 10 jest znak nowej linii , które mogą ci pomóc o wynik.

Edit:

1 opcja dla spożywania przełamane -

printf("what character?"); 
c = getchar(); // Get the character from stdin 
getchar();  // consume the newline character that was left 

druga opcja:

printf("what character?"); 
scanf("%c ", &c); // Get the character from stdin, note the space after the %c 
        // that will allow any special characters including \t and \n 

Jeśli tylko chcesz uzyskać znak, a następnie zakończyć w & spożywać '\n', musisz dodać i opuścić znak nowej linii:

printf("what character?"); 
scanf("%c\\n", &c); 
+0

Bardzo pomocny. To nie rozwiązało mojego problemu, ale doprowadziło mnie to do lepszego zrozumienia, jak to działa. Dziękuję Ci! –

+1

@JamesManes - Tak, naprawdę nie wspomniałem * jak * to naprawić, tylko co się działo ... Z perspektywy czasu dodałem kilka "szybkich" poprawek dla twojego zainteresowania (zobacz Edycja do mojego postu). Druga opcja jest lepsza, ponieważ pozwala na większą elastyczność – Mike

+0

Zajrzałem do tego i zacząłem używać opcji getchar(). Używanie scanf ("% c" &c"); nie powiodło się Po naciśnięciu klawisza Enter, aby dokonać selekcji, spowodowałoby to tylko utworzenie nowej linii w terminalu, mogłem ciągle uderzać w wejście bez końca, z wyprowadzaniem tylko nowych linii –

-1

Zabłąkany charakter, niemal na pewno „\ n ', pozostawia się w buforze wejściowym po wprowadzeniu poleceń.

Aby ją usunąć, można dodać:

fflush(stdin) 

... tuż przed rozmowy getchar().

+0

Próbowałem tego i to nie działa. Słyszałem, że używanie fflush (stdin) jest bardzo niewłaściwe w takich sytuacjach jakkolwiek. –

+1

@JamesManes C99 7.21.5.2p2, puszczanie czegokolwiek poza strumieniem wyjściowym, strumieniem aktualizacji lub NULL, jest niezdefiniowanym zachowaniem, a nie tylko "niewłaściwym". [Nie rób tego] (http://stackoverflow.com/questions/2979209/using-fflushstdin). – WhozCraig

+0

@WhozCraig Nie wiedziałem, że to było niezdefiniowane zachowanie.Zapamiętam to. Byłbyś zaskoczony, jak wiele osób zasugerowało mi to na innych stronach! –

0

Zwrotny znak "\ n" prawdopodobnie zostanie pozostawiony w stdin, więc następnym razem, gdy go obejrzysz, pobierze go getchar().

Spróbuj spojrzeć na wartość pobraną z getchar() albo za pomocą debuggera, albo po prostu przez wydrukowanie.

Może być tak, że getchar() nie jest najlepszym wyborem dla twojej aplikacji i że scanf() wykona lepszą robotę, w ten sposób wszystkie stdin zostaną pobrane i powinno być puste przy następnym podejściu. Oczywiście będziesz musiał dostarczyć scanf więcej niż jeden znak do napisania, tak jak w twoim innym kodzie.

Możesz po prostu spojrzeć na pierwszy znak w tablicy, aby uzyskać znak.

2

Jak inni podkreślili, jest to znak nowej linii. Po prostu dodaj kolejne

gdziekolwiek chcesz przeczytać tylko jedną postać.

+0

Dziękuję bardzo. Dodałem to na końcu każdej wywoływanej funkcji i całkowicie rozwiązałem problem. To może nie być najlepszy sposób, ale działa. Poszukam innego rozwiązania, ale wykorzystam to w międzyczasie. –

Powiązane problemy