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

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

Δημοσ.

Εστω οτι χρειαζομαστε λυση στα παρακατω ζητηματα:

 

Ένα συγκρότημα αιθουσών κινηματογράφου αποτελείται απο 10 συνολικά αίθουσες. Κάθε αίθουσα χαρακτηρίζεται από το όνομά της, 30 το πολύ χαρακτήρων.

Στη main() ενός προγράμματος:

  • Να δηλώσετε ένα πίνακα, τον cinema, για να αποθηκεύσετε τα ονόματα των 10 αιθουσών, τον οποίο να γεμίσετε από το πληκτρολόγιο.

  • Να δηλώσετε ένα πίνακα δύο διαστάσεων ακεραίων 10x12, τον money, στον οποίο θα καταχωρούνται οι εισπράξεις των αιθουσών για κάθε μήνα. Στον πίνακα αυτόν να δώσετε επίσης τιμές από το πληκτρολόγιο.

Να ορίσετε και να καλέσετε μια συνάρτηση, την display(), η οποία θα καλείται μία μόνο φορά από τη main() και θα κάνει τα εξής:

  • Θα αθροίζει τις εισπράξεις κάθε αίθουσας για όλο το χρόνο και θα εμφανίζει στην οθόνη τα ονόματα των αιθουσών, των οποίων οι ετήσιες εισπράξεις υπερβαίνουν τις 5000 ΕΥΡΩ.

  • Θα επιστρέφει το πλήθος των αιθουσών με ετήσιες εισπράξεις άνω των 5000 ΕΥΡΩ.

Η main() να εμφανίζει στην οθόνη το πλήθος των αιθουσών με ετήσιες εισπράξεις άνω των 5000 ΕΥΡΩ (αυτόν που επέστρεψε η συνάρτηση).

 

Προσεγγίζω το προβλημα ως εξής, δεν μου τρεχει γιατι παίρνω segmentation fault, περα οτι υπάρχει σιγουρα λάθος, η προσεγγιση μου ειναι σε καλό δρομο?

 

#include <stdio.h>

#define AITHOUSES 10

int display (int money[][31], int n, char *p );

int display (int money[][31], int n, char *p) {

	int i, j, count = 0, sumi;
	int sum[n];


	for (i = 0; i < n; i++) {
		for (j = 0; j < 12; j++) {
			sum[i] += money[i][j];
		}
	}

	for (sumi = 0; sumi < n; sumi++) {
		if(sum[sumi] > 5000){
			count++;
			printf("o pinakas %s exei esoda panw apo 5000 eyrw\n", *(p + sumi));
		}
	}

	return count;
}


main (void) 
{

	char cinemas[AITHOUSES][31], *p;
	int money[AITHOUSES][12];
	int i, j, x, z, profitables;

	p = &cinemas[0];

	// cinemas
	printf("parakalw pliktrologiste ta onomata twn 10 aithouswn\n");

	for (i = 0; i < AITHOUSES; i++){
		scanf("%s", &cinemas[i]);
	}

	printf("exete pliktrologisei ta eksis onomata\n");
	for (j = 0; j < AITHOUSES; j++){
		puts(cinemas[j]);
	}

	// money
	printf("parakalw eisagete tis eisprakseis kathe aithousas gia olous toys mines\n");

	for (x = 0; x < AITHOUSES; x++){
		for (z = 0; z < 12; z++){
			scanf("%d", &money[x][z]);
		}
	}

	profitables = display(money, AITHOUSES, *p);

	printf("yparxoyn %d aithouses me ethsies eisprakseis anw twn 5000 eyrw\n", profitables);
}

Σας ευχαριστώ για τον χρόνο σας.

Δημοσ.

Καλά το πας.

Έχεις βρει σε ποιο σημείο σκάει το προγραμμά σου ; Τρέξε τον debugger και δες που είναι το πρόβλημα.Αν δεν είσαι εξοικειωμένος με τον debugger,δοκίμασε να βάλεις printf σε διάφορα σημεία του κώδικα και προσπάθησε να βρεις ποιά είναι η τελευταία εντολή που εκτελείται πριν πάρεις segmentation fault

Επίσης ο compiler  λογικά θα σου βγάζει warnings στο σημείο που καλείς την display.Πρόσεξε το τρίτο όρισμα....

Τέλος έχεις ξεχάσει μια μικρή λεπτομέρια στην display( δεν αρχικοποιείς τον πίνακα sum[n] σε μηδέν και υπολογίζεις σκουπίδια  )

  • Like 1
Δημοσ.

Σε ευχαριστω

 

Εχεις δικιο με την αρχικοποιηση του sum[] το εκανα, οπως και στο 3ο arg της display, τωρα περναω δεικτη σε αντικειμενο-δομη και οχι δεικτη σε τιμη του αντικειμενου-δομη (διορθωσε με το γραφω και δεν το πιστευω). Επισης ειχα warning στην αρχικοποιηση του δεικτη p και το εκανα στο σωστο format, απο p = &cinemas[0]; σε p = &cinemas[0][0]; ) χωρις να ειμαι σιγουρος αν αυτο ειχε προεκταση στη λετουργια με τη χρηση δεικτη, αν υπαρχει τετοιο θεμα θα ηθελα μια διευκρινηση.

#include <stdio.h>

#define AITHOUSES 10

int display (int money[][31], int n, char *p );

int display (int money[][31], int n, char *p) {

	int i, j, count = 0, sumi;
	int sum[n];
	sum[0]= 0;


	for (i = 0; i < n; i++) {
		for (j = 0; j < 12; j++) {
			sum[i] += money[i][j];
		}
	}

	for (sumi = 0; sumi < n; sumi++){
		if(sum[sumi] > 5000){
			count++;
			printf("h aithousa %s exei esoda panw apo 5000 eyrw\n", p + sumi);
		}
	}

	return count;
}


main (void) 
{

	char cinemas[AITHOUSES][31], *p;
	int money[AITHOUSES][12];
	int i, j, x, z, profitables;

	p = &cinemas[0][0];

	// cinemas
	printf("parakalw pliktrologiste ta onomata twn 10 aithouswn\n");

	for (i = 0; i < AITHOUSES; i++){
		scanf("%s", cinemas[i]);
	}

	printf("exete pliktrologisei ta eksis onomata\n");
	for (j = 0; j < AITHOUSES; j++){
		puts(cinemas[j]);
	}

	// money
	printf("parakalw eisagete tis eisprakseis kathe aithousas gia olous toys mines\n");

	for (x = 0; x < AITHOUSES; x++){
		for (z = 0; z < 12; z++){
			scanf("%d", &money[x][z]);
		}
	}

	profitables = display(money, AITHOUSES, p);

	printf("yparxoyn %d aithouses me ethsies eisprakseis anw twn 5000 eyrw\n", profitables);
}

To segmentation fault παρουσιαζοταν στην prinf εντος της display στο 2ο for loop, του περιμενε string και του εδινα χαρακτηρα, οποτε το *(p + numi) εγινε p + numi, αν το segmentation fault συμβαινει οταν προσπαθουμε να προσπελασουμε διευθυνσεις μνημης και δεν εχουμε μεριμνησει να προυποθετει σωστο format μαλλον εκει πρεπει να γινεται. Αλλα δεν το εχω συνηδητοποιησει 100% οποτε κρατω μικρο καλάθι.

Δυστυχως με τρομαζει προς το παρων ο debuger, πολυ πληροφορια που δεν μπορω να διαχειριστω ακομη, και το πηγα με τα warnings και ψαχνοντας τα στο internet.

 

Κατάφερε να τρεξει το προγραμμα επιτυχως αλλα με ενα οχι critical λαθος (τρεχει δηλαδη) απλα οταν βρισκει πάνω απο 1 αιθουσα με εισπραξεις πάνω απο 5000 ευρω δεν κανει print το ονομα της, ενω γινεται στο πρωτο, πιθανοτατα η scanf να μην κανει δουλεια (πιθανον καπου εχω κανει λαθος στη καταχωρηση με καποιο white space ισως), αλλα δεν ειμαι σιγουρος.

 

Το οutput του compiler:
 

christos@laptop ~/Workspace/diavasma $ gcc -o ian10pin ian10pin.c
ian10pin.c: In function ‘main’:
ian10pin.c:61:2: warning: passing argument 1 of ‘display’ from incompatible pointer type [enabled by default]
ian10pin.c:7:5: note: expected ‘int (*)[31]’ but argument is of type ‘int (*)[12]’

Δεν εχω καταλαβει πως θα επρεπε να γινει στο 61:2, επίσης κ στο 7:5 τι λάθος κάνω;

 

 

Το προγραμμα τρεχει:
 

parakalw pliktrologiste ta onomata twn 10 aithouswn
ena      
dyo
tria
....
....
deka
exete pliktrologisei ta eksis onomata
ena
dyo
tria
...
...
deka
parakalw eisagete tis eisprakseis kathe aithousas gia olous toys mines
123
500
...
...
h aithousa ena exei esoda panw apo 5000 eyrw
h aithousa  exei esoda panw apo 5000 eyrw 
yparxoyn 2 aithouses me ethsies eisprakseis anw twn 5000 eyrw

στη προτελευταια γραμμη ειναι το λαθακι που ανεφερα, δεν κανει print το ονομα της αιθουσας για αριθμο αιθουσων με εισπραξεις ανω των 5000 ευρω να ειναι μεγαλυτερο του ενος.

Δημοσ.

 

int display (int money[][31], int n, char *p );

main (void)
{
int money[AITHOUSES][12];
profitables = display(money, AITHOUSES, p);
}

Το οutput του compiler:

 

christos@laptop ~/Workspace/diavasma $ gcc -o ian10pin ian10pin.c
ian10pin.c: In function ‘main’:
ian10pin.c:61:2: warning: passing argument 1 of ‘display’ from incompatible pointer type [enabled by default]
ian10pin.c:7:5: note: expected ‘int (*)[31]’ but argument is of type ‘int (*)[12]’
Δεν εχω καταλαβει πως θα επρεπε να γινει στο 61:2, επίσης κ στο 7:5 τι λάθος κάνω;

 

Το πρόβλημα είναι ακριβώς αυτό που σου λέει ο compiler δηλαδή λάθος βιασύνης. Θέλεις να περάσεις τον πίνακα money στην display. Ο πίνακας money έχει 12 μήνες για κάθε αίθουσα. Ωραία ως εδώ. Στη δήλωση της συνάρτησης τι πίνακα είπες ότι θέλεις να περνάς ?

 

Τις άλλες ερωτήσεις δεν τις είδα γιατί βιάζομαι. Αν δεν απαντήσει ο Chris ή κάποιος άλλος θα σου απαντήσω αργότερα.

  • Like 1
Δημοσ.

Όπως λέει και ο imitheos πιο πάνω,  μες τη βιασύνη σου κάνεις  ένα λαθάκι στον πίνακα money.Ο ορισμός της display λέει οτι το πρώτο όρισμα είναι ένας πίνακας ακεραίων και η δεύτερη διάσταση του έχει μέγεθος 31.Ο πίνακας money όμως που ορίζεις στην main έχει μέγεθος 12 στη δεύτερη διάσταση...

Segfault παίρνεις όταν "ακουμπάς" μνήμη που δεν είναι δικιά σου , δηλαδή δεν έχεις ζητήσει από το σύστημα να τη δεσμεύσει για σένα.Στον προηγούμενο κώδικα που ανέβασες,χρησιμοποιούσες στην printf της display την τιμή που έδειχνε ο p για να κάνεις προσπέλαση.Φυσικά ο p έδειχνε στο γάμο του καραγκιόζη και έτσι έσκαγε το πρόγραμμα.

Τώρα στην printf περνάς σαν όρισμα τη διεύθυνση του πρώτου χαρακτήρα του πίνακα  cinemas. Το p + sumi δεν θα σε πάει -sumi- strings πιο κάτω,αλλά -sumi- χαρακτήρες από εκει που δείχνει ο p.Γιατί δεν περνάς ολόκληρο τον πίνακα cinemas στην display ( όπως κάνεις και με τον money ) και να έχεις το κεφάλι σου ήσυχο ; :)

Αυτό με το sum[n] όμως δεν το διόρθωσες.Έκανες αρχικοποιήση σε μηδέν μόνο στο sum[0].Τα υπόλοιπα n-1 στοιχεία του sum έχουν ακομα σκουπίδια

  • Like 1
Δημοσ.

Το πρόβλημα είναι ακριβώς αυτό που σου λέει ο compiler δηλαδή λάθος βιασύνης. Θέλεις να περάσεις τον πίνακα money στην display. Ο πίνακας money έχει 12 μήνες για κάθε αίθουσα. Ωραία ως εδώ. Στη δήλωση της συνάρτησης τι πίνακα είπες ότι θέλεις να περνάς ?

 

Εχετε δικιο, υπαρχει παραδοξο στη λογικη εδω. το διορθωσα και δεν επιστρεφει warning

 

Τώρα στην printf περνάς σαν όρισμα τη διεύθυνση του πρώτου χαρακτήρα του πίνακα  cinemas. Το p + sumi δεν θα σε πάει -sumi- strings πιο κάτω,αλλά -sumi- χαρακτήρες από εκει που δείχνει ο p.Γιατί δεν περνάς ολόκληρο τον πίνακα cinemas στην display ( όπως κάνεις και με τον money ) και να έχεις το κεφάλι σου ήσυχο ;

 

 

Εδω φαινεται οτι δεν κατεχω τη λειτουργια των δεικτων, σε ευχαριστω για την παρατηρηση. Πρωτου ομως αποδεχτω τη προταση, θα ηθελα να χρησιμοποιήσω τον δεικτη p, αρχικοποιώντας τον ως p = &cinemas[0];

 

Εδω ο p δειχνει την διευθυνση του δισδιαστατου πινακα cinemas, ο οποιος ειναι και δεικτης σε πινακα της πρωτης γραμμης η οποια ειναι συμβολοσειρα (ετσι το καταλαβαινω) πιθανον να κανω λαθος, οπως και να έχει πως θα γινοταν να χρησιμοποιήσω τον δεικτη p αντι τον πινακα (ο οποιος ειναι δεικτης και παλι);

 

Πως θα γινοταν να αντιστοιχισω την sumi με γραμμη του δισδιαστατου πινακα cinemas ετσι ωστε να με κατεβαζει γραμμη και να μπορει να διαβαστει η συμβολοσειρα;

 

Αυτό με το sum[n] όμως δεν το διόρθωσες.Έκανες αρχικοποιήση σε μηδέν μόνο στο sum[0].Τα υπόλοιπα n-1 στοιχεία του sum έχουν ακομα σκουπίδια

 

Αυτο ειναι κάτι που με διαφευγει, ειχα την εντυπωση οτι θα γινει overwrite με την ακολουθια τελεστων += σε καθε του θεση

Δημοσ.

Αυτό με το sum[n] όμως δεν το διόρθωσες.Έκανες αρχικοποιήση σε μηδέν μόνο στο sum[0].Τα υπόλοιπα n-1 στοιχεία του sum έχουν ακομα σκουπίδια

Εφόσον έχεις ένα βρόχο που προσθέτει κάθε φορά τα χρήματα, θα πρέπει οι μεταβλητές να αρχικοποιούνται σε 0. Όπως είπε ο Chris6, εσύ έθεσες 0 μόνο στο sum[0] και όχι σε όλα τα στοιχεία. Αν δεν έχετε μάθει ακόμη το ιδίωμα { 0 } το οποίο θα σου θέσει 0 σε όλα τα στοιχεία, μπορείς να τα αρχικοποιήσεις με βρόχο. Εφόσον έχεις ήδη το βρόχο που υπολογίζει τα αθροίσματα, μπορείς εννοείται να βάλεις εκεί την αρχικοποίηση.

 

 

Τώρα στην printf περνάς σαν όρισμα τη διεύθυνση του πρώτου χαρακτήρα του πίνακα  cinemas. Το p + sumi δεν θα σε πάει -sumi- strings πιο κάτω,αλλά -sumi- χαρακτήρες από εκει που δείχνει ο p.Γιατί δεν περνάς ολόκληρο τον πίνακα cinemas στην display ( όπως κάνεις και με τον money ) και να έχεις το κεφάλι σου ήσυχο ; :)

Εδω φαινεται οτι δεν κατεχω τη λειτουργια των δεικτων, σε ευχαριστω για την παρατηρηση. Πρωτου ομως αποδεχτω τη προταση, θα ηθελα να χρησιμοποιήσω τον δεικτη p, αρχικοποιώντας τον ως p = &cinemas[0];

Στα 10 άτομα τα 9 μπερδεύουν τους πίνακες και τους δείκτες οπότε μην αγχώνεσαι :) Δήλωσες ένα δείκτη σε χαρακτήρα και του έδωσες την διεύθυνση του πρώτου γράμματος της 1ης αίθουσας. Όταν μετά σε αυτό προσθέτεις τον αριθμό sumi, τότε μετακινείσαι κατά τόσους χαρακτήρες όπως σου είπε ο Chris6 αντί να πας στην sumi-οστή αίθουσα. Για να γίνει αυτό μπορείς να κάνεις διάφορες δηλώσεις ανάλογα με αυτό που θέλεις. Ένας τρόπος είναι αυτός που είπε ο Chris6 να περάσεις ολόκληρο τον πίνακα. Άλλος τρόπος είναι να ορίσεις στην main τον p ως δείκτη σε πίνακα 31 χαρακτήρων (*p)[31] και μετά να τον περάσεις στην συνάρτηση και να τον αυξάνεις κανονικά.

 

Εδω ο p δειχνει την διευθυνση του δισδιαστατου πινακα cinemas, ο οποιος ειναι και δεικτης σε πινακα της πρωτης γραμμης η οποια ειναι συμβολοσειρα (ετσι το καταλαβαινω) πιθανον να κανω λαθος, οπως και να έχει πως θα γινοταν να χρησιμοποιήσω τον δεικτη p αντι τον πινακα (ο οποιος ειναι δεικτης και παλι);

 

Πως θα γινοταν να αντιστοιχισω την sumi με γραμμη του δισδιαστατου πινακα cinemas ετσι ωστε να με κατεβαζει γραμμη και να μπορει να διαβαστει η συμβολοσειρα;

 

Αυτο ειναι κάτι που με διαφευγει, ειχα την εντυπωση οτι θα γινει overwrite με την ακολουθια τελεστων += σε καθε του θεση

Μπερδεύεσαι γιατί σκέφτεσαι δισδιάστατος συμβολοσειρά και τέτοια. Δεν σε ενδιαφέρουν αυτά. Όρισες τον p ως δείκτη σε χαρακτήρα οπότε κάθε αύξηση του μετακινεί τον p κατά ένα χαρακτήρα. Το cinemas[0][0] του οποίου την διεύθυνση έδωσες στον p είναι ένας χαρακτήρας. Το αν τώρα το cinemas[0] είναι συμβολοσειρά ή το cinemas είναι δισδιάστατος πίνακας δεν τον νοιάζει τον p.

 

Αν θέλεις κάθε αύξηση του p να μετακινεί κατά 31 bytes τότε θα πρέπει να μην τον ορίσεις ως δείκτη σε χαρακτήρα αλλά ως δείκτη σε κάτι που καταλαμβάνει 31 bytes.

 

int display (int money[][12], int n, char cinemas[][31])

Στη main:
profitables = display(money, AITHOUSES, cinemas);
Όπως ορίζεις στην συνάρτηση τον money, έτσι ορίζεις κανονικά και τον cinemas. Στην main περνάς κανονικά όλον τον πίνακα και στην display τον χρησιμοποιείς ως cinemas[sumi].

 

 

int display (int money[][12], int n, char p[][31])

Στη main:
char (*p)[31];
p = &cinemas[0]; (ή σκέτο cinemas)
profitables = display(money, AITHOUSES, p);
Αν θέλεις οπωσδήποτε να ορίσεις ένα νέο δείκτη p, τότε μπορεί να γίνει όπως φαίνεται παραπάνω. Ο p ορίζεται ως δείκτης σε πίνακες 31 χαρακτήρων ώστε να αυξάνεται όπως θέλεις και τον βάζουμε να δείχνει στο όνομα της 1ης αίθουσας. Μετά μπαίνει κανονικά όρισμα στην συνάρτηση όπως τον είχες και τον χρησιμοποιείς είτε πάλι ως p[sumi] είτε ως *(p + sumi).
  • Like 1
Δημοσ.

Σας ευχαριστώ για το χρονο σας, εμαθα σημαντικα πραγματα μεσα απο τη συζητηση αυτη, θα ενημερώσω συντομα το thread με καινουργια πραγματα, την επομένη θα γραψω για λίστες.

 

Να στε καλα.

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

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

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

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

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

Σύνδεση

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

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