[gelöst] Funktion mit Funktionspointer als Parameter
-
Hallo c-community,
ich probiere mich seit langem mal wieder an der c-Programmierung und bin gleich mal auf ein Problem gestoßen.
Kurz zur meiner selbst gewählten Aufgabenstellung:
Ich möchte in einer Linux-Umgebung ein Terminalprogramm schreiben, welches wie bei Linux üblich mehrere variable Parameter beim Start vom User übergegeben bekommt.
./Prgrammname <Option 1> <Option 2> ... <Option n>
Derzeit bin ich soweit, dass mein Programm die Optionen durchsucht und mit einem relativ einfachen Abfolgealgorithmus (Analyse welche Buchstaben aufeinander folgen -> erkennen der gewählten Option) die Optionen von einander unterscheiden kann.
Dabei nutze ich derzeit mehrere Funktionen gleicher Struktur, welche ich jetzt in eine EINZIGE Funktion zusammen fassen möchte.
Funktionsstruktur:
int next_letter(char* string, void *funcPtr) //funcPtr soll der Pointer für die Folgefunktion sein { char* nextLetter; nextLetter = Cut_First_Letter(string); return funcPtr(nextLetter); }
Kurze Erklärung:
Ich übergebe der next_letter-Funktion die Option, wie sie der User eingegeben hat (vorher wurde der 1. Buchstabe der Opion schon ausgewertet, was ihn für die weitere Betrachtung unwichtig macht. Deswegen wird er auch gleich abgeschnitten). Der erste Buchstabe wird abgeschnitten und soll dann an eine weitere Funktion übergeben werden, die wieder den 1. Buchstaben der Rest-Option auswerten soll.Der Aufruf der next_letter-Funktion erfolgt im Programm wie folgt:
// Deklaration der Funktionen die in den funcPtr aufgenommen werden sollen int Varificate_First_Letter_Option(char*); int Varificate_Second_Letter_Option(char*); int Varificate_Third_Letter_Option(char*); // Aufruf/ Verwendung int (*funcPtr)(char*); // void *funcPtr; //altrnativer Pointer Test leider negativ = gleicher Fehler funcPtr = Verificate_Second_Letter_Option; switch(Next_Letter_Option(soption, funcPtr)) { case 1: return 70; break; case 2: return 17; break; case 21: return 70; break; case 22: return 10; break; default: return -1; break; }
Das Problem/ der Fehler welcher mir durch das System ausgegeben wird ist nun der: "XX: error, called object 'funcPtr' is not a function".
Warum nimmt er den Pointer nicht als Funktion wahr?
MfG
mirrowwinger
-
mirrowwinger schrieb:
Warum nimmt er den Pointer nicht als Funktion wahr?
Weil du nur einen void-Zeiger übergibst.
Der Lesbarkeit halber könnte man schreiben:
typedef int(* MyCB)(const char*);
next_letter könnte neben dem char* dann eine Funktion mit den Argumenten und dem Rückgabetyp von MyCB übergeben werden (*).
Ein (sinnloses) Beispiel:
int f(const char* string, MyCB cb) { //.. while(*string) cb(string++); return 1; } int CB(const char* string) { puts(string); return 0; } int main() { const char* string = "Hello"; f(string, CB); return 0; }
* ich bin mir nicht ganz sicher, ob dies auch für C gilt, hier korrekt zu sein, ist sicherlich dennoch nicht verkehrt.
-
Benutze einen eigenen Typ:
typedef int (*FuncPtr)(char*);
Die Verwendung wird dann einfacher, z.B.
int next_letter(char* string, FuncPtr fkt) //funcPtr soll der Pointer für die Folgefunktion sein { char* nextLetter; nextLetter = Cut_First_Letter(string); return fkt(nextLetter); }
sowie
FuncPtr fkt = Varificate_First_Letter_Option; ... switch(next_letter(soption, fkt)) { case 1: return 70; break; case 2: return 17; break; case 21: return 70; break; case 22: return 10; break; default: return -1; break; }
Abgesehen davon gibt es für deinen Anwendungsfall bereits die GNU Erweiterung getopt:
http://www.gnu.org/s/libc/manual/html_node/Example-of-Getopt.html
-
Also habe das jetzt umgestellt, so wie ihr das vorgeschalgen habt. ABER ich bekomme jetzt beim Compilieren folgenden Fehler:
test.c:(.text+0x177): undefined reference to `Verificate_Second_Letter_Option'
Hier zum Nachvollziehen, was ich geändert habe (hab auch ein paar Funktionen wegrationalisiert aber Prinzip ist das Gleiche):
// der Typedef typedef int(* FuncPtr)(const char*); // die Aufrufende Funktion int Verificate_Option(const char* soption, FuncPtr funcPtr) { return funcPtr(soption); } // die zu integrierenden Funktionen int Verificate_First_Letter_Option(const char*); int Verificate_Second_Letter_Option(const char*); int Verificate_Third_Letter_Option(const char*); // die Aufrufvarianten (beide haben den oben genannten Fehler zur Folge): // Variante 1 (Funktion über Pointer übergeben) FuncPtr funcPtr; funcPtr = Verificate_Second_Letter_Option; switch(Verificate_Option(soption++, funcPtr)) { case 1: return 70; break; case 2: return 17; break; case 21: return 70; break; case 22: return 10; break; default: return -1; break; } // Variante 2 (Funktion direkt übergeben// nach meinen Infos ist der Funktionsname selber direkt ein Pointer) switch(Verificate_Option(soption++, Verificate_Second_Letter_Option)) { case 3: return 40; break; case 4: return 10; break; case 5: return 10; break; case 2: return 70; break; default: return -1; break; }
Sieht jemand wo jetzt der Fehler noch sitzt? Eigentlich sollte ich doch alles richtig umgestellt haben. Den Umweg über die Cut_First_Letter(..) hab ich rausgeschmissen, weil mir die string++ besser gefallen hat.
mirrowwinger
-
'undefined reference' bedeutet, dass du zwar was deklariert hast aber die Definition der Funktion nirgendwo gefunden wurde.
-
ups
Schreibfehler.
// Deklaration int Verificate_Second_Letter_Option(const char*); // Definition int Varificate_Second_Letter_Option(const char*) { .. }
Thanks funktioniert alles.
mirrowwinger