I have a structure that more or less follows this pattern:
struct sTruct {
int count;
struct {
int A;
int B;
int C;
} array[]; //count is the size of this array
};
I would like to be able to initialize these with something like the following syntax:
sTruct gInit1 = { 2, { {1,2,3},{4,5,6} }};
Really, that initialization syntax (or rather, the compactness of it) is more important than the specific struct layout. I do not have access to the standard containers (embedded platform), but I might be able to replicate some of their behavior if needed.
In final form, I would like to initialize an array of roughly 300 of these sTruct containers at once, just to add one more level of parenthesis.
You can't do it. If you gave the array a size you could. An alternative might be:
template < int size >
struct sTruct
{
struct { int a, int b, int c } array[size];
};
sTruct<2> gInit1 = {{1,2,3},{4,5,6}};
But, of course, all your sTructs are different types and so it may not be what you want. Your only other alternative is going to have to be free-store based and won't give you that syntax until initialization lists in 0x.
Related
I want to make an Array with 3 differnt definitions. More specifically i want an array like this : A[i,j]=(string, int, bool
string, int, bool)
I am trying to make a template but i am confused.
If you want to use templates you can make an array of structs:
template <class A, class B, class C>
struct Vars{
A a;
B b;
C c;
};
//declaring the types of the template you want to use
Vars <std::string, int, bool> *ray;
//initializing array in heap
ray = new Vars<std::string, int, bool>[SIZE];
Alternatively, If you have decided you always want to use this combination you can much more easily do this:
struct Vars{
std::string a;
int b;
bool c;
};
Vars *ray = new Vars[SIZE];
You can make a regular class that implements this behavior.
Something like this:
class specialArray {
char *** strings;
int **integers;
bool **booleans;
public:
specialArray(int rows, int columns, unsigned char data[]) {
//initialize arrays to correct sizes
/*add a special values, such as 253, 254, 255 (which are not
used for chars, bools, or strings (since the operating system
takes control of memory locations 253, 254, 255)) every time the
type of the array changes*/
/*Use the special values to determine which array each byte of
information should go to (and use casts). Arrays which are not
filled at each index should be set to 0 at that position*/
/*create a function access(int loc) to obtain a value. In this
function, check each of the three arrays until one of the arrays
at that index value is not 0. Return a byte array.*/
/*Implementing this in c++ is extremely inefficient, by the
way as you can see by the enormous amount of code this
requires*/
}
//do something similar for operator=()
}
If I understand you correctly, arrays -AFAIK- can have only one datatype. However you can use struct/classes pair two different types then make a one dimensional array out of it.
Check this code illustration, and check if it is what you are looking for.
template<typename T, typename U>
struct MyArray
{
T a;
U b;
};
int main()
{
MyArray<int,bool> arr[2];
arr[0] = {30,1};
cout << arr[0].a;
cout << " : ";
cout << arr[0].b;
}
You may also use pair, tuples and/or vectors... etc. It all depends on your vision and needs.
I am being asked to make the types of the loop control variables known via a typedef statement. The problem I am having is that I don't know how, or even if it is possible, to make a typedef to a reference to an array of 4 elements.
/*
Write a program to print the elements of ia. It should
use a range for to manage the iteration.
*/
int main()
{
int ia[3][4] = {
{4,3,2,1},
{1,2,3,4},
{3,1,4,2}
};
for (int (&p)[4] : ia) // This is the line I am talking about
for(int z : p)
cout << z;
return 0;
}
I am still very new to programming, and I cannot seem to find an answer to this question. Any advice/help regarding the usage of typedef you can offer would be appreciated.
If you are using at least C++11, which is implied by the range-for statement, you can turn to "using" instead of "typedef". It serves the same uses and more, and it has a less confusing syntax:
// Equivalent declarations
typedef int (&arrayRef)[4];
using arrayRef = int (&)[4];
// Usage
for (arrayRef p : ia) { ... }
Furthermore, with using you can template the declaration itself:
template<typename T, size_t n>
using arrayRef = T (&)[n];
for (arrayRef<int,4> p : ia) { ... }
You write a typedef the same way as you write a variable declaration, except that you replace the variable name with the name you want to give to the type, and you stick typedef in front, hence:
typedef int (&R)[4];
will declare R to be the type "reference to an array of 4 ints".
In my platformer game which I'm writing in Visual C++, each level will initially be stored as a 2-dimensional array of ints. I decided it would make more sense to store this array in a class, so I created a class called Level. It looks like this:
class Level {
private:
int map[20][30];
public:
Level(int a[20][30]) {
map = a;
}
int getcell(int row, int column) {
return map[row][column];
}
};
As far as I can see - from looking up tutorials on class constructors, and passing 2-dimensional arrays as parameters, this should work, so I really don't understand why it doesn't.
On the line where I do map = a, I get an error: Error: expression must be a modifiable lvalue. I've looked this error up on stackoverflow, but I can't find any answers which relate to my problem.
So, how can I fix this error?
This doesn't really have anything to do with a constructor. You cannot assign arrays in C++. Whether in the constructor, or anywhere else.
There are two ways to work around it. The first way is the brute force way. Instead of
map = a;
write a loop to copy the contents of the array from the constructor's parameter into the class member array.
The second way is to stuff the array into an intermediate class:
class Level {
public:
struct level_map {
int map[20][30];
};
private:
level_map map;
public:
Level(const level_map &initial_map) : map(initial_map)
{
}
int getcell(int row, int column) {
return level_map.map[row][column];
}
};
This may or may not be practical, and introduces a little bit more complexity.
But the real answer here is to use std::vectors instead of plain arrays, which will solve all of these problems.
Others have already mentioned the real reason: you cannot assign an array to another using = operator. My two cents about your class:
map is not a good name, it may get conflict with std::map if using namespace std; or using std::map was specified somewhere.
The constant array sizes make this class non-reusable. Class should be flexible to allow any N*M sized 2D array. For this, better to use vector<vector<int>>.
getcell should be a const method, and it should do error checking with row and column numbers passed.
If you want this class to have static-sized array sizes and compile time, you may use class templates with row and column sizes as non type template arguments.
template<size_t row, size_t column>
class Level
{
int _map[row][column];
public:
Level(int src[row][column])
{
memcpy(_map, src, sizeof(_map)); // why not simply 'memcpy' ?
}
};
int main()
{
int source[10][2] = { {1, 2}, {3,4} };
Level<10, 2> ten_by_2(source);
}
Here the map is a constant value, which could not been assigned as an lvalue. This could be fixed by iterating the element of the array, and assign a[i][j] to map[i][j].
class Level {
private:
int map[20][30];
public:
Level(int a[20][30]) {
for(int i = 0; i < 20; ++i)
for(int j = 0; j < 30; ++j)
map[i][j] = a[i][j];
}
int getcell(int row, int column) {
return map[row][column];
}
};
As programming becomes more complex, and the need to perform operations on struct data becomes visible. Is there a conversion method for converting a struct type into an array of its members such that:
struct FooDesc Foo{
int num_Foo;
int num_Bar;
int GreenFoo;
};
can be represented by:
int Bar[2];
Or better, dynamically as:
vector<int> Bar;
The goal is to convert or re-represent the data struct as an iteratable form, without the excessive use of the assignment operator.
You could use unnamed structs to make a hybrid struct where its member could be treated as an array:
struct Foo {
union {
struct {
int x;
int y;
int z;
};
struct {
int array[3];
};
};
};
LIVE DEMO
Note however, that unnamed struct comes from C11 and its not a standard C++ feature. It is supported as an extension though by GCC as well Clang.
If your structs are POD then you might consider using std::tuple instead of structs. You could then use various template facilities to work through the members of the tuple.
Here is a simple example that prints the elements of a tuple - using boost::fusion::tuple instead of the std::tuple since it has many more tuple-manipulating facilities available:
#include <boost/fusion/tuple.hpp>
#include <boost/fusion/include/for_each.hpp>
#include <iostream>
struct Printer {
template<typename T>
void operator()(const T &t) const {
std::cout << t << std::endl;
}
};
int main(int argc, const char * argv[])
{
boost::fusion::tuple<int, int, int, int, float> t =
boost::fusion::make_tuple(3, 5, 1, 9, 7.6f);
boost::fusion::for_each(t, Printer());
return 0;
}
You could include these in unions with the struct but you'd want to do some testing to ensure proper alignment agreement.
The upside is that these manipulations are very fast - most of the work is done at compile time. The down-side is that you can't use normal control structs like indexing with runtime indices - you'd have to build an abstraction layer around that as the normal get<i>(tuple) accessor requires that i be a compile time constant. Whether this is worth the complexity depends strongly on the application.
How about:
vector <Foo> Bar;
You can then add instances of your struct and then access each element as desired, using an array-like format.
See this related question for further information:
Vector of structs initialization
Upon re-reading your question a few times, I think I mis-understood your intent and answered the "wrong question". You can make an array of your struct as mentioned above and index it as an array, but I don't believe it is quite as simple as that to make each struct element a different element of an array. If you are looking to make an array of structs, my answer should help. If you are looking to make each element of your struct an element of your array, 40two's answer should help you out.
I am busy with a dynamic 2d array and I have declared it as follows:
string** MakeArray(int row,int col)
{
string** array;
array = new string* [col];
for(int r = 0; r < row; r++)
{
array[r] = new string [col];
}
return array;
}
Now I can place string values in the array. How can I place Integer values in the first column and strings in second and integers in third, if my array is 4 by 99?
The elements in an array are all the same type. To get what you're after, you probably want to start off rather differently, with an array of structs:
struct whatever {
int a;
std::string b;
int c;
};
std::vector<whatever> your_array;
Edit: although it's almost certainly a lousy idea, if you really need this to be a 2D array, you could try making all your elements the same type of union:
union whatever {
int a;
std::string b;
};
This has some pretty severe limitations though -- in fact, putting a std::string in a union isn't officially supported at all. There's a fairly decent chance it'll work, but no guarantee of it at all. If you really, really need to do something like this, you can make that member of the union a pointer instead. That is guaranteed to work, but also guaranteed to be so clumsy that making mistakes with it is nearly inevitable.
Don't do that. Instead create a struct that will represent single record in a table, and contain a string and two integers. Then create one dimensional array of those structures.
struct record
{
int a;
std::string b;
int c;
};
record* MakeArray(int row)
{
return new record[row];
}
better yet, ditch arrays and use std::vector:
std::vector<record> array(99);
Have you looked at having a vector/array of tuples, if you have C++11 available to you? So you could do something such as:
#include <tuple>
#include <vector>
typedef std::tuple<int, std::string, int> MyTuple;
std::vector<MyTuple> MakeVector()
{
std::vector<MyTuple> vecTuples;
for( int i = 0; i < 5; ++i )
{
vecTuples.emplace_back( std::make_tuple<int, std::string, int>( i, "Test"+i, i+5 ) );
}
return vecTuples;
}
C++ is a "strong-typed" language. One of the things that means is you cannot mix data types (unless they are related, like base-derived class hierarchical relationship).
In other words what you are doing is not what C++ directly supports.
Having said that there's something you can do that would do what you want - have an array of triplets, like this:
struct triplet
{
int first;
string second;
int third;
};
triplet** MakeArray(...
What you are doing in your example looks alot like a JS code though. Maybe what you want is to store all your data as strings? Then yes, you can use a 2D array of strings, but that requires you to convert datum into string when storing it and converting back from string for calculations. Which is a major performance issue