-1

I am trying to reset 2D array to its original form after it's been sorted with a bubble sort. I need to reset it back to what it was before sorting. How do I do it? In case you have a question why an array is global. It's a school assignment and that's how our professor wants us to do it. Here is my program:

 #include<iostream>

    using namespace std;
    const int NUM_COLS=4;
    const int NUM_ROWS=5;       

    int array[NUM_ROWS][NUM_COLS]={{5, 3, 2, 16},
                            {9, 8, 10, 17},
                            {4, 7, 11, 18},
                            {2, 5, 9, 12},
                        {7, 9, 4, 10}};

it sorts an array with bubbleSort

void bubbleSort(int row, int col){}

it is display array function header

void displayArray(){}

and here is main function

int main(){



        cout<<"original array"<<endl;
        displayArray();

        bubbleSort(NUM_ROWS-1, NUM_COLS);
        cout<<"\nbubble sort"<<endl;
        displayArray();

        reset();
        displayArray();
        return 0;
    }

Now I need to reset an array back to original. I did this but it doesn't work.

void reset(){

 int array[NUM_ROWS][NUM_COLS]={{5, 3, 2, 16},
                                {9, 8, 10, 17},
                                {4, 7, 11, 18},
                                {2, 5, 9, 12},
                                {7, 9, 4, 10}};
}
Maria
  • 17
  • 2
  • 3
    This is not possible, the initial order of elements is not preserved anywhere. You will have to create a copy of the array. – Dmytro Dadyka Mar 11 '19 at 17:07
  • Can you elaborate pls. I've been searching internet for an answer and I found answers like "create a copy" but it didn't work when I tried to do it. – Maria Mar 11 '19 at 17:14
  • Make a copy before sorting. Or, sort a new container of `std::reference_wrapper` to get a sorted *view* of the original container. – Jesper Juhl Mar 11 '19 at 17:25
  • you're creating a new array in `reset()`, but you can't assign to plain arrays anyway. consider using `std::array` so you can reassign `=` it. – kmdreko Mar 11 '19 at 17:25

3 Answers3

2

Your reset is declaring a new array (and doing nothing with it). You can't assign (=) C style arrays, so you will need something that looks different. If you can use std::array instead, you could assign in reset.

#include <array>

const int NUM_COLS=4;
const int NUM_ROWS=5;       

std::array<std::array<int, NUM_ROWS>, NUM_COLS> values = {
    {5, 3, 2, 16},
    {9, 8, 10, 17},
    {4, 7, 11, 18},
    {2, 5, 9, 12},
    {7, 9, 4, 10}};

// Other code probably remains unchanged

void reset() {
    values = {
        {5, 3, 2, 16},
        {9, 8, 10, 17},
        {4, 7, 11, 18},
        {2, 5, 9, 12},
        {7, 9, 4, 10}};
}

At which point you notice that you've got your bounds the wrong way round, and it should either be

const int NUM_COLS=5;
const int NUM_ROWS=4;       

or a differently shaped array initialiser.

Caleth
  • 52,200
  • 2
  • 44
  • 75
  • +1 but shouldn't you have: `std::array, NUM_ROWS> values ...` and then original 2d array would work? I also think you need extra braces to not confuse the compiler, like so: `values = {{{5, 3, 2, 16}, {9, 8, 10, 17}, {4, 7, 11, 18}, {2, 5, 9, 12}, {7, 9, 4, 10}}};` – Ted Lyngmo Mar 11 '19 at 17:41
0
void reset(){
  static int original[NUM_ROWS][NUM_COLS]={{5, 3, 2, 16},
                                {9, 8, 10, 17},
                                {4, 7, 11, 18},
                                {2, 5, 9, 12},
                                {7, 9, 4, 10}};

  for (int i = 0; i < NUM_ROWS; i++)
    memcpy(array[i], original[i], NUM_COLS * sizeof(int));
}

Not the prettiest thing, but this should work. Since that's how your professor wants you to do it, go for it ¯\_(ツ)_/¯

GBrandt
  • 685
  • 4
  • 11
  • 2
    Isn't that using the wrong bounds? You have `NUM_ROWS` instances of `int[NUM_COLS]` – Caleth Mar 11 '19 at 17:35
  • I would consider using `std::copy(std::begin(*original), std::begin(*original) + NUM_ROWS * NUM_COLS, std::begin(*array))` instead of that loop and memcpy – local-ninja Mar 11 '19 at 17:37
  • @fdan I'm not sure if the matrix would be aligned correctly in memory, but yeah, maybe. I'd still go for `memcpy(array, original, NUM_ROWS * NUM_COLS * sizeof(int))` though. If the professor is asking for a `int[][]` they probably wouldn't want people to use `std::copy`. Ideally, using C++ STL would be the way to go, yes, but you never know. – GBrandt Mar 11 '19 at 17:43
0

As I said in a comment, the easiest way to assign arrays is to wrap them in a structure. Voilà, suddenly C++ develops abilities it didn't even know it had inherited from C and copies arrays!1 Even nested, multi-dimensional arrays!

#include <iostream>
#include <iomanip>
#include <algorithm>
using namespace std;

const int NUM_COLS=4;
const int NUM_ROWS=5;       

// Define a struct (i.e., a class with all public members)
// which has just a single member, the array. Note that this is
// only a *type* declaration, no object is created yet.
struct arrT
{
  int array [NUM_ROWS][NUM_COLS];
};

// object creation.
arrT workArr;

void reset()
{
  // The initialization value is hidden inside the function.
  // static variables are initialized only once, for constant 
  // data at compile time.
  static const arrT oriArr 
  {
    { {5, 3, 2, 16},
      {9, 8, 10, 17},
      {4, 7, 11, 18},
      {2, 5, 9, 12},
      {7, 9, 4, 10}
    }
  };

  workArr = oriArr; // simple default assignment of structs
}

// The parameters are redundant.
void stdSort(int /*row*/, int /*col*/)
{ 
  // Sort the 2D array as a one-dimensional sequence
  // (which the elements are in memory).
  // The algorithm expects iterators to the first and
  // one-after-the-last elements in the sequence. Pointers
  // to the elements in an array are perfectly good iterators.
  std::sort(&workArr.array[0][0], &workArr.array[NUM_ROWS-1][NUM_COLS]);
}

void displayArray()
{
  // The top-level elements of a 2D array are the rows...
  for(auto &row: workArr.array)
  {
    // ... and the elements of the rows are ints. 
    // Note how the
    // dimensions are known from the class declaration.
    for(auto &el: row)
    {
      cout << setw(4) << el;
    }
    cout << "\n";
  }
}

int main(){

  cout << "Work array before initialization:\n";
  displayArray();

  reset(); // before, the values of the global array are 0.
  cout<<"\nWork array after init:\n";
  displayArray();

  stdSort(NUM_ROWS, NUM_COLS);
  cout<<"\nWork array after std sort"<<endl;
  displayArray();

  reset();
  cout << "\nWork array after reset\n";
  displayArray();
  return 0;
}


1 Arrays are the only example I know of off the cuff where the memberwise assignment of the generated default assignment operator can assign a type which does not have a standalone assignment operator (which is the exact reason we jump through this hoop). Are there others?
Peter - Reinstate Monica
  • 15,048
  • 4
  • 37
  • 62