1

I created a code.I want to use the same varible in 2 functions, but I don't want the funtion to change the value to the other function. To make my self more clear here is an example:

int num1(int arr[5][6],int count);
int num2(int arr[5][6],int count2);
   int main()
   {
       int count = 0;
    int count2 = 0;
    int arr[5][6] = {
   {0, 0, 0, 1, 0, 0} ,   
   {0, 0, 0, 0, 0, 0} ,   
   {0, 0, 0, 0, 0, 0} ,
   {0, 0, 0, 0, 0, 0} ,
   {0, 0, 0, 0, 0, 0}
    };
    cout << num1(arr,count);
    cout << num2(arr,count2);
    return 0;
    }
int num1(int arr[5][6],int count){
    for (int i = 0; i < 5; i++) {
        for (int j = 0; j < 6; j++) {
            if(arr[i][j] == 1){
            count++;
            arr[i][j] = 0;
            }
        }
    }
    return count;
}
int num2(int arr[5][6],int count2){
    for (int i = 0; i < 5; i++) {
        for (int j = 0; j < 6; j++) {
            if(arr[i][j] == 1){
             count2++;
            arr[i][j] = 0;
            }

        }
    }
    return count2;
}

This code will print 1 and 0 because num1 changes the only '1' in arr to '0' and because of that num2 will get an array which all of the places have 0. what I want is for BOTH of the functions to print 1 so the output will be "11" insted of 10. And no, without making a new array I really want to know if there's a way to do it with a single array

  • You're going to need to make a copy of that array. – Michael Bianconi Aug 07 '19 at 19:43
  • 2
    Possible duplicate of [Why can't we pass arrays to function by value?](https://stackoverflow.com/questions/7454990/why-cant-we-pass-arrays-to-function-by-value) – Michael Bianconi Aug 07 '19 at 19:44
  • @MichaelBianconi Is that really the only way? I did it in my original code but I really want to know if there's a way to do that in the same one –  Aug 07 '19 at 19:45
  • 2
    Ditch the raw arrays and switch to using [`std::array`](https://en.cppreference.com/w/cpp/container/array). That will behave like a normal object and make a copy when passed by value. – NathanOliver Aug 07 '19 at 19:45
  • `int arr[5][6]` in your function parameters is equivalent to `int** arr`. What your function receive is just a pointer to a memory location containing an integer (The first element of your array). What will happen is that `num1` will modify the content of your array, so `num2` return value will be affected. – Adrien Givry Aug 07 '19 at 19:46
  • have you considered using `std::vector`? – Daniel Aug 07 '19 at 19:48
  • 2
    @AdrienGivry No, it's not `int **arr`. Only the top-level array decays, which makes it `int (*arr)[6]`. – HolyBlackCat Aug 07 '19 at 19:49
  • @Daniel No, I didn't learn about vectors yet. –  Aug 07 '19 at 19:49
  • @NathanOliver I don't understand. Can you please explain more? –  Aug 07 '19 at 19:50
  • @AdrienGivry Yeah, I know what happends. Thanks anyway. –  Aug 07 '19 at 19:50
  • *`int arr[5][6]` in your function parameters is equivalent to `int** arr`* is troublesome and leads to many bad assumptions that will make you suffer. – user4581301 Aug 07 '19 at 19:55
  • @R4Z7 vectors are arrays with dynamic size (that means, not constant size). When you pass a vector as an argument to a function, the compiler creates a copy of it, so the original variable doesn't change it's value when you modify its copy inside a function. Take a quick look [here](https://en.cppreference.com/w/cpp/container/vector), this might solve your problem. – Daniel Aug 07 '19 at 19:56
  • @AdrienGivry `int arr[5][6] in your function parameters is equivalent to int** arr` -- Please no. If it were equivalent, the C++ compiler would never complain if you tried to assign one to the other. – PaulMcKenzie Aug 07 '19 at 19:58
  • 1
    @R4Z7 -- [See this answer](https://stackoverflow.com/questions/27410943/returning-arrays-from-a-function-in-c/27411483#27411483). Basically very easy -- just wrap a struct around your array, and instantly you have an "array" that's copyable, assignable, can pass it to functions and return it by value, etc. All you need is to use an extra `.` syntax to access the array. – PaulMcKenzie Aug 07 '19 at 20:09

2 Answers2

5

C arrays don't support proper value semantics in the way that most other things in C++ (or in C) do. An alternative which does work as one might expect is std::array. To get your 6 wide by 5 tall array, the type is std::array<std::array<int, 6>, 5>. Since that's a little verbose, you might want a using statement, e.g.

using arr_6_5 = std::array<std::array<int, 6>, 5>;

EDIT: Unfortunately, declaring such an array is a little annoying. You actually need two layers of curly braces per array: one for the the wrapping std::array, and one for the C-style array that it wraps (these layers of indirection are eliminated during compilation, however).

const arr_6_5 arr = {{
  {{0, 0, 0, 1, 0, 0}} ,   
  {{0, 0, 0, 0, 0, 0}} ,   
  {{0, 0, 0, 0, 0, 0}} ,
  {{0, 0, 0, 0, 0, 0}} ,
  {{0, 0, 0, 0, 0, 0}}
}};

And you would change the type signature of num1 and num2 to

int num1(arr_6_5 arr, int count);
int num2(arr_6_5 arr, int count);

If you do want to edit the original array, then it's arr_6_5 & arr, and if you want to read the original and not make a copy then it's arr_6_5 const& arr.

hegel5000
  • 876
  • 1
  • 7
  • 13
  • No, It only takes a single array it gives me an error when I am trying to do 2D array. –  Aug 07 '19 at 20:09
  • @R427 I've fixed the syntax. Sorry about that! – hegel5000 Aug 07 '19 at 20:11
  • all good but why do I need 2 {{ that's just how the syntax works? and how do I call them so they'll print the return value? –  Aug 07 '19 at 20:14
  • @R4Z7 [Here's a more thorough explanation than I could ever give](https://stackoverflow.com/questions/11734861/when-can-outer-braces-be-omitted-in-an-initializer-list). – hegel5000 Aug 07 '19 at 20:16
  • Ok, but how do I print the value to the screen? That's the last qustion I just need to mark you as the answer I just need to see if both of them print 1 –  Aug 07 '19 at 20:18
  • @R4Z7 C++ doesn't have built-in printing of collections :\ So you'd need loops like `for(auto&& row : arr){ for(int elem : row){ std::cout << elem << '\t'; } std::cout << std::endl; }` – hegel5000 Aug 07 '19 at 20:26
  • I want to print the return of the functions, not the 2d array –  Aug 07 '19 at 20:47
  • @R4Z7 Oh, well you would do that the same way you were already doing it in your question. – hegel5000 Aug 07 '19 at 20:50
  • That doesn't work this is the error: https://learn.microsoft.com/en-us/cpp/error-messages/tool-errors/linker-tools-error-lnk2019?f1url=https%3A%2F%2Fmsdn.microsoft.com%2Fquery%2Fdev15.query%3FappId%3DDev15IDEF1%26l%3DEN-US%26k%3Dk(LNK2019)%26rd%3Dtrue&view=vs-2019 it's an error with LNK2019 –  Aug 07 '19 at 20:51
  • @R4Z7 You need to make sure that the type signatures match between both your forward declaration and your function definition. – hegel5000 Aug 07 '19 at 20:54
  • I am calling it as an int arrgument in the funtion. how do I need to call it? –  Aug 07 '19 at 20:56
  • You call it the same way, but you need to make sure that both lines which start with `int num*` (where * is either 1 or 2) go on to say `(arr_6_5 arr, int count)`. If you're getting a linker error, that probably means that in your function definition, you still have `int arr[5][6]`. – hegel5000 Aug 07 '19 at 21:10
  • I know that, but what do I need to change the int arr[5][6] to? –  Aug 07 '19 at 21:32
  • 1
    @R4Z7 `std::array, 5> arr`, or just `arr_6_5 arr` (assuming you have the relevant `using` statement). – hegel5000 Aug 07 '19 at 21:37
1

Since you are essentially passing a pointer to the 2D array to the function there is no way to modify the parameter arr without modifying the array arr in your main function.

A possible solution would be to pass arr as const and then copy it to a temporary array for modification.

int num1(const int arr[5][6],int count){
    int arrLoc[5][6];
    for (int i = 0; i < 5; i++) {
        for (int j = 0; j < 6; j++) {
            arrLoc[i][j] = arr[i][j];
            if (arrLoc[i][j] == 1) {
                count++;
                arrLoc[i][j] = 0;
            }
        }
    }
    // mutate local copy while leaving `arr` unmodified
    mutation(arrLoc);
    return count;
}
dpuleri
  • 96
  • 1
  • 4
  • Alright! so all I need to do it to create a 2D array in the function and then sa that the 2D array = arr every time and then at the end of the function do mutation to the value I created? But then, what do I call in the main function? arr or arrLoc –  Aug 07 '19 at 19:48
  • `arrLoc` won't be available in the main function as its scope is limited to the `num1()` function. If you would like to mutate the original array then your implementation in the correction would be fine. Are you asking how to pass the array to the `num1()` function? You wouldn't need to change what you're doing because `arr` will automatically be a const pointer in the function and the new array is local only. – dpuleri Aug 07 '19 at 19:50
  • But it'll act like arr in the function? –  Aug 07 '19 at 19:51
  • Yes since you named the parameter `arr`. You could name it `pointer2Arr` and it would also act like a `const` pointer to the original `arr` in your main function. – dpuleri Aug 07 '19 at 19:52
  • @Jarod42, you're right. I didn't proofread the code fully. – dpuleri Aug 08 '19 at 17:45