Προς το περιεχόμενο

Συναρτησεις C


gian_90

Προτεινόμενες αναρτήσεις

Δημοσ.

Εχω καποιες αποριες σχετικα με τις συναρτησεις στην c.Ο μονος τροπος να αλλαξει μια τιμη μεσω μιας συναρτησης χωρις return ειναι μεσω ενος pointer η ενος πινακα string?

και επισης για να καλεσω μια συναρτηση που περιεχει ενα δισδιαστατο πινακα ο μονος τροπος ειναι στη δηλωση να υπαρχει τετοια συνταξη?

void pinakas(char disdiastatos[][10]);

δηλαδη μια κενη αγκυλη και η δευτερη να περιεχει τον αριθμο των στηλων?

γιατι ετσι μονο μου κανει compile.

ευχαριστω προκαταβολικα για την βοηθεια!:-)

Δημοσ.

Έφτιαξα ένα κώδικα για να δείς στην πράξη αυτά που ρωτάς.

 

>
/*
*                      Δοκιμή για πέρασμα ορισμάτων
*
* Υπάρχουν δύο τρόποι να περάσεις ορίσματα σε μία
* συνάρτηση. Ο ένας είναι "με τιμή" (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
Δημοσ.
Εχω καποιες αποριες σχετικα με τις συναρτησεις στην 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);

Δημοσ.

Το μόνο πρόβλημα όταν περνάς δέικτες (που δέιχνουν σε πίνακες) ως ορίσματα σε συναρτήσεις δεν γνωρίζεις το μέγεθος τους. Θα πρέπει να περνάς και το μέγεθος τους μαζί.

 

Υ.Γ.:

 

Υπάρχει και άλλος ένα τρόπος όχι τόσο κομψός αλλά πιό έυκολος (όχι όμως και ο καλύτερος ανάλογα την περίσταση βέβαια):P

 

>
#include <stdio.h>

void twoDimension(void);

static char a[5][10];

int main() {
 ...
 twoDimension();
 ...
}

void twoDimension(void)
{
 ...
 a[0][0] = ...
 ...
}

Αρχειοθετημένο

Αυτό το θέμα έχει αρχειοθετηθεί και είναι κλειστό για περαιτέρω απαντήσεις.

  • Δημιουργία νέου...