logo elektroda
logo elektroda
X
logo elektroda
REKLAMA
REKLAMA
Adblock/uBlockOrigin/AdGuard mogą powodować znikanie niektórych postów z powodu nowej reguły.

[Visual C++] Pomijanie wczytywania zmiennej y w funkcji scanf - jak naprawić?

Yakhub 24 Maj 2004 19:38 3924 8
REKLAMA
  • #1 657781
    Yakhub
    Poziom 11  
    Posty: 38
    Pomógł: 1
    Ocena: 2
    Jak w temacie. Problem sprawia funkcja scanf. Oto fragment kodu:

    
    int x=0,y=0,z=0;
    printf ("Poczatek programu");
    printf ("\nPodaj x ");  scanf ("%d",&x);
    printf ("\nPodaj y ");  scanf ("%d",&y);
    printf ("\nPodaj z ");  scanf ("%d",&z);
    printf ("x=%d\ny=%d\nz=%d",x,y,z);
    


    Program się ładnie kompiluje (pod MS Visual C++ (niestety tylko taki kompilator mamy na laborkach)), ale z wykonaniem gorzej.

    Efekt uruchomienia programu (czcionką pogrubioną napisałem to, co ja wprowadzam z klawiatury, kursywą to, co wyświetla komputer):

    Poczatek programu
    Podaj x
    10
    Podaj y
    Podaj z
    20
    x=10y=0z=20


    Problem polega na tym, że wczytywanie zmiennej y jest w ogóle pomijane, to znaczy program nie zatrzymuje się w tym punkcie, żeby mi pozwolić wprowadzić coś z klawiatury. Jeżeli wykonam program w ten sposób:

    Poczatek programu
    Podaj x
    10 15
    Podaj y
    Podaj z
    20
    x=10y=15z=20


    To nie ma problemu, ale nie o to chodzi... Czemu ten drugi scanf nie dziala jak trzeba??

    Najchętniej napisałbym to od nowa, stosując wygodniejsze, łatwiejsze i - przede wszystkim - działające cin i cout, ale to ma być w 'klasycznym' C a nie w C++...

    Zamykam. - arnoldziq
  • REKLAMA
  • #2 657799
    ACULA
    Poziom 34  
    Posty: 3005
    Pomógł: 105
    Ocena: 114
    bo w buforze nadal są dane trzeba użyć funkcji fflush opróżniającej ten bufor przed kolejnym scanf
  • REKLAMA
  • #3 657833
    mmm777
    Poziom 31  
    Posty: 1824
    Pomógł: 98
    Ocena: 240
    Tak z czystej ciekawości, zrobiłem to w moim starym, wiernym VS6 i działa:
    [c:\home\VC\Test\Debug]Test.exe
    Poczatek programu
    Podaj x 10

    Podaj y 20

    Podaj z 30
    x=10
    y=20
    z=30

    W czym to robisz?
  • #4 657835
    Yakhub
    Poziom 11  
    Posty: 38
    Pomógł: 1
    Ocena: 2
    Jakie dane? Skąd one się wzięły w tym buforze? Pomiędzy pierwszym a drugim scanf nie ma żadnych instrukcji. Nie naciskane są żadne klawisze. Błąd jest powtarzalny - występuje przy każdym uruchomieniu...

    Rozumiem, że to ma jakiś związek ze strumieniami? (cholera, trzeba było nie spać na wykładzie...)

    Zależy mi na tym, żeby poznać przyczynę, a nie na rozwiązaniu....
  • REKLAMA
  • #5 657846
    mmm777
    Poziom 31  
    Posty: 1824
    Pomógł: 98
    Ocena: 240
    Zawsze można dać gets + sscanf, tak jest zdecydowanie bardziej pewnie.

    Podesłać exeka ? :)

    -----------------------------------------------------------
    A teraz inny kompilator:
    [c:\Program Files\Microsoft Visual C++ Toolkit 2003]cl a.c
    Microsoft (R) 32-bit C/C++ Optimizing Compiler Version 13.10.3052 for 80x86
    Copyright (C) Microsoft Corporation 1984-2002. All rights reserved.

    a.c
    Microsoft (R) Incremental Linker Version 7.10.3052
    Copyright (C) Microsoft Corporation. All rights reserved.

    /out:a.exe
    a.obj

    [c:\Program Files\Microsoft Visual C++ Toolkit 2003]a
    Poczatek programu
    Podaj x 10

    Podaj y 20

    Podaj z 30
    x=10
    y=20
    z=30
  • REKLAMA
  • #6 657906
    BoskiDialer
    Poziom 34  
    Posty: 1530
    Pomógł: 353
    Ocena: 42
    Problem polega na windowsowym znaczku enter.. enter składa sie z dwóch bajtów 0x0d i 0x0a (crlf)
    pierwszy bajt kończy (u ciebie) linijke z X, a drugi linijke z Y omijając tą właśnie linijke.. tak więc potrzebne jest czyszczenie strumienia..

    experyment:
    zamiast enter wpisz na klawiaturze alfanumerycznej (trzymając lewy klawisz alt) 013, wtedy niepowinno przeskoczyć tej linijki...
  • #7 657919
    mmm777
    Poziom 31  
    Posty: 1824
    Pomógł: 98
    Ocena: 240
    Znak enter na klawiaturze to nic innego (o ile pamietam z dawnych, dawnych czasów) ^M, albo Control-M.

    Aaa, poza tym biblioteki w C są tak zrobione, że załatwiają niezbędne konwersje: fprintf(fpo,"\n") wyśle do pliku na PC \r\n, a na Unixie \n, a na Macu pewnie \r (nie widziałem Maca na własne oczy).

    Tak chodzi mi coś po pordzewiałych zwojach mózgu, że ze względu na czasami dosyć niespodziewane zachowania scanfa lepiej najpierw wczytać cały wiersz, a dopiero potem go sscanfować.

    Baj de łej, ja to robię na XP-Pro, a Ty?
  • #8 687486
    adames80
    Poziom 18  
    Posty: 348
    Pomógł: 12
    Ocena: 10
    uzyj fgetc do odczytania znakow z pliku lub fgets do odczytania textu z pliku a do zapisania fputs lub fputc:)
  • #9 695085
    krzychoo_soft
    Poziom 17  
    Posty: 233
    Pomógł: 16
    Ocena: 13
    jak miewałem problemy z buforem klawiatóry itp,
    to przeszedłem ze scanf(const char format, &pointer); na cout; i teraz nie martwie się o takie detale. Podobnie denerwująca sytuacja jest przy:
    getch();
    scanf("%s",&t1[0]);

    pozdrawiam,

Podsumowanie tematu

LABEL_AI_GENERATED
Problem dotyczy pomijania wczytywania zmiennej y w funkcji scanf w środowisku Microsoft Visual C++. Kod kompiluje się poprawnie, jednak podczas wykonania program nie zatrzymuje się na wczytaniu y, co skutkuje pominięciem tej wartości. Przyczyną jest obecność znaków końca linii (CRLF, czyli 0x0d 0x0a) w buforze wejściowym po wczytaniu zmiennej x, które powodują, że scanf dla y odczytuje pozostały znak nowej linii zamiast oczekiwanego wejścia użytkownika. Rozwiązaniem jest oczyszczenie bufora wejściowego przed kolejnym wywołaniem scanf, np. za pomocą fflush(stdin) (choć jest to niezalecane i niezgodne ze standardem C) lub alternatywnie wczytanie całej linii tekstu funkcją fgets, a następnie parsowanie jej za pomocą sscanf. Wskazano również, że w innych kompilatorach Visual C++ (np. VS6, Visual C++ Toolkit 2003) problem nie występuje, co sugeruje różnice w implementacji obsługi bufora wejściowego. Zwrócono uwagę na specyfikę znaków końca linii w systemie Windows oraz na praktyczne podejście do wczytywania danych wejściowych, które minimalizuje problemy z buforem i znakami nowej linii.
Podsumowanie AI na podstawie dyskusji. Może zawierać błędy.
REKLAMA