Elektroda.pl
Elektroda.pl
X

Search our partners

Find the latest content on electronic components. Datasheets.com
Elektroda.pl
Computer ControlsComputer Controls
Please add exception to AdBlock for elektroda.pl.
If you watch the ads, you support portal and users.

C++ porównanie danych wprowadzonych przez usera do danych z.

16 Dec 2010 21:24 3377 28
  • Level 10  
    Witam.
    Pisze program na zaliczenie i wczytuje w nim dane z pliku do tabeli, a następnie chce porównać dane z tabeli(są to w tym przypadki pojedyńcze litery każda w innym wierszu) z literą wciśniętą przez usera.
    Wcześniej losuje nr wiersza z którego będą porbrane dane.
    wers[nr]. No i przydało by się jeszcze ograniczenie liter do A,B,C i D.
  • Computer ControlsComputer Controls
  • Level 10  
    ale to nie chce działać...
  • Level 17  
    Quote:
    ale to nie chce działać...


    To może kawałek nie działającego kodu?
  • Level 10  
    Code:
     if(y==wodp[nr])
    

    in.cpp||In function 'int main()':|
    in.cpp|296|error: no match for 'operator==' in 'y == wodp[nr]'|
    c:\program files\codeblocks\mingw\bin\..\lib\gcc\mingw32\4.4.1\..\..\..\..\include\objbase.h|78|note: candidates are: BOOL operator==(const GUID&, const GUID&)|
    ||=== Build finished: 1 errors, 0 warnings ===|

    Nie wiem jak porównać dane wprowadzone z zewnątrz do tych z tabeli....
  • Computer ControlsComputer Controls
  • Level 17  
    Trochę więcej mogłeś wrzucić. Co to za typy są przechowywane w tablic "wodp" a jakiego typu jest "y"? To drugie to pewnie się domyślam, że char (skoro z klawiatury), ale to pierwsze?
  • Level 10  
    Code:
    {
    
        ifstream odp;
        odp.open("loodp.txt");
        odp.seekg(0,ios::beg);
        int nr=1;
        char znak=' ';
       string wodp[100];  <----------------------------
       while(getline(odp, wodp[nr]))
        {
        nr++;
       }
     if(m==0){break;}
    if(y==wodp[nr])
                     {
                     p++;
                     textattr(293) ;
                     gotoxy(qw,l);
                     printf ("dobrze" );
                     }
                     else{
                     n++;
                     textattr(124);
                     gotoxy(qw,l);
                     printf ("zle" );
                     }

    y jest typu char
    cały czas mam błąd:
    Code:
    in.cpp||In function 'int main()':|
    
    in.cpp|296|error: no match for 'operator==' in 'y == wodp[nr]'|
    c:\program files\codeblocks\mingw\bin\..\lib\gcc\mingw32\4.4.1\..\..\..\..\include\objbase.h|78|note: candidates are: BOOL operator==(const GUID&, const GUID&)|
    ||=== Build finished: 1 errors, 0 warnings ===|

    »

    Rozpisując o co mi chodzi to pobieram dane z pliku do stringa(pytania, przykładowe odp i właściewe odp) a następnie wyświetlam co potrzebuję i czekam na odpowiedź usera. Dobra odp 1pkt zła 0 itp. Być może źle na początku wczytuje dane?
  • Level 17  
    A jaki sens ma według Ciebie porównanie char ze stringiem? Co to miałoby niby stwierdzić?
  • Level 10  
    Nie pisałem bardzo długo i już prawie nic nie pamiętam. Nie wymądrzaj się tylko napisz jak to porównać albo w co zmienić, żeby było porównywalne.
    Szperam szperam i narazie znalazlem tyle

    Code:
     char* word = strtok( line, "separatory");


    //
    właśnie staram się zrozumieć, a jak już pisałem długo czasu nie programowałem nic w c++ i muszę sobie wszystko przypomnieć.
    I przepraszam za zachowanie jest piątek nie mam czasu na nic, a mam jeszcze naprawdę dużo do zrobienia.
  • Level 17  
    Może spuść trochę z tonu kolego - nikt tu się nie wymądrza, tylko próbuje Ci pomóc zrozumieć, nie licz na to, że ktoś napisze coś za Ciebie. String jest klasą, char jest typem podstawowym - tak się składa, że nie da się porównać tych dwóch obiektów. Jak rozumiem z opisu problemu w wierszu tabeli masz tylko jedną literę i z nią chcesz porównać znak z klawiatury. Wpierw więc musisz wyłuskać tę literę z wiersza (stringa) i z nią porównywać swój znak.
  • Level 10  
    Już mniej więcej wiem o co chodzi, musze skopiować stringa to nowej tabeli tak?

    Code:
    char* odpowiedzi;
    
        for(nr=0; nr>20;nr++)
    odpowiedzi = wodp[nr].c_str();

    hmm
  • Level 17  
    Nie wiem po robisz takie przepisanie. To, że zmienisz std::string na char* nie spowoduje tego, że wyjdzie Ci porównanie char == char*, bo to też nie ma sensu. Rozróżniasz w ogóle te dwie rzeczy? Musisz z obiektu char* (albo string) wyciągnąć znak (string vel char* jest de facto tablicą znaków), który chcesz porównywać z tym wprowadzonym z klawiatury. Więc to przede wszystkim zrób, wyciąg ze stringa, znak który chcesz porównywać.
  • Level 10  
    Nie mam pomysłu jak się do tego zabrać... Z tego co kojarze to tablica stringów zapisuje całe "wyrazy". Jak na razie udało mi się odczytać dane z pliku i "umieścić" je w tablicy (stringów), a następnie mogę wyświetlać dane które chce podając nr wiersza. W pliku z odpowiedziami mam w każdym wersie po 1 literze albo liczbie(zależnie od tego czy wykombinuje jak to porównać).
    Potrzebuję konkretniejszej wskazówki jak to porównać.
    //
    Znalazłem coś takiego:
    Code:

    int liczba;
        liczba = strtol(pop[nr].c_str(), NULL, 10);

    I niby zwraca dobrze. Czyli to dobrze to zrobiłem?
  • Level 17  
    Pokaż jeden wiersz, jak wygląda w twoim pliku, z którego wczytujesz dane.
  • Level 10  
    Code:

     string pop[50];

    {
         fstream odppop("loodp.txt");
        odppop<<noskipws;
        Licznik =0;
        while(getline(odppop,pop[Licznik]))
        {Licznik++;}
        odppop.close();
    }

    int liczba;
        liczba = strtol(pop[nr].c_str(), NULL, 10);
    if(nr2==liczba)
    cout<<"ok";
    else
    cout<<"error";


    Coś takiego na razie mam w sumie przydało by się ubranie w funkcje ale funkcje nie zwracają tabel (chyba):P
  • Level 16  
    Ale przyjmują i zwracają wskaźniki. ;)
    edit:
    Swoją drogą, skoro nie masz zakazu stosowania STL, to czemu nie pójść tą drogą do końca?
  • Level 10  
    Chyba właśnie będę iść dalej tym co zrobiłem do tej pory. Bo ze wskaźnikami to już zielonego pojęcia nie mam jak to zrobić:P.
  • Level 15  
    strasznie gmatfasz;). Też dawno nie pisałem i muszę sobie przypomnieć
    'Ograniczenie do ABCD

    do {
    znak = getch(); // wczytaj znak z klawiatury
    } while (znak != "A" && znak!= "B" && znak!= "C" && znak!= "D")

    nie pamiętam dokładnie " albo '

    co do reszty to nie bardzo rozumiem co chcesz uzyskać i czemu korzystasz ze stringa?
  • Level 10  
    Matiush wrote:
    co do reszty to nie bardzo rozumiem co chcesz uzyskać i czemu korzystasz ze stringa?

    Korzystam z czego umiem, a że nie umiem inaczej wczytać danych z pliku i wyświetlić to korzystam ze stringa. Chyba, że ktoś pokarze jak to zrobić inaczej:).
  • Level 15  
    tylko wytłumacz dokładniej, o co chodzi w tym programie, bo nie mogę zaskoczyć. Wczytujesz wcześniej wprowadzone dane z pliku, a tam rozumiem jest zapisane A,B,C lub D, każde w osobnym wierszu. Potem user wprowadza znak z klawiatury, ale może wybrać tylko A..D, i to co wprowadzi jest porównywane z losowym wierszem? Program odpowiada TAK lub NIE?
  • Level 10  
    Mam pytania w 1 pliku, przykładowe odpowiedzi w 2 pliku i w 3 pliku poprawną odpowiedź. User odpowiada na pytania.
  • Level 15  
    Nie wysilasz się, ale dobra.

    Przykładowa funkcja na wczytanie znaków do tablicy:
    void wczytaj () {
    ifstream plik(nazwa_pliku.c_str(), ios::in);
    if(plik.good()==true) {
    for (int i = 0; i < n; i++) {
    plik >> C[i];
    }
    plik.close();
    } else
    {
    plik.close();
    cout<<"plik nie istenieje, kliknij dowolny klawisz, aby kontynuowac..";
    getch();
    }
    }

    Porównywanie powinno działać na ASCII, ale nie gwarantuje bo nie mam w czym sprawdzić.
    Inny sposób to przekonwertować ABCD na liczby np. wybór usera: jeśli A to zmienna=1 itd. i to samo podczas wczytania plików do tablicy. Na cyfrach łatwiej się operuje.
  • Level 16  
    Ekhem:
    - nie musisz wywoływać plik.close(), ponieważ destruktor zajmie się zwolnieniem zasobów automatycznie (RIIA?).
    - getch() jest niestandardową funkcją z conio.h - biblioteki Borlanda.
    - Nigdzie nie zadeklarowano C, ani n, a poleganie na zmiennych globalnych w funkcji to zła praktyka (przynajmniej bez dobrego powodu...).
    - Skąd wiesz, że w pliku będzie n znaków?

    toxa.nf: podaję Ci kod, który jest dość blisko tego czego oczekujesz, ale nie jest nim dosłownie. Jeżeli nie będziesz potrafił tak prostego kodu zmodyfikować do własnych potrzeb, to mogę tylko zasugerować zabranie się za naukę programowania w C++ od początku, najlepiej używając jakiejś książki napisanej po 99 roku z uwzględnieniem STL.

    Code:
    #include <iostream>
    
    #include <string>
    #include <vector>
    #include <fstream>
    #include <exception>
    #include <cstdlib>
    #include <ctime>

    class Error : public std::exception {
        std::string msg;
    public:
        Error(const std::string& message) : msg(message) {}
        virtual ~Error() throw() {}
       
        virtual const char* what() const throw() {
            return msg.c_str();
        }
    };

    std::vector<std::string> getWords(const std::string& filename) {
        std::fstream file;
        std::vector<std::string> words;
        file.open(filename.c_str(), std::ios::in);
        if (file.good()) {
            std::string line;
            while(std::getline(file, line)) {
                words.push_back(line);
            }
        } else {
            throw Error("Problem z otwarciem pliku");
        }
        return words;
    }

    int main() {
        try {

            std::vector<std::string> words = getWords("test2");

            std::srand(std::time(0));
            int random_word_index = std::rand() % words.size();

            std::cout << "Slowo: '" << words[random_word_index] << "'\n" // debug
                << "Podaj slowo: ";

            std::string line;
            std::getline(std::cin, line);
           
            if (line == words[random_word_index]) {
                std::cout << "Podales prawidlowe slowo. :)\n";
            } else {
                std::cout << "Podales nieprawidlowe slowo.\n'" << line << "' != '" << words[random_word_index] << "'  >:(\n";
            }

        } catch (std::exception& e) {
            std::cerr << "Zlapalem wyjatek: " << e.what() << "\n";
        }

        return 0;
    }

  • Level 15  
    kolego azara czepiasz się. Napisałem przykładowa funkcja i była kopiuj-wklej, z większego programu (a dokładnie z pracy inż), gdzie zmienne globalne miały swoje zastosowanie. Jednak oczywiste jest że deklaracje zmiennych trzeba dostosować do własnego programu, to był tylko przykład jakbyś nie zauważył.
    Nie wiem czy będzie "n" czy "z" to wie autor:P, a pliki w funkcji się zamyka, co jeśli ta funkcja jest zagnieżdżona? i operujesz na wielu plikach?
    getch() - niestandardowa, ale działa dobrze i nadaje się jak najbardziej do char.

    Nie ma co dyskutować nad stylem, bo program ma działać!! A to, co Ty uważasz nie jest istotne. Ja w twoim kodzie też bym co nieco pozmieniał, ale po co?
  • Level 10  
    azra wrote:
    Ekhem:
    - nie musisz wywoływać plik.close(), ponieważ destruktor zajmie się zwolnieniem zasobów automatycznie (RIIA?).
    - getch() jest niestandardową funkcją z conio.h - biblioteki Borlanda.
    - Nigdzie nie zadeklarowano C, ani n, a poleganie na zmiennych globalnych w funkcji to zła praktyka (przynajmniej bez dobrego powodu...).
    - Skąd wiesz, że w pliku będzie n znaków?

    toxa.nf: podaję Ci kod, który jest dość blisko tego czego oczekujesz, ale nie jest nim dosłownie. Jeżeli nie będziesz potrafił tak prostego kodu zmodyfikować do własnych potrzeb, to mogę tylko zasugerować zabranie się za naukę programowania w C++ od początku, najlepiej używając jakiejś książki napisanej po 99 roku z uwzględnieniem STL.

    Code:
    #include <iostream>
    
    #include <string>
    #include <vector>
    #include <fstream>
    #include <exception>
    #include <cstdlib>
    #include <ctime>

    class Error : public std::exception {
        std::string msg;
    public:
        Error(const std::string& message) : msg(message) {}
        virtual ~Error() throw() {}
       
        virtual const char* what() const throw() {
            return msg.c_str();
        }
    };

    std::vector<std::string> getWords(const std::string& filename) {
        std::fstream file;
        std::vector<std::string> words;
        file.open(filename.c_str(), std::ios::in);
        if (file.good()) {
            std::string line;
            while(std::getline(file, line)) {
                words.push_back(line);
            }
        } else {
            throw Error("Problem z otwarciem pliku");
        }
        return words;
    }

    int main() {
        try {

            std::vector<std::string> words = getWords("test2");

            std::srand(std::time(0));
            int random_word_index = std::rand() % words.size();

            std::cout << "Slowo: '" << words[random_word_index] << "'\n" // debug
                << "Podaj slowo: ";

            std::string line;
            std::getline(std::cin, line);
           
            if (line == words[random_word_index]) {
                std::cout << "Podales prawidlowe slowo. :)\n";
            } else {
                std::cout << "Podales nieprawidlowe slowo.\n'" << line << "' != '" << words[random_word_index] << "'  >:(\n";
            }

        } catch (std::exception& e) {
            std::cerr << "Zlapalem wyjatek: " << e.what() << "\n";
        }

        return 0;
    }


    Mniej więcej wiem o co chodzi ale nie chcę operować na vectorach. Chcę to zrobić w miarę prosty sposób bo "zaczynam" programowanie chodź w sumie już kiedyś coś tam pisałem. Nie chce pisać jakiegoś kosmicznego kodu, wolę coś prostszego co znam, żeby można było to łatwo obronić. Ile wykombinowałem tyle mam i w sumie tyle mi wystarcza. Nie ważne, że zużyje dużo pamięci bo to się zbytnio nie liczy ważne żeby to jakoś działało. Na razie buduje szkielet programu. Wczytywanie i wyświetlanie z porównaniem wprowadzonych danych mam, teraz zależy mi na czym innym. Nie mam określone, że to ma być na funkcjach. To ma działać tak jak Ja chce. I uważam, że nie umiem jeszcze pisać, a cały czas się uczę i to w wolnych chwilach bo ich naprawę jest mało...
  • Level 16  
    Matiush wrote:
    kolego azara czepiasz się. Napisałem przykładowa funkcja i była kopiuj-wklej, z większego programu (a dokładnie z pracy inż), gdzie zmienne globalne miały swoje zastosowanie.
    Oczywiście, że zmienne globalne mogą mieć swoje zastosowanie... Ale nie tutaj, na bogów. Tym bardziej się dziwię, że kolega używa/użył ich w pracy inżynierskiej. Czyżby wielowątkowość?

    Matiush wrote:
    Jednak oczywiste jest że deklaracje zmiennych trzeba dostosować do własnego programu, to był tylko przykład jakbyś nie zauważył.
    Co nie zmienia faktu, że jeśli nie ma innej potrzeby to funkcja powinna być czarną skrzynką. Programista coś wrzuca i coś dostaje, nie musząc się martwić o "magiczne" zmienne globalne, które wykorzystywać może ta funkcja. Wydawało by się, że to oczywiste. Tym bardziej, jeżeli to jest przykład.

    Matiush wrote:
    [...]a pliki w funkcji się zamyka, co jeśli ta funkcja jest zagnieżdżona? i operujesz na wielu plikach?
    Przeczytał kolega ze zrozumieniem to co napisałem w poprzednim poście? Destruktor się tym zajmie, więc nie musimy wywoływać plik.close() ręcznie. Ta zmienna za moment kończy swój żywot, więc wszystkie powiązane z nią zasoby zostaną zwolnione. Podstawa RAII.
    Normalnym jest, że przy wielokrotnym wykorzystaniu tego samego obiektu, trzeba by go "zamykać", aby później "otworzyć", ale nie o tym mowa i takiej sytuacji tutaj nie ma.

    Matiush wrote:
    getch() - niestandardowa, ale działa dobrze i nadaje się jak najbardziej do char.
    Ale tutaj używa jej kolega tylko i wyłącznie do tego, by zatrzymać działanie programu po wyświetleniu błędu, co w przypadku aplikacji konsolowej mija się z celem (a na dodatek trudniej jest taki program zautomatyzować, co jest po prostu wadą).

    Matiush wrote:
    Nie ma co dyskutować nad stylem, bo program ma działać!! A to, co Ty uważasz nie jest istotne. Ja w twoim kodzie też bym co nieco pozmieniał, ale po co?
    Ma działać... No jasne, że ma. Tylko, że to jest programowanie ad hoc.
    Zacznie się kolega jednak zastanawiać nad stylem kiedy programować będzie w grupie, albo będzie coś większego do zrobienia. Wtedy nie liczy się tylko to czy kod działa. ;)


    toxa.nf: nie bardzo rozumiem, jeśli chcesz to zrobić w miarę prosty sposób, to powinieneś wykorzystywać proste rozwiązania. To w żadnym wypadku nie jest kosmiczny kod, a najzwyklejsza w świecie utylizacja dostępnych i bardzo łatwych w użyciu narzędzi. Składnia wykorzystania szablonów (vector<string> tablica_stringow; ) wcale nie jest taka straszna. :)
    No ale zawsze możesz pisać C w C++ i bawić się w "prostsze" tablice i wskaźniki. ;)

    Zaproponowałem Ci kawałek kodu, nad którym możesz pomyśleć i popracować, ale nie zamierzam Cię zmuszać do jego użycia. Jak mawiał Jurek Owsiak: "Róbta co chceta" :)
  • Level 15  
    kolego azra. Weź wyluzuj. Nie jesteś tutaj mentorem. Podejście toxa.nf jest jak najbardziej prawidłowe. To jest podejrzewam przyszły inżynier, a inżynier upraszcza jak może i korzysta z tego co może. Nie ma sensu pisać i tracić czas na idelne programy, skoro te nieidealne działają tak samo.

    Co do zmiennych globalnych kto Ci je tutaj napisał?? ich po prostu nie ma, myślę, że ktoś kto piszę program sobie z tym poradził i uzupełnił deklaracje, pewnie nawet lokalnie.

    W moim programie były globalne. Dlatego, że uprościło mi to pisanie kodu. Globalne są zmiennymi w całym programie i o to właśnie chodzi!! Więc zostaw już te globalne w spokoju, bo czemuś mimo wszystko służą. Tak samo zamykanie pliku, jest dlatego że to tylko przykład!!!! Nic to nie zmienia

    Samo getch () to tylko zatrzymanie ekranu, można to zrobić w każdy inny sposób i też ma swój cel, ale ja pisałem raczej o: znak = getch(); sprawdza się idealnie jako wczytywanie znaku z klawiatury do zmiennej char.

    Nie zamierzam ciągnąć wątku, co jest lepsze, a co gorsze, co jest dobrym stylem, a co nie.
  • Level 10  
    Do inżyniera jeszcze cho cho :). Projekt piszę na zaliczenie laborków z programowania nie jako pracę inżynierską. Ogólnie to na laborkach nawet nie mieliśmy o otwieraniu plików, a doszliśmy tylko do funkcji/referencji -.-
    Przejrzę i przemyślę jeszcze raz opcje zaproponowaną przez azra jak znajdę chwilę wolnego czasu:).
  • Level 16  
    toxa.nf Jak zwykle w C++ wiele jest dróg do tego samego celu. Niektóre są jednak bardziej kręte od innych, ale mam nadzieję, że którąś z nich "dojdziesz końca". Powodzenia. ;)

    Matiush, nie rozumiem o co koledze chodzi, to że się do niego zwracam per "kolega" i nie zgadzam się z jego opiniami, to chyba jeszcze nie powód aby się denerwować i używać nadmiernej ilości znaków interpunkcyjnych? ;)

    Wracając do getch() - ta funkcja czeka na klawisz, ale nie pobiera go "normalnie", czyli ze standardowego wejścia, co może być przydatne jeśli bawimy się w "tekstowe gui" (ale wtedy warto rozejrzeć się za ncurses/pdcurses), mniej jeżeli piszemy po prostu narzędzie, które ma działać i kompilować się pod różnymi setupami.

    Przykład:
    Code:
    #include <iostream>
    
    //#include <conio.h> // wersja z getch()
    int main() {
        std::cout << "Czy na pewno wykonac opcje XXX? (y/n):\n";
        char decyzja;
        std::cin >> decyzja;
        //decyzja = getch(); // wersja z getch()
        if (decyzja == 'y' || decyzja == 'Y') {
            std::cout << "Wykonano: XXX\n";
        }
        std::cout << "Czy na pewno wykonac opcje YYY? (y/n):\n";
        std::cin >> decyzja;
        //decyzja = getch(); // wersja z getch()
        if (decyzja == 'y' || decyzja == 'Y') {
            std::cout << "Wykonano: YYY\n";
        }

        std::cout << "Koniec programu.\n";

        return 0;
    }

    Po odpaleniu programu będzie się on zachowywał podobnie (ale nie tak samo) w obydwu wersjach. Zautomatyzowanie "normalnego" kodu będzie bardzo proste, wystarczy utworzyć plik "opcje" o treści:
    Code:
    yy
    i odpalić program:
    Code:
    $ ./cpp.exe < opcje
    
    Czy na pewno wywolac opcje XXX? (y/n):
    Wykonano: XXX
    Czy na pewno wywolac opcje YYY? (y/n):
    Wykonano: YYY
    Koniec programu.
    0 ;)  azrael@/Projekty/CPP/dist/Debug/MinGW-Windows
    $

    Jeśli zechcemy zautomatyzować wersję z getch(), to sprawi ona nam już problem.
    Przyczyna? Jak wcześniej napisałem, getch() nie czyta znaków ze standardowego wejścia, a czeka na "prawdziwe" naciśnięcie klawisza. ;)

    Inną sprawą jest, że w aplikacji konsolowej powinno się unikać takiego pytania użytkownika, o ile to możliwe (wyjątkiem są decyzje które powinno się użytkownikowi zostawić) - a jeśli już, to właśnie zostawić możliwość automatyzacji.