deostry Δημοσ. 31 Δεκεμβρίου 2014 Δημοσ. 31 Δεκεμβρίου 2014 α)Για κάποιο λόγο οταν το τρέχω το προγραμμα δεν μου καλεί την συνάρτηση..ποιό είναι το πρόβλημα;β)πως θα καλέσω την συνάρτηση με την βοήθεια δεικτών;#include <stdio.h> #include <string.h> char pr(char x[80]) { char y[80], *p1, *p2; int i, o,n; n = strlen(x); o = n - 1; for (i = 0; i <n; i++) { p1 = &x; y[o] = *p1; o--; } for (i = 0; i < n; i++) x = y; return (x); } main() { char f[80], x, c[80]; int i, y = 0, n = 0; printf("Grapse mia grammatoseira\n"); gets(f); scanf("%c", &x); n = strlen(f); for (i = 0; i < n; i++) { if (f == x) y++; }; printf("to sumvolo emfanizetai %d fores\n", y); puts(f); c[80]= pr(f); puts© ;}
gon1332 Δημοσ. 31 Δεκεμβρίου 2014 Δημοσ. 31 Δεκεμβρίου 2014 (επεξεργασμένο) #include <stdio.h> #include <string.h> char pr(char x[80]) { char y[80], *p1, *p2; int i, o,n; n = strlen(x); o = n - 1; for (i = 0; i < n; i++) { p1 = &x[i]; y[o] = *p1; o--; } for (i = 0; i < n; i++) x[i] = y[i]; return (x); } main() { char f[80], x, c[80]; int i, y = 0, n = 0; printf("Grapse mia grammatoseira\n"); gets(f); scanf("%c", &x); n = strlen(f); for (i = 0; i < n; i++) { if (f[i] == x) y++; } printf("to sumvolo emfanizetai %d fores\n", y); puts(f); c[80]= pr(f); puts(c); } Αρχικά έχω να κάνω κάποιες vital παρατηρήσεις όσον αφορά τον κώδικα. Αναγνωσιμότητα Το πρώτο βήμα για ένα αναγνώσιμο πρόγραμμα είναι η στοίχιση. Όπως βλέπεις παραπάνω ένα σωστά στοιχισμένο πρόγραμμα, είναι πιο ευχάριστο στο μάτι και αυτό είναι καλό για διάφορους λό- γους. Ένας λόγος είναι ότι θέλεις να ξέρεις πως δουλεύει το πρό- γραμμά σου και μετά από ένα μήνα. Δε θες να κάθεσαι να σπατα- λάς χρόνο διαβάζοντάς το για να καταλάβεις τί στο καλό έκανες τό- τε. Εδώ θα έρθουν να κολλήσουν οι επόμενες παρατηρήσεις που αφορούν την αναγνωσιμότητα. Πρέπει να βάζεις ονόματα τα οποία είναι ευκολοδιάβαστα και να έχουν νόημα. Μονογραμματισμοί, δι- γραμματισμοί και τέτοιου είδους ονοματισμοί προκαλούν μόνο #$#%$%@. Θα βάζεις λέξεις. Τέλος κάνε ορθή χρήση σχολίων (0 && 1 && 2). Τα τρία αυτά άρθρα λένε αρκετά για να ξεκινήσεις. EDIT: Στην αναγνωσιμότητα θα σου πρότεινα (από προσωπικό πόνο) να βάζεις curled braces σε κάθε περίπτωση ακόμη κι αν πρόκειται για μία εντόλη κάτω από την if ή την for. C Κάνουμε compile με τα Warnings ενεργοποιημένα: gcc -g3 -Wall -Wextra -o my_exe my_file.c ~^~~~~~^~~~~~ Η main πλέον επιστρέφει έναν integer οπότε θα την γράφεις έτσι: int main(void) // or int main(int argc, char *argv[]) { // .... return 0; } H gets είναι κακή. Αν δεις εδώ: Never use gets(). Because it is impossible to tell without knowing the data in advance how many characters gets() will read, and because gets() will continue to store characters past the end of the buffer, it is extremely dangerous to use. It has been used to break computer security. Use fgets() instead. Συγκεκριμένα έχει χρήση της για ένα είδος exploitation που ονομάζεται buffer overflow. Μπορείς να δεις εδώ ένα παράδειγμα σε C. Είναι πολύ σημαντικό αυτό το σημείο. Πρέπει να δώσεις βάση όσο είναι νωρίς. Πολλοί μεγαλώνουν, δουλεύουν σε σημαντικές θέσεις και δεν τα προσέχουν αυτά. Πχ πέρυσι ένα παιδάκι hack-αρε καταλάθως το Xbox Online λογαριασμό του πατέρα του κάνοντας buffer overflow. Το πρόγραμμά σου Γρήγορη εξήγηση: Έτσι όπως έχεις γράψει τη συνάρτησή σου, επιστρέφει μία διεύθυνση. Συγκεκριμένα επιστρέφει τη διεύθυνση του πίνακα x. Κάνοντας μετά εσύ αυτό: c[80] = pr(f), πας και αναθέτεις τη διεύθυνση του x στη θέση 80 του πίνακα c. Αν ενεργοποιούσες τα warnings θα το είχες καταλάβει αυτό. Άρα πρέπει να παίξεις εκεί. Προτεινόμενη λύση: void pr(char *dest, char x[80]) { char y[80], *p1, *p2; int i, o,n; n = strlen(x); o = n - 1; for (i = 0; i < n; i++) { p1 = &x[i]; dest[o] = *p1; o--; } } int main(void) { ... if (NULL == (c = malloc(81 * sizeof(char))) { puts("Memory allocation error. Exiting."); exit(EXIT_FAILURE); } pr(c, f); puts(c); return 0; } Να φτιάξεις τη συνάρτησή σου ώστε να παίρνει ένα δείκτη σε μνήμη δεσμευμένη για το αποτέλεσμα και να αναθέτει κατευθείαν σε αυτή. Αν κάνεις τις παραπάνω μετατροπές το πρόγραμμα θα δουλέψει, αλλά θέλει αρκετό patch-άρισμα για να είναι σωστό σύμφωνα με τα κριτήρια που ανέφερα παραπάνω και δη σε αυτό με το buffer overflow. Κάποια στιγμή αργότερα, αν βρω λίγο χρόνο θα σου ανεβάσω και μία δικιά μου ολοκληρωμένη εκδοχή. Επεξ/σία 31 Δεκεμβρίου 2014 από gon1332
gon1332 Δημοσ. 31 Δεκεμβρίου 2014 Δημοσ. 31 Δεκεμβρίου 2014 Ορίστε και μία δική μου εκδοχή. Πολλά σημεία θα μπορούσαν να είναι διαφορετικά, αλλά προσπάθησα να μην μπω στον πει- ρασμό: #include <stdio.h> #include <string.h> #include <stdlib.h> #define MAX_INPUT_LENGTH 80 void string_reverse(char *dst, const char *src) { if (src == NULL) { return; } const char *src_start = src; char *dst_end = dst + strlen(src)-1; while ((*dst_end-- = *src_start++)) { ; } } int main(void) { /* === User input =============================== */ char input[MAX_INPUT_LENGTH+1] = { '\0' }; printf("Please enter a string: "); fgets(input, MAX_INPUT_LENGTH, stdin); // notice that fgets includes '\n' // ΕΔΩ ΠΕΡΙΜΕΝΩ ΤΟΝ MIGF1 ΝΑ ΔΩΣΕΙ ΛΙΓΗ ΧΑΡΑ. ΤΟ ΑΦΗΝΩ ΓΙΑ ΣΕΝΑ. size_t input_length = strlen(input); input[--input_length] = '\0'; // erase '\n' from input string *and* // therefore decrease the string length char char_to_search; printf("Please enter a character to search for: "); scanf("%c", &char_to_search); /* === Search for *char_to_search* in *input* === */ size_t occurrences = 0; for (size_t i = 0; i < input_length; i++) { occurrences += (char_to_search == input[i]); } printf("\nCharacter \'%c\' appears %lu times in \"%s\".\n", char_to_search, occurrences, input); /* === Reverse the input string ================= */ char *reversed_input = malloc((input_length+1) * sizeof(char)); if (NULL == reversed_input) { puts("malloc failed: Aborting execution.\n"); exit(EXIT_FAILURE); } string_reverse(reversed_input, input); printf("\nReversed \"%s\" looks like \"%s\".\n", input, reversed_input); return 0; } Ορίστε κι ένα ενδεικτικό output: Please enter a string: Nipson anomimata mh monan opsin Please enter a character to search for: i Character 'i' appears 3 times in "Nipson anomimata mh monan opsin". Reversed "Nipson anomimata mh monan opsin" looks like "nispo nanom hm atamimona nospiN".
deostry Δημοσ. 31 Δεκεμβρίου 2014 Μέλος Δημοσ. 31 Δεκεμβρίου 2014 Ευχαριστώ..απλά είναι άσκηση για την σχολή και δεν έχουμε μάθει πολύπλοκα οπως αυτα που εχεις κάνει και δεν τα καταλαβαίνω ολα...μεχρι #include stdio Και string εχουμε κάνει..έχω συγκεκριμένες οδηγίες απο την άσκηση..και εχω κολλήσει στο κομμάτι του να καλώ την συνάρτηση με την βοήθεια δεικτών..(η αναστροφη γίνεται όπως θέλει ο καθένας) και έχω θέμα με την εντολη c[80]=pr(f);καμια ιδέα? :/γιατι οταν την συναρτηση την ετρεξα ξεχωριστα σε αλλο προγραμμα (με 1-2 εντολες παραπανω οπως gets) και τη main σε άλλο όλα δούλευαν ρολόι..αλλα όταν τα ένωσα...η συνάρτηση ήταν σαν να μήν υπήρχε
gon1332 Δημοσ. 31 Δεκεμβρίου 2014 Δημοσ. 31 Δεκεμβρίου 2014 Ευχαριστώ..απλά είναι άσκηση για την σχολή και δεν έχουμε μάθει πολύπλοκα οπως αυτα που εχεις κάνει και δεν τα καταλαβαίνω ολα...μεχρι #include stdio Και string εχουμε κάνει..έχω συγκεκριμένες οδηγίες απο την άσκηση..και εχω κολλήσει στο κομμάτι του να καλώ την συνάρτηση με την βοήθεια δεικτών..(η αναστροφη γίνεται όπως θέλει ο καθένας) και έχω θέμα με την εντολη c[80]=pr(f);καμια ιδέα? :/ Αν δεις το την γρήγορη εξήγηση που δίνω καθώς και την προτεινόμενη λύση θα καταλάβεις πως αυτή η εντολή κάνει κάτι εντελώς άσχετο από αυτό που θέλεις να κάνεις. Είναι βασισμένη στο πρόβλημά σου. Έχετε κάνει δυναμική δέσμευση μνήμης;
deostry Δημοσ. 31 Δεκεμβρίου 2014 Μέλος Δημοσ. 31 Δεκεμβρίου 2014 οχι δεν έχουμε κάνει ουτε την εντολη fgets ήξερα απλά πανω στον τροπο που την έχω χτύσει εκτός από την gets τι αλλο έχει λαθος..πως διορθώνω το c[80]=pr(f)
gon1332 Δημοσ. 31 Δεκεμβρίου 2014 Δημοσ. 31 Δεκεμβρίου 2014 Το μόνο που μένει να διορθώσεις τότε είναι η δήλωση του c, η κλήση της συνάρτησης και το signature της συνάρτησης: #include <stdio.h> #include <string.h> char *pr(char x[80]) { char y[80], *p1; int i, o,n; n = strlen(x); o = n - 1; for (i = 0; i < n; i++) { p1 = &x[i]; y[o] = *p1; o--; } for (i = 0; i < n; i++) x[i] = y[i]; return (x); } int main() { char f[80], x, *c; int i, y = 0, n = 0; printf("Grapse mia grammatoseira\n"); gets(f); scanf("%c", &x); n = strlen(f); for (i = 0; i < n; i++) { if (f[i] == x) y++; } printf("to sumvolo emfanizetai %d fores\n", y); puts(f); c = pr(f); puts(c); return 0; }
deostry Δημοσ. 31 Δεκεμβρίου 2014 Μέλος Δημοσ. 31 Δεκεμβρίου 2014 Το μόνο που μένει να διορθώσεις τότε είναι η δήλωση του c, η κλήση της συνάρτησης και το signature της συνάρτησης: #include <stdio.h> #include <string.h> char *pr(char x[80]) { char y[80], *p1; int i, o,n; n = strlen(x); o = n - 1; for (i = 0; i < n; i++) { p1 = &x[i]; y[o] = *p1; o--; } for (i = 0; i < n; i++) x[i] = y[i]; return (x); } int main() { char f[80], x, *c; int i, y = 0, n = 0; printf("Grapse mia grammatoseira\n"); gets(f); scanf("%c", &x); n = strlen(f); for (i = 0; i < n; i++) { if (f[i] == x) y++; } printf("to sumvolo emfanizetai %d fores\n", y); puts(f); c = pr(f); puts(c); return 0; } se xilioeuxaristw file!!! doulevei! :) :)
gon1332 Δημοσ. 31 Δεκεμβρίου 2014 Δημοσ. 31 Δεκεμβρίου 2014 se xilioeuxaristw file!!! doulevei! :) :) Τίποτα. Θα σου πρότεινα όμως να δώσεις προσοχή σε αυτά που σου είπα παραπάνω καθώς είναι πολύ σημαντικά. Καλή πρωτοχρονιά! 1
deostry Δημοσ. 31 Δεκεμβρίου 2014 Μέλος Δημοσ. 31 Δεκεμβρίου 2014 οκ! θα τα ξαναδω αναλυτικά όλα! χρονια πολλα και καλη πρωτοχρονια!
migf1 Δημοσ. 1 Ιανουαρίου 2015 Δημοσ. 1 Ιανουαρίου 2015 Ορίστε και μία δική μου εκδοχή. Πολλά σημεία θα μπορούσαν να είναι διαφορετικά, αλλά προσπάθησα να μην μπω στον πει- ρασμό: #define MAX_INPUT_LENGTH 80 ... int main(void) { /* === User input =============================== */ char input[MAX_INPUT_LENGTH+1] = { '\0' }; printf("Please enter a string: "); fgets(input, MAX_INPUT_LENGTH, stdin); // notice that fgets includes '\n' // ΕΔΩ ΠΕΡΙΜΕΝΩ ΤΟΝ MIGF1 ΝΑ ΔΩΣΕΙ ΛΙΓΗ ΧΑΡΑ. ΤΟ ΑΦΗΝΩ ΓΙΑ ΣΕΝΑ. size_t input_length = strlen(input); input[--input_length] = '\0'; // erase '\n' from input string *and* // therefore decrease the string length ... Χεχε Άντε να μη σου χαλάσω το χατήρι. Έχεις δυο μικρές αβλεψίες στον κώδικα. 1. Κόβεις τον strlen()-1 χαρακτήρα του input, ακόμα κι όταν δεν είναι '\n' (όταν δηλαδή επιχειρηθεί overflow του input στην είσοδο). Δηλαδή, δεν ελέγχεις αν όντως υπάρχει '\n' μέσα στο input πριν το αντικαταστήσεις με '\0'. 2. Στην fgets() κόβεις έναν χαρακτήρα από το full-potential του input string. Η fgets() κόβει έτσι κι αλλιώς έναν χαρακτήρα από το νούμερο που της περνάς ως MAX_INPUT (για να προσθέσει τον '\0' στο τέλος), οπότε στον κώδικά σου θα χρησιμοποιήσει MAX_INPUT-1 χαρακτήρες, ενώ σύμφωνα με τον ορισμό του input που κάνεις, θα μπορούσε να χρησιμοποιήσει MAX_INPUT. Μια καλύτερη υλοποίηση (η χρήση προσωρινού δείκτη δεν είναι απαραίτητη, απλώς βολεύει εμένα καλύτερα): #define MAX_INPUT (80+1) ... char input[MAX_INPUT] = { '\0' }; ... fgets( input, MAX_INPUT, stdin ); char *cp = strchr(input, '\n'); /* returns a pointer to the 1st '\n' found in input */ if ( cp ) { /* or NULL if no '\n' was found */ *cp = '\0'; } ... Το πρόβλημα είναι πως η fgets() διατηρεί το '\n' (δηλαδή το τελικό ENTER που πατάει ο χρήστης στην είσοδο) μέσα στο input (και αμέσως μετά βάζει το '\0'). ΕΚΤΟΣ αν αυτό που πληκτρολογεί ο χρήστης στην είσοδο έχει μήκος (σε χαρακτήρες) μεγαλύτερο από MAX_INPUT-1. Σε αυτή την περίπτωση, η fgets() βάζει μέσα στο input τους πρώτους MAX_INPUT-2 χαρακτήρες από αυτούς που πληκτρολόγησε ο χρήστης, και στη θέση MAX_INPUT-1 βάζει τον '\0'. 2
Προτεινόμενες αναρτήσεις
Δημιουργήστε ένα λογαριασμό ή συνδεθείτε για να σχολιάσετε
Πρέπει να είστε μέλος για να αφήσετε σχόλιο
Δημιουργία λογαριασμού
Εγγραφείτε με νέο λογαριασμό στην κοινότητα μας. Είναι πανεύκολο!
Δημιουργία νέου λογαριασμούΣύνδεση
Έχετε ήδη λογαριασμό; Συνδεθείτε εδώ.
Συνδεθείτε τώρα