Allgemeine Funktionen um Listen zu bearbeiten (ANSI C)

Schnelle objektorientierte, kompilierende Programmiersprache.
Antworten
aequatio
Beiträge: 5
Registriert: Fr Mär 13, 2015 10:33 am

Allgemeine Funktionen um Listen zu bearbeiten (ANSI C)

Beitrag von aequatio » Fr Mär 13, 2015 10:53 am

Hallo :)

folgendes Problem hätte ich gerade:
Wir müssen für die Hochschule ein Projekt in ANSI C (C99) programmieren (Kompiler soll gcc sein).
Dazu habe ich verschiedene Listen die aus verschiedenen structs bestehen.

Mein Problem ist, ich hätte gerne meine Funktionen zum manipulieren der Listen nicht für jede einzeln, sondern je eine allgemeine zum Anfügen von einem neuen Element, das Löschen von einem Element etc. Dazu übergebe ich der Funktion im Beispiel void *start, das erste Element einer beliebigen Liste, und benenne sie *p um mit ihr weiterzuarbeiten:

Code: Alles auswählen

/* Funktion:	listAdd()					*
 * Input:	void *start - Zeiger auf das erste Objekt	*
 * 		void *new - Zeiger auf neues Objekt		*
 * Output:	void						*
 * Aufgabe:	Element am Ende der Liste hinzufügen		*/
void listAdd( void *start, void *new ) {
	void *p = start;			// Pointer auf aktuelles Objekt

	while( p != NULL ) {			// Schleife bis letztes Element gefunden
		if( p->next == NULL ) {		// Wenn letztes Element
			p->next = new;		// Dann setze neues Element statt NULL
			return;			// Beende Funktion
		}
		else {				// Wenn nicht letztes Element
			p = p->next;		// Sprine
		}
	}
}
Dabei meckert der Kompiler aber:

Code: Alles auswählen

lists.c:74:10: warning: dereferencing ‘void *’ pointer
     p = p->next;   // Sonst springe zu nächsten Element
          ^
lists.c:74:10: error: request for member ‘next’ in something not a structure or union
Gut logisch, er weiß ja nicht was hinter dem void* steckt. Also habe ich folgendes Konstrukt zum um deklarieren meines Pointers je nach Notwendigkeit (Parameter strNR liefer ich entsprechend mit) gebaut:

Code: Alles auswählen

	switch( strNR ) {			// p je nach Typ deklarieren
		case 1:		; product *p = start;
				break;
		case 2: 	; costumer *p = start;
				break;
		case 3:		; order *p = start;
				break;
		case 4:		; costumOrder *p = start;
				break;
		default:	; void *p = NULL;
				break;
	}
Neue Fehlermeldung ist dann:

Code: Alles auswählen

lists.c:32:24: error: conflicting types for ‘p’
   case 2:  ; costumer *p = start;
                        ^
lists.c:30:23: note: previous definition of ‘p’ was here
   case 1:  ; product *p = start;
                       ^
...

Ich hab echt keinen Ansatz wie ich das Problem direkt beheben kann oder meine Daten vll anders Strukturieren kann (Listen sind hier schon sinnvoll da es beliebig viele neue User etc geben soll).

Danke schonmal fürs durchlesen und im vorraus für eure Tipps :)


Gruß
aequatio

aequatio
Beiträge: 5
Registriert: Fr Mär 13, 2015 10:33 am

Re: Allgemeine Funktionen um Listen zu bearbeiten (ANSI C)

Beitrag von aequatio » Fr Mär 13, 2015 11:03 am

Edit: in jedem struct wird mit der Variablen next auf das nächste Element gezeigt

aequatio
Beiträge: 5
Registriert: Fr Mär 13, 2015 10:33 am

Re: Allgemeine Funktionen um Listen zu bearbeiten (ANSI C)

Beitrag von aequatio » Fr Mär 13, 2015 11:12 am

Ok das Problem mal für andere zu Formulieren hat mich auf ne Idee gebracht:

Statt diesem nicht gerade hübschen Konstrukt mache ich in meinen Header ein Makro:

Code: Alles auswählen

#define STRUCT_TYPE(typ) typ
und habe dann in meiner Funktion:

Code: Alles auswählen

void fkt( char* type, ....) {
          STRUCT_TYPE(type) *p = new;
          ...
Zumindest meckert der Kompiler nichtmehr :)
Ich halt euch auf dem laufenden ob das auch so klappt ;) (falls einer da Anmerkungen hat bitte her damit :) )

Benutzeravatar
cloidnerux
Moderator
Beiträge: 3125
Registriert: Fr Sep 26, 2008 4:37 pm
Wohnort: Ram (Gibts wirklich)

Re: Allgemeine Funktionen um Listen zu bearbeiten (ANSI C)

Beitrag von cloidnerux » Fr Mär 13, 2015 11:15 am

Hallo :)
Hi und Willkommen im Forum :D
Dazu habe ich verschiedene Listen die aus verschiedenen structs bestehen.
Hier liegt das Gesamtproblem.
Die typische Liste(https://www.proggen.org/doku.php?id=struct:list:start) ist eine Datenstruktur um generische Daten zu speichern.

Jetzt legst du mehrere Listen an, die aber keine funktionellen Unterschiede(?) haben, sondern nur von der Art ihreres Datentyps(?)

Code: Alles auswählen

 case 1:      ; product *p = start;
            break;
      case 2:    ; costumer *p = start;
            break;
      case 3:      ; order *p = start;
            break;
      case 4:      ; costumOrder *p = start;
            break;
      default:   ; void *p = NULL;
            break;
Und das funktioniert dann nicht mehr.
Warum kannst du nicht eine generische Liste erzeugen, und dann einfach die Instanzen Spezifisch machen?
Redundanz macht wiederholen unnötig.
quod erat expectandum

aequatio
Beiträge: 5
Registriert: Fr Mär 13, 2015 10:33 am

Re: Allgemeine Funktionen um Listen zu bearbeiten (ANSI C)

Beitrag von aequatio » Fr Mär 13, 2015 11:20 am

Danke dir erstmal. Was genau meinst du jedoch mit Instanzen spezifisch machen? (hört sich etwas nach Objektorientiert an und würde das Problem deutlich vereinfachen :D )

Jede Liste besteht aus den gleichen Structs. Ich habe sozusagen für jede Struktur eine Liste, will aber immer mit der gleichen Funktion darauf zugreifen um Code-Wiederholungen zu sparen.

Ich probiere einfach mal ob meine Variante auch so Funktioniert :)

Benutzeravatar
cloidnerux
Moderator
Beiträge: 3125
Registriert: Fr Sep 26, 2008 4:37 pm
Wohnort: Ram (Gibts wirklich)

Re: Allgemeine Funktionen um Listen zu bearbeiten (ANSI C)

Beitrag von cloidnerux » Fr Mär 13, 2015 11:33 am

Danke dir erstmal. Was genau meinst du jedoch mit Instanzen spezifisch machen? (hört sich etwas nach Objektorientiert an und würde das Problem deutlich vereinfachen :D )
Es ist Objektorientierung, nur ohne Klassen.
Was ich meine ist:

Code: Alles auswählen

struct liste
{
    void * data;
    struct liste * next;
}
[...]
struct liste customer;
struct liste prdouct;
struct liste order;
[...]
order.data = &myOrder;
Du hast eine Liste, die generisch ist.
Und deine Unterscheidung, ob es sich nun um Produkte oder Kunden handelt, erfolgt dann nur im Kontext über die Instanz.
Redundanz macht wiederholen unnötig.
quod erat expectandum

aequatio
Beiträge: 5
Registriert: Fr Mär 13, 2015 10:33 am

Re: Allgemeine Funktionen um Listen zu bearbeiten (ANSI C)

Beitrag von aequatio » Fr Mär 13, 2015 11:37 am

Mhmm über so ein Konstrukt habe ich vorhin Stundenlang nachgegrübelt und nach gegoogelt...

Hätte wohl früher hier reinschreiben sollen :D :D :D

Gut vielen Dank dir :)

mfro
Beiträge: 346
Registriert: Mi Jan 16, 2013 4:58 pm

Re: Allgemeine Funktionen um Listen zu bearbeiten (ANSI C)

Beitrag von mfro » Fr Mär 13, 2015 2:14 pm

Wenn "data" jetzt noch eine union ist, ist das ganze sogar typsicher...
It's as simple as that. And remember, Beethoven wrote his first symphony in C.

Benutzeravatar
Xin
nur zu Besuch hier
Beiträge: 8862
Registriert: Fr Jul 04, 2008 11:10 pm
Wohnort: /home/xin
Kontaktdaten:

Re: Allgemeine Funktionen um Listen zu bearbeiten (ANSI C)

Beitrag von Xin » Fr Mär 13, 2015 4:00 pm

mfro hat geschrieben:Wenn "data" jetzt noch eine union ist, ist das ganze sogar typsicher...
Hüstl... es ist zumindest nicht ganz so unsicher. ;-)


Wenn Du es Typsicher haben möchtest, musst Du wirklich mehrere Listen machen:

Code: Alles auswählen

struct Product
{
  struct Product * Next;    // hier ist die Liste...

  char Name[80];   // Produktname
};
Da sich das für alle Datentypen wiederholt, kann man später in C++ den Code so erstellen lassen (generische Programmierung), dass der Compiler einem alle Funktionalitäten für eine Liste für Produkte oder für Order automatisch erstellt. Ohne generische Programmierung, muss man entweder auf Typsicherheit verzichten (also void *), das selbst ausformulieren oder mit Macros arbeiten.
Merke: Wer Ordnung hellt ist nicht zwangsläufig eine Leuchte.

Ich beantworte keine generellen Programmierfragen per PN oder Mail. Dafür ist das Forum da.

Antworten