Keydo Δημοσ. 1 Ιουνίου 2007 Δημοσ. 1 Ιουνίου 2007 >Random_Keys = (char*)malloc(Encryption_Strength*sizeof(char)); while (strcmp(Key_Acception, "No") == 0) { for (i = 0 ; i < Encryption_Strength ; i++){ temp = (rand()%36); Random_Keys[i] = Keys[temp]; } printf("Key: %s will be used for the encryption\n", Random_Keys); printf("Do you want to keep it?\n"); printf("Yes/No: "); fgets(Key_Acception, 4, stdin); } Δουλεύει κανονικά το while-loop αλλά συμπεριφέρεται σαν να μην βλέπει την fgets(). Όλες οι παραπάνω εντολές δουλεύουνε κανονικότατα, αλλά με το που φτάνει στο fgets() βγαίνει από το loop χωρίς να περιμένει κάποιο input από τον χρήστη. Αν σβήσω την fgets() το loop επαναλαμβάνεται χωρίς να σταματάει. Καμιά ιδέα για το τι φταίει? :roll:
parsifal Δημοσ. 1 Ιουνίου 2007 Δημοσ. 1 Ιουνίου 2007 Πριν από αυτό το τμήμα κώδικα, εκτελείται μήπως καμμία scanf/fscanf...;
Keydo Δημοσ. 1 Ιουνίου 2007 Μέλος Δημοσ. 1 Ιουνίου 2007 Υπάρχει fgets() και πιο πάνω αλλά ότι input δίνω από το πληκτρολόγιο το αποθηκεύει, μέχρι και το \n πιάνει.
gilmour Δημοσ. 1 Ιουνίου 2007 Δημοσ. 1 Ιουνίου 2007 δοκίμασε πριν την fgets να κάνεις fflush το stdin......fflush(stdin)
Keydo Δημοσ. 1 Ιουνίου 2007 Μέλος Δημοσ. 1 Ιουνίου 2007 δοκίμασε πριν την fgets να κάνεις fflush το stdin......fflush(stdin) Τώρα δουλεύει αλλά την πρώτη φορά κάνει 2 επαναλήψεις χωρίς να πάρει input από το πληκτρολόγιο. Μετά όμως κανονικά.. :???:
gilmour Δημοσ. 2 Ιουνίου 2007 Δημοσ. 2 Ιουνίου 2007 αν θες, και μπορεις, δωσε μας τον κωδικα πριν απο το σημείο αυτό.... Η ιδεα του fflush ειναι οτι καθαρίζει τον buffer του stdin... Γιατι όμως χρησιμοποιείς την fgets για να πάρεις είσοδο απο το πληκτρολόγιο;
Keydo Δημοσ. 2 Ιουνίου 2007 Μέλος Δημοσ. 2 Ιουνίου 2007 αν θες, και μπορεις, δωσε μας τον κωδικα πριν απο το σημείο αυτό....Η ιδεα του fflush ειναι οτι καθαρίζει τον buffer του stdin... Γιατι όμως χρησιμοποιείς την fgets για να πάρεις είσοδο απο το πληκτρολόγιο; Θέλω να πάρω ολόκληρο string ως είσοδο που πιθανώς να έχει κενά. Η gets() μπορεί να δημιουργήσει overrun του buffer, η scanf() δεν διαβάζει κενά, οπότε η μόνη λύση είναι η fgets() (ή κάποια άλλη εντολή που δεν ξέρω ). Σκοπός του προγράμματος είναι να κωδικοποιήσει ένα αρχείο που θα του δωθεί, αλλά μέχρι στιγμής ότι έχω κάνει αφορά φρου-φρου κι αρώματα και όχι κάτι επί της ουσίας μιας και σκανάρει το αρχείο & δημιουργεί το κλειδί που θα χρησιμοποιηθεί για την κωδικοποίηση. Ο κώδικας μπορεί να κατέβει από εδώ για όσους ενδιαφέρεστε.
dealer Δημοσ. 3 Ιουνίου 2007 Δημοσ. 3 Ιουνίου 2007 παλεψα λιγο με τον κωδικα αλλα δεν καταφερα να το λυσω,μου αγνοουσε ακομα κ δοκιμαστικα printf που εβαζα.Πολυ σπαστικο,κ γω την ειχα παθει ετσι μια φορα,δεν υπολογιζε το scanf("%c",&a) αλλα το scanf("%1s",&a)...ειναι για τον πο*τσο μερικες φορες...
Directx Δημοσ. 3 Ιουνίου 2007 Δημοσ. 3 Ιουνίου 2007 Μια εναλλακτική λύση της fgets είναι η scanf(“%10s”,string); όπου ζητούμε από την scanf να περιορίσει το μέγεθος των εισαχθέντων στοιχείων ως τους 9 πρώτους χαρακτήρες της εισόδου. Βέβαια αν μας ενδιαφέρει το formation του προγράμματος τότε η scanf από όσο γνωρίζω δεν βοηθά ιδιαίτερα καθώς αγνοεί «επιδεικτικά» περιπτώσεις κενής εισόδου (πχ. Enter δίχως είσοδο άλλων χαρακτήρων). Εάν η scanf διαγνώσει λανθασμένη μορφή εισόδου (πχ. κείμενο αντί αριθμού) επιστρέφει 0 τόσες φορές όσες και οι λανθασμένες τιμές εισόδου μας (για αυτό άμα επιστρέψει 0 κάνουμε ένα fflush ώστε να ξεμπερδέψουμε από όλο το περιεχόμενο του STDIN μας). Από εκεί και πέρα, ο κώδικας σου σε γενικές γραμμές δουλεύει καλά, με την σημείωση όμως πως α) έχεις ορισμένα λάθει όσον αφορά την δήλωση στο μέγεθος των μεταβλητών τύπου char τόσο των σταθερών (Keys – είναι 37 αντί 36) όσο και των δυναμικά δεσμευμένων (Random_Keys – δέσμευσε +1 χαρακτήρα και φρόντισε να καθαρίσεις να το καθαρίσεις ώστε να είναι \0-Termineted όπως θέλει η C τα String της), β) χρειάζεται μια αναδιάρθρωση στα σημεία που περιμένεις και ελέγχεις την είσοδο του χειριστή ώστε να μην χρειάζεται να δηλώνεις δυο φορές το prompt εισόδου σου (πχ. «Enter the file you want to be encrypted:») και γ) μπορεί εύκολα να ελέγξεις για το “no” ανεξάρτητα του τρόπου γραφής του (κεφαλαία ή μικρά κτλ) με την stricmp, ενώ για να αφαιρέσεις το \n της fgets μπορείς απλά να διαγράψεις με \0 το προ-τελευταίο χαρακτήρα του string). Καλή συνέχεια. Ο κώδικας δοκιμάστηκε σε CodeGear C/C++ Builder 6.0 (MS-Windows) (όπου for(; να θυμάσαι πως ισούται με while(1)). > //Made by Kid //kid.blogotropia.gr //[email protected] #include <stdio.h> #include <stdlib.h> #include <string.h> #include <time.h> int main(){ // Variables char Filename[256]="a", Buffer[256]; // Directx: Set from 36 to 37 char Keys[37]="abcdefghijklmnopqrstuvwxyz0123456789"; char *Random_Keys = NULL; // Directx: Always set free * to NULL int Encryption_Strength = 5; int i, x, y, temp; FILE *fopen(), *Source_File; srand((unsigned int)time((time_t *)NULL)); // Options printf("In order to encrypt a file, it must be \n"); printf("in the same folder with the executable file.\n"); printf("Dictionary: %s", Keys); printf("\n"); // File Scanning for(; // directx { printf("Enter the file you want to be encrypted:"); scanf("%255s",Filename); if((Source_File = fopen(Filename, "r"))!=NULL) break; printf("%s: File does not exist.\n", Filename); } // Encryption Strength printf("\n"); printf("How strong encryption do you want to use?\n"); printf("(Value must be between 1 and 10, default is 5)\n"); printf("(10 is the strongest possible encryption)\n"); printf("If you don't want to change that, enter 0\n"); for(; // directx { printf("Value:"); if(!scanf("%d", &Encryption_Strength)) { fflush(stdin); // Ignore rest of possible bad input chars of STDIN Encryption_Strength = -1; } if(Encryption_Strength < 0 || Encryption_Strength > 10) printf("Value must be between 1 and 10.\n"); else break; } if (Encryption_Strength == 0) Encryption_Strength = 5; // Key Randomizer // directx: +1 one byte to reserved \0 (C NULL-Terminator) Random_Keys = (char*)malloc((Encryption_Strength*sizeof(char))+1); // directx: Set entire buffer to \0 (safeguard of rest C functions) memset(Random_Keys,0,(Encryption_Strength*sizeof(char))+1); do // directx { for (i = 0 ; i < Encryption_Strength ; i++) { temp = (rand()%36); Random_Keys[i] = Keys[temp]; } printf("Key: %s will be used for the encryption.\n", Random_Keys); printf("If you want to use it, press any key, otherwise type No:"); fflush(stdin); fgets(Buffer, 256, stdin); Buffer[strlen(Buffer)-1] = '\0'; }while(!stricmp(Buffer,"no")); printf(" ... Encrypting ...\n"); // directx: Free program resources fclose(Source_File); free(Random_Keys); return 0; }
Keydo Δημοσ. 3 Ιουνίου 2007 Μέλος Δημοσ. 3 Ιουνίου 2007 Κάνοντας c/p το πρόγραμμα με τις διορθώσεις του DirectX έκανε πάλι το ίδιο, προσπέρασε το fgets() μέσα στην while. Μήπως είναι θέμα compiler? gcc χρησιμοποιώ.. :roll:
Directx Δημοσ. 3 Ιουνίου 2007 Δημοσ. 3 Ιουνίου 2007 Ενδεχομένως διότι δοκίμασα τον κώδικα σε: α) CodeGear C/C++ Builder 6.0 -είναι compiler του 2002 για MS-Windows. β) CodeGear Turbo C++ Explorer -είναι compiler του 2006 για MS-Windows. γ) Borland Turbo C++ 3.0 -είναι compiler του 1991 για MS-DOS. δ) Microsoft-C 6.0 -είναι compiler του 1990 για MS-DOS (!) Και στους 4 Compiler ο κώδικας δουλεύει κανονικά.. - Και μια μικρή διόρθωση ώστε να είμαστε 100% ANSI-C συμβατοί: Ψάχνοντας το θέμα περισσότερο παρατηρώ πως η εντολή stricmp θεωρείται από πολλούς ως μη ANSI-C συμβατή - από την άλλη πλευρά για άλλους ορίζεται ως ANSI-C συμβατή (μπάχαλο δηλαδή). Σε αυτή την περίπτωση, μιας και δουλεύεις με τον GCC για κάθε ενδεχόμενο καλού - κακού προτίμησε την παρακάτω αλλαγή (η strlwr μετατρέπει το Buffer σε μικρά γράμματα & ελέγχει με την strcmp για "no"): > do { for (i = 0 ; i < Encryption_Strength ; i++) { temp = (rand()%36); Random_Keys[i] = Keys[temp]; } printf("Key: %s will be used for the encryption.\n", Random_Keys); printf("If you want to use it, press any key, otherwise type No:"); fflush(stdin); fgets(Buffer, 256, stdin); Buffer[strlen(Buffer)-1] = '\0'; strlwr(Buffer); }while(!strcmp(Buffer,"no")); Τώρα όσον αφορά το fgets πιστεύω ότι κάτι συμβαίνει με το GCC και το STDIN (φαίνεται πως παρ' όλο το fflush -ορισμένοι θεωρούν παράνομο να γίνεται σε STDIN έτσι και αλλιώς..- μένει κάποιο \r\n escape-sequency μάλλον..) όμως δεν δουλεύω με Unix/Linux και δεν μπορώ να σε βοηθήσω περαιτέρω
Keydo Δημοσ. 3 Ιουνίου 2007 Μέλος Δημοσ. 3 Ιουνίου 2007 Σε gcc δεν μου αναγνώρισε την stricmp αλλά θεώρησα ότι ήταν απλά κάποιο typo και έσβησα το i. Η strlwr επίσης δεν αναγνωρίστηκε. Όπως θα πρόσεξες, οι βιβλιοθήκες που έχω ορίσει είναι οι stdio/stdlib/time/string, μήπως πρέπει να προσθέσω κάποια ακόμα? Κατά τα άλλα, τα ίδια, ουδεμία αλλαγή, συνεχίζει να βγαίνει από το while-loop.
Directx Δημοσ. 3 Ιουνίου 2007 Δημοσ. 3 Ιουνίου 2007 Φίλε μου, από ότι βλέπω στον κόσμο του Unix ούτε η strlwr υπάρχει στην string.h -αν και μέχρι σήμερα όλοι οι compiler μου (στα documentation τους) την έδιναν και αυτή ως ANSI-C .. θα ξεχάσω και αυτά που ξέρω.. Δεν έχει νόημα να σε ταλαιπωρώ περισσότερο - δεν δουλεύω τον GCC (όπως είδες δουλεύω χρόνια σε DOS/Windows platforms) και από ότι βλέπω ο κόσμος του είναι πολύ διαφορετικός από τους δικούς μου compiler για να μην πω από την δικιά μου C Ελπίζω όσοι τον δουλεύουν να σε βοηθήσουν.. άλλωστε το πρόβλημα της fgets που είναι το βασικό σου όπως είπα μάλλον σχετίζεται με την διαχείριση console stdin του Linux σου.. Αν κάποια στιγμή γυρίσεις σε DOS/Windows ο κώδικας δουλεύει με αυτούς τους compiler που σου έγραψα.. Καλή τύχη!
alkisg Δημοσ. 4 Ιουνίου 2007 Δημοσ. 4 Ιουνίου 2007 Στο αρχικό πρόβλημα: > scanf("%d", &Encryption_Strength); Η scanf σταματάει με το που βλέπει το enter μετά τον αριθμό. Η επόμενη fgets, > fgets(Key_Acception, 4, stdin); διαβάζει απλά το enter και γι' αυτό σου φαίνεται σαν να μην εκτελείται. Επομένως πρέπει πριν από την fgets να βάλεις το enter από το input buffer. Το fflush(stdin) δουλεύει μερικές φορές, αλλά το πρότυπο της C προτείνει ξεκάθαρα να μην χρησιμοποιείται. Εναλλακτικές: > scanf("%d ", &Encryption_Strength); Έχει ένα κενό μετά το %d και λέει στην scanf να προσπεράσει το enter. > while (!feof(stdin)) getchar(); Αδειάζεις τον input buffer με compliant τρόπο.
Προτεινόμενες αναρτήσεις
Αρχειοθετημένο
Αυτό το θέμα έχει αρχειοθετηθεί και είναι κλειστό για περαιτέρω απαντήσεις.