c++ 2D vector push_back error in code - c++

I had my program working with a single vector and decided to use a 2D vector to represent multiple hands (one dimensional vector vPlayerHand1 plus one dimensional vector vPlayerHand2 plus ...). I can't figure out how to populate the vector. I am using Visual Studio C++ 2010 which does not seem to fully implement C++11 and reports parsing errors in the IDE for code that is provided as answers to similar questions in this forum. In the outline below Card is a class.
#include <vector>
std::vector<std::vector<Card>> vPlayerHand;
vPlayerHand.push_back(vShoe.back()); /* fails with parsing error No instance of
overloaded function... */
vPlayerHand[0].push_back(vShoe.back()); /* builds okay then error Debug Assertion
Failed... vector subscript out of range */
I am missing something on the correct use of the push_back function with a 2D vector (vector of vectors) I understand the first reference is to the row. and when I populate with push_back it should just do the first row.
Here is more complete code:
Edited at line 29... code runs correctly as given
Re-edited at line 32a as per solution by #RSahu runs correctly. Commented out line 29
1 # include <iostream>
2 # include <vector>
3 # include <algorithm>
4 # include <ctime>
5 # include "Card.h" //Defines Card as having Suit, Rank and functions GetSuit() GetRank()
6
7 std::vector<Card> vShoe; //Card Shoe vector holds 1-8 decks
8 std::vector<Card> vDeck; //Deck vector holds 52 cards of Card class
9 std::vector<std::vector<Card>> vPlayerHand; // Player Hands 0-original, 1-split1, n-splitn
10 std::vector<Card> vDealerHand;
11
12 void CreateDeck(); //Populates Deck with 52 Cards
13 void CreateShoe(int); //Populates Show with Decks*n number of Decks
14 void ShuffleShoe(); // uses random_shuffle
15
16 int main() {
17
18 int iDeckCount = 2;
19 const int NumPlayers = 1;
20 srand(time(0));
21
22
23 CreaateDeck();
24 CreateShoe(iDeckCount);
25 ShuffleShoe();
26
27 // Following line gives parsing error
28 // vPlayerHand = std::vector<std::vector<Card>> (5, std::vector<std::vector<Card>>(12));
// added this line and now runs as expected
/* removed this line in favor of line 32a as per #RSahu
29 vPlayerHand.resize(2); // need only initial size for 2 elements
*/
30 for (int i=0; i<=NumPlayers; i++) {
31 // I believe this is where dimension error comes vPlayerHand[0].push_back
32 // I tried vPlayerHand.push_back(vShoe.back()) but get parsing error "No instance of overloaded function.."
// This line added as per R Sahu. compiles and runs correctly
32a vPlayerHand.push_back(std::vector<Card>());
33 vPlayerHand[0].push_back(vShoe.back()); //Top card in Shoe (last card in vector) is dealt to Player
34 vShoe.pop_back(); //Top card in Shoe is removed (destroyed) from vector Shoe
35 vDealerHand.push_back(vShoe.back()); //Top card in Shoe (last card in vector) is dealt to Dealer
36 vShoe.pop_back(); //Top card in Shoe is removed (destroyed) from vector Shoe
37 }
38
39 /* Show Results
40 std::cout << "\n---------------------------------\n" ;
41 std::cout << " Players Hand" << std::endl;
42 std::cout << vPlayerHand[0][0].GetRank() << "," << vPlayerHand[0][0].GetSuit() << " ";
43 std::cout << vPlayerHand[0][1].GetRank() << "," << vPlayerHand[0][1].GetSuit() << std::endl;
44 */
45 }
Any insight would be helpful.

You have defined vPlayerHand as:
std::vector<std::vector<Card>> vPlayerHand;
When you use vPlayerHand.push_back(arg), arg has to be of type std::vector<Card> or convertible to std::vector<Card>. An argument of type Card cannot be used as an argument to that function. That's what you are trying when you use
vPlayerHand.push_back(vShoe.back())
What you need is:
vPlayerHand.push_back(std::vector<Card>());
vPlayerHand.back().push_back(vShoe.back());
vShoe.pop_back();
vPlayerHand.back().push_back(vShoe.back());
vShoe.pop_back();

Related

How to iterate two vectors in one for loop?

I'm only showing my functions because I believe the problem is in my for loop.
DataStoreVectors::DataStoreVectors() {
}
void DataStoreVectors::addItem(string item1, int item2) {
videoGame.push_back(item1);
gameSize.push_back(item2);
}
void DataStoreVectors::listItems()
{
vector <string>::iterator pv;
vector <int>::iterator px;
for (pv = videoGame.begin(); pv < videoGame.end(); pv++)
{
for (px = gameSize.begin(); px < gameSize.end(); px++)
cout << *pv << " " << *px << endl;
}
}
When I try to print out the data in my two arrays, it prints out the name of each video game about 6 times and assigns my int values to them like so:
Valorant 8
Valorant 70
Valorant 50
Valorant 1
Valorant 26
Valorant 35
Fortnite 8
Fortnite 70
Fortnite 50
Fortnite 1
Fortnite 26
Fortnite 35
Doom Eternal 8
Doom Eternal 70
Doom Eternal 50
Doom Eternal 1
Doom Eternal 26
Doom Eternal 35
Minecraft 8
Minecraft 70
Minecraft 50
Minecraft 1
Minecraft 26
Minecraft 35
Apex Legends 8
Apex Legends 70
Apex Legends 50
Apex Legends 1
Apex Legends 26
Apex Legends 35
Control 8
Control 70
Control 50
Control 1
Control 26
Control 35
Is this possible? Would it be better to make a struct? I'm trying to figure out the right way to print out two vectors side by side.
It's quite simple to keep the iterators synchronized in position. Just add another increment in the for loop like this:
vector <int>::iterator px = gameSize.begin(); // << Add this
for (pv = videoGame.begin(); pv < videoGame.end(); pv++, px++)
// ^^^^^^ Add this
Ensure that both vectors have the same size, or the vector px points to is at least bigger than the other one (videoGame) though.
You could use a range-v3 zip view.
for (auto [game, size] : ranges::views::zip(videoGame, gameSize))
{
std::cout << game << " " << size << std::endl;
}
If the data is linked then you should make a struct from this.
I also recommend giving your parameters a more descriptive name in addItem such as addItem(string gameName, int gameSize) and maybe rename the vectors to use the plural form such as videoGames and gameSizes.
Regarding the iteration over two vectors you can iterate over those with a simple int index (this assumes both vectors have the same size as it seems to be in your case):
for (int i = 0; i < videoGame.size(); ++i)
{
cout << videoGame[i] << " " << gameSize[i] << endl;
}
You can increment each iterator in the same loop, but both arrays would need to be the same size, however it's a horrible bug prone approach, your single array of a struct that includes both fields is a far better approach.

c++ code using std::cin as input crashes halfway

I am currently doing this exercise on codeabbey. https://www.codeabbey.com/index/task_view/greatest-common-divisor
Here is my code.
main.cpp
#include <iostream>
int main()
{
int cases;
int gcd[cases], lcm[cases];
std::cin >> cases; //first input for number of data to be input
for(int x=0; x<cases; x++) { //loop number of times = to cases
int a, b; //for storing the two numbers
std::cin >> a >> b;
int atemp = a, btemp = b; //need to hold initial value of a and b for lcm
while (a!=b) { //basically to calculate gcd.
if(a>b)
a-=b;
else if (b>a)
b-=a;
}
gcd[x] = a; //store gcd for this case.
lcm[x] = atemp * btemp / gcd[x]; // store lcm
}
for(int x=0; x<cases; x++) {
std::cout << "(" << gcd[x] << " " << lcm[x] << ") "; //output gcd and lcm for every case.
}
}
However, when I try running it and using the sample values that the website gave, it always crashes. Below is the list of values that I copied into my console as input.
22
567 10
38 2
4214 2150
489 7459
82 5069
4200 784
4720 1770
2200 1440
6637 1
4984 7
1197 525
9905 472
648 552
7068 5700
22 2
2610 2160
7 7874
3663 3267
25 75
5985 3402
3337 5751
998 7895
When I copied the whole chunk of values as input, it doesn't work. I tried typing in manually, and discovered that it always ends on line 11 of input, (the line that is 4984 7). I think my code is really simple that it shouldn't go wrong... so I am wondering if there is something I do not know of happening here.
First, note that variable length arrays (VLAs) are not a feature of standard C++, although some compilers (like g++) do support them.
With this in mind, note that you are declaring your VLAs - each of size cases before you have assigned a value to cases! So, the arrays will have undefined (possibly zero) size.
To fix this, you should move the declaration of the arrays to after the line that reads the cases value:
int cases; // Variable is declared here BUT HAS NO VALUE ASSIGNED
//int gcd[cases], lcm[cases]; // WRONG - what value is "cases?"
std::cin >> cases; // First input for number of data to be input
int gcd[cases], lcm[cases]; // NOW we can declare the VLAs, knowing the "cases" value!
//...
However, to make your code compatible with Standard C++ you should use the std::vector container class; so, in place of:
int gcd[cases], lcm[cases];
use:
std::vector<int> gcd(cases), lcm(cases);
You can continue to access the elements of the two vectors using the gcd[x] syntax, as std::vector provides the [] operator.

Knapsack problem with multiple availabe packages using dynamic programming

Hello and thanks for helping!
So we've got a list of fireworks containing 1) Number in stock 2) Number of fireworks in this package 3) Diameter which equals the noise and
4) The price.
This is the list:
25 17 10 21
10 15 10 18
5 16 10 19
10 15 12 20
15 9 11 12
10 7 28 23
8 7 16 11
10 6 16 10
25 10 18 25
25 12 18 27
10 5 40 35
60 40 5 27
5 25 30 90
50 1 60 8
Our task is to create a shopping list and buy fireworks so we get the highest possible noise. We've got a knapsack capacity of 1000€. We're also supposed to solve this without using tables (so with dynamic programming instead).
I only use one class called Package which contains the four constraints as shown above.
At first I thought it would make sense to try to write an algorithm for a normal knapsack, so just with the price and the diameter (=weight). I tested it with a different list and it worked perfectly fine. I just iterated through all packages and then again used a nested for loop to find the best constellation (exhaustive search). My next idea was to merge the number of fireworks per package with the diameter, because fireworks can only be bought in a full package.
The only thing left which I still haven't found out is what to do with the amount of packages in stock. Like, with my current algorithm it just buys all packages of a firework until the knapsack is full. But obviously that won't be correct.
void knapsack(vector<Package*> stock){
vector<int> indices, tmp_indices;
int noise,tmp_noise= 0;
int price;
for (unsigned int i = 0; i < stock.size(); i++) {
price = stock[i]->price;
noise = stock[i]->diameter*stock[i]->number_fireworks;
indices.push_back(i);
for (unsigned int j = 0; j < stock.size(); j++) {
if (i != j) {
if (price+stock[j]->price<= BUDGET) {
price+=stock[j]->price;
noise+=stock[j]->diameter*stock[j]->number_fireworks;
indices.push_back(j);
}
}
}
// After second loop we have a new possible constellation
// Check if the previous constellation had a lower value and if so, set it to the current one
if (noise > tmp_noise) {
tmp_noise = noise;
tmp_indices.clear();
// tmp save
for (auto &index : indices) {
tmp_indices.push_back(index);
}
}
price= 0;
noise = 0;
indices.clear();
}
// Best constellation found, Print the shopping list
cout << "\Stock.\tNum\Diameter.\Price\n" << endl;
for(unsigned int i = 0; i < tmp_indices.size(); i++) {
cout << stock[tmp_indices[i]]->stock<< "\t";
cout << stock[tmp_indices[i]]->number_fireworks<< "\t";
cout << stock[tmp_indices[i]]->diameter<< "\t";
cout << stock[tmp_indices[i]]->price<< "\t\n";
}
}
We've been told that we should be able to spend exactly 1000€ to get the correct constellation of fireworks. My idea was to add another for loop to iterate through the amount of available packages, but that didn't really work...
This was our first lesson and I'm a bit desperate, because we have only learned how to solve a knapsack problem with 2 constraints and by using a table R.
Edit: Since one user insisted to get a specific question, here it is: Is the idea of using another loop to include the third constraint correct or is there a better/easier way of doing it? Or is it possible that I need a completely different approach for a knapsack with 3 instead of 2 constraints?
Thanks for help in advance

Need Help in a Project of C++

So this is the actual Problem
Can anyone tell me that how I read the repective Data from the file, and how would I able to store it in variables (without using array) also the code should be generic, That if the number of series will incresed or decresed.. Code will not be affected... I Just can't understand that how would I store sata in variables and how.. Please Help.. :(
Problem
A file contains information of a batsman. Information is no of series
played by the batsman. No of matches played in each series & score in
each match by the batsman. You have to read the data (without using
any array) and find average score and maximum score in all matches of
a series. In the end find overall average score and max score in all
matches.
Input:
Read data from file "cricket.txt". First line contains no of seasons/
series played by the player. Next pair of lines contains matches
played by the batsman followed in next line scores by batsman in
different matches of a season. See sample "cricket.txt"
5
6
93 75 41 40 90 19
5
45 86 30 60 29
3
47 90 33
4
22 2 92 5
5
88 67 96 91 90
First 5 shows player has played 5 seasons/ series
Next 6 show in first series player has played 6 matches
Next line has scores of player in 6 matches
Next 5 show in second series player has played 5 matches
Next line has scores of player in 5 matches
So on in second last line 5 shows player has played 5 matches in 5th
series
Last line has scores of player in 5 matches of last series
You're looking for an array.
int a[10];
// Loop that assigns all elements in array a to 0
for (int i = 0; i < 10; i++)
{
a[i] = 0;
}
// Array b will have all of it's members initialized to 0
int b[10]{};
// You can also assign different values to different elements of the array
b[0] = 6;
b[8] = 2;
// You can then use the array elements in operations
int c = b[0] * b[8];
If you want array like structure without compile time defined size, then use std::vector.
// An empty vector of ints
std::vector<int> d;
// A simple int
int e = 5;
// Push 2 values to the end of the vector
d.push_back(2);
d.push_back(e);
// Use the members for operations
int f = d.at(0) * d.at(1);
Since you've now described the problem you're trying to solve instead of just the problem with the solution you came up with:
You don't need to invent variable names or use arrays to compute averages and maximums.
Here's an example of how you can compute an average of the numbers a user inputs:
float sum = 0;
int elements = 0;
float input = 0;
while (cin >> input)
{
sum += input;
elements += 1;
}
std::cout << "Average: " << sum / elements << std::endl;
It's easy to expand this to also keep track of the maximum value so far.
To expand to the average and maximum of a number of series, add another loop "around" it.

c++ string capacity change during copy assignment

In the C++ Standard std:string follows an exponential growth policy, therefore I suppose the capacity() of string during concatenation will always be increased when necessary. However, when I test test.cpp, I found that in the for-loop, only every two times will the capacity() be shrunk back to length() during assignment.
Why isn't this behavior depending on the length of string, but depending on how frequent I change the string? Is it some kind of optimization?
The following codes are tested with g++ -std=c++11.
test.cpp:
#include <iostream>
int main(int argc, char **argv) {
std::string s = "";
for (int i = 1; i <= 1000; i++) {
//s += "*";
s = s + "*";
std::cout << s.length() << " " << s.capacity() << std::endl;
}
return 0;
}
And the output will be like this:
1 1
2 2
3 4
4 4
5 8
6 6 // why is capacity shrunk?
7 12
8 8 // and again?
9 16
10 10 // and again?
11 20
12 12 // and again?
13 24
14 14 // and again?
15 28
16 16 // and again?
17 32
...
996 996
997 1992
998 998 // and again?
999 1996
1000 1000 // and again?
When you do this:
s = s + "*";
You're doing two separate things: making a new temporary string, consisting of "*" concatenated onto the end of the contents s, and then copy-assigning that new string to s.
It's not the + that's shrinking, it's the =. When copy-assigning from one string to another, there's no reason to copy the capacity, just the actual used bytes.
Your commented-out code does this:
s += "*";
… is only doing one thing, appending "*" onto the end of s. So, there's nowhere for the "optimization" to happen (if it happened, it would be a pessimization, defeating the entire purpose of the exponential growth).
It's actually not convered by the C++ standard what happens to capacity() when strings are moved, assigned, etc. This could be a defect. The only constraints are those derivable from the time complexity specified for the operation.
See here for similar discussion about vectors.