Încărcare date din fișier extern

Hey. Lucrez la un joc Trivia in C++ si am o problema cu incarcarea intrebarilor si a raspunsurilor. Cum pot sa incarc intrebarile si raspunsurile dintr-un fisier extern (am questions.txt si answers.txt). Am incercat de unul singur insa metoda aleasa nu e cea buna.

Arată-ne metoda ta, să vedem dacă e bună sau nu.

void loadQuestions ( ) {
    fstream loadQ ( "C:\\Users\\Tudor\\Desktop\\Trivia\\questions.txt", ios::in );

    /* http://www.cplusplus.com/forum/beginner/78150/ */
    if( loadQ.is_open ( ) ) {
        for ( int i = 0; i < maxQuestions; ++i )
        {
            loadQ >> question[i];
        }
    }
    else exit ( 0 );
}

void loadAnswers ( ) {
    fstream loadA ( "C:\\Users\\Tudor\\Desktop\\Trivia\\answers.txt", ios::in );

    /* http://www.cplusplus.com/forum/beginner/78150/ */
    if( loadA.is_open ( ) ) {
      for ( int i = 0; i < maxQuestions; ++i )
      {
            loadA >> answer[i];
      }

    }
    else exit ( 0 );
}
  1. NU mai folosi variabile globale, este incredibil de greu de inteles flow-ul.
  2. NU mai folosi array-uri fixe. Ce crezi ca se va intampla daca numarul de linii din fisier va fi mai mare sau mai mic decat maxQuestions?
#include <iostream>
#include <fstream>
#include <vector>

typedef std::vector<std::string> vector_of_strings;


vector_of_strings load_file(const std::string &fname)
{
        std::ifstream input_file(fname);

        vector_of_strings result;

        for(std::string buf_line; std::getline(input_file, buf_line);)
                result.push_back(buf_line);

        return result;
}


int main()
{
        vector_of_strings questions = load_file("questions.txt");
        vector_of_strings answers = load_file("answers.txt");

        std::cout << "QUESTIONS:" << std::endl;
        for(auto &line : questions)
                std::cout << "  " << line << std::endl;

        std::cout << std::endl << "ANSWERS:" << std::endl;
        for(auto &line : answers)
                std::cout << "  " << line << std::endl;

        return 0;
}
3 Likes

Sunt newbie :slight_smile:

Ideea e ca nu am reusit sa atasez codul tau la codul meu.

Pai codul tau e varză oricum, mai bine îl refaci în jurul codului meu, va fi mult mai simplu asa.

Acum ai intrebarile si raspunsurile in vectori, e suficient sa faci comparatie cu ce a raspuns player-ul cu ce ai in memorie, de exemplu:

#include <iostream>
#include <fstream>
#include <vector>
#include <cstdlib>

typedef std::vector<std::string> vector_of_strings;


vector_of_strings load_file(const std::string &fname)
{
        std::ifstream input_file(fname);

        vector_of_strings result;

        for(std::string buf_line; std::getline(input_file, buf_line);)
                result.push_back(buf_line);

        return result;
}


int main()
{
        // se initializeaza generatorul de numere pseudoaleatoare
        // o varianta mai buna ar fi http://www.cplusplus.com/reference/random/
        srand(time(nullptr));

        vector_of_strings questions = load_file("questions.txt");
        vector_of_strings answers = load_file("answers.txt");

        // selectam un numar aleator, intre 0 si lungimea vectorului - 1
        int random_index = rand() % questions.size();

        // selectam o intrebare aleatoare
        std::string question = questions.at(random_index);

        // punem intrebarea
        std::cout << "Intrebare: " << question << std::endl << "Raspuns: ";

        // asteptam raspunsul
        std::string player_response;
        std::cin >> player_response;

        // comparam raspunsul dat de jucator cu raspunsul pe care
        // il avem in vectorul de raspunsuri la pozitia random_index
        if(player_response == answers.at(random_index))
                std::cout << "Raspunsul tau este corect" << std::endl;
        else
                std::cout << "Raspunsul tau este gresit" << std::endl;

        return 0;
}

Iti las tie placerea de a implementa restul :slight_smile:

1 Like

Nu stiu daca asa se practica pe devforum, dar mi se pare aiurea sa-i spui omului ca, codul e varza (@Kingsley a si zis ca e incepator) si ca mai bine sa foloseasca solutia gandita de tine.

Parerea mea e ca in afara de a-ti mari tu post countul, nu ai ajutat pe nimeni.

5 Likes

Poate n-ai observat că i-am explicat colegului şi de ce codul lui e varză şi că i-am şi sugerat o solutie corectă? Mai degrabă postul tău n-a ajutat pe nimeni…

3 Likes


https://msdn.microsoft.com/en-us/library/dd293667.aspx

poate te ajuta sa intelegi mai bine codul scris de Serghei !
:slight_smile:

ps: recomandarea mea este sa incepi cu bazele C, apoi C++, Standard template library
Succes !

1 Like

În prima fază nici macar nu e necesar să înţelegi treaba cu template-urile (care de fapt este o chestie chiar foarte complexă, mai ales dacă intram in variadic templates). E suficient să ştii că declaraţia std::vector<std::string> creaza un vector de stringuri, std::vector<int> crează un vectori de integeri si asa mai departe.

Deci, un loc de

char blabla[50][100];

scrii pur si simplu

std::vector<std::string> blabla;

Chestia asta te va scuti de foarte multa bataie de cap, ca nu mai trebuie sa ai grija managementului memoriei, sa stai cu grija sa nu cumva sa depasesti limita de 50 stringuri, care pot avea lungimea maxima de 99 de caractere (ca nu trebuie sa uiti ca ultimul caracter trebuie sa fie 0) si asa mai departe.

In plus, C++11 vine cu niste “syntax sugar” foarte mişto, care face iterarea printr-un astfel de container o placere, cam asa:

for(const std::string &mystring : blabla)
    cout << mystring << endl;

For-ul de mai sus stie si cand sa se opreasca din iteratie, pentru ca stie automat cate elemente are vectorul (ma rog, intern foloseste iterator, care verifica daca s-a atins punctul de end(), dar nu e relevant pentru programator).

Cu vector clasici e mult mai complicat. Odata ca trebuie sa ai grija sa nu treci de limita pe care ai stabilit-o pentru numarul de elemente, si inca o daca ca nu stii cate “sloturi” sunt ocupate pe bune (faptul ca vectorul are 50 de elemente, nu inseamna neaparat ca sunt si folosite, ca poate ai doar 15 string-uri). O astfel de iteratie ar trebuie sa fie cam in genul asta (presupunând ca vectorul a fost corect initializat):

for(int i = 0; i < 50 && blabla[i]; i++)
    std::cout << blabla[i] << endl;

Varianta de mai sus este predispusă la o gramadă de tipuri de erori de programare, care pot face programul sa crape in fel si chip (daca ai noroc, genereaza doar un segmentation fault, daca esti esti ghinionist iti corupe memoria heap si/sau stack iar programul tau se poate comporta in moduri bizare, făcând depanarea foarte dificilă).

Daca chiar vrei să înveţi chestiile astea de la cineva care programeaza in C++ de peste 20 de ani, eu zic ca poti sa treci peste miştouri mai mult sau mai puţin subtile de genul “codul scris de tine e varză si mai bine il rescrii de la zero”. Dar dacă orgoliul e mai mare decât setea de cunoaştere, well… asta e :slight_smile:

2 Likes

un fel de foreach ?

Dap, înainte o iterare in containere STL trebuia facuta cam asa:

for(std::vector<std::string>::iterator it = blabla.begin(); it != blabla.end(); ++it)
    std::cout << *it << endl;

Le-a trebuit aproape 30 de ani sa-si dea seama ca ar fi o idee nemaipomenită să simplifice sintaxa :slight_smile: Ma uitam cu jind cum toate limbajele aveau foreach, numai C++ nu…

1 Like