Vector of tuple structs - c++

I'm getting an error on the following code snippet;
#include <cstdio>
#include <cstdlib>
#include <vector>
#include <iostream>
using namespace std;
struct tuple {
int x;
int y;
};
int main() {
//srand(time(NULL));
vector<tuple> locations;
int dimentions = 20;
double filledness = 0.65;
while (locations.size() < dimentions * dimentions * filledness) {
tuple point;
point.x = rand() % dimentions;
point.y = rand() % dimentions;
locations.push_back(point);
}
int count = locations.size();
tuple start, end;
start = locations[rand() % count];
end = locations[rand() % count];
cout << count << endl;
for (int i = 0; i < locations.size(); i++) {
cout << locations[i].x << " " << locations[i].y << endl;
}
cout << start.x << start.y << endl;
cout << end.x << end.y;
return 0;
}
The vector initialization is in my main and the struct outline just above. I obviously don't understand something about vectors. I've tried making the struct a class as well as replacing vector of tuples with a vector of tuple*.
Can someone please explain why a vector can't be used in this way,
I would prefer if you didn't tell me how to fix the error directly.
error: template argument 1 is invalid
vector<tuple> locations;

The reason for your error is this struct:
struct tuple {
int x;
int y;
};
1) You called your type tuple, when there is a std::tuple that exists in the standard library and
2) You used using namespace std;, thus any mention of tuple in your code potentially clashes with std::tuple.
If you rename your struct to my_tuple or similar, the error that you are getting now should be remediated.

Related

C++ Class of array of objects

I am learning C++ and for that, I try to do a simple game project (having the same rows as columns and randomly distributed numbers from 0-blank to rows*rows-1. Target is for player to change numbers to be in numeric order by rows). Then 0-blank can be switched with any neighborhood horizontally or vertically) I code it through procedural code and it works fine. Now I am trying to redo it using object-oriented programming and classes.
For that reason I have 2 classes:
Number - stores 2 integers with position x and y
Deck - stores array of Numbers, practically s index of an array is the number itself and Number object just store position.
Deck deck (rows) creates sorted numbers with position and is checked by std::cout.
Now I am trying to implement the shuffle function which will take randomly 2 Numbers and switch their positions (m_posX and m_posY) however trying the same principle to get m_posX is not correct and gives different large numbers compared to the creation of the position.
getNumber just does not work as I intended.
Practically I need to return m_posX and m_posY from exact Number object in array of m_game deck.
Any suggestions what am I doing wrong is welcome.
I have this code:
Number.h
#ifndef NUMBER_H
#define NUMBER_H
#include <array>
class Number
{
public:
// Number(int x, int y, int d);
setPosition (int x, int y);
setPosition (std::array <int,2> &xy ); // std::array [2]
setDigits (int d);
switchPosition (Number &c1, Number &c2);
std::array<int,2> getPosition (); // std::array [2]
int getPositionX ();
int getPositionY ();
int getDigits(); // int
protected:
int m_posX;
int m_posY;
int m_digits;
};
#endif // NUMBER_H
Number.cpp
Number::setPosition (int x, int y)
{
m_posX = x;
m_posY = y;
}
Number::setPosition (std::array <int,2> &xy )
{
m_posX = xy [0];
m_posY = xy [1];
}
Number::setDigits (int d)
{
m_digits=d;
}
Number::switchPosition (Number &c1, Number &c2)
{
int tempX {c1.m_posX};
int tempY {c1.m_posY};
c1.setPosition (c2.m_posX, c2.m_posY);
c2.setPosition (tempX, tempY);
}
std::array<int,2> Number::getPosition ()
{
static std::array <int,2> position;
position [0] = m_posX;
position [1] = m_posY;
return position;
}
int Number::getDigits ()
{
return m_digits;
}
int Number::getPositionX ()
{
return m_posX;
}
int Number::getPositionY ()
{
return m_posY;
}
deck.h
#ifndef DECK_H
#define DECK_H
#include "number.h"
class Deck
{
public:
Deck(int rows=3);
shuffleDeck (int rows);
Number & getNumber (int elementNumber);
protected:
std::array <Number,100> m_game;
};
#endif // DECK_H
deck.cpp
#include "deck.h"
#include "number.h"
#include "rnd.h"
#include <iostream>
Deck::Deck(int rows)
{
std::array <Number,100> m_game;
for (int j {0}; j < (rows); ++j)
{
for (int i {0}; i < (rows); ++i)
{
m_game[i+j*rows].setPosition (i,j);
std::cout << "Number: " << (i+j*rows) << '\t' << "Coordinates: " << '\t' << m_game[i+j*rows].getPosition()[0] <<"," << m_game[i+j*rows].getPosition()[1] << '\n' ;
};
};
std::cout << "fc Deck::Deck (int rows) Number10 posX: "<< m_game[10].getPosition()[0] << '\n';
std::cout << "fc Deck::Deck (int rows) Number10 posY: "<< m_game[10].getPosition()[1] << '\n';
}
Number & Deck::getNumber (int elementNumber)
{
std::cout << "fc Deck::getNumber() Number " << elementNumber << " getPosition X,Y: " << m_game[elementNumber].getPositionX() << "," << m_game[elementNumber].getPositionY() << '\n' ;
return m_game[elementNumber];
}
game.cpp running code
#include "game.h"
#include "gmath.h"
#include "constant.h"
#include "graphics.h"
#include "number.h"
#include "deck.h"
#include <iostream>
int game (int rows)
{
int steps = 0;
Graphics piece {};
Deck deck(rows);
Number temp = deck.getNumber(10);
int tempI = temp.getPosition()[10];
//
// THIS DOES NOT WORK GETTING printed large number as 28573728
// [10] has m_posX set to 2 and m_posY set to 2 by Deck deck (rows);
//
std::cout << "CHECK game.h Number10 positionX: "<< tempI << '\n';
return steps; // for future counting score
}
Try return by value and not by reference here:
Number & Deck::getNumber (int elementNumber)
{
std::cout << "fc Deck::getNumber() Number " << elementNumber << " getPosition X,Y: " << m_game[elementNumber].getPositionX() << "," << m_game[elementNumber].getPositionY() << '\n' ;
return m_game[elementNumber];
}
like this:
Number Deck::getNumber (int elementNumber)
{
std::cout << "fc Deck::getNumber() Number " << elementNumber << " getPosition X,Y: " << m_game[elementNumber].getPositionX() << "," << m_game[elementNumber].getPositionY() << '\n' ;
return m_game[elementNumber];
}
and of course do not forget to change the declaration:
Number getNumber (int elementNumber);
The problem is very obvious.
In function game you are writing int tempI = temp.getPosition()[10];.
The function getPosition() returns a std::array<int, 2>. So, an array having 2 elements. One for x and one for y position. But with [10] your are trying to access the element number 10 from your array (which has only 2 elements). This is an out of bounds error. So, It will read some random nonesense value and show that. This is undefined behaviour.
I am not sure, which compiler you have, but in debug mode, it should throw an exception and inform you about the problem.
Correct it to
int tempx = temp.getPosition()[0];
int temp< = temp.getPosition()[1];
You anyway need to enable ALL compiler warnings. It did it and got dozens of messages.
You define many functions without return type. You must use void for this, e.g. function setPosition(int x, int y); must be defined as void setPosition(int x, int y);. And so on.
Also in constructor of Deck you are redefining and with that overwriting the already defined array std::array <Number, 100> m_game; in class deck. Delete the line in the constructor.
You may also consider to replace the std::array <int, 2>& xy by a std::pair or a simple struct like:
struct Position{
int x;
int y;
};
That would be more intuitive . . .

Usage of vector push_back with pair

I was looking at the implementation of Prim's Algorithim on geeksforgeeks.org and tried to implement the function on practice mode. I looked at how the input was received and I saw this:
#include<bits/stdc++.h>
using namespace std;
const int MAX = 1e4 + 5;
int spanningTree(vector <pair<int,int> > g[], int n);
int main()
{
int t ;
cin>>t;
while(t--)
{
vector <pair<int,int> > adj[MAX];
int n,e;
int w, mC;
cin >> n>> e;
for(int i = 0;i < e;++i)
{
int x,y;
cin >> x >> y >> w;
adj[x].push_back({w, y});
adj[y].push_back({w, x});
}
mC= spanningTree(adj, MAX);
cout << mC << endl;
}
return 0;
}
I'm having a lot of trouble understanding how they're using vector. I've never seen the passing of a vector in a similar way to an array: vector <pair<int,int> > g[].
I looked at the STD implementation of vector and couldn't find anything about passing a vector this way, or constructing a vector with vector <pair<int,int> > adj[MAX];.
Lastly, I am very confused about what the following code does:
adj[x].push_back({w, y});
adj[y].push_back({w, x});
I tried implementing it myself:
#include <iostream>
#include <vector>
#include <utility>
#include <string>
using namespace std;
int main()
{
vector< pair<string, int> > vec[2];
vec[0].push_back({"One", 1});
vec[1].push_back({"Two", 2});
for(int x = 0; x < 2; ++x){
cout << vec[x].first << ", " << vec[x].second << endl;
}
return 0;
}
But I get an error class 'std::vector< pair<string, int> >' has no member named ‘first’.
If I could have some help understanding how vector is being used here, I would really appreciate it. I looked at multiple StackOverflow posts already, including vector::push_back vs vector::operator[].
The link to the original problem is here
I've never seen the passing of a vector in a similar way to an array: vector <pair<int,int> > g[]
It is an array! An array of vectors.
The problem with your code is that you have two vectors, both with a single element, and your loop only pulls out the vectors... not their single element.
Your version would be:
#include <iostream>
#include <vector>
#include <utility>
#include <string>
using namespace std;
int main()
{
vector< pair<string, int> > vec[2];
vec[0].push_back({"One", 1});
vec[1].push_back({"Two", 2});
for(int x = 0; x < 2; ++x){
cout << vec[x][0].first << ", " << vec[x][0].second << endl;
}
return 0;
}
All I added was [0] (index into each vector).
Of course such an example is of questionable practicality. In such a situation it would seem that you want one vector with two elements, and no arrays in sight.
To be honest, I'm not wild about the original code, either. Mixing arrays and vectors is a recipe for confusion (hyello); they could have used "2D vectors" or, better, a 1D vector with 2D indexes laid on top of it. That would then have much better cache locality as well.
Its' a C-style array of vectors, really nothing magic here.
int spanningTree(vector <pair<int,int> > g[], int n);
Maybe you have seen something like that before:
int foo( int array[], int n);
In their code, the elements of the array are not ints but std::vectors. Why they mix plain arrays and std::vector I cannot tell you.
In your example, you need to first use operator[] to access an element before you can access its .first and .second, or use front to get the first element:
for(int x = 0; x < 2; ++x){
cout << vec[x].front().first << ", " << vec[x].front().second << endl;
}

c++ right way to initialize a vector of a struct

i searched a lot here, but there is no right explanation for me, for an advanced newbie in c++. I worked before with vector of structs and now I get segmentation faults...
Thats why I want to know how such objects actually works and if it is the right the way I am doing!
I have a struct like
struct numberOfSpecies {
int predator;
int prey1;
int prey2;
};
and a vector of it:
std::vector<numberOfSpecies> size;
Before I resize it and fill it with values.
size.resize(100);
what is actually this doing? Is this right for a struct?
It looks like it is initialized with zeros...
Now I am doing this like:
size[t].predator=0;
size[t].prey1=0;
size[t].prey2=0;
for(int k = 0; k < N; ++k){
size[t].predator++;
size[t].prey1++;
size[t].prey2++;
}
Is this right? Where are possible issues? How to do it better?
The easiest and 'correct' solution here is probably to just use the resize() function that belongs to the vector object with aggregate initialization (if you have access to c++11 and on), something like
size.resize(100,{0,0,0}); //aggregate initialization
for(int k = 0; k < N; ++k)
{
size[t].predator++;
size[t].prey1++;
size[t].prey2++;
}
All members of each numberOfSpecies object will be initialized to 0.
This:
size[t].predator=0;
size[t].prey1=0;
size[t].prey2=0;
will write zeros to the tth element of size - that may or may not be useful:
This:
for(int k = 0; k < N; ++k){
size[t].predator++;
size[t].prey1++;
size[t].prey2++;
}
will increment the tth element of size N times. This seems incredibly unlikely to be useful. I think what you want is:
size[0].predator=0; // Technically not needed because .resize()
size[0].prey1=0; // will have initialized it to zero anyway
size[0].prey2=0; // *BUT* explicit is always better than implicit.
// Initialize each element of size to be one greater than previous.
for(int k = 1; k < N; ++k){
size[k].predator = size[k-1].predator + 1;
size[k].prey1 = size[k-1].prey1 + 1;
size[k].prey2 = size[k-1].prey2 + 1;;
}
Use the value parameter for static parameters.
#include <vector>
struct foo{
int g;
int h;
int l;
};
int main()
{
std::vector<foo> manyFoo(10, {0});
manyFoo.resize(60, {0});
}
If you want to grow your vector as you also put arbitrary values into the struct you could ->
#include <iostream>
#include <vector>
struct foo{
foo(int aG,int aH, int aL):g(aG),h(aH),l(aL) {};
int g;
int h;
int l;
};
int main() {
std::vector<foo> lVec;
for (int i=0;i<10;i++) {
lVec.emplace_back(foo(i,i*2,i*4));
}
int lPos=0;
for (auto &rFoo: lVec) {
std::cout << "Item pos" << lPos++ << " g:" << rFoo.g << " h:" << rFoo.h << " l:" << rFoo.l << std::endl;
}
return EXIT_SUCCESS;
}
If you know the size of the vector and you want to populate it you could ->
#include <iostream>
#include <vector>
struct foo{
foo(int aG,int aH, int aL):g(aG),h(aH),l(aL) {};
int g;
int h;
int l;
};
int main() {
std::vector<foo> lVec(10,{0,0,0});
int lPos = 0;
for (auto &rFoo: lVec) {
rFoo = foo(lPos,lPos*2,lPos*4);
lPos++;
}
lPos=0;
for (auto &rFoo: lVec) {
std::cout << "Item pos" << lPos++ << " g:" << rFoo.g << " h:" << rFoo.h << " l:" << rFoo.l << std::endl;
}
return EXIT_SUCCESS;
}
You could add an default constructor to your structure. The new code will look something like this:
struct numberOfSpecies {
numberOfSpecies (): predator(0), prey1(0), prey2(0) { } // default constructor
int predator;
int prey1;
int prey2;
};
That way, your structure will be properly initialized inside your vector when resize is applied.

C++ Problems with arrays, begin and end in functions

Hello I am trying to write a script that picks a random number and then excludes that number afterwards.
#include <iostream>
#include <ctime>
#include <random>
#include <iterator>
using namespace std;
random_device rd; // non-deterministic generator
mt19937 gen(rd()); // to seed mersenne twister.
uniform_int_distribution<> dist(1, 52); // distribute results between 1 and 6 inclusive.
int testFunc(int cardArray, int cardArray2, int k) {
cardArray[k] = dist(gen);
copy(begin(cardArray), end(cardArray), begin(cardArray2));
cardArray2[k] = 0;
bool exists = find(begin(cardArray2), end(cardArray2), cardArray[k]) != end(cardArray2);
cardArray[k] = dist(gen);
cout << i + 1 << ": " << cardArray[k] << " " << exists << endl;
return 0;
}
int main()
{
int cardArray[52] = { 0 };
int cardArray2[52] = { 0 };
int i = 0;
for (int n = 0; cardArray[n] == 0 && n < 52; n++) {
cardArray[i] = dist(gen);
copy(begin(cardArray), end(cardArray), begin(cardArray2));
cardArray2[i] = 0;
bool exists = find(begin(cardArray2), end(cardArray2), cardArray[i]) != end(cardArray2);
cardArray[i] = dist(gen);
cout << i + 1 << ": " << cardArray[i] << " " << exists << endl;
i++;
}
cout << endl;
cin.ignore();
return 0;
}
So there's a few problems so far. Here are the errors:
no instance of overloaded function "end" matches the argument list
no instance of overloaded function "begin" matches the argument list
expression must have pointer - to - object type
I just can't figure out what's wrong. The function itself works fine if it's just in main but I need to be able to call it.
Please tell me if I need to post more information.
You are taking in ints in you function not int*
int testFunc(int cardArray, int cardArray2, int k)
should be
int testFunc(int* cardArray, int* cardArray2, int k)
Unfortunately this will stop std::begin and std::end from working as they need an array and not a pointer. To pass the arrays to function you need to take them by reference. To do that we can use a template like:
template<typename T, std::size_t N, std::size_t M>
int testFunc(T (&cardArray)[N], T (&cardArray2)[M], int k)
Or we can skip using native arrays and use a std::array or std::vector

Why am i getting out-of-range error?

I can't seem to find where my issue is. Its a three file program with aDie class in one file, aHistogram class in another file, and the main.cpp file. It is supposed to print a histogram constructed with X's to show how many times the die landed on each of the six faces. I cant move forward because of the vector error... There may be other issues with the program that i haven't worked out yet, but I just want to know about the vector error. Thank you.
main.cpp:
#include <iostream>
#include <stdlib.h> //srand and rand
#include <time.h> //Time
#include <vector>
#include <algorithm>
#include "aHistogram.h"
#include "aDie.h"
using namespace std;
int main()
{
srand (time(NULL));
int numRolls;
const int maxLengthOfLine = 50;
cout << "How many rolls? " << endl;
cin >> numRolls;
aDie fairDie;
aHistogram fairHistogram;
//For Loop rolls the die and updates the histogram vector ~~binHistogram.
for(int i = 0; i < numRolls; i++)
{
int face = fairDie.roll();
fairHistogram.update(face);
}
cout << "*******************" << endl;
cout << "*****Histogram*****" << endl;
cout << "*******************" << endl;
fairHistogram.display(maxLengthOfLine);
}
aDie.h:
#ifndef ADIE_H_INCLUDED
#define ADIE_H_INCLUDED
#include <stdlib.h>
#include <time.h>
#include <vector>
#include <algorithm>
using namespace std;
/********************************************/
/*******Definition of aDie class*************/
/********************************************/
class aDie
{
public:
int roll(); //return an integer between 1 and 6 to represent what face appears when the die is rolled.
aDie(); //Default constructor
~aDie(); //Destructor
private:
int numFaces = 6;
};
int aDie::roll()
{
return ((rand() % numFaces) + 1); //returns a random number between 1 and 6
}
aDie::aDie()
{
cout << "Dice Roll...." << endl;
return;
}
aDie::~aDie()
{
return;
}
#endif // ADIE_H_INCLUDED
aHistogram.h:
#ifndef AHISTOGRAM_H_INCLUDED
#define AHISTOGRAM_H_INCLUDED
#include <algorithm>
#include <stdlib.h>
#include <vector>
using namespace std;
/********************************************/
/*******Definition of aHistogram class*******/
/********************************************/
class aHistogram
{
public:
void update(int face);
void display(int maxLengthOfLine);
int Count(int face);
void clear();
aHistogram(); //Constructor
~aHistogram(); //Destructor
private:
vector<int> binHistogram;
const int numFaces = 6;
int totalRolls;
int largeBin = 0;
double xScale;
};
//Adds a count to each face every time the die lands on said face.
void aHistogram::update(int face)
{
binHistogram.at(face) += 1;
return;
}
//Displays the histogram with X's
//maxLengthOfLine represents the maximum number of x’s to be printed for the largest bin count.
void aHistogram::display(int maxLengthOfLine)
{
xScale = maxLengthOfLine / largeBin;
for(int i = 1; i <= 6; i++)
{
cout << i << " : " << Count(i) << " : ";
int numXs = xScale * binHistogram.at(i);
for(int j = 0; j < numXs; j++)
{
cout << "X";
}
}
}
//To be called AFTER aHistogram::update
//Returns a count of how many times for each face of the die
int aHistogram::Count(int face)
{
//For Loop determines the largest bin count
for (int i = 1; i < numFaces; i++)
{
while (binHistogram[i] >= largeBin)
{
largeBin = binHistogram.at(i);
}
}
//
return binHistogram.at(face);
}
void aHistogram::clear()
{
binHistogram.clear();
return;
}
//Defines the DEFAULT CONSTRUCTOR. Sets all elements of the histogram to zero.
aHistogram::aHistogram()
{
return;
}
//Defines the DESTRUCTOR. Clears vector after use.
aHistogram::~aHistogram()
{
binHistogram.clear(); //Clears vector
return;
}
#endif // AHISTOGRAM_H_INCLUDED
I didnt find the place where you initialize the histogram this might be the problem. But even if you fix that, you will hit two other bugs:
for (int i = 1; i < numFaces; i++)
{
while (binHistogram[i] >= largeBin)
{
largeBin = binHistogram.at(i);
}
}
you are accessing elements 1....6 when probably it should be 0...5. Same problem in the line where you have
largeBin = binHistogram.at(i);
which is most likely the line that causes the error (the one above wont be so nice to tell you what is the problem but just crash your program).
You never change the size of the vector in the aHistogram class, which means its size will always zero. Any index will be out of bounds.
For things like histograms I would actually recommend you to use std::unorderd_map instead of std::vector, with the "face" being the key and the count being the data. Then you could do e.g.
binHistogramMap[face] += 1;
without worrying about the element for face not existing (it will be created and initialized to zero if the entry doesn't exist).