Aristeidis Δημοσ. 7 Μαΐου 2008 Δημοσ. 7 Μαΐου 2008 Μας έβαλαν την παρακάτω άσκηση στη σχολή και δεν έχω διαβάσει τόσο καλά περί pointers και συναρτήσεων. Θα ήθελα αν μπορούσατε να με βοήθησετε να βρω τα λάθη μου και να μάθω απ'αυτά. Η εκφώνηση: Για να ελεγχθούν οι παρεμβολές μεταξύ Ν ραδιοσταθμών που εκπέμπουν με ισχύ Wi watt (i=1,…,Ν) να γραφεί το πρόγραμμα στο οποίο να ορίζεται η συνάρτηση void check(…) η οποία δέχεται την ισχύ εκπομπής δύο σταθμών, μια ελάχιστη wmin και μια μέγιστη wmax αποδεκτή ισχύ σήματος και την απόσταση μεταξύ των δυο σταθμών. Η συνάρτηση να υπολογίζει την ακτίνα εκπομπής κάθε σταθμού από τον τύπο Ri=sqrt(Wi/wmin) και αν υπάρχει επικάλυψη να υπολογίζει ένα κοινό ελάχιστο ποσοστό μείωσης της ισχύος των δυο σταθμών έτσι ώστε να μην υφίσταται η επικάλυψη. Η ίδια συνάρτηση να υπολογίζει με βάση αυτό το ποσοστό τις νέες τιμές για την εκπεμπόμενη ισχύ του κάθε σταθμού έτσι ώστε αυτές να βρίσκονται μέσα στα επιτρεπτά όρια και να μην υπάρχει επικάλυψη. Η συνάρτηση main να διαβάζει την ελάχιστη αποδεκτή ισχύ σήματος wmin, τη μέγιστη επιτρεπόμενη ισχύ wmax, τις συντεταγμένες (Xi,Yi) (i=1,…,Ν) και την ισχύ εκπομπής Wi, (i=1,…,Ν) από Ν σταθμούς και να χρησιμοποιεί τη συνάρτηση check για να υπολογίσει και να εκτυπώσει τις νέες τιμές για την ισχύ εκπομπής κάθε σταθμού έτσι ώστε να μην υπάρχει επικάλυψη. Σημείωση: Να μη χρησιμοποιηθούν πουθενά γενικές μεταβλητές. Η συνάρτηση check δε διαβάζει δεδομένα και δεν εκτυπώνει αποτελέσματα. και η υλοποίηση μου: #include <stdio.h> #include <stdlib.h> #include <math.h> void check(float wmin, float wmax, float *w1, float *w2, float r, double *pos); main() { float wmin,wmax,x1,y1,x2,y2,r,*w1,*w2; int n,i; printf("Dwse ton ari8mo twn sta8mwn\n"); scanf("%d\n",&n); printf("Dwse th wmin \n"); scanf("%f\n",&wmin); printf("Dwse th wmax \n"); scanf("%f\n",&wmax); for (i=1;i<=n;i++) { printf("Dwse tis suntetagmenes tou %d sta8mou\n",i); scanf("%f %f",&x1,&y1); do { printf("Dwse th suxnothta tou %d sta8mou\n",i); scanf("%f",&w1); } while (*w1 >= wmin && *w1 <= wmax); for (int j=1;j<=n;j++) { if (j != i) { double *pos = 0; printf("Dwse tis suntetagmenes tou %d sta8mou\n",j); scanf("%f %f", &x2, &y2); do { printf("Dwse th suxnothta tou %d sta8mou\n",i); scanf("%f",&w2); } while (*w2 >= wmin && *w2 <= wmax); float r=sqrt((x1-x2)*(x1-x2) + (y1-y2)*(y1-y2)); check(wmin,wmax,w1,w2,r,pos); printf("To pososto einai %f h w1 %f kai h w2 %f",pos,w1,w2); } } } } void check(float wmin, float wmax, float *w1, float *w2, float r, double *pos) { if (sqrt(*w1/wmin) + sqrt(*w2/wmin) > r) { double pos = r*r/((sqrt(*w1/wmin) + sqrt(*w2/wmin))*((sqrt(*w1/wmin) + sqrt(*w2/wmin)))); *w1=pos*(*w1); *w2=pos*(*w2); } if (*w1 < wmin) { *w1=wmin; } if (*w1 > wmax) { *w1=wmax; } if (*w2 < wmin) { *w2=wmin; } if (*w2 > wmax) { *w2=wmax; } }
Aesmade Δημοσ. 7 Μαΐου 2008 Δημοσ. 7 Μαΐου 2008 Κάποια απ'τα προβλήματα που βρήκα: Οι w1 και w2 είναι pointers, οπότε για να τους χρησιμοποιήσεις θα πρέπει να τους κάνεις allocate κάποια μνήμη. Αυτο μπορεί να γίνει βάζοντας αυτό πριν το πρώτο printf στο main: > w1=malloc(sizeof(float)); w2=malloc(sizeof(float)); double *pos=malloc(sizeof(double)); Σε κάποιο σημείο κάνεις double *pos=0. Αυτό κάνει το pos να "δείχνει" στη μνήμη στη διεύθυνση 0, την οποία δεν μπορείς να διαβάσεις, ενώ αν δοκιμάσεις θα γίνει access violation. Γι'αυτό, σβήσε αυτή τη γραμμή και, αφού χρησιμοποιήσεις τον παραπάνω κώδικα, κάνε *pos=0. Επίσης, ως pointers, η τιμή των w1,w2 είναι κάποια διεύθυνση. Οπότε, αντί να χρησιμοποιείς π.χ. scanf("%f",&w1) θα πρέπει να χρησιμοποιείς scanf("%f",w1) ώστε αυτό που θα διαβάσεις να αποθηκευτεί στο *w1. Μερικές φορές κάνεις declare κάποιες μεταβλητές για δεύτερη φορά (float r, double pos). Χρησιμοποίησε διαφορετικά ονόματα. Τέλος, καλό θα ήταν να κάνεις declare κάθε μεταβλητή στην αρχή κάθε συνάρτησης (π.χ. κάνεις for (int j=1;j<=n;j++) ενώ θα έπρεπε να έχεις κάνει declare τη j στην αρχή), αφού κάποιοι compilers (όπως ο δικός μου) το παίρνουν ως λάθος. Μπορεί να υπάρχει κάποιο άλλο λάθος που δεν βρήκα, δοκίμασε αυτά για τώρα και πες μας αν και πάλι δε λειτουργεί σωστά.
Aristeidis Δημοσ. 7 Μαΐου 2008 Μέλος Δημοσ. 7 Μαΐου 2008 Καταρχάς σε ευχαριστώ πολύ που ασχολήθηκες με το πρόβλημά μου. Επειδή δεν έχουμε κάνει malloc και τα συναφή με τη δυναμική μνήμη, θα ήθελα, αν είναι δυνατόν να μην περιέχονται τέτοιες συναρτήσεις - εντολές. Για το *pos δεν ξέρω πως αλλιώς γίνεται να το κάνω χώρις malloc οπότε το άφησα έτσι (δε μου έβγαλε πρόβλημα, δεν ξέρω τώρα μετά στην εκτέλεση τι θα γίνει). Πρέπει να πειράξω και τα *w1 *w2 στις δηλώσεις;
Aesmade Δημοσ. 7 Μαΐου 2008 Δημοσ. 7 Μαΐου 2008 Πρέπει, αλλιώς δεν θα έχουν μνήμη στην οποία να "δείχνουν". Για να μην μπλέκεις με malloc, κάνε τα declare ως int (όχι pointers) και πέρασε τις διευθύνσεις τους στην check (το ίδιο και με την pos): > check(wmin,wmax,&w1,&w2,r,&pos);
d-l-sama Δημοσ. 8 Μαΐου 2008 Δημοσ. 8 Μαΐου 2008 Καλά πως είναι δυνατόν να μην έχετε κάνει malloc και να σας βάζει τέτοιο πρόβλημα?Με pointers?Σου είπε υποχρεωτικά να βάλεις pointers?
warchief Δημοσ. 8 Μαΐου 2008 Δημοσ. 8 Μαΐου 2008 Η εκφώνηση πάντως δεν έχει τπτ εξωτικό. Μια χαρά γίνεται και χωρίς pointers ρε παιδιά.
Aristeidis Δημοσ. 8 Μαΐου 2008 Μέλος Δημοσ. 8 Μαΐου 2008 Δε μας είπε ότι κάτι είναι υποχρεωτικό. Εξάλλου δεν μπορώ να καταλάβω τη λογική των pointers. Καταλαβαίνω όλα αυτά περί μνήμης και των διευθύνσεων κλπ, αλλά δεν αντιλαμβάνομαι τη χρησιμότητά τους. Πότε τους χρησιμοποιούμε και γιατί.. Ευχαριστώ πολύ για τις απαντήσεις σας!
Aesmade Δημοσ. 8 Μαΐου 2008 Δημοσ. 8 Μαΐου 2008 Η εκφώνηση πάντως δεν έχει τπτ εξωτικό. Μια χαρά γίνεται και χωρίς pointers ρε παιδιά. Καλά πως είναι δυνατόν να μην έχετε κάνει malloc και να σας βάζει τέτοιο πρόβλημα?Με pointers?Σου είπε υποχρεωτικά να βάλεις pointers? Χρειάζονται pointers (ή και references, αν και δεν τις έχω χρησιμοποιήσει και ποτέ και δεν είμαι σίγουρος) αφού η check είναι void, δεν γράφει τα αποτελέσματα και δεν υπάρχουν γενικές μεταβλητές, οπότε μόνο με pointers μπορεί να πάρει η main τα αποτελέσματα ώστε να τα δείξει. Αυτό είναι το μόνο μέρος της λύσης που χρειάζονται pointers. Δε μας είπε ότι κάτι είναι υποχρεωτικό. Εξάλλου δεν μπορώ να καταλάβω τη λογική των pointers. Καταλαβαίνω όλα αυτά περί μνήμης και των διευθύνσεων κλπ, αλλά δεν αντιλαμβάνομαι τη χρησιμότητά τους. Πότε τους χρησιμοποιούμε και γιατί.. Εκτός από την παραπάνω χρήση, μπορούν να χρησιμοποιηθούν για να περάσεις πολλά δεδομένα σε κάποια συνάρτηση μόνο με μια διεύθυνση, στη C αν χρειαστείς μια dynamic array, θα πρέπει να την κάνεις με pointers. Επίσης χρησιμοποιούνται για να διαβάσεις/γράψεις σε κάποιο συγκεκριμένο κομμάτι της μνήμης. Οι συναρτήσεις μάλιστα δεν είναι παρά ένας pointer που "δείχνει" σε μια διεύθυνση όπου υπάρχει ο κώδικας της συνάρτησης. Αν μάθεις assembly, μπορεί να καταλάβεις περισσότερα.
ippo00 Δημοσ. 8 Μαΐου 2008 Δημοσ. 8 Μαΐου 2008 Το θέμα είναι ότι μπορείς να κάνεις increment τον δείκτη σου, αλλά και να τον αλλάξεις. Εκεί είναι το ζουμί. Πώς αλλιώς θα έφτιαχνες ενα string array σε C? Τέλος, καλό θα ήταν να κάνεις declare κάθε μεταβλητή στην αρχή κάθε συνάρτησης (π.χ. κάνεις for (int j=1;j<=n;j++) ενώ θα έπρεπε να έχεις κάνει declare τη j στην αρχή), αφού κάποιοι compilers (όπως ο δικός μου) το παίρνουν ως λάθος. Δεν είναι ακριβώς λάθος, είναι C++ Πάντως άμα είσαι άντρας και τάχεις βαριά η μόνη λύση είναι > int i; i=0+1; boom: code code; code code code; code code; code code code; j+=1; if(j<=n) goto boom;
chris2060 Δημοσ. 8 Μαΐου 2008 Δημοσ. 8 Μαΐου 2008 ξερουμε οτι μια συναρτηση επιστρεφει μια τιμη σωστα? με pointers καταφερνεις και την κανεις να επιστρεφει πολλες τιμες.... χρησιμα τωρα τα pointers???
d-l-sama Δημοσ. 11 Μαΐου 2008 Δημοσ. 11 Μαΐου 2008 Ναι και συν τις αλλης σκέψου ότι αν χρειαζόταν να περάσεις έναν πίνακα 1000000 στοιχείων από 3 συναρτήσεις θα το έκανες το πρόγραμμά σου να γονατίσει!Αλλά άμα περάσεις μόνο την διεύθυνση του πρώτου στοιχείου τηου πίνακα,χρησιμοποιείς μόνο λίγα bytes!Είναι κλάσεις αποδοτικότερο!Και pointers ασφαλώς και χρειάζονται!Αλλά άμα δεν τους έχει διδάξει malloc κτλ και είναι και κανένας στριφνός καθηγητής καλύτερα να το κάνει στατικά!
Προτεινόμενες αναρτήσεις
Αρχειοθετημένο
Αυτό το θέμα έχει αρχειοθετηθεί και είναι κλειστό για περαιτέρω απαντήσεις.