[C] Linked list foutief populated

Pagina: 1
Acties:

Onderwerpen


Acties:
  • 0 Henk 'm!

  • Arrancar
  • Registratie: December 2006
  • Laatst online: 20-06 10:49
Ik ben bezig met een appje om een textbestandje uit te lezen en de afzonderlijke woorden in een linked list te plaatsen (en daarna weer verder te verwerken, maar is niet voor mijn vraag van belang). In dit geval bevat het txt bestandje alleen de woorden "appel peer boom". In het loopje print ik de pointer van de variabele "newword" voor (noob)debug doeleinden. Als ik de linked list print krijg ik de volgende output:

code:
1
2
3
4
5
6
processing file...003E2508

003E2548

The list is :
boorl --> boorl --> NULL


Het lijkt erop dat hij de ruimte die met malloc voor "appel" gereserveerd wordt blijft gebruiken voor de nodes en op 1 of andere manier het volgende woord eroverheen wilt schrijven.

Blijkbaar zie ik aardig wat over het hoofd, heeft er iemand toevallig tips hoe ik dit op zou kunnen lossen?

Ik heb main.c even buiten beschouwing gelaten.

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
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
/*
 *  File:           Linkedlist.c
 *  Title:          Linkedlist
 *  Description:    contains linked list code
 *  Author:         Stephan Bakker
 *
 *  $Id:$
 *
 *  $Log:$
 *
 *
 */

#include <stdio.h>
#include <stdlib.h>
#include <string.h>
#include "prototypes.h"

void insert(NODESPTR *, char *);
void printList(NODESPTR);
int isChar(char);
void linkedList();

struct Nodes {
   char *data;
   struct Nodes *nextPtr; /* pointer to next structure */
};


typedef struct Nodes NODES;
typedef NODES *NODESPTR;

void linkedList(){

    d.count = 0;
    NODESPTR startPtr = NULL;

    d.c = fgetc(d.fileDocument);
    printf("processing file...");

    while ((d.d = fgetc(d.fileDocument)) != EOF) {

          /*If two lines in a row*/
          if ((d.c == '\n') && (d.d == '\n')) {
            }

          /* if not two non-characters in a row */
          else if ((isChar(d.c) == 0) && (isChar(d.d) == 0)) {
               d.c = d.d;
          }

          /* if c and d are both characters */
          else if ((isChar(d.c) == 1) && (isChar(d.d) == 1)) {
              d.word[d.count] = d.c;
              d.c = d.d;
              d.count++;
          }

            /* if c is character and d is space, return, tab, or new line */
          else if ((isChar(d.c) == 1) && (isChar(d.d) == 0)) {
              d.word[d.count] = d.c;

              char *newword = malloc(sizeof(d.word));
              printf("%p\n\n\n", newword);
              newword = d.word;
              insert(&startPtr, newword);

              d.c = d.d;
              d.count = 0;
          }

          /* if d is start of new word */
          else if ((isChar(d.d) == 1) && (isChar(d.c) == 0)) {
              d.c = d.d;
          }
    }
  fclose(d.fileDocument);

  printList(startPtr);
}

/* insert into linked list */
void insert(NODESPTR *sPtr, char *value)
{
   NODESPTR newPtr, previousPtr, currentPtr;

   newPtr = malloc(sizeof(NODES));


   if (newPtr != NULL) {    /* is space available */
      newPtr->data = malloc(sizeof(value));
      newPtr->data = value;
      newPtr->nextPtr = NULL;

      previousPtr = NULL;
      currentPtr = *sPtr;

      while (currentPtr != NULL && value > currentPtr->data) {
         previousPtr = currentPtr;
         currentPtr = currentPtr->nextPtr;  /* walk to next node */
      }

      if (previousPtr == NULL) {
         newPtr->nextPtr = *sPtr;
         *sPtr = newPtr;
      }
      else {
         previousPtr->nextPtr = newPtr;
         newPtr->nextPtr = currentPtr;
      }
   }
   else
      printf("%s not inserted. No memory available.\n", value);
}

/* Print the list */
void printList(NODESPTR currentPtr)
{
   if (currentPtr == NULL)
      printf("List is empty.\n\n");
   else {
      printf("The list is:\n");

      while (currentPtr != NULL) {
         printf("%s --> ", currentPtr->data);
         currentPtr = currentPtr->nextPtr;
      }

      printf("NULL\n\n");
   }
}

Acties:
  • 0 Henk 'm!

  • .oisyn
  • Registratie: September 2000
  • Laatst online: 17-09 14:05

.oisyn

Moderator Devschuur®

Demotivational Speaker

Wat is 'd' voor een ding, en waarom alloceer je sizeof(d.word) chars voor een string?

Daarnaast is het denk ik handig om gewoon eens een goed C boek te kopen of een tutorial door te nemen, want van C string handling heb je duidelijk nog geen kaas gegeten. Als je een pointer-naar-char aan een andere pointer-naar-char assignt, wat denk je dan dat er gebeurt?

[ Voor 65% gewijzigd door .oisyn op 06-10-2009 15:57 ]

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!

  • Arrancar
  • Registratie: December 2006
  • Laatst online: 20-06 10:49
Oja :P d is een struct met globale variabelen, niet echt netjes maar ben een beginner ;) En malloc ben ik nog niet helemaal meester. In principe hoef je dus malloc niet te gebruiken voor voor chars?

Acties:
  • 0 Henk 'm!

  • .oisyn
  • Registratie: September 2000
  • Laatst online: 17-09 14:05

.oisyn

Moderator Devschuur®

Demotivational Speaker

d is een struct met globale variabelen, niet echt netjes maar ben een beginner
Ja zo ver was ik ook, maar het is handig als je de definitie daarvan ook even post.
In principe hoef je dus malloc niet te gebruiken voor voor chars?
Als je de boel wilt kopieëren wel. Maar wat jij nu doet is geheugen reserveren, en dan vervolgens keihard die pointer weer overschrijven door 'm te laten wijzen naar een andere geheugenbuffer. Als je echt strings wilt kopieëren zul je strcpy() moeten gebruiken. Maar dan moet je ook wel genoeg geheugen reserveren (het aantal tekens in de string + 1 voor de '\0' op het eind), en dus niet sizeof gebruiken (die de grootte van het datatype teruggeeft, wat typisch 4 bytes is voor een pointer op een 32 bits systeem)

Maar dat is allemaal nogal basis C kennis.

[ Voor 3% gewijzigd door .oisyn op 06-10-2009 16:10 ]

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!

  • NMe
  • Registratie: Februari 2004
  • Laatst online: 09-09 13:58

NMe

Quia Ego Sic Dico.

Arrancar schreef op dinsdag 06 oktober 2009 @ 16:04:
Oja :P d is een struct met globale variabelen, niet echt netjes maar ben een beginner ;) En malloc ben ik nog niet helemaal meester. In principe hoef je dus malloc niet te gebruiken voor voor chars?
Alleen als je dynamisch geheugen wil alloceren (en dat wil je hier). En je werkt niet met chars, je werkt met char pointers, C's variant op een string. Een char pointer is een pointer naar het eerste karakter van je string. Een pointer is niet meer dan een nummertje van het geheugenadres waar je naar verwijst.

Stel je hebt de string "foo". Normaal zou je zoiets schrijven:
C:
1
char *bar = "foo";

Wat er dan onderwater gebeurt is dat er ruimte wordt aangemaakt voor 4 tekens ("foo" en \0 om de string af te sluiten). Laten we zeggen dat die ruimte gemaakt wordt op geheugenadres 1337. De variabele bar bevat vervolgens niet de string "foo" die je wilde opslaan, maar de waarde 1337.

Als je vervolgens een string "baz" aanmaakt:
C:
1
char *quux = "baz";

...dan doe je feitelijk hetzelfde. Je hebt 4 bytes geheugen vrijgemaakt voor de string en de variabele quux bevat een verwijzing naar het adres (bijvoorbeeld 31337) van die string.

Laten we nu zeggen dat je de strings wil kopiëren. Je wil dus dat de variabele bar dezelfde tekst gaat bevatten als quux. Je eerste gedachte is dan waarschijnlijk om te schrijven:
C:
1
bar = quux;

Ogenschijnlijk doet dat wat je wil: de waarde overschrijven. Echter, dat is niet wat er gebeurt. Wat er gebeurt is dat je de pointer naar adres 1337 overschrijft met de pointer naar adres 31337. Met als gevolg dat je twee pointers hebt naar dezelfde string terwijl de string "foo" nog steeds zonder referentie ernaartoe bestaat.

Zoals .oisyn al zei: ga je eens inlezen in hoe stringmutatie in C werkt, want dit is de eerste les die je leert als je C gaat leren. ;) En het heeft niks met malloc te maken. :)

'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.


Acties:
  • 0 Henk 'm!

  • Arrancar
  • Registratie: December 2006
  • Laatst online: 20-06 10:49
Alright fijn uitgelegd, beide bedankt :) Iets teveel op de linked list gehamerd terwijl de basis er nog niet genoeg in zit...

Zal hem even herschrijven en posten voor eventuele feedback.

Acties:
  • 0 Henk 'm!

  • Arrancar
  • Registratie: December 2006
  • Laatst online: 20-06 10:49
Alright heb het wat getweaked, krijg de volgende output met de testwoorden "appel appels boom.":

code:
1
appel --> appels --> booml --> NULL


Allen zodra er een woord kleiner dan het eerste woord wordt gelezen blijft de ruimte voor het eerste woord staan, zoals bij "booml" wordt gedaan. Enig idee wat dit kan veroorzaken?

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
void linkedList(){

    d.count = 0;
    NODESPTR startPtr = NULL;

    d.c = fgetc(d.fileDocument);
    printf("processing file...\n\n");

    while ((d.d = fgetc(d.fileDocument)) != EOF) {

          /*If two lines in a row*/
          if ((d.c == '\n') && (d.d == '\n')) {
            }

          /* if not two non-characters in a row */
          else if ((isChar(d.c) == 0) && (isChar(d.d) == 0)) {
               d.c = d.d;
          }

          /* if c and d are both characters */
          else if ((isChar(d.c) == 1) && (isChar(d.d) == 1)) {
              d.word[d.count] = d.c;
              d.c = d.d;
              d.count++;
          }

            /* if c is character and d is space, return, tab, or new line */
          else if ((isChar(d.c) == 1) && (isChar(d.d) == 0)) {
              d.word[d.count] = d.c;
              d.word[d.count += 2] = '\0';

              char *newword = malloc(strlen(d.word) + 1);
              strcpy(newword, d.word);
              printf("%p\n\n\n\n", newword);
              insert(&startPtr, newword);

              d.c = d.d;
              d.count = 0;
          }

          /* if d is start of new word */
          else if ((isChar(d.d) == 1) && (isChar(d.c) == 0)) {
              d.c = d.d;
          }
    }
  fclose(d.fileDocument);

  printList(startPtr);
}


isChar();
C:
1
2
3
4
5
6
7
8
9
int isChar(char c) {
    if ((c >= 'a') && (c <= 'z') || ((c>='A') && (c<='Z'))) {
        return 1;
    }
    else 
    {
    return 0;
}
}

[ Voor 4% gewijzigd door Arrancar op 08-10-2009 13:12 ]


Acties:
  • 0 Henk 'm!

  • .oisyn
  • Registratie: September 2000
  • Laatst online: 17-09 14:05

.oisyn

Moderator Devschuur®

Demotivational Speaker

Heb je al eens gewoon een debugger gebruikt? Want voor dit soort vragen is GoT niet echt bedoeld... En je geeft nog steeds niet de definitie (en initialisatie) van 'd'.

En vanwaar de += 2 op regel 30?

[ Voor 34% gewijzigd door .oisyn op 08-10-2009 13:15 ]

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!

  • Arrancar
  • Registratie: December 2006
  • Laatst online: 20-06 10:49
Ah ok, niet echt een fora voor beginners dus. Mijn excuses als het niet de bedoeling is, je mag hem locken als je het een probleem vind uiteraard.

Alsnog even 'd':

C:
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
#include <stdio.h>
#include <stdlib.h>

typedef struct defineer{
       char *cvalue;
       char *fileName;
       char word[50];
       char d;
       char c;  
       
       int count;      
       int s;
       
       FILE *fileDocument, *fileDocument2;
}defineer;

defineer d;

Acties:
  • 0 Henk 'm!

  • .oisyn
  • Registratie: September 2000
  • Laatst online: 17-09 14:05

.oisyn

Moderator Devschuur®

Demotivational Speaker

Arrancar schreef op donderdag 08 oktober 2009 @ 13:19:
Ah ok, niet echt een fora voor beginners dus.
Weldegelijk voor beginners, maar we verwachten eigen inzet, en niet dat je hier gewoon maar je vraag neerplempt. Als je je code gaat debuggen dan wordt het meestal vanzelf duidelijk waarom het niet klopt (en zo niet, dan kun je dat hier vragen met een uitvoerige beschrijving van de symptomen die je ziet met debuggen). Nu vraag je aan ons of wij je code gaan debuggen, zo werkt dat natuurlijk niet.

Zelfs een gevorderde programmeur kan niet in 1 opslag zien wat een stuk code doet.

[ Voor 7% gewijzigd door .oisyn op 08-10-2009 13:23 ]

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!

  • NMe
  • Registratie: Februari 2004
  • Laatst online: 09-09 13:58

NMe

Quia Ego Sic Dico.

Sterker nog, de keuze voor de namen "c" en "d" maakt het niet eens duidelijk wat die struct moet doen.

Je uitvoer lijkt overigens erop te wijzen dat je de string wel kopiëert, maar de \0 niet meekomt. Wat volgens mij ook weer de reden is dat .oisyn jou naar regel 30 wijst, want volgens mij bedoel je daar eigenlijk iets anders dan eerst de counter ophogen en vervolgens op die plek een nul-char neerzetten. Ik denk dat je dat andersom wil doen. ;)

'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.


Acties:
  • 0 Henk 'm!

  • .oisyn
  • Registratie: September 2000
  • Laatst online: 17-09 14:05

.oisyn

Moderator Devschuur®

Demotivational Speaker

NMe schreef op donderdag 08 oktober 2009 @ 13:31:
Ik denk dat je dat andersom wil doen. ;)
Ik denk dat ie wel eerst wil ophogen, gezien het feit dat ie de regel ervoor nog een nieuwe waarde toekent aan die char op die plek. En het feit dat ie met 2 ophoogt lijkt mij de reden dat de 'l' van het vorige woord 'appel' blijft staan. Maar goed, dit blijft giswerk. Ik doe nu een shift-F5 op mezelf, want ik heb nu wel genoeg gedebugged :P

[ Voor 7% gewijzigd door .oisyn op 08-10-2009 13:41 ]

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!

  • Arrancar
  • Registratie: December 2006
  • Laatst online: 20-06 10:49
Ik geloof dat ik hem heb. [d.count++] werkte ook niet goed dus ik ging er vanuit dat het += 2 moest zijn (wat ook niet goed werkte). Uit jullie feedback haal ik dat ik toch met 1 moet verhogen wat logisch is eigenlijk.Het zit dus blijkbaar zo: Met [d.count++] returned hij de value van "count" !voordat! hij incremented wordt. In principe moet ik dus += 1 doen wat hetzelfde is als [++d.count] om de value van count te returnen nadat hij incremented is:

C:
1
d.word[++d.count] = '\0';


output:

code:
1
appel --> appels --> boom --> NULL


Thx!

[ Voor 5% gewijzigd door Arrancar op 08-10-2009 14:05 ]


Acties:
  • 0 Henk 'm!

  • NMe
  • Registratie: Februari 2004
  • Laatst online: 09-09 13:58

NMe

Quia Ego Sic Dico.

De ++ operator heet in variabele++ niet voor niks anders dan in ++variabele. ;) In het eerste geval is het een post-increment, in het tweede geval een pre-increment

'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.

Pagina: 1