pbp Δημοσ. 30 Οκτωβρίου 2012 Δημοσ. 30 Οκτωβρίου 2012 Καλησπέρα παιδιά, μήπως θα μπορούσε να μου εξηγήσει κάποιος το συγκεκριμένο κομμάτι της typedef γιατί μου είναι λίγο δυσνόητο; > typedef int (*funcptr)(double); // pointer to function of double returning int funcptr x = (funcptr) NULL; // C or C++ funcptr y = funcptr(NULL); // C or C++ Ευχαριστώ για το χρόνο σας.
παπι Δημοσ. 30 Οκτωβρίου 2012 Δημοσ. 30 Οκτωβρίου 2012 Δεν μπερδευσαι στο typedef. Το typedef ειναι απλο. Οπως λες int i; και ξερεις οτι το i ειναι μεταβλητη τυπου int ετσι με το typedef int i; ξερεις οτι το i ειναι συνωνημο του int. το θεμα ειναι ο function pointer που αντι να δηλωνεται οπως οι κοινες μεταβλητες "τυπος μεταβλητη" πχ int i; αυτη δηλωνεται ως τυμεταβλητηπος δηλαδη αντι να εχεις void (*)(int) func; εχεις void (*func)(int); Για να ορισεις εναν τυπο function pointer εχεις ΑυτοΠουΕπιστρεφειΗΣυναρτηση (*ονομαΜεταβλητης)(Παραμετορς1,Παραμετρος2); αρα για συνρατηση int foo(float,double,char) θα εχεις το int (*foo)(folat,double,char) πχ > void print1(const char* str) { printf("%s",str); } int main(int argc, char **argv) { void (*func)(const char*) = &print1; func("hey"); return 0; } αν το καταλαβες αυτο, τοτε το βαζοντας το typedef απλα το foo αντι να ειναι μεταβλητη, γινεται ενα συνωνημο του τυπου. Thats all.
migf1 Δημοσ. 30 Οκτωβρίου 2012 Δημοσ. 30 Οκτωβρίου 2012 Σε ευχαριστω...Με βοηθησες παρα πολυ...Εμαθα πραγματα μεσα απο αυτο που εγραψες...Ευχαριστω και παλι!!! Χαίρομαι που σου φάνηκαν χρήσιμα Σήμερα που το ξαναδιάβασα, έκανα μια μικρή διόρθωση στον κώδικα (έβαλα 2ο edit στο τέλος εκείνης της δημοσίευσης). Επίσης, μάλλον είναι καλύτερα αντί για malloc() να χρησιμοποιήσουμε calloc() ως extra safety measure, γενικότερα.
migf1 Δημοσ. 30 Οκτωβρίου 2012 Δημοσ. 30 Οκτωβρίου 2012 Καλησπέρα παιδιά, μήπως θα μπορούσε να μου εξηγήσει κάποιος το συγκεκριμένο κομμάτι της typedef γιατί μου είναι λίγο δυσνόητο; > typedef int (*funcptr)(double); // pointer to function of double returning int funcptr x = (funcptr) NULL; // C or C++ funcptr y = funcptr(NULL); // C or C++ Ευχαριστώ για το χρόνο σας. Η ιδιομορφία με τους function pointer τύπους είναι πως τα typedef τους διατυπώνονται όμοια με τους απλούς ορισμούς των μεταβλητών (δεικτών) τους. Δηλαδή, έστω πως ορίζουμε (κι αρχικοποιούμε σε NULL) χωρίς typedef μια μεταβλητή (δείκτη) p1func της οποίας ο τύπος είναι δείκτης σε μια συνάρτηση που παίρνει ως ορίσματα 2 int κι επιστρέφει bool... > bool (*p1func)(int, int) = NULL; Ομοίως, για να ορίσουμε (και να αρχικοποιήσουμε σε NULL) έναν δεύτερο δείκτη p2func ίδιου τύπου γράφουμε... > bool (*p2func)(int, int) = NULL; Οπότε, για να μην "κουβαλάμε" όλο αυτό το μακρινάρι κάθε φορά που θέλουμε να ορίσουμε έναν δείκτη του συγκεκριμένου τύπου, μπορούμε να δημιουργήσουμε ένα alias του τύπου, με χρήση της εντολής typedef... >typedef bool (*PtrFuncTake2IntReturnBool)(int, int); Η γενικότερη διατύπωση είναι ακριβώς η ίδια με τους απλούς ορισμούς, με μόνη εξαίρεση το όνομα του τύπου, το οποίο το έχω επίτηδες περιφραστικό, προς διευκόλυνση της κατανόησής του (στους απλούς ορισμούς, η ονομασία αυτή αναφέρεται στο όνομα της μεταβλητής-δείκτη που ορίζουμε). Οπότε με αυτό το typedef θα μπορούσαμε να είχαμε ορίσει του δείκτες p1func και p2func ως εξής: > PtrFuncTake2IntReturnBool p1func = NULL, p2func = NULL; Τώρα, στο απόσπασμα που παραθέτεις, αρχικά δημιουργείται ένα alias (ονόματι funcptr) ενός τύπου που είναι δείκτης σε όποια συνάρτηση δέχεται ένα double όρισμα κι επιστρέφει int... > typedef int (*funcptr)(double); // pointer to function of double returning int Αμέσως μετά ορίζεται (κι αρχικοποιείται σε NULL) ένας δείκτης x αυτού του τύπου (κάνοντας cast την τιμή NULL σε αυτόν τον τύπο)... > funcptr x = (funcptr) NULL; // C or C++ ΟΜΩΣ η επόμενη γραμμή, που επιχειρεί να ορίσει την μεταβλητή y είναι εσφαλμένη σε ότι αφορά την C. Δεν έχω ιδέα αν επιτρέπεται η/και τι ακριβώς σημαίνει στην C++ (μονάχα υποψιάζομαι), αλλά σε πρώτη φάση στην C δεν επιτρέπεται το name mangling (στην προκειμένη περίπτωση ένας τύπος και μια συνάρτηση μοιράζονται το ίδιο όνομα: funcptr ... κάτι τέτοιο δεν περνάει καν από τον C compiler). Σε δεύτερη φάση δεν επιτρέπεται ούτε το function-overloading (στην προκειμένη περίπτωση, η συνάρτηση funcptr(NULL) καλείται με όρισμα NULL που παραπέμπει σε δείκτη, ενώ ο τύπος της έχει οριστεί στο συγκεκριμένο context να αναμένει double όρισμα)... > funcptr y = funcptr(NULL); // C or C++ Σημείωση 1: Από C89/90 και μετά το casting του NULL κατά την αρχικοποίηση του x δεν χρειάζεται. Όμως χωρίς να είμαι 100% σίγουρος νομίζω πως χρειάζεται στην C++ Σημείωση 2: Ένα από τα πιο well-thought C coding-styles (και personal favorite κατά το 90% του για γενικούς κώδικες) είναι το Standards and Style for Coding in ANSI C. Σύμφωνα με αυτά τα στάνταρ λοιπόν, οι ονομασίες όλων των custom defined τύπων (δηλαδή των typedef's) έχουν κεφαλαίο μόνο το πρώτο τους γράμμα, ή τα πρώτα γράμματα των όποιων συνθετικών απαρτίζουν την ονομασία τους (με όλα πεζά είναι μονάχα οι ονομασίες των εγγενών τύπων της γλώσσας). Επίσης, τα ονόματα των μεταβλητών προτείνεται να έχουν πάντα πεζά γράμματα με τυχόν συνθετικά να διαχωρίζονται με underbar αν είναι πολύ μεγάλο το όνομα (εγώ παρεκκλίνω σε αυτό, γράφοντας κολλητά τα όποια συνθετικά, κεφαλαιοποιώντας τα πρώτα γράμματα από το 2ο συνθετικό και μετά, χρησιμοποιώντας underbars μόνο στα ονόματα συναρτήσεων). Τα γράφω αυτά ως εισαγωγή για να καταλήξω στο ότι όποιος είναι ενήμερος για το συγκεκριμένο coding-style, βρίσκει πολύ πιο κατανοητό κάτι σαν αυτό... > typedef int (*FuncPtr)(double); // pointer to function of double returning int FuncPtr x = (FuncPtr) NULL; // C or C++ έναντι αυτού... > typedef int (*funcptr)(double); // pointer to function of double returning int funcftr x = (funcptr) NULL; // C or C++ Το βρίσκει πιο κατανοητό επειδή είναι ξεκάθαρο και μόνο από την ονομασία του πως το FuncPtr αναφέρεται σε custom τύπο. Ομοίως είναι ξεκάθαρο και μόνο από την ονομασία του πως το funcptr στο παρακάτω αναφέρεται σε μεταβλητή (δείκτη) και όχι σε custom τύπο... >int (*funcptr)(double);
nik324 Δημοσ. 30 Οκτωβρίου 2012 Δημοσ. 30 Οκτωβρίου 2012 Εχω μια συναρτηση InsertNode(TypeΑ **a, type value); Και θελω να δεσμευσω μνημη για περισσοτερους απο εναν κομβους και να αρχικοποιηση τα πεδια τους με την τιμη value Επισης εχω ενα δεικτη τυπου TypeA τον οποιο τον περναω byRef στην συναρτηση Insert() Κανω το εξης..Βαζω μεσα σε ενα foorLoop την συναρτηση Insert αλλα δεν βλεπω αποτελεσμα...Καμια αλλη ιδεα? Ευχαριστω για αλλη μια φορα ps.Eστω y το πληθος των κομβων που θελω να εισαγω...Το foorLoop που χρησιμοποιησα πηγαινε απο 1 εως y
migf1 Δημοσ. 30 Οκτωβρίου 2012 Δημοσ. 30 Οκτωβρίου 2012 Δώσε μας κώδικα να δούμε πως το κάνεις, διότι ως λογική αυτό που περιγράφεις δεν δείχνει να έχει κάποιο πρόβλημα (με μια επιφύλαξη για το by-ref πέρασμα του a).
nik324 Δημοσ. 30 Οκτωβρίου 2012 Δημοσ. 30 Οκτωβρίου 2012 Δεν θελω να δημοσιευσω κωδικα...Και δεν μπορω να στειλω μονο ενα μικρο κομματι γιατι μετα δεν θα καταλαβαιτε τι θελω...Θα το ψαξω δεν πειραζει...Ευχαριστω παντως
migf1 Δημοσ. 30 Οκτωβρίου 2012 Δημοσ. 30 Οκτωβρίου 2012 Οκ, αν και λογικά θα μας αρκούσε απλώς ο κώδικας της Insert και το σημείο του for-loop που την καλεί.
Timonkaipumpa Δημοσ. 30 Οκτωβρίου 2012 Δημοσ. 30 Οκτωβρίου 2012 Καλησπέρα παιδιά, μήπως θα μπορούσε να μου εξηγήσει κάποιος το συγκεκριμένο κομμάτι της typedef γιατί μου είναι λίγο δυσνόητο; > typedef int (*funcptr)(double); // pointer to function of double returning int funcptr x = (funcptr) NULL; // C or C++ funcptr y = funcptr(NULL); // C or C++ Ευχαριστώ για το χρόνο σας. Να δώσω και εγώ μία απάντηση μιας και είναι αγαπημένο μου θέμα οι function pointers... typedef και function pointers είναι τρεις δυσκολίες αντί για δύο. 1η Η πρώτη είναι οι function pointers. Οι οποίοι είναι pointers, όπερ σημαίνει ότι είναι μεταβλητές που δείχνουν σε μία διεύθυνση μνήμης. Το πρόβλημα είναι όμως ότι δείχνουν σε διεύθυνση η οποία "περιέχει" function. 2η typedef και function pointers.... όπου, όπως είπαν και τα παιδιά πιο πριν, ορίζεις έναν τύπο δείκτη. Τι τύπο όμως; Απλά ένα δείκτη σε μία συνάρτηση; Όχι. Έναν δείκτη σε συνάρτηση που έχει τα συγκεκριμένα χαρακτηριστικά που χρησιμοποίησες στο typedef. Και δεν μπορείς να κοροϊδέψεις τον Η/Υ.... εάν δηλώσεις > typedef int (*fcnPnt) (int , int ) και μετά πας να κάνεις ένα τέτοιο δείκτη να δείξει σε > int foo (int ) Σε δάγκωσε. 3η, και η πιο σημαντική, για εμένα, δυσκολία... Ωραία. Τους δήλωσες. Μετά, τι; Τι κάνεις αυτούς τους pointers; Τους χρησιμοποιείς ως μεταβλητές; Πού; Η πιο συχνή, σε εμένα, χρήση τους είναι για την δήλωση API. Interfaces που χρησιμοποιούν συναρτήσεις για τις οποίες όμως θα πρέπει να τηρούνται το τι τύπο επιστρέφουν και τι ορίσματα παίρνουν. Όπου πρέπει να ορίσεις, σαφώς, τις συναρτήσεις για να τις καλέσεις αλλά το τι θα κάνουν αυτές το αφήνεις σε αυτόν που θα κάνει το implementation για όπου το κάνει. Οπότε, αυτός που θα κάνει το implementation... γράφει μία συνάρτηση τέτοιου τύπου (που έχεις ορίσει στο typedef) και απλά βάζει τον δείκτη να δείχνει εκεί. Έτσι, εξασφαλίζεις ότι όλη η δομή που θες να τηρήσεις χρησιμοποιεί συγκεκριμένα "στοιχεία" αλλά το τι ακριβώς θα γίνει από τις κλήσεις το αφήνεις στην εκάστοτε υλοποίηση. Για να το κάνεις αυτό, μπορείς να χρησιμοποιήσεις κάτι σαν: > typedef int (*fcnPntr1) (int , int ); typedef float (*fcnPntr2) (float , float ); typedef struct { intAdding fcnPntr1; floatAdding fcnPntr2; }AddingStruct; και όταν θα αρχικοποιήσεις την μεταβλητή AddingStruct θα δώσεις στα πεδία της τους δείκτες σε συναρτήσεις ΚΑΤΑΛΛΗΛΕΣ που να κάνουν αυτό που θες εσύ. edit: Υπάρχουν ολόκληρα πρότυπα, εγκεκριμένα από μεγάλους οργανισμούς, τα οποία χρησιμοποιούν, σχεδόν στο 80%, function pointers και typedef's αυτών....
migf1 Δημοσ. 31 Οκτωβρίου 2012 Δημοσ. 31 Οκτωβρίου 2012 Και μιας και αναλύουμε τους δείκτες σε συναρτήσεις, είναι χρήσιμο νομίζω να συμπληρώσουμε κάτι που ξεχάσαμε, ότι δηλαδή δεν γίνονται dereference όπως οι υπόλοιποι δείκτες. Το dereferencing ενός function pointer μετατρέπεται αυτόματα και πάλι σε function pointer. Με άλλα λόγια, το dereferencing τους ισοδυναμεί με την κλήση τους. Ο παρακάτω πρόχειρος κώδικας χρησιμοποιεί έναν function pointer pIntCompare για να συγκρίνει 2 ακέραιους και κατόπιν τυπώνει στα αγγλικά το αποτέλεσμα της σύγκρισης... > #include <stdio.h> // -------------------------------- int intcmpr( int n1, int n2 ) { return (n1 > n2) - (n1 < n2); } // -------------------------------- int main( void ) { int n1 = 100, n2 = 100; int (*pIntCompare)(int, int) = intcmpr; char *sarrResultsEn[] = { "equals", "is greater than", "is less than" }; int result = pIntCompare(n1, n2); char *cpResult = result < 0 ? sarrResultsEn[2] : sarrResultsEn[result]; printf( "%d %s %d\n", n1, cpResult, n2 ); return 0; } Με τους κανονικούς δείκτες θα κάναμε dereference όταν θέλαμε να πάρουμε την τιμή του περιεχόμενού του (δηλαδή σε αυτήν την περίπτωση για ανάθεση στην result) κι επίσης θα χρησιμοποιούσαμε τον addressof operator (&) όταν αναθέταμε διεύθυνση στον δείκτη μας (δηλαδή σε αυτήν την περίπτωση στην ανάθεση του pIntCompare). Οπότε ο κώδικάς της main() θα ήταν σαν τον παρακάτω... > int main( void ) { int n1 = 100, n2 = 100; int (*pIntCompare)(int, int) = &intcmpr; // χρήση του addressof operator char *sarrResultsEn[] = { "equals", "is greater than", "is less than" }; int result = (*pIntCompare)(n1, n2); // dereference του δείκτη για ανάθεση του περιεχόμενού του στην result char *cpResult = result < 0 ? sarrResultsEn[2] : sarrResultsEn[result]; printf( "%d %s %d\n", n1, cpResult, n2 ); return 0; } Στην πράξη, ακριβώς επειδή οι function pointers γίνονται dereferenced στον εαυτό τους, μπορούμε να χρησιμοποιήσουμε οποιονδήποτε από τους 2 παραπάνω τρόπους. Για πολλούς (συμπεριλαμβανομένου κι εμένα) ο 2ος τρόπος θεωρείται καλύτερη πρακτική, επειδή διαχωρίζουμε οπτικά άμεσα τις κλήσεις των απλών συναρτήσεις από εκείνες που γίνονται δια μέσω δεικτών σε συναρτήσεις. Ο λόγος που οι δείκτες συναρτήσεων δεν γίνονται dereferenced όπως οι υπόλοιποι δείκτες είναι επειδή αν γίνονταν θα έπρεπε να επιστρέψουν δεδομένα από το CODE segment (βασικά να μας δώσουν LVALUE πρόσβαση σε read-only memory). Όλοι οι υπόλοιποι δείκτες επιστρέφουν δεδομένα από το DATA segment. Ένα άλλο παράδειγμα που επιδεικνύει αυτή την συμπεριφορά είναι πως τα παρακάτω ισοδυναμούν όλα σε μια απλή κλήση της συνάρτησης test() ... > int test( void ) { puts("test"); } int main( void ) { test(); (*test)(); (**test)(); (***test)(); return 0; }
Timonkaipumpa Δημοσ. 31 Οκτωβρίου 2012 Δημοσ. 31 Οκτωβρίου 2012 Σωστός ο migf1... όντως σημαντική αναφορά για το dereferencing.
migf1 Δημοσ. 31 Οκτωβρίου 2012 Δημοσ. 31 Οκτωβρίου 2012 Καλησπέρα παιδιά, μήπως θα μπορούσε να μου εξηγήσει κάποιος το συγκεκριμένο κομμάτι της typedef γιατί μου είναι λίγο δυσνόητο; > typedef int (*funcptr)(double); // pointer to function of double returning int funcptr x = (funcptr) NULL; // C or C++ funcptr y = funcptr(NULL); // C or C++ Ευχαριστώ για το χρόνο σας. Τελικά βοηθήσαμε καθόλου ή σε μπερδέψαμε χειρότερα; Μας έχεις αφήσει να... γράφουμε έκθεση και δεν ξανάδωσες σημεία ζωής στο νήμα
migf1 Δημοσ. 1 Νοεμβρίου 2012 Δημοσ. 1 Νοεμβρίου 2012 Μένοντας στα των δεικτών (συναρτήσεων και μη) παραθέτω και μια συνάρτηση κονσόλας >bool askfor_yesno_noblanks(); που μόλις έγραψα για το τρέχον project με το οποίο ασχολούμαι, αλλά κάνει και για γενικότερη χρήση (οι άλλες δυο από τις οποίες εξαρτάται είναι επίσης γενικής χρήσης, αλλά από παλαιότερα projects: prompt_for & cc-hexview, οπότε τις παραθέτω κι αυτές) > #define MAXINPUT (255+1) /*********************************************************//** * @brief Ανάγνωση ενός c-string από την κύρια είσοδο. * * @param[in] prompt Κείμενο προτροπής εισόδου. * @param[in,out] str Το c-string στο οποίο αντιγράφονται οι χαρακτήρες. * @param maxlen Μέγιστο μήκος του c-string, συμπεριλαμβανομένου του * τελικού χαρακτήρα. * * @return 0 (FALSE) σε περίπτωση σφάλματος, αλλιώς 1 (TRUE). * * @remark To c-string \a str πρέπει να είναι ήδη δημιουργημένο και * να έχει χώρο για τουλάχιστον \a maxlen χαρακτήρες. * Στην <em>maxlen-οστή</em> θέση μπαίνει πάντα ο μηδενικός * χαρακτήρας, αυτόματα. ************************************************************* */ int prompt_for_string( const char *prompt, char *str, const int maxlen ) { int i; if ( !str ) return 0; /* FALSE */ if ( maxlen < 1 ) return 0; /* FALSE */ if ( prompt ) { printf( "%s", prompt ); fflush( stdout ); } for (i=0; i < maxlen-1 && (str[i]=(char)getchar()) != '\n' && str[i] != EOF; i++) ; /* eat up any extra characters from stdin */ if ( str[i] != '\n' && str[i] != EOF ) { int c; while ( (c=getchar()) != '\n' && c != EOF ) ; } /* nil-terminate str */ str[i] = '\0'; return 1; /* TRUE */ } /*********************************************************//** * @brief Return a pointer to the 1st non-blank character of a c-string, * or NULL on error. ************************************************************* */ char *s_cpTrim( const char *s ) { char *cp = (char *)s; if ( !s ) return cp; while ( isspace( (int)(*cp) ) ) cp++; return cp; } /*********************************************************//** * ************************************************************* */ bool askfor_yesno_noblanks( const char *prompt, const char chExpected, int (*cb_normalize)(int) ) { char input[MAXINPUT] = {'\0'}; char *cpTrimmed = NULL; int (*normalize)(int) = (NULL == cb_normalize) ? &tolower : cb_normalize; int ch = (*normalize)( (int)chExpected ); do { // demand anything but blanks OR chExpected prompt_for_string(prompt, input, MAXINPUT ); cpTrimmed = s_cpTrim(input); if ( cpTrimmed && (*normalize)(*cpTrimmed) == ch ) break; } while( NULL == cpTrimmed || '\0' == *cpTrimmed ); return (*normalize)(*cpTrimmed) == ch; } Στόχος της να μειώσει την επανάληψη του ίδιου κώδικα κατά την διαχείριση ερωτήσεων τύπου yes/no προς τον χρήστη. Αφαιρεί leading blanks (εκτός αν κάποιο από αυτά της δοθεί ως καθοριστικός χαρακτήρας) και αγνοεί κενές γραμμές (επαναλαμβάνει την ερώτηση). char *prompt: η ερώτηση char chExpected: ο αναμενόμενος καθοριστικός χαρακτήρας int (*cb_normalize)(int): callback συνάρτηση στα πρότυπα των tolower/toupper για normalization των απαντήσεων (αν περαστεί ως NULL κάνει default σε tolower() Δείγματα χρήσης... > if ( !askfor_yesno_noblanks("are you sure (y/)? ", 'y', &toupper) ) { puts( "operation cancelled" ); } else { // user answered 'y', so carry on with his will } > for (; { data = read_data(...); if ( list_isdup_data(...) ) { if ( !askfor_yesno_noblanks("data exist, overwrite or skip them (o/s)? ", 'o', NULL) ) continue; list_overwrite_data(...); } else { list_inset_data(...); } if ( !askfor_yesno_noblanks("more (y/)? ", 'y', NULL) ) break; }
migf1 Δημοσ. 1 Νοεμβρίου 2012 Δημοσ. 1 Νοεμβρίου 2012 (επεξεργασμένο) Έχει δίκιο η παροιμία "της νύχτας τα καμώματα τα βλέπει η μέρα και γελά" Μια βελτιωμένη και πιο γενική έκδοση της συνάρτησης του προηγούμενου ποστ (νομίζω και με πιο αντιπροσωπευτικό όνομα)... > /*********************************************************//** * @brief Ask the user a question, expecting a specified char as a positive answer. * @param[in] prompt The prompt to be displayed (NULL for no prompt at all). * @param[in] chExpected The character to be considered as a positive answer. * @param[in] cb_normalize Callback function to normalize the expected char in user input * (NULL for no normalization). * @return true if the expected char is inputted as the 1st (non-blank ?) char, * false otherwise. * @note The following notes help in using this function with its full potential: * - Normally, all leading blanks in the input line are ignored. However, a * blank character (e.g ' ' or '\t') may be specified in the 2nd argument * of the function, if you need it as a positive answer. But this will work * \b only if that blank is the very 1st character in the input line. * - Answers consisting of just an empty line, cause the function to repeat * the question. "Empty line" means 0 or any blank characters followed by * the final '\n', unless a blank character is specified in the 2nd argument * of the function \b and it is found as the very 1st character in the input. * - Normalization most usually concerns the uppper/lower case of the expected * character, so the prototype of the callback function complies with the * standard <ctype.h> functions \a tolower() and \a toupper() ). ************************************************************* */ /** Helper function (standard C doesn't support function nesting) */ static int _cb_dontNormalizeChar( int c ) { return c; } bool askfor_yes_noblanks( const char *prompt, // NULL for no prompt const char chExpected, // to be considered a positive answer int (*cb_normalize)(int) // NULL for no char normalization ) { char input[MAXINPUT] = {'\0'}; char *cpTrimmed = NULL; int (*normalize)(int) = (NULL == cb_normalize) ? &_cb_dontNormalizeChar : cb_normalize; int ch = (*normalize)( (int)chExpected ); do { // demand anything but blanks OR chExpected if ( prompt_for_string(prompt, input, MAXINPUT) && (*normalize)(*input) == ch ) return true; // or just: break; cpTrimmed = s_cpTrim(input); } while( NULL == cpTrimmed || '\0' == *cpTrimmed ); return (*normalize)(*cpTrimmed) == ch; } ΥΓ. Τα κεφάλια μέσα πάλι, back to work... EDIT: Ακριβέστερη περιγραφή της συνάρτησης, στα doxygen σχόλιά της. Επεξ/σία 1 Νοεμβρίου 2012 από migf1
nik324 Δημοσ. 1 Νοεμβρίου 2012 Δημοσ. 1 Νοεμβρίου 2012 Ερωτηση... Ειχα γραψει καποιες συναρτησεις οι οποιες επερναν ορισματα για structures καποιου συγκεκριμενου τυπου... Τωρα θελω να ξανα χρησιμοιποιησω τις ιδιες συναρτησεις για αλλους τυπους δομων...Τα αλλάζω ολα οσα χρειαζονται και ο minGW μου πεταει μερικα warnings και αυτο assignment from incompatible pointer type [enabled by default] σε σημειο που κανω list = list->next; σε συναρτηση εισαγωγης κομβου πχ Kαμια ιδεα για τι τι μπορει να φταιει; Ευχαριστω
Προτεινόμενες αναρτήσεις