Dynamischen langen String Parsen

Hast eigentlich recht...bin schon so von VS verwöhnt...
Werd in Zukunft mehr darauf achten und habs oben auch editiert.
Besser so?
Viel besser :) Danke.

Schau mal... der String beihaltet immer mal mehr Wörter oder Zahlen und mal weniger. Diese sind durch ein Blank von einander getrennt. Wenn ich jetzt also mit sscanf arbeiten möchte, muss ich von vorn herein wissen, wie lang mein String ist. Sprich das geht nur, wenn mein String immer eine constant Anzahl von Wörtern bzw. Zahlen besitzt.
Wie kommst du darauf? sscanf ist es egal, wie viele Wörter in der Zeichenkette sind. Hast du den Quellcode von Muepe32 denn ausprobiert? Er funktioniert nämlich.

in der Referenz steht auch nur, dass bei %s bis zu einem Whitespace gelesen wird. Welches in meinem fall gut wäre, da ich ja das erste Wort bis zum Whitespace aus meinem String lesen möchte. aber dies ist halt nicht der Fall. Wenn ich das Ergebnis mit printf lese, wird gar nichts aus gegeben.
Dass dein Quellcode aus dem ersten Beitrag so nicht funktioniert, ist dir ja wohl klar?! Du reservierst ja überhaupt keinen Speicher für string2.

Matthias Reitinger hat mich auf Anhieb verstanden was ich eigentlich wollte. Dennoch finde ich seine Lösung nicht gerade die Beste!! wollte schon irgentwie mit der Funktion sscanf arbeiten, aber in der Referenz steht ebend nicht drin, wie ich mit variable langen Strings - ich sags nochmal - die eine verschiedene Wortanzahl haben können, nur das erste Wort isolieren kann, um dieses für einen Vergleich mit strcasecmp verwenden kann.
Meine Lösung funktioniert und legt keine unnötige Kopie des Wortes an. Was willst du denn noch? Warum du krampfhaft versuchst, mit sscanf zu arbeiten, verstehe ich übrigens nicht.

Grüße,
Matthias

\edit:
PS. weil ich die letzten 2 Berichte erst später gelesen habe, das Erste Wort, welches ich abfangen möchte, ist auch immer unterschiedlich lang. D.H. strncpy kommt nicht in Frage!
Wieso nicht? :confused:
 
Zuletzt bearbeitet:
Wie kommst du darauf? sscanf ist es egal, wie viele Wörter in der Zeichenkette sind. Hast du den Quellcode von Muepe32 denn ausprobiert? Er funktioniert nämlich.

Ja.. ich möchte es aber lieber vermeiden, unnötig Speicher -> char string2[255]; zu reservieren als vielleicht mein wort gebraucht hätte.

Dass dein Quellcode aus dem ersten Beitrag so nicht funktioniert, ist dir ja wohl klar?! Du reservierst ja überhaupt keinen Speicher für string2.

Das ich immer Speicher neu reservieren muss, war mir nicht klar, weil ich nicht weiß wieso, wenn ich nur ein Wort aus einem string kopieren möchte. Wenn das so ist, wie so nicht auch bei den Funktionen: strtok oder sscanf? Da wird doch auch nie vorher Speicher allokiert. Wieso also bei meiner Variable "string2", wenn ich die mit char* deklariere und dann mit NULL initialisiere? Wenn ich da eine Wissenslücke habe, bitte um Aufklärung. Bin immer noch nicht firm, was C betrifft, da ich viel zu verwöhnt bin von Java!

Meine Lösung funktioniert und legt keine unnötige Kopie des Wortes an. Was willst du denn noch? Warum du krampfhaft versuchst, mit sscanf zu arbeiten, verstehe ich übrigens nicht.

..ich denke mir einfach, das müsse doch noch praktischer von statten gehen. kann mir nicht vorstellen, das man das so wie Du das gemacht hat, so kompliziert gemacht werden muss. natürlich geht das auch so. aber vielleicht ist das auch nicht die eleganteste Lösung!

Gruß.
 
Zuletzt bearbeitet:
Wenn du nicht unnötig viel Speicher reservieren möchtest, such doch einfach nach dem ersten Leerzeichen etc
und finde so heraus, wieviel Buchstaben es bis dahin sind.
Auch wenn mein Code vorher nicht schön formatiert war, zeigt er das prinzipiell.

Und auch für sscanf (um das es ja gerade geht) muss man zuerst Speicher haben.
string ist ja schon vorhanden, nur string2 eben noch nicht.
Und dabei ist es egal, ob die Menge zuviel oder genau richtig ist, aber es muss was da sein.

Auch in Java kannst du nicht xyz=null; schreiben und xyz dann verwenden.
In Java wirds halt NullPointerException genannt.
 
Hi sheel,

hab mal Deinen Code nach gebaut

C:
...
char* string = NULL;
		char* string2 = NULL;

int i = 0;
while(string[i] != ' ')
			{
				i++;
				string2 = (char*) malloc(i);
			}
strncpy(string2, string, i);

printf("string: %s\n", string2);

if(strcasecmp((char*) neuer_String, string2) == 0)
			{

Das Programm zeigt mir jetzt auch immer nur das erste Wort auf der Konsole an und bricht dann nach ca. 20 Wörten ab und gibt dann folgendes wieder.

C:
...
string: und
string: Medizin
string: Und
string: leider
string: auch
string: Theologie
string: Durchaus
string: studiert
string: mit
string: heissem
string: Bemuehn
string: Da
string: steh
string: ich
string: nun
string: ich
string: armer
string: Tor
string: Und
string: Habe
Liste: malloc.c:3096: sYSMALLOc: Assertion `(old_top == (((mbinptr) (((char *) &((av)->bins[((1) - 1) *
2])) - __builtin_offsetof (struct malloc_chunk, fd)))) && old_size == 0) || ((unsigned long) (old_size) >=
(unsigned long)((((__builtin_offsetof (struct malloc_chunk, fd_nextsize))+((2 * (sizeof(size_t))) - 1)) & 
~((2 * (sizeof(size_t))) - 1))) && ((old_top)->size & 0x1) && ((unsigned long)old_end & pagemask) ==
0)' failed.
Abgebrochen
Davicito@ubuntu:~/C/Beleg_01$

Damit kann ich leider nichts anfangen. Wiss Ihr vielleicht was ich hier wieder falsch gemacht habe?

Gruß.
 
Zuletzt bearbeitet:
Kannst du den Code posten, der diese Ausgabe erzeugt?
Der gezeigt ist es sicher nicht, der stürzt nämlich sofort ab.

Und da es wahrscheinlich nicht so lang ist, bitte gleich das komplette Programm.

PS: Das Programm ist als Debug kompiliert, oder?
 
wie du willst.

C:
...
if(kopf == aktl_Elem -> left && aktl_Elem -> content == NULL)
{	
		char* conttmp = (char*) set(neuer_String);
		//! Blank hinten einfügen
		strcat(conttmp, " ");
		//! Dateinmane hinten einfügen
		strcat(conttmp, (char*) set(dateiname));
		//! Blank hinten einfügen
		strcat(conttmp, " ");
		//! ZeilenCounter für ListenContent in Zeichen umwandeln
		char t[6];
		sprintf(t, "%i", counter);
		//! ZeilenCounter hinten einfügen
		strcat(conttmp, (char*)set((void*)t));
		//! Alle Parameter in Content einfügen
		neu_Elem -> content     = set((void*) conttmp);
		//printf("conttmp: %s\n", (char*) (neu_Elem -> content) );
}
else 
{
       char* string = NULL;
		char* string2 = NULL;
		
		while(kopf != (aktl_Elem = aktl_Elem -> left))
		{
			
			string = (char*) aktl_Elem -> content;
			
			int i = 0;
            while(string[i] != ' ')
            {
                i++;
                string2 = (char*) malloc(i);
            }
            strncpy(string2, string, i);	
			
			printf("string: %s\n", string2);

			if(strcasecmp((char*) neuer_String, string2) == 0)
			{
				char* conttmp = (char*) aktl_Elem -> content;
				//! ZeilenCounter für ListenContent in Zeichen umwandeln
				char t[6];
				sprintf(t, "%i", counter);
				//! ZeilenCounter hinten einfügen
				strcat(conttmp, (char*)set((void*)t));
				neu_Elem -> content     = set((void*) conttmp);
			}
			else
			{
				char* conttmp = (char*) set(neuer_String);
				//! Blank hinten einfügen
				strcat(conttmp, " ");
				//! Dateinmane hinten einfügen
				strcat(conttmp, (char*) set(dateiname));
				//! Blank hinten einfügen
				strcat(conttmp, " ");
				//! ZeilenCounter für ListenContent in Zeichen umwandeln
				char t[6];
				sprintf(t, "%i", counter);
				//! ZeilenCounter hinten einfügen
				strcat(conttmp, (char*)set((void*)t));
				//! Alle Parameter in Content einfügen
				neu_Elem -> content     = set((void*) conttmp);
				//printf("conttmp: %s\n", (char*) (neu_Elem -> content) );
			}
			
		}
}
...

PS. ja das Programm ist fehlerfrei kompiliert worden.
 
Zuletzt bearbeitet:
Das ist zwar auch kein Komplettprogramm...wenn es fürs Forum zu lang wird,
kannst du ruhig die Datei anhängen.
Ich werd von der Codemenge sicher nicht erschlagen.

Ich versuch, so gut wie möglich auf das sichtbare einzugehen:
C++:
        char* string = NULL;
        char* string2 = NULL;
        
        while(kopf != (aktl_Elem = aktl_Elem -> left))
        {
            
            string = (char*) aktl_Elem -> content;
            
            int i = 0;
            while(string[i] != ' ')
            {
                i++;
                string2 = (char*) malloc(i);
            }
            strncpy(string2, string, i);    
            
            printf("string: %s\n", string2);
In der Schleife weist du String schonmal was zu. Gut.

Das strncpy und printf am Schluss schauen auch OK aus.

Die Schleife mit dem malloc allerdings ist grausam.
Angenommen, das erste Wort hat 8 Buchstaben, reservierst du 1, dann 2, dann 3...bis 8 Byte.
Macht bei 8 Buchstaben ca. 36 Byte, bei 10 55 usw...
Erstens brauchst du das Ganze garnicht, zweitens ist nirgends ein free drinnen.
Schau nocheinmal meine Codezeilen an. Da ist das malloc außerhalb der Schleife.

Der eigentliche Fehler lässt sich im geposteten Code nicht finden.

Zum PS: Ich meinte, ob du es als Debug oder Release kompiliert hast.

Gruß

PS: Der Satz in der Ausgabe...ist das Faust?
 
Zuletzt bearbeitet:
Uff!

Debugen unter Ubuntu weiß nicht nicht wie man das machen kann!

und 2. ich habe folgendes vor.
meine anhaeng-Funktion soll Wörter, was es bekommt in meine doppelt verkettete generische Liste einfügen.

der funktionierende Code dazu sieht so aus.

C:
typedef struct node
{
	struct node* right; // Zeiger auf das Nachfolgerelement
	struct node* left;  // Zeiger auf das Vorgängerelement
	void* content; // Für den Dateninhalt	
} node;
...

C:
...
#include "Liste.h"

node* init_Liste()
{
	node* n = (node*) malloc(sizeof(node));
	n -> right   = n;
	n -> left    = n;
	n -> content = NULL;
		
	return n;
}

node* anhaengen(node* list, void* neuer_String, void* dateiname, void* (*set)(void*), int counter)
{
	node* neu_Elem = (node*) malloc(sizeof(node)); //! Speicher für neuen Knoten besorgen 
	//! Überprüfen, ob Speicher angelegt worden ist	
	if(neu_Elem == NULL)
	{
		printf("\n Listenelement konnte nicht angelegt werden, da kein Speicher vorhanden ist! \n");
		exit(1);
	}
	
	//*******  Vorbereiten des Datensatzes für die generiche Liste *************************
	char* conttmp = (char*) set(neuer_String);
	//! Blank hinten einfügen
	strcat(conttmp, " ");
	//! Dateinmane hinten einfügen
	strcat(conttmp, (char*) set(dateiname));
	//! Blank hinten einfügen
	strcat(conttmp, " ");
	//! ZeilenCounter für ListenContent in Zeichen umwandeln
	char t[6];
	sprintf(t, "%i", counter);
	//! ZeilenCounter hinten einfügen
	strcat(conttmp, (char*)set((void*)t));
	//! Alle Parameter in Content einfügen
	neu_Elem -> content     = set((void*) conttmp);
	printf("conttmp: %s\n", (char*) (neu_Elem -> content) );
		
	//printf("conttmp: %s\n", (char*) (neu_Elem -> content) );
	//! Neues Element zeigt mit linkem Zeiger auf aktuelles Element (Liste)
	neu_Elem -> left       = list;
	//! Neues Element zeigt mit rechtem Zeiger auf rechten Nachbarn des Aktuellen Elements
	neu_Elem -> right      = list -> right;
	//! Von aktuellem Element auf rechtes Zeigen und von rechtem Element auf mit left auf neues Element zeigen
	list -> right-> left   = neu_Elem;
	//! Von aktuellem Element mit right auf neues Element zeigen
	list -> right          = neu_Elem;
		
	return neu_Elem;
}
...
//! Kopieren von übergebenem String
void* copyString(void* stringUebergabe)
{
	//! Wandelt void zeiger in char zeiger
	char* string = (char*) stringUebergabe;
	char* speicher = (char*) malloc(sizeof(node/*strlen(string)+1)*/));
	//Nach Speicherreservierung immer prüfen, ob auch Speicher vorhanden war!!
	if(speicher == NULL)
	{
		printf("\n Programm wurde beendet, da kein Speicher vorhanden ist! \n");
		exit(1);
	}
	//! Kopiert StringUebergabe in Speicher
	strcpy(speicher, string);
	return speicher;	
}
...

So wie es oben ist, wird auch alles nach und nach in meine Liste eingegeben. D.H. der Content eines Listen Elements beinhaltet immer ein Wort Dateiname und die Zeile in dem das Wort vorgekommen ist.
Beispiel: Haben Test.txt 3

das wird auch prima gemacht.

Was ich also die ganze Zeit versucht habe ist, wenn ein neues Wort der anhaeng-Funktion übergeben wird soll geprüft werden ob das Wort in der Liste schon vorhanden ist. Wenn ja, soll nicht das selbe Wort nochmal in die Liste eingefügt werden, sondern nur die Zeilenzahl hinten im Content des gleichen Wortes angefügt werden. Sprich: haben Test.txt 3 6.
Wenn das Wort noch nicht in der Liste steht, soll es neu in die Liste eingefügt werden.

Das hatte ich zweifelhaft versucht mit If-Abfragen in meiner anhaeng-Funktion zu realisieren.

sprich:
C:
...
node* anhaengen(node* list, void* neuer_String, void* dateiname, void* (*set)(void*), int counter)
{
	node* kopf      = list;
	node* aktl_Elem = list;

	node* neu_Elem = (node*) malloc(sizeof(node)); //! Speicher für neuen Knoten besorgen 
	//! Überprüfen, ob Speicher angelegt worden ist	
	if(neu_Elem == NULL)
	{
		printf("\n Listenelement konnte nicht angelegt werden, da kein Speicher vorhanden ist! \n");
		exit(1);
	}
	//! nodeCounter bekommt Maximale Anzahl bei jedem Funktionsaufruf der Listenelemente b zugewiesen
	//neu_Elem -> nodeCounter = list -> nodeCounter++;
	
	// Wenn Liste leer ist, wird das erste Wort eingefügt	
if(kopf == aktl_Elem -> left /*&& aktl_Elem -> content == NULL*/)
	{	//printf("Test!\n");
		char* conttmp = (char*) set(neuer_String);
		//! Blank hinten einfügen
		strcat(conttmp, " ");
		//! Dateinmane hinten einfügen
		strcat(conttmp, (char*) set(dateiname));
		//! Blank hinten einfügen
		strcat(conttmp, " ");
		//! ZeilenCounter für ListenContent in Zeichen umwandeln
		char t[6];
		sprintf(t, "%i", counter);
		//! ZeilenCounter hinten einfügen
		strcat(conttmp, (char*)set((void*)t));
		//! Alle Parameter in Content einfügen
		neu_Elem -> content     = set((void*) conttmp);
		printf("conttmp: %s\n", (char*) (neu_Elem -> content) );
		
		//printf("conttmp: %s\n", (char*) (neu_Elem -> content) );
		//! Neues Element zeigt mit linkem Zeiger auf aktuelles Element (Liste)
		neu_Elem -> left       = list;
		//! Neues Element zeigt mit rechtem Zeiger auf rechten Nachbarn des Aktuellen Elements
		neu_Elem -> right      = list -> right;
		//! Von aktuellem Element auf rechtes Zeigen und von rechtem Element auf mit left auf neues Element zeigen
		list -> right-> left   = neu_Elem;
		//! Von aktuellem Element mit right auf neues Element zeigen
		list -> right          = neu_Elem;
	}	
	else
	{ 
		char* string = NULL;
		char* string2 = NULL;
		
		while(kopf != (aktl_Elem = aktl_Elem -> left))
		{
			
			string = (char*) aktl_Elem -> content;
			
			int i = 0;			
			while(string[i] != ' ')	i++;
			string2 = (char*) malloc(++i);
			
			strncpy(string2, string, i);
			
			//sscanf(string, "%s", string2);			
			
			//printf("string: %s\n", string2);

			if(strcasecmp((char*) neuer_String, string2) == 0)
			{
				char* conttmp = (char*) aktl_Elem -> content;
				//! ZeilenCounter für ListenContent in Zeichen umwandeln
				char t[6];
				sprintf(t, "%i", counter);
				//! ZeilenCounter hinten einfügen
				strcat(conttmp, (char*)set((void*)t));
				neu_Elem -> content     = set((void*) conttmp);
			}
			else
			{
				char* conttmp = (char*) set(neuer_String);
				//! Blank hinten einfügen
				strcat(conttmp, " ");
				//! Dateinmane hinten einfügen
				strcat(conttmp, (char*) set(dateiname));
				//! Blank hinten einfügen
				strcat(conttmp, " ");
				//! ZeilenCounter für ListenContent in Zeichen umwandeln
				char t[6];
				sprintf(t, "%i", counter);
				//! ZeilenCounter hinten einfügen
				strcat(conttmp, (char*)set((void*)t));
				//! Alle Parameter in Content einfügen
				neu_Elem -> content     = set((void*) conttmp);
				//printf("conttmp: %s\n", (char*) (neu_Elem -> content) );

				//printf("conttmp: %s\n", (char*) (neu_Elem -> content) );
				//! Neues Element zeigt mit linkem Zeiger auf aktuelles Element (Liste)
				neu_Elem -> left       = list;
				//! Neues Element zeigt mit rechtem Zeiger auf rechten Nachbarn des Aktuellen Elements
				neu_Elem -> right      = list -> right;
				//! Von aktuellem Element auf rechtes Zeigen und von rechtem Element auf mit left auf neues Element zeigen	
				list -> right-> left   = neu_Elem;
				//! Von aktuellem Element mit right auf neues Element zeigen
				list -> right          = neu_Elem;
			}
			//free(string2);
			printf("conttmp: %s\n", (char*) (neu_Elem -> content) );
			
		}
	}
	return neu_Elem;
}

PS. Ich kann Dir nicht das gesamte Programm geben, da es eine große Baustelle ist und ich einige Funktionen auskommentiert habe .. es befindet sich in einer Umstrukturierung und wenn du den Quelltext siehst, wirst du nichts mehr verstehen können. Handelt sich auch zudem um ca. 500 Zeilen!

Gruß.
 
Zuletzt bearbeitet:
Debugen unter Ubuntu weiß nicht nicht wie man das machen kann!
Von dem redet ja auch keiner.
Du solltest dir bezüglich Debug/Release dringend anschauen, wie man einen Compiler bedient.
Das sind eigentlich Grundlagen, vor allem auf der Uni.

und 2. ich habe folgendes vor.
meine anhaeng-Funktion soll Wörter, was es bekommt in meine doppelt verkettete generische Liste einfügen.

der funktionierende Code dazu sieht so aus.
...
So wie es oben ist, wird auch alles nach und nach in meine Liste eingegeben. D.H. der Content eines Listen Elements beinhaltet immer ein Wort Dateiname und die Zeile in dem das Wort vorgekommen ist.
Beispiel: Haben Test.txt 3

das wird auch prima gemacht.
Da ich dir auch bei dieser Funktion schon helfen musste, ist sie mir noch in Erinnerung.
Da braucht es keine weiteren Erklärungen, ich weiss worum es geht.

Zu bemängeln ist allerdings, dass du Dateinamen und Zeilennummer mit dem Wert in Content speicherst.
Dadurch bekommst du ja erst die ganzen aktuellen Probleme.
Warum nicht in 3 Variablen auftrennen (und noch dazu den Dateinamen nicht immer redundant speichern)?

Was ich also die ganze Zeit versucht habe ist, wenn ein neues Wort der anhaeng-Funktion übergeben wird soll geprüft werden ob das Wort in der Liste schon vorhanden ist. Wenn ja, soll nicht das selbe Wort nochmal in die Liste eingefügt werden, sondern nur die Zeilenzahl hinten im Content des gleichen Wortes angefügt werden. Sprich: haben Test.txt 3 6.
Wenn das Wort noch nicht in der Liste steht, soll es neu in die Liste eingefügt werden.
Auch hier gilt die Antwort auf den vorigen Absatz.
Mit einer anderen Datenstruktur machst du dir das Leben viel einfacher.
Warum bist du schon wochenlang so versessen auf eine einzelne doppelt verkettete Liste?

Ich würde folgendes machen:
Liste aus Dateinamen, von der jedes Element wieder eine Liste aus Worten hat.
Jedes Wort hat wieder eine Liste aus int mit den Zeilennummern.
Für jede Liste kann man optional auch ein Array verwenden.

Schaut zwar auf den ersten Blick nach mehr Arbeit aus, macht aber alles übersichtlicher, einfacher und erspart zudem noch die Wurschtelei mit den Stringfunktionen.

PS. Ich kann Dir nicht das gesamte Programm geben, da es eine große Baustelle ist und ich einige Funktionen auskommentiert habe .. es befindet sich in einer Umstrukturierung und wenn du den Quelltext siehst, wirst du nichts mehr verstehen können. Handelt sich auch zudem um ca. 500 Zeilen!
Kannst oder willst du nur nicht?
Ich hätte damit kein Problem.
Für den Fall, dass ich wirklich einmal den Sinn einer Anweisung nicht nachvollziehen kann, hast du ja (für dich) sowieso schon alles schön auskommentiert.
Und 500 Zeilen ist auch kein Problem, hab schon bei weitem größere Programme gesehen und geschrieben.

Gruß
 
Von dem redet ja auch keiner.
Du solltest dir bezüglich Debug/Release dringend anschauen, wie man einen Compiler bedient.
Das sind eigentlich Grundlagen, vor allem auf der Uni.

Ich kenne nur: cc -o -Wall -std=c99 Liste Liste.c bzw. gcc -g -Wall -std=c99 -o Liste Liste.c mit dem ich kompeliere und sehe, ob mir der Kompiler Fehlermeldungen ausspuckt oder nicht!
Wenn Du dass meintest, arbeite ich schon die ganze Zeit damit.

Zu bemängeln ist allerdings, dass du Dateinamen und Zeilennummer mit dem Wert in Content speicherst.
Dadurch bekommst du ja erst die ganzen aktuellen Probleme.
Warum nicht in 3 Variablen auftrennen (und noch dazu den Dateinamen nicht immer redundant speichern)?

Es soll ebent nicht 3 Variablen sein, da es eine Auflage in unserem Kurs ist, generische Variablen zu benutzen. D.H. ein typlosen Container (void) der alles beinhalten soll um so die Wiederverwendbarkeit zwischen den Funktionen zu garantieren.

Mit einer anderen Datenstruktur machst du dir das Leben viel einfacher.
Warum bist du schon wochenlang so versessen auf eine einzelne doppelt verkettete Liste?

Das ist mir auch bekannt, das ich mit anderen Datenstrukturen einfacher fahre als mit nur einer Variablen. Dies ist aber nicht Aufgabe und Idee einer generischen Datenstruktur! Es wird von uns verlangt!
Zudem müssen wir unsere doppelt verkettete Liste weiter ausbauen und alles was wir im Unterricht lernen, müssen wir auf unserer Liste anwenden. Es sind nicht meine Wünsche.. So viel steht fest.

hier meine Liste.h:
C:
//! Diese Struktur definiert die einzelnen Listenknoten für die doppelt verkettete Liste an
typedef struct node
{
	struct node* right; // Zeiger auf das Nachfolgerelement
	struct node* left;  // Zeiger auf das Vorgängerelement
	void* content; // Für den Dateninhalt	
} node;

int strcasecmp(const char* s1, const char* s2);

// Startfunktion der Liste.
node* init_Liste();

// Diese Funktion fügt einzelne Stings in die Liste ein.
node* anhaengen(node* aktl_Elem, void* neuer_String, void* dateiname, void* (*set)(void*), int counter);

// Diese Funktion sortiert Wörter
void sort(node* list);//, int wortLineCounter);

// Ausgabe aller Listenelemente.
void print_all(node* list, void* (*getcontent)(void*), void* (*getfilename)(void*), FILE* file2, char* option);

void deleten(struct node* list);
void delete_all(struct node* list, int wordnumber);

Hier meine Liste.c
C:
#include <stdlib.h>
#include <stdio.h>
#include <string.h>

#include "Liste.h"
#define SIZE 256

//! Listeninitierung: right und left zeigen auf sich selbst, content zeigt auf NULL  und lineCounter und nodeCounter werden mit 0 initialisiert
node* init_Liste()
{
	node* n = (node*) malloc(sizeof(node));
	n -> right   = n;
	n -> left    = n;
	n -> content = NULL;
		
	return n;
}

//************************************ Listenfunktionen ***********************************
//! Parameter: 1. aktuelles Element, 2. aktuelles Wort, 3. Dateiname 4. Kopie des Strings, 5. ZeilenCounter
node* anhaengen(node* list, void* neuer_String, void* dateiname, void* (*set)(void*), int counter)//, int counter2)
{
	node* kopf      = list;
	node* aktl_Elem = list;

	node* neu_Elem = (node*) malloc(sizeof(node)); //! Speicher für neuen Knoten besorgen 
	//! Überprüfen, ob Speicher angelegt worden ist	
	if(neu_Elem == NULL)
	{
		printf("\n Listenelement konnte nicht angelegt werden, da kein Speicher vorhanden ist! \n");
		exit(1);
	}
	//! nodeCounter bekommt Maximale Anzahl bei jedem Funktionsaufruf der Listenelemente b zugewiesen
	//neu_Elem -> nodeCounter = list -> nodeCounter++;
	
	// Wenn Liste leer ist, wird das erste Wort eingefügt	
	if(kopf == aktl_Elem -> left /*&& aktl_Elem -> content == NULL*/)
	{	//printf("Test!\n");
		char* conttmp = (char*) set(neuer_String);
		//! Blank hinten einfügen
		strcat(conttmp, " ");
		//! Dateinmane hinten einfügen
		strcat(conttmp, (char*) set(dateiname));
		//! Blank hinten einfügen
		strcat(conttmp, " ");
		//! ZeilenCounter für ListenContent in Zeichen umwandeln
		char t[6];
		sprintf(t, "%i", counter);
		//! ZeilenCounter hinten einfügen
		strcat(conttmp, (char*)set((void*)t));
		//! Alle Parameter in Content einfügen
		neu_Elem -> content     = set((void*) conttmp);
		printf("conttmp: %s\n", (char*) (neu_Elem -> content) );
		
		//printf("conttmp: %s\n", (char*) (neu_Elem -> content) );
		//! Neues Element zeigt mit linkem Zeiger auf aktuelles Element (Liste)
		neu_Elem -> left       = list;
		//! Neues Element zeigt mit rechtem Zeiger auf rechten Nachbarn des Aktuellen Elements
		neu_Elem -> right      = list -> right;
		//! Von aktuellem Element auf rechtes Zeigen und von rechtem Element auf mit left auf neues Element zeigen
		list -> right-> left   = neu_Elem;
		//! Von aktuellem Element mit right auf neues Element zeigen
		list -> right          = neu_Elem;
	}	
	else
	{ 
		char* string = NULL;
		char* string2 = NULL;
		
		while(kopf != (aktl_Elem = aktl_Elem -> left))
		{
			
			string = (char*) aktl_Elem -> content;
			
			int i = 0;			
			while(string[i] != ' ')	i++;
			string2 = (char*) malloc(++i);
			
			strncpy(string2, string, i);
			
			//sscanf(string, "%s", string2);			
			
			//printf("string: %s\n", string2);

			if(strcasecmp((char*) neuer_String, string2) == 0)
			{
				char* conttmp = (char*) aktl_Elem -> content;
				//! ZeilenCounter für ListenContent in Zeichen umwandeln
				char t[6];
				sprintf(t, "%i", counter);
				//! ZeilenCounter hinten einfügen
				strcat(conttmp, (char*)set((void*)t));
				neu_Elem -> content     = set((void*) conttmp);
			}
			else
			{
				char* conttmp = (char*) set(neuer_String);
				//! Blank hinten einfügen
				strcat(conttmp, " ");
				//! Dateinmane hinten einfügen
				strcat(conttmp, (char*) set(dateiname));
				//! Blank hinten einfügen
				strcat(conttmp, " ");
				//! ZeilenCounter für ListenContent in Zeichen umwandeln
				char t[6];
				sprintf(t, "%i", counter);
				//! ZeilenCounter hinten einfügen
				strcat(conttmp, (char*)set((void*)t));
				//! Alle Parameter in Content einfügen
				neu_Elem -> content     = set((void*) conttmp);
				//printf("conttmp: %s\n", (char*) (neu_Elem -> content) );

				//printf("conttmp: %s\n", (char*) (neu_Elem -> content) );
				//! Neues Element zeigt mit linkem Zeiger auf aktuelles Element (Liste)
				neu_Elem -> left       = list;
				//! Neues Element zeigt mit rechtem Zeiger auf rechten Nachbarn des Aktuellen Elements
				neu_Elem -> right      = list -> right;
				//! Von aktuellem Element auf rechtes Zeigen und von rechtem Element auf mit left auf neues Element zeigen	
				list -> right-> left   = neu_Elem;
				//! Von aktuellem Element mit right auf neues Element zeigen
				list -> right          = neu_Elem;
			}
			//free(string2);
			printf("conttmp: %s\n", (char*) (neu_Elem -> content) );
			
		}
	}
	return neu_Elem;
}

void deleten(struct node* list)
{
	//! Zeiger neu setzen
	list->right->left = list->left;
	list->left->right = list->right;
	
	//! Freigeben des allokierten Speichers
	free(list);
	//free(list->dateiname);
	free(list->content);
}


void delete_all(struct node* list, int wordnumber)
{	
	int i = 0;
	//! Freigeben für Wörter -1 Elemente
	while (i<wordnumber)
	{
		deleten(list);	
		list=list->left;			
		i++;
	}	
	//! Freigeben für letztes Wort
	deleten(list);
}
/*
void sort(node* list)//, int wortLineCounter)
{
	//! Listenkopf - Abbruchbedingung für innere While-Schleife, kopf und aktuelles Element zu Anfang identisch
	node* kopf      = list;
	node* aktl_Elem = list; 
		 
	//! Für die Sortierung der Liste	
	void* tmpWort = NULL;
	void* tmpFilename = NULL;	
	int tmpLineCounter = 0;
	
	//Start des Bubblesort-Algorithmus
	int i = 0; // Zähler für Äußere While-Schleife - Bubblesort
	
	//! Führt Schleife Wortanzahl mal 2 durch
	while(i <= list->nodeCounter*2)
	{
		//! Solange Listenkopf ungleich aktuellem Element und aktuelles Element ungleich NULL (linksrum)
		while(kopf != (aktl_Elem = aktl_Elem -> left) && aktl_Elem -> left -> content != NULL)
		{
		  	
			char* string1 = (char*) aktl_Elem -> content;		//!Wort des aktuellen Elements
			char* string2 = (char*) aktl_Elem -> left -> content;   //!Wort des linken Elements
								
			
			if(strcasecmp(string1, string2) > 0)
			{					
				//! Wort aus aktuellen Element sichern
				tmpWort = aktl_Elem -> content;
				//! Wort aus aktuellen Element sichern
				tmpFilename = aktl_Elem -> dateiname;
				//! Zeilennummer aus aktuellem Element sichern
				tmpLineCounter = aktl_Elem -> lineCounter;

				//! Wort des linken Elements dem aktuellen Element zuweisen
				aktl_Elem -> content = aktl_Elem -> left -> content;
				//! Wort des linken Elements dem aktuellen Element zuweisen
				aktl_Elem -> dateiname = aktl_Elem -> left -> dateiname;
				//! Zeilennummer des linken Elements dem aktuellen Element zuweisen
				aktl_Elem -> lineCounter = aktl_Elem -> left -> lineCounter;

				//! Gesichertes Wort in linken Nachbarn Einfügen
				aktl_Elem -> left -> content = tmpWort;
				//! Gesichertes Wort in linken Nachbarn Einfügen
				aktl_Elem -> left -> dateiname = tmpFilename;
				//! Gesicherts Zeilennummer in linken Nachbarn Einfügen
				aktl_Elem -> left -> lineCounter = tmpLineCounter;
			}
			//! Wenn Wörter gleich sind, soll nach Zeilennummer sortiert werden
			if(strcasecmp(string1, string2) == 0)
			{
				int zeilennr1 = aktl_Elem -> lineCounter;
				int zeilennr2 = aktl_Elem -> left ->lineCounter;

				if(zeilennr1 > zeilennr2)
				{					
					//! Wort aus aktuellen Element sichern
					tmpWort = aktl_Elem -> content;
					//! Wort aus aktuellen Element sichern
					tmpFilename = aktl_Elem -> dateiname;
					//! Zeilennummer aus aktuellem Element sichern
					tmpLineCounter = aktl_Elem -> lineCounter;

					//! Wort des linken Elements dem aktuellen Element zuweisen
					aktl_Elem -> content = aktl_Elem -> left -> content;
					//! Wort des linken Elements dem aktuellen Element zuweisen
					aktl_Elem -> dateiname = aktl_Elem -> left -> dateiname;
					//! Zeilennummer des linken Elements dem aktuellen Element zuweisen
					aktl_Elem -> lineCounter = aktl_Elem -> left -> lineCounter;

					//! Gesichertes Wort in linken Nachbarn Einfügen
					aktl_Elem -> left -> content = tmpWort;
					//! Gesichertes Wort in linken Nachbarn Einfügen
					aktl_Elem -> left -> dateiname = tmpFilename;
					//! Gesicherts Zeilennummer in linken Nachbarn Einfügen
					aktl_Elem -> left -> lineCounter = tmpLineCounter;
				}
			}		
			
		}
		i++;		
	}	
}
*/

//! Parameter: 1.aktuelles_Element, 2.Kopiertes Wort, 3.Ausgabedatei, 4.Übergebener Optionsparameter
void print_all(node* list, void* (*getcontent)(void*), void* (getfilename)(void*), FILE* file2, char* option)
{
	//! Listenkopf - Abbruchbedingung für innere While-Schleife, kopf und aktuelles Element zu Anfang identisch
	node* kopf      = list;
	node* aktl_Elem = list;
	
	char* wort = NULL;	// Für den Rückgabewert aus der Funktionsvariablen - getcontent 
	char* filename = NULL;  // Für den Rückgabewert aus der Funktionsvariablen - getfilename

	//! Wenn die Liste leer ist soll nichts passieren
	if(kopf == NULL && kopf -> content == NULL)
	{
		return; 
	}			
	else
	{				
		int zahl = 0; //! Für den Schwellenwert
						
		/*sscanf(option,"-w=%d", &zahl);	//!Ließt Schwellenwert ein	
		strtok(option, "=");  //! Trennt Zeichenfolge, aus option, bis zum = Zeichen ab. 
		
		//! Wenn der Optionsparameter '-w=n'gewählt wurde		
		if(strcasecmp(option, "-w") == 0 && zahl > 1)
		{		
			//! Werden alle Listenelemente abgegangen					
			while(kopf != (aktl_Elem = aktl_Elem -> left))
			{				
				//! Wenn Listenelemente größer bzw. gleich groß sind werden diese ausgegeben.				
				if(strlen(aktl_Elem -> content) >= zahl && zahl >= 1 && strlen(aktl_Elem -> content) >= zahl && zahl >= 1)
				{	
					char* string1 = (char*) aktl_Elem -> content;		//!Wort des aktuellen Elements
					char* string2 = (char*) aktl_Elem -> left -> content;   //!Wort des linken Elements			
			
					if(strcasecmp(string1, string2) < 0)
					{
						printf(" %i. ", aktl_Elem -> nodeCounter);	
						wort = (char*) getcontent(aktl_Elem -> content);
						filename = (char*) getfilename(aktl_Elem -> dateiname);		
						printf(" %i", aktl_Elem -> lineCounter);
						
						if(strcasecmp((char*)aktl_Elem ->left-> content, (char*)aktl_Elem ->left-> left-> content) < 0)
						{						
							printf("\n");
						}							
						fprintf(file2,"%i %s %s %i\n", aktl_Elem -> nodeCounter, wort, filename, aktl_Elem -> lineCounter);
						//printf("\nFehler bei fprintf: %i\n\n", h);
					}
					else if (strcasecmp(string1, string2) == 0)
					{
											
						printf(", %i", aktl_Elem -> lineCounter);
						if(strcasecmp((char*) aktl_Elem ->left-> content, (char*)aktl_Elem ->left-> left-> content) < 0)
						{						
							printf("\n");
						}
						fprintf(file2,"%i ", aktl_Elem -> lineCounter);				

					}						
					//!Informationen werden anschließend in eine Textdatei einlesen
					//fprintf(file2,"%i %s %s %i\n", aktl_Elem -> nodeCounter, wort, filename, aktl_Elem -> lineCounter);				
				}											
			}				
		}*/
		//! Wenn der Optionsparameter '-p'gewählt wurde		
		if(strcasecmp(option, "-p") == 0)
		{
			char* string1 = NULL;
			char* string2 = NULL;	
			//! Werden alle Listenelemente abgegangen und ausgegeben				
			while(kopf != (aktl_Elem = aktl_Elem -> left))
			{
								
				char* conttmp1 = (char*) aktl_Elem -> content;		//!Wort des aktuellen Elements
				char* conttmp2 = (char*) aktl_Elem -> left -> content; //!Wort des linken Elements			
				
				sscanf(conttmp1, "%s ",string1);
				sscanf(conttmp2, "%s ",string2);
				//if(strcasecmp(string1, string2) < 0 )
				//{
					//printf(" %i. ", aktl_Elem -> nodeCounter);	
					wort = (char*) getcontent(aktl_Elem -> content);
					//filename = (char*) getfilename(aktl_Elem -> dateiname);		
					//printf(" %i", aktl_Elem -> lineCounter);
					
				//	if(strcasecmp((char*)aktl_Elem ->left-> content, (char*)aktl_Elem ->left-> left-> content) < 0)
				//	{						
						printf("\n");
				//	}							
				//	fprintf(file2,"%i %s %s %i\n", aktl_Elem -> nodeCounter, wort, filename, aktl_Elem -> lineCounter);
					//printf("\nFehler bei fprintf: %i\n\n", h);
				//}
				/*else if (strcasecmp(string1, string2) == 0)
				{
											
					printf(", %i", aktl_Elem -> lineCounter);
					if(strcasecmp((char*) aktl_Elem ->left-> content, (char*)aktl_Elem ->left-> left-> content) < 0)
					{						
						printf("\n");
					}
					fprintf(file2,"%i ", aktl_Elem -> lineCounter);				

				}*/					
				
				//!Informationen werden anschließend in eine Textdatei einlesen
				//fprintf(file2,"%i %s %s %i\n", aktl_Elem -> nodeCounter, wort, filename, aktl_Elem -> lineCounter);											
			}						
		}
		//! Fehlermeldung bei Falscheingabe, vom Anwender.
		else 
		{
			printf("\n Falschen Optionsparameter gewählt!\n\n");
			printf(" Wählen Sie nach Aufruf './Liste' als Optionsparameter '-p' oder '-w=n' aus!\n");
			printf(" - der Optionsparameter '-p' gibt alle Wöter mit der Wordindexnummer aus.\n");
			printf(" - Optionsparameter '-w=n' dient als Schwellenwert für Wortlängen. Für 'n'\n");
			printf("   wählen Sie einen beliebigen Schwellenwert, der größer ist als 1 \n\n");
		}			
	}        		
}

//***************************** Funktionen für Funktionsvariablen *************************
//! Kopieren von übergebenem String
void* copyString(void* stringUebergabe)
{
	//! Wandelt void zeiger in char zeiger
	char* string = (char*) stringUebergabe;
	char* speicher = (char*) malloc(sizeof(node/*strlen(string)+1)*/));
	//Nach Speicherreservierung immer prüfen, ob auch Speicher vorhanden war!!
	if(speicher == NULL)
	{
		printf("\n Programm wurde beendet, da kein Speicher vorhanden ist! \n");
		exit(1);
	}
	//! Kopiert StringUebergabe in Speicher
	strcpy(speicher, string);
	return speicher;	
}
//! Gibt String der Liste auf Konsole aus
void* printContent(void* contentUebergabe)
{
	char* string = (char*) contentUebergabe;	
	printf(" %s ",string);	
	return (void*) string;
}
void* printFilename(void* filenameUebergabe)
{
	char* string = (char*) filenameUebergabe;	
	printf(" %s ",string);	
	return (void*) string;
}

//************************************** Main-Funktion *************************************
int main(int argc, char *argv[])
{		
	node* kopf = (node*) init_Liste(); 	//! init_List() wird dem Kopf der Liste zugewiesen
	node* aktl_Elem = kopf; 		//! Zum Anfang wird aktuelles Element auf kopf gesetzt
	
	//! Definition benötiger variablen um die Texfiles zu öffnen, einzulesen und abzuspeichern
	char buffer[SIZE];
	FILE *file1, *file2;
	char splitt[] = ",;.:!?><#'’+*~´`^?[]{}()/\%&$§=|öäüÖÜÄߢ£¤¥¦§ ¨©ª«¬®¯°±²³´µ¶·¸¹º»¼½¾¿¡ÀÁÂÃÄÅÆÇÈÉÊËÌÍÎÏÑÒÓÔÕÖ×ØÙÚÛÜÝÐÞßáâãäåæçèéêëìíîïðñòóôõö÷øùúûüýþÿ\"\n\0 "; //Definition der Trennzeichen	
	char* wort;
			
	
	if(argc > 1 && argv[1] != NULL && (file2 = fopen(argv[2], "w+")) != NULL && (file1 = fopen(argv[3], "r")) != NULL)
	{	
		int i = 3; //! Startpunkt für Eingabedateien
		while(i < argc)
		{
			int counter = 0;		
			if((file1 = fopen(argv[i], "r")) != NULL)
			{			
				while(fgets(buffer, SIZE, file1) != NULL)
				{					
					counter++; //! Counter für Zeilenanzahl				
					wort = strtok(buffer, splitt);				
							
					while(wort != NULL)
					{
						//! Wort darf nicht mit folgenden Zeichen beginnen!					    	
						if(strncmp(wort,"-",1) != 0 && strncmp(wort,"0",1) != 0 && strncmp(wort,"1",1) != 0
 						&& strncmp(wort,"2",1) != 0 && strncmp(wort,"3",1) != 0 && strncmp(wort,"4",1) != 0
 						&& strncmp(wort,"5",1) != 0 && strncmp(wort,"6",1) != 0 && strncmp(wort,"7",1) != 0
 						&& strncmp(wort,"8",1) != 0 && strncmp(wort,"9",1) != 0)
						{				
							anhaengen(aktl_Elem, wort, argv[i], copyString, counter);
						}
						//! speichert NULL in wort für Abbruchbedingung
						wort = strtok(NULL, splitt);		    				
					}								    			
				}			
				fclose(file1);		
			}		
			i++;
		}
		//! Aufruf sortieren von aktuellem Element
		//sort(aktl_Elem);
		//! Gibt alle Listenelemente aus
		//print_all(aktl_Elem, printContent, printFilename, file2, argv[1]);
		
		fclose(file2); //! Da die äußere While-Schleife evtl. mehrere Eingabetextdateien ließt, soll die geschriebene Datei auch solange offen bleiben.  
	}
	//! Fehlermeldung bei Falscheingabe, vom Anwender.
	else
	{ 
		printf("\n Das Programm wurde mit den falschen Parametern aufgerufen! \n\n");
		printf(" Rufen Sie das Programm folgendermaßen auf:\n");
		printf(" - './Liste <option> <Ausgabedatei> <Eingabedatei>'. \n");
		printf(" - Sie können auch mehrere Eingabedateien übergeben. \n");
		printf("   ->'...<Ausgabedatei> <Eingabedatei1>,..,< Eingabedatei<n> >'. \n\n");
		exit(1);	
	}
	
	//! Freigeben von allokiertem Speicher
	//delete_all(aktl_Elem, aktl_Elem -> nodeCounter);
	free(kopf) ;
	return EXIT_SUCCESS;
}
 
Zuletzt bearbeitet:
Zurück