Reputation: 175
I'm relatively new to programming, and am currently learning C++. I'm doubtful if my logic in this is even correct, but here's something I've been trying to work out:
I have a simple program that outputs the size and content of a vector;
vector<int> v1;
vector<int> v2(10);
vector<int> v3(10, 42);
vector<int> v4{ 10 };
vector<int> v5{ 10, 42 };
vector<string> v6{ 10 };
vector<string> v7{ 10, "hi" };
//and so on...........
bool firstPass= true;
for (auto i : v3){
if (firstPass) cout << "Vector size: " << v3.size() << ".\nElements: " << i << ", ";
cout << i << ", ";
firstPass= false;
}
If i want to iterate through another vector, i have to manually change the v3 to vX, but what i'd like is for this snippet of code to go through all the vectors.
I've tried several methods, such as creating a
vector<string> V8{"v1","v2","v3"..}
for (auto i : V8[counter])
but essentially I've failed because "v1" != v1.(This is where i got the "convert string to vector" idea from, but something tells me this isn't the way to go about doing this...)
Any help & criticism would be greatly appreciated, and i apologize as this will probably get filed under too specific or even useless, considering my way of trying to solve this is probably faulty and i asked the wrong question!
Upvotes: 2
Views: 1051
Reputation: 2059
If you're simply convering a string
into a vector<int>
then this example may give you an idea how to do it in general.
#include <iostream>
#include <string>
#include <vector>
using namespace std;
int main()
{
string str = "1234567890";
vector<int> intedStr;
for (size_t i = 0; i < str.length(); i++)
{
intedStr.push_back((int)str[i] - '0');
}
for (size_t i = 0; i < intedStr.size(); i++)
{
cout << intedStr[i] << " ";
}
system("pause");
}
Note: this is not a safe function. What happens if you want to covert "abcsd"
to vector<int>
?
Upvotes: 0
Reputation: 179819
You'll need C++11, but it's definitely possible:
template<typename V>
void PrintVector(V const& v) {
for (auto elem : v) std::cout << elem << " ";
std::cout << std::endl;
}
template <typename V, typename ... Vectors>
void PrintAll(V const& v1, Vectors... vtail)
{
PrintVector(v);
PrintAll(vtail...);
}
PrintAll(v1, v2, v3, v4, v5, v6, v7, v8, v9);
Upvotes: 1
Reputation: 70402
To solve your literal problem of looking up a variable by a string representing the variable's name: The only facility that POSIX supplies to look up a global variable by name is dlsym()
. It only works for globals, and you have to declare your functions with extern "C"
to suppress C++ name mangling (global variable names don't get mangled).
#include <vector>
#include <assert.h>
#include <dlfcn.h>
std::vector<int> v1;
int main () {
void *h = dlopen(0, RTLD_NOW);
void *v = dlsym(h, "v1");
assert(v == &v1);
}
To get the sample above to work, you need to compile with g++ -rdynamic prog.cpp -ldl
.
The limitation of this technique is that you need to know the type of the pointer that is returned a priori, and cast it accordingly.
If you are willing to "pass" your arrays to a function to print out each array for you, you can implement a variadic template function to do this.
template <typename Vector>
void print_all_vectors (Vector v) {
/* enforce we are only interested in vectors */
const std::vector<typename Vector::value_type> &vr = v;
std::cout << "Vector size: " << vr.size() << ".";
if (!vr.empty()) std::cout << "\nElements";
bool first = true;
for (auto i : vr) {
std::cout << (first ? ": " : ", ") << i;
first = false;
}
std::cout << '\n';
}
template <typename Vector, typename... Vectors>
void print_all_vectors (Vector v, Vectors... vectors) {
print_all_vectors(v);
print_all_vectors(vectors...);
}
The first template in the code above prints out a vector. The second template function recursively unpacks the variadic parameter list and passes each to the first template function.
Using the functions is easy, illustrated below:
std::vector<int> v1{1, 3, 5, 7};
std::vector<std::string> v2{"doh", "ray", "me"};
print_all_vectors(v1, v2);
Upvotes: 1
Reputation: 106096
(This is more a comment than an answer, but am listing a bit of code too long for a comment...)
If you don't want to clean up the code to only have a vector<vector<int>>
+ vector<vector<string>>
, vector<vector<boost::variant<int,string>>>
, or similar, then you could create e.g. vector<vector<int>*>
and vv.push_back(&v1); vv.push_back(&v2);
et al to avoid the expense of copying.
There's no way to easy iterate over variables called v1
, v2
, v3
etc. (the preprocessor can do it but it's complicated - see the boost preprocessor library if you want to pursue that).
It might be easiest to settle for a more concise convenience function to do the push_backs... something like:
vector<vector<int>>& operator<<(vector<vector<int>>& vv, vector<int>& v)
{
vv.push_back(v);
return vv;
}
Then you can code...
vv << v1 << v2 << v3 << v4 << v5;
Ideally, you'd put the operator in an anonymous namespace so only your code sees it, avoiding accidental usage or potential conflicts in other code.
Upvotes: 0
Reputation: 1
You need something to iterate on if you need something that is resolved in runtime, you could use a vector of vectors but they should be of the same type (vector of strings mixed with int is not be possible since they are different types due to the template instantation ) On the other hand you can use the preprocessor and macro expansion for static stuff or templates
Upvotes: 0