[C] Pointers & Inhouden van pointers

Pagina: 1
Acties:
  • 166 views sinds 30-01-2008
  • Reageer

  • ThaStealth
  • Registratie: Oktober 2004
  • Laatst online: 27-11 13:59
Hallo,
Ik moet voor school een snoepautomaat nabootsen als project. Aangezien het nu vrijdag na 12 uur is, zijn alle docenten dus bij de vrouw en kids en worden we aan ons lot overgelaten.......
Ik heb een vraag mbt. de benadering van pointers en de benadering van de inhoud van pointers, Ik heb de volgende functie ontwikkeld, deze stopt een event (enum) in een mailBox object, naast dat deze het event in een mailBox duwt kan hij ook nog data (hetzij een enum van Snoep, hetzij een double geldbedrag zijn) in een ander mailBox.

C:
1
2
3
4
5
6
7
8
9
void sendEvent_Automaat(Automaat* automaatje, AutomaatEvents e, void* data){
 put_mailBox(&((*automaatje)->automaatMail),&e);
 if (e == ProductknopInduwen){
  put_mailBox(&((*automaatje)->productMail),(Snoep*) data);
 }
 if (e == GeldInwerpen){
    put_mailBox(&((*automaatje)->geldMail),(double*) data);
 }
}

een andere threat leest deze mailbox van tijd tot tijd uit en gaat dan hierop reageren, eventueel met de bijgevoegde data. Hieronder word bijvoorbeeld als er een geldInworpEvent is opgetreden

C:
1
2
3
4
5
6
7
8
9
10
static void GeldInworp(void* automaatje){
 Automaat* mAutomaat = (Automaat*) automaatje;
 double  inworp;
  get_mailBox(&(*mAutomaat)->geldMail,&inworp);
 (*mAutomaat)->saldo +=  (inworp);

              char test[100];
 sprintf(test,"%.2f",&((*mAutomaat)->saldo));
   (*mAutomaat)->disp(test);
}

ik lees dus uit de mailbox de waarde die ik net erin gestopt heb, en ga hiermee aan de slag. Het enige probleem is dat ik dus ipv 0,05 0,10 0,20 etc. waardes er getallen ala 3.12 * 10^40 uitkrijg. Duidelijk is dus dat ik ergens een fout(je) heb zitten mbt het doorgeven van een pointer of inhoud van een geheugenhokje

Aangezien ik pas sinds een paar weken met C aan de gang ben (van te voren met C#, die zo lief is voor mij om het geheugengebeuren zelf te fixen) heb ik niet echt een id waar ik mee bezig ben qua geheugen adressering en pointerverhalen. Dus wees aub mild :P

Ow en dan nog een ander vraagje,
Ik stop die snoepmerken (Mars, Snikkers, Twix) in een enum, maar aangezien ik van mijn invoer een string krijg met deze waardes moet ik 1 van de twee natuurlijk omzetten naar de juiste waarde, hoe kan ik dit het beste doen? via een switch of typecasten?

[ Voor 7% gewijzigd door RobIII op 23-03-2007 18:36 . Reden: Code tags toegevoegd ]

Mess with the best, die like the rest


  • RobIII
  • Registratie: December 2001
  • Niet online

RobIII

Admin Devschuur®

^ Romeinse Ⅲ ja!

(overleden)
offtopic:
Als je code post, gebruik dan [code] tags a.u.b. Dat maakt het een stuk leesbaarder.

[ Voor 4% gewijzigd door RobIII op 23-03-2007 18:35 ]

There are only two hard problems in distributed systems: 2. Exactly-once delivery 1. Guaranteed order of messages 2. Exactly-once delivery.

Je eigen tweaker.me redirect

Over mij


Verwijderd

Lijkt me dat het probleem zit in bijv
C:
1
&((*automaatje)->geldMail)


Je kunt op een aantal manieren 'geldMail' opvragen van 'automaatje', maar wat jij doet is toch wel een beetje raar :P Jij vraagt dmv '&' nog eens om het adres van automaatje->geldMail. Sowieso begrijp ik de constructie van eerst dereferencen van 'automaatje' dmv '*' en dan '->' gebruiken niet helemaal 8)7
C:
1
2
automaatje->geldMail; // dit werkt
(*automaatje).geldMail; // dit ook 

[ Voor 14% gewijzigd door Verwijderd op 23-03-2007 18:47 ]


  • ThaStealth
  • Registratie: Oktober 2004
  • Laatst online: 27-11 13:59
tnx Roblll, kon het niet vinden in de GUI en dacht dat het er niet was (silly me)

C:
1
automaatje->geldMail;

geeft de volgende foutmelding:
[C++ Error] BCAutomaat.c(210): E2288 Pointer to structure required on left side of -> or ->* (hij zegt wel C++ error, maar is echt C)

Hier even de headers van put_mailBox en get_mailBox:
C:
1
2
void put_mailBox(mailBox* b,void* mess);
void get_mailBox(mailBox* b,void* mess);

Denk dat ie het niet slikt omdat ie een pointer? verwacht, ik roep ook mijn struct 'automaatje' overal op de volgende manier aan:

(*automaatje)->Status = IDLE;
(*automaatje)->Saldo = 2.10;

Mess with the best, die like the rest


Verwijderd

code:
1
&((*mAutomaat)->saldo)


je behandelt hier de inhoud van mAutomaat als een pointer, je vraagt uit de inhoud van die pointer het "saldo"-element op en vraagt daar het adres van op ? is dat wel wat je wil ?

als saldo geen pointer is dan denk ik dat je dit wil:
code:
1
2
mAutomaat->saldo
//zelfde als (*mAutomaat).saldo


edit: zoals Waltor dus al zei :)

[ Voor 26% gewijzigd door Verwijderd op 23-03-2007 18:54 ]


Verwijderd

ThaStealth schreef op vrijdag 23 maart 2007 @ 18:49:

Denk dat ie het niet slikt omdat ie een pointer? verwacht, ik roep ook mijn struct 'automaatje' overal op de volgende manier aan:

(*automaatje)->Status = IDLE;
(*automaatje)->Saldo = 2.10;
Als ik dat probeer krijg ik een melding van deze aard: left operand has 'struct' type, use '.'
Precies wat ik al zei dus... Lees anders even een tutorial over pointers door, of check dit http://cslibrary.stanford.edu/104/ :)

[ Voor 10% gewijzigd door Verwijderd op 23-03-2007 19:02 ]


  • ThaStealth
  • Registratie: Oktober 2004
  • Laatst online: 27-11 13:59
Denk dat ik hier en daar wat weggelaten heb, daarom post ik de struct ook ff mee:

Deze zit in de .h file
C:
1
typedef struct _automaat* Automaat;


Hetvolgende zit in de C file:

C:
1
2
3
void create_automaat(Automaat* automaatje,void (*disp)(char*, char*)){
* automaatje=(struct _automaat*)malloc(sizeof(struct _automaat)); //constructor aanroep
}


C:
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
struct _automaat{
   int automaatid;
   char * Productnamen[9];
   int Productinformatie[9][2];
   double Productkosten[9];
   Persistentie Persistent;
   int aantalWisselMunten[5];
   task* AutomaatController;
   AutomaatStatus Status;
   mailBox automaatMail,productMail, geldMail;
   Snoep HuidigProduct;
      char bericht[100];
   double saldo;
   void (*dispay)(char*, char*);
};


En deze word vanuit de parent aangeroepen op het hele ding:
code:
1
 create_automaat((&((*Aanschaf)->MijnAutomaat)),disp);


als ik (*automaatje)-> gebruik doet hij het perfect, op andere manieren krijg ik of runtime errors of compile errors..

Mess with the best, die like the rest


  • Arjan
  • Registratie: Juni 2001
  • Niet online

Arjan

copyright is wrong

ThaStealth schreef op vrijdag 23 maart 2007 @ 19:03:
[...]

En deze word vanuit de parent aangeroepen op het hele ding:
code:
1
 create_automaat((&((*Aanschaf)->MijnAutomaat)),disp);

[..]
code:
1
2
3
( &((*Aanschaf)->MijnAutomaat) )
&( (*Aanschaf)->MijnAutomaat )
&(*Aanschaf)->MijnAutomaat
ThaStealth schreef op vrijdag 23 maart 2007 @ 19:03:[...]
als ik (*automaatje)-> gebruik doet hij het perfect, op andere manieren krijg ik of runtime errors of compile errors..
Als Aanschaf een pointer naar een pointer is klopt dat wel ja ;)
C++:
1
2
3
4
5
6
7
8
9
int main() {
    int a = 1;
    int *b = &a;
    int **c = &b;

    std::cout << "a = " << *(*c) << std::endl;

    return 0;
}

oprecht vertrouwen wordt nooit geschaad


  • Daos
  • Registratie: Oktober 2004
  • Niet online
ThaStealth schreef op vrijdag 23 maart 2007 @ 19:03:

C:
1
typedef struct _automaat* Automaat;
Automaat is dus een pointer naar een _automaat structure.
C:
1
2
3
void create_automaat(Automaat* automaatje,void (*disp)(char*, char*)){
* automaatje=(struct _automaat*)malloc(sizeof(struct _automaat)); //constructor aanroep
}
automaatje is een pointer naar een Automaat en dus pointer naar een pointer naar een _automaat structure.
Dat is (alleen hier) nodig omdat je anders het resultaat van malloc niet kan opslaan in de oorsponkelijke variabele.

Bij andere functies hoef je alleen een enkele pointer naar je struct te sturen. "struct _automaat* a" of "Automaat a".
als ik (*automaatje)-> gebruik doet hij het perfect, op andere manieren krijg ik of runtime errors of compile errors..
Dat klopt. Met het sterretje dereference je de 1e pointer en met -> de 2e. Maar zoals ik al zei: Je heb maar 1 pointer nodig. Iedereen ging er vanuit dat er geen pointer in Automaat verborgen zit.
En deze word vanuit de parent aangeroepen op het hele ding:
code:
1
 create_automaat((&((*Aanschaf)->MijnAutomaat)),disp);
Is Aanschaf soms ook een dubbele pointer?

  • ThaStealth
  • Registratie: Oktober 2004
  • Laatst online: 27-11 13:59
aanschaf is op dezelfde manier opgebouwd, dus als ik het goed heb kan ik overal in de aanroep het * eruit slopen?

Dit is eigk niet het probleem, het probleem ligt em bij het vullen van de mailbox

C:
1
2
3
4
5
6
7
8
9
void sendEvent_Automaat(Automaat* automaatje, AutomaatEvents e, void* data){
 put_mailBox(&((*automaatje)->automaatMail),&e);
 if (e == ProductknopInduwen){
  put_mailBox(&((*automaatje)->productMail),(Snoep*) data);
 }
 if (e == GeldInwerpen){
    put_mailBox(&((*automaatje)->geldMail),(double*) data);
 }
}

Ik denk dat die typecast niet helemaal goed is van (Snoep*) en (double*) ik krijg nl rare waardes hierin.

[ Voor 70% gewijzigd door ThaStealth op 23-03-2007 20:48 ]

Mess with the best, die like the rest


  • Daos
  • Registratie: Oktober 2004
  • Niet online
get_mailBox kan gewoon niet werken zoals jij het hebt: get_mailBox weet niet hoe groot de mess is en dus kan hij/zij er niet naar schrijven.

[edit]
Er zat een bugje in mijn voorbeeldje...

[ Voor 44% gewijzigd door Daos op 23-03-2007 21:00 ]


  • ThaStealth
  • Registratie: Oktober 2004
  • Laatst online: 27-11 13:59
Hij complieerd dat netjes maar geeft @ runtime een acces violation :S
Lol Daos

[ Voor 6% gewijzigd door ThaStealth op 23-03-2007 21:03 ]

Mess with the best, die like the rest


  • Daos
  • Registratie: Oktober 2004
  • Niet online
ThaStealth schreef op vrijdag 23 maart 2007 @ 21:02:
Hij complieerd dat netjes maar geeft @ runtime een acces violation :S
Lol Daos
Er zat een bugje in.

Probeer eerst eens berichtjes uit met put_mailBox en get_mailBox door ze in een testfunctie na elkaar te gebruiken.

[edit]
Poging 2. get_mailBox kan alleen maar een pointer naar een bericht teruggeven en dat zou dan via een dubbele pointer moeten gebeuren zoals bij je create_automaat. (Of zit de grootte van een bericht soms verstopt in mailBox?)
C:
1
2
3
4
double *p_inworp;
double  inworp; 
get_mailBox(&(*mAutomaat)->geldMail,&p_inworp);
inworp = *p_inworp;



Heb je geen documentatie/voorbeeldjes bij get_mailBox en put_mailBox gekregen?

[ Voor 40% gewijzigd door Daos op 23-03-2007 21:17 ]


  • ThaStealth
  • Registratie: Oktober 2004
  • Laatst online: 27-11 13:59
Jawel hoor, ik zal ze even opzoeken, heb het geprobeert, krijg nog steeds onzingetallen uit :'(
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
//---------------------------------------------------------------------------
//mailbox prototypes --------------------------------------------------------
//Asynchrone communicatie tussen taken
//messages worden in FIFO order verwerkt
typedef struct _mailBox* mailBox;

void create_mailBox(mailBox* b,size_t sizeOfBuffer,size_t sizeOfElement);

void delete_mailBox(mailBox* b);

//lees bericht
void get_mailBox(mailBox* b,void* mess);

//return value:
//WAIT_OBJECT_0, message verkregen en timeOut niet verstreken
//WAIT_TIMEOUT, timeOut verstreken, geen message verkregen
unsigned long getTimed_mailBox(mailBox* b,void* mess,unsigned long timeOut);

//plaats bericht
void put_mailBox(mailBox* b,void* mess);

//return value:
//WAIT_OBJECT_0, bericht geplaatst en timeOut niet verstreken
//WAIT_TIMEOUT, timeOut verstreken, bericht niet geplaatst
unsigned long putTimed_mailBox(mailBox* b,void* mess,unsigned long timeOut);

//return value:
//false, indien mailBox niet leeg
//true, indien mailBox is leeg
int isEmpty_mailBox(mailBox* b);


Dit is de .h file van het object wat we hiervoor gebruiken, ga nu ff opzoek naar een p[aar voorbeelden

2.7. Mailbox concept, asynchrone communicatie.
Een mailbox voorziet in een faciliteit om taken asynchroon met elkaar te kunnen laten communiceren. Een mailbox heeft meestal een vaste grootte. Deze grootte wordt bij de
33
initialisatie van de mailbox vastgelegd, alsmede de grootte van de te verwachten berichten. Taken kunnen berichten plaatsen in/ophalen uit een mailbox. Wil een taak een bericht plaatsen in een volle mailBox of een bericht lezen uit een lege mailBox, dan zal de betreffende taak moeten wachten tot de vol/leeg conditie opgeheven is. Mailboxes bevatten dus ook wachtrijen, een voor taken die een bericht willen plaatsen in een volle mailBox, en een met taken die een bericht willen lezen uit een lege mailBox. Als er wachtende taken op een lege/volle mailBox zijn, dan zal de eerste taak uit deze wachtrij weer actief worden gemaakt, indien een andere taak een bericht ophaalt uit/plaatst in de betreffende mailBox . De organisatie van de wachtrijen, alsmede die van de geplaatste berichten, is dus FIFO.
Het hierboven beschreven mailbox concept kan vergeleken worden met het in [GOM00] beschreven concept in § 3.6.6., t.w. loosely coupled asynchronous message communication.

Een paar regels documentatie

En een C voorbeeld: (helaas geen projectfile)
http://www.blueknightsnl2.nl/vatPrj.zip

[ Voor 164% gewijzigd door ThaStealth op 23-03-2007 21:44 ]

Mess with the best, die like the rest


  • Daos
  • Registratie: Oktober 2004
  • Niet online
ThaStealth schreef op vrijdag 23 maart 2007 @ 21:30:
alsmede de grootte van de te verwachten berichten.
De grootte van een bericht zit dus verstopt in de mailBox. Wat ik hierboven gezegd heb is dus niet relevant. Zo'n constructie heb ik nog nooit gezien. Je eerste gebruik van get_mailBox kan dus goed zijn.

  • Daos
  • Registratie: Oktober 2004
  • Niet online
Werkt zoiets niet:
C:
1
2
3
4
5
6
7
8
9
10
11
12
13
void test() {
  mailBox m;

  double in = 3.14;
  double out;

  create_mailBox(&m, 2, sizeof(double)); 
  put_mailBox(&m,&in);
  get_mailBox(&m,&out);
  delete_mailBox(&m); /* wat het doet?? */

  printf("in:%lf out:%lf\n", in, out);
}



Misschien is je printf wel fout. Een double print je normaal met %lf.

  • ThaStealth
  • Registratie: Oktober 2004
  • Laatst online: 27-11 13:59
De printf word pas later in de code aangeroepen, dmv de debugger kan ik al aan de inhoud van de variabelen zien dat deze niet klopt. Als ik de huidige code uitvoer krijg ik nog steeds rare getallen :'(

Mess with the best, die like the rest


  • Daos
  • Registratie: Oktober 2004
  • Niet online
ThaStealth schreef op vrijdag 23 maart 2007 @ 22:22:
De printf word pas later in de code aangeroepen, dmv de debugger kan ik al aan de inhoud van de variabelen zien dat deze niet klopt. Als ik de huidige code uitvoer krijg ik nog steeds rare getallen :'(
Ik bedoelde de
C:
8
 sprintf(test,"%.2f",&((*mAutomaat)->saldo));
.

Je zal aan de gang moeten met je debugger, elke functie apart moeten testen of stapje voor stapje opnieuw opbouwen. Gewoon een hoop code typen en hopen dat het werk is niet zo handig als je er nog niet zo in thuis bent.

[edit]
En zorg ervoor dat je bij elke *, &, . en -> precies weet wat er moet gebeuren en ga na of dat ook in de code gebeurt. Zomaar *'jes toevoegen of verwijderen maakt meestal meer stuk dan heel.

[ Voor 13% gewijzigd door Daos op 23-03-2007 22:40 ]


  • ThaStealth
  • Registratie: Oktober 2004
  • Laatst online: 27-11 13:59
Daos schreef op vrijdag 23 maart 2007 @ 22:36:
[...]

Ik bedoelde de
C:
8
 sprintf(test,"%.2f",&((*mAutomaat)->saldo));
.

Je zal aan de gang moeten met je debugger, elke functie apart moeten testen of stapje voor stapje opnieuw opbouwen. Gewoon een hoop code typen en hopen dat het werk is niet zo handig als je er nog niet zo in thuis bent.
Ja d8 al dat je sprintf bedoelde, maar maakt toch niet uit want word pas later gebruikt ;), de originele code was zonder mailbox, dit is pas later gebeurd : 8)7

Mess with the best, die like the rest


  • Daos
  • Registratie: Oktober 2004
  • Niet online
ThaStealth schreef op vrijdag 23 maart 2007 @ 20:39:
Ik denk dat die typecast niet helemaal goed is van (Snoep*) en (double*) ik krijg nl rare waardes hierin.
De casts doen niets met de waarde (kan je zelfs weghalen omdat put_mailBox ook void* wil). Het zegt alleen tegen de compiler dat het geen void*, maar een double* is. Je zegt dus alleen dat op dat adres een double te vinden is. Het adres is en blijft hetzelfde (en dat geef je door aan put_mailBox).

De rare waarde kan juist komen omdat het een geheugenadres is. Misschien moet je eerst de Snoep (of waar de Snoep naar wijst als het een pointer is) en de double even lokaal opslaan.

  • H!GHGuY
  • Registratie: December 2002
  • Niet online

H!GHGuY

Try and take over the world...

Ik denk dat je echt wel even een goeie pointer tutorial moet gaan zoeken:
- pointer declaratie (Automaat* automaat = new Automaat())
- pointer dereferencing (Automaat a = *automaat en Automaat& a = *automaat met de verschillen ertussen)
- address operator (Automaat* a3 = &a en Automaat* a4 = &a2)
- operator precedence ( (*b).Klep, b->Klep, *b.Klep etc )

Verder kan ik je vertellen dat een typedef liefst wel een duidelijke naam verkiest:
C++:
1
typedef _automaat* PAutomaat;

Dit is een veelgebruikte naamgeving voor pointer typedefs waar je qua leesbaarheid al een heel stuk verder mee komt.

Als extraatje kan ik je melden dat je ook void* casten liefst kan mijden. Een void* kan naar letterlijk alles wijzen (daarvoor gebruik je't trouwens ook), maar samen met zijn kracht komt zijn zwakte: De boekhouding van waar het ding nu toch effectief naar wijst durft in de praktijk wel al eens een foutje te hebben waardoor je vervelende foutjes krijgt.

Een voorbeeld hoe je op een iets betere manier (zeker niet de perfecte manier) een typische message queue kan omvormen:
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
55
void HandleMessage(eMessage eMessageId, void* data)
{
  switch (eMessageID)
  {
    case eMessage1:
       HandleMessage1(data); break; // als je functies de cast zelf doen
    case eMessage2:
       HandleMessage2(reinterpret_cast<double*>(data)); break; // Als je functies het juiste argument willen
    default:
       std::cerr << "unknown message" << (ULONG)eMessageID << std::endl;
  }
}

// NAAR:
class CBaseMessage
{
  public:
     eMessage GetMessageID() const { return m_eMessageID; }
  protected:
     CBaseMessage(eMessage eMessageID) : m_eMessageID(eMessageID) {}
  private:
    eMessage m_eMessageID;
};

class CMessage1 : public CBaseMessage
{
  public:
    CMessage1(double dValue) : CBaseMessage(eMessage1), m_dValue(dValue) {}
    double GetValue() const { return m_dValue; }
  private:
    double m_dValue;
};
// hier ook CMessage2 etc.

void HandleMessage(CBaseMessage* msg)
{
  if (!msg)
    return;

  switch (msg->GetMessageID())
  {
    case eMessage1:
      HandleMessage1(dynamic_cast<CMessage1*>(msg)); break;
    case eMessage2:
      HandleMessage2(dynamic_cast<CMessage2*>(msg)); break;
    // enz.
  }
}

void HandleMessage1(CMessage1* msg)
{
  if (!msg)
    return;
  // handle message
}


Het lijkt meer werk en dat is het waarschijnlijk ook, maar het voorkomt code die al snel vies en niet-onderhoudbaar wordt. Er zijn natuurlijk nog betere alternatieven, maar die vallen zeker buiten de scope van jouw opdracht.

ASSUME makes an ASS out of U and ME


  • ThaStealth
  • Registratie: Oktober 2004
  • Laatst online: 27-11 13:59
Het probleem is dat het perse in C moet en niet inC++ mag, tevens moeten we gebruik maken van een voorgedefineerde file die het mailBox, etc. gedeelte afhandeld.deze zijn door de docenten ontwikkeld en moeten dus gebruikt worden in de case.....
Daos schreef op vrijdag 23 maart 2007 @ 22:58:
[...]
De rare waarde kan juist komen omdat het een geheugenadres is. Misschien moet je eerst de Snoep (of waar de Snoep naar wijst als het een pointer is) en de double even lokaal opslaan.
Kun je het misschien toelichten met een stukje code, ik snap niet zo goed wat je eigk bedoeld :o

Mess with the best, die like the rest


  • Daos
  • Registratie: Oktober 2004
  • Niet online
ThaStealth schreef op zaterdag 24 maart 2007 @ 15:41:
Kun je het misschien toelichten met een stukje code, ik snap niet zo goed wat je eigk bedoeld :o
C:
1
2
3
4
5
6
7
8
9
10
11
void sendEvent_Automaat(Automaat* automaatje, AutomaatEvents e, void* data){
 put_mailBox(&((*automaatje)->automaatMail),&e);
 if (e == ProductknopInduwen){
  Snoep product = *(Snoep*)data;
  put_mailBox(&(*automaatje)->productMail, data);
 }
 if (e == GeldInwerpen){
  double geld = *(double*)data;
  put_mailBox(&(*automaatje)->geldMail, data);
 }
}


Als je in je debugger een breakpoint op de put_mailBox zet, dan kan je zien wat er in product of geld zit als je daar stopt.

  • ThaStealth
  • Registratie: Oktober 2004
  • Laatst online: 27-11 13:59
Als ik dat probeer dan krijg ik dezelfde 'rare' variablen als ik bij het ophalen van de mailbox krijg,
C:
1
2
3
4
5
6
7
8
9
10
11
void sendEvent_Automaat(Automaat* automaatje, AutomaatEvents e, void* data){
 put_mailBox(&((*automaatje)->automaatMail),&e);
 if (e == ProductknopInduwen){
  Snoep product = *(Snoep*)data; // Hier dus
  put_mailBox(&(*automaatje)->productMail, data);
 }
 if (e == GeldInwerpen){
  double geld = *(double*)data;
  put_mailBox(&(*automaatje)->geldMail, data);
 }
}


Als ik in de debugger op de regel Snoep product = *(Snoep*)data; kijk dan zie ik dat data het getal 77 is, als ik Snoep product = (Snoep)data; dit doe, dan word data het getal 133;

Mess with the best, die like the rest


  • ThaStealth
  • Registratie: Oktober 2004
  • Laatst online: 27-11 13:59
Tevens heb ik een andere vraag

hoe kan ik een string omzetten naar een enum type (snoep)
dus string -> Snoep

Mess with the best, die like the rest


  • .oisyn
  • Registratie: September 2000
  • Laatst online: 10:04

.oisyn

Moderator Devschuur®

Demotivational Speaker

Dat kan niet zomaar in C, je zult dus zelf de waarde bij de string moeten definieren (bijvoorbeeld een array maken van string-enum paren en dan het juiste paar opzoeken)

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.


  • ThaStealth
  • Registratie: Oktober 2004
  • Laatst online: 27-11 13:59
Oke tnx :D

Omdat het met mijn gare uitleg het probleem niet goed over te brengen is heb ik het project online gezet, hoop alleen dat mijn klasgenoten dit niet zien maarja dat merken we wel weer ;)

http://www.blueknightsnl2.nl/prjAutomaat.zip

Hier is ie te downloaden, hij is met Borland C++ Builder 6 gemaakt dus kan zijn dat het probs geeft met compileren....

Om de fout te zien kun je simpelweg op een geldknop duwen rechtsboven (2 euro uitgezonderd die meot meteen uitgeworpen worden). Hetzelfde probleem treed trouwens ook op bij het indrukken van een productknop, alleen geeft ie dan een runtime error omdat ie hem niet kan omzetten van enum naar string..

Mess with the best, die like the rest


  • Daos
  • Registratie: Oktober 2004
  • Niet online
ThaStealth schreef op zaterdag 24 maart 2007 @ 16:16:
Als ik in de debugger op de regel Snoep product = *(Snoep*)data; kijk dan zie ik dat data het getal 77 is
77 is de 'M' (van "Mars"). data is nog een char * en dat moet je eerst herkennen/vertalen voordat je hem opstuurt in ProductGekozen(). Bij geld doe je het wel zoiets in geldInwerpen (of het ook werkt is een tweede).

Dit doe je vaker fout. Bv in BepaalKosten:
if (((Snoep)((mAutomaat)->Productnamen[i])) == (mAutomaat)->HuidigProduct){
ThaStealth schreef op zaterdag 24 maart 2007 @ 16:55:
Tevens heb ik een andere vraag

hoe kan ik een string omzetten naar een enum type (snoep)
dus string -> Snoep
Dat is dus dezelfde vraag.
Daar doen we niet aan. Je moet zelf debuggen als je er echt niet uitkomt, dan kan je relevante code hier posten. Als bv de conversie in geldInwerpen niet goed gaat, dan is zoiets relevante code:
C:
1
2
3
4
5
6
7
8
9
10
11
12
13
void test() {
   char* a = "E 1,50";

   double b;
   char bedrag[4];

   bedrag[0] = a[2];
   bedrag[1] = '.';
   bedrag[2] = a[4];
   bedrag[3] = a[5];

   b = atof(bedrag);
}


De antwoorden die dan kunnen komen zijn:
- Een string in C eindigt met een 0. Het moet dus zijn char bedrag[5]; met bedrag[4] = 0;
- Geld kan je beter opslaan/bewerken als integer (centen). Anders krijg je afrondingsfouten. De conversie kan dan met atoi. Je hebt dan natuurlijk geen punt ('.') nodig in de string.
- Het is verstandiger om de conversie in een aparte functie te zetten. Je kan hem dan apart testen en er is een kleinere kans dat je hem sloopt.

Verwijderd

Strings in C eindigen niet met "0", maar met "\0".

  • MSalters
  • Registratie: Juni 2001
  • Laatst online: 13-09 00:05
Dat zei Daos ook niet; hij zei 0. "0" is een char[2] array met (ASCII) waarden {48, 0}. "\0" is ook een char[2] met waarden {0,0}. De beste string benadering van 0 is "", omdat elke string eindigt met 0 (of '\0')

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


  • ThaStealth
  • Registratie: Oktober 2004
  • Laatst online: 27-11 13:59
Sorry voor de supertrage reactie maar mijn pc was dus gecrashed en heb project even aan de kant moeten leggen. Gelukkig kwam ik afgelopen woensdag een docent tegen en aan hem heb ik gevraagt hoe ik dit kon oplossen, ik heb het dus opgelost door de dingen om te zetten naar char array's, deze in de mailbox te duwen en dan uit te lezen op de goede plek, gelukkig werkte dit en kon ik weer verder :) :) :)

helaas kom ik nu op aan ander (gelukkig klein, maar wel irritant probleem) uit:

Als ik de volgende code uitvoer dan begint hij telkens aan het begin van de string te schrijven, op andere plekken plakt hij netjes de string erachter, maar hier begint hij dus telkens bij het begin te schrijven, dus hij overschrijft de inhoud...

De code bepaald dus telkens of een bepaalde muntsoort gewisseld mag worden, en als dit het geval is dan word deze gewisseld, er word 1 eenheid van die soort van de interne muntenrij eraf gehaald (automaat heeft 1 .50 cent munt minder) en word in een string toegevoegd (die gaat naar "uitvoerbak" toe, waar naast het wisselgeld dus ook het snoepgoed in terecht komt, dit word gesimuleert dmv een textbox)
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
void geefwisselgeld(void* automaatje){
   Automaat* mAutomaat = (Automaat*) automaatje;
int i = 0;
int j = 4;

char temp[100];
double minusbedrag = 1.00;
double tegoed = (*mAutomaat)->saldo;
while ((tegoed > 0.00)&&(j>=0)){
  if ((minusbedrag <= tegoed) && ( (*mAutomaat)->aantalWisselMunten[j] > 0)){ 
   sprintf(temp,"%s %.2f+",temp,minusbedrag); //hier begint hij telkens in het begin van de string te schrijven
   (*mAutomaat)->aantalWisselMunten[j] -= 1;
   i++;
   tegoed -= minusbedrag;
  }
  else  {
    j--;
    if  (minusbedrag == 0.10) {
   minusbedrag = 0.05;
   }
   else if  (minusbedrag == 0.20) {
    minusbedrag = 0.10;
    }
      else if  (minusbedrag == 0.50) {
      minusbedrag = 0.20;
      }
         else if  (minusbedrag == 1.00) {
         minusbedrag = 0.50;
         }
}
}

if (tegoed < 0.05){
 tegoed = 0.00;
}
(*mAutomaat)->saldo = tegoed;
}

Mess with the best, die like the rest


  • ThaStealth
  • Registratie: Oktober 2004
  • Laatst online: 27-11 13:59
Ow, nog kleine vraag: weet iemand een goed programma voor Borland C++ Builder 6 (ja waardeloze editor, maar moet van school :() om de code uit te lijnen? voor Borland Delphi 6 had ik er een mooie app voor, maar dies dus niet beschikbaar voor C++ Builder

Mess with the best, die like the rest


  • farlane
  • Registratie: Maart 2000
  • Laatst online: 30-11 00:17
ThaStealth schreef op maandag 02 april 2007 @ 15:52:
Ow, nog kleine vraag: weet iemand een goed programma voor Borland C++ Builder 6 (ja waardeloze editor, maar moet van school :() om de code uit te lijnen? voor Borland Delphi 6 had ik er een mooie app voor, maar dies dus niet beschikbaar voor C++ Builder
http://www.google.nl/sear...c%2B%2B&btnG=Zoeken&meta=

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.


  • ThaStealth
  • Registratie: Oktober 2004
  • Laatst online: 27-11 13:59
}:O

Mess with the best, die like the rest


  • Daos
  • Registratie: Oktober 2004
  • Niet online
Relevante code is:
C:
1
2
3
4
5
6
7
8
9
10
void test() {
  char temp[100];

  double minusbedrag = 1.00;

  sprintf(temp, "%s %.2f+", temp, minusbedrag);
  sprintf(temp, "%s %.2f+", temp, minusbedrag);

  puts(temp);
}


Dat het niet werkt komt waarschijnlijk door de temp als src en dest in sprintf.
Bovendien zit er bagger in temp bij het begin.

Het is dus zo te verbeteren:
C:
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
void test() {
  char temp[100];
  char temp2[100];

  double minusbedrag = 1.00;

  temp[0] = 0; /* temp bevat nu "" */

  sprintf(temp2, "%s %.2f+", temp, minusbedrag);
  strcpy(temp, temp2);

  sprintf(temp2, "%s %.2f+", temp, minusbedrag);
  strcpy(temp, temp2);

  puts(temp);
}


Je kan het ook met alleen temp doen, maar dan moet je bijhouden waar je gebleven bent. Het wordt dan zoiets:
C:
1
2
3
4
5
6
7
8
9
10
11
12
13
void test() {
  char temp[100];
  int offset = 0;

  double minusbedrag = 1.00;

  temp[0] = 0; /* temp bevat nu "" */

  offset += sprintf(temp + offset, " %.2f+", minusbedrag);
  offset += sprintf(temp + offset, " %.2f+", minusbedrag);

  puts(temp);
}

[ Voor 15% gewijzigd door Daos op 02-04-2007 18:09 . Reden: mooier 2e voorbeeldje ]


  • ThaStealth
  • Registratie: Oktober 2004
  • Laatst online: 27-11 13:59
nee, heb het geprobeert maar hij overschrijft nog steeds eerste deel van het array

Mess with the best, die like the rest


  • Daos
  • Registratie: Oktober 2004
  • Niet online
ThaStealth schreef op maandag 02 april 2007 @ 21:55:
nee, heb het geprobeert maar hij overschrijft nog steeds eerste deel van het array
Weet je zeker dat hij het overschrijft?

Ik had je al gewezen op de floatingpoints:
Daos schreef op zondag 25 maart 2007 @ 14:28:
- Geld kan je beter opslaan/bewerken als integer (centen). Anders krijg je afrondingsfouten.
[edit]
Probeer eens tegoed = 1.70 })

[edit2/edit3: break; ipv exta variabele]
De waarde van de munten had je ook in een array kunnen zetten (de werking is hetzelfde):
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
#include <stdio.h>

int main() {
  double tegoed = 1.70;


  #define AANTALMUNTSOORTEN 5
  int aantalWisselMunten[AANTALMUNTSOORTEN] = {5, 2, 2, 0, 2};
  const double waardeWisselMunten[AANTALMUNTSOORTEN] = {0.05, 0.10, 0.20, 0.50, 1.00};

  int muntsoort = AANTALMUNTSOORTEN - 1;
  double muntwaarde = waardeWisselMunten[muntsoort];


  char bericht[100]; /* is 100 altijd genoeg? */
  int berichtoffset = 0;


  while (tegoed > 0.00) {
    if (muntwaarde <= tegoed && aantalWisselMunten[muntsoort] > 0) {
      berichtoffset += sprintf(bericht + berichtoffset, " %.2f+", muntwaarde);
      aantalWisselMunten[muntsoort] -= 1;
      tegoed -= muntwaarde;
    }
    else if (muntsoort > 0) {
      muntsoort--;
      muntwaarde = waardeWisselMunten[muntsoort];
    }
    else {
      break; /* niet genoeg munten */
    }
  }

  puts(bericht);

  if (tegoed < waardeWisselMunten[0]) {
    printf(" weggegooid: %0.2f\n", tegoed);
    tegoed = 0.00;
  }
}


Geeft:
 1.00+ 0.20+ 0.20+ 0.10+ 0.10+ 0.05+
 weggegooid: 0.05

[ Voor 64% gewijzigd door Daos op 03-04-2007 12:21 ]


Verwijderd

je bedoelde een typedef?

dan is het:
C:
1
typedef string Snoep;


het gaat er dus om dat je gewoon ipv
string koekjes;
het volgende kan typen:
Snoep koekjes;

  • .oisyn
  • Registratie: September 2000
  • Laatst online: 10:04

.oisyn

Moderator Devschuur®

Demotivational Speaker

waar bedoelde wie een typedef?

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