"We are back" « oc.at

Pointer Problem in C

Brunnman 09.04.2003 - 20:56 1199 15
Posts

Brunnman

Addicted
Registered: Jul 2002
Location: Wien
Posts: 583
Hi, ich habe folgendes Problem:
Ich habe ein binäres Baum Programm, es sollen Char mit einer Länge von 20 Zeichen eingelesen werden und in gewissen "Orders" wieder ausgegben werden.

Nur bei mir scheint es so, als hätte ich was mit dne Pointer falsch gemacht, nur ich komme ienfach nicht darauf :(

Weiß wer wo bzw. was nicht korrekt ist?
Ich schätze, dass der Wert vom Pointer help der Funktion inorder nicht korrekt übregeben wird.

Danke,
Brunnman

EDIT #1:
Ich glaube jetzt einen Fehler entdeckt zu haben, komme aber nicht weiter. Fehler:
Root wird irgendwie verändert (wodurch auch immer :confused:) und dadurch wird nicht das letzte Element ausgegeben.

Nur wo verändere ich den root?!?

EDIT #2:
in void eingabe(...) bekomme ich immer nur in den 1. If-Zweig, so als wäre help immer neu.
Help hat am Ende der Funktion einen wert der übergeben wird, aber am beginn der rekursion müsst help dann ja den korrekten wert haben, hat jedoch immer den wert NULL...

Code:
#ifdef HAVE_CONFIG_H 
#include <config.h> 
#endif 
 
#include <stdio.h> 
#include <strings.h> 
#include <stdlib.h> 
 
typedef struct node 
{ 
  char info[21]; 
  struct node *left, *right; 
} NODE; 
 
typedef NODE *Ref; 

Ref root = NULL;

void eingabe(char datensatz[21], Ref root); 
void ausgabe(Ref help);
void print(Ref help);
void inorder(Ref help);
void fehler(); 

 
int main(int argc, char *argv[]) 
{ 
  Ref help=NULL;
  int ein=1; 
  char datensatz[21]; 
  while(ein!=0) 
  { 
    printf("%s","\nBitte waehlen Sie die gewuenschte Funktion aus dem Menue:\n\n"); 
    printf("%s","[1]... Eingabe\n"); 
    printf("%s","[2]... Ausgabe\n"); 
    printf("%s","[0]... Ende\n"); 
    scanf("%d",&ein); 
    if (ein=='\n') 
      scanf("%d",&ein); 
    switch (ein) 
    { 
      case 1: printf("%s","\nEingabe:\n\n"); 
              printf("%s","Bitte geben Sie den Datensatz ein:\n");
              scanf("%s",datensatz); eingabe(datensatz,help); 
            break; 
      case 2: ausgabe(help); break; 
      case 0: break; 
      default: fehler(); break; 
    }; 
  } 
  return EXIT_SUCCESS; 
} 
 
void fehler() 
{ 
  printf("%s","\nFEHLER! Bitte wiederholen Sie die letzte Aktion\n\n"); 
} 
 
void eingabe(char datensatz[21], Ref help) 
{ 
  if (!help) 
  { 
     help=(Ref)malloc(sizeof(NODE)); 
     help->left=(Ref)malloc(sizeof(NODE));
     help->right=(Ref)malloc(sizeof(NODE));
     help->left = help->right=NULL ; 
     strcpy(help->info,datensatz); 
  }
  else
  {
    if (strcmp(datensatz,help->info)<0)
    {
      help->left=(Ref)malloc(sizeof(NODE));
      strcpy(help->left->info,datensatz);
      eingabe(datensatz,(help->left)); 
    }
    if (strcmp(datensatz,help->info)>0)
    {
      help->right=(Ref)malloc(sizeof(NODE));
      strcpy(help->right->info,datensatz);
      eingabe(datensatz,(help->right));
    }
  }
  print(help);
} 
 
void ausgabe(Ref help) 
{ 
  int eing=1; 
    printf("%s","\nBitte waehlen Sie die Art der Ausgabe:\n\n");
    printf("%s","[1]... Inorder\n");
    printf("%s","[0]... Ende\n");
    scanf("%d",&eing);
    switch(eing)
    {
      case 1: printf("%s","Inorder:\n"); help=root; inorder(help); break;
      default: break;
    };
} 
void inorder(Ref help)
{ 
  if (help)
  { 
    inorder(help->left);
    print(help);
    inorder(help->right);
  }
  getch();
}

void print(Ref help)
{
    printf("%s,   \n",help->info);
}
Bearbeitet von atrox am 10.04.2003, 02:12 (readability)

atrox

in fairy dust... I trust!
Avatar
Registered: Sep 2002
Location: HTTP/1.1 404
Posts: 2782
ich werde nicht ganz schlau aus dem programm, weil es mehrere unterschiedliche lösungsansätze für das problem gibt, und nicht eindeutig klar ist was du meinst:
a) kann es sein dass du an einigen stellen help und root verwechselt hast, bzw warum verwendest du nicht root ?
b) oder wolltest du ein call-by-reference erreichen (dafür spricht, dass du versucht help zu verändern, ohne in wahrheit das "original" beim aufruf zu verändern
c) beim einfügen in einen binärbaum: entweder du verzweigst rekursiv in einen der äste ODER du schreibst deinen neuen wert in den baum - nicht beides gleichzeitig.

atrox

in fairy dust... I trust!
Avatar
Registered: Sep 2002
Location: HTTP/1.1 404
Posts: 2782
auf der suche nach einem einfachen selbstgeschriebenen beispielprogram hab ich folgende code-stücke gefunden:
Code:
typedef struct person *personptr;
struct person {
   char name[30];
   personptr kl,gr; // entspricht left und right
   };

void insert(personptr *wurzel,personptr element)
{ if (*wurzel) insert(strcmp((*wurzel)->name,element->name)<1?
                &(*wurzel)->kl:&(*wurzel)->gr,element);
  else *wurzel=element;
}
zeigt das einfügen in den baum, allerdings unter der annahme, daß malloc schon vor dem einfügen in den baum aufgerufen wurde. du siehst auch wie der call-by-reference nach strengen Ansi-C regeln gelöst wird: durch übergabe von pointern auf pointer (personptr*). in vielen modernen C-compilern kann man allerdings auch & in den funktionskopf aufnehmen und sich so ein bishen referenzerungs und dereferenzerungs-aufwand sparen.

das zweite code-stück hat eher erheiternden charakter es macht im prinzip das was dein program oben macht, zuerst strings einlesen, baum aufbauen (bis leerstring) und danach inorder ausgeben. habs trotzdem nicht geschafft unter die magischen 256 bytes zu kommen :(
Code:
#include <string.h>
#include <stdio.h>
#include <stdlib.h>
#define s strcmp
typedef struct pr *p;
struct pr {char n[30];p k,g;};
i(p*w,p e){(*w)?i(s((*w)->n,e->n)>0?&(*w)->k:&(*w)->g,e),e:[b][/b](*w=e);}
a(p w){if(w)a(w->k),puts(w->n),a(w->g);}
main(){p w=0,e;
while(e=malloc(sizeof(struct pr)),e->k=e->g=0,*gets(e->n))i(&w,e);
a(w);}

Brunnman

Addicted
Registered: Jul 2002
Location: Wien
Posts: 583
Zitat von atrox
ich werde nicht ganz schlau aus dem programm, weil es mehrere unterschiedliche lösungsansätze für das problem gibt, und nicht eindeutig klar ist was du meinst:
a) kann es sein dass du an einigen stellen help und root verwechselt hast, bzw warum verwendest du nicht root ?
b) oder wolltest du ein call-by-reference erreichen (dafür spricht, dass du versucht help zu verändern, ohne in wahrheit das "original" beim aufruf zu verändern
c) beim einfügen in einen binärbaum: entweder du verzweigst rekursiv in einen der äste ODER du schreibst deinen neuen wert in den baum - nicht beides gleichzeitig.

zu a) ich brauche help da root immer am beginn des baumes stehen soll.

zu b) ich möchte, dass help immer auf das letzte Elements zeigt, d.h. help sollte schon verändert werden.

c) d.h. ich soll bis zum freien Platz gehen und dann erst einfügren?


Daweil amal DANKE!
Brunnman

atrox

in fairy dust... I trust!
Avatar
Registered: Sep 2002
Location: HTTP/1.1 404
Posts: 2782
a & b) das passiert aber aus den oben erwähnten gründen nicht.
c) so ist es. du wanderst den baum entlang auf der suche nach einem freien platz und wenn du diesen gefunden hast, fügst du dein neues element ein.

Brunnman

Addicted
Registered: Jul 2002
Location: Wien
Posts: 583
ok danke ich glaube ich habe das problem irgendwie behoben...
es lebe die pfuscherei ;)

nur hab ich jetzt wieder ein prob...

Code:
FILE *filepointer;

scanf("%s",filename);
filepointer = fopen(filename, "r");
do
{
    fscanf(filepointer,"%20s",info);
    print(info);
}while(eof(filepointer==0)

welche abbruchbedingung muss ich da nehmen?

while(eof(filepointer==0)
haben wir in der Schule aufgeschrieben, das funzt aber nicht :(

atrox

in fairy dust... I trust!
Avatar
Registered: Sep 2002
Location: HTTP/1.1 404
Posts: 2782
while(feof(filepointer)==0)
bzw kurz:
while(!feof(filepointer))

//btw: was passiert, wenn die datei vollkommen leer ist ?

//edit: s/eof/feof/
Bearbeitet von atrox am 11.04.2003, 01:52

Brunnman

Addicted
Registered: Jul 2002
Location: Wien
Posts: 583
wenn die datei leer ist...

if(!filepointer) printf("%s","Error\n");
else
{
...
}

das muss ich noch einbaun...

Danke atrox!

atrox

in fairy dust... I trust!
Avatar
Registered: Sep 2002
Location: HTTP/1.1 404
Posts: 2782
naja, nicht ganz, wirst aber noch draufkommen :)
Bearbeitet von atrox am 10.04.2003, 12:32

Brunnman

Addicted
Registered: Jul 2002
Location: Wien
Posts: 583
ok das ist jetzt mein letztes Problem :(


[Linker error] undefined reference to `__gxx_personality_v0'



Im Borland C funzt das Prog, aber im Dev-C nicht :(

weiss wer warum der Linker Error ist?
brmatre_27466.txt (downloaded 50x)
Bearbeitet von Brunnman am 10.04.2003, 18:33

atrox

in fairy dust... I trust!
Avatar
Registered: Sep 2002
Location: HTTP/1.1 404
Posts: 2782
falls du aus dem selben verzeichnis heraus compilierst wie mit borland-c, lösche vorher alle .obj dateien aus dem verz.

FMFlash

tranceCoder
Avatar
Registered: Mar 2001
Location: Wien
Posts: 2037
Zitat von atrox
while(eof(filepointer)==0)
bzw kurz:
while(!eof(filepointer))

seh ich das richtig das sich hier eof zu feof genauso verhält wie - im vergangenen thread - send zu sendTo ?

bei der benutzung von fopen () verwende ich nämlich als bis-zum-ende-lesen-schleife: while (!feof(FILE*)) { ... } ... fclose (FILE*)

ps: es könnte nicht schaden als 2. parameter von fopen "r+t" anzugeben (t steht für "open in text (translated) mode"
just my 0,02€ ;)

that

Hoffnungsloser Optimist
Avatar
Registered: Mar 2000
Location: MeidLing
Posts: 11343
Zitat von FMFlash
ps: es könnte nicht schaden als 2. parameter von fopen "r+t" anzugeben (t steht für "open in text (translated) mode"
just my 0,02€ ;)

Es könnte schon schaden, weil "t" ist in keinem Standard definiert.

Zitat
WG14/N843 Committee Draft -- August 3, 1998

The argument mode points to a string. If the string is
one of the following, the file is open in the indicated
mode. Otherwise, the behavior is undefined.)

r open text file for reading
w truncate to zero length or create text file for writing
a append; open or create text file for writing at end-of-file
rb open binary file for reading
wb truncate to zero length or create binary file for writing
ab append; open or create binary file for writing at end-of-file
r+ open text file for update (reading and writing)
w+ truncate to zero length or create text file for update
a+ append; open or create text file for update, writing at end-of-file
r+b or rb+ open binary file for update (reading and writing)
w+b or wb+ truncate to zero length or create binary file for update
a+b or ab+ append; open or create binary file for update, writing at end-of-file

FMFlash

tranceCoder
Avatar
Registered: Mar 2001
Location: Wien
Posts: 2037
Zitat von that
Es könnte schon schaden, weil "t" ist in keinem Standard definiert.

afaik sind t und b in ANSI-C definiert und bestandteil der C standard library -> referenz

that

Hoffnungsloser Optimist
Avatar
Registered: Mar 2000
Location: MeidLing
Posts: 11343
"b" schon, "t" nicht. Sagt zumindest mein Standard-Draft (siehe oben - die echte Version ist ja nicht frei erhältlich, aber angeblich praktisch identisch) und meine Linux man-Page.

Zitat
The mode string can also include the letter ``b'' either as a last
character or as a character between the characters in any of the two-
character strings described above. This is strictly for compatibility
with ANSI X3.159-1989 (``ANSI C'') and has no effect; the ``b'' is
ignored on all POSIX conforming systems, including Linux. (Other sys-
tems may treat text files and binary files differently, and adding the
``b'' may be a good idea if you do I/O to a binary file and expect that
your program may be ported to non-Unix environments.)
Kontakt | Unser Forum | Über overclockers.at | Impressum | Datenschutz