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

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

Δημοσ.

Καλημερα,κανω ενα project σε c++ και θελω να διαβασω μια συμβολοσειρα απο αρχειο text.Το προβλημα ειναι οτι η συμβολοσειρα θελω να περιεχει και κενα .Οταν ομως διαβαζει κενο απο το αρχειο τοτε σταματαει εκει.Η συμβολοσειρα αυτη που θα διαβαστει απο το αρχειο θελω να εκχωρειται σε εναν δεικτη.Καμια βοηθεια ?

ευχαριστω.

Δημοσ.

H getline() μου δινει λυση στο προβλημα μου αλλα εγω θελω η συμβολοσειρα να εκχωρηθει σε δεικτη.

για παραδειγμα με στατικο η συνταξη της getline einai :

char name[256];

 

cout << "Enter your name: ";

cin.getline (name,256);

 

με δεικτη πως μπορει να γινει ?

ευχαριστω.

Δημοσ.

H getline() μου δινει λυση στο προβλημα μου αλλα εγω θελω η συμβολοσειρα να εκχωρηθει σε δεικτη.

για παραδειγμα με στατικο η συνταξη της getline einai :

char name[256];

 

cout << "Enter your name: ";

cin.getline (name,256);

 

με δεικτη πως μπορει να γινει ?

ευχαριστω.

χμμ

 

 

>char pName[256];
 cout << "Enter your name: ";

 cin.getline (pName,256);

 

Δημοσ.

H getline() μου δινει λυση στο προβλημα μου αλλα εγω θελω η συμβολοσειρα να εκχωρηθει σε δεικτη.

για παραδειγμα με στατικο η συνταξη της getline einai :

char name[256];

 

cout << "Enter your name: ";

cin.getline (name,256);

 

με δεικτη πως μπορει να γινει ?

ευχαριστω.

 

@koyn3l:

 

Στη C και τη C++ γίνεται αυτό που λέμε "array to pointer decay". Εν συντομία: όταν κάπου o compiler δει μια έκφραση με τύπο array-σε-κάτι ενώ περιμένει να δει pointer-σε-κάτι, αυτόματα μετρατρέπει τον πίνακα σε pointer στο πρώτο στοιχείο του.

 

Αυτό ακριβώς συμβαίνει στον κώδικα που έδωσες, όπου το name είναι char[] ενώ η πρώτη παράμετρος της getline πρέπει να είναι char*. Κάνεις δηλαδή λάθος στο πώς είναι η σύνταξη της getline, όπως θα μπορούσες να δείς και μόνος σου.

 

Sorry αν σου τη σπάω, το point μου είναι ότι αν μάθεις να ψάχνεις θα κάνεις τη δουλειά σου πολύ γρηγορότερα απ' το να ρωτάς σε forum πράγματα τα οποία αναφέρονται αυτούσια στο manual.

 

Update: Ναι, με μια δυναμική δέσμευση μνήμης είσαι ΟΚ. Έχε υπόψη ότι στη C++ δεν κάνουμε malloc, κάνουμε new και new[] (επίσης delete και delete[] αντί για free). Όχι γιατί δε δουλεύει η malloc, αλλά γιατί δεν είναι έτσι το ζεν της C++.

Δημοσ.

και μετα απο αυτο κανω μια malloc για δυναμικη δεσμευση και ειμαι comple e ?

Αντί να το ορίζεις στατικά το name , όρισέ το δυναμικά (δείκτη), κάνε το malloc(), διάβασε το, και όταν τελειώσεις κάνε το free().

Δημοσ.

Αμα δεν χρησιμοποιησω στατικο πινακα στην αρχη και χρησιμοποιησω δεικτη μετα στη συνταξη της getline τι θα βαλω ως ariθμο χωριτικοτητας ? Αυτο ειναι το προβλημα μου.

Δημοσ.

Αμα δεν χρησιμοποιησω στατικο πινακα στην αρχη και χρησιμοποιησω δεικτη μετα στη συνταξη της getline τι θα βαλω ως ariθμο χωριτικοτητας ? Αυτο ειναι το προβλημα μου.

Το πλήθος χαρακτήρων με το οποίο θα κάνεις malloc() το name. Την getline() δεν την ενδιαφέρει αν το έχεις ορίσει στατικά ή δυναμικά το name, αρκεί να είναι buffer από char.

 

EDIT:

 

Έχει δίκιο ο defacer για τα new και delete ... έτσι είναι το σωστό να το κάνεις σε C++.

Δημοσ.

Μα το πληθος των χαρακτηρων θα το ξερω αφου πληκτρολογησει ο χρηστης την συμβολοσειρα...

Δημοσ.

Μα το πληθος των χαρακτηρων θα το ξερω αφου πληκτρολογησει ο χρηστης την συμβολοσειρα...

Δεν σε "πιάνω"!

 

Με τον στατικό ορισμό πως το ξέρεις το πλήθος δηλαδή;

Δημοσ.

Μα το πληθος των χαρακτηρων θα το ξερω αφου πληκτρολογησει ο χρηστης την συμβολοσειρα...

 

Καλωσήρθες στον κόσμο του προγραμματισμού. :-D

 

Οποιαδήποτε function και να χρησιμοποιήσεις για να διαβάσεις από ένα stream και να αποθηκεύσεις σε μια μεταβλητή θα έχει να αντιμετωπίσει αυτό το πρόβλημα. Εκ της φύσεώς του το stream μπορεί να έχει περιεχόμενα αγνώστου μεγέθους ενώ η οποιαδήποτε μεταβλητή/buffer χρησιμοποιείς για την αποθήκευση θα έχει γνωστό μέγεθος (προφανώς, πρέπει να δεσμεύσεις μνήμη άρα πρέπει να πεις και πόση). Βεβαίως δε γίνεται το γνωστό να είναι εγγυημένα μεγαλύτερο από το άγνωστο, οπότε πρόβλημα.

 

Εδώ τώρα υπάρχουν διάφορες προσεγγίσεις. Η "καλή" είναι να διαβάζεις έναν ένα τους χαρακτήρες αντιγράφοντάς τους στον buffer. Όταν δεις ότι ο buffer γέμισε κάνεις allocate έναν μεγαλύτερο, αντιγράφεις τα περιεχόμενα από τον παλιό, αποδεσμεύεις τον παλιό και συνεχίζεις έτσι (επαναλαμβάνοντας αν χρειαστεί) μέχρι να αποφασίσεις να σταματήσεις.

 

Αυτό αμέσως μας λέει ότι:

 

  1. Ο buffer που χρησιμοποιείς πρέπει να είναι τσιφλίκι σου γιατί δε γίνεται να αποδεσμεύεις μνήμη που είναι τσιφλίκι αλλουνού (θα έχουμε πρόβλημα)
  2. Πρέπει να βάλεις κάπου ένα αυθαίρετο όριο έτσι κι αλλιώς γιατί διαφορετικά μπορεί κάποιος να οδηγήσει το προγραμμά σου στη δέσμευση όλης της διαθέσιμης μνήμης του συστήματος

 

Θα μου πεις αν πρέπει να βάλω αυθαίρετο όριο έτσι κι αλλιώς τότε τι κατάλαβα σε σχέση με το στατικό μέγεθος; Κατάλαβες ότι το στατικό buffer καταναλώνει τόση μνήμη πάντα, ενώ το δυναμικό μόνο αν χρειαστεί. Αυτή την ευκολία βέβαια την πληρώνεις με αίμα, δάκρυα και ταχύτητα εκτέλεσης.

 

Για να μην πολυλογώ, είτε διάλεξε μόνος σου ένα "αρκετά μεγάλο" μέγεθος είτε χρησιμοποίησε την free function getline που αποθηκεύει σε ένα std::string (κάνοντας αυτό ακριβώς που περιέγραψα παραπάνω). Δεν υπάρχει δικαιολογία να μη χρησιμοποιείς std::string στη c++ εκτός κι αν η εκφώνηση δεν το επιτρέπει.

Δημοσ.

Δεν σε "πιάνω"!

 

Με τον στατικό ορισμό πως το ξέρεις το πλήθος δηλαδή;

Οντως εχεις δικιο :P :P

 

Καλωσήρθες στον κόσμο του προγραμματισμού. :-D

 

Οποιαδήποτε function και να χρησιμοποιήσεις για να διαβάσεις από ένα stream και να αποθηκεύσεις σε μια μεταβλητή θα έχει να αντιμετωπίσει αυτό το πρόβλημα. Εκ της φύσεώς του το stream μπορεί να έχει περιεχόμενα αγνώστου μεγέθους ενώ η οποιαδήποτε μεταβλητή/buffer χρησιμοποιείς για την αποθήκευση θα έχει γνωστό μέγεθος (προφανώς, πρέπει να δεσμεύσεις μνήμη άρα πρέπει να πεις και πόση). Βεβαίως δε γίνεται το γνωστό να είναι εγγυημένα μεγαλύτερο από το άγνωστο, οπότε πρόβλημα.

 

Εδώ τώρα υπάρχουν διάφορες προσεγγίσεις. Η "καλή" είναι να διαβάζεις έναν ένα τους χαρακτήρες αντιγράφοντάς τους στον buffer. Όταν δεις ότι ο buffer γέμισε κάνεις allocate έναν μεγαλύτερο, αντιγράφεις τα περιεχόμενα από τον παλιό, αποδεσμεύεις τον παλιό και συνεχίζεις έτσι (επαναλαμβάνοντας αν χρειαστεί) μέχρι να αποφασίσεις να σταματήσεις.

 

Αυτό αμέσως μας λέει ότι:

 

  1. Ο buffer που χρησιμοποιείς πρέπει να είναι τσιφλίκι σου γιατί δε γίνεται να αποδεσμεύεις μνήμη που είναι τσιφλίκι αλλουνού (θα έχουμε πρόβλημα)
  2. Πρέπει να βάλεις κάπου ένα αυθαίρετο όριο έτσι κι αλλιώς γιατί διαφορετικά μπορεί κάποιος να οδηγήσει το προγραμμά σου στη δέσμευση όλης της διαθέσιμης μνήμης του συστήματος

 

Θα μου πεις αν πρέπει να βάλω αυθαίρετο όριο έτσι κι αλλιώς τότε τι κατάλαβα σε σχέση με το στατικό μέγεθος; Κατάλαβες ότι το στατικό buffer καταναλώνει τόση μνήμη πάντα, ενώ το δυναμικό μόνο αν χρειαστεί. Αυτή την ευκολία βέβαια την πληρώνεις με αίμα, δάκρυα και ταχύτητα εκτέλεσης.

 

Για να μην πολυλογώ, είτε διάλεξε μόνος σου ένα "αρκετά μεγάλο" μέγεθος είτε χρησιμοποίησε την free function getline που αποθηκεύει σε ένα std::string (κάνοντας αυτό ακριβώς που περιέγραψα παραπάνω). Δεν υπάρχει δικαιολογία να μη χρησιμοποιείς std::string στη c++ εκτός κι αν η εκφώνηση δεν το επιτρέπει.

Δεν θελω να χρησιμοποιησω std::string γιατι ο καθηγητης δεν μας την εχει αναφερει αυτη την κλαση και δεν ξερω για πιο λογο αφου σου λυνει τα χερια.

ευχαριστω παντως για της πληροφοριες :)

Δημοσ.

Βασικά αν το αρχείο είναι εξαρχής well defined ( δηλαδή ξέρεις εκ των προτέρων πως η μεγαλύτερη γραμμή του δεν μπορεί π.χ. να είναι μεγαλύτερη από N χαρακτήρες) τους κάνεις new εξαρχής και τελειώνεις, αλλιώς πρέπει να κάνεις αυτό που λέει ο defacer ... η global getline() κάνει την βρώμικη δουλειά για σένα, ενώ με την istream::getline() πρέπει να την κάνεις εσύ, με ελεγχόμενο realloc() δηλαδή).

 

Αν το αρχείο είναι well defined, π.χ. με max 255 chars per line, τότε (σε C)...

 

>
#define MAXLEN_FLINE  (255+1)
 ...
 FILE *fp = fopen( "filein.txt", "r");
 if ( !fp )
 	// fopen failed
 	exit(1);

 char *name = calloc( MAXLEN_FLINE, sizeof(char) );
 if ( !name )
 	// calloc failed
 	exit(1);

 while ( !feof(fp) && fgets(name, MAXLEN_FLINE, fp) )
 	// remove here '\n' form name's tail if you do no need it
 	puts( name );

 free( name );
 fclose(fp);
 ...

Προσάρμοσέ το σε c++ και getline εσύ ;)

 

ΥΓ. Εμένα πάντως με έχεις μπερδέψει γιατί αρχικά είπες πως θέλεις να διαβάζεις ένα αρχείο, αλλά μετά μίλησες για string που θα σου δίνει ο χρήστης.

Δημοσ.

Βασικά αν το αρχείο είναι εξαρχής well defined ( δηλαδή ξέρεις εκ των προτέρων πως η μεγαλύτερη γραμμή του δεν μπορεί π.χ. να είναι μεγαλύτερη από N χαρακτήρες) τους κάνεις new εξαρχής και τελειώνεις, αλλιώς πρέπει να κάνεις αυτό που λέει ο defacer ... η global getline() κάνει την βρώμικη δουλειά για σένα, ενώ με την istream::getline() πρέπει να την κάνεις εσύ, με ελεγχόμενο realloc() δηλαδή).

 

Αν το αρχείο είναι well defined, π.χ. με max 255 chars per line, τότε (σε C)...

 

>
#define MAXLEN_FLINE  (255+1)
 ...
 FILE *fp = fopen( "filein.txt", "r");
 if ( !fp )
 	// fopen failed
 	exit(1);

 char *name = calloc( MAXLEN_FLINE, sizeof(char) );
 if ( !name )
 	// calloc failed
 	exit(1);

 while ( !feof(fp) && fgets(name, MAXLEN_FLINE, fp) )
 	// remove here '\n' form name's tail if you do no need it
 	puts( name );

 free( name );
 fclose(fp);
 ...

Προσάρμοσέ το σε c++ και getline εσύ ;)

 

ΥΓ. Εμένα πάντως με έχεις μπερδέψει γιατί αρχικά είπες πως θέλεις να διαβάζεις ένα αρχείο, αλλά μετά μίλησες για string που θα σου δίνει ο χρήστης.

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

ευχαριστω για τον κωδικα. :-)

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

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

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

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

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

Σύνδεση

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

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