Timonkaipumpa Δημοσ. 15 Φεβρουαρίου 2012 Δημοσ. 15 Φεβρουαρίου 2012 Ναι. Με το προηγούμενο (const char * * const * const sarr) είχες έναν σταθερό δείκτη σε σταθερό δείκτη σε απλό δείκτη που έδειχνε σε σταθερές τιμές char. Με αυτό (const char * const * const *sarr) έχεις έναν απλό δείκτη σε σταθερό δείκτη σε σταθερό δείκτη σε σταθερές τιμές char.
migf1 Δημοσ. 15 Φεβρουαρίου 2012 Μέλος Δημοσ. 15 Φεβρουαρίου 2012 Ούτε αυτό Μου χει σπάσει τα νεύρα !!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!! > #include <stdio.h> #include <stdlib.h> #include <string.h> #define pressENTER() \ do{ \ char mYcHAr; \ printf( "press ENTER..." ); \ while ( (mYcHAr=getchar()) != '\n' && mYcHAr != EOF ) \ ; \ }while(0) /*********************************************************//** * ************************************************************* */ int sarr_swap( char ***sarr1, char ***sarr2 ) { char **temp = *sarr1; if ( !sarr1 || !*sarr1 || !sarr2 || !*sarr2 ) return 0; /* FALSE */ *sarr1 = *sarr2; *sarr2 = temp; return 1; /* TRUE */ } /*********************************************************//** * @brief Print to stdout the contents of a NULL terminated * array of c-strings. * @param[in] sarr The NULL terminated array of c-strings. ************************************************************* */ void sarr_print( char *const *const sarr ) { int i = 0; if ( !sarr ) return; for (i=0; sarr[i]; i++ ) printf("%2d: %s\n", i, sarr[i] ); return; } /*********************************************************//** * ************************************************************* */ char **sarr_init( char ***sarr, const char *sinit ) { int i = 0; if ( !sarr || !*sarr || !sinit ) return *sarr; for (i=0; (*sarr)[i]; i++) strcpy( (*sarr)[i], sinit ); return *sarr; } /*********************************************************//** * @brief Free memory reserved for a NULL terminated array of c-strings. * @param[in,out] sarr Pointer to the NULL terminated array of c-strings. * @remark The array pointer is reset to NULL (that's why the array is * passed by reference). ************************************************************* */ void sarr_free( char ***sarr ) { int i = 0; if ( !sarr || !*sarr ) return; while ( (*sarr)[i] ) free( (*sarr)[i++] ); *sarr = NULL; } /*********************************************************//** * Reserve memory for a NULL terminated array of nstrings c-strings, * each one being len characters long, excluding the nil terminating character. ************************************************************* */ char **sarr_new( const int nstrings, const int lenstr ) { char **sarr = NULL; int i=0; if ( nstrings < 1 || lenstr < 1 ) return NULL; if ( NULL == (sarr = calloc( nstrings+1, sizeof(char *) )) ) return NULL; for (i=0; i < nstrings; i++) { if ( NULL == (sarr[i] = calloc( lenstr+1, sizeof(char) )) ) { int j; for (j=i-1; j > -1; j--) free( sarr[j] ); free( sarr ); return NULL; } } return sarr; } /* ------------------------------------------------------- * * ------------------------------------------------------- */ int main( void ) { char **sarr1 = NULL, **sarr2 = NULL; if ( NULL == (sarr1=sarr_new( 5, 80+1)) ) { puts("*** sarr1 = sarr_new() failed!"); pressENTER(); exit( EXIT_FAILURE ); } if ( NULL == (sarr2=sarr_new( 5, 80+1)) ) { puts("*** sarr2 = sarr_new() failed!"); sarr_free( &sarr1 ); pressENTER(); exit( EXIT_FAILURE ); } sarr_init( &sarr1, "inited" ); sarr_print( sarr1 ); sarr_init( &sarr2, "INITED" ); sarr_print( sarr2 ); if ( !sarr_swap( &sarr1, &sarr2 ) ) puts("*** sarr_swap() failed!"); sarr_print( sarr1 ); sarr_print( sarr2 ); sarr_free( &sarr1 ); sarr_free( &sarr2 ); pressENTER(); exit( EXIT_SUCCESS ); } Θα μπορούσε κάποια ευγενική ψυχή να φτιάξει τις δηλώσεις των ορισμάτων της sarr_swap() και το temp, ώστε να κάνει αυτό που συζητάμε; EDIT: Έβαλα ένα if στην main() για όταν απoτυγχάνει η sarr_swap()
Timonkaipumpa Δημοσ. 15 Φεβρουαρίου 2012 Δημοσ. 15 Φεβρουαρίου 2012 Όπως έχεις τον κώδικα, δεν θα δουλέψει. Δες αυτό: >#include <stdio.h> #include <stdlib.h> /* * */ typedef const char * const theString; typedef const theString * const ptheString; typedef const ptheString* sarr; int main(int argc, char** argv) { //=================== // Πρώτος πίνακας theString str1_1= "str1_1\0"; theString str1_2= "str1_2\0"; theString str2_1= "str2_1\0"; theString str2_2= "str2_2\0"; char** row1Tmp = (char**) malloc (sizeof(char*) * 2); row1Tmp[0] = &str1_1; row1Tmp[1] = &str1_2; ptheString row1 = row1Tmp; row1Tmp = NULL; char** row2Tmp = (char**) malloc (sizeof(char*) * 2); row2Tmp[0] = &str2_1; row2Tmp[1] = &str2_2; ptheString row2 = row2Tmp; row2Tmp = NULL; char*** sarr1Tmp = (char***) malloc( sizeof(char**) * 2); sarr1Tmp[0] = row1; sarr1Tmp[1] = row2; sarr sarr1 = sarr1Tmp; sarr1Tmp = NULL; //=========================== // Δεύτερος πίνακας theString strNew1_1= "strNew1_1\0"; theString strNew1_2= "strNew1_2\0"; theString strNew2_1= "strNew2_1\0"; theString strNew2_2= "strNew2_2\0"; char** row21Tmp = (char**) malloc (sizeof(char*) * 2); row21Tmp[0] = &strNew1_1; row21Tmp[1] = &strNew1_2; ptheString row21 = row21Tmp; row21Tmp = NULL; char** row22Tmp = (char**) malloc (sizeof(char*) * 2); row22Tmp[0] = &strNew2_1; row22Tmp[1] = &strNew2_2; ptheString row22 = row22Tmp; row22Tmp = NULL; char*** sarr21Tmp = (char***) malloc( sizeof(char**) * 2); sarr21Tmp[0] = row21; sarr21Tmp[1] = row22; //Από εδώ και κάτω είναι το swap sarr sarr2 = sarr1Tmp; sarr1Tmp = NULL; sarr sarrTmp = sarr1; sarr1 = sarr2; sarr2 = sarr1; return (EXIT_SUCCESS); } (Πολύ γρήγορο παράδειγμα) Παρατήρησε πως χτίζεται ο πίνακας που θες. Εφόσον δηλώνεις σταθερούς δείκτες, δεν μπορείς να κάνεις malloc, γιατί ήδη ο δείκτης παίρνει τιμή. Σαν περιοχή μνήμης. Και αυτή η περιοχή, έχει ήδη κάτι μέσα... ό,τι και να είναι αυτό. Και αυτό επίσης είναι σταθερό. Και δεν μπορεί να αλλάξει.
virxen75 Δημοσ. 15 Φεβρουαρίου 2012 Δημοσ. 15 Φεβρουαρίου 2012 //Από εδώ και κάτω είναι το swap sarr sarr2 = sarr1Tmp; sarr1Tmp = NULL; sarr sarrTmp = sarr1; sarr1 = sarr2; sarr2 = sarr1;//<----------------------- μηπως θες να πεις sarr2=sarrTmp;
migf1 Δημοσ. 15 Φεβρουαρίου 2012 Μέλος Δημοσ. 15 Φεβρουαρίου 2012 Παιδιά έχω πάρει ήδη ένα Depon, πάω για 2ο... και άκρη δεν έχω βγάλει ακόμα Χρειάζομαι ξεχωριστή ρουτίνα σαν την sarr_swap() που έχω ποστάρει, τα ορίσματα της οποίας να είναι πίνακες από c-strings (string arrays, sarr) δηλωμένα στην λίστα ορισμάτων της συνάρτησης έτσι ώστε μέσα στη συνάρτηση να μπορούν να αλλάζουν μονάχα οι δείκτες sarr1 και sarr2 και απολύτως τίποτε άλλο. EDIT: Δεν ξέρω αν σας βοηθάει, αλλά ουσιαστικά αυτό που χρειάζομαι είναι το αντίστοιχο του... > /* ------------------------------------------------------- * * ------------------------------------------------------- */ int s_swap( const char **s1, const char **s2 ) { const char *temp = *s1; if ( !s1 || !s2 ) return 0; *s1 = *s2; *s2 = temp; return 1; } int main( void ) { char *s1 = "str1long"; char *s2 = "str2"; puts( s1 ); puts( s2 ); s_swap( (const char **)&s1, (const char **)&s2 ); puts( s1 ); puts( s2 ); return 0; } αλλά για πίνακες από strings αντί για σκέτα strings Είναι απίστευτο το ότι έχω φάει τόσες ώρες χωρίς αποτέλεσμα
Timonkaipumpa Δημοσ. 15 Φεβρουαρίου 2012 Δημοσ. 15 Φεβρουαρίου 2012 Α χα.. Τώρα κατάλαβα τι ζητάς...! > int swap( const char * const * const *input1, const char * const * const *input2) { const char * const * const *tmp1 = input1; input1 = input2; input2 = tmp1; return 1; } Αυτό δεν σου τρέχει; Ναι Virxen... αυτό ήθελα
migf1 Δημοσ. 15 Φεβρουαρίου 2012 Μέλος Δημοσ. 15 Φεβρουαρίου 2012 ... Αυτό δεν σου τρέχει; ... Δεν τρέχει το μπ&*%^%$λο !!! Δεν κάνει την εναλλαγή. ΥΓ1. Φίλε Virxen, το πρόβλημα είναι όταν πάω να το κάνω ξεχωριστή συνάρτηση. ΥΓ2. Με βλέπω να καταπίνω την εθνική μου (μας) περηφάνια και να ποστάρω στο StackOverflow
Timonkaipumpa Δημοσ. 15 Φεβρουαρίου 2012 Δημοσ. 15 Φεβρουαρίου 2012 Α χα.. Δοκίμασέ το ως: > int swap_sarr(const char * const * const **in1, const char * const * const **in2) { char*** tmp1; tmp1 = (*in1); (*in1) = (*in2); (*in2) = tmp1; } Και κάνε χρήση ως: > char*** test1, test2; .... swap_sarr(&test1, &test2); Λογικά αυτό θα δουλέψει.
migf1 Δημοσ. 15 Φεβρουαρίου 2012 Μέλος Δημοσ. 15 Φεβρουαρίου 2012 Ήρθα σπίτι και νομίζω το κατάφερα! > int sarr_swap(const char *const **sarr1, const char *const **sarr2 ) { const char *const *temp = NULL; if ( !sarr1 || !*sarr1 || !sarr2 || !*sarr2 ) return 0; /* FALSE */ temp = *sarr1; *sarr1 = *sarr2; *sarr2 = temp; return 1; /* TRUE */ } Κατέφυγα όμως στο: http://cdecl.org για να δω ότι: > const char *const **sarr // declare sarr as pointer to pointer to const pointer to const char και const char *const *temp // declare temp as pointer to const pointer to const char Το μόνο "πρόβλημα" που δεν ξέρω αν είναι κρίσιμης σημασίας είναι πως χωρίς casting στην κλήση... > sarr_swap( &sarr1, &sarr2 ); ο compiler παραπονιέται για πέρασμα ασύμβατων τύπων ως ορίσματα της συνάρτησης, αλλά ως προειδοποιήσεις και όχι ως fatal errors. EDIT: Λοιπόν νομίζω έκλεισε στο παραπάνω! Και με 2 typedefs όλα πρέπει να είναι οκ... > typedef const char *const ConstString; typedef const char *const * ArrayOfConstString; ... int sarr_swap( ArrayOfConstString *sarr1, ArrayOfConstString *sarr2 ) { ConstString *temp = NULL; if ( !sarr1 || !*sarr1 || !sarr2 || !*sarr2 ) return 0; /* FALSE */ temp = *sarr1; *sarr1 = *sarr2; *sarr2 = temp; return 1; /* TRUE */ } ... int main( void ) { ... if ( !sarr_swap( (ArrayOfConstString *)&sarr1, (ArrayOfConstString *)&sarr2 ) ) puts("*** sarr_swap() failed!"); ... }
defacer Δημοσ. 15 Φεβρουαρίου 2012 Δημοσ. 15 Φεβρουαρίου 2012 Από τη στιγμή που ήθελες να κάνεις απλώς swap πάντως θα μπορούσες να τα περάσεις σαν void** και να γλυτώσεις πολλούς πονοκεφάλους... Πέρα από την πλάκα, δε νομίζω ότι κάνοντας τη συγκεκριμένη function πιο απαιτητική όσον αφορά τις παραμέτρους της προκύπτει ώφελος.
migf1 Δημοσ. 15 Φεβρουαρίου 2012 Μέλος Δημοσ. 15 Φεβρουαρίου 2012 Από τη στιγμή που ήθελες να κάνεις απλώς swap πάντως θα μπορούσες να τα περάσεις σαν void** και να γλυτώσεις πολλούς πονοκεφάλους... Όχι, το swap ήταν απλώς παράδειγμα. Εκεί που σκάλωσα άσχημα και ταλαιπωρήθηκα και ταλαιπώρησα και τα παιδιά ήταν στο ότι οι δείκτες sarr δεν μπορούν να γίνουν const χωρίς να μεσολαβήσει κι άλλος δείκτης Η τελευταία δημοσίευση του timonkaipumpa δείχνει αυτό ακριβώς (btw, timon είσαι μεγάλη μορφή! ) Πέρα από την πλάκα, δε νομίζω ότι κάνοντας τη συγκεκριμένη function πιο απαιτητική όσον αφορά τις παραμέτρους της προκύπτει ώφελος. Χρειάζομαι εγγύηση πως κάποιες συναρτήσεις δεν θα πειράξουν καθόλου τον πίνακα.
defacer Δημοσ. 15 Φεβρουαρίου 2012 Δημοσ. 15 Φεβρουαρίου 2012 Χρειάζομαι εγγύηση πως κάποιες συναρτήσεις δεν θα πειράξουν καθόλου τον πίνακα. ...άρα χρειάζεσαι μια γλώσσα που δεν επιτρέπει casts. ;-)
Timonkaipumpa Δημοσ. 15 Φεβρουαρίου 2012 Δημοσ. 15 Φεβρουαρίου 2012 ...άρα χρειάζεσαι μια γλώσσα που δεν επιτρέπει casts. ;-) Ή μία που να μπορεί να παρέχει τέτοιες εγγυήσεις και να επιτρέπει και casts
migf1 Δημοσ. 15 Φεβρουαρίου 2012 Μέλος Δημοσ. 15 Φεβρουαρίου 2012 Γιατί ρε παιδιά; Έτσι όπως το κάναμε τώρα δεν είναι εγγυημένο πως π.χ. η swap μέσα της δεν μπορεί ούτε και κατά λάθος να αλλάξει τα περιεχόμενα του πίνακα (π.χ. να βάλει τον δείκτη sarr[5] να δείχνει κάπου αλλού, ή να αλλάξει τα περιεχόμενα του string *(sarr[3]) ); EDIT: Εγώ πάντως δοκίμασα μόλις τώρα το παρακάτω (γιατί δεν μου έχω και πολύ εμπιστοσύνη μετά το πακέτο που έφαγα σήμερα, με το μυαλό μου να έχει γίνει ... ζουμί) και δουλεύει as intended... > int sarr_swap(ArrayOfConstString *sarr1, ArrayOfConstString *sarr2 ) { ConstString *temp = NULL; if ( !sarr1 || !*sarr1 || !sarr2 || !*sarr2 ) return 0; /* FALSE */ temp = *sarr1; *sarr1 = *sarr2; *sarr2 = temp; **sarr2[0] = 'N'; /* <--- IMPOSSIBLE */ *sarr2[0] = *sarr2[1]; /* <--- IMPOSSIBLE */ return 1; /* TRUE */ } δηλαδή βαράει errors ο compiler στις 2 προτελευταίες γραμμές, as it should... > temp1.c:50:2: error: assignment of read-only location '***sarr2' temp1.c:51:2: error: assignment of read-only location '**sarr2'
Timonkaipumpa Δημοσ. 15 Φεβρουαρίου 2012 Δημοσ. 15 Φεβρουαρίου 2012 Είναι και παρα-είναι Αυτό έλεγα ότι μία γλώσσα που επιτρέπει casts (π.χ. (char*) (void*) ) αλλά και να παρέχει τέτοιου είδους εγγυήσεις (π.χ. const )
Προτεινόμενες αναρτήσεις
Δημιουργήστε ένα λογαριασμό ή συνδεθείτε για να σχολιάσετε
Πρέπει να είστε μέλος για να αφήσετε σχόλιο
Δημιουργία λογαριασμού
Εγγραφείτε με νέο λογαριασμό στην κοινότητα μας. Είναι πανεύκολο!
Δημιουργία νέου λογαριασμούΣύνδεση
Έχετε ήδη λογαριασμό; Συνδεθείτε εδώ.
Συνδεθείτε τώρα