[Erledigt]Problem mit dynamischer Listenverwaltung



  • Guten Tag,
    Ich programmiere momentan ein kleines Programm, dass mir aus Mp3-Daten vorhandene Metadaten ausliest.
    Allerdings hätte ich hierzu gerne eine "einfach verkette" Liste, die dynamisch sein sollte,

    #include <stdio.h>
    #include <conio.h>
    #include <string.h>
    #include <stdlib.h>
    #include <malloc.h>
    #include "header.h"
    
        struct s_TAG
        {    
         int     Anzahl;
         char a_tit[256];
         char a_interpret[256];
         char a_alb[256];
         struct s_TAG *p_next;    
         }*p_TAGKopf, *p_Temp;
    
    int Laden()
    {
    
        FILE *schreiben, *schreiben2;
        FILE *mp3File;
        char stringbuffer[256], Eingabe[5];
        int data=0, weiter=0;
    
           struct s_TAG *p_TAGZeiger = NULL;
        p_TAGZeiger = (struct s_TAG*) malloc (sizeof (struct s_TAG));
        p_TAGKopf = p_TAGZeiger;
        p_TAGZeiger->Anzahl=1;
    
    do
    {
    
        printf("Namen der Mp3-Datei eingeben: ");
        scanf("%s",stringbuffer);
    
        mp3File=fopen(stringbuffer, "rb");
        if(!mp3File)
        {
            printf("Datei konnte nicht geoeffnet werden.");
        }
    
        //Suche des Titels
        while(fread(stringbuffer, 4, 1, mp3File)==1)
        {
            //Kopfieren von Titel
            if(strncmp(stringbuffer, "TIT2", 4)==0)
            {
                //7-Bytes weiter springen
                fseek(mp3File, 7, SEEK_CUR);
    
                fgets(stringbuffer, 256, mp3File);
    
                //Entfernen des TIT2 \0
                stringbuffer[strlen(stringbuffer)-4]=0;
    
                //Kopieren von stringbuffer in Titel
                strcpy(p_TAGZeiger->a_tit, stringbuffer);
    
                break;
            }
    
            else
                fseek(mp3File, -3, SEEK_CUR);
        }
    
        //Anfang der Datei
        fseek(mp3File, 0, SEEK_SET);
    
        while(fread(stringbuffer, 4, 1, mp3File)==1)
        {
            //Suchen nach dem Interpreten
            if(strncmp(stringbuffer, "TPE1", 4)==0)
            {
                fseek(mp3File, 7, SEEK_CUR);
                fgets(stringbuffer, 256, mp3File);
                stringbuffer[strlen(stringbuffer)-4]=0;
                strcpy(p_TAGZeiger->a_interpret, stringbuffer);
                break;
            }
            else
                fseek(mp3File, -3, SEEK_CUR);
        }
    
        fseek(mp3File, 0, SEEK_SET);
    
        //Albumsuche
        while(fread(stringbuffer, 4, 1, mp3File)==1)
        {
    
            if(strncmp(stringbuffer, "TALB", 4)==0)
            {
                fseek(mp3File, 7, SEEK_CUR);
                fgets(stringbuffer, 256, mp3File);
                stringbuffer[strlen(stringbuffer)-4]=0;
                strcpy(p_TAGZeiger->a_alb, stringbuffer);
                break;
            }
            else
                fseek(mp3File, -3, SEEK_CUR);
        }
        p_TAGZeiger->p_next = NULL;   
    
        printf("\n----ID3v2 Informationen----\n");
        printf("Titel: %s\n", p_TAGZeiger->a_tit);
        printf("Interpret: %s\n", p_TAGZeiger->a_interpret);
        printf("Album: %s", p_TAGZeiger->a_alb);
    
        printf ("\n\nWeitere Mp3_Datei laden? [JA]/[NEIN]: ");
        scanf("%s",Eingabe);
    
                         if ((Eingabe[0]=='N')||(Eingabe[0]=='n'))
                         {
                         weiter=2;
                         }
                         else if ((Eingabe[0]=='J')||(Eingabe[0]=='j'))
                         {
    
        p_TAGZeiger = p_TAGKopf;
        while (p_TAGZeiger->p_next != NULL)
            p_TAGZeiger = p_TAGZeiger->p_next;
    
        struct s_TAG *p_TAGNeu = NULL;
    
        p_TAGNeu = (struct s_TAG*) malloc (sizeof (struct s_TAG));
        p_TAGZeiger->p_next = p_TAGNeu;
        p_TAGZeiger = p_TAGZeiger->p_next;
        p_TAGZeiger->Anzahl =p_TAGZeiger->Anzahl+1;
    
                          weiter=1;  
                         }
                         else
                         {
                         printf ("Falsche Eingabe!");
                         }
    
    }
    while(weiter==1);
    
                      schreiben2 = fopen("Ini.txt""w+");
                      fprintf (schreiben2,"%i\n", p_TAGZeiger->Anzahl);
                      fclose(schreiben2);
    
    for(weiter=0;weiter<p_TAGZeiger->Anzahl;weiter++)
    {
        //schreiben in .txt
    
        schreiben = fopen("Mp3-Daten.txt""a");
    
        fprintf (schreiben,"\n\n");
        fprintf (schreiben,"----ID3v2 Information----\n");
        fprintf (schreiben,"Interpret: %s\n", p_TAGZeiger->a_interpret);
        fprintf (schreiben,"Titel: %s\n", p_TAGZeiger->a_tit);
        fprintf (schreiben,"Album: %s\n", p_TAGZeiger->a_alb);
    
        fclose (schreiben);
        schreiben2 = fopen("Ini.txt""a");
    
        fprintf (schreiben2,"%s\n", p_TAGZeiger->a_interpret);
        fprintf (schreiben2,"%s\n", p_TAGZeiger->a_tit);
        fprintf (schreiben2,"%s\n", p_TAGZeiger->a_alb);
    
        fclose(schreiben2);
    
    }
    
        return 0;
    }
    

    Leider verstehe ich einfach nicht warum es so nicht funktioniert :).
    Würde mich sehr freuen, wenn mir jemand helfen könnte.
    vielen Dank schon mal im Voraus
    mit freundlichen Grüßen



  • DonnerKeks schrieb:

    Leider verstehe ich einfach nicht warum es so nicht funktioniert

    was passiert denn stattdessen, absturz, garnichts, falsche daten, etc.?
    🙂



  • Wenn man beispielsweise 2 test.mp3 einfügt
    stehen dann am Schluss in der erzeugten Mp3-Daten.txt
    2* die Daten von der 2. test.mp3.
    Meine Vermutung ist, dass keine neue Struktur im Hauptspeicher angelegt wird sondern einfach die bereits bestehende überschrieben, also scheinbar ein Fehler mit den Pointern den ich aber leider nicht finde 🙂



  • Hallo,
    für meinen Geschmack sind da zu viele fseek/fread Anweisungen drin.
    Mein Vorschlag ist,
    schreib dir Strukturen, die in etwa so aussehen,

    #define SLEN 30
    
    typedef struct ID3Tag ID3Tag;
    typedef struct ID3Head ID3Head;
    
    struct ID3Tag {
        char title[SLEN+1];
        char artist[31];
        char album[31];
    ...
    	ID3Tag* next;
    };
    
    struct ID3Head {
    	ID3Tag* first; // Speichert den Anfang der Liste.
    	ID3Tag* current; // Speichert das zuletzt angehängte Element.
    	unsigned n; // Speichert die Anzahl (wenn es denn sein muss :).
    };
    

    und lies das ID3 Tag komplett in solch eine Struktur ein. Die hängst du an deine Liste an.

    Zu deinem Verkettete-Listen-Problem: ich würde mir erst ein Minimalprogramm
    schreiben, das eine verkettete Liste aufbaut und z.B. die Titel anzeigt, die
    man per stdin eingibt. Dann erst würde ich das funktionierende Beispiel ausbauen und ans Einlesen der Datei rangehen.

    Gruß,
    B.B.



  • Btw. hast du da nen ganz schönen Spaghetticode. Es ist von Vorteil, den Code zu strukturieren, in kleine Teilaufgaben zu zerlegen und diese in Funktionen zu erledigen. Dann ist die Wahrscheinlichkeit größer, das du auch nach einer längeren Programmierpause durch den Code durchblickst.

    Hier kannst du dir angucken, wie ich das z.B. mit dem ID3 Header meine. Achja, man braucht die Liste nicht immer wieder von vorn zu durchlaufen, um ein neues Element anzuhängen:

    ID3Tag* new_tag() {
    	return calloc ( 1, sizeof(ID3Tag) ); // Calloc initialisiert alle Structmember mit 0.
    }
    
    void append_tag ( ID3Head* phead, ID3Tag* id3tag ) {
    	if ( phead->first == NULL )
    		phead->current = phead->first = id3tag;
    	else
    		phead->current = phead->current->next = id3tag;
    	phead->n++; // Anzahl erhöhen.
    }
    
    void view_list ( ID3Head* phead ) {
    	ID3Tag* id3tag = phead->first;
    	printf( "Showing list, %u entries: \n", phead->n );
    	while ( id3tag )
    		printf("%s", id3tag->title), id3tag = id3tag->next;
    }
    
    void free_list ( ID3Head* phead ) {
    	ID3Tag* id3tag = phead->first;
    	while ( id3tag )
    		id3tag = id3tag->next, free ( phead->first ), phead->first = id3tag;
    	puts("List freed.");
    }
    
    int eret( ID3Head* phead, char* s ) {
    	fprintf ( stderr, "%s %s\n", s, strerror(errno)); // string.h, errno.h
    	free_list ( phead );
    	return 0;
    }
    
    int main() { 
    	ID3Head phead = {0}; // Initialisierung aller Struct Member mit 0.
    	ID3Tag* id3tag = NULL;
    	char buf[BUFSIZ+1] = {0};
    
    	puts( "Titel eingeben, beenden mit Entertastendruck." );
    
    	while ( fgets ( buf, sizeof(buf), stdin )) {
    		if ( *buf == '\n' )
    			break; // Wird die Entertaste ohne weitere Eingabe gedrückt, ist nur das '\n' im Puffer.
    		if ( NULL == ( id3tag = new_tag()))
    			return eret ( &phead, "new_tag() failed!" );
    		strncpy ( id3tag->title, buf, SLEN );
    		append_tag ( &phead, id3tag );
    	}
    	view_list ( &phead );
    	free_list ( &phead );
    	return 0;
    }
    


  • erst mal vielen Dank für deine so ausführliche Erklärung
    leider bin ich noch ein echter Anfänger was das Programmieren betrifft
    und finde es echt interessant wie man das noch schreiben kann 😃
    werde deine Tips auf jeden Fall in zukünftige Quellcodes mit einbeziehen^^
    btw: mein Programm funktioniert endlich
    nochmal vielen Dank


Anmelden zum Antworten