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

απορία σε απλό κώδικα στην C με struct


maniac89

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

>
#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.

Ευχαριστώ πολύ!

Συνδέστε για να σχολιάσετε
Κοινοποίηση σε άλλες σελίδες

>
#include <stdio.h>

struct str
{
    char name[50];
};
void main()
{
    struct str s;
    scanf("%s",s.name);
    printf("%s\n",s.name);
}

 

τώρα δουλεύει!

έχω μπερδευτεί λίγο με pointers, νόμιζα ότι δέσμευε αυτόματα μνήμη.

Συνδέστε για να σχολιάσετε
Κοινοποίηση σε άλλες σελίδες

Πρέπει είτε να ορίσεις το 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 μαζί γράφαμε :lol:

Συνδέστε για να σχολιάσετε
Κοινοποίηση σε άλλες σελίδες

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;
}

  • Like 1
Συνδέστε για να σχολιάσετε
Κοινοποίηση σε άλλες σελίδες

@Latency:

 

Χρειάζονται πολύ περισσότερα για να διαβαστεί με ασφάλεια ένα string από την κύρια είσοδο, στην C. Η gets() btw απαγορεύεται δια ροπάλου, επειδή δεν σε αφήνει να ελέγξεις πόσους χαρακτήρες διαβάζεις (αν στο παράδειγμά σου σου δώσουν π.χ. 102 χαρακτήρες για όνομα θα κρασάρει)... είναι από τους λόγους που ήταν ήδη depreciated στην C99 και καταργήθηκε πλήρως στην C11.

 

Use fgets() instead.

 

Επίσης, το malloc() που κάνεις δεν θέλει αστερίσκο στο sizeof()... έτσι όπως το 'χεις τώρα δεσμεύεις length δείκτες σε char, αντί για length chars που θέλεις (επίσης δεν χρειάζεται καν το cast, εκτός αν μιλάμε για πολύ εξειδικευμένη πλατφόρμα, που ξέρω γω χρησιμοποιεί K&R C)

Συνδέστε για να σχολιάσετε
Κοινοποίηση σε άλλες σελίδες

>
#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);

 

@παπι

όπως είπα όταν παίζεις με δυναμική δέσμευση μνήμης τα ξέρεις αυτά, μπορείς να το κάνεις φυσικά να δεσμεύσει επιπλέον αν βγει παραπάνω ...

Συνδέστε για να σχολιάσετε
Κοινοποίηση σε άλλες σελίδες

...

@παπι

όπως είπα όταν παίζεις με δυναμική δέσμευση μνήμης τα ξέρεις αυτά, μπορείς να το κάνεις φυσικά να δεσμεύσει επιπλέον αν βγει παραπάνω ...

 

Ή πολύ πιο απλά μπορείς να διαβάζεις με fgets() ώστε να κοντρολάρεις το πλήθος των χαρακτήρων που διαβάζεις.

 

ΥΓ. Υποθέτω εμένα εννοούσες αντί για τον πάπι ;)

 

>
#define MAXINPUT   Whatever
...
char input[ MAXINPUT ] = {'\0'};
...
fgets( input, MAXINPUT, stdin);
// remove '\n' from end if you don't need it
...

Συνδέστε για να σχολιάσετε
Κοινοποίηση σε άλλες σελίδες

λες να χρησιμοποίησης ένα προσωρινό αρχείο?

fgets(char *_Buf, int _MaxCount, FILE *_File);

 

ΥΓ: μην γράφετε στα παραδείγματα σας τέτοιο κώδικα

>
if(NULL == Blabla)

 

γιατί απλά μπερδεύει τον κόσμο, ας μάθει ο κόσμος το κανονικό και μετά προχωράει και σε αυτό.

Συνδέστε για να σχολιάσετε
Κοινοποίηση σε άλλες σελίδες

Το stdin δεν είναι προσωρινό αρχείο, είναι η κύρια είσοδος.

 

ΥΓ. Δεν ξέρω αν τον μπερδεύει τον κόσμο το να βάζει τις σταθερές πρώτα στις συγκρίσεις, σίγουρα όμως τον προστατεύει από αρκετούς πονοκεφάλους (ιδιαίτερα όταν κάνει τα πρώτα του βήματα).

  • Like 2
Συνδέστε για να σχολιάσετε
Κοινοποίηση σε άλλες σελίδες

>
char *pos_term;
pos_term=(char*)malloc(sizeof(char));

 

δεν το χω πιάσει ακόμα! :fear:

αν έχω τον παραπάνω κώδικα ο pos_term είναι σαν ένας πίνακας;

και αν ναι πόσα στοιχεία μπορεί να αποθηκεύσει;

δηλαδή το αντίστοιχο pos_term[ ] ποιό είναι;

Συνδέστε για να σχολιάσετε
Κοινοποίηση σε άλλες σελίδες

>
       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));

 

δεν το χω πιάσει ακόμα! :fear:

αν έχω τον παραπάνω κώδικα ο pos_term είναι σαν ένας πίνακας;

και αν ναι πόσα στοιχεία μπορεί να αποθηκεύσει;

δηλαδή το αντίστοιχο pos_term[ ] ποιό είναι;

Οι παραπάνω εντολές δηλώνουν ένα δείκτη σε char και μετά του εκχωρούν μνήμη μεγέθους ενός char οπότε μπορείς να χρησιμοποιήσεις τον δείκτη pos_term για να αποθηκεύσεις μία τιμή char (πχ *pos_term = 19). Αν έγραφες malloc(13) θα δέσμευες μνήμη μεγέθους 13 char και τότε θα ήταν σαν να είναι πίνακας που είπες.

 

  • Like 1
Συνδέστε για να σχολιάσετε
Κοινοποίηση σε άλλες σελίδες

ok, ευχαριστώ για την βοήθεια!

Τώρα θέλω να διαβάσω από ένα αρχείο ένα string και να το αποθηκεύσω στon *pos_term.

Ενώ κάνω μόνο malloc για ένα char

>
pos_term=(char*)malloc(sizeof(char));

τρέχει κανονικά και αποθηκεύει και τεράστιες λέξεις.

Από ότι κατάλαβα αυτό είναι σαν να αποθηκεύεται στην πρώτη θέση ενός "πίνακα".

Συνδέστε για να σχολιάσετε
Κοινοποίηση σε άλλες σελίδες

ok, ευχαριστώ για την βοήθεια!

Τώρα θέλω να διαβάσω από ένα αρχείο ένα string και να το αποθηκεύσω στon *pos_term.

Ενώ κάνω μόνο malloc για ένα char

>
pos_term=(char*)malloc(sizeof(char));

τρέχει κανονικά και αποθηκεύει και τεράστιες λέξεις.

Από ότι κατάλαβα αυτό είναι σαν να αποθηκεύεται στην πρώτη θέση ενός "πίνακα".

 

Θα σου "χτυπήσει" segmentation fault στο run-time, αν και όταν το πρόγραμμά σου επιχειρήσει να χρησιμοποιήσει την έξτρα μνήμη που έχει καταχραστεί το stream-input του προγράμματός σου (δηλαδή οτιδήποτε βρίσκεται δίπλα στον 1 χαρακτήρα που έχεις δεσμεύσει με αυτό το malloc() )

Συνδέστε για να σχολιάσετε
Κοινοποίηση σε άλλες σελίδες

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

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

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

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

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

Σύνδεση

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

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