I am learning about c++ and was following a course. A final exercise involves making a program for deck of cards. I have thought of an approach:
I initially tried to do everything with string arrays but realised that it would make more sense to use vectors since. I am now trying to create a std::vector std::string out of my std::string array but with no luck.
I have found some example code online such as:
from https://thispointer.com/5-different-ways-to-initialize-a-vector-in-c/
And tried to implement it for my program, however, I cannot get it to work and cant fully understand what is the issue.
My code:
#include <iostream>
#include <string>
#include <vector>
class card_deck {
public:
card_deck();
std::vector<std::string> deal_hand(int num_cards);
void new_deck();
private:
//std::vector<std::string> cards_vector;
std::string cards[52] =
{
"As","2s","3s","4s","5s","6s","7s","8s","9s","Ts","Js","Qs","Ks",
"Ah","2h","3h","4h","5h","6h","7h","8h","9h","Th","Jh","Qh","Kh",
"Ad","2d","3d","4d","5d","6d","7d","8d","9d","Td","Jd","Qd","Kd",
"Ac","2c","3c","4c","5c","6c","7c","8c","9c","Tc","Jc","Qc","Kc"
};
std::vector<std::string> cards_vector(cards, sizeof(cards)/sizeof(std::string) );
};
As you can see from my code, I initialize a string array in my private variables, and then want to convert this string array to std::vector
The error message returned:
UPDATE
Code works when called in main()
int main()
{
std::string cards[52] =
{
"As","2s","3s","4s","5s","6s","7s","8s","9s","Ts","Js","Qs","Ks",
"Ah","2h","3h","4h","5h","6h","7h","8h","9h","Th","Jh","Qh","Kh",
"Ad","2d","3d","4d","5d","6d","7d","8d","9d","Td","Jd","Qd","Kd",
"Ac","2c","3c","4c","5c","6c","7c","8c","9c","Tc","Jc","Qc","Kc"
};
// Initialize vector with a string array
std::vector<std::string> vecOfStr(cards, cards + sizeof(cards) / sizeof(std::string));
for (std::string str : vecOfStr)
std::cout << str << std::endl;
}
Does not work when used in class
#include <iostream>
#include <string>
#include <vector>
class card_deck {
public:
card_deck();
std::vector<std::string> deal_hand(int num_cards);
void new_deck();
private:
std::string cards[52] =
{
"As","2s","3s","4s","5s","6s","7s","8s","9s","Ts","Js","Qs","Ks",
"Ah","2h","3h","4h","5h","6h","7h","8h","9h","Th","Jh","Qh","Kh",
"Ad","2d","3d","4d","5d","6d","7d","8d","9d","Td","Jd","Qd","Kd",
"Ac","2c","3c","4c","5c","6c","7c","8c","9c","Tc","Jc","Qc","Kc"
};
// Initialize vector with a string array
std::vector<std::string> vecOfStr(cards, cards + sizeof(cards) / sizeof(std::string));
for (std::string str : vecOfStr)
std::cout << str << std::endl;
};
int main()
{
}
Easy way:
std::vector<std::string> cards {
"As","2s","3s","4s","5s","6s","7s","8s","9s","Ts","Js","Qs","Ks",
"Ah","2h","3h","4h","5h","6h","7h","8h","9h","Th","Jh","Qh","Kh",
"Ad","2d","3d","4d","5d","6d","7d","8d","9d","Td","Jd","Qd","Kd",
"Ac","2c","3c","4c","5c","6c","7c","8c","9c","Tc","Jc","Qc","Kc"
};
and drop the separate cards_vector member. cards.size() yields the number of elements in the vector.
This uses the initialiser-list syntax of C++11.
And the compiler works out the size for you: handy if you need to add the jokers in later for example.
im new in c++ (and not to old in programming...) and i have problem with handling vectors and strucs in class.
basically i have a vector and a array of pointers to struct members in the class and i want work on the in my methos but im doing something worng/
here is my movement.h
#pragma once
using namespace std;
class movement
{
private:
static const int MAX_ROW_PER_TRACKER = 100;
static const int MIN_TO_START_CALC = 30;
static const int MAX_TRACKERS = 20;
struct tracker
{
int id;
double a[MAX_ROW_PER_TRACKER];
double b[MAX_ROW_PER_TRACKER];
double c;
};
vector<int> trackersOrder[MAX_TRACKERS] = {};
tracker* trackersArr[MAX_TRACKERS];
public:
movement();
void addRow(int a, int b, int c);
~movement();
};
and my movement.cpp
#include "stdafx.h"
#include "movement.h"
#include <iostream>
#include <algorithm>
#include <vector>
using namespace std;
movement::movement()
{
}
void movement::addRow(int id, int a, int b)
{
int index;
vector<int>::iterator searchID = find(trackersOrder.begin(), trackersOrder.end(), ID);
if (searchID == trackersOrder.end())
{
vector<int>::iterator freeLocation = find(trackersOrder.begin(), trackersOrder.end(), 0);
index = freeLocation - trackersOrder.begin();
trackersOrder.insert(trackersOrder.begin + index, id);
structArr[index] = new tracker;
structArr[index]->id = id;
structArr[index]->a[0] = a;
structArr[index]->b[0] = b;
structArr[index]->c = 0;
}
}
movement::~movement()
{
}
so when i send to method "addRow" id, and b i want to first check if i allready have this id in my vector (the vector just give me the index for the structs array) and if not then if put the id in the first empty place in the vector and on the structs array/
but from some reasin its look to me that the methid dont reconized the vector and the structs. can you help me understand why?
p.s - i can bet that i have more mistakes in my code, its my firs try with pointers and ect. (im comming from the good life in Matlab) so i will be happy to learn on them also
thank you very much!
The main problem
The problem is that in your code, trackersOrder is not a vector but an array of vectors:
vector<int> trackersOrder[MAX_TRACKERS] = {}; // array of MAXTRACKERS vectors !!
The solution
If you define it as simple vector, it should work better:
vector<int> trackersOrder;
If you want to set its size do it in the movement constructor:
movement::movement() : trackersOrder(MAX_TRACKERS)
{
}
Other issues
There is a case typo with an ID that should be id.
auto searchID = find(trackersOrder.begin(), trackersOrder.end(), id); // by the way auto is easier + ID corrected
There are a missing () after a begin whicn transforms unfortunately your iterator arithmetic into function pointer arithmetic (sic!!):
trackersOrder.insert(trackersOrder.begin() + index, id); // corrected
Finally, there are a couple of structArr that should be replaced by trackersArr.
The result does finally compile (online demo)
How would I add data to map containing an int key and a value that is a struct without first creating and defining an actual object with the struct type? Basically I have:
struct myStruct { string name2; int aCnt; std::list<string> theItems; };
// Now I define a map
std::map<string, myStruct> myMap;
// Now I want to add items to myMap.
mymap["ONE"] = {"TEN", 3, {"p1","p2","p3"}}; // But this doesn't seem to work
// I know I could do something like
myStruct myst;
myst.name2 = "TEN";
myst.aCnt = 3;
...blah blah
mymap["ONE"] = myst;
// But I don't want to have to write all of those lines especially because
// this is being done as an initialization of the map.
Thanks!
If you are using C++11, this code is already working:
#include <iostream>
#include <map>
#include <string>
#include <list>
using namespace std;
struct myStruct { string name2; int aCnt; std::list<string> theItems; };
int main()
{
// Now I define a map
std::map<string, myStruct> myMap;
// Now I want to add items to myMap.
myMap["ONE"] = {"TEN", 3, {"p1","p2","p3"}}; // But this doesn't seem to work
return 0;
}
And compile:
burgos#germany:~/test$ g++ struct.cpp -o struct -std=c++11
burgos#germany:~/test$
If you don't then you're out of luck, but all major compilers should support c++11 initialization - make sure you get the latest version.
In the ideal case, I would like to use the ClassVariant in the following way:
// store & retrieve int
map<string, ClassVariant> mapValues;
mapValues["int_fieldX"] = ClassVariant(20);
int fieldX = (mapValues["int_fieldX"])();
// Or int fieldX = (mapValues["int_fieldX"]);
However, I can ONLY implement the following code that requires the retrieving statement to feed the type info as follows:
int fieldB = (mapValuesTwo["int_fieldB"])(int(0));
As you can see int(0) is provided as type info. Is there a way that I can remove this limitation. So that the type info is NOT needed.
#include <iostream>
#include <iomanip>
#include <string>
#include <map>
#include <boost/variant.hpp>
using namespace std;
typedef boost::variant<int, double, string> VarIntDoubleString;
class ClassVariant
{
public:
ClassVariant() : m_value(int(0)) {}
ClassVariant(VarIntDoubleString _val) : m_value(_val) {}
template<typename T>
T operator()(const T&) const
{
return boost::get<T>(m_value);
}
private:
VarIntDoubleString m_value;
};
int main(void)
{
map<string, ClassVariant> mapValuesTwo;
// store & retrieve int
mapValuesTwo["int_fieldB"] = ClassVariant(20);
int fieldB = (mapValuesTwo["int_fieldB"])(int(0));
cout << "fieldB: " << fieldB << endl;
// store & retrieve string
mapValuesTwo["int_fieldD"] = ClassVariant("Hello world");
string fieldD = (mapValuesTwo["int_fieldD"])(string(""));
cout << "fieldD: " << fieldD << endl;
}
// Output
fieldB: 20
fieldD: Hello world
You can't do this, template argument deduction works only on the parameters, not on the return value of a function. Your best choice is to ditch operator() for a normal function like get<T>(). I can't point to the relevant line in the standard though, too obscure for me.
Note: if such a thing was possible, my guess would be that boost::variant would already have a get function where specifying T is not requried.
EDIT: see this question
You SHOULD use boost::variant together with visitor to access the value in it. see here