Programm läuft amok Hilfe!



  • Hi,

    ich habe ein Programm geschrieben das Eine Datei (Telefonbuch mit variablen index, nummer und name)per < Parameter einließt oder man kann auch die Werte per Hand eingeben. (beide stdin). Dann zum schluß soll das Programm das eingelesene wieder ausgeben.

    Ich habe mit switch und case ein menü eingebaut das dann die sachen ausgibt. aber das Problem ist ich komme nicht einmal dazu etwas auszuwählen weil sobald ich das Programm starte mit aufgabe36 < dat.txt das Programm das Menü immer wieder wiederholt. Wie eine schleife und es hört nie auf. Meiner Meinung nach muß das Problem bei der funktion get_data liegen oder add_element da wo ich es in die verkettet liste eingebe. wäre echt cool wenn mir da einer hilft und sich da mal anschaut. copilieren funktioniert ohne Warnmeldungen. Das Programm ist in modulen aufgeteilt: main.c, tele.h(hier ist das struct für die Liste) und funktion.c wo die ganzen Funktionen (glaube man sagt)deklariert sind.

    Das Programm soll später mit binärem Suchen ergänzt werden. Ist halt ne aufgabe die ich mit Verketteten listen lösen muß. Die funktion search und enter habe ich mal so prepariert das das Programm läuft. also nicht erschrecken wenn da drin müll steht.

    THX in vorraus

    Hier der Code:

    main.c

    #include <stdio.h>
    #include <stdlib.h>
    #include <string.h>
    #include "tele.h"
    
    int main()
    {
      int wahl;
    
      get_data();
    
      do
      {
        puts("Wählen Sie!");
        puts("(1) Nach Namen suchen in der Telefonliste");
        puts("(2) Programm beenden");
    
        scanf("%d", wahl);
    
        switch(wahl)
         {     
              case 1: search(enter());
                        break;
              case 2: return 0;
                        break;
              default: printf("Ungültige Eingabe!");
         }
      }while (wahl!=2);
      free_element();
    return 0;
    }
    

    tele.h

    #ifndef TELE_H
    #define TELE_H
    
    typedef struct tele{
        long int index;
        long int number;
        char name[20];
        struct tele *next;
        struct tele *prev;
        }TELE;
    
    extern TELE *anfang;
    extern TELE *ende;
    
    extern void get_data();
    extern void add_element(long int t_index,long int t_number,char *t_name);
    extern TELE *create_list_element(TELE *ptr);
    extern long int enter();
    extern void search(long int key);
    extern void free_element();
    
    #endif
    

    und die function.h

    #include "tele.h"
    #include <stdio.h>
    #include <stdlib.h>
    #include <string.h>
    
    TELE *anfang=NULL;
    TELE *ende=NULL;
    
    TELE *create_list_element(TELE *ptr)
    {
        if((ptr=(TELE *)malloc(sizeof(TELE)))==NULL){
            fprintf(stderr,"Fehler bei der speicherreservierung!\n");
            exit;
                }
        return ptr;
    }
    
    void add_element(long int t_index,long int t_number,char *t_name)
    {
       TELE *zeiger;
       if(anfang==NULL){
          anfang=create_list_element(anfang);
          anfang->index=t_index;
          anfang->number=t_number;
          strcpy((anfang->name), t_name);//anfang->name=t_name[];
          anfang->next=NULL;
          anfang->prev=NULL;
          }
       else{
          zeiger=anfang;
          while(zeiger->next!=NULL)
          {     
                zeiger=zeiger->next;
          }
          ende=create_list_element(zeiger);
          zeiger->next=ende;
          ende->index=t_index;
          ende->number=t_number;
          strcpy((anfang->name), t_name);//ende->name=t_name[];
          ende->next=NULL;
          ende->prev=zeiger;
          }
          return;
    }
    
    void get_data()
    {
        char line[256], *a, *b;
        long int temp_index, temp_number;
    
        while(fgets(line, sizeof(line),stdin))
        {
            temp_index=strtol(line, &a, 10);
            temp_number=strtol(a, &b, 10);
    
            add_element(temp_index,temp_number, b);
        }
        return;
    }
    
    long int enter()
    {
        long int telefon_nummer;
        puts("Geben Sie eine Telelfonnummer ein!");
        scanf("%dl", &telefon_nummer);
    
        return telefon_nummer;
    }
    
    void search(long int key)
    {
        TELE *zeiger;
    
        zeiger=anfang;
        while((zeiger->next)!=NULL)
        {
            printf("Index: %dl            Nummer: %dl            Name: %s          ",zeiger->index,zeiger->number,zeiger->name );
            zeiger=zeiger->next;
        }
        printf("Index: %dl            Nummer: %dl            Name: %s          ",zeiger->index,zeiger->number,zeiger->name );
        return;
    }
    
    void free_element()
    {
        free(anfang);
        free(ende);
        return;
    }
    


  • Es muß heißen:
    scanf("%d", &wahl);



  • Stimmt das da ein Fehler ist hat aber trotzdem nichts gebracht noch einen Tipp vielleicht oder so?



  • ich habs mir jetzt nur kurz angeschaut

    hier meine einwuerfe:

    der code:

    #include <stdio.h> 
    #include <stdlib.h> 
    #include <string.h> 
    #include "tele.h" 
    
    int main() 
    { 
      int wahl; 
    
      get_data(); 
    
      do 
      { 
        puts("Wählen Sie!"); 
        puts("(1) Nach Namen suchen in der Telefonliste"); 
        puts("(2) Programm beenden"); 
    
        scanf("%d", wahl); 
    
        switch(wahl) 
         {     
              case 1: search(enter()); 
                        break; 
              case 2: return 0; 
                        break; 
              default: printf("Ungültige Eingabe!"); 
         } 
      }while (wahl!=2); 
      free_element(); 
    return 0; 
    }
    
    1. du liest wahl ein per scanf - scanf erwartet sich den zeiger auf eine variable

    das heisst
    scanf("%d", wahl);
    gehoert ersetzt durch
    scanf("%d", &wahl);

    was sonst noch
    return 0; im case statement ist nicht sehr gluecklich
    das springt aus dem program
    dementsprechend wird free_element() nie gemacht

    das sollte es mal sein

    gomberl



  • ach ja - ein leeren (flush) des stdin puffers kann auch nicht schaden
    mit fflush(stdin)



  • Es springt aus dem Programm aber das nur wenn man Beenden will oder ein Fehler auftritt... und nur dann soll die liste auch gelöscht werden macht ja sonst keinen sinn mit der verketteten liste.



  • Außerdem: exit(1); statt exit;
    und bei sowas
    case 2: return 0;
    break;
    brauchst Du wirklich kein break mehr!
    Deine Formatierung ist auch sehr schwer lesbar.
    Sowas
    if((ptr=(TELE )malloc(sizeof(TELE)))==NULL)
    while(zeiger->next!=NULL)
    schreibt man gewöhnlich prägnanter
    if(!(ptr = (TELE
    ) malloc(sizeof(TELE))))
    while(zeiger->next)
    Wenn Du schon eine create_list_element()-Funktion spendierst, sollte dadrinne auch die Initialisierung geschehen.
    Das letzte return in void-Funktionen kannst Du Dir auch schenken, das dient höchsten der Verwirrung.
    Die free_element()-Funktion löscht nur das erste und das letzte Element der Liste.
    Niemand (?) schreibt long int, man schreibt einfach long.
    void search(long int key): key wird nicht benutzt.



  • Ok habe alles so geändert und mehrere fflushs eingebaut aber das Programm läuft immer noch so wie am Anfang? Hab das Gefühl das es irgendwo da bei add_element nicht klappt oder so.



  • Ich poste mal das neue jetzt

    main.c

    #include <stdio.h>
    #include <stdlib.h>
    #include <string.h>
    #include "tele.h"
    
    int main()
    {
      int wahl;
    
      get_data();
    
      do
      {
    
        puts(" ");
        puts("    Wählen Sie!");
        puts("(1) Nach Namen suchen in der Telefonliste");
        puts("(2) Programm beenden");
        scanf("%d", &wahl);
    
        switch(wahl)
         {     
              case 1: search(enter());
                        break;
              case 2: return 0;
              default: printf("    Ungültige Eingabe!\n");
    
         }
      }while (wahl!=2);
      free_element();
    return 0;
    }
    

    tele.h

    #ifndef TELE_H
    #define TELE_H
    
    typedef struct tele{
        long index;
        long number;
        char name[20];
        struct tele *next;
        struct tele *prev;
        }TELE;
    
    extern TELE *anfang;
    extern TELE *ende;
    
    extern void get_data();
    extern void add_element(long t_index,long t_number,char *t_name);
    extern TELE *create_list_element(TELE *ptr);
    extern long enter();
    extern void search(long key);
    extern void free_element();
    
    #endif
    

    und die function.c

    #include "tele.h"
    #include <stdio.h>
    #include <stdlib.h>
    #include <string.h>
    
    TELE *anfang=NULL;
    TELE *ende=NULL;
    
    TELE *create_list_element(TELE *ptr)
    {
        if(!(ptr=(TELE *)malloc(sizeof(TELE)))){
            fprintf(stderr,"Fehler bei der speicherreservierung!\n");
            exit(1);
                }
        return ptr;
    }
    
    void add_element(long t_index,long t_number,char *t_name)
    {
       TELE *zeiger;
       if(anfang==NULL){
          anfang=create_list_element(anfang);
          anfang->index=t_index;
          anfang->number=t_number;
          strcpy((anfang->name), t_name);//anfang->name=t_name[];
          anfang->next=NULL;
          anfang->prev=NULL;
          }
       else{
          zeiger=anfang;
          while(zeiger->next!=NULL)
          {     
                zeiger=zeiger->next;
          }
          ende=create_list_element(zeiger);
          zeiger->next=ende;
          ende->index=t_index;
          ende->number=t_number;
          strcpy((anfang->name), t_name);//ende->name=t_name[];
          ende->next=NULL;
          ende->prev=zeiger;
          }
    
    }
    
    void get_data()
    {
        char line[256], *a, *b;
        long temp_index, temp_number;
        int i; 
    
        for (i=0; i<5;i++)
        {    
            while(fgets(line, sizeof(line),stdin))
                {
                        temp_index=strtol(line, &a, 10);
                        temp_number=strtol(a, &b, 10);
                        fflush(stdin);
                        add_element(temp_index,temp_number, b);
    
                }
        }
    
    }
    
    long enter()
    {
        long telefon_nummer;
        puts("Geben Sie eine Telelfonnummer ein!");
        scanf("%dl", &telefon_nummer);
    
        return telefon_nummer;
    }
    
    void search(long key)
    {
        TELE *zeiger;
    
        zeiger=anfang;
        while((zeiger->next)!=NULL)
        {
            printf("Index: %dl            Nummer: %dl            Name: %s          ",zeiger->index,zeiger->number,zeiger->name );
            zeiger=zeiger->next;
        }
        printf("Index: %dl            Nummer: %dl            Name: %s          ",zeiger->index,zeiger->number,zeiger->name );
    
    }
    
    void free_element()
    {
        free(anfang);
        free(ende);
    
    }
    


  • ach ja - ein leeren (flush) des stdin puffers kann auch nicht schaden
    mit fflush(stdin)

    fflush(stdin); ist `undefined behavior'. Siehe auch hier



  • Es muß einmal strcpy(ende->name, t_name); heißen.
    Außerdem mußt Du dein Programm so starten:
    aufgabe36 dat.txt
    Die get_data()-Funktion muß daraufhin die übergebene Datei zeilenweise auslesen, und nicht, wie Du, die Zeilen von stdin einlesen!!!???!!!

    Was das Menü betrifft, so vermeide scanf(), das macht immer Probleme wegen der unbekannten int-Größe; besser gets() verwenden:

    int main(int argc, char** argv)
    {
    	char puffer[999];
    	char* datei;
    
    	if(argc < 2)
    	{
    		printf("Welche Datei soll geladen werden? ");
    		gets(puffer);
    		datei = puffer;
    	}
    	else
    		datei = argv[1];
    
    	get_data(datei);
    
    	for(;;)
    	{
    		puts("Wählen Sie!");
    		puts("(1) Nach Namen suchen in der Telefonliste");
    		puts("(2) Programm beenden");
    
    		gets(puffer);
    
    		switch(*puffer) 
    		{
    		case '1':
    			search(enter());
    			break;
    		case '2':
    			free_element();
    			return 0;
    		default:
    			printf("Ungültige Eingabe!");
    		}
    	}
    }
    


  • Ich habe das mal von dir übernommen aber nun stürzt das Programm ab habe das mal so abgändert... es stürtzt dann ab wenn es anfängt einzuleisen... die eingabe funzt....

    Danke dir dasdu mir so hilfst!

    void get_data(char *dat)
    {
        char line[256], *a, *b;
        long temp_index, temp_number;
        int i; 
    
            while(fgets(line, sizeof(line),dat))
                {
                        temp_index=strtol(line, &a, 10);
                        temp_number=strtol(a, &b, 10);
                        fflush(stdin);
                        add_element(temp_index,temp_number, b);
    
                }
    
    }
    

    Hier noch die Warnung vom Compiler:
    [Warning] passing arg 3 of `fgets' from incompatible pointer type



  • Hallo,

    du mußt erst einmal die Datei öffnen, bevor du mit fget lesen kannst. Hier einmal eine Änderung zum bisherigen Code:

    int get_data(const char *dat) 
    { 
        char line[256], *a, *b; 
        long temp_index, temp_number; 
        FILE *stream;
        int noerror = 1;
    
        if( (stream = fopen( dat, "r" )) != NULL )
        {
             while(fgets(line, sizeof(line),stream)) 
             { 
                        temp_index=strtol(line, &a, 10); 
                        temp_number=strtol(a, &b, 10); 
                        fflush(stdin); 
                        add_element(temp_index,temp_number, b); 
    
             }
    
             if (!feof(stream)) noerror = 0;
    
             fclose( stream );
         }
         else
             noerror = 0;
    
         return noerror;
    }
    

    in main kann dann die Funktion so eingesetzt werden:

    ...
    ...
        if(argc < 2)
        {
            printf("Welche Datei soll geladen werden? ");
            gets(puffer);
            datei = puffer;
        }
        else
            datei = argv[1];
    
    if (!get_data(datei)) 
    {
       printf("\nFehler beim Einlesen\n");
       return 1;
    }
    
        for(;;)
        {
      ........
      ........
      ........
    

    MfG



  • Krösus schrieb:

    ...besser gets() verwenden:...

    Anstatt gets() wäre fgets() besser, da man bei fgets() einen Bufferoverflow abfangen kann!



  • AJ schrieb:

    Anstatt gets() wäre fgets() besser, da man bei fgets() einen Bufferoverflow abfangen kann!

    korrekt, "secure programming" ist angesagt, aber bei mir nicht mehr um "02:50:16 03.03.2004" :), um die Zeit war nur noch copy & paste drin...

    MfG



  • wofür das feof?

    Danke!



  • die Abfrage auf feof stellt sicher, daß die Datei auch fehlerfrei eingelesen wurde. Wenn feof nicht erkannt wurde, dann muß ein anderer Fehler schon beim Lesen (mittendrin) passiert sein (z.B. nicht vollständig eingelesen). Wurde feof erkannt, dann ist mit dem Verlassen der while-Schleife auch klar, daß wirklich alles eingelesen wurde (weil feof prüft, ob man bis zum Datei-Ende gekommen ist)

    MfG



  • Wie kann ich eigentlich sagen das er beim einlesen die Leerzeilen überspringt sondern nur die Werte nimmt? geht das mit fgets?



  • Nein mit fgets() nicht, aber mit fscanf().



  • Oh man das heißt das Ganze Prog ist am Ars. Egal habe dabei etwas gelernt!


Anmelden zum Antworten