Search code examples
c++fileifstreaminformation-retrievalofstream

How to fetch information randomly from files in C++?


I am creating a quiz game in C++. So, the main requirement is that questions should be fetched randomly from file each time program runs. So, How can I do this in C++? Consider following two simple programs.

Write.cpp

#include <iostream>
#include <fstream>
#include <string>
using std::cout;
using std::ofstream;
using std::string;
int main()
{
    ofstream fout("test.txt");
    if(!fout)
        cout<<"Error in opening file";
    string s[3];
    s[0]="C++ provides object oriented string handling";
    s[1]="C++ provides object oriented exception handling";
    s[2]="C++ provides highest flexibility to the programmer";
    for(int i=0;i<3;i++)
        fout<<s[i]<<'\n';
    fout.close();
}

Read.cpp

#include <iostream>
#include <fstream>
#include <string>
using std::cout;
using std::string;
using std::ifstream;
int main()
{
    ifstream fin("test.txt");
    if(!fin)
        cout<<"Error in opening file";
    string s[3];
    for(int i=0;i<3;i++)
        getline(fin,s[i]);
    for(int i=0;i<3;i++)
        cout<<s[i]<<'\n';
    fin.close();
}

What should I do so that when I compile Read.cpp & run Read.exe file the 3 strings should be fetched randomly from file & gets displayed?

Your help is highly appreciated.


Solution

  • If you want to maintain the array of strings in the order you read them from the file

    You can achieve that by creating another integer array that contains the numbers [1, 2 .. n-1] (where n is the number of strings) and then shuffling it to obtain a randomized sequences of indices, which you can use to print the strings.

    #include <iostream>
    #include <fstream>
    #include <string>
    #include <vector>
    #include <algorithm>
    #include <random>
    #include <chrono>
    
    using std::cout;
    using std::string;
    using std::ifstream;
    
    int main()
    {
        ifstream fin("test.txt");
        if(!fin)
            cout<<"Error in opening file";
    
        std::vector<string> lines;
        string line;
        while (getline(fin, line))
              lines.push_back(line);
    
        // Create a std::vector containing {1, 2 .. n-1} 
        // and shuffle it to obtain a random ordering.
        std::vector<int> order;
        for (int i = 0; i < lines.size(); ++i)
        {
           order.push_back(i);
        }
    
        // C++11
        unsigned seed = std::chrono::system_clock::now().time_since_epoch().count(); // Seed from current time.
        auto engine = std::default_random_engine{seed}; // You may also want to look into uniform_int_distribution.
        std::shuffle(std::begin(order), std::end(order), engine);
    
        // C++98
        // std::random_shuffle(order.begin(), order.end());
    
        // Prints strings in random order.
        for (int number : order)
             cout << lines[number] <<'\n';
    
        fin.close();
    }
    

    If you can modify (shuffle) the string array

    #include <iostream>
    #include <fstream>
    #include <string>
    #include <vector>
    #include <algorithm>
    #include <random>
    #include <chrono>
    
    using std::cout;
    using std::string;
    using std::ifstream;
    
    int main()
    {
        ifstream fin("test.txt");
        if(!fin)
            cout<<"Error in opening file";
    
        std::vector<string> lines;
        string line;
        while (getline(fin, line))
              lines.push_back(line);
    
        // C++11
        unsigned seed = std::chrono::system_clock::now().time_since_epoch().count(); // Seed from current time.
        auto engine = std::default_random_engine{seed}; // You may also want to look into uniform_int_distribution.
        std::shuffle(std::begin(lines), std::end(lines), engine);
    
        // C++98
        // std::random_shuffle(lines.begin(), lines.end());
    
        // Prints strings in random order.
        for (string& line : lines)
             cout << line <<'\n';
    
        fin.close();
    }
    

    Try it online!