3

I am new to programming and Stack Overflow.So I've been building a simple database for my own enjoyment and to practice my knowledge. It registers a user's username, password and assigns a user ID. To a text file and you can also view the user's information.

My main problem is that I want the program to assign the user an ID that is random from say 1-1000 (ex. 1000 being the maximum employees).

This block of code executes when the user registers a new username and password. The program outputs the username, password, and the user ID in this part. I am able to get the program to output a random number for each user made, but I am not able to make it generate numbers with no duplicates.

The program should output a message that if there are no more user IDs available, then the registration process will not complete.

I created a function that prints a bunch of lines to clear the screen, but everything is at the bottom. If there is a different function I can use I would be glad to know!

if (passwordCheck == password) {
            const int minEmp = 1, maxEmp = 10;          
            srand(time(0));
            userID = (rand() % (maxEmp - minEmp + 1)) + minEmp;

            ofstream outfile (username + ".txt"); //Creates txt file with user name
            outfile << "User ID: " << userID << endl << //Outputs info to txt file
                "Account Username: "<< username << endl
                << "Account Password: " << password;
            outfile.close();
            clearScreen(); //My function to add lines to clear the screen

            cout << endl << "Your account has been created." << endl
                << endl << "Returning to main menu.";

            clearScreen();
            mainMenu(); //Function to return back to menu
  • I don't get the actual question, You want to generate a unique random number for each user? – Ali Sepehri-Amin Oct 14 '17 at 20:13
  • 3
    "_My main problem is that I want the program to assign the user an ID that is random from say 1-1000_" And.. Where is the problem in here? If you want to generate unique ID from that range - easiest solution is to remember/read all used IDs, and generate ID until you get one, which is not on that "used ID" list. Did you try that? – Algirdas Preidžius Oct 14 '17 at 20:15
  • 5
    You should call `srand` only once. And why can't you assign IDs starting from `1` and simply incrementing? – rustyx Oct 14 '17 at 20:16
  • So you're asking how to make sure you don't accidentally assign the same number twice? Algirdas's suggestion is probably the simplest and should work fine. You could also try to do something complicated like here: https://stackoverflow.com/questions/693880/create-random-number-sequence-with-no-repeats – Kyle A Oct 14 '17 at 20:19
  • I would use an incrementing number given that the only requirement is that it is unique. – Galik Oct 14 '17 at 20:42
  • Initially generate and store a list of all numbers 1..1000. Then each time randomly pick one of them and remove it from the list. – Bo Persson Oct 14 '17 at 20:43

2 Answers2

2

Your basic problem is that random number generation does not guarantee uniqueness. It certainly does not guarantee uniqueness between runs of the program (e.g. if you want to modify the database during multiple runs of the program, and maintain consistency). Therefore, you need a way of generating a set of unique IDs, remove any that have been previously used (e.g. are represented in the database), and then shuffle whatever is left.

One approach might be;

  1. Create a list of 1000 (or whatever number you need) unique IDs (e.g. in a vector). This can be done with a simple loop, or using std::generate() with an appropriate generator that returns a different value every time it is called. The method of generating unique IDs need to be consistent (no randomness) to allow the second step to work.
  2. Read the database and remove every ID that is in the database from the list.
  3. If the remaining list has zero elements, don't allow adding more users.
  4. Shuffle the list. In C++11 or later, use std::shuffle(). You'll need to read up on random number generation. Before C++14, you MIGHT use std::random_shuffle(), but bear in mind it uses rand() to generate random values, and the quality of that is uncertain - which is why it has been deprecated in C++14 (flagged for future removal from the standard).
  5. Every time you need a new unique value (e.g. when creating a user) obtain the last value from the list, remove that value from the list, create the user, and save it to the database.
Peter
  • 35,646
  • 4
  • 32
  • 74
  • This is exactly what I was looking for, a vector. I haven't heard about them yet, but I've been reading about them since the answer and am going to try to apply them to my program as soon as I can. Thank you very much! – Johnson Nguyen Oct 15 '17 at 05:45
1

There is a tricky thing to get that: Let's say you want 10 values randomly generated as a permutation and you want to store them in a file.

So you can calculate how to generate the random indexes then use the indexes on the array of values to store data:

I also face some same issue one day when I was developing a game of card with images that each failure the hidden images jump randomly into some positions.

#include <iostream>
#include <fstream>
#include <ctime>


int main(){

    srand(time(NULL)); 

    std::ofstream out("data.txt");

    // arrays of data whose values will be stored randomly in a text file.  
    int array[10] = {7, 57, 23, 21, 1,
                    0, 18, 19, 3, 777};

    // array of indexes and initializing it
    int indexes[10];
    for(int i(0); i < 10; i++)
        indexes[i] = rand() % 10;

    // indexes are filled with random values from 0 to 9 but it surely contains duplicates eg:

    // 3, 0, 7, 5, 2, 8, 0, 1, 0, 0


    // Now I use my algorithm to discard duplicates and repeating until I get an array of unique indexes.

    for(int i = 0; i < 10; i++){
        for(int j(0); j < 10; j++){
            if(indexes[i] == indexes[j] && i != j){
                indexes[j] = rand() % 10;
                i = 0;
            }           
        }
    }   

    // check out that the indexes are unique and no duplicates there:

    std::cout << "\n\nThe random indexes: " << std::endl;

    for(int i = 0; i < 10; i++)
        std::cout << indexes[i] << ", ";

    // writing the random values of array using the random indexes array to the file:

    for(int i = 0; i < 10; i++)
        out << array[indexes[i]] << ", ";

    // printing the random values of the array
    std::cout << "\n\nThe random values: " << std::endl;

    for(int i = 0; i < 10; i++)
        std::cout << array[indexes[i]] << ", ";

    out.close();

    std::cout << std::endl << std::endl << std::endl;
    return 0;
}

The output: Try to run the program many times and see the result.

//   1
The random indexes:
3, 9, 5, 1, 7, 6, 0, 4, 8, 2,

The random values:
21, 777, 0, 57, 19, 18, 7, 1, 3, 23,

//   2
The random indexes:
5, 8, 0, 1, 3, 9, 4, 2, 6, 7,

The random values:
0, 3, 7, 57, 21, 777, 1, 23, 18, 19,


//   3
The random indexes:
6, 7, 3, 1, 5, 2, 4, 9, 0, 8,

The random values:
18, 19, 21, 57, 0, 23, 1, 777, 7, 3,
  • I offered only a small example so in your case if you want 1000 unique values just look at 0-1000 as an array of unique values so you can use the algorithm above:

    1// initializing
    int randValues[1000];
    for(int i(0); i < 1000; i++)
        randValues[i] = (rand() % 1000) + 1; // because you want to discard 0
    

    now get the unique values:

    for(int i(0); i < 1000; i++){
        for(int j(0); j < 1000; j++){
            if(randValues[i] == randValues[j] && i != j){
                randValues[j] = (rand() % 1000) + 1;
                i = 0; // reset
            }
        }
    }
    
Raindrop7
  • 3,889
  • 3
  • 16
  • 27