Prob: Lineare Liste

#994952
Lesenswert?

Hallo zusammen,

ich habe ein Problem mit meiner Linearen Liste in ANSI-C.

Wenn ich die Liste erstelle, werden die richtigen Werte in sie 
reingeschrieben, aber beim Auslesen führt mein Code zu einem Programm 
absturz.

Ich vermute mal, das ich beim schreiben nur die Zeiger auf lokale 
Variablen setzte und nach der Routine diese nicht mehr gültig sind. Bin 
aber noch nicht so erfahren mit Zeigern, so das ich den Fehler nicht 
finden kann.

Hier mein Code:
1
typedef struct GC
2
{
3
    unsigned int G;               // G-Code
4
    unsigned int X;               // X-Koordinate (Optional)
5
    unsigned int Y;               // Y-Koordinate (Optional)
6
    unsigned int D;               // D-Code (Optional)
7
    struct DB *Block_Liste;       // Nur wenn dem G-Code ein Block folgt
8
} G_CODE;
9

10
typedef struct DB
11
{ 
12
    unsigned int X;               // X-Koordinate
13
    unsigned int Y;               // Y-Koordinate
14
    unsigned int PLOT_FUNCTION;   // D-Code
15
} DATA_BLOCK;
16

17

18
typedef struct Block
19
{
20
  char union_type;
21
  union 
22
  {
23
    G_CODE  g;                          //Falls das Element ein G-Code ist
24
    DATA_BLOCK data;                    //Falls das Element ein Data-Block ist        
25
  } body;
26
  struct Block *next;     
27
} DATA_LIST;
28

29

30
/*----------------------------------------------------------------------------*/
31
/*----------------------------------------------------------------------------*/
32
/*----------------------------------------------------------------------------*/
33
/* Einfuegen von wert an passender Stelle (aufsteigend sortiert) */
34
void Einfuegen_Block(DATA_LIST **pliste,G_CODE *g,DATA_BLOCK *data)
35
{
36
 if (*pliste==NULL)
37
 {
38
  *pliste = (DATA_LIST*)malloc(sizeof(DATA_LIST));
39
  
40
  if (*pliste == NULL)
41
  {
42
   fprintf(stderr,"\nmalloc()-Aufruf schlug fehl!\n");
43
//   exit(0);
44
  } /* end if malloc() schlug fehl */
45
  
46
  if( g != NULL)
47
  {
48
      (*pliste)->union_type = 1;
49
      (*pliste)->body.g = *g; 
50
      printf("\n\t%d\n",(*pliste)->union_type);
51
  }          
52
  else if ( data != NULL )
53
  {
54
      (*pliste)->union_type = 2;
55
      (*pliste)->body.data = *data; 
56
      printf("\n\t%d\n",(*pliste)->union_type);
57
  }
58
       
59
  (*pliste)->next = NULL;
60

61
 } /* end if *pliste==NULL */
62
 else 
63
 {
64

65
  Einfuegen_Block(&((*pliste)->next),g,data);
66
 } /* rekursiver Zweig - weiter hinten anhängen oder einfügen*/
67
} /* end Einfuegen */
68

69
/*----------------------------------------------------------------------------*/
70
/*----------------------------------------------------------------------------*/
71
/*----------------------------------------------------------------------------*/
72
/* Einfache Ausgabe der linearen Liste */
73
void Ausgeben_Block(DATA_LIST *liste)
74
{
75
DATA_BLOCK data;
76
int i,x;
77
 if (liste==NULL)
78
    printf("\n(Ende der Liste)\n");
79
 else
80
 {
81
  printf("\n(Test %d)\n",(*liste).union_type);
82
  if( ((*liste).union_type) == 1 )
83
  {
84
   printf("G%02d",liste->body.g.G);    
85
  }
86
  else if( ((*liste).union_type) == 2 )
87
  {
88
       
89
  }
90
  Ausgeben_Block(liste->next);   
91
 }
92
} /* end Ausgeben */
93

94
/*----------------------------------------------------------------------------*/
95
/*----------------------------------------------------------------------------*/
96
/*----------------------------------------------------------------------------*/
97

98
DATA_LIST *scan_line(char *s,DATA_LIST *pointer)
99
{
100
DATA_BLOCK data_block;
101
G_CODE g_block;
102

103

104
if( DATA_BLOCK_FILTER(s,&data_block) != NULL)
105
{
106

107
Einfuegen_Block(pointer,NULL,&data_block);
108

109
 #if DEBUG == 1
110
     printf("\n\tX = %d\n\tY = %d\n\tD = %d\n",data_block.X,data_block.Y,data_block.PLOT_FUNCTION);
111
 #endif
112
}
113
else if ( G_CODE_FILTER(s,&g_block) != NULL)
114
{
115
Einfuegen_Block(pointer,&g_block,NULL);
116
 #if DEBUG == 1
117
     printf("\n\tG = %d\n\tX = %d\n\tY = %d\n\tD = %d\n",g_block.G,g_block.X,g_block.Y,g_block.D);
118
 #endif     
119
}
120
       
121
}
122

123
int main(void)
124
{
125
....
126
scan_line("G54D10*",&liste);
127

128
scan_line("X1000Y4356D01*",&liste);
129

130
Ausgeben_Block(&liste);
131
....
132
}

Wenn die Zeile Ausgeben_Block(&liste); auskommentiert ist, stürzt mein 
Programm nicht ab.

Ich würde mich freuen wenn mir jemand helfen kann.

Gruß
NemesisoD
Gast #996175
Lesenswert?

Wie ist liste in main definiert? Ich schätze, so:
1
  DATA_LIST *liste;

Dann muss die Argumentliste von scan_line aber nicht so
1
DATA_LIST *scan_line(char *s,DATA_LIST *pointer)

sondern wahrscheinlich so aussehen:
1
DATA_LIST *scan_line(char *s,DATA_LIST **pointer)

und der Aufruf von Ausgeben_Block nicht so
1
  Ausgeben_Block(&liste);

sondern so:
1
  Ausgeben_Block(liste);

Gibt der Compiler bei der Übergabe nichtkompatibler Pointer keine
Warnung aus? Wenn nicht, musst du den Warning-Level erhöhen. Wenn doch,
musst du diese auch beachten ;-)
Gast #996189
Lesenswert?

Noch etwas: Hast du, bevor du C gelernt hast, LISP programmiert? Das
würde deinen Hang zur rekursiven Programmierung erklären ;-)

Die Rekursionstiefe in Einfuegen_Block und Ausgeben_Block ist gleich
der Anzahl der Elemente in der Liste. Bei sehr langen Listen kommt es
dann irgendwann zum Stacküberlauf. Da es sich in beiden Fällen um eine
Endrekursion handelt, wird sie ein intelligenter Compiler (z.B. GCC bei
Optimierungsstufe -O2, -O3 oder -Os) zwar in eine Schleife umwandeln, es
ist aber gefährlich, sich auf solche Features zu verlassen.

In C vermeidet man Rekursionen, wo dies so leicht möglich ist, wie in
diesem Fall.

Anders in LISP: Dort ist es sogar guter Stil, Endrekursionen
(funktionales Konstrukt, hui) statt Schleifen (prozedurales Konstrukt,
pfui) zu verwenden. Im Gegensatz zu C gehört in LISP die Auflösung von
Endrekursionen durch den Compiler aber zur Sprachspezifikation, weswegen
man sich auf sie verlassen kann.

Antwort schreiben

Bitte melde dich an, um einen Beitrag zu schreiben.

oder

Mit Google-Account einloggen

Die Registrierung ist kostenlos und dauert nur eine Minute.

Jetzt registrieren