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
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;
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.
Read the database and remove every ID that is in the database from
the list.
If the remaining list has zero elements, don't allow adding more
users.
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).
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.
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
}
}
}
Related
For this assignment, I have to write a program that removes the odd numbers from an array
and replaces them with even numbers. The array must have 10 elements and be initialized with the
following numbers: 42, 9, 23, 101, 99, 22, 13, 5, 77, 28.
These are the requirements:
Must use the values provided in my array.
Print the original array to the console.
Identify any odd values in the array and replace them with even values.
Display the updated array to the console.
This is the output I am going for:
The original array is: 42 9 23 101 99 22 13 5 77 28
Your even number array is: 42 18 46 202 198 22 26 10 154 28
I'm super new to programming, so this concept is difficult for me to grasp, so if someone could give guidance that would mean the world.
This is what I have so far
#include <iostream>
using namespace std;
int main()
{
int const size = 10;
int values[size] = { 42, 9, 23, 101, 99, 22, 13, 5, 77, 28 };
for (int i = 0; i < size; i++)
{
if (values[i] % 2 != 0)
{
cout << (values[i] * 2) << endl;
}
}
return 0;
}
output
It's multiplying the odd numbers, which is want I want, but not each one in their own line. Also the new even numbers need to be along with the original even numbers.
You mentioned that you are somehow new to programming. So, we need to adapt our answer to that fact. You will not yet know all the existing functions in the standard library. So, let us come up with a very easy solution.
Obviously we need to frist print the original unmodified date from the array. So, we will output the initial text and then iterate over all the slements in the array and output them as is.
Next, we show the second label string and then iterate again over all elements in the array. We the check for each value, if it is odd. If it is, then we print the double of this value, else, we show to unmodified value.
Please have a look at the below for one potential solution approach:
#include <iostream>
using namespace std;
int main() {
// Size of our array
int const size = 10;
// Arry with some random sample data
int values[size] = { 42, 9, 23, 101, 99, 22, 13, 5, 77, 28 };
// Show the original array
cout << "\nThe original array is: ";
for (int i = 0; i < size; ++i) cout << values[i] << ' ';
// Now show check for odd numbers
cout << "\nYour even number array is: ";
// Show result
for (int i = 0; i < size; ++i)
if (values[i] % 2 != 0)
cout << (values[i] * 2) << ' ';
else
cout << values[i] << ' ';
cout << '\n';
}
The transformation itself seems pretty simple. There are a number of ways to do the job. Here's one possibility:
std::transform(b, e, b, [](auto v) { return v * ((v & 1) + 1); });
Just as a fair warning: if you turn that in for homework, whoever's teaching the class is probably going to ask some deep and searching questions about how it works, and start to get really suspicious if you don't have answers showing equally deep understanding.
I'm trying to make a deck of cards with only using array and no classes.
How do I declare a value to each and every card? It seems very inefficient trying to write it like this, and then trying to give a value to each index position:
int deckOfcards[52]{ 1,2,3,4,5,6,7,8,9,10.......... };
Also I will then draw 2 random cards and declare a winner. Is it possible to use rand() function in arrays?
You can create a loop to populate your array for you..
int deckOfCards[52]{};
for (int i = 0; i < 52; i++)
{
deckOfCards[i] = i+1;
}
That works just fine for this particular instance, but you may want to use
std::size(deckOfCards) in your loop because the size of the array may not always be known.
int deckOfCards[52]{};
for (int i = 0; i < std::size(deckOfCards); i++)
{
deckOfCards[i] = i+1;
}
Remember that array index's start at 0, so i will go from 0 to 51. That's why we are setting deckOfCards[i] equal to i + 1
There is imo even a nicer way to introduce randomness to cards,
use std::shuffle. By using this function you get code that kind of
explains itself. It will also introduce the deck of cards you are looking for.
#include <algorithm>
#include <array>
#include <random>
#include <iostream>
//-----------------------------------------------------------------------------
struct card_t
{
// each new instance gets a number which is then increased
// ++ at the end is important.
card_t() :
number{ g_card_number++ }
{
}
std::size_t number;
static std::size_t g_card_number;
};
std::size_t card_t::g_card_number = 1;
//-----------------------------------------------------------------------------
int main()
{
// setup random generation c++ style
std::random_device rd;
std::default_random_engine random_generator{ rd() };
// create a deck of 52 cards
// this will call the constructor for each of them so they all get
// a unique number
std::array<card_t, 52> cards;
// shuffle the cards using the random generator
std::shuffle(cards.begin(), cards.end(), random_generator);
std::cout << "first card has number : " << cards[0].number << "\n";
std::cout << "second card has number : " << cards[1].number << "\n";
return 0;
}
The requirements are that you want to emulate a standard deck of playing cards, and comments indicate that you want to track the suit and the value. You also claim that you want to do this with just an array of integers.
It is possible, but probably not what you're really after. Simpler solutions have already been posted as answers, but I will attempt to provide an answer that meets the stated requirements.
I'll just say up front that this is likely an XY problem, meaning the problem you stated is not the real problem you're having. You'll see as much with the code.
To uniquely encode two pieces of information into a single int, you'll need a way to encode and decode. The simplest way to do this is with prime number multiplication. This is because the only two dividends can be the prime numbers. Just for kicks, this is also the basis of a lot of modern cryptography.
You'll need 17 prime numbers (4 suits and 13 values). I'm choosing the 'first' 17, starting from 3. They are: 3, 5, 7, 11, 13, 17, 19, 23, 29, 31, 37, 41, 43, 47, 53, 59, and 61.
I will arbitrarily use the last 4 to represent the suits. So for me, clubs is 47, spades is 53, then hearts then diamonds.
So for example, a 3 of clubs would have a value of 235 (5 * 47). A 3 of hearts would have a value of 295 (5 * 59). Every card is uniquely identifiable, and you can know the value and the suit.
You could probably get away with just prime numbers for the suits, but I know that if we use two primes, the uniqueness is guaranteed.
To randomly pick two cards, you'll actually shuffle the entire deck and just look at the first two elements of the array. This is because if you try to just pick two random numbers in the range [0, 51], (the [] means it's inclusive), there is the possibility that you pick the same number twice, which is impossible in a real deck.
Here's the code, which I tried to keep as simple as possible (i.e., trying to keep my Standard Library use to a minimum with sanity exceptions)
#include <algorithm>
#include <iostream>
#include <iterator>
#include <random>
void create_deck(int deck[], int deckSize) {
// cl sp he di
int suits[]{47, 53, 59, 61};
// 2 3 4 5 6 7 8 9 10 J Q K A
int values[]{3, 5, 7, 11, 13, 17, 19, 23, 29, 31, 37, 41, 43};
int idx = 0;
for (std::size_t s = 0; s < sizeof(suits) / sizeof(suits[0]); ++s) {
for (std::size_t v = 0;
v < sizeof(values) / sizeof(values[0]) && idx < deckSize; ++v) {
deck[idx] = suits[s] * values[v];
++idx;
}
}
}
// Prints the name of the card and returns the value
int decode_card(int val) {
// cl sp he di
int suits[]{47, 53, 59, 61};
std::string suitNames[]{"clubs", "spades", "hearts", "diamonds"};
// 2 3 4 5 6 7 8 9 10 J Q K A
int values[]{3, 5, 7, 11, 13, 17, 19, 23, 29, 31, 37, 41, 43};
std::string valueNames[]{"two", "three", "four", "five", "six",
"seven", "eight", "nine", "ten", "jack",
"queen", "king", "ace"};
int realValues[]{2, 3, 4, 5, 6, 7, 8, 9, 10, 11, 12, 13, 14};
std::string suit;
std::string value;
for (std::size_t i = 0; i < sizeof(suits) / sizeof(suits[0]); ++i) {
if (val % suits[i] == 0) {
suit = suitNames[i];
val /= suits[i];
for (std::size_t v = 0; v < sizeof(values) / sizeof(values[0]); ++v) {
if (values[v] == val) {
value = valueNames[v];
std::cout << value << " of " << suit << ".\n";
return realValues[v];
}
}
}
}
return -1;
}
int main() {
const int deckSize = 52;
int deck[deckSize];
create_deck(deck, deckSize);
std::shuffle(std::begin(deck), std::end(deck),
std::mt19937(std::random_device{}()));
int playerOneDraw = deck[0];
int playerTwoDraw = deck[1];
std::cout << "Player 1: ";
int playerOneValue = decode_card(playerOneDraw);
std::cout << "Player 2: ";
int playerTwoValue = decode_card(playerTwoDraw);
if (playerOneValue > playerTwoValue) {
std::cout << "Player 1 wins.\n";
} else if (playerOneValue == playerTwoValue) {
std::cout << "It's a draw.\n";
} else {
std::cout << "Player Two wins.\n";
}
}
One run's output:
Player 1: ace of spades.
Player 2: three of diamonds.
Player 1 wins.
Right away, I hope you see that is code a lot longer and a lot more complex than the other solutions that use classes. That makes this code harder to maintain in the long run.
This is exactly because the requirements you've given are making the task harder than it needs to be. I opted to not use global variables because you really shouldn't, but I also opted out of a namespace because I'm assuming if you don't want classes you probably don't want a namespace.
For example, if the user enters the number 21, I want all the polite numbers listed. so for 21, the output would be 3, 5, 6, 7, 9, 10, 11, 12, 13, 14, 15, 17, 18, 19, 20, 21. I am new for loops and I am having a difficult time trying to get this to work. I cant include any global variables for this assignment. Any help would be greatly appreciated. Thank you.
Seems like you are just excluding the numbers which are squares, which would not produce the right answer.
You can either create an array upto upValue with initial value set to 0 and mark all the powers of 2 as 1 using this for loop:
for(int j=1;j<=upValue;j*=2){
arr[j]=1;
}
now you have flagged all the powers of two and then iterate over the all values from 1 to upValue and print the ones that are set to 0;
The following program does what you want it to do.
#include <iostream>
#include <math.h>
void politeNo(int input)
{
// Print all initial input Polite number
for (int n = 1; n <= input; ++n)
{
// Calculate nth Polite number
int result = (int)(n +
(log((n + (log(n) /
log(2))))) /
log(2));
// Display calculated result
std::cout << " " << result;
if (result == input){break; }
}
}
int main()
{
int upValue = 0;
std::cout<<" What is the upper value ?";
std::cin >> upValue; //Stores user input into upValue
while (upValue < 1) //Validate user input of upper limit
{
std::cout << "What is the upper value? (must be an integer > 0) ";
std::cin >> upValue;
}
politeNo(upValue);
return 0;
}
Output:
1 3 5 6 7 9 10 11 12 13 14 15 17 18 19 20 21
I am struggling to understand the concept of randomly reading numbers from an array of integers using 'rand()'. I have created a random number generator between 1-3 and want to output an index of an array, then for the generator to randomly output the next generated number from the previous index, until it reaches the end of the array. For example:
'rand()'= 3, 'array[2]'
'rand()' = 2, 'array[4]'
'rand()' = 3, 'array[7]'
if that makes sense?? etc, etc.
The code I'm currently using just outputs a sequence of random numbers. I have place a 'seed' so I can look at the same sequence.
int main()
{
int arrayTest[20] = {1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11, 12, 13, 14, 15, 16,
17, 18, 19, 20};
srand(4);
for(int i = 0; i < 20; i++)
{
arrayTest[i] = (rand() % 3);
cout << arrayTest[i] << endl;
}
}
I am somewhat guessing at what you really want. But it seems to want to make random increments to an index, and use that index to read from the array in a loop.
So this code just doesn't do anything like you want
arrayTest[i] = (rand() % 3);
It writes (not reads) a random value to an array using a sequential (i.e. non-random) index.
Here's what I think you want
int main()
{
int arrayTest[20] = { ... };
srand(4);
int index = -1;
for(int i = 0; i < 20; i++)
{
index += (rand() % 3) + 1; // add random number from 1 to 3 to index
if (index >= 20) // if index too big for array
index -= 20; // wrap around to beginning of array
cout << arrayTest[index] << endl; // read array at random index, and output
}
}
But I'm not completely sure, in particular the way your testArray has the numbers 1 to 20 in order is making me a bit suspicious. Maybe if you explain why you want to do whatever you want to do it would be a bit clearer.
I have a pretty simple question. My goal for this short program is for it to display the set of numbers(which is hard coded), then have the user specify which index a number of the array should be deleted from. It then outputs the new array. This program works but has one major error. When I run it and choose position 2 for example, which should delete 45, instead deletes 34. The program outputs :
12
45
2
8
10
16
180
182
22
instead of :
12
34
2
8
10
16
180
182
22
notice that the number position I want removed instead removes in the position before the number I actually want removed, if you remember that lists start at 0. Thank you!
//This program demos basic arrays
#include <iostream>
using namespace std;
const int CAP = 10;
int main()
{
//read index from user, delete number in position of index they specify.
//when printing the list, number should be gone.
int size;
int list[CAP] = { 12, 34, 45, 2, 8, 10, 16, 180, 182, 22 };
size = 10;
int i, delIndex;
cout << "Your list is: " << endl;
for (i = 0; i < CAP; i++)
{
cout << list[i] << endl;
}
cout << "\nPlease enter index to delete from: ";
cin >> delIndex;
for (i = delIndex; i <= 10; i++)
{
list[i - 1] = list[i];
}
cout << "The index position you specified has been deleted." << endl;
cout << "The new array is: " << endl;
for (i = 0; i < (size - 1); i++)
{
cout << list[i] << endl;
}
return 0;
}
Replace this:
for (i = delIndex; i <= 10; i++)
{
list[i - 1] = list[i];
}
with that:
for (i = delIndex; i < size-1; i++)
{
list[i] = list[i+1];
}
Since you are with C++, why not just using a std vector?
#include <vector>
// Initialize
int vv[10] = { 12, 34, 45, 2, 8, 10, 16, 180, 182, 22 };
std::vector<int> myvector(&vv[0], &vv[0]+10);
There are other easier ways to initialize the vector depending on the compiler. See how to initialize a vector.
Then you can just use the erase method of the vector (here I assume the user knows the indexing starts with 0, otherwise you can just put delIndex-1):
myvector.erase (myvector.begin()+delIndex);
You can easily iterate over the vector to show its contents (there are easier ways of doing this depending on the compiler, use the auto keyword).
for (std::vector<int>::iterator it = myvector.begin(); it != myvector.end(); ++it)
std::cout << ' ' << *it;