3

I have a 3D array and I need to find a int in that array using a single int.

My array:

int arrayOne[3][3] = {
    {1,2,3},
    {4,5,6},
    {7,8,9}
};

I need to be able to navigate the array using a single int like:

int i = 4;
cout << arrayOne[4];

This will print out 5.

It it possible to do it like this or is it another way to do this?

I started to code with a 3D array and I really don't want to rewrite everything if I don't need to.

I have googled around and did not find a solution.

Andreas DM
  • 10,685
  • 6
  • 35
  • 62
tobhal
  • 33
  • 5
  • Why do you need to treat multi-dimensional arrays as 1-dimensional ones? – Benjamin Urquhart Aug 10 '19 at 23:14
  • See Also: [Map a 2D array onto a 1D array](https://stackoverflow.com/questions/2151084/map-a-2d-array-onto-a-1d-array) – David C. Rankin Aug 10 '19 at 23:34
  • You could go for the unreadable version without any intervening variable and giving only a single index, `std::cout << "4th element: " << *(*(arrayOne + 4 % sizeof *arrayOne/sizeof **arrayOne) + 4 % sizeof *arrayOne/sizeof **arrayOne) << '\n';` – David C. Rankin Aug 11 '19 at 00:05

3 Answers3

5

You could wrap your single int around the size of your array (on a chosen dimension):

arrayOne[i / 3][i % 3]  // wrapping around the size of the inner arrays

To clarify what is going on here:

  • i = 0 => i/3 = 0, i%3 = 0
  • i = 1 => i/3 = 0, i%3 = 1
  • i = 2 => i/3 = 0, i%3 = 2
  • i = 3 => i/3 = 1, i%3 = 0
  • i = 4 => i/3 = 1, i%3 = 1
  • i = 5 => i/3 = 1, i%3 = 2
  • i = 6 => i/3 = 2, i%3 = 0
  • i = 7 => i/3 = 2, i%3 = 1
  • i = 8 => i/3 = 2, i%3 = 2

You can see that i can take 3*3 different values before (i/3) or (i%3) overflow, which makes perfect sense.

The reverse operation would be multiplying the first coordinate by 3 and adding the second:

(i/3) * 3 + (i%3) == i

Knowing how to switch between the two "indexing systems", it will be trivial for you to write a loop that translates your 2-array into a 1-dimension one.


I find the picture of a (2D!) coil useful here, because the coil is a 1D wire that spans a 2D area:

1d-to-2d coil


EDIT: Be sure to also check out Andreas DM's answer!

hugo
  • 3,067
  • 2
  • 12
  • 22
3

I need to be able to navigate the array using a single int like: int i = 4; cout << arrayOne[4]; It it possible to do it like this

Yes, it is:

int arrayOne[3][3] {
  {1,2,3},
  {4,5,6},
  {7,8,9},
};

int* array = arrayOne[0];
std::cout << array[4];
Andreas DM
  • 10,685
  • 6
  • 35
  • 62
  • it is pedantically UB though. – Jarod42 Aug 11 '19 at 07:30
  • @Jarod42 Is it? Since array items must be contiguous, I fail to see how that could not work. – hugo Aug 11 '19 at 20:34
  • 1
    @hugo: `arrayOne[0]` is a `int (&)[3]`, accessing out of bound access is UB. So `array[0]`, `array[1]`, `array[2]` and even `array + 3` are valid but `array[3]` and `array + 4` are UB. Unfortunately, rule doesn't cover that case. In practice, I believe it would work but we are in UB world. – Jarod42 Aug 11 '19 at 21:27
-1

You iterate a two dimensional array with two for loops, one nested into the other. In fact you don't even need a variable you just cout the number in the index of every iteration. If you want to do it with a single index, turn the two dimensional array into a single dimensional array.

    int arr[3][3] = {
            {1, 2, 3},
            {4, 5, 6},
            {7, 8, 9}
          };

    int singleArr [arr.length*arr[0].length];
    int counter = 0;

    for (int i = 0; i < sizeof(arr)/4; i++) {
        for (int j = 0; j < sizeof(arr[0])/4; j++) {
            singleArr[counter] = arr[i][j];
            counter++;
        }
    }
    std::cout<<singleArr[4];