maniac89 Δημοσ. 2 Οκτωβρίου 2012 Δημοσ. 2 Οκτωβρίου 2012 > #include <stdio.h> struct str { char *name; }; void main() { struct str s; scanf("%s",s.name); printf("%s\n",s.name); } στον παραπάνω κώδικα γιατί μου βγαζει Segmentation Fault. Αυτό που θέλω να κάνω είναι να διαβάσω ένα όνομα και να το αποθηκεύσω στο πεδίο name του struct. Ευχαριστώ πολύ!
ChRis6 Δημοσ. 2 Οκτωβρίου 2012 Δημοσ. 2 Οκτωβρίου 2012 Γιατι δεν εχεις δεσμευσει μνημη για το string.Αν τη μεταβλητη name τη κανεις πινακα,δεν θα εχεις προβλημα 1
maniac89 Δημοσ. 2 Οκτωβρίου 2012 Μέλος Δημοσ. 2 Οκτωβρίου 2012 > #include <stdio.h> struct str { char name[50]; }; void main() { struct str s; scanf("%s",s.name); printf("%s\n",s.name); } τώρα δουλεύει! έχω μπερδευτεί λίγο με pointers, νόμιζα ότι δέσμευε αυτόματα μνήμη.
migf1 Δημοσ. 2 Οκτωβρίου 2012 Δημοσ. 2 Οκτωβρίου 2012 Πρέπει είτε να ορίσεις το name στατικά με συγκεκριμένο μέγεθος... >char name[100+1] = {'\0'} είτε να το κάνεις δυναμικά malloc() πριν επιχειρήσεις να διαβάσεις κάτι μέσα του... >if ( NULL == (name=calloc(100+1, sizeof(char)) ) exit(1); και πριν τερματίσεις το πρόγραμμά σου να το απελευθερώσεις με... >if (name) free(name); Τα παραπάνω χωρίς να είναι σε struct το name. Προσάρμοσέ το στο struct εσύ. EDIT: Και οι 3 μαζί γράφαμε
Latency Δημοσ. 2 Οκτωβρίου 2012 Δημοσ. 2 Οκτωβρίου 2012 Use gets() instant of scanf() > #include "stdafx.h" #include <malloc.h> #include <stdlib.h> typedef struct { char *Name; int Age; int Weight; }Person; #define Length 100 int _tmain(int argc, _TCHAR* argv[]) { Person P; P.Name = (char *) malloc(sizeof(char *) * Length); if (P.Name == NULL) exit(1); // Initial vars, dont ask (is boring) P.Age = 20; P.Weight = 100; // Read from keyboard printf("Enter your name: "); gets(P.Name); // Print printf("I' am %s, i am %d years old and im only %d pounds \n", P.Name, P.Age, P.Weight ); if (P.Name != NULL) free(P.Name); return 0; } 1
migf1 Δημοσ. 2 Οκτωβρίου 2012 Δημοσ. 2 Οκτωβρίου 2012 @Latency: Χρειάζονται πολύ περισσότερα για να διαβαστεί με ασφάλεια ένα string από την κύρια είσοδο, στην C. Η gets() btw απαγορεύεται δια ροπάλου, επειδή δεν σε αφήνει να ελέγξεις πόσους χαρακτήρες διαβάζεις (αν στο παράδειγμά σου σου δώσουν π.χ. 102 χαρακτήρες για όνομα θα κρασάρει)... είναι από τους λόγους που ήταν ήδη depreciated στην C99 και καταργήθηκε πλήρως στην C11. Use fgets() instead. Επίσης, το malloc() που κάνεις δεν θέλει αστερίσκο στο sizeof()... έτσι όπως το 'χεις τώρα δεσμεύεις length δείκτες σε char, αντί για length chars που θέλεις (επίσης δεν χρειάζεται καν το cast, εκτός αν μιλάμε για πολύ εξειδικευμένη πλατφόρμα, που ξέρω γω χρησιμοποιεί K&R C)
Latency Δημοσ. 2 Οκτωβρίου 2012 Δημοσ. 2 Οκτωβρίου 2012 > #include <stdio.h> struct str { char name[50]; }; void main() { struct str s; scanf("%s",s.name); printf("%s\n",s.name); } τώρα δουλεύει! έχω μπερδευτεί λίγο με pointers, νόμιζα ότι δέσμευε αυτόματα μνήμη. σε αυτό το παράδειγμα δουλεύει γιατί έχεις πίνακα και δεσμεύει από μόνο του μνήμη, στο προηγούμενο είχες έναν δείκτη και ως γνωστός πρέπει μόνος σου να δεσμεύσεις μνήμη ο ρόλος του "Length" ουσιαστικά είναι πόσους χαρακτήρες παίρνει, δηλαδή δεσμεύει μνήμη για 100 χαρακτήρες στο συγκεκριμένο παράδειγμα, υπολόγισε -1 συνέχεια για τον τερματικό χαρακτήρα, άρα 99 μπορείς να χρησιμοποιήσεις... @Latency: Χρειάζονται πολύ περισσότερα για να διαβαστεί με ασφάλεια ένα string από την κύρια είσοδο, στην C. Η gets() btw απαγορεύεται δια ροπάλου, επειδή δεν σε αφήνει να ελέγξεις πόσους χαρακτήρες διαβάζεις (αν στο παράδειγμά σου σου δώσουν π.χ. 102 χαρακτήρες για όνομα θα κρασάρει)... είναι από τους λόγους που ήταν ήδη depreciated στην C99 και καταργήθηκε πλήρως στην C11. Use fgets() instead. Επίσης, το malloc() που κάνεις δεν θέλει αστερίσκο στο sizeof()... έτσι όπως το 'χεις τώρα δεσμεύεις length δείκτες σε char, αντί για length chars που θέλεις (επίσης δεν χρειάζεται καν το cast, εκτός αν μιλάμε για πολύ εξειδικευμένη πλατφόρμα, που ξέρω γω χρησιμοποιεί K&R C) μου κάνει εντύπωση που δεν χτυπάει, μπορείς να δεσμεύσεις για 5 χαρακτήρες και να γράψεις 50, μόνο όταν αφήνεις κενά χτυπάει, δηλαδή αν δηλώσεις Length 2 και γράψεις one two θα το πάρει, αν γράψεις onetwothreefore θα το πάρει, αν γράψεις one two three χτυπάει αντί να διαβάζει χαρακτήρες διαβάζει ομάδες... ohh τώρα το είδα > P.Name = (char *) malloc(sizeof(char *) * Length); @τοπικ σταρτερ, το παραπάνω θέλει αλλαγή σε > P.Name = (char *) malloc(sizeof(char) * Length); @παπι όπως είπα όταν παίζεις με δυναμική δέσμευση μνήμης τα ξέρεις αυτά, μπορείς να το κάνεις φυσικά να δεσμεύσει επιπλέον αν βγει παραπάνω ...
migf1 Δημοσ. 2 Οκτωβρίου 2012 Δημοσ. 2 Οκτωβρίου 2012 ... @παπι όπως είπα όταν παίζεις με δυναμική δέσμευση μνήμης τα ξέρεις αυτά, μπορείς να το κάνεις φυσικά να δεσμεύσει επιπλέον αν βγει παραπάνω ... Ή πολύ πιο απλά μπορείς να διαβάζεις με fgets() ώστε να κοντρολάρεις το πλήθος των χαρακτήρων που διαβάζεις. ΥΓ. Υποθέτω εμένα εννοούσες αντί για τον πάπι > #define MAXINPUT Whatever ... char input[ MAXINPUT ] = {'\0'}; ... fgets( input, MAXINPUT, stdin); // remove '\n' from end if you don't need it ...
Latency Δημοσ. 2 Οκτωβρίου 2012 Δημοσ. 2 Οκτωβρίου 2012 λες να χρησιμοποίησης ένα προσωρινό αρχείο? fgets(char *_Buf, int _MaxCount, FILE *_File); ΥΓ: μην γράφετε στα παραδείγματα σας τέτοιο κώδικα > if(NULL == Blabla) γιατί απλά μπερδεύει τον κόσμο, ας μάθει ο κόσμος το κανονικό και μετά προχωράει και σε αυτό.
migf1 Δημοσ. 2 Οκτωβρίου 2012 Δημοσ. 2 Οκτωβρίου 2012 Το stdin δεν είναι προσωρινό αρχείο, είναι η κύρια είσοδος. ΥΓ. Δεν ξέρω αν τον μπερδεύει τον κόσμο το να βάζει τις σταθερές πρώτα στις συγκρίσεις, σίγουρα όμως τον προστατεύει από αρκετούς πονοκεφάλους (ιδιαίτερα όταν κάνει τα πρώτα του βήματα). 2
maniac89 Δημοσ. 6 Οκτωβρίου 2012 Μέλος Δημοσ. 6 Οκτωβρίου 2012 > char *pos_term; pos_term=(char*)malloc(sizeof(char)); δεν το χω πιάσει ακόμα! αν έχω τον παραπάνω κώδικα ο pos_term είναι σαν ένας πίνακας; και αν ναι πόσα στοιχεία μπορεί να αποθηκεύσει; δηλαδή το αντίστοιχο pos_term[ ] ποιό είναι;
imitheos Δημοσ. 6 Οκτωβρίου 2012 Δημοσ. 6 Οκτωβρίου 2012 > char name[50]; τώρα δουλεύει! έχω μπερδευτεί λίγο με pointers, νόμιζα ότι δέσμευε αυτόματα μνήμη. Όντως δεσμεύει μνήμη αλλά όχι όπως το φαντάζεσαι. Αν παραβλέψουμε προχωρημένα σενάρια, όταν δηλώνεις μια μεταβλητή, δεσμεύεται στην στοίβα όση μνήμη χρειάζεται για αυτή τη μεταβλητή. Το όνομα της μεταβλητής είναι ένας εύκολος συμβολικός τρόπος να προσπελαύνεις αυτή τη διεύθυνση μνήμης. > 1) int i; 2) float f[5]; 3) char *p; Σύμφωνα με αυτό που είπαμε, στην 1η περίπτωση δεσμεύεται μνήμη για ένα int και έτσι μπορείς και χρησιμοποιείς κανονικά το i. Στη 2η περίπτωση δεσμεύεται μνήμη συνεχόμενα για 5 floats. Στην 3η περίπτωση έχουμε ένα δείκτη οπότε δεσμεύεται όση μνήμη χρειάζεται για ένα δείκτη. Αυτή η διεύθυνση που δεσμεύτηκε μπορεί να χρησιμοποιηθεί κανονικά. Όπως δηλαδή λες i = 5, μπορείς να γράψεις μια τιμή σε αυτή τη διεύθυνση. Η τιμή αυτή όμως που θα γράψεις για να μπορεί να προσπελαστεί θα πρέπει να είναι διεύθυνση που έχει δωθεί στο πρόγραμμά σου, για αυτό και έπρεπε να δεσμεύσεις και άλλη μνήμη. Μπορείς δηλαδή να γράψεις p = 5 αλλά επειδή η διεύθυνση 5 δεν ανήκει στο πρόγραμμά σου δεν μπορείς να γράψεις *p = 12. > char *pos_term; pos_term=(char*)malloc(sizeof(char)); δεν το χω πιάσει ακόμα! αν έχω τον παραπάνω κώδικα ο pos_term είναι σαν ένας πίνακας; και αν ναι πόσα στοιχεία μπορεί να αποθηκεύσει; δηλαδή το αντίστοιχο pos_term[ ] ποιό είναι; Οι παραπάνω εντολές δηλώνουν ένα δείκτη σε char και μετά του εκχωρούν μνήμη μεγέθους ενός char οπότε μπορείς να χρησιμοποιήσεις τον δείκτη pos_term για να αποθηκεύσεις μία τιμή char (πχ *pos_term = 19). Αν έγραφες malloc(13) θα δέσμευες μνήμη μεγέθους 13 char και τότε θα ήταν σαν να είναι πίνακας που είπες. 1
maniac89 Δημοσ. 6 Οκτωβρίου 2012 Μέλος Δημοσ. 6 Οκτωβρίου 2012 ok, ευχαριστώ για την βοήθεια! Τώρα θέλω να διαβάσω από ένα αρχείο ένα string και να το αποθηκεύσω στon *pos_term. Ενώ κάνω μόνο malloc για ένα char > pos_term=(char*)malloc(sizeof(char)); τρέχει κανονικά και αποθηκεύει και τεράστιες λέξεις. Από ότι κατάλαβα αυτό είναι σαν να αποθηκεύεται στην πρώτη θέση ενός "πίνακα".
migf1 Δημοσ. 6 Οκτωβρίου 2012 Δημοσ. 6 Οκτωβρίου 2012 ok, ευχαριστώ για την βοήθεια! Τώρα θέλω να διαβάσω από ένα αρχείο ένα string και να το αποθηκεύσω στon *pos_term. Ενώ κάνω μόνο malloc για ένα char > pos_term=(char*)malloc(sizeof(char)); τρέχει κανονικά και αποθηκεύει και τεράστιες λέξεις. Από ότι κατάλαβα αυτό είναι σαν να αποθηκεύεται στην πρώτη θέση ενός "πίνακα". Θα σου "χτυπήσει" segmentation fault στο run-time, αν και όταν το πρόγραμμά σου επιχειρήσει να χρησιμοποιήσει την έξτρα μνήμη που έχει καταχραστεί το stream-input του προγράμματός σου (δηλαδή οτιδήποτε βρίσκεται δίπλα στον 1 χαρακτήρα που έχεις δεσμεύσει με αυτό το malloc() )
Προτεινόμενες αναρτήσεις
Δημιουργήστε ένα λογαριασμό ή συνδεθείτε για να σχολιάσετε
Πρέπει να είστε μέλος για να αφήσετε σχόλιο
Δημιουργία λογαριασμού
Εγγραφείτε με νέο λογαριασμό στην κοινότητα μας. Είναι πανεύκολο!
Δημιουργία νέου λογαριασμούΣύνδεση
Έχετε ήδη λογαριασμό; Συνδεθείτε εδώ.
Συνδεθείτε τώρα