[C] Array in struct afhankelijk van input struct zelf...

Pagina: 1
Acties:

Acties:
  • 0 Henk 'm!

  • Chip.
  • Registratie: Mei 2006
  • Niet online
Voor een project van school moeten we een lift controller maken in C..

nu heb ik de volgende struct...
C:
1
2
3
4
5
6
7
8
typedef struct {
    unsigned int id, maxWeight;
    int fd, strLevel, endLevel, curLevel;
    char dir;
    bool door, moving;
} LiftDataType;

typedef LiftDataType* LiftType;

(bool is eigengemaakte enum type ;))

nu wil ik eigenlijk dat bij deze struct nog een variable bij doen namelijk level[], wat dus een array is. Alleen hoe groot deze array is is afhankelijk van het start level en het eind level van de lift... de array moet dus eind-start elementen hebben... alleen hoe kan ik deze bijvoegen in me struct??? En dat wanneer ik dan

C:
1
LiftType lift = {id, maxWeight, fd, strLevel, endLevel, curLevel, dir, door, moving}


doe dat dan de grootte van level[] gedefinieerd wordt...

Acties:
  • 0 Henk 'm!

  • Elijan9
  • Registratie: Februari 2004
  • Laatst online: 20-09 18:03
Een variable-size-array is niet mogelijk in een struct. De offsets van elk element van de struct moeten namelijk al tijdens het compileren bekend zijn, ongeacht de data in de struct.

Wat wel een vaste size heeft is of een array met een vaste grootte, of een pointer naar een array...

War is when the young and stupid are tricked by the old and bitter into killing each other. - Niko Bellic


Acties:
  • 0 Henk 'm!

  • MLM
  • Registratie: Juli 2004
  • Laatst online: 12-03-2023

MLM

aka Zolo

Je gaat sowieso geen variable size wat dan ook kunnen krijgen zonder malloc() oid. Wat je wel kan doen is gewoon een maximum hoeveelheid levels hebben, en ruimte voor dat maximum aanmaken in je struct. Heb je geen optimaal geheugengebruik, maar het werkt wel vrij simpel :)

-niks-


Acties:
  • 0 Henk 'm!

  • Elijan9
  • Registratie: Februari 2004
  • Laatst online: 20-09 18:03
MLM schreef op donderdag 09 april 2009 @ 16:29:
Je gaat sowieso geen variable size wat dan ook kunnen krijgen zonder malloc() oid.
Wel met C99. Dan kun je wel variable-length-arrays hebben, maar nooit in een struct, wel in een functie of binnen een vaste scoop:
C:
1
2
3
4
int do_something(int size) {
    unsigned int array[size * 2];
    ...
}

War is when the young and stupid are tricked by the old and bitter into killing each other. - Niko Bellic


Acties:
  • 0 Henk 'm!

  • farlane
  • Registratie: Maart 2000
  • Laatst online: 22-09 22:17
Wat wel eens wordt gedaan is een array met 1 element opnemen aan het einde van de struct, en vervolgens met malloc ruimte reserveren voor de struct + het aantal arrayelementen.

Dit werkt echter alleen als het variabele array aan het einde van de struct kan staan.

Somniferous whisperings of scarlet fields. Sleep calling me and in my dreams i wander. My reality is abandoned (I traverse afar). Not a care if I never everwake.


Acties:
  • 0 Henk 'm!

  • .oisyn
  • Registratie: September 2000
  • Laatst online: 22-09 16:37

.oisyn

Moderator Devschuur®

Demotivational Speaker

Wel opletten dat je je struct daarna niet meer in een array kunt zetten :)

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.


Acties:
  • 0 Henk 'm!

  • PaveloW
  • Registratie: September 2005
  • Laatst online: 22-09 16:54
.oisyn schreef op vrijdag 10 april 2009 @ 11:51:
Wel opletten dat je je struct daarna niet meer in een array kunt zetten :)
Natuurlijk wel als je bijhoudt hoe groot de uiteindelijke totale grote van elke gecreerde struct inclusief de levels is. Vereist wel iets meer werk/aandacht maar zou alsnog wel kunnen.

Acties:
  • 0 Henk 'm!

  • Woy
  • Registratie: April 2000
  • Niet online

Woy

Moderator Devschuur®
PaveloW schreef op vrijdag 10 april 2009 @ 12:04:
[...]

Natuurlijk wel als je bijhoudt hoe groot de uiteindelijke totale grote van elke gecreerde struct inclusief de levels is. Vereist wel iets meer werk/aandacht maar zou alsnog wel kunnen.
Je kunt natuurlijk niet meer de normale syntax gebruiken, aangezien de size van alle elementen verschillend is ( en de compiler dat niet kan weten ). Een array van pointers is dan nuttiger.

“Build a man a fire, and he'll be warm for a day. Set a man on fire, and he'll be warm for the rest of his life.”


Acties:
  • 0 Henk 'm!

  • .oisyn
  • Registratie: September 2000
  • Laatst online: 22-09 16:37

.oisyn

Moderator Devschuur®

Demotivational Speaker

PaveloW schreef op vrijdag 10 april 2009 @ 12:04:
[...]

Natuurlijk wel als je bijhoudt hoe groot de uiteindelijke totale grote van elke gecreerde struct inclusief de levels is. Vereist wel iets meer werk/aandacht maar zou alsnog wel kunnen.
Nee, je hebt dan geen goed indexeerbare array meer. Je kunt niet zeggen: oh, het derde element, dat staat op plek array[2]. Natuurlijk kun je ze wel achter elkaar in het geheugen hebben staan, maar een array van pointers voor de indexatie is dan toch handiger.

.edit: euh ja, dat zei Woy dus al 8)7

[ Voor 3% gewijzigd door .oisyn op 10-04-2009 12:46 ]

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.


Acties:
  • 0 Henk 'm!

  • PaveloW
  • Registratie: September 2005
  • Laatst online: 22-09 16:54
Ik zat geloof ik veels te moeilijk te denken....

Acties:
  • 0 Henk 'm!

  • Reptile209
  • Registratie: Juni 2001
  • Laatst online: 12:24

Reptile209

- gers -

Ik probeer te bedenken wat je - gezien vanuit een lift-object - in een array op zou willen slaan. Kan je dat eens toelichten? Misschien dat je het met een ander datatype beter op kunt lossen.

Daarnaast zou ik je aanraden om je booleans 'door' en 'moving' wat duidelijkere namen te geven. Als 'door' de waarde true heeft, is de deur dan open, aanwezig, dicht, geel? Iets als 'isDoorClosed' is al veel duidelijker. Idem met 'moving' versus 'isMoving'.

Zo scherp als een voetbal!


Acties:
  • 0 Henk 'm!

  • Chip.
  • Registratie: Mei 2006
  • Niet online
farlane schreef op vrijdag 10 april 2009 @ 10:24:
Wat wel eens wordt gedaan is een array met 1 element opnemen aan het einde van de struct, en vervolgens met malloc ruimte reserveren voor de struct + het aantal arrayelementen.

Dit werkt echter alleen als het variabele array aan het einde van de struct kan staan.
Maar dat kan toch niet wanneer het aantal array elementen afhankelijk is van de struct zelf...

C:
1
2
3
4
5
6
7
8
typedef struct {
    unsigned int id, maxWeight;
    int fd, strLevel, endLevel, curLevel, offsetBit;
    char direction;
    bool isDoorOpen, isMoving;
    int levels[1] = {false}; 
    // levels moet uiteindelijk de grootte krijgen van levels[endLevel - strLevel]
} LiftDataType;


Dus zeg maar de grootte van de array is dus afhankelijk van de array die ik invoer... zover ik weet kan ik ook geen (default?) element eigenlijk toevoegen in een array binnen een struct in C...

Hetgene wat ik in die array wil opslaan is op welke verdieping een aanvraag is gedaan (waarbij de index van de array dus de verdieping is (samen met de startLevel erbij opgeteld dus). Ik kan ook simpel een globale array maken aangezien het programma toch maar voor 1 lift hoeft te werken, maar ik wil dus graag voor N liften werkend hebben (:
en om nou N globale arrays te maken...

En ik reserveer trouwens toch al ruimte voor me struct bij het aanmaken van me object omdat ik alles op de addresse (zeg ik dat correct) opsla...

C:
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
typedef struct {
    unsigned int id, maxWeight;
    int fd, strLevel, endLevel, curLevel, offsetBit;
    char direction;
    bool isDoorOpen, isMoving;
} LiftDataType;

typedef LiftDataType* LiftType;

LiftType createLift(const unsigned int id, ...)
{
    LiftType lift;
    lift = (LiftType) malloc(sizeof(LiftDataType));

    lift->id = id;
    lift->maxWeight = maxWeight;
    ...
    return lift;
}

[ Voor 17% gewijzigd door Chip. op 10-04-2009 22:43 ]


Acties:
  • 0 Henk 'm!

  • Emmeau
  • Registratie: Mei 2003
  • Niet online

Emmeau

All your UNIX are belong to us

welke versie van C is get die je gebruikt?

in C++ kan je aan een struct een constructor hangen en dan zou je probleem opgelost zijn.

If you choose to criticise you choose your enemies


Acties:
  • 0 Henk 'm!

  • Chip.
  • Registratie: Mei 2006
  • Niet online
We gebruiken de gcc compiler (heb je waarschijnlijk niks aan?) Welke versie echter precies weet ik niet moet ik navragen op school volgende week.

Heb trouwens even me code online gezet voor diegene die het willen zien.. http://plaatscode.be/134060/

[ Voor 26% gewijzigd door Chip. op 11-04-2009 00:17 ]


Acties:
  • 0 Henk 'm!

  • farlane
  • Registratie: Maart 2000
  • Laatst online: 22-09 22:17
Wouser schreef op vrijdag 10 april 2009 @ 21:55:
Maar dat kan toch niet wanneer het aantal array elementen afhankelijk is van de struct zelf...
Je moet bij het instantieren van de struct weten hoe groot het moet worden, weet je dat niet dan kun je van die level natuurlijk een gemalloc'ed array maken. ( Alhoewel dat volgens mij hier niet nodig is aangezien het aantal verdiepingen niet echt zal gaan varieren )

Misschien moet je trouwens eerst even over je design nadenken, ik krijg het idee dat je nog niet helemaal weet waar het naar toe moet gaan.

Somniferous whisperings of scarlet fields. Sleep calling me and in my dreams i wander. My reality is abandoned (I traverse afar). Not a care if I never everwake.


Acties:
  • 0 Henk 'm!

  • Chip.
  • Registratie: Mei 2006
  • Niet online
Nou ik zat dus zelf al te denken aan grote gebouwen waarbij niet iedere lift op 0 begint maar op 0 en vervolgens op verdieping 25 moet overstappen op een andere lift om naar 50 (of hoger hoeft dus niet perse met sprongen van 25 te gaan) te komen zeg maar dus in mijn inzicht varieert het aantal verdiepingen wel. Anders had ik die startLevel en eindLevel niet in me struct gezet.

Maar als ik dus zeg maar al in me functie waarin ik me object aanmaak eet hoe groot de array moet zijn kan ik dus ook de array grootte definiëren?
C:
1
LiftType createLift(const unsigned int id, ...) 

Want als input van me functie heb ik ook strLevel + endLevel de 2 waardes die de grootte van de array definiëren. Dit zou ik dus ook als parameter aan de struct kunnen meegeven... maar ander vraagje dan (hoe programmeer je dat :$)

Acties:
  • 0 Henk 'm!

  • farlane
  • Registratie: Maart 2000
  • Laatst online: 22-09 22:17
Als je een start en eindlevel gebruikt als administratie maakt het iig niet uit hoe groot de storage is voor je levels array maargoed, het gaat om een dergelijke methode:

C++:
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
26
27
28
29
30
struct BuggerStruct
{
    int     OneBogus;
    float   AnotherBogus;
    int     VariableSize;
    int     Levels[ 1 ];
};

BuggerStruct* CreateTheBugger( unsigned int VariableSize )
{
    size_t TotalSize = sizeof( BuggerStruct ) + ( VariableSize - 1 ) * sizeof( int );

    BuggerStruct* RetVal = ( BuggerStruct* ) malloc( TotalSize );

    RetVal->VariableSize  = VariableSize;

    return  RetVal; 
}

void TestTheBugger( void )
{
    BuggerStruct* Bugger = CreateTheBugger( 10 );
    
    for( int i = 0; i < Bugger->VariableSize; ++i )
        Bugger->Levels[ i ] = i;

    // ... stuff ...

    free( Bugger );
}


Mag je zelf C code van maken :P

Somniferous whisperings of scarlet fields. Sleep calling me and in my dreams i wander. My reality is abandoned (I traverse afar). Not a care if I never everwake.


Acties:
  • 0 Henk 'm!

  • Chip.
  • Registratie: Mei 2006
  • Niet online
farlane schreef op zaterdag 11 april 2009 @ 11:34:
Als je een start en eindlevel gebruikt als administratie maakt het iig niet uit hoe groot de storage is voor je levels array maargoed, het gaat om een dergelijke methode:
Allereerst harstikke bedankt voor je stukje code ga straks als ik op me kamer ben uitproberen. Verder snap ik niet helemaal wat je bedoelt met je eerste zin, ik zal hem even beantwoorde hoe jij bedoelt denk ik...

Maar de grootte van me storage moet toch de grootte hebben van eindlevel - startlevel ik ga toch immers de grootte niet groter (of kleiner) maken als ik die levels niet heb?

[ Voor 4% gewijzigd door Chip. op 11-04-2009 12:13 ]


Acties:
  • 0 Henk 'm!

  • farlane
  • Registratie: Maart 2000
  • Laatst online: 22-09 22:17
Wouser schreef op zaterdag 11 april 2009 @ 12:12:
Maar de grootte van me storage moet toch de grootte hebben van eindlevel - startlevel ik ga toch immers de grootte niet groter (of kleiner) maken als ik die levels niet heb?
Stel je moet een liftbesturing bouwen voor een gebouw met 150 verdiepingen, dan kun je alle liften die je hebt een array geven van 150, waarbij je per lift met je level administratie bijhoudt of de lift daar ook kan komen of niet. ( Die had je toch al nodig )
Je kunt dan idd een aantal liften hebben waarbij je array niet helemaal wordt gebruikt, maar of dat een probleem is valt nog maar te bezien.

Somniferous whisperings of scarlet fields. Sleep calling me and in my dreams i wander. My reality is abandoned (I traverse afar). Not a care if I never everwake.


Acties:
  • 0 Henk 'm!

  • MLM
  • Registratie: Juli 2004
  • Laatst online: 12-03-2023

MLM

aka Zolo

tbh, waarom doe je moeilijk met variable size structs etc. Je kan prima een fixed size struct maken.

Uit de losse pols:
C:
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
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
typedef int LevelDataType; //Maak er iets leuks van

typedef struct { 
    unsigned int id, maxWeight; 
    int fd, strLevel, endLevel, curLevel; 
    char dir; 
    bool door, moving; 
    LevelDataType *level;
} LiftDataType; 

typedef LiftDataType* LiftType;

LiftType CreateLiftType(int strLevel, int endLevel /* meer argumenten als je die wilt */)
{
  //Locals
  int numLevel;
  size_t szLevel;
  LiftType result;

  //Maak en vul result
  result = (LiftType)malloc(sizeof(LiftDataType));
  result->strLevel = strLevel;
  result->endLevel = endLevel;
  /* initialiseer de rest van je struct */

  //Maak ruimte voor levels aan
  numLevel = endLevel - strLevel + 1; //+1 omdat ik >>DENK<< dat je endLevel ook wilt gebruiken
  szLevel = sizeof(LevelDataType) * numLevels; //aantal bytes benodigd
  result->level = (LevelDataType *)malloc(szLevel);

  //Hier wil je je LevelDataTypes initialiseren waarschijnlijk
  
  //Klaar!
  return result;
}

void DestroyLiftType(LiftType lift)
{
  if(!lift) return;
  free(lift->level);
  free(lift);
}

LevelDataType *GetLevel(LiftType lift, int level)
{
  //Retardcheck
  if(!lift) return 0;

  //Controleer of dit level wel bereikbaar is door de lift
  if(lift->strLevel > level || lift->endLevel < level) return 0;

  //Retourneer juiste level
  return &(lift->level[level - lift->strLevel]);
}


De Create/Destroy functies gebruik je om LiftTypes aan te maken, de GetLevel() functie is een voorbeeldje over hoe je het kan gebruiken.

-niks-

Pagina: 1