[C++] <enter> sie dubluje

0

Witam, tym razem problem z kodem w c++, jest to program na zaliczenie.

Kiedy wczytuje dane z pliku (a nazwa jest do wprowadzenia przez usera) to wszystko ok - dane pobieraja sie do bazy, jak chce zapisac wowczas program nie zatrzymuje sie przy scanf, ktory ma za zadanie pobrac nazwe pliku, tylko zachowuje sie jakby juz byl wcisniety <enter> bez wpisanej wartosci. Chcialem sie tego pozbyc stosujac fgets, niestety konczy sie tym samym. Dawanie getch() przed scanf powoduje, ze program czeka na dowolny klawisz, po czym jest to samo czyli omija scanf i zmiennej, ktorej mialem przypisac cos z klawiatury daje pusta wartosc..

Nie wiem czy jest potrzeba zamieszczania kodu, jesli tak to wrzuce. Sytuacja jest o tyle dziwna, ze za pierwszym uruchomieniem, gdy chce zapisac do pliku to wszystko jest ok, dopiero po otwarciu pliku lub juz jednokrotnym zapisaniu pojawia sie w/w problem...

0

Zapewne gdzieś w stdin leży ci znak newline. Tak zwykle bywa jak ktoś miesza np. strumienie z funkcjami znanymi z C. Bez kodu jednak nic nie wymyślimy...

0

To bedzie dlugie... :) dotyczy funkcji int save_record()
Nie chcialem wpisywac tylko tej jednej funkcji, bo moze to jest zalezne od innych..


int save_record()
{
   textbackground(BLACK);
   clrscr();
   printheader("Zapisz plik");
   gotoxy(1, 3);
   printf("Podaj nazwe pliku (bez rozszerzenia): ");

   char filename2[32];
   char filename[32];
   //scanf("%127s", filename2);
   fgets(filename2, 31, stdin);
   for (int i=0; i<=(strlen(filename2)-2); i++)
       filename[i] = filename2[i];
   strcat(filename, ".res");
   ofstream in(filename, ios::out | ios::trunc);
   for (int i=1; i<=record_cnt; i++)
       {
        in <<studenci[i].imie<<endl;
        in <<studenci[i].nazwisko<<endl;
        in <<studenci[i].nr_alb<<endl;
       }
   in.close();
   gotoxy(1, 5);
   printf("Dane zostaly pomyslnie zapisane do pliku %s", filename);
   gotoxy(1, 6);
   textcolor(RED);
   textbackground(BLACK);
   cprintf("Nacisnij <enter> aby powrocic listy...");
   char key4 = 0;
   while (!((int)key4 == 13))
         {
          key4 = getch();
         }
   return(1);
}

int check_gmenu()
{
   switch (gmenu)
          {
           case 1 : add_record();
                    break;
           case 2 : if (record_cnt>0)
                        record_list();
                    break;
           case 3 : load_record();
                    break;
           case 4 : save_record();
                    break;
           case 5 : wyjscie = true;
                    break;
          }
   return(1);
}

int main()
{
   clrscr();
   strcpy(menus[1].tekst, "Dodaj studenta");
   strcpy(menus[2].tekst, "Wyswietl baze studentow");
   strcpy(menus[3].tekst, "Wczytaj baze z pliku");
   strcpy(menus[4].tekst, "Zapisz baze do pliku");
   strcpy(menus[5].tekst, "Wyjdz");
   Menu();
   char key;
   record_cnt = 0;
   gmenu = prevmenu = 1;
   while (!wyjscie)
         {
          check_menu_pos();
          key = getch();
          gotoxy(1, 5);
          //printf("%d", (int)key);
          prevmenu = gmenu;
          switch ((int)key)
                 {
                 case 80 : gmenu++;
                           if (gmenu>menu_num)
                              gmenu = 1;
                           break;
                 case 72 : gmenu--;
                           if (gmenu<1)
                               gmenu = menu_num;
                           break;
                 case 77 : gmenu = menu_num;
                           break;
                 case 75 : gmenu = 1;
                           break;
                 case 13 : check_gmenu();
                           Menu();
                           key = 0;
                           break;
                 case 27 : wyjscie = true;
                           break;
                 }
         }

//EDIT - ucialem czesc kodu, jest tylko to co wydaje mi sie za niezbedne

0

To po cholerę wklejasz całe źródło skoro problem jest z jedną funkcją? MYŚL.

   while (!((int)key4 == 13))
         {
          key4 = getch();
         }
  1. To jest terroryzm. NAJPIERW sprawdzasz warunek, a POTEM dopiero wczytujesz dane (które chwilę temu zostały sprawdzone), nie było w kursie "do while"?
  2. Zdecyduj się czy korzystasz z iostream czy z cstdio
fgets(filename2, 31, stdin);

Ryzykowne bo fgets wczyta ci newline do tego filename2. Rozumiem że dlatego później robisz jakieś dziwne pętle które wycinają tego newline? o_O No tak, lepiej wkleić jakiegoś "hacka" zamiast pomyśleć i przeczytać kawałek dokumentacji.
4. Przypuszczam że główny problem polega na tym że wczytujesz akcje za pomocą getch(), który wczyta tylko jeden znak (tzn nie ruszy wcale tego newline który po znaku nastąpi i ten newline będzie leżał w stdin i czekał na lepsze czasy).

0

Wszyscy tutaj sie tak witacie z poczatkujacymi? Pozostawie to bez komentarza..

Faktycznie to z petla do while bedzie normalnym rozwiazaniem, dzieki.
Fgets uzylem alternatywnie szukajac roznych rozwiazan, stad te dziwne petle ;). Tam chyba jest wykomentowany scanf tak btw.
Czym innym moge operowac zamiast getch();? Poniewaz jezeli on robi problemy, to moze da sie jakos wyzerowac ostatnia akcje (ostatni wcisniety klawisz)?

//EDIT - ok mam juz rozwiazanie, wystarczylo przed scanf wpisac fflush(stdin); aby wyzerowac stdin z jakiegokolwiek znaku ;). Ale i tak dzieki za pomoc i checi!

1

Genialne rozwiązanie, szkoda że to kolejny "hack", co więcej taki który zadziała tylko na szczególnych implementacjach. Wiem wiem, kto by się przejmował czytaniem dokumentacji...
cytując za: http://www.cplusplus.com/reference/clibrary/cstdio/fflush/

In some implementations this causes the input buffer to be cleared, but this is not standard behavior.

A jak powinno sie ten problem rozwiązać?
http://4programmers.net/C/FAQ/Zabezpieczenie_przed_wpisywaniem_liter

0

Shalom, dziekuje za pomoc, ale chyba nie potrzebuje juz czytac twoich wypowiedzi przesiaknietych ironia. Prosze naucz sie pomagac ludziom z checia a nie tak jakbys musial to wykonywac - taka praca charytatywna.. Co jak co mnie ignorantem nazwac nie mozesz. Siedze od wielu lat w pascalu i nigdy nie mialem tak dziwnych problemow z wczytywaniem znakow, stad moje kombinowanie plus wietrzenie google aby tu nic wiecej nie napisac - tak dzialasz na innych, nowych..

Pamietaj - nie znasz czlowieka - nie insynuuj.

Dzieki i pozdro.

0

Czyli ciągle używasz "rozwiązania" (niepoprawnego...) z fflush(stdin)?

0

@AmBeam cieszę sie jeśli moja postawa zachęciła cię do korzystania z google zamiast spamowania na forum problemami które miało milion osób przed tobą i do których rozwiązanie można znaleźć w 30 sek za pomocą google. Nie mogę nazwać cie ignorantem? A jak nazwać osobę która (jak wynika z poprzednich postów i kodu) wkleja sobie losowe instrukcje do kodu i liczy na to że "może akurat zadziała". A jak coś zadziałało (albo przynajmniej wygląda że zadziałało) to lepiej nie ruszać, mimo ze rozwiązanie jest błędne i nieprzenośne.
Poza tym błędy nie wynikają z języka jako takiego, a z jego nieznajomości. Zamiast googlować (szukając pewnie pod enigmatycznymi hasłami jak "enter się dubluje") warto czasem rzucić okiem na dokumentację, ona naprawdę nie gryzie ;)

0

Program rozwala ci fun.getch() ,jeśli używasz strzałek to funkcja powinna w przypadku strzałki zostać wywołana 2x :

          key = getch() ;      
                                                      // kod strzałek wymaga wczytania 2 znaków
          if(key== 0 || key == 244)
          {
              key = getch();                     // wczyta sama   
          }

W Borlandzie w tym przypadku jako pierwszy kod zwracane było 0 .

#include <conio.h>
#include <iostream>
using namespace std ;
//---------------------------------------
const int UP   = 0x48 ;
const int DOWN = 0x50 ;
const int ENTER= 0x0d ;
const int ESC  = 0x1b ;
//---------------------------------------
typedef void(*fun)(void);

void Dodaj(void);
void Odejmi(void);
void Monozenie(void);
void Dziel(void);
void Pierwiastek(void);
void Kwadrat(void);
void Koniec(void);

struct pozycja_menu{
                       char* nazwa ;
                       fun obsluga_poz ;
                   };
//----------------------------------------------------------
pozycja_menu menu[]={
                     {"1 - Dodaj      ",   Dodaj   },
                     {"2 - Odejmi     ",   Odejmi  },
                     {"3 - Monozenie  ",  Monozenie},
                     {"4 - Dziel      ",    Dziel  },
                     {"5 - Pierwiastek",Pierwiastek},
                     {"6 - Kwadrat    ",   Kwadrat },
                     };
//----------------------------------------------------------
int ile_pozycji ;
//---------------------------------------
int wybierz(pozycja_menu*menu)
{
   int numer_pozycji = 0 ;
   int kod ;
   while(1){
            system("cls");
            cout << endl << endl ;
         //---------------------------
         for (int i = 0 ;i< ile_pozycji ;i++)
         {
             if(i == numer_pozycji)
             {
               cout << " > " ;
               cout << menu[i].nazwa << " < " << endl ;
              }else{
                      cout << "   " ;
                      cout << menu[i].nazwa << "   " << endl ;
                   }
         }
         //---------------------------
         cout << endl << " [Enter] - Wybierz" << endl ;
         cout<<  " [Esc  ] - Koniec" << endl ;
         //---------------------------
          kod = getch() ;       //<- obsluga klawiatury przez menu
          if(kod == 0 || kod == 244){ kod = getch(); }

      switch (kod)
      {
        case ENTER:
         return numer_pozycji ;

        case UP   :
         numer_pozycji-- ;
         if(numer_pozycji < 0){ numer_pozycji = 0 ; }
        break;

        case DOWN :
        numer_pozycji++;
        if(numer_pozycji > ile_pozycji-1){ numer_pozycji = ile_pozycji -1; }
        break;

        case ESC :
        return ile_pozycji;

        default: ;
      }
   }// while
}
//---------------------------------------------------------------------
void Dodaj(void)
{
float x,y ;
cout<<"Podaj pierwsza liczbe"<<endl;
cin>> x;
cout<<"podaj druga liczbe"<<endl;
cin>> y;
cout << x << " + " << y << " = " << x+y << endl ;
}
//---------------------------------------------------------------------
void Odejmi(void)
{
float x,y ;
cout<<"Podaj pierwsza liczbe"<<endl;
cin>> x;
cout<<"podaj druga liczbe"<<endl;
cin>> y;
cout << x << " - " << y << " = " << x-y << endl ;
}
//---------------------------------------------------------------------
void Monozenie(void)
{
   cout << "Uzupelnij kod funkcji :-)" << endl ;
}
//---------------------------------------------------------------------
void Dziel(void)
{
   cout << "Uzupelnij kod funkcji :-)" << endl ;
}
//---------------------------------------------------------------------
void Pierwiastek(void)
{
   cout << "Uzupelnij kod funkcji :-)" << endl ;
}
//---------------------------------------------------------------------
void Kwadrat(void)
{
   cout << "Uzupelnij kod funkcji :-)" << endl ;
}
//---------------------------------------------------------------------
int main(int argc, char **argv)
{
  int poz ;
  ile_pozycji = sizeof(menu)/sizeof(pozycja_menu);

  while((ile_pozycji) != (poz=wybierz(menu)))
  {
          system("cls");
          menu[poz].obsluga_poz();
          getch();
  }
        return 0;
}
 
AmBeam napisał(a)

//EDIT - ucialem czesc kodu, jest tylko to co wydaje mi sie za niezbedne

Optymista ... masz totalny b.rdel w tym kodzie .

0
Azrael_Valedhel napisał(a)

Czyli ciągle używasz "rozwiązania" (niepoprawnego...) z fflush(stdin)?

Nie, już zmieniłem na pętle while, wszystko działa ;).

@Shalom - uwierz mi, szukam, dużo szukam zanim cokolwiek napiszę. Staram się być samodzielny. Na przekór tutaj działa poprzedni język, który jest dla mnie bardziej intuicyjny. Prawdą jest to co piszesz, że szukam pod enigmatycznymi hasłami, ale niestety brak mi takiej wiedzy jaką Ty posiadasz, żeby nazywać problemy po imieniu..

Dokumentacja to jest dla mnie enigmatycznie napisana:)..

@dzejo - inne przyzwyczajenia, c++ dopiero się uczę, formatowanie z pascala..

1 użytkowników online, w tym zalogowanych: 0, gości: 1