2016-03-25 18 views
9

Próbowałem skopiować dwuwymiarową tablicę do innej macierzy o innym rozmiarze. Na przykład pierwsza tablica w 4 wierszy i 4 kolumnyKopiowanie dwuwymiarowych elementów tablicy do innej dwuwymiarowej tablicy o innym rozmiarze

1 2 3 4 
5 6 7 8 
9 0 1 2 
3 4 5 6 

drugi układ 2 wierszy i 8 kolumn:

1 2 3 4 5 6 7 8 
9 0 1 2 3 4 5 6 

i jeśli w nowej tablicy więcej elementów niż pierwszy wtedy funkcja zapełni ją 0

to jest funkcja, którą zrobiłem, ale problem z indeksami. Jak napisać to we właściwy sposób?

void changearr(int **ppm, int size1, int size2, int size_1, int size_2) 
{ 
    int **temp = new int*[size_1]; 
    for (int i = 0; i < size_1; i++) 
     temp[i] = new int[size_2]; 
    int z = 0; 
    for (int i = 0; i < size_1; i++, z++) 
    { 
     for (int j = 0, k = 0; j < size_2; j++, k++) 
     { 
      if (i < size_1 || j < size_2) 
      { 
       temp[i][j] = ppm[z][k]; 
      } 
      else 
       temp[i][j] = 0 
     } 
    } 
+0

Wystarczy pętli na pierwszej tablicy za pomocą i i j. Indeksy z i k dla drugiej macierzy muszą być oszacowane z i i j, nie pętli ponad z i k. –

+0

Ponieważ tablica jest ciągła w pamięci, tablice są prawie takie same w sposobie ich przechowywania. Pytanie brzmi, jaki poziom kontroli potrzebujesz w swojej funkcji. Czego chcesz pod warunkiem, że miejsce docelowe jest mniejsze niż źródło? I jak już wspomniano poniżej, czy musi działać tylko dla tablic, czy też dla szeregu wskaźników? Ponieważ jeśli dane są ciągłe w pamięci, możesz to zrobić w jednym lub dwóch wierszach. – Chiel

Odpowiedz

7

Dlaczego nie zrobić tymczasową tablicę liniowy z macierzy wejściowej, a następnie używać, aby wypełnić macierz wyjściową:

void changearr (int** ppm, int old_row, int old_col, int new_row, int new_col) 
{ 
    int* temp_linear = new int[old_row * old_col]; 

    int k = 0; 
    for (int i = 0; i < old_row; i++) 
    { 
     for (int j = 0; j < old_col; j++) 
     { 
      temp_linear[k++] = ppm[i][j]; 
     } 
    } 

    int** temp = new int* [new_row]; 
    for (int i = 0; i < new_row; i++) 
    { 
     temp[i] = new int[new_col]; 
    } 

    k = 0; 
    for (int i = 0; i < new_row; i++) 
    { 
     for (int j = 0; j < new_col; j++) 
     { 
      if (k < old_row * old_col) 
      { 
       temp[i][j] = temp_linear[k++]; 
      } 
      else 
      { 
       temp[i][j] = 0; 
      } 
     } 
    } 
} 
8

Ohhhhh, co za miłe puzzle do programowania. Moim rozwiązaniem jest spłaszczenie obu tablic i ich skopiowanie.

template <typename T> 
static constexpr T* begin(T& value) noexcept 
{ 
    return &value; 
} 

template <typename T, ::std::size_t N> 
static constexpr typename ::std::remove_all_extents<T>::type* 
begin(T (&array)[N]) noexcept 
{ 
    return begin(*array); 
} 

template <typename T> 
static constexpr T* end(T& value) noexcept 
{ 
    return &value + 1; 
} 

template <typename T, ::std::size_t N> 
static constexpr typename ::std::remove_all_extents<T>::type* 
end(T (&array)[N]) noexcept 
{ 
    return end(array[N - 1]); 
} 

int a[4][4]; 
int b[2][8]; 

::std::copy(begin(a), end(a), begin(b)); 
+0

To jest 8 wierszy i 2 kolumny;) – xinaiz

+0

To rozwiązanie nie działa w przykładzie OP, gdzie ma wskaźnik, a nie tablicę, a twoje rozwiązanie zależy od znajomości rozmiaru tablicy w czasie kompilacji. – LoPiTaL

6

Można użyć prostego tymczasowego pojemnika:

#include <iostream> 
#include <deque> 
#include <array> 

int main() 
{ 
    std::array<std::array<int,4>,4> first {1,2,3,4,5,6,7,8,9,10,11,12,13,14,15,16}; //4x4 
    std::array<std::array<int,8>,2> second; //2x8 
    std::deque<int> temp; //temporary container 

    for(auto x : first) 
     for(auto y : x) 
      temp.push_back(y); //push everything from first to deque 

    for(auto& x : second) 
     for(auto& y : x) 
     { 
      y = temp.front(); //move from deque to second and pop() 
      temp.pop_front(); 
     } 
} 
3

Jak wiadomo, macierze n-wymiarowe C/C++ mają liniową reprezentację w pamięci. Więc jeśli będzie włączać takiej reprezentacji można uzyskać następujące korzyści:

std::vector<int> v1{1,2,3,4,5,6,7,8,9,10,11,12,13,14,15,16}; 
for(size_t r = 0; r < 4; r++) 
for(size_t c = 0; c < 4; c++) 
    std::cout << v1[r*4+c]; 
std::vector<int> v2(v1); 
for(size_t r = 0; r < 2; r++) 
for(size_t c = 0; c < 8; c++) 
    std::cout << v2[r*8+c]; 
4

2D tablica jest nie samo wskaźnik do wskaźnika jest! Jako 2D tablicy po prostu przechowywać rzędach jeden za drugim, trzeba tylko skopiować elementy:

#include <iostream> 

void trans(int* orig, int rows1, int cols1, int *resul, int rows2, int cols2) { 
    int tot1 = rows1 * cols1; 
    int tot2 = rows2 * cols2; 
    int tot = tot1; 
    if (tot2 < tot) tot = tot2; 
    // copy the smallest size from both arrays 
    for(int i=0; i<tot; i++) { 
     resul[i] = orig[i]; 
    } 
    // eventually add 0 to fill resul array 
    for(int i=tot; i<tot2; i++) { 
     resul[i] = 0; 
    } 
} 
int main() 
{ 
    int orig[4][4] = { 1, 2, 3, 4, 5, 6, 7, 8, 9, 0, 1, 2, 3, 4, 5, 6}; 
    // control initial array 
    for (int i=0; i<4; i++) { 
     for (int j=0; j<4; j++) { 
      std::cout << orig[i][j]; 
     } 
     std::cout << std::endl; 
    } 
    int resul[2][8]; 
    // pass arrays as 1D array pointers! 
    trans(reinterpret_cast<int *>(&orig), 4, 4, reinterpret_cast<int *>(&resul), 2, 8); 
    // control converted array 
    for (int i=0; i<2; i++) { 
     for (int j=0; j<8; j++) { 
      std::cout << resul[i][j]; 
     } 
     std::cout << std::endl; 
    } 
    return 0; 
} 

Daje zgodnie z oczekiwaniami:

1234 
5678 
9012 
3456 
12345678 
9
3

Oto bardzo prosty sposób:

void 
    changearr(
    int **in,int in_size1,int in_size2, 
    int **out,int out_size1,int out_size2 
    ) 
{ 
    int in_n = in_size1*in_size2; 
    int out_n = out_size1*out_size2; 
    int n = min(in_n,out_n); 
    int i = 0; 

    for (; i!=n; ++i) { 
    out[i/out_size2][i%out_size2] = in[i/in_size2][i%in_size2]; 
    } 

    for (; i!=out_n; ++i) { 
    out[i/out_size2][i%out_size2] = 0; 
    } 
} 

Chodzi o to, aby w sposób liniowy powtórzyć indeksy i obliczyć odpowiednie indeksy dla tablic wejściowych i wyjściowych w razie potrzeby.

Powiązane problemy