[c++] Przkeazanie tablicy dwuwymiarowej do funkcji


(xBotekx) #1

Witam otóż mam następujący problem próbuje przekazać tablicę dwuwymiarową do funkcji gdzie drugi wymiar jest stał (const) niektóre kompilatory przyjmują zapis tab[n][1000] gdzie n jest dynamicznie pobierany niestety nie visual. Natomiast gdy próbuje to zrobić
int ** dp = new int*[e + 1];
for(int i=0;i<e+1;i++)
dp[i] =new int[MAX];

To przy wywołaniu wyskakuje niezgodność typów. Rozwiązanie pewnie jest banalne i proste jednak jakoś nie potrafię na nie wpaść.

Tak wygląda argument funkcji bool cos(int dp[][MAX])


(Fizyda) #2
 *dp[i] =new int[MAX];

A deklaracja funkcji:

 bool cos(int ** dp, int n, int max)

(xBotekx) #3

*dp[i] =new int[MAX];

To nie działa albo ja to źle zrozumiałem. A co do deklaracji to nie wiem dlaczego ale taka deklaracja daje złe wyniki. Inne od statycznej deklaracji.


(Fizyda) #4

Działający przykład:

#include <iostream>
#include <string>
#include <cstdlib>
#include <ctime>

void printMatrix(int** matrix, int n, int m)
{
    for(int i = 0; i < n; i++)
    {
        for(int j = 0; j < m; j++)
            //std::cout << (matrix[i])[j] << ", ";
            //std::cout << matrix[i][j] << ", ";
            std::cout << *((*(matrix + i)) + j) << ", ";
            
        std::cout << std::endl;
    }
}

void fillMatrix(int** matrix, int n, int m)
{
    srand(time(NULL));
    
    for(int i = 0; i < n; i++)
        for(int j = 0; j < m; j++)
            //(matrix[i])[j] = rand() % 100 + 1;
            //matrix[i][j] = rand() % 100 + 1;
            *((*(matrix + i)) + j) = rand() % 100 + 1;
}

int main()
{
    int n = 5, m = 8;
    
    int** matrix = new int*[n];
    
    for(int i = 0; i < n; i++)
        matrix[i] = new int[m];
        
    fillMatrix(matrix, n, m);
    printMatrix(matrix, n, m);
}

http://cpp.sh/75fil

3 linijki w obu pętlach są równoważne - czemu? bo nazwa tablicy jest jej wskaźnikiem.


(xBotekx) #5
 int dp[4][MAX];
		//MAX is the Maximum value M can take 
		//int ** dp = new int*[4];
		
		//for(int i=0;i<4;i++)
		// dp[i] = new int[MAX]; 

I teraz jeśli pierwszą linię zakomentuje a pozostałe odkometuje i zmienię argument na przez ciebie podany to funkcja zwraca zły wynik. Przyczyną może być to ,że używam rekurencji. Ale nie wiem jak to napisać by działało.


(Fizyda) #6

Może Tobie chodzi o coś takiego?

#include <iostream>
#include <cstdlib>
#include <ctime>

int const matrix_max = 8;

void printMatrix(int matrix[][matrix_max], int n)
{
    for(int i = 0; i < n; i++)
    {
        for(int j = 0; j < matrix_max; j++)
            std::cout << matrix[i][j] << ", ";
            
        std::cout << std::endl;
    }
}

void fillMatrix(int matrix[][matrix_max], int n)
{
    srand(time(NULL));
    
    for(int i = 0; i < n; i++)
        for(int j = 0; j < matrix_max; j++)
            matrix[i][j] = rand() % 100 + 1;
}

int main()
{
    int n = 5;
    
    int matrixOne[5][matrix_max];
        
    fillMatrix(matrixOne, n);
    printMatrix(matrixOne, n);
    
    std::cout << std::endl << "Druga macierz" << std::endl << std::endl;
    
    
    int (*matrixTwo)[matrix_max];
    
    matrixTwo = new int[n][matrix_max];
        
    fillMatrix(matrixTwo, n);
    printMatrix(matrixTwo, n);
}

http://cpp.sh/25nm6


(xBotekx) #7

Właśnie o to mi chodziło dzięki wielki. Tylko dalej to nie działa po prostu nie wiem już co się dzieje.

                //int dp[4][MAX];
		int(*dp)[MAX];

		dp = new int[4][MAX];

W teorii powinno dać to samo, no a w praktyce niestety nie, znowu jeśli “odwrócę” komentarze to działa a jak jest tak, to nie. Ale generalnie o to mi chodziło.

Masz pomysł czym się one różnią?

Winna jest funkcja memset która ma zamienić wszystkie wartości w tablicy na -1. Nie wiem dlaczego ona nie działa. Po ręcznym zamienieniu na -1 działa. Masz pomysł dlaczego nie działa?

Tak ona wygląda memset(dp, -1, sizeof(dp));

Dziękuje bardzo za pomoc zamiast sizeoff dałem po prostu n*MAX. Na razie wszystko działa ,ale muszę go jeszcze porządnie przetestować.


(Fizyda) #8
  1. Czyli czemu nie działa: bo wskaźnik na tablicę typu int to nie jest to samo co tablica tablic.
  2. Czemu funkcja nie działa?: bo ona jest do tablic, a nie do macierzy, chcesz wypełnić macierz to musisz to zrobić w pętli. Pseudokod:
for(int i = 0; i < sizeof(dp); i++)
    memset(dp[i], -1, MAX);

EDIT:
Oczywiście jeśli rezerwujesz pamięć ciągiem dla całej macierzy to możesz zrobić tak:

memset(dp, -1, 4 * MAX);

Ale w tedy nie możesz tworzyć tej tablicy jak w pierwszym przykładzie - czyli w pętli. Odpada w tedy int ** ptr;.


(xBotekx) #9

Dzięki wielki. Nie wiem czemu mnie zaćmiło i w ogóle nie brałem pod uwagę ,że nie działa ta linijka. Skoro mam i jeden wymiar i drugi to chyba szybciej będzie po prostu je przemnożyć zamiast używać sizeof. Czy się mylę?


(Fizyda) #10

To zależy w jaki sposób masz dostęp do tablicy. Jeśli już możesz użyć sizeof to zawsze lepiej wywalić ją poza funkcję i nie wywoływać jej przy każdym przebiegu pętli.

size_t size = sizeof(dp);

for(int i = 0; i < size; i++)
    memset(dp[i], -1, MAX);

(Fizyda) #11

Ehh, ale dałem się wprowadzić w błąd. Przecież sizeof nie zwróci Ci ilości elementów tablicy. Jak chcesz mieć długość (ilość elementów) tablicy to musisz zrobić coś takiego:

int size = sizeof(dp) / sizeof(dp[0]);

(xBotekx) #12

Tak tylko pytanie czy jest sens skoro mam pobrane oba wymiary i mogę sobie sam obliczyć liczbę elementów.


(Fizyda) #13

W którym miejscu chcesz to zrobić bo chyba nie do końca rozumiem o co chodzi.


(xBotekx) #14

Chodzi mi o zmienienie wszystkich wartości w tej tablicy dwuwymiarowej na -1.


(Fizyda) #15

Aha, ja myślałem, że pytasz o sens używania sizeof. Co do memset to tak jak napisałem, zależy jak utworzysz macierz. Osobiście jednak uważam, że załatwienie tego “za jednym zamachem” może być miejscem generującym błąd trudny do wyśledzenia. Osobiście zrobiłbym to w pętli.


(xBotekx) #16

Jeszcze jedna prośba podpowiesz jak usnąć tablicę utworzoną w ten sposób?


(Fizyda) #17

Domyślam się, że chodzi o tak tworzoną tablicę:

    int (*matrixTwo)[matrix_max];
    
    matrixTwo = new int[n][matrix_max];

Szczerze to nie jestem pewny. Wydaje mi się, że innej opcji jak delete[] nie ma i to jest sposób na jej skasowanie. Dla pewności jednak sprawdziłbym czy na pewno zwalniane są wszystkie zasoby.


(xBotekx) #18

No właśnie, gdy daję zwykły delete to pokazuje ,że nie zwalniam całej pamięci (ostrzeżenie). A gdy próbuje to zrobić w pętli to od razu błąd dostępu.

 for (int j = 0; j < e + 1; j++) 
delete dp[j];

Oczywiście tablica taka jak napisałeś.


(Fizyda) #19

delete[] dp;
pewnie robisz
delete dp;