[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