Can't initialise an array - c++

Okay, I'm pretty new when it comes to C++ (having moved over from VB) and I can't seem to work out how to populate an array without doing:
array[0] = 1
array[1] = 2
etc etc
So as could be expected, I have tried this:
float posVector[3]; //Declared outside of int main() as needs to be global
posVector = {0.0f,0.0f,0.0f}; //Inside int main()
Which is causing this error to be displayed:
extended initializer lists only available with -std=c++0x or -std=gnu++0x [enabled by default]
Nothing I have been able to locate online so far has been of any help. So any advice you can give me on fixing this will be appreciated!

Once the array is declared it cannot be initialized using the initializer list. You can go with
float posVector[] = {0.0f,0.0f,0.0f};
or even better go with std::vector:
#include <vector>
std::vector<float> posVector = {0.0f,0.0f,0.0f};

It can be done like this:
float f[] = {1.0, 2.0, 3.0, 4.0, 5.0};

Shortest way i think: float posVector[] { 0.0f,0.0f,0.0f };

As far as I understand, the question is not about INITIALIZING the array, but about assigning the array after it was already created. The answer is 'no way'. Arrays can not be assigned after they are initialized. However, arrays of fixed sizes some time might be more adequately presented as structs, and this is exactly the case! Coordinates are much better presented as structs!
Not commenting on the neccessity of global variable (most likely, not needed) here is the way to make it work:
struct Coordinate {
float x;
float y;
float z;
};
Coordinate coord;
void foo() {
coord = {1, 2, 3};
}

Related

C++ trying to create a queue of 2d points (arrays)

I am trying to create a queue of 2d points, like this:
queue<int[2]> q;
this compiles, however, after doing:
q.push({0,0});
I get an compile error, saying that my call to push is ambiguous. Not sure how to fix this. Please help.
I'm not sure if this is a good way to represent 2d points on a plane, but it seems to me to be the most lightweight.
You can use Pair to represent your points.
queue<pair<int,int>>q;
q.push({0,0});
You can create a structure for the 2D points:
struct Point2D {
int x;
int y;
};
And you can create a std::vector instead of std::queue.
std::vector<Point2D> q {{ {1, 2}, {9, 3}, ... }};
And you can normally:
q.push_back({0, 0});
EDIT:
You can also create a vector of int[2] instead of Point2D and do the same thing.
You can always create a struct to hold your point coordinates. It's actually a good idea to have a representation for such entity regardless of your current problem.
The answer below is a more general one regarding arrays in c++, and does not require a custom struct:
In c++ it's usually recomended to use std::array instead of such small fixed size c style arrays (and std::vector for dynamic size ones).
Code example:
#include <queue>
#include <array>
int main() {
std::queue<std::array<int,2>> q;
q.push({ 0,0 });
return 0;
}
A side note: better to avoid using namespace std - see here Why is "using namespace std;" considered bad practice?.
Array are just pointers. Raw C arrays cannot be stored in container.
Solution 1: Use type of stored element as int*
std::queue<int*> q1;
int s1[2]{0,0};
q1.push(s1);
Solution 2: Use other container like std::array or std::vector
std::queue<std::array<int,2>> q;
q.push({0,0});

How to initialize a vector in a struct in c++

I am having a problem with vectors in c++. I am new to c++ so keep this in mind please.
So I have the following struct in the begining of my program:
typedef struct grupo
{
float transX, transY, transZ, rotX, rotY, rotZ, rotAngle, scaleX, scaleY, scaleZ;
char **modelos;
struct grupo** grupos;
int nNomes = 0, nGrupos=0;
std::vector<float> vertices;
};
struct grupo *grupo;
And I just start the main like this:
grupo = (struct grupo*)malloc(sizeof(struct grupo));
grupo->modelos = (char **)malloc(sizeof(1));
grupo->grupos = (struct grupo **)malloc(sizeof(struct grupo));
And in the middle of main I am tryting to use this:
grupo->vertices.push_back(x);
But it keeps crashing the program. I am using visual studio, and using debugging mode. I can see that is when pushing X to the vector that crashes (x has a value). I've tried to change the vector to an array of floats. So the problem i can imagine is with the initialization of the vector... Can you help with what am I missing?
Thank you :)
You're using C++, you don't need the "new" or malloc keyword unless for specific reasons. You don't need the typedef for structs.
I'm not sure what your char** is supposed to be, but you can use std::string for strings.
Maybe what you're trying to do is this:
struct Grupo
{
float transX, transY, transZ, rotX, rotY, rotZ, rotAngle, scaleX, scaleY, scaleZ;
std::string modelos;
int nNomes = 0, nGrupos=0;
std::vector<float> vertices;
};
In main:
Grupo grupo;
grupo.vertices.push_back( ... );
Then I would advise you to read a bit more about what is exactly the C++ language and how it's not C.
Since you're using C++; if you want to create a grupo dynamically, you should use the new operator, with the constructor:
grupo = new grupo();
malloc does not properly initialize C++ objects such as std::vector.
P.S. I am not sure what the grupo->modelos and grupo->grupos are supposed to be, but I'd use proper C++ types for them (perhaps modelos should be std::string, etc). Additionally, I suspect that you've got one * too much for both modelos and grupos.
C++ does not need the typedef in the declaration.
To properly initialize a structure, you should write a ctor to replace the compiler provided ctor (which generally does nothing).
Something like the following (with just a few attributes):
struct grupo
{
float transX, transY;
// ...
int nNomes;
int nGrupos;
std::vector<float> vertices;
// I prefer initialization list form
grupo() : transX(0.0),
transY(1.0),
// ...
nNomes(0),
nGrupos(0)
// vertices default ctor is ok, creates empty vector
{
// use vertices.push_back(...); to fill vertices
}
};
grupo grupo;
Next you will want to write a more useful ctor, one with parameters to use (instead of the literal constants), such that you could build multiple grupo.
grupo grupo1(1.0, 2.0, 3, 4);
grupo grupo2(3.0, 4.0, 5, 6);
// etc.

C++ - How do I put a static array inside my array?

I apologize for the total noob question, but I just cannot find an answer. I googled, searched here, searched C++ array documentation, and some C++ array tutorials.
The question is simple. Why does
#include "stdafx.h"
int _tmain(int argc, _TCHAR* argv[])
{
short pixelarray[3][3] = {{1,1,1},{0,0,0},{-1,-1,-1}};
... //do stuff. Imagine a loop here, and BIG array - I'm just simplifying it for StackOverflow
pixelarray = {{1,0,-1},{1,0,-1},{1,0,-1}};
return 0;
}
result in an error?
1>arraytest.cpp(11): error C2059: syntax error : '{'
How do I put a static array inside my array? I realize I could set each item individually, but there has to be a better way.
Built-in arrays in C++ have their problems, and not being assignable does make them rather inflexible. I'd stick with std::array, a C++11 container that emulates a better style of array, which allows a somewhat similar syntax to what you're looking for:
std::array<int, 3> arr{{1, 2, 3}};
std::array<int, 3>{{4, 5, 6}}.swap(arr);
//now arr is {4, 5, 6}
Here's a full sample. The trick is to use the initializer list on a newly-constructed array and then swap that with yours. I believe that the next C++ update is going to remove the need for the double braces as well, which makes it an even closer match to familiar syntax.
Initializer lists can be used just for initialization :)
Like when you declare your variable:
short pixelarray[3][3] = {{1,1,1},{0,0,0},{-1,-1,-1}}; // this is ok
You have to remove this:
pixelarray = {{1,0,-1},{1,0,-1},{1,0,-1}};
And assign new values manually (i.e. pixelarray[x][y] = or with a memcpy(pixelarray, <some other array>, sizeof(pixelarray)))
If you don't want to assign each individual element manually, you can do this:
short pixelarray2[3][3] = {{1,0,-1},{1,0,-1},{1,0,-1}};
memcpy(pixelarray, pixelarray2, sizeof(pixelarray));
As #Nick points out: initializer lists are not for assignment.
Arrays are not assignable, so the short answer is that you can't do exactly what you're asking for. The most direct way to do something similar enough for most purposes is probably a 2D array class that acts as a wrapper around a std::vector, on the order of the one I posted in a previous answer.
If you insist on staying with C-style arrays, one possibility would be to use a pointer:
int main() {
typedef short array[3];
array pixelarray0[3] = {{1,1,1},{0,0,0},{-1,-1,-1}};
array pixelarray1[3] = {{1,0,-1},{1,0,-1},{1,0,-1}};
array *pixelarray = pixelarray0;
// when needed:
pixelarray = pixelarray1;
}
Taking this question from a straight C context, you can have different constant arrays and just copy them with memcpy:
typedef short TArray[3][3];
const TArray a1 = {{1,1,1},{0,0,0},{-1,-1,-1}};
const TArray a2 = {{1,0,-1},{1,0,-1},{1,0,-1}};
// ...
TArray a;
memcpy( a, a2, sizeof(TArray));
Or you could exploit C99 struct copying, but I'd consider this a dangerous hack because the structure might be padded to be larger than the array, or have a different alignment.
typedef struct {
TArray arr;
} TDummyArray;
// ...
TArray a;
*(TDummyArray*)a = *(TDummyArray*)a2;
Once you have declared your array there is no way to use the assignment operator to reassign the entire content of the array.
So to change the contents or your array after this:
short pixelarray[3][3] = {{1,1,1},{0,0,0},{-1,-1,-1}};
You need to either loop through the array and manually change each value, or you something like std::memcpy to copy your new values over.
But you should really not be using an array in the first place, use some fromthing the std collections library instead like std::array or std::vector. Only use arrays if you have a really really good reason why you can't use a collection.

Cleanest way to copy a constant size array in c++11

I often find myself wanting to copy the contents of arrays that have a constant size, I usually just write something along the lines of:
float a[4] = {0,1,2,3};
float b[4];
for(int i=0; i<4; i++){
b[i]=a[i];
}
As of lately, I am writing a linear calculus library for educational purposes, and I was wondering if there was a better way to do it.
The first thing that came to my mind, was using memcpy:
memcpy(b, a, sizeof(float) * 4);
But this seems very c-like and error prone to me. I like having my errors at compile time, and this can get ugly for data types with non-trivial copy constructors, or if I forget to multiply with sizeof(datatype).
Since I am writing a math library that I am going to use intensively, performance is very important to me. Are the compilers today smart enough to understand that the first example is just copying a chunk of memory and optimize it to be as efficient as the second solution?
Perhaps there is a function in the standard library that can help me? Something new in c++11? Or should I just create a macro or a template function?
If you use std::array instead of a built-in array (which you should), it becomes very simple. Copying an array is then the same as copying any other object.
std::array<float,4> a = {0,1,2,3};
std::array<float,4> b = a;
The C++03 way
Use std::copy():
float a[4] = {0,1,2,3};
float b[4];
std::copy(a,a + 4, b);
That's about as clean as it gets.
The C++11 way
std::copy(std::begin(a), std::end(a), std::begin(b));
If you can use std::array
With std::array you just do simple assignment:
std::array<float,4> a = {0,1,2,3};
auto b = a;
For interested in C++03 (and also C) solution - always use struct containing an array instead of solely array:
struct s { float arr[5]; };
Structs are copyable by default.
Its equivalent in C++11 is,already mentioned, std::array<float,5>;
Below method works for usual arrays as well std:array.
float a[4] = {0,1,2,3};
float b[4];
std::copy(std::begin(a), std::end(a), b);
#include <algorithm>
std::copy_n(a, 4, b)

C hard coding an array of typedef struct

This is such a dumb question it's frustrating even asking it. Please, bear with me, I'm feeling particularly dumb over this one today....
I've got a library with a certain typedef struct. basically:
typedef struct {int x; int y;} coords;
What I really wanted to do was declare in my header a variable array of this:
coords MyCoords[];
(I recently switched it to just coords *MyCoords; and then ran a MyCoords = new coords[4];)
and then in my init I wanted to hardcode some values in it.
MyCoords[] = {{0, 0}, {2, 2} etc.
I must just be brainfarting today because it's not letting me do any manner of simply putting in even something simple like MyCoords[0] = {0, 0}
sorry about some of the syntax above. Thanks for any help. I don't even care about hard-coding all the values at once. I'm now fine with just geting MyCoords[0] = {0, 0} working. I could do MyCoords[0].x = 0; MyCoords[0].y = 0 but then I'd never figure out what I'm doing wrong. Thanks a lot anyone..
You can only initialize an array at the same spot you declare it. The form that will work is:
coords MyCoords[] = {{0, 0}, {2, 2}};
If you need to declare MyCoords in a header so that many modules can access it, I think the following will work:
extern coords MyCoords[];
Well, what you created is not a variable array. It's an array whose size is not known. That array has an incomplete type, and can thus not be defined in C++. What you can do is to make it just a declaration by putting extern before it.
extern coords MyCoords[];
Then, in the .cpp file that initializes it, you can then create (define) that array - beware you should do it at namespace scope, outside any function, of course:
coords MyCoords[] = {{1, 2}, {3, 4}, ... };
If what you want is an array whose size is not known at compile time yet, but rather at runtime, you should use a std::vector:
std::vector< coords > MyCoords;
Then later if you fill it, do
MyCoords.push_back( coords(1, 2) );
MyCoords.push_back( coords(3, 4) );
....
Or create a local array and then initialize the vector using a copy of the elements of that array:
coords c[] = ....;
MyCoords.insert(MyCoords.end(), c, c + sizeof c / sizeof *c);
Well, in C, it is slightly different than in C++. You can define an array whose dimension isn't known. What happens is that it's taken to be a "tentative" definition. If at the end of the file (more precisely, of its translation unit, which is that file, and all the files it includes - meaning everything the compiler translates together) there is not a subsequent definition of it that includes the size, then the size is taken to be 1. However, in C++ there are no tentative definitions, and a definition that does not include the size and does not contain an initializer that can tell the size is an invalid C++ program.
For the reason why your code goes grazy, you are doing
MyCoords[0] = {0, 0}
Which the compiler will read as:
-> Set LHS to RHS
-> -> LHS is a variable of type `coords`. Fine
-> -> RHS is... hmm, `{0, 0}`. What the heck is it??
You see, the compiler has no clue what the right hand side is supposed to mean. C99, for that reason (1999 version of C) introduced so-called compound literals. It allows you to write
MyCoords[0] = (coords){0, 0};
And it will actually do what you want it to do - creating a right hand side value of type coord and assigns it to the left hand side. But you should just, already from a compatibility reason (many C compilers are not reasonable C99 compliant - and neither C++ nor C89 supports compound literals), use one of the previous ways i showed you.
I'm not sure whether this is also a problem in your actual code, but:
typedef struct coords {int x, int y};
is not a complete typedef declaration in C, as it does not give a name to the type, only to the struct (struct tags are not in the same namespace as type names in standard C). To make the typedef declaration correct, you have to specify a name for the whole type struct coords {int x, int y}, as if you were declaring a variable of that type, like so:
typedef struct coords {int x, int y} coords;
It should be:
typedef struct coords {int x, int y} coords;
coords MyCoords[] = {{0, 0}, {2, 2}, {3, 4}};