I have this struct:
struct noduri {
int nod[100];
};
and this function:
int clearMatrix(int var)
{
cout << all[1].nod[30];
}
int main()
{
noduri all[100];
cout << all[1].nod[30];
return 0;
}
and I want the struct to be assigned to all 100 elements of array all[], when I do cout << all[1].nod[30]; everything works fine, no errors, it outputs 0. When I call clearMatrix(1) I get this error : error: request for member nod in all[1], which is of non-class type int, what am I doing wrong ?!
The array variable all is local to the main function, so you cannot reference it in clearMatrix unless you pass a pointer to it into the function:
int clearMatrix(int var, noduri *all)
{
cout<<all[1].nod[30];
}
int main()
{
noduri all[100];
clearMatrix(5, all);
return 0;
}
you are reffering in the function that array which is not in its scope, you need to do it as
int clearMatrix(int var,noduri *all)
{
cout<<all[1].nod[30]; // as here you have the base address of the array of type noduri you can refer it.
}
int main()
{
noduri all[100];
clearMatrix(5, all);
return 0;
}
You are using raw arrays. That's not a good idea. Use std::vector if the size if not known at compile time, consider std::array if it is known at compile time and dynamic resizing would cause measurable performance problems.
One of the problems with raw arrays in C++ is that it's not at all(!) as easy to pass them to a function like, say, an int or a double. std::vector and std::array, in contrast, are as easy to pass to a function like any other normal type.
Here's a complete example:
#include <array>
#include <iostream>
struct noduri {
std::array<int, 100> nod;
};
void clearMatrix(std::array<noduri, 100> const &array) {
std::cout << array[1].nod[30];
}
int main() {
std::array<noduri, 100> all;
std::cout << all[1].nod[30];
}
Note that std::array is only available if your compiler supports C++11. For an older compiler, use boost::array or just do it with a std::vector.
The code you showed will not be compiled and has no any sense. If I have understood correctly you want to assign each element of the array by some value in function clearMatrix. If so then the code will look the following way
#include <iostream>
struct noduri
{
int nod[100];
};
int clearMatrix( noduri *matrix, int size, int var )
{
for ( int i = 0; i < size; i++ )
{
for ( int &n : matrix[i].nod ) n = var;
}
}
int main()
{
const int N = 100;
noduri all[N] = {};
std::cout << all[1].nod[30] << std::endl;
clearMatrix( all, N, 10 );
std::cout << all[1].nod[30] << std::endl;
return 0;
}
Related
I can't able to understand , so please help me .
Whrn we are passing the array to any function and then we write the array type in function parameter to fetch it but why we are not initialize its size in the parameter .
Of course you could specify (fixed) size of array as function parameter - you have to pass array by reference.
void func(int (&x)[100]);
is passing array of int with size 100.
You could even make a template for it
template<class T, size_t N> void func(T (&x)[N]) {...}
In C++, always prefer containers to raw pointers or arrays when possible.
Array types in function signatures are actually pointers. The following three declarations are all exactly the same:
void foo(int a[10]);
void foo(int a[]);
void foo(int* a);
In all three cases, foo takes a single parameter: a pointer to an int. When you pass an array to that function, it implicitly decays to a pointer to its first element.
When an array decays into a pointer, the length of the array is lost. That means the following code will compile, but is logically wrong:
void foo(int a[10]) {
for (size_t i = 0; i < 10; ++i) {
std::cout << a[i] << '\n';
}
}
int main() {
// Whoops, wrong size array!
int arr[5] = {};
foo(arr);
}
Live Demo
The length declaration, in this case, is a complete and total lie. Writing a meaningless number in the function definition just increases the risk someone will make an error.
If you must use raw pointers for a function parameter accepting an array, your function should also accept a size parameter:
void foo(int* a, size_t length) {
for (size_t i = 0; i < length; ++i) {
std::cout << a[i] << '\n';
}
}
int main() {
int arr[5] = {};
foo(arr, 5);
}
Live Demo
This is also dangerous though, since it's entirely possible for someone to pass the wrong size and cause errors:
void foo(int* a, size_t length) {
for (size_t i = 0; i < length; ++i) {
std::cout << a[i] << '\n';
}
}
int main() {
int arr[5] = {};
//Whoops, passed the wrong size!
foo(arr, 10);
}
Live Demo
For that reason, you should prefer to use a container:
void foo(const std::vector<int>& a) {
for (int i : a) {
std::cout << i << '\n';
}
}
int main() {
std::vector<int> arr(5);
foo(arr);
}
Live Demo
If you don't know what type of container to use; default to std::vector. If your function must support multiple types of containers, use a template:
template <typename Container>
void foo(const Container& a) {
for (int i : a) {
std::cout << i << '\n';
}
}
int main() {
std::vector<int> arr(5);
foo(arr);
std::array<int, 5> arr2 = {};
foo(arr2);
}
Live Demo
I really want to do the following:
(sorry about syntax, I have no idea how this is done)
struct Data {
int var = 5;
} data;
struct Data2 {
var;
} data2;
data2.var = data;
cout << data2.var.var; //prints 5
Basically I want to have a dynamic struct variable in a struct that can be given any struct as value and access it through the mains struct.
Please be nice. I really don't know how to explain it better and I really want to do this and been reading a lot yet haven't found any methods to do this.
Ps.
I DON'T want to do the following:
struct Data {
int var = 0;
} data;
struct Data2 {
data;
} data2;
I want it to be dynamic, that is, that I can change it any time during the program. Thank you.
Conceptually, you may (?) be asking about references:
#include <iostream>
int main() {
int x = 10;
int & xref = x;
std::cout << xref << "\n";
x = 20;
std::cout << xref << "\n";
}
That will print:
10
20
Underlying a reference is essentially a pointer, but it is one which can never be null...and notationally you don't have to "dereference" it. Were you using pointers, the above would look like:
#include <iostream>
int main() {
int x = 10;
int * xptr = &x;
std::cout << *xptr << "\n";
x = 20;
std::cout << *xptr << "\n";
}
Here they are applied to your example with minimal changes:
#include <iostream>
struct Data {
int var;
};
struct Data2 {
Data & var;
};
int main()
{
Data data = {5};
Data2 data2 {data};
std::cout << data2.var.var << "\n";
data.var = 10;
std::cout << data2.var.var << "\n";
return 0;
}
Odds are "this isn't what you actually want" (you shouldn't usually be exposing member variables, much less member variables that are references to other variables). And they shouldn't be all named var. Etc.
Still, references are an integral part of the language and worth learning about.
(Note: for brevity, you may omit the return 0;...only from main. That's assumed, and legal in the standard; and you may omit its arguments. But you must return an int.)
You can use void pointer like this:
#include <iostream>
using namespace std;
struct Data
{
int var;
}data;
struct Data2
{
void *var;
}data2;
int main()
{
data.var = 5;
data2.var = &data;
cout<<((Data *)data2.var)->var<<endl;
return 0;
}
But it is not safe because somtimes you can't make sure that other struct has member called var which may cause unexpected result.
Basically I want to have a dynamic struct variable in a struct that
can be given any struct as value and access it through the mains
struct.
You can emulate the effect of dynamic typing by using polymorphism. The following is a test example for your case.
#include <iostream>
using namespace std;
struct BaseDataStruct
{
virtual int get_data() = 0;
};
struct Data : BaseDataStruct
{
int var = 5;
virtual int get_data() { return var;}
} data;
struct Data2 {
BaseDataStruct* var;
} data2;
int main()
{
data2.var = &data;
cout<<data2.var->get_data();
return 0;
}
By using BaseDataStruct as an interface base class for all the structs which Data2::var is expected to point to you can achieve the "dynamic typing" behavior you are trying to get.
Note: I changed the Data2::var a to pointer to avoid object slicing. You will need to jump through many hoops to avoid that if you want to have it by value.
TL/DR: C++ is statically typed, so what you want to do is against the spirit of thr language. However, if you really have to you can use void* in C and boost::any in C++
Now a bit more about void* (to know more about boost::any refer to its documentation).
void* is a pointer that holds a raw address in memory. This value beyond this address could be everything: float, int or your struct. Here is the usage example.
struct Data {
int var = 5;
};
struct Data2 {
void* var;
};
int main() {
Data data;
Data2 data2;
data2.var = (void*)(&data);
cout << ((struct Data*)data2.var)->var << endl;
}
If the concept of pointers is new for you you can read about it here. Void pointers are explained there as well.
I have an array of pointers declared as a class member like this:
class Bar
{
private:
static constexpr int SIZE = 10;
Foo* m[SIZE];
}
In one of my class methods, I would like to return a pointer (or preferably, a reference) to this array. The array has a known size at compile time, but I am keeping track of how many items I have put in there (it is a buffer of stuff).
What is the best way to return a reference to this array in C++11 ?
Here are the things I have tried:
GetArray(Foo* &f[], unsigned &size) const
I like the syntax because it makes it clear that the reference value is an array of pointers, but this gives a compiler error: Declared as array of references of type Foo*
GetArray(Foo** &f, unsigned &size) const
{
f = m;
size = mSize;
}
Gives me: Error: assigning to Foo **' from incompatible type Foo *const[10]. Casting mFoo to (Foo**) alleviates the error, but IMHO, this is not elegant.
Nobody posted an answer using std::array yet, it is a very simple replacement:
class Bar
{
std::array<Foo *, 10> m;
public:
std::array<Foo *, 10> & getArray() { return m; }
std::array<Foo *, 10> const & getArray() const { return m; }
};
This seems to me a lot simpler than the hoops you have to jump through to use your C-style array version.
To avoid code duplication you could typedef std::array<Foo *, 10> FooArray; .
The technique of having both a const and a non-const implementation is a common pattern for accessor functions which return a reference or a pointer. (It's not required if your accessor returns by value, of course).
I would seek to use a std::array or a std::vector in most cases. If you are determined to use a raw array then you could go this way with it:
typedef int Foo;
typedef Foo* (&FooPtrArrayRef)[10]; // to make the syntax less hairy
class Bar
{
private:
Foo* m[10];
public:
// First way without using typedef
Foo* (&getArray())[10]
{
return m;
}
// Nicer looking way with a typedef
FooPtrArrayRef getArrayByRef()
{
return m;
}
};
int main()
{
Bar b;
Foo* (&array)[10] = b.getArray();
std::cout << (sizeof(array) / sizeof(Foo*)) << '\n';
// Alternative using "size deduction"
Foo* (&array2)[sizeof(b.getArray()) / sizeof(Foo*)] = b.getArray();
std::cout << (sizeof(array2) / sizeof(Foo*)) << '\n';
// MUCH nicer using the typedef
FooPtrArrayRef array3 = b.getArrayByRef();
std::cout << (sizeof(array3) / sizeof(Foo*)) << '\n';
}
The syntax is pretty obscure though.
The benefits of this is approach is that it retains the full type information of the array you are passing by reference. The obscure syntax is necessary to avoid the type collapsing to a Foo**. By retaining the full type of the array you retain the ability to know its size at compile time using the sizeof() operator.
here's another approach that returns the array reference and the current size as a tuple:
#include <tuple>
#include <functional>
#include <algorithm>
#include <iterator>
#include <iostream>
struct Foo {};
using FooBuffer = Foo*[10];
class Bar
{
public:
Bar()
: _m { nullptr }
{
_m[0] = new Foo;
_m[1] = new Foo;
_items = 2;
}
~Bar() {
for(auto fp : _m)
delete fp;
}
std::tuple<FooBuffer&, size_t> getInfo() {
return std::make_tuple(std::ref(_m), _items);
}
private:
Foo* _m[10];
size_t _items;
};
int main() {
Bar b;
auto info = b.getInfo();
FooBuffer& buf = std::get<0>(info);
size_t items = std::get<1>(info);
for(Foo** p = buf ; p != buf + items ; ++p) {
std::cout << "Foo at " << std::hex << *p << std::endl;
}
return 0;
}
I have 3 arrays, A[5][3][5], B[5][4][5], C[5][2][5].
Is it possible to access them by an array of pointers, with their second dimension being different? Something like:
int A[5][3][5], B[5][4][5], C[5][2][5];
int ***D[3];
D[0] = A;
D[1] = B;
D[2] = C;
I know this is wrong, I just want to know if it's possible to access them by one array?
No, if the second dimension is different it won't work. The best you can do is something like this:
struct arr {
int *p; // pointer to first element
int x, y, z; // array size
int &at(int i, int j, int k) {
return p[((i*y)+j)*z+k];
}
}
Or you can use your favorite multidimensional array library. C++ lacks built-in support for multidimensional arrays unless all but the first size is known at compile time, and C99 VLAs won't work in this situation. This is because C/C++ use the type of the array to figure out how big it is in each dimension (except the first dimension, which can be unspecified).
It's definitely not possible to do what you want directly due to the type system's restrictions, but you may want to consider something like the following (in C++11 syntax):
#include <vector>
#include <array>
#include <iostream>
template <typename T, size_t x, size_t z>
struct Ragged : std::array<std::vector<std::array<T, z>>, x> {
Ragged(size_t y) {
for (auto &i : *this) {
i.resize(y);
}
}
};
int main() {
using R5y5 = Ragged<int, 5, 5>;
R5y5 a(3), b(4), c(2);
vector<R5y5> d{a, b, c};
d[1][1][2][3] = 99; // checked at() calls supported for all dimensions, too
for (auto const &d : D) {
for (auto const &x : d) {
std::cout << "[";
for (auto const &y : x) {
std::cout << "[";
for (auto const &z : y) {
std::cout << z << " ";
}
std::cout << "]";
}
std::cout << "]" << std::endl;
}
std::cout << std::endl;
}
}
This gets you multidimensional operator[] access to d and its elements, and allows you to put whatever y-dimensioned array inside d you want to. Note that the 3-dimensional pseudo-arrays are no longer stored completely compactly, but in potentially growable 2-D slices.
#include <stdio.h>
int main(){
int A[5][3][5], B[5][4][5], C[5][2][5];
void *D[3];
D[0]=&A;
D[1]=&B;
D[2]=&C;
B[1][2][3] = 99;
printf("%d\n", (*(int(*)[5][4][5])D[1])[1][2][3]);//99
return 0;
}
The code:
int i;
struct st
{
int m;
}st_t[2];
void foo()
{
i = 4;
st_t[2] =
{
{10},{20}
}; // it's wrong !!!! but I don't know how to do.
}
int main()
{
foo();
cout<<i<<endl; // will output 4;
cout<<st_t[0].m<<endl; // this should output 10
cout<<st_t[1].m<<endl; // this should output 20
return 0;
}
Is it possible to define a struct array in a function? If it is, then how to do this?
Thanks in advance.
PS:
Sorry my English is not good. I am making a Tetris game, it have a Shape class, I declared a shape struct array in Shape.h, then I assign to the struct array in Shape constructor function in Shape.cpp. Is it right? or how to assign to the struct array so I can use it in another function?
You can initialize an array in the place where it's defined. I.e. either move the definition into the function, or move the initialization out of the function:
struct st
{
int m;
}
st_t[2] = {{10},{20}};
Instead of the direct assignment of values, you can initialize a temporary variable and copy this variable to your global variable:
Delete:
...
st_t[2] = {
{10},{20}
};
...
and add:
...
st tmp[2] = { {10}, {20} };
memcpy(st_t, tmp, sizeof st_t);
...
Addendum:
If it doesn't work for you, there might be another error in your code. From your example:
#include <iostream>
#include <memory.h>
using namespace std;
int i;
struct st { int m; } st_t[2];
void foo()
{
i = 4;
st tmp[2] = { {10}, {20} };
memcpy(st_t, tmp, sizeof st_t); // use: const_addr instead of &const_addr
}
int main()
{
foo();
cout << i << endl; // will output 4;
cout << st_t[0].m << endl; // this should output 10
cout << st_t[1].m << endl; // this should output 20
return 0;
}
all works fine as expected.
If you want to define an array in the function (as your question title and text implies), then add the type specifier st to the definition:
st st_t[2] =
{
{10},{20}
};
However, this will be a separate array to the global one, and so the output from main() won't match what your comments say should happen. If you actually want to assign to the global array, then:
st_t[0].m = 10;
st_t[1].m = 20;
or, in C++11, you can use similar syntax to your example if you replace the plain array with std::array:
std::array<st, 2> st_t;
void foo() {
// Note the extra braces - std::array is an aggregate containing an array
st_t =
{{
{10},{20}
}};
}
If you only want the variable at function scope then
void foo() {
struct {
int m;
} st_t = { {10}, {20} };
// do something
}