gian_90 Δημοσ. 9 Νοεμβρίου 2009 Δημοσ. 9 Νοεμβρίου 2009 Εχω καποιες αποριες σχετικα με τις συναρτησεις στην c.Ο μονος τροπος να αλλαξει μια τιμη μεσω μιας συναρτησης χωρις return ειναι μεσω ενος pointer η ενος πινακα string? και επισης για να καλεσω μια συναρτηση που περιεχει ενα δισδιαστατο πινακα ο μονος τροπος ειναι στη δηλωση να υπαρχει τετοια συνταξη? void pinakas(char disdiastatos[][10]); δηλαδη μια κενη αγκυλη και η δευτερη να περιεχει τον αριθμο των στηλων? γιατι ετσι μονο μου κανει compile. ευχαριστω προκαταβολικα για την βοηθεια!
bab1s Δημοσ. 9 Νοεμβρίου 2009 Δημοσ. 9 Νοεμβρίου 2009 Έφτιαξα ένα κώδικα για να δείς στην πράξη αυτά που ρωτάς. > /* * Δοκιμή για πέρασμα ορισμάτων * * Υπάρχουν δύο τρόποι να περάσεις ορίσματα σε μία * συνάρτηση. Ο ένας είναι "με τιμή" (by value) και άλλος είναι * "με αναφορά" (by reference). * * Όταν περνάς τα ορίσματα "με τιμή" αυτό που γίνεται είναι να * δημιουργείται ένα προσωρινό αντόγραφο της μεταβλητής που περνάς * για την συγκεκριμένη συνάρτηση. Έχει διάρκεια ζωής όσο και η * συνάρτηση (οπότε χάνεται μόλις τελειώσει η εκτέλεση της) και * δεν επηρεάζει την τιμή της μεταβλητής. * * Αντίθετα, όταν περνάς τα ορίσματα "με αναφορά" δεν δημιουργείται * αντίγραφο γιατί δίνεις ουσιαστικά τη διεύθυνση μνήμης της μεταβλητής. * Έτσι, η συνάρτηση ό,τι αλλαγές κάνει πάνω στην μεταβλητή είναι * μόνιμες. Οπότε, άν θες μία συνάρτηση να "επιστρέψει" κάτι χωρίς το * return ή αν πρέπει να επιστρέψει παραπάνω από μία τιμές, πρέπει να * περάσεις τα ορίσματα "με αναφορά". Τέλος, αυτός ο τρόπος είναι * χρήσιμος όταν το όρισμα που περνάς έχει πολύ μεγάλο μέγεθος, όπως * πχ μία μεγάλη "δομή" (struct). Σε αυτήν την περίπτωση επωφελείσε από * το γεγονός ότι δε δημιουργείται αντίγραφο και άρα δουλεύει πιο γρήγορα. * * * * Πάμε και στο δυσδιάστατο πίνακα τώρα! Όταν ορίζεις τον πίνακα δείνεις * σαν όρισμα το μέγεθος του πίνακα σε κάθε διάσταση. Ο υπολογιστής * δεσμεύει χώρο στη μνήμη για τον πίνακα σε διαδοχικές θέσεις μνήμης. Αν * λοιπόν ο πίνακας είναι ο array[2][3] και η μνήμη ξεκινάει στη θέση 100, * τότε θα έχεις το εξής: * * Θέση μνήμης Στοιχείο Πίνακα * 100 array[0][0] * 101 array[0][1] * 102 array[0][2] * 103 array[1][0] * 104 array[1][1] * 105 array[1][2] * * Πρόσεξε ότι η "πρώτη διάσταση" λοιπόν θα επαναλαμβάνεται τόσες φορές * όσο είναι η τιμή της "δεύτερης διάστασης". * * Όταν εσύ θα ζητήσεις αργότερα ένα στοιχείο από τον πίνακα, έστω το * array[1][1], ο υπολογιστή θα κάνει τον παρακάτω υπολογισμό. Ξέρει ότι * το array ξεκιναέι στη θέση 100 και ότι η "δεύτερη διάσταση" είναι 3, * οπότε θα σου φέρει το περιεχόμενο της διεύθυνσης 100 + 1*3 + 1 = 104. * * Όλα αυτά, είναι ο λόγος για τον οποίο δεν μπορείς να μην ορίσεις τη * δεύτερη διάσταση ενώ η πρώτη μπορεί να μείνει κενή. Σίγουρα αυτό μπορεί * να είναι λίγο βλακεία, αλλά αν χρησιμοποιήσεις κάποιο "#define" για τις * διαστάσεις μπορείς να κάνεις τον κώδικα σου πιο κομψό. Θα βοηθούσε και * ένα "typedef"! */ #include <stdio.h> // Ορίζω το μέγιστο για κάθε διάσταση #define MAX_X 2 #define MAX_Y 7 // Κάνουμε ένα "typedef" για να γίνει πιο ωραίος ο κώδικας typedef char Array[MAX_X][MAX_Y]; // Τα ορίσματα είναι τύπου integer void fooByValue( int a, int b ); // Τα ορίσματα είναι pointer σε integer void fooByReference( int *a, int *b ); /* * Ο δυσδιάστατος πίνακας ορίζεται όπως είπες. * Δεν χρησιμοποίησα το "typedef" εδώ για να το δείς * γραμμένο ολογράφως! */ void twoDimension( char array[][MAX_Y] ); int main() { // Οι μεταβλητές για το πρώτο παράδειγμα int a = 2; int b = 3; // Οι μεταβλητές για το δεύτερο παράδειγμα char c[2][MAX_Y] = {"Hello,", "world!"}; Array d = {"\nBye ", "bye!"}; // Εναλλακτικός τρόπος γραφής // Θα μπορούσες να το βάλεις και // στη δήλωση της συνάρτησης // Βλέπουμε τις τιμές που ορίσαμε στη main printf("main says : a = %d, b = %d\n\n", a, ; // Βλέπουμε τις τιμές από την fooByValue και από τη main fooByValue(a, ; printf("but main says : a = %d, b = %d\n\n", a, ; // Βλέπουμε τις τιμές από την fooByReference και από τη main fooByReference(&a, &; printf("and main agrees : a = %d, b = %d\n\n", a, ; // Περνάμε τον πίνακα απλώς με το όνομα του twoDimension(c); twoDimension(d); return 0; } void fooByValue( int a, int b ) { a = 2*a; // Διπλασιάζουμε τα ορίσματα b = 2*b; // Βλέπουμε το αποτέλεσμα πριν φύγουμε από τη συνάρτηση printf("fooByValue says : a = %d, b = %d\n", a, ; } void fooByReference( int *a, int *b ) { (*a) = 2*(*a); // Διπλασιάζουμε τα ορίσματα (* = 2*(*; // Βλέπουμε το αποτέλεσμα πριν φύγουμε από τη συνάρτηση printf("fooByReference says: a = %d, b = %d\n", *a, *; } /* * ΠΡΟΣΟΧΗ!!! * * Δεν έχω κάνει κανένα έλεγχο για τις διαστάσεις!!! * Κανονικά θα έπρεπε να περάσεις σαν integer τις διαστάσεις * για να ελέγχεις μην ξεφύγεις από τα όρια!!! Βέβαια, αφού * τα κάναμε "#define" μπορείς να χρησιμοποιήσεις τα "MAX_X" * και "MAX_Y" */ void twoDimension( char array[][MAX_Y] ) { printf("%s %s\n", array[0], array[1]); } // Ελπίζω να βοήθησα!
Moderators Praetorian Δημοσ. 9 Νοεμβρίου 2009 Moderators Δημοσ. 9 Νοεμβρίου 2009 Εχω καποιες αποριες σχετικα με τις συναρτησεις στην c.Ο μονος τροπος να αλλαξει μια τιμη μεσω μιας συναρτησης χωρις return ειναι μεσω ενος pointer η ενος πινακα string? Ο μόνος τρόπος για να τροποποιηθεί η τιμή μιας παραμέτρου (ορίσματος) της συνάρτησης και να παραμείνει τροποποιημένη μετά την επιστροφή από τη συνάρτηση, είναι να περαστεί η παράμετρος κατ' αναφορά και συνεπώς με δείκτη. Την περιπτωση του πίνακα string δεν ξέρω γιατί την αναφέρεις (ίσως λόγω του char* argv[] στη main), αλλά οι πίνακες είναι κατ' ουσίαν δείκτες και προσωπικά προτιμώ να βλέπω δείκτες παρά πίνακες ειδικά σε ορίσματα συνάρτησης. Το char *argv[] (πίνακας από δείκτες σε char) είναι το ίδιο με το char **argv (δείκτης σε δείκτη char). και επισης για να καλεσω μια συναρτηση που περιεχει ενα δισδιαστατο πινακα ο μονος τροπος ειναι στη δηλωση να υπαρχει τετοια συνταξη? void pinakas(char disdiastatos[][10]); Ο δικός μου τρόπος θα ήταν να δηλώσω τη συνάρτηση ως: >void pinakas(char **disdiastatos); Ο δείκτης σε δείκτη char (ή πιο απλοϊκά δείκτης σε string) μπορεί να δεχτεί "δισδιάστατους" πίνακες από char. Αν ορίσεις τον δισδιάστατο πίνακά σου ως char a[5][10] (5 γραμμές των 10 χαρακτήρων) μπορείς να χρησιμοποιήσεις το a ως όρισμα στην κλήση της συνάρτησης pinakas. > char a[5][10]; pinakas(a);
pinball_elf Δημοσ. 10 Νοεμβρίου 2009 Δημοσ. 10 Νοεμβρίου 2009 Το μόνο πρόβλημα όταν περνάς δέικτες (που δέιχνουν σε πίνακες) ως ορίσματα σε συναρτήσεις δεν γνωρίζεις το μέγεθος τους. Θα πρέπει να περνάς και το μέγεθος τους μαζί. Υ.Γ.: Υπάρχει και άλλος ένα τρόπος όχι τόσο κομψός αλλά πιό έυκολος (όχι όμως και ο καλύτερος ανάλογα την περίσταση βέβαια) > #include <stdio.h> void twoDimension(void); static char a[5][10]; int main() { ... twoDimension(); ... } void twoDimension(void) { ... a[0][0] = ... ... }
Προτεινόμενες αναρτήσεις
Αρχειοθετημένο
Αυτό το θέμα έχει αρχειοθετηθεί και είναι κλειστό για περαιτέρω απαντήσεις.