How to get size of const array in c++? [duplicate] - c++

This question already has answers here:
getting size of array from pointer c++
(6 answers)
Closed 1 year ago.
#include <iostream>
using namespace std;
const int triTable[4][6] = {
{},
{0, 8, 3},
{0, 1, 9},
{1, 8, 3, 9, 8, 1},
};
int main() {
const int *f = triTable[3];
int size = sizeof(f)/sizeof(*f);
cout << size;
}
This gives me wrong numbers. It should print 6. How can I get it?

How to get size of const array in c++?
Like this:
std::size(triTable[3])
This gives me wrong numbers.
You generally cannot get the size of an array by using a pointer to element of that array.

As stated sizeof f is the size of the pointer not the size of the object where it points to, as also said, using STL containers is a much better option given that they have size members that keep track of the size of the container.
That being said, if you're adamant in using a C style array, a solution would be to wrap it in a struct or class and return the size from there, i.e:
struct myArray
{
const int triTable[4][6] = {
{},
{0, 8, 3},
{0, 1, 9},
{1, 8, 3, 9, 8, 1},
};
const int size = std::size(triTable[3]); // size data member
int arraySize() const{
return std::size(triTable[3]); // size method
}
};
int main()
{
myArray a;
std::cout << a.size << "\n";
std::cout << a.arraySize();
}
Output:
6
6

Related

How do I append 10 arrays to form a single array in c++?

Let's say I have these 10 previously declared arrays in my code.
int arr1[] = {1,2,3,4,5,6,7,8,9,10};
int arr2[] = {1,2,3,4,5,6,7,8,9,10};
int arr3[] = {1,2,3,4,5,6,7,8,9,10};
int arr4[] = {1,2,3,4,5,6,7,8,9,10};
int arr5[] = {1,2,3,4,5,6,7,8,9,10};
int arr6[] = {1,2,3,4,5,6,7,8,9,10};
int arr7[] = {1,2,3,4,5,6,7,8,9,10};
int arr8[] = {1,2,3,4,5,6,7,8,9,10};
int arr9[] = {1,2,3,4,5,6,7,8,9,10};
int arr10[] = {1,2,3,4,5,6,7,8,9,10};
Basically, I want to append all 10 of these arrays one after another to make one single array.
ArrayOfArrays = { arr1[], arr2[], arr3[], arr4[], arr5[], arr6[], arr7[], arr8[], arr9[], arr10[] }
How would I go about doing this? This question might seem trivial for some, but I'm new to C++ and can not figure out how to do it. Please help and thanks in advance.
Basically, I want to append all 10 of these arrays one after another to make one single array.
You cannot do that.
The closest you can get to that is by using std::array.
std::array<int, 10> arr1 = {1,2,3,4,5,6,7,8,9,10};
...
std::array<int, 10> arr10 = {1,2,3,4,5,6,7,8,9,10};
std::array<std::array<int, 10>, 10> arrayOfArray = {arr1, ..., arr10};
Try this approach:
#include <iostream>
#include <vector>
int arr1[] = { 1, 2, 3, 4, 5, 6, 7, 8, 9, 10 };
int arr2[] = { 1, 2, 3, 4, 5, 6, 7, 8, 9, 10 };
// ...other arrays here...
// We pass a reference to a vector and return the same vector for performance reasons.
// Compiler often can optimize that into a better code.
std::vector<int> append(std::vector<int> & vec, int * data, int size)
{
for (int i = 0; i < size; ++i)
vec.push_back(data[i]);
return vec;
}
int main()
{
std::vector<int> data;
data = append(data, arr1, 10);
data = append(data, arr2, 10);
for (auto i : data)
std::cout << i << ", ";
std::cout << std::endl;
return 0;
}
Also, in C++ there are good containers for storing arrays, try searching for std::array and std::vector containers. First is a fixed size static array, the other one is dynamic.
I want to append all 10 of these arrays one after another to make one
single array ?
You can have array of pointers like
int *ArrayOfPointers[10] = { &arr1, &arr2, &arr3, &arr4, &arr5, &arr6, &arr7, &arr8, &arr9, &arr10};
Here ArrayOfPointers is array of 10 int pointers i.e it can store address of 10 one dimension int array like arr1, arr2 etc.
I assume there may be better method than what I'm suggesting in advance C++ for the same task.
In C++ it is unnecessary and ill-advised to use C-style arrays. For arrays of
constant size you may use std::array
and for arrays of variable size, std::vector
It looks rather as if what you actually want is a constant two-dimensional matrix
and to be able to access each of its rows as as a constant array, but do not
know how to initialise a two-dimensional matrix. If that's the case, here's how:
#include <iostream>
#include <array>
std::array<std::array<int,10>,10> matrix = {{
{{1,2,3,4,5,6,7,8,9,10}},
{{1,2,3,4,5,6,7,8,9,10}},
{{1,2,3,4,5,6,7,8,9,10}},
{{1,2,3,4,5,6,7,8,9,10}},
{{1,2,3,4,5,6,7,8,9,10}},
{{1,2,3,4,5,6,7,8,9,10}},
{{1,2,3,4,5,6,7,8,9,10}},
{{1,2,3,4,5,6,7,8,9,10}},
{{1,2,3,4,5,6,7,8,9,10}},
{{1,2,3,4,5,6,7,8,9,10}}
}};
int main()
{
std::array<int,10> const & arr0 = matrix[0];
for (int const & i : arr0) {
std::cout << i << ' ';
}
std::cout << std::endl;
// Or more simply...
auto const & arr5 = matrix[5];
for (auto const & i : arr5) {
std::cout << i << ' ';
}
std::cout << std::endl;
}
Compile, link and run:
$ g++ -Wall -Wextra main.cpp && ./a.out
1 2 3 4 5 6 7 8 9 10
1 2 3 4 5 6 7 8 9 10
live demo

set multiple array variables at the same time (c++)

I'm trying to make an ASCII art using C++, and having some problems in arrays.
Is there any way to set multiple array variables at the same time?
Let me be more specific.
When you initialize an array, you can do this way.
int arr[10] = {0, 1, 2, 3, 4, 5, 6, 7, 8, 9};
By the way shown above, you can set 10 array variables at the same time.
However, I want to (re) set some of the array variables like this?
a[1] = 3;
a[4] = 2;
a[5] = 2;
a[7] = 2;
Since there is NO rule in the variables, I can't do
for(int i=0; i<10; i++) a[i] = i+1;
fill(n);
I can't use an for statement or the fill, fill_n function, since there is no regularity.
To sum up,
Is there any way to set more than 1 array variables at the same time? (Like the second code snipplet above?
Given a index-value mapping list, and assign it one by one.
template<typename T, size_t N>
void Update(T(&arr)[N], const std::vector<std::pair<size_t, T>>& mappings)
{
for (const auto& mapping : mappings)
if(mapping.first < N)
arr[mapping.first] = arr[mapping.second];
}
int main()
{
int arr[10] = { 0, 1, 2, 3, 4, 5, 6, 7, 8, 9 };
Update(arr, { {1, 3}, {4, 2}, {5, 2}, {7, 2} });
return 0;
}
As far as I'm aware without a pattern a control structure is kind of redundant, you might be better served reading from a file.
// for user input
int arr[10] = { 0,1,2,3,4,5,6,7,8,9 };
for (int i = 0; i < 10; i++) {
cout << "Please input your value for array index " << i << endl;
cin >> arr[i];
}
// for manual input in initalization
int arr[10] = { 0, 3, 2, 2, 2, 5, 6, 7, 8, 9 };
However a better approach might be to read it from a file, http://www.cplusplus.com/forum/general/58945/ Read "TheMassiveChipmunk"'s post there for exactly how to do it.
Assuming you know which indices you will be changing upfront you can use a separate index array:
int ind[4]= {1,4,5,7};
..and an accompanying array with values
int new_val[4] = {3,2,2,2};
The you can use the following for loop to assign the values:
for (int i=0; i<4; i++)
arr[ind[i]] = new_val[i];
You should also use some variable signifying the number of indices to be changed like int val_num = 4 instead of plain number 4.
Changes that are defined in runtime to an array can be easily implemented by using a list to save tuples that represent the changes you want to make. As an example, we can write:
#include <tuple>
#include <list>
#include <iostream>
using namespace std;
typedef tuple <int, int> Change;
int main() {
int a[5] = {1,2,3,4,5};
list<Change> changes;
//represents changing the 2-th entry to 8.
Change change(2,8);
changes.push_back(change);
for(auto current_change: changes)
a[get<0>(current_change)] = get<1>(current_change);
cout << a[2] << '\n';
}
Prints 8.

Passing Multidimenionall Arrays through C++ functiones [duplicate]

This question already has answers here:
Passing a 2D array to a C++ function
(18 answers)
Closed 6 years ago.
#include <iostream>
using namespace std;
int ROWS = 3;
int COLS = 4;
How do I solve this c++ multidimensionalArray problem? I have been working on this for some time but I just cant figiure it out, thank you verry much
void fillScores(int [ROWS][COLS]);
int main() {
int scores[ROWS][COLS] = {{1, 2, 3, 4}, {5, 6, 7, 8}, {9, 10, 11, 12}};
fillScores(scores);
return 0;
}
void fillScores(int newScores[ROWS][COLS]) {
cout << newScores[1][1]<<endl;
}
You can wrap the array in a struct and then pass it by address, where you need.
struct ArrayWrapper
{
int _arr[ROWS][COLS];
};

How does sizeof work when passing a template array? [duplicate]

This question already has answers here:
Can someone explain this template code that gives me the size of an array? [duplicate]
(4 answers)
Closed 7 years ago.
Since sizeof and templates are both compile-time. What is it about the second parameter of the template that determines the size without specifying it in the caller function?
template <typename T, size_t n> bool isInHaystack(const T (&arr)[n], const T &needle)
{ /* I know const references are best with strings and non-primitives and should
be mitigated when using ints as in the example.*/
size_t i, size = sizeof arr / sizeof T; // how does it know n is the size?
for (i = 0; i < size; ++i)
if (arr[i] == needle)
return true;
return false;
}
int main(int argc, char **argv) {
int arr[] = { 1, 3, 5, 7, 9, 11, 13, 15, 17, 19, 21 };
cout << isInHaystack(arr, 7) << endl;
isInHaystack<int, (size_t)(sizeof(arr) / sizeof(int))>(arr, 7); // this works, too
return 0;
}
How does this size_t n get its value when passing an array? How does it know without providing it explicitly?
To make this a little more clear, this will not compile:
template <typename T> bool foo(const T(&arr)[], const T needle) {
cout << sizeof arr << endl;
return true;
}
int main(){
int arr[] = {1,2,3};
foo(arr, 1); // Error: could not deduce template argument for 'const T (&)[]' from 'int [21]'
}
What is the issue?
If you are asking "how does the compiler know to put the array size into n"... The expression
const T (&arr)[n]
is being passed
int arr[11]
hence it is able to deduce T is int and n is 11.
If you are asking how it knows how large arr is...
int arr[] = { 1, 3, 5, 7, 9, 11, 13, 15, 17, 19, 21 };
cout << isInHaystack(arr, 7) << endl;
arr is an array. The compiler knows how big it is. If you are thinking "arr is really just a pointer", that's not true. Arrays and pointers are said to have equivalence (see K&R section 5.3), which doesn't mean they are same, but that they result in the same behavior in a limited number of contexts.
In C and C++ arrays are able to decay into pointers, but they are still not pointers until the decay occurs.
int arr[] = { 1, 3, 5, 7 };
int* arrp = arr; // decay
cout << isInHaystack(arr, 7); // Error.
See http://c-faq.com/aryptr/aryptrequiv.html

How to return 2 dimension array in C++

I have a segmentationfault at the line :
cout << b[0][0];
Could someone tell me what should I do to fix my code?
#include <iostream>
using namespace std;
int** gettab(int tab[][2]){
return (int**)tab;
}
int main() {
int a[4][2] = {{0, 0}, {1, 0}, {2, 0}, {2, 1}};
int ** b = gettab(a);
cout << b[0][0];
return 0;
}
A 2-dimensional array is not the same thing as an array of pointers, which is how int** is interpreted. Change the return type of gettab.
int* gettab(int tab[][2]){
return &tab[0][0];
}
int main() {
int a[4][2] = {{0, 0}, {1, 0}, {2, 0}, {2, 1}};
int* b = gettab(a);
cout << b[0]; // b[row_index * num_cols + col_index]
cout << b[1 * 2 + 0]; // the 1 from {1, 0}
}
Or:
int (*gettab(int tab[][2]))[2] {
return tab;
}
// or:
template<class T> struct identity { typedef T type; };
identity<int(*)[2]>::type gettab(int tab[][2]) {
return tab;
}
int main() {
int a[4][2] = {{0, 0}, {1, 0}, {2, 0}, {2, 1}};
int (*b)[2] = gettab(a);
cout << b[0][0];
}
Being c++, rather than c, there are much better ways of handling arrays of all sorts, and passing them around.
The type of tab without square brackets is not actually int **. It is actually int (*)[2]. When you apply two [] operators to the resulting pointer, you end up dereferencing the first value in your array, 0, as a NULL pointer. Try this instead:
#include <iostream>
using namespace std;
typedef int (*foo)[2];
foo gettab(int tab[][2]){
return tab;
}
int main() {
int a[4][2] = {{0, 0}, {1, 0}, {2, 0}, {2, 1}};
foo b = gettab(a);
cout << b[0][0];
return 0;
}
Your seg fault us because you pass in an "int*" effectively. A 2D array is not a double pointer ...
You are best off using a pointer that is "x*y" in size and addressing it without the 2 dimensions ... the code will end up the same anyway as the compiler will just generate the same code you would have to write more explicitly anyway :)
a 2 diminsional array isn't the same thing as an array of pointers. a 2 dimensional array is just a pointer to a hunk of memory that you have told the compiler to let you access as a 2 dimensional array
int* gettab(int tab[][2]) {
return (int*)tab;
}
int main() {
int a[4][2] = {{0, 0}, {1, 0}, {2, 0}, {2, 1}};
int* b = gettab(a);
cout << b[0 + 2*0];
return 0;
}
will do what you want. But I wonder if you really need to be trying to return a 2 dimensional array from a function in the first place. Perhaps a less made-up example if what you are trying to do would be helpful?
edit: fixed missing *2 in the calculation [0 + (sizeof(int)*2)*0].
edit again: well that was dumb. the multiplication of the column size of 2 by the size of an int is automatic in this case. sizeof(int) removed.