www.mikrocontroller.net

Forum: PC-Programmierung Prob: Lineare Liste


Autor: Michael Leske (nemesisod)
Datum:

Bewertung
0 lesenswert
nicht 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:
typedef struct GC
{
    unsigned int G;               // G-Code
    unsigned int X;               // X-Koordinate (Optional)
    unsigned int Y;               // Y-Koordinate (Optional)
    unsigned int D;               // D-Code (Optional)
    struct DB *Block_Liste;       // Nur wenn dem G-Code ein Block folgt
} G_CODE;

typedef struct DB
{ 
    unsigned int X;               // X-Koordinate
    unsigned int Y;               // Y-Koordinate
    unsigned int PLOT_FUNCTION;   // D-Code
} DATA_BLOCK;


typedef struct Block
{
  char union_type;
  union 
  {
    G_CODE  g;                          //Falls das Element ein G-Code ist
    DATA_BLOCK data;                    //Falls das Element ein Data-Block ist        
  } body;
  struct Block *next;     
} DATA_LIST;


/*----------------------------------------------------------------------------*/
/*----------------------------------------------------------------------------*/
/*----------------------------------------------------------------------------*/
/* Einfuegen von wert an passender Stelle (aufsteigend sortiert) */
void Einfuegen_Block(DATA_LIST **pliste,G_CODE *g,DATA_BLOCK *data)
{
 if (*pliste==NULL)
 {
  *pliste = (DATA_LIST*)malloc(sizeof(DATA_LIST));
  
  if (*pliste == NULL)
  {
   fprintf(stderr,"\nmalloc()-Aufruf schlug fehl!\n");
//   exit(0);
  } /* end if malloc() schlug fehl */
  
  if( g != NULL)
  {
      (*pliste)->union_type = 1;
      (*pliste)->body.g = *g; 
      printf("\n\t%d\n",(*pliste)->union_type);
  }          
  else if ( data != NULL )
  {
      (*pliste)->union_type = 2;
      (*pliste)->body.data = *data; 
      printf("\n\t%d\n",(*pliste)->union_type);
  }
       
  (*pliste)->next = NULL;

 } /* end if *pliste==NULL */
 else 
 {

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

/*----------------------------------------------------------------------------*/
/*----------------------------------------------------------------------------*/
/*----------------------------------------------------------------------------*/
/* Einfache Ausgabe der linearen Liste */
void Ausgeben_Block(DATA_LIST *liste)
{
DATA_BLOCK data;
int i,x;
 if (liste==NULL)
    printf("\n(Ende der Liste)\n");
 else
 {
  printf("\n(Test %d)\n",(*liste).union_type);
  if( ((*liste).union_type) == 1 )
  {
   printf("G%02d",liste->body.g.G);    
  }
  else if( ((*liste).union_type) == 2 )
  {
       
  }
  Ausgeben_Block(liste->next);   
 }
} /* end Ausgeben */

/*----------------------------------------------------------------------------*/
/*----------------------------------------------------------------------------*/
/*----------------------------------------------------------------------------*/

DATA_LIST *scan_line(char *s,DATA_LIST *pointer)
{
DATA_BLOCK data_block;
G_CODE g_block;


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

Einfuegen_Block(pointer,NULL,&data_block);

 #if DEBUG == 1
     printf("\n\tX = %d\n\tY = %d\n\tD = %d\n",data_block.X,data_block.Y,data_block.PLOT_FUNCTION);
 #endif
}
else if ( G_CODE_FILTER(s,&g_block) != NULL)
{
Einfuegen_Block(pointer,&g_block,NULL);
 #if DEBUG == 1
     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);
 #endif     
}
       
}

int main(void)
{
....
scan_line("G54D10*",&liste);

scan_line("X1000Y4356D01*",&liste);

Ausgeben_Block(&liste);
....
}

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

Autor: Stefan B. (stefan) Benutzerseite
Datum:

Bewertung
0 lesenswert
nicht lesenswert
Crash sofort ohne jede fprintf/printf-Ausgabe?

Autor: Michael Leske (nemesisod)
Datum:

Bewertung
0 lesenswert
nicht lesenswert
Also,
das "Test %d" gibt er aus, und zwar 3 mal, aber in %d steht nicht das 
was ich erwaret habe.

Auch das "G%02d" wird ausgegeben, aber auch hier steht nicht der 
richtige wert drin.

Danke

Autor: yalu (Gast)
Datum:

Bewertung
0 lesenswert
nicht lesenswert
Wie ist liste in main definiert? Ich schätze, so:
  DATA_LIST *liste;

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

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

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

sondern so:
  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 ;-)

Autor: yalu (Gast)
Datum:

Bewertung
0 lesenswert
nicht 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.

Autor: Stefan B. (stefan) Benutzerseite
Datum:

Bewertung
0 lesenswert
nicht lesenswert
Ich schliesse mich Yalu an und ergänze noch was formales:

In Einfuegen_Block() reicht diese Anweisung (*pliste)->body.g = *g; 
nicht aus, um aus der Quelle (Zeiger g) in das Ziel (Element g vom Typ 
G_CODE in der Union body) zu kopieren. Hier muss eine Blockkopieraktion 
wie z.B. memcpy() ran. Gleiches gilt für data.

Antwort schreiben

Die Angabe einer E-Mail-Adresse ist freiwillig. Wenn Sie automatisch per E-Mail über Antworten auf Ihren Beitrag informiert werden möchten, melden Sie sich bitte an.

Wichtige Regeln - erst lesen, dann posten!

  • Groß- und Kleinschreibung verwenden
  • Längeren Sourcecode nicht im Text einfügen, sondern als Dateianhang

Formatierung (mehr Informationen...)

  • [c]C-Code[/c]
  • [avrasm]AVR-Assembler-Code[/avrasm]
  • [code]Code in anderen Sprachen, ASCII-Zeichnungen[/code]
  • [math]Formel in LaTeX-Syntax[/math]
  • [[Titel]] - Link zu Artikel
  • Verweis auf anderen Beitrag einfügen: Rechtsklick auf Beitragstitel,
    "Adresse kopieren", und in den Text einfügen




Bild automatisch verkleinern, falls nötig
Bitte das JPG-Format nur für Fotos und Scans verwenden!
Zeichnungen und Screenshots im PNG- oder
GIF-Format hochladen. Siehe Bildformate.
Hinweis: der ursprüngliche Beitrag ist mehr als 6 Monate alt.
Bitte hier nur auf die ursprüngliche Frage antworten,
für neue Fragen einen neuen Beitrag erstellen.

Mit dem Abschicken bestätigst du, die Nutzungsbedingungen anzuerkennen.