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

Ασκηση σε C με δεικτες

Ερώτηση

Καλησπερα στο φορουμ και Χρονια πολλα... Εχω μια ασκηση σε C που χρειαζεται να χρησιμοποιω δεικτες και δυναμικη αναθεση μνημης. Πρεπει το προγραμμα να καλει μια συναρτηση οπου η συναρτηση θα κανει συγκεκριμένη δουλεια.. Αυτο που θελω να ρωτησω για αρχη ειναι τι σημαινει οταν μπροστα απο την συναρτηση υπαρχει ο αστερισκος (*)? Δηλαδη μας δινει ετοιμο το ονομα της συναρτησης ετσι: 

 

int * biggerTable(int *old, int old_size, int new_size)

Καταλαβαινω πως σαν ορισματα δεχεται τον πινακα old με δεικτη ετσι ωστε να τον τροποποιησει, και 2 ακεραια μεγεθη.. Μπροστα απο το ονομα της συναρτησης γιατι εχει ομως το αστερακι? Τι υποδειλωνει και πως εγω θα την καλεσω?

Κοινοποιήστε αυτήν την ανάρτηση


Σύνδεσμος στην ανάρτηση
Κοινοποίηση σε άλλες σελίδες

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

  • 0

Καλησπέρα και χρόνια πολλά.

 

Ουσιαστικά σου λέει πως η συνάρτηση θα επιστρέφει τον μεγαλωμένο πίνακα old. Μιας και για να αλλάξεις το μέγεθος του πίνακα θα χρησιμοποιήσεις την realloc(), οπότε δεν είναι εγγυημένο πως ο δείκτης που θα σου επιστρέψει η realloc() θα δείχνει στην ίδια διεύθυνση που έδειχνε ο αρχικός δέικτης old (δες την τεκμηρίωση της realloc()) η συνάρτησή σου πρέπει να επιστρέφει τον δείκτη που επιστρέφει η realloc() και όχι τον αρχικό old που περνάς σαν όρισμα.

Κοινοποιήστε αυτήν την ανάρτηση


Σύνδεσμος στην ανάρτηση
Κοινοποίηση σε άλλες σελίδες
  • 0

Όχι.

Απλά το επιστρεφόμενο αποτέλεσμα το περνάς σε ένα int* (το αστεράκι πάει στο int, όχι στην συνάρτηση).

 

int * newTable = biggerTable(A, old_size, new_size);
//Δεν βάζεις * στο Α για να περάσεις τον δείκτη του μονάχα και όχι τα περιεχόμενά του
//και η επιστρεφόμενη τιμή είναι int * οπότε το αναθέτεις αντίστοιχα.

Κοινοποιήστε αυτήν την ανάρτηση


Σύνδεσμος στην ανάρτηση
Κοινοποίηση σε άλλες σελίδες
  • 0

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

 

Στην περίπτωσή σου, η λογική κλήση της συνάρτησης είναι η παρακάτω...

arrInt= biggerTable(arrInt, old_size, new_size);

(*) EDIT:

 

Το κείμενο αναφέρεται στην γενική περίπτωση μιας συνάρτησης που επιστρέφει δείκτη σε int, ενώ ο κώδικας αναφέρεται στη δική σου περίπτωση που αφορά ειδικά πίνακα από int.

Κοινοποιήστε αυτήν την ανάρτηση


Σύνδεσμος στην ανάρτηση
Κοινοποίηση σε άλλες σελίδες
  • 0

Ωραια.. Τωρα εχω δημιουργησει την συναρτηση που αυξανει το μεγεθος του πινακα.. Φτιαχνω μια επαναληψη για να δω το περιεχομενο των πινακων ομως μου εμφανιζει την θεση μνημης αυτων.. Τι κανω λαθος..? 

int *biggerTable(int *old, int old_size, int new_size){
	int i;
	old = malloc ((new_size-old_size) *sizeof(int));
	for (i=0;i<new_size;i++){
		printf ("%d\n",&old[i]);
	}
}

Κοινοποιήστε αυτήν την ανάρτηση


Σύνδεσμος στην ανάρτηση
Κοινοποίηση σε άλλες σελίδες
  • 0

Πρώτον,έχεις λάθος στη δέσμευση μεγαλύτερης μνήμης για τον πίνακα.

Όχι μόνο δε δεσμεύεις περισσότερη μνήμη,αλλά προσπαθείς να κάνεις access

μνήμη που βρίσκεται πέρα από τα όρια του old.

Αυτό θα έχει αποτέλεσμα  ή να φας segmentation fault ή να τυπώσεις "σκουπίδια".

Για να λυθεί το πρόβλημα χρησιμοποιήσε τη realloc για να μεγαλώσεις το πίνακα σου.   

 

old = (int *)realloc (old,(new_size-old_size) * sizeof(int));
 

 

Σου εμφανίζει τη θέση μνήμης γιατί χρησιμοποιείς το τελεστή &, οποίος επιστρέφει τη διεύθυνση της μνήμης του old.

Οπότε απλώς βγάλε το &

 

 

Τέλος κάνε και ένα

 

return old;

 

αφού η συνάρτηση πρέπει να επιστρέφει το δείκτη προν το μεγαλύτερο πίνακα.

Κοινοποιήστε αυτήν την ανάρτηση


Σύνδεσμος στην ανάρτηση
Κοινοποίηση σε άλλες σελίδες
  • 0

Καλησπερα στο φορουμ και Χρονια πολλα... Εχω μια ασκηση σε C που χρειαζεται να χρησιμοποιω δεικτες και δυναμικη αναθεση μνημης. Πρεπει το προγραμμα να καλει μια συναρτηση οπου η συναρτηση θα κανει συγκεκριμένη δουλεια.. Αυτο που θελω να ρωτησω για αρχη ειναι τι σημαινει οταν μπροστα απο την συναρτηση υπαρχει ο αστερισκος (*)? Δηλαδη μας δινει ετοιμο το ονομα της συναρτησης ετσι: 

 

int * biggerTable(int *old, int old_size, int new_size)

Καταλαβαινω πως σαν ορισματα δεχεται τον πινακα old με δεικτη ετσι ωστε να τον τροποποιησει, και 2 ακεραια μεγεθη.. Μπροστα απο το ονομα της συναρτησης γιατι εχει ομως το αστερακι? Τι υποδειλωνει και πως εγω θα την καλεσω?

 

Ακομη και αν η παραμετρος old περνουσε μεσα με array notation old[] παλι δεικτης (με τιμή διευθυνση στο 1ο στοιχειο του πινακα σου) θα ηταν αυτο που θα περνουσε μεσα στην συναρτηση. Μεσα σε μια συναρτηση ενας πινακας αντιμετωπιζεται σαν δεικτης με την προυποθεση οτι τον εχεις δηλωσει στις παραμετρους της συναρτησης ειτε με μορφη πινακα ειτε με μορφη δεικτη. Ειναι πολυ σημαντικο να το ξεκαθαρισεις αυτο γιατι ειναι σημαντικοτερο απο αυτο που ρωτας  :P

Κοινοποιήστε αυτήν την ανάρτηση


Σύνδεσμος στην ανάρτηση
Κοινοποίηση σε άλλες σελίδες
  • 0

Ένα θεματάκι είναι να μάθεις να διαβάζεις τη σύνταξη στη C...το παρακάτω θα σε βοηθήσει να ξερεις τι ακριβώς είναι καθε declaration

 

http://c-faq.com/decl/spiral.anderson.html

Κοινοποιήστε αυτήν την ανάρτηση


Σύνδεσμος στην ανάρτηση
Κοινοποίηση σε άλλες σελίδες
  • 0

Ευχαριστω παιδια για τις απαντησεις.. Μου προέκυψε ομως ενα άλλο προβλημα.. Στην συναρτηση επεξεργαζομαι τον πινακα old και στο τελος κανω return old, ομως στο προγραμμα δινω την εντολη να εμφανισει τα περιεχομενα του "νεου" πλεον πινακα και μου γραφει: process exited with return value 3221225477

 

Ο κωδικας ειναι ο εξης: 

int *biggerTable(int *old, int old_size, int new_size){
	int i, k;
	old = (int *)realloc (old,(new_size-old_size) *sizeof(int));
...
...
...
...
	return old;


int main() {
...
...
...
...
    biggerTable(A, old_size, new_size);
	for (i=0;i<(new_size);i++){
		printf ("%d\n", A[i]);
	}
	return 0;
}

 

Γιατι δεν εμφανιζει τα στοιχεια του Α πλεον? :/

Κοινοποιήστε αυτήν την ανάρτηση


Σύνδεσμος στην ανάρτηση
Κοινοποίηση σε άλλες σελίδες
  • 0

Αν δεν κάνω λάθος η realloc δεν παίρνει σαν δεύτερο όρισμα την διαφορά των μεγεθών αλλά το καινούργιο μέγεθος.

Οπότε δεν είναι

old = (int *)realloc (old,(new_size-old_size) *sizeof(int));
αλλά
old = (int *)realloc (old, new_size * sizeof(int));

Κοινοποιήστε αυτήν την ανάρτηση


Σύνδεσμος στην ανάρτηση
Κοινοποίηση σε άλλες σελίδες
  • 0

Αν δεν κάνω λάθος η realloc δεν παίρνει σαν δεύτερο όρισμα την διαφορά των μεγεθών αλλά το καινούργιο μέγεθος.

Οπότε δεν είναι

old = (int *)realloc (old,(new_size-old_size) *sizeof(int));
αλλά
old = (int *)realloc (old, new_size * sizeof(int));
 

 

 

 

 

 

 

 

 

 

 

 

 

Σωστός ο MitsakosGR, πόνεσαν τα μάτια μας πριν.

 

Επίσης καλό θα ήταν να αποθηκεύσεις το αποτέλεσμα της realloc σε έναν άλλο temporary pointer, και μόνο αν η δέσμευση πετύχει να επιστρέψεις αυτόν, δηλαδή αν δεν επιστραφεί NULL από τη realloc. Σε περίπτωση που η realloc αποτύχει θα επιστρέφεις τον pointer που περάστηκε σαν όρισμα. Αυτό βέβαια έχει το άλλο κακό, πώς η συνάρτησή σου θα αποτύχει σιωπηρά, και γι'αυτό υπάρχουν δύο λύσεις.

 

1. Περνάς κάποιον int by reference στην συνάρτηση και επιστρέφεις σε αυτόν ένα status code που υποδεικνύει αν η συνάρτησή σου πέτυχε ή απέτυχε.

 

Ακόμα καλύτερα:

 

2. Η συνάρτηση να επιστρέφει int με το status code και τον πίνακα που θες να κάνεις resize να τον περνάς στη συνάρτηση με διπλό pointer.

 

Από τις δύο, συγκεκριμένα σ'εσένα θα πρότεινα την 1η, γιατί είσαι πολύ αρχάριος με τους pointers. Αλλά αν είσαι πολύ περιπετειώδης τύπος μπορείς να δοκιμάσεις τη 2η.

 

Όλα αυτά χρειάζονται γιατί σε περίπτωση που αποτύχει η realloc, θα εκχωρήσεις NULL στον pointer που έδειχνε στον πίνακα (εκεί που θα κληθεί η συνάρτησή σου), και εκτός του ότι θα χάσεις τα δεδομένα του, θα έχεις και memory leak.

 

Έσχατη λύση είναι να εκχωρείς το αποτέλεσμα της κλήσης της συνάρτησής σου σε temporary pointer και αν δεν είναι NULL να εκχωρείς αυτόν τον pointer σε αυτόν που έδειχνε στον πίνακα. Αυτό έχει το μειονέκτημα πως θα πρέπει να γίνεται ΚΑΘΕ φορά που την καλείς.

Κοινοποιήστε αυτήν την ανάρτηση


Σύνδεσμος στην ανάρτηση
Κοινοποίηση σε άλλες σελίδες
  • 0

Να απτυχει η realloc ειναι λιγο δυσκολο στην συγκεκριμενη περιπτωση γιατι δινονται τα νουμερα στανταρ απο πριν.. (π.χ στην main τα μεγεθη old_size και new_size παιρνουν συγκεκριμενους αριθμους) οποτε εμενα το μονο μου προβλημα ειναι γιατι δεν κανει print αυτα που θελω στην main..

 

EDIT: Ακυρο.. Τελικα το προβλημα ηταν με την συνταξη της realloc.. Προφανως με την διορθωση αυτη διορθωθηκε και το προβλημα.. 

 

ΕΥΧΑΡΙΣΤΩ ολους για την πολυτιμη βοηθεια..

Κοινοποιήστε αυτήν την ανάρτηση


Σύνδεσμος στην ανάρτηση
Κοινοποίηση σε άλλες σελίδες
  • 0

Να ξέρεις ότι δεν έχουν σημασία τα μεγέθη που δίνεις για το αν θα πετύχει ή θα αποτύχει η realloc. Για να μην γίνομαι ανακριβής, ΕΧΟΥΝ αλλά όχι στο context που νομίζεις εσύ. H realloc συνήθως αποτυγχάνει λόγω κατακερματισμού του heap, δηλαδή δεν υπάρχουν αρκετές συνεχόμενες θέσεις μνήμης ελεύθερες στο heap ώστε να δεσμευθούν. Άλλος λόγος είναι το ότι έχεις εξαντλήσει το virtual address space σου, δηλαδή δεν υπάρχει άλλη ελεύθερη μνήμη .

 

Επίσης, σου προτείνω να μην προγραμματίζεις με το σκεπτικό ότι κάτι σου κάνει για μια συγκεκριμένη περίπτωση, αλλά για το τι είναι καλό ΓΕΝΙΚΑ. Γιατί να μάθεις να κάνεις κάτι σωστά αργότερα, ενώ μπορείς να το κάνεις τώρα?

Κοινοποιήστε αυτήν την ανάρτηση


Σύνδεσμος στην ανάρτηση
Κοινοποίηση σε άλλες σελίδες

Δημιουργήστε έναν λογαριασμό ή συνδεθείτε για να σχολιάσετε

Πρέπει να είστε μέλος για να αφήσετε σχόλιο

Δημιουργία λογαριασμού

Εγγραφείτε με νέο λογαριασμό στην κοινότητα μας. Είναι εύκολο!

Εγγραφείτε για έναν νέο λογαριασμό

Σύνδεση

Έχετε ήδη λογαριασμό; Συνδεθείτε εδώ.

Συνδεθείτε τώρα
×
×
  • Δημιουργία νέου...

Χρήσιμες πληροφορίες

Με την περιήγησή σας στο insomnia.gr, αποδέχεστε τη χρήση cookies που ενισχύουν σημαντικά την εμπειρία χρήσης.