Atexor Temat założony przez niniejszego użytkownika |
Zwracanie tablicy dwuwymiarowej z funkcji » 2014-01-26 19:54:06 Witajcie, Mam problem z programem, który wypełni macierz 10x10 losowymi wartościami z przedziału [a,b], potem w pierwszej funkcji ją wyświetli i w drugiej także wyświetli, ale zawężoną o losowe współrzędne. Dokładnie to nie wiem jak mam zwrócić tablicę z funkcji "wys" do głównej funkcji programu, aby z powrotem ją dać do innej funkcji. Przy sprawdzaniu czy dobrze zwróciło do funkcji int main() (na dole kodu) pokazuje mi duże liczby w macierzy zamiast tę samą macierz. Jak to naprawić? Kod (bez drugiej funkcji, bo na razie niepotrzebna): #include <stdio.h> #include <stdlib.h> #include <time.h> #include <limits.h> typedef int MAC[ 10 ][ 10 ];
int wys( int af, int bf, int Nf ) { int j, k; int macierz[ 10 ][ 10 ]; for( j = 0; j < Nf; j++ ) { for( k = 0; k < Nf; k++ ) { macierz[ j ][ k ] = af + rand() %( int )( bf - af + 1 ); printf( "\t%d", macierz[ j ][ k ] ); } printf( "\n\n" ); } return( macierz[ 10 ][ 10 ] ); }
int main() { srand( time( NULL ) ); float liczba, a, b, x; int i, j, k, N, ilosc; float tab[ 15 ]; for( i = 0; i < 10; i++ ) { tab[ i ] = rand() % 15; if( i == 0 ) { a = tab[ i ]; b = tab[ i ]; } if( a > tab[ i ] ) a = tab[ i ]; if( b < tab[ i ] ) b = tab[ i ]; } printf( "Jaka macierz NxN chcesz wyswietlic? " ); scanf( "%d", & N ); puts( "\n" ); MAC mactab; mactab[ 10 ][ 10 ] = wys( a, b, N ); printf( "\n\n" ); for( i = 0; i < N; i++ ) { for( j = 0; j < N; j++ ) { printf( "%d\t", mactab[ i ][ j ] ); } printf( "\n\n" ); } system( "PAUSE" ); return 0; }
/ cpp ] |
|
Monika90 |
» 2014-01-26 20:25:36 Można zwrócic tablicę z funkcji jak się ją opakuje w strukturę. Można też zwrócić wskaźnik do dynamicznie zaalokowanej tablicy. Ale najlepiej będzie przekazać tablicę do wypełnienia przez referencję: void f( int( & tab )[ 10 ][ 10 ] ) { }
int main() { int a[ 10 ][ 10 ]; f( a ); }
|
|
alixir |
» 2014-01-26 20:57:03 Dla wyjaśnienia podam dwa przykłady: 1 - przekazywanie przez wskaźnik (jak tablice jednowymiarowe) oraz symulowanie wielowymiarowości void wypelnijMacierz( int * tab ) { for( int i = 0; i < 10; i++ ) for( int j = 0; j < 10; j++ ) tab[ i * 10 + j ] = i + j; } ... int macierz[ 10 ][ 10 ];
wypelnijMacierz( & macierz[ 0 ][ 0 ] );
2 - jak koleżanka wspomniała przez wskaźnik do dynamicznie zaalokowanej tablicy void wypelnijMacierz( int ** tab ) { for( int i = 0; i < 10; i++ ) for( int j = 0; j < 10; j++ ) tab[ i ][ j ] = i + j; } ... int ** macierz;
macierz = new int *[ 10 ]; for( int i = 0; i < 10; i++ ) macierz[ i ] = new int[ 10 ];
wypelnijMacierz( macierz );
for( int i = 0; i < 10; i++ ) delete[] macierz[ i ];
delete[] macierz;
|
|
Monika90 |
» 2014-01-26 21:41:47 |
|
Atexor Temat założony przez niniejszego użytkownika |
» 2014-01-26 22:49:04 Super... pisałem długiego posta i przy "Zapisz zmiany" go nie wysłało tylko pokazało temat bez mojej odpowiedzi. Chyba jakiś bug forum , bo już drugi raz mi się to zdarzyło.
---------------- Najogólniej to ja na początku chciałem w funkcji (nie main) stworzyć tablicę, tam na niej operować i ją zwrócić do głównej funkcji main poprzez return, a nie przekazywać ją z main do funkcji. Dałoby radę tak zrobić?
Moniko - próbowałem to zrobić za pomocą Twojego przykładu, jednak wyskakiwał mi błąd. Próbowałem także za pomocą podobnego przykładu do twojego (tylko tam do tablic jednowymiarowych) i też nie działało. Wzorzec: http://wklej.to/GGN4V W komentarzach zaznaczyłem co nie działa w obu przypadkach: Kod: http://wklej.to/2sZAk Czy w Twoim przykładzie zamiast operatora wyłuskania & nie powinno być wskaźnika *?
Spróbowałem też to stworzyć przy pomocy zdefiniowania nowej zmiennej - jak w tym przykładzie http://wklej.to/s40aq. Kod: http://wklej.to/V3Fdb Macierz mi wyświetla w konsoli, jednak nie wiem jak tę tablicę zwrócić do funkcji main.
Chciałem także przez struktury jak poleciłaś. Znalazłem na [a href="http://pl.wikibooks.org/wiki/C/Funkcje#Za_pomoc.C4.85_struktur" name"wikibooks"] jak to niby zrobić, ale mi nie działało. Fragment kodu: http://wklej.to/Qxahj
Alixir - niezbyt rozumiem twoje przykłady. W pierwszym jako rozmiar tablicy korzystasz z mnożenia i* 10 i dodajesz do tego j, aby uzyskać i+j. Co to w ogóle oznacza?
Zaś w drugim korzystasz ze... wskaźnika na wskaźnik (dwie gwiazdki), new int i delete [] innej tablicy. Nie wiem o co chodzi w tym zapisie. Teoretyczniejak pisałeś jest to rozwiązanie dla dynamicznie zaalokowanej tablicy, jednak nie kojarzę abyś korzystał tam z malloc'a, czy coś w ten deseń. Nie, alokować też jeszcze nie potrafię, dzisiaj próbowałem akurat malloc'ować realloc'ować, ale jak zwykle nie działało. Teraz w ogóle widzę, że nie usunąłem biblioteki limits.h w powyższych moich kodach. |
|
Monika90 |
» 2014-01-27 00:11:21 Moniko - próbowałem to zrobić za pomocą Twojego przykładu, jednak wyskakiwał mi błąd. Próbowałem także za pomocą podobnego przykładu do twojego (tylko tam do tablic jednowymiarowych) i też nie działało. Wzorzec: http://wklej.to/GGN4V W komentarzach zaznaczyłem co nie działa w obu przypadkach: Kod: http://wklej.to/2sZAk Czy w Twoim przykładzie zamiast operatora wyłuskania & nie powinno być wskaźnika *?
|
Mój przykład jest w C++. W C++ & służy do deklarowania referencji - w C nie ma referencji. Za pomocą struktury w języku C można tak: #include <stdlib.h> #include <stdio.h>
typedef struct { int macierz[ 10 ][ 10 ]; } s1;
s1 wys( int af, int bf, int Nf ) { int j, k; s1 s; for( j = 0; j < Nf; j++ ) { for( k = 0; k < Nf; k++ ) { s.macierz[ j ][ k ] = af + rand() %( int )( bf - af + 1 ); printf( "\t%d", s.macierz[ j ][ k ] ); } printf( "\n\n" ); } return s; }
int main() { s1 s; s = wys( 1, 3, 10 ); }
Takie zwracanie struktury z funkcji oznacza, że jej cała zawartośc jest kopiowana (100 intów), w pewnych sytuacjach to może prowadzić do problemów z wydajnością, ale w takim prostym programiku to raczej nie ma znaczenia. A w ogóle, radzę Ci przejść na C++. |
|
Atexor Temat założony przez niniejszego użytkownika |
» 2014-01-27 00:52:04 Za pierwszym pisaniem mojego poprzedniego postu wspominałem o referencji, gdyż słyszałem o niej, że istnieje jako alternatywa wskaźników z C. Myślałem, że tamten kod napisałaś w języku C, bo nie widziałem żadnych charakterystycznych rzeczy dla C++ typu strumienie itp. Pomyślałem, że poprzez stwierdzenie "referencja" mogłaś mieć na myśli ów wskaźniki, tylko zrobiłaś literówkę pomiędzy & i *.
W międzyczasie jak mi odpisywałaś zrozumiałem już o co chodziło z tym przykładem na wikibooks ze strukturami. Po prostu nie sądziłem, że może istnieć bez etykiety i to mi głównie psuło "szyk". Teraz przeanalizowałem Twój przykład jak wyglądał i z pamięci postarałem się zrobić analogiczny. Działa :) Dziękuję Ci bardzo!
P.S. Z miłą chęcią bym przeszedł na C++, ale na studiach muszę poznać C, zaś programowaniem obiektowym zajmę się bodajże za dwa semestry.
Pozdrawiam :) |
|
alixir |
» 2014-01-27 07:23:56 Atexor w swoim pierwszym poście nie zaznaczyłeś, że chodzi ci o rozwiązanie czysto C. Ja z reguły używam C++, stąd też pewne nieporozumienie i niejasność w moim kodzie.
Gwoli wyjaśnienia: Mój pierwszy przykład opierał się na symulowania wielowymiarowości tablicy, tak jak robią to kompilatory (pamięć jak wiadomo jest liniowa). Monika jednak dobrze zauważyła, że ten sposób ma niezdefiniowane zachowanie w kompilatorach zgodnych ze standardem C99 (nawet nie wiedziałem – mój błąd). Chodziło tu ogólnie o wyliczanie indeksu ze wzoru: Nr_indeksu = i * w + j Gdzie: i,j - to współrzędne w tablicy dwuwymiarowej w – szerokości tablicy dwuwymiarowej W twoim przykładzie (macierz o szerokości 10), gdybyś chciał dostać się do elementu tab[2][6] zapis symulowany wyglądał by tak: tab[2*10+6]
Drugi przykład opierał się o tablice zaalokowane dynamicznie. Nie ma tam zapisu malloc, gdyż zastępuje go napis new (z języka C++)
Pozdrawiam
|
|
« 1 » 2 |