C functie return array (2d)

Pagina: 1
Acties:

  • vinietje
  • Registratie: Januari 2001
  • Laatst online: 04-04 15:08
Hoi,

ZIt al paar uur te hobby'en om iets aan de gang te krijgen.

Heb een functie in elkaar gezet, zie onderstaande code (pseudo)

code:
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
#include <stdio.h>

int functie(void)

maint()
{
int 2darray[12][6];

2darray = functie();

return 0;
}

int functie(void)y
{
int temparry[12][6];

for (x=0; ......
{

open bestand. lees alles in array etc. etc.

return array;

}

Nou is bovenstaande een stukje pseudo code maar het id is als volgt.
Door een functie wordt een tekst file ingelezen. (dit werkt).
Maar nu wil ik via return een 2 demensionaal array terug sturen aan main.
dit werkt dus niet ofzo. krijg hele tijd fouten.

vraag: is dit wel mogelijk: een array via return terug sturen in een array in de main?

bvd.

Vincent

Gelieve je code in 't vervolg tussen code-tags te plaatsen, dat leest stukken beter

[ Voor 8% gewijzigd door whoami op 11-11-2005 10:33 ]

AMD 80mzh, 428mb hd, soundblaster 16 clone, hitachi 8x dvd + Creative DXR2, 16mb FastPage Ram


  • Reptile209
  • Registratie: Juni 2001
  • Laatst online: 20:45

Reptile209

- gers -

Ja, dat is mogelijk. Maar in C gaat dat via een pointer (google that :) ) en dat is iets dat je jezelf goed eigen moet maken om effectief in C te kunnen werken. Je functiedefinitie wordt dan iets als:
code:
1
int **functie(void)


Edit: Eh, ja, wat Daos en Voutloos hieronder zeggen. :)
Als je je array pas in de functie declareert, mag je hem daarbuiten niet meer gebruiken. Daar krijg je hele vieze en vervelende bugs van. Declareer een array in main (of in de aanroepende functie), geef een pointer naar de array aan je functie, doe je ding en dan hoef je ook niks meer terug te geven (behalve bijvoorbeeld een foutcode) want de array is al bekend bij de aanroepende functie.

[ Voor 50% gewijzigd door Reptile209 op 10-11-2005 21:34 ]

Zo scherp als een voetbal!


  • Daos
  • Registratie: Oktober 2004
  • Niet online
nee, dat gaat niet werken. Je moet dat array meegeven als argument aan je functie.

[edit]
Zoiets dus:
C:
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
#include <stdio.h>
void functie(int[][]);

int main() {
  int tweedarray[12][6];

  functie(tweedarray);

  return 0;
}

void functie(int temparray[][6]) {
  int x;
  for (x=0; ...... ) {
  }

  open bestand. lees alles in array etc. etc.
}

Meer uitleg hierover vind je in elk boek over C(++).
offtopic:
Gebruik voortaan codetags in je post.

[ Voor 75% gewijzigd door Daos op 10-11-2005 21:44 ]


  • Voutloos
  • Registratie: Januari 2002
  • Niet online
Daos schreef op donderdag 10 november 2005 @ 21:30:
nee, dat gaat niet werken. Je moet de pointer naardat array meegeven als argument aan je functie.
;)

{signature}


  • MisterData
  • Registratie: September 2001
  • Laatst online: 09-04 12:07
Als je C++ zou kunnen gebruiken kun je misschien beter een std::vector< std::string > returnen, dat is een stuk makkelijker en veiliger :)

  • vinietje
  • Registratie: Januari 2001
  • Laatst online: 04-04 15:08
Helaas, kan alleen c gebruiken.

maar het is dus niet mogelijk een lokaal gedefinierd array via return in een main array over te zetten?

AMD 80mzh, 428mb hd, soundblaster 16 clone, hitachi 8x dvd + Creative DXR2, 16mb FastPage Ram


  • Reptile209
  • Registratie: Juni 2001
  • Laatst online: 20:45

Reptile209

- gers -

vinietje schreef op donderdag 10 november 2005 @ 21:34:
Helaas, kan alleen c gebruiken.

maar het is dus niet mogelijk een lokaal gedefinierd array via return in een main array over te zetten?
Dat kan wel (hint: new), maar het is niet echt netjes en tamelijk foutgevoelig, zeker bij beginnende programmeurs (zoals ik gok dat jij bent) ;). Het is veel makkelijker om dat buiten je functie te houden.

Zo scherp als een voetbal!


  • Soultaker
  • Registratie: September 2000
  • Laatst online: 23-04 02:19
Ten eerste moet je onderscheid maken tussen een jagged array en een 'echte' twee-dimensionale array. De eerste is een array van pointers naar arrays en heeft bijvoorbeeld type int**; de andere is een echte array van arrays en heeft bijvoorbeeld type int(*)[6].

Een jagged array ziet er in het geheugen zo uit:
code:
1
2
3
4
5
6
7
8
+---+     +---+---+---+
| 0 | ==> | a | b | c |     
+---+     +---+---+---+     +---+---+---+
| 1 | ====================> | d | e | f |
+---+     +---+---+---+     +---+---+---+
| 2 | ==> | g | h | i |
~~~~~     +---+---+---+
 etc.

Elke rij (of kolom) uit je matrix zit dus in een opvolgend stuk geheugen. Dat betekent dat niet elke rij even lang hoeft te zijn en je hoeft bij het compileren nog niet te weten welke dimensies je array krijgt.

Een 'echte' 2D array ziet er zo uit:
code:
1
2
3
+---+---+---++---+---+---++---+---+~
| a | b | c || d | e | f || g | h |~ etc.
+---+---+---++---+---+---++---+---+~

Daarbij zitten dus alle waarden in het geheugen en moet je wel bij het compileren alle dimensies (behalve één) specificeren.

In beide gevallen kun je een array niet direct retourneren omdat het geen volwaardig datatype is (een array vervalt naar een pointer als je 'm wil retourneren). Als de array een vaste afmeting heeft, is een mogelijke oplossing om een struct te definiëren met daarin de array. Die kun je wel retourneren.

Een andere veelgebruikte methode is dat de caller de afmetingen en een pointer naar de array meegeeft en dat jouw functie 'm alleen maar invult.

  • .oisyn
  • Registratie: September 2000
  • Laatst online: 24-04 11:12

.oisyn

Moderator Devschuur®

Demotivational Speaker

vinietje schreef op donderdag 10 november 2005 @ 21:34:
Helaas, kan alleen c gebruiken.

maar het is dus niet mogelijk een lokaal gedefinierd array via return in een main array over te zetten?
Nee, hij is immers lokaal en bestaat daarna niet meer.
(hint: je bedoelt malloc ;))

[ Voor 81% gewijzigd door .oisyn op 10-11-2005 21:37 ]

Give a man a game and he'll have fun for a day. Teach a man to make games and he'll never have fun again.


  • Reptile209
  • Registratie: Juni 2001
  • Laatst online: 20:45

Reptile209

- gers -

offtopic:
* Reptile209 zegt niks meer en zwengelt voor het eerst in jaaaaren weer eens een C-compiler aan voordat hij nog wat zegt :+

Zo scherp als een voetbal!


  • Voutloos
  • Registratie: Januari 2002
  • Niet online
Als we dan toch zoektermen strooien, wijs ik TS er bij deze maar op dat malloc() gepaard gaat met free(). :P

{signature}


  • NMe
  • Registratie: Februari 2004
  • Laatst online: 15-04 22:07

NMe

Quia Ego Sic Dico.

Bij arrays vind ik het persoonlijk altijd fijner om calloc te gebruiken in plaats van malloc. Ten eerste omdat die daar eigenlijk voor gemaakt is, en ten tweede omdat calloc meteen elk element initialiseert op 0. :P

Maar is dat initialiseren niet nodig, dan zou je in principe wegens snelheidsoverwegingen beter malloc kunnen gebruiken. :P

'E's fighting in there!' he stuttered, grabbing the captain's arm.
'All by himself?' said the captain.
'No, with everyone!' shouted Nobby, hopping from one foot to the other.


  • epic007
  • Registratie: Februari 2004
  • Laatst online: 11-03 09:21
In C++ lukt het wel via een "vieze" cast
C++:
1
2
3
4
int size = 12*6*sizeof(int);
char * pointer = new char[size];
int (&array2d)[12][6] = *(int(*)[12][6])pointer;
// pointer en array2d verwijzen nu naar hetzelfde stuk geheugen

  • .oisyn
  • Registratie: September 2000
  • Laatst online: 24-04 11:12

.oisyn

Moderator Devschuur®

Demotivational Speaker

In C++ heb je die cast niet nodig
C++:
1
int (*array)[6] = new int[12][6];


Bovendien gaat jouw code gruwelijk fout als je een multidimensional array wil maken van custom types met een constructor, omdat die dan niet aangeroepen worden en je 'm bovendien niet meer kunt delete[]'en (alleen door terug te casten naar een char*, en dan runnen er weer geen destructors)

[ Voor 71% gewijzigd door .oisyn op 11-11-2005 11:33 ]

Give a man a game and he'll have fun for a day. Teach a man to make games and he'll never have fun again.


  • Soultaker
  • Registratie: September 2000
  • Laatst online: 23-04 02:19
@.oisyn: als je die syntax niet kent (de syntax voor multi-dimensionale arrays en functie-pointers vinden veel mensen - terecht - moeilijk) kun je altijd nog 'new T[12*6]' doen en dat casten. Dan worden alle constructors netjes aangeroepen en kun je (na terugkasten naar T*) ook met delete[] alles netjes opruimen.

Voor anderen: kijk nog even naar mijn eerdere post over de geheugenlay-out van multidimensionale arrays. Die komt overeen met die van enkele arrays en de casts zijn dus alleen nodig zodat de compiler hetzelfde geheugen anders interpreteert.

  • .oisyn
  • Registratie: September 2000
  • Laatst online: 24-04 11:12

.oisyn

Moderator Devschuur®

Demotivational Speaker

Soultaker schreef op vrijdag 11 november 2005 @ 16:39:
@.oisyn: als je die syntax niet kent (de syntax voor multi-dimensionale arrays en functie-pointers vinden veel mensen - terecht - moeilijk) kun je altijd nog 'new T[12*6]' doen en dat casten. Dan worden alle constructors netjes aangeroepen en kun je (na terugkasten naar T*) ook met delete[] alles netjes opruimen.
Mijn punt was echter dat epic007 die syntax klaarblijkelijk wél kent, maar het alsnog met een omweg doet die niet safe is. En ook jouw manier hoeft niet safe te zijn, wie zegt dat een implementatie het aantal objecten in een multidimensionale array op dezelfde manier in het geheugen zet als bij een enkele array? Wellicht zet hij elke dimensie wel apart in het geheugen. Ook van jouw oplossing heb je dus geen keiharde garantie dat het werkt.

Give a man a game and he'll have fun for a day. Teach a man to make games and he'll never have fun again.


  • MSalters
  • Registratie: Juni 2001
  • Laatst online: 09-04 22:08
Nou is dat laatste geen probleem: een array, hoeveel dimensies die ook heeft, is 1 object, en dus een enkel blok geheugen. Elke dimensie apart mag alleen bij arrays-van-arrays (de "jagged" versies), en dat zijn geen multidimensionale arrays.

Man hopes. Genius creates. Ralph Waldo Emerson
Never worry about theory as long as the machinery does what it's supposed to do. R. A. Heinlein


  • Soultaker
  • Registratie: September 2000
  • Laatst online: 23-04 02:19
.oisyn schreef op vrijdag 11 november 2005 @ 17:00:
En ook jouw manier hoeft niet safe te zijn, wie zegt dat een implementatie het aantal objecten in een multidimensionale array op dezelfde manier in het geheugen zet als bij een enkele array?
Voor zover ik weet is de compiler dat nu juist wel verplicht. (Als die layout niet vaststond zou ik er niet over beginnen in mijn uitleg eerder.) Gaat dus wel goed; maar wijs me gerust op de passage in de standaard die het tegendeel beweert. ;)

  • .oisyn
  • Registratie: September 2000
  • Laatst online: 24-04 11:12

.oisyn

Moderator Devschuur®

Demotivational Speaker

Ik bedoel niet de layout van de items in de array, maar het getalletje dat aangeeft hoeveel items er in de array staan (welke bij destruction weer wordt gebruikt). Ook dat staat meestal in het stuk geheugen, en dat hoeft volgens mij niet per se hetzelfde te zijn voor enkele en multidimensionale arrays

[ Voor 8% gewijzigd door .oisyn op 12-11-2005 16:37 ]

Give a man a game and he'll have fun for a day. Teach a man to make games and he'll never have fun again.


  • Soultaker
  • Registratie: September 2000
  • Laatst online: 23-04 02:19
Ja natuurlijk, maar dat maakt niet uit als je 'm maar weer terugcast voordat je er delete[] op uitvoert. (Ik neem aan dat je bedoelt dat die i.h.a. niet veilig is: delete((B*)(new A))). Als je 'm hebt gealloceerd als ééndimensionale array, dan kun je 'm ook vrijgeven als ééndimensionale array.

In de praktijk denk ik trouwens dat de memory allocator geen onderscheid maakt tussen ééndimensionale en meerdimensionale arrays, maar goed, het gaat om het principe. :) Verder mag de memory allocator afaik helemaal zelf weten waar 'ie z'n bookkeeping doet, dus aannemen dat er getalletjes in je blok geheugen komen is natuurlijk ook niet de bedoeling.

[ Voor 65% gewijzigd door Soultaker op 12-11-2005 16:58 ]


  • .oisyn
  • Registratie: September 2000
  • Laatst online: 24-04 11:12

.oisyn

Moderator Devschuur®

Demotivational Speaker

Soultaker schreef op zaterdag 12 november 2005 @ 16:56:
Ja natuurlijk, maar dat maakt niet uit als je 'm maar weer terugcast voordat je er delete[] op uitvoert. (Ik neem aan dat je bedoelt dat die i.h.a. niet veilig is: delete((B*)(new A))). Als je 'm hebt gealloceerd als ééndimensionale array, dan kun je 'm ook vrijgeven als ééndimensionale array.
Daar heb je idd gelijk in.
Verder mag de memory allocator afaik helemaal zelf weten waar 'ie z'n bookkeeping doet, dus aannemen dat er getalletjes in je blok geheugen komen is natuurlijk ook niet de bedoeling.
Ik zei ook "meestal" :). Hij kan natuurlijk net zo goed ergens een std::map<void*, size_t> oid bijhouden, mijn punt was meer dat een implementatie ervoor kon kiezen om dat verschillend te doen voor enkele en meerdimensionale arrays. Waarom moet je me niet vragen, maar zoals je zei, het gaat om het principe ;)

Give a man a game and he'll have fun for a day. Teach a man to make games and he'll never have fun again.

Pagina: 1