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

Προβλημα με συναρτηση gets στην γλωσσα C


I@n15

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

Δημοσ.

Γεια και χαρα σε ολους τους φιλους,λοιπον αντιμετωπιζω ενα μικρο προβλημα με την συναρτηση gets και θα θελα την γνωμη σας.

Το ζητουμενο εχεις ως εξης:

 

α)Ο χρηστης πρεπει να δωσει το ονομα και το επιθετο

β) μετα την ηλικια

γ)και μετα απλα τα επιστρεφει στην main

 

>
[color="DarkGreen"]#include [/color][color="Orange"]<stdio.h>[/color]
[color="DarkGreen"]#include[/color] [color="Orange"]<stdlib.h>[/color]


[color="Blue"]struct [/color]num{
   
     [color="Blue"] char [/color]age[20];
      [color="Blue"]char [/color]name[20];
};


//Sinartisi pou epistrefei to onoma kai tin ilikia 

[color="Blue"]struct[/color] num *readData([color="Blue"]struct [/color]num *p)   
{
   [color="Blue"]int[/color] i;
   p = malloc(3 * [color="Blue"]sizeof[/color]([color="Blue"]struct[/color] num)); 
   
   [color="Blue"]if[/color](p != [color="DarkGreen"]NULL[/color])
   {
      [color="Blue"]for[/color](i = 0; i <= 2; i++)
      {
          printf("[color="Orange"]dose tin ilikia gia to %io atomo[/color]:\n",i+1);
          scanf("[color="DarkOrange"]%s[/color]",(p+i)->age);
       
          printf("[color="Orange"]dose to onoma gia to %io atomo:[/color]\n",i+1);
          scanf("[color="Orange"]%s[/color]",(p+i)->name);
      }
   }


[color="Blue"]else[/color]
   {
       printf("[color="Orange"]Memory not available\n[/color]");
   }
   
   [color="Blue"]return[/color] p;
}

/*---------------------------------------------------------------------------*/


[color="Blue"]int[/color] main()
{   
   [color="Blue"]struct[/color] num *ptr;
   [color="Blue"]int[/color] i;
   [color="Blue"]int[/color] r[3];
  

   ptr = readData(ptr);
   
   [color="Blue"] for[/color](i = 0; i <= 2; i++)
    {
       r[i] = atoi((ptr+i)->age);
    }
     

   [color="Blue"]for[/color](i = 0; i <= 2; i++)
   {
       printf("[color="Orange"]%s %i\[/color]n",(ptr+i)->name,r[i]);
   }
   
}

 

Eτσι οπως ειναι το προγραμμα με την χρηση της scanf τρεχει μια χαρα αλλα επειδη σαν εισοδο θα πρεπει να δωσω και ονομα και επιθετο αναγκαστικα θα πρεπει να χρησιμοποιησω την gets η οποια ομως δεν μου δουλευει.Καμια ιδεα καποιος?

Δημοσ.

Όπως λέει και το wikiepedia:

 

Use of gets is strongly discouraged. It is left in the C89 and C99 standards for backward compatibility. Many development tools such as GNU ld emit warnings when code using gets is linked.

Δημοσ.

Απ οτι βλεπω την συναρτηση gets ολοι την χαρακτηριζουν επικυνδυνη αρα αναγκαστικα θα χρησιμοποιησω 2 πινακεσ,εναν για το ονομα και εναν για το επιθετο

Δημοσ.

Μπορεί αντί της gets μπορείς να δεις την fgets η οποία σου επιτρέπει να ορίσεις το μέγεθος του input buffer:

 

>
fgets((p+i)->name, sizeof((p+i)->name), stdin);

 

Επίσης μπορείς να δοκιμάσεις και την scanf με ένα τρικ που της επιτρέπει να δέχεται strings καθορισμένου μεγέθους και με κενά (αρκεί να το υποστηρίζει ο compiler σου ..):

 

>
scanf("%15[^\n]s",(p+i)->age);

 

Εδώ το 15 (για παράδειγμα) εξηγεί στην scanf ότι δεν θα πρέπει να αποθηκεύσει πάνω από 15 χαρακτήρες ενώ το [^\n] ότι θα πρέπει να δέχεται όλους τους χαρακτήρες μέχρι να συναντήσει \n (δηλαδή ας πούμε Enter).

 

Υ.Γ.

Και οι δυο ρουτίνες έχουν προβληματική συμπεριφορά σε περιπτώσεις overflow αφού ναι μεν δεν παραβιάζουν τον buffer (δεν κάνουν buffer overflow) αλλά οι έξτρα χαρακτήρες γεμίζουν το stdin buffer και δημιουργούν προβλήματα (flush κτλ), οπότε αντί για 20 βάλε μια μεγαλύτερη τιμή (πχ. η BUFSIZ του stdio.h είναι μια πολύ μεγάλη τιμή που σε εξασφαλίζει συνήθως από buffer overflow μέσο console input).

Δημοσ.

Ειλικρινά, ελπίζω να σου φανούν χρήσιμα! :-)

 

Μόνο μια μικρή λεπτομέρεια που αμέλησαν να αναφέρω σχετικά με την fgets. Να έχεις υπόψη σου ότι στο τέλος του string και εφόσον δεν έχεις εισάγει παραπάνω χαρακτήρες από όσους ορίζεις ως μάξιμουμ μέγεθος, προσθέτει ένα \n πράγμα που δεν συμβαίνει με την scanf.

Δημοσ.

Ok.Γιατι αυτες οι ιδιαιτεροτητες με τους χαρακτηρες και τις συμβολοσειρες ρε γμτ ομως?Υποθετω σε γλωσσες υψηλου επιπεδου αυτα ειναι λυμενα ε?

Δεν ξερω αν ειναι θεμα compiler(Netbeans) η λαθους δικου μου αλλα συναντω προβλημα ακομα και με απλους χαρακτηρες,δινω ενα παραδειγμα

 

>int main()
{
   char ch;
   
   do {
       
       printf("enter characters:\n");
       scanf("%c",&ch);
   }
   
   while(ch != 'b');
}

 

Αυτο εδω ετσι δεν δουλευει,αναγκαζομαι να κανω την εξης πατεντα

 

>int main()
{
   char ch,ch1;
   
   do {
       
       printf("enter characters:\n");
       scanf("%c%c",&ch,&ch1);
   }
   
   while(ch != 'b');
}

 

 

Και δινω απλα ενα χαρακτηρα καθε φορα πατωντας μετα το Enter,μονο ετσι μπορεσαν βγαλω ακρη

Δημοσ.

Η scanf/gets/getchar() χρησιμοποιούν το buffered stdin, αρα δεν επιστρεφουν τίποτα μέχρι να πατηθει ENTER. Σε dos, εχεις το

>
#include <conio.h>
..........
        c = getch(); 

η οποία επιστρέφει αμέσως, σε linux έχεις δυνατότητα να ορίσεις το stdin να είναι unbuffered.

 

δες και εδώ

Δημοσ.
Ok.Γιατι αυτες οι ιδιαιτεροτητες με τους χαρακτηρες και τις συμβολοσειρες ρε γμτ ομως?Υποθετω σε γλωσσες υψηλου επιπεδου αυτα ειναι λυμενα ε?

Δεν ξερω αν ειναι θεμα compiler(Netbeans) η λαθους δικου μου αλλα συναντω προβλημα ακομα και με απλους χαρακτηρες,δινω ενα παραδειγμα

[/code]

 

Και δινω απλα ενα χαρακτηρα καθε φορα πατωντας μετα το Enter,μονο ετσι μπορεσαν βγαλω ακρη

 

Πράγματι η ANSI C χωλαίνει όσο αφορά την διαχείριση (ειδικά) της εισόδου και εξόδου προς την κονσόλα, παρόλα αυτά αν δεν σε ενδιαφέρει η ANSI C συμβατότητα μπορείς να βασισθείς σε ειδικές non standard βιβλιοθήκες καλύπτοντας το κενό της ANSI C. Φυσικά εδώ μεγάλη σημασία παίζει ο compiler που χρησιμοποιείς και τι βοηθητικές βιβλιοθήκες τούτος σου παρέχει. Για παράδειγμα οι Borland/CodeGear (και ορισμένοι Microsoft) compilers τόσο για DOS όσο και για Windows έχουν την βιβλιοθήκη conio.h (που ανέφερε o bxenos) που καλύπτει την άμεση ανάγνωση του keyboard, τον έλεγχο του keyboard buffer κτλ. Άλλοι compilers μπορεί να παρέχουν άλλες βιβλιοθήκες ή στην χειρότερη περίπτωση καταλήγεις στην χρήση των ρουτινών του Λ.Σ. σου που κάνουν αυτές τις δουλειές (για παράδειγμα οι Console functions του Windows API).

 

Τώρα όσο αφορά γλώσσες υψηλότερου επιπέδου.. η διαχείριση των strings μπορεί πράγματι να είναι ευκολότερη, το ίδιο μπορεί να συμβεί αν στραφείς σε C++ όπου εκεί τα πράγματα είναι σε ορισμένα θέματα ευκολότερα.

Δημοσ.

Ας ειναι τοτε φιλε Directx,θα το υποστουμε τοτε,υποθετω λογο του οτι ειμαι αρχαριος οτι καθε γλωσσα θα εχει τις δικες τις ιδιαιτεροτητες ε?Το θετικο ειναι οτι με το να λυνω τετοιου ειδους προβληματα παρατηρω οτι καπου μου εχει δωσει μια μικρη ευελιξια οσο αφορα τον χειρισμο,ετσι για να παιρνουμε και λιγο κουραγιο ε?:-):-)

Αρχειοθετημένο

Αυτό το θέμα έχει αρχειοθετηθεί και είναι κλειστό για περαιτέρω απαντήσεις.

  • Δημιουργία νέου...