I have two multidimensional arrays
uint8_t arr1 [24][8];
uint8_t arr2 [24][8];
I am writing a function to print out the contents of these arrays, and I wish to specify to the function which of the arrays I want printed. I tried the following:
void print_array(int n) {
uint8_t arr[24][8];
if (n == 1) {
arr = arr1;
}
else if (n == 2) {
arr = arr2;
}
// ... code to print "arr" contents ...
}
Basically, I want to be able to copy the reference to the multidimensional array to avoid having duplicated code to print the array contents. The above gives me an 'invalid array assignment' error. What do I need to do to copy the array reference successfully?
When an array is used as a value (I'm talking of C arrays) then its name represents the address of the first element. This means that either you need to copy the memory by hand somehow (memcpy) or that you need to use that pointer somehow.
For the second choice (recommended since there's no copy involved) this will work:
#include <iostream>
using namespace std;
uint8_t arr1 [24][8];
uint8_t arr2 [24][8];
void print_array(int n) {
uint8_t (*arr)[24][8];
if (n == 1) {
arr = &arr1;
}
else if (n == 2) {
arr = &arr2;
}
for(int i=0; i<24; i++){
for(int j=0; j<8; j++)
printf("\n %d ", (int)(*arr)[i][j]);
}
}
int main() {
arr1[0][1] = 3;
arr1[1][5] = 6;
print_array(1);
return 0;
}
Try it live: http://ideone.com/CvMQfB
Also notice that if you're using C++11, then you might get away with std::array and have exactly what you had in mind with the same syntax
std::array<int,4> A = {10,20,30,40};
std::array<int,4> B = A; //copy array A into array B
You could create pointer to array:
void print_array(int n) {
uint8_t (*arr)[24][8];
if (n == 1) {
arr = &arr1;
}
else if (n == 2) {
arr = &arr2;
}
// ... code to print "arr" contents ...
}
I would do something like :
void print_array(const uint8_t (&arr)[24][8]) {
for (std::size_t i = 0; i != 24; ++i) {
for (std::size_t j = 0; j != 8; ++j) {
std::cout << arr[i][j] << " ";
}
std::cout << std::endl;
}
}
then call it print_array(arr1); or print_array(n == 1 ? arr1 : arr2);.
Related
I have a problem with function that takes: array, size of that array and function (or lambda), and then sort given array depending of what function given in argument returns. For example:
int a1[] = {1,2,3,4,5,6};
part(a1,6,isEven); // where isEven is simple function for checking if element is even
Should return:
[ 2 4 6 1 5 3 ]
I already write this like that, where im retur new, sorted array:
template <typename T, typename FUN>
size_t part(T* arr, size_t size, FUN f) {
T new_arr[size] = {};
int first = 0;
int last = size - 1;
int index = 0;
bool changed = false;
for(int i = 0; i < size; i++){
if(f(arr[i])){
new_arr[first] = arr[i];
first++;
} else {
if(!changed){index = i;}
new_arr[last] = arr[i];
last--;
}
}
for(int j = 0; j < size; j++){
std::cout << new_arr[j] << " ";
}
return new_arr;
}
But I have to do this without using any other array. And it has to be done in one loop.
You were nearly there.
You must not use an additional array. But in line T new_arr[size] = {}; you try to do this. And, this will not work, because this is a VLA (Variable Lenth Array). VLAs are not part of the C++ language. Some compilers accept VLAs as extension, but, if you tell them to compile C++, then also those will reject it. In C++ the size of an array must be known at compile time. It must be a constant.
So, since you anyway work with pointers, you can also use new to allocate temporary memory. Then simply replace the above line with T* new_arr = new T[size]{};
And, you must not forget to delete the allocated memory. Or, you could copy the new data at the end of the function to the original and then delete the temporaray memory there.
So, in my opinion not the best approach. Anyway, the C++ standard library has the functions partition and stable_partition.
Anyway. Please see below:
#include <iostream>
#include <algorithm>
template <typename T, typename FUN>
T* part(T* arr, size_t size, FUN f) {
T* new_arr = new T[size]{};
int first = 0;
int last = size - 1;
int index = 0;
bool changed = false;
for (int i = 0; i < size; i++) {
if (f(arr[i])) {
new_arr[first] = arr[i];
first++;
}
else {
if (!changed) { index = i; }
new_arr[last] = arr[i];
last--;
}
}
return new_arr;
}
int main() {
int data[]{ 1,2,3,4,5,6 };
int *p = part(data, (sizeof(data) / sizeof(data[0])), [](const int i) {return i % 2 == 0; });
for (int i = 0; i < (sizeof(data) / sizeof(data[0])); ++i)
std::cout << p[i] << ' ';
delete[]p;
}
Write a function, equalsArray that when passed two int arrays of the same length that is greater than 0 will return true if every number in the first array is equal to the number at the same index in the second array. If the length of the arrays is less than 1 the function must return false. For example, comparing the two arrays, {1,2,3,4,5} and {1,2,3,4,5} would return true but the two arrays {3,7} and {3,6} would return false.
You should start by copying the function-1-1.cpp file and name it function-3-1.cpp. Then add the function equalsArray to the new file.
The main function for this problem must call your readNumbers function twice, then pass both new arrays to your equalsArray function, display the result as true or false and finally delete the array. The main function in the file main-3-1.cpp.
The signature for your new function is:
bool equalsArray(int *numbers1,int *numbers2,int length) ;
This is my code, and i try to use the int* readNumber two times.
#include <iostream>
using namespace std;
int* readNumbers()
{
int* a = new int[10];
for (int i = 1; i < 11; i++) {
int x;
cin >> x;
a[i] = x;
}
a++;
return a;
// delete[] a;
}
bool equalsArray(int* numbers1, int* numbers2, int length)
{
if (length >= 1) {
for (int i = 0; i < length; i++) {
if (numbers1[i] == numbers2[i]) {
}
else {
return false;
}
}
return true;
}
// delete[] numbers1;
// delete[] numbers2;
int main()
{
int* arr1 = readNumbers();
int* arr2 = readNumbers();
equalsArray(arr1, arr2, 10);
return 0;
}
There there is an error,control reaches end of non-void function.
How to improve my code?
Thank you all.
Expect result:
1
2
3
4
5
6
7
8
9
10
1
2
3
4
5
6
7
8
9
10
True(1)
OK, first I will show you your code, with comments where the errors are.
Then I will show you a fixed version. And, at the end, a little bit more robust C++ soultion.
I know that you learn in school all this nasty stuff with pointers, decayed pointers for arrays, C-style arrays,pointers for owned memory, new and delete.
That is basically bad. It should never be used in C++.
Anyway. Teachers still think like that. What a pity . . .
OK. You code with comments:
#include <iostream>
using namespace std; // Should not be used
int* readNumbers()
{
int* a = new int[10]; // Do not use C-style arrays, pointer for owned memory, new and delete
for (int i = 1; i < 11; i++) { // Will lead to out of bound error
int x; // Why using additional variables?
cin >> x;
a[i] = x;
}
a++; // Wrong
return a;
// delete[] a; // Not here
}
bool equalsArray(int* numbers1, int* numbers2, int length)
{
if (length >= 1) {
for (int i = 0; i < length; i++) {
if (numbers1[i] == numbers2[i]) {
}
else {
return false;
}
}
return true;
}
// Here nothing will be returned
} // Closing bracket misding
// delete[] numbers1; // Not here
// delete[] numbers2; // Not here
int main()
{
int* arr1 = readNumbers();
int* arr2 = readNumbers();
equalsArray(arr1, arr2, 10);
return 0; // No output
} // No Release of memory
Next, your fixed code
#include <iostream>
using namespace std;
// Function to read a given numbers of values and returns them in a dynaimcally allocated array
int* readArrayOfNumbers(int numberOfValuesToRead) {
// Allocate a new array for the given amount of integers
int* dynamicArrayOfIntegers = new int[numberOfValuesToRead];
// Read all values in a loop from user via std::cin
for (int index = 0; index < numberOfValuesToRead; ++index) {
cin >> dynamicArrayOfIntegers[index];
}
return dynamicArrayOfIntegers;
}
// Compare 2 arrays with same size
bool equalsArray(int* numbers1, int* numbers2, int length) {
// We assume in the beginning that the arrays will be equal
bool result = true;
// We will only compare arrays, if they contain data
if (length >= 1) {
// Now compare arrays element by element
for (int i = 0; i < length; i++) {
if (numbers1[i] != numbers2[i]) {
// If not equal then set result to false and stop loop
result = false;
break;
}
}
}
else {
// No data in array. Consider as not equal
result = false;
}
return result;
}
int main()
{
// Define size of arrays
const int sizeOfArray = 10;
// Get 2 arrays in dynamically allocated arrays
int* array1 = readArrayOfNumbers(sizeOfArray);
int* array2 = readArrayOfNumbers(sizeOfArray);
// Compare both arrays
const bool arraysAreEqual = equalsArray(array1, array2, sizeOfArray);
// Show result
if (arraysAreEqual)
std::cout << "\nTrue(1)\n";
else
std::cout << "\nFalse(0)\n";
// Release memory
delete[] array1;
delete[] array2;
}
And finally, the C++ solution
#include <iostream>
#include <iomanip>
#include <array>
constexpr size_t NumberOfElements = 10u;
using MyType = int;
using MyArray = std::array<MyType, NumberOfElements>;
int main() {
// Define arrays
MyArray myArray1{};
MyArray myArray2{};
// Read values
for (size_t i{}; (i < NumberOfElements) and (std::cin >> myArray1[i]); ++i)
;
for (size_t i{}; (i < NumberOfElements) and (std::cin >> myArray2[i]); ++i)
;
// If all numbers could be read . . .
if (std::cin) {
// Show result of comparison
std::cout << '\n' << std::boolalpha << (myArray1 == myArray2) << '(' << (myArray1 == myArray2) * 1 << ")\n";
}
else std::cerr << "\n*** Error. Invalid input data\n";
}
This question already has answers here:
Length of array in function argument
(9 answers)
Find the Size of integer array received as an argument to a function in c [duplicate]
(4 answers)
How to find the size of an array (from a pointer pointing to the first element array)?
(17 answers)
Closed 1 year ago.
I'm trying to pass an array as a pointer to a function, but when I do that the function only sees the pointer as an array with 1 variable.
Here is my code:
void make3(int* a) {
int n = sizeof(a) / sizeof(a[0]);
for (int i = 0; i < n; i++) {a[i] = 3;}
}
int main()
{
int a[3] = { 0, 1, 2 };
make3(a);
int* b = a;
for (int i = 0; i < sizeof(a)/sizeof(a[0]); i++) {
cout << *(b + i) << endl;
}
}
The function make3 only changes the first value of the array to 3, instead of all of them.
Is this normal?
If not, what am I doing wrong?
When you pass an array to a function, it decays to a pointer.
int n = sizeof(a) / sizeof(a[0]);
Gets evaluated to
int n = sizeof(int*) / sizeof(int);
Which is 1 (when sizeof(int*) is 4 - depends on inplementation).
You should pass the array size as an argument instead:
void make3(int* a, int n) {
for (int i = 0; i < n; i++) {a[i] = 3;}
}
int main()
{
int a[3] = { 0, 1, 2 };
make3(a, 3);
for (int i = 0; i < 3; i++) {
cout << a[i] << endl;
}
}
If you can’t add that argument, use std::vector:
#include <vector>
void make3(std::vector<int> &a) {
for (int i = 0; i < a.size(); i++) {a[i] = 3;}
}
int main()
{
std::vector<int> a{ 0, 1, 2 };
make3(a);
for (int i = 0; i < a.size(); i++) {
cout << a[i] << endl;
}
}
Is this normal?
Yes.
In C++, an array will decay to a pointer at any opportunity. C++ inherited this convenience behavior from C.
It makes thinking about arrays as-if they were the same as pointers. But they are not.
In C++ a pointer can point to nothing (nullptr), or point to an object, or point to an array of objects. The pointer is oblivious of whether it points to an object or an array of objects.
(Or be dangling, or be uninitialized, or be some arbitrary value. These should be avoided.)
If not, what am I doing wrong?
You are not using std::vector.
Since, in the comments, you say that you cannot use a std::vector, then you'll need to pass in the length of the array as a std::size_t parameter along with a pointer to the array.
But you also say you cannot pass in the length of the array. So then you will need to use an array reference rather than a pointer.
Also, C++17 has std::size(a) which can be used instead of sizeof(a)/sizeof(a[0]).
#include <cstddef>
#include <iostream>
using std::cout;
using std::size_t;
template <size_t N>
void make3(int(&a)[N]) {
for (size_t i = 0; i < N; ++i) {
a[i] = 3;
}
}
int main() {
int a[3] = { 0, 1, 2 };
make3(a);
int* b = a;
for (size_t i = 0; i < sizeof(a)/sizeof(a[0]); ++i) {
cout << *(b + i) << "\n";
}
}
This question already has answers here:
Can a local variable's memory be accessed outside its scope?
(20 answers)
Closed 8 years ago.
I'm at college and we're learning pointers. Our job was to input a char, compare it to an array and return a pointer to the first reference of that char in the array. But, as I don't like easy things, I've asked my teacher what about having that char more than once in the array.
That's where my headache begins.
So I have this code. The idea is: create a function that compares the input char to the entire array, get the pointers of the references and save them in an array and return that array.
Unfortunately it's not working as I wish :(
What can be wrong?
#include<iostream>
#include<cstdlib>
using namespace std;
char list [10];
int main()
{
initialize();
show();
cout<<search('1');
}
void initialize()
{
int i;
for(i=0; i<10;i++)
{
list[i]='1';
}
}
void show()
{
int i;
for(i=0; i<10;i++)
{
cout<<list[i];
}
}
int* search(char* input)
{
int* result[10];
int i;
char *temp;
for (i=0; i<10; i++)
{
*temp=list[i];
if(strcmp(temp, input) != NULL)
{
result[i]=i;
}
}
return result[];
}
I'm on a mobile device so I can't go into huge detail unfortunately, but you are returning a pointer to an array that you create in the function which goes out of scope at the end of the function.
My massive edit:
As everyone has already stated, a C++ array is actually only a pointer to the first element in the array. As a result, if you return a pointer to an array created in the scope of the function, you are returning a pointer to garbage. If I were doing this I would use a vector, but if I were to be forced into using an array, I would use something like the code below. Hope this helps!
#include <iostream>
#include <cstdlib>
void initialize(char* list) {
for(int i = 0; i < 10; ++i) {
if(i < 4) {
list[i] = '2';
} else {
list[i] = '1';
}
}
}
void show(char *list) {
for(int i = 0; i < 10; ++i) {
std::cout << list[i] << ' ';
}
std::cout << std::endl;
}
// Note the function requires an additional argument that is a pointer
// this is how you can avoid returning a pointer
int search(char input, char* list, char* result) {
int j = 0;
for(int i = 0; i < 10; ++i) {
// comparing characters can be done via ==
if(input == list[i]) {
*(result + j) = list[i];
// You could use result[j], but I used this to show that
// result really is just a pointer to the first element
// of the array. As a result saying result[j] is the same
// as saying I want to deference j elements past the first
// element or *(result + j)
++j; // increment j
}
}
// return how many elements matched
return(j);
}
int main(int argc, char *argv[]) {
char list[10];
char temp[10];
initialize(list);
show(list);
int size = search('1', list, temp);
// create a dynamically sized array containing space for each match
// because we don't know the size at compile time we must use
// a library type or a dynamically sized array
char *result = new char[size];
for(int i = 0; i < size; ++i) {
result[i] = temp[i];
// again you could use result[i]
std::cout << *(result + i) << std::endl;
}
delete[] result; // otherwise you'll get a memory leak
return(0);
}
If i had an array of lets say 15 elements is there anyway for me to make it into a 2d array having it 5x3?
Or if i had a string with 15 letters would it be possible to make it into a 2d array having it 5x3?
This is what i have(using variables but using 5 as a and 3 as b in console)
void finishMap(string map, int a, int b)
{
string finalMap[a][b];
for(int i = 0; b>i; i++)
{
for(int x = 0; a>x; x++)
{
finalMap[a][b] += {{map[x]}, {i}};
}
}
}
Also pretty new to c++ so if you see anything i shouldn't be please tell me :3
I'm using char arrays (c strings) in my answer because I think they are useful to illustrate how arrays work - and thre really isn't a point in using std::string in your case. std::string hides a lot of the underlying nuts and bolts so I would generally recommend to play around with C strings first to understand how std::string works. Also, check out this tutorial: http://www.cplusplus.com/doc/tutorial/arrays/
A 2-dimensional array has the same memory layout as a 1-d array. In terms of memory layout, char[3][5] is the same as char[3*5] is the same as char[15]. You can use a 1-d array as a 2-d array using char[column+row*width]. The only difference if you use subscripts is that the compiler remembers how many dimensions there are and will do the whole column+row*width calculation for you.
Take this example:
char temp[5] = "abcd"; //need 5 for string termination char `\0`
for(int i = 0; i < 4; ++i) {
std::cout << temp[i];
}
std::cout << "\n\n";
for(int i = 0; i < 2; ++i) {
for(int j = 0; j < 2; ++j) {
std::cout << temp[j+2*i];
}
std::cout << std::endl;
}
Will print:
abcd
ab
cd
You can always access an array in strides. Here's a possible example using templates to restride a 1D array as a 2D array:
template <typename T, unsigned int N1, unsigned int N2>
struct strider
{
using array_type = T[N1 * N2];
array_type & data_;
Strider(array_type & data) : data_(data) {}
T & operator()(std::size_t i1, std::size_t i2)
{
return data_[i1 * N2 + i2];
}
};
template <unsigned int N1, unsigned int N2, T>
strider<T, N1, N2> stride(T (&a)[N1, N2]) { return {a}; }
Usage:
int a[15] = {};
strider<int, 3, 5> s(a);
s(1, 2) = 20;
assert(a[7] == 20);
stride<5, 3>(a)(4, 2) = 10;
assert(a[14] == 10);
I've overloaded operator() for the strided access, since unlike operator[] it can have arbirary signatures.
With some more work you could make the rank of the strided view variadic.
Okey so i used something a bit different then what i mentioned. What i did was have the user enter 3 lines of 5 length letters, which i figured out how to add into the 2d array. If your having the same issue as me, heres my code:
int main()
{
string path;
int a, b;
cin >> a >> b;
string finalMap[a][b];
for(int i = 0; b>i; i++){
cin >> path;
for(int x = 0; a>x; x++){
finalMap[x][i] = (path[x]);
}
}
for(int x = 0; b>x; x++)
{
for(int y = 0; a>y; y++)
{
cout << finalMap[y][x];
}
cout << endl;
}
return 0;
}
Thanks for trying tho, really appreciate it ^.-
You can try to use reinterpret_cast. Complete example:
#include <iostream>
using namespace std;
typedef char mtrx[5][3];
int main(){
char data[15] = "Some String";
mtrx &m = *reinterpret_cast<mtrx*>(&data);
m[1][2] = '*';
cout << data << endl;
return 0;
}