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

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

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

  • 0
makis89

Εισαγωγή text file στη c

Ερώτηση

Καλημέρα....Θα ήθελα τη βοήθειά σας ...

 

Θέλω να γράψω ένα πρόγραμμα στη c που θα ανοίγει ένα αρχείο txt το οποίο θα είναι στην ακόλουθη μορφή:

 

12345,fdafaaf,sdfsaf

 

Δηλαδή θα έχουμε int,string,string

Εγώ θέλω να διαβάσω κάθε αντικείμενο ανάμεσα στα κόμματα χωριστά. Για παράδειγμα θέλω τον ακέραιο να τον αποθηκεύσω σε μία μεταβλητή, το fdafaaf σε ένα string κλπ

 

Αυτό που ρωτάω είναι πώς μπορώ να πάρω κάθε αντικείμενο που βρίσκεται ανάμεσα σε κόμματα ;

 

Σκέφτηκα να περάσω όλη τη γραμμή σε ένα string, και με ένα for να ξεχωρίσω κάθε τι που είναι ανάμεσα στα κόμματα...αλλά μήπως υπάρχει καμιά πιο εύκολη λύση ;

 

Ευχαριστώ !

Κοινοποιήστε αυτήν την ανάρτηση


Σύνδεσμος στην ανάρτηση
Κοινοποίηση σε άλλες σελίδες

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

H sscanf με %s στο fromat string θα διαβάσει ένα string μέχρι να βρει κενό. Μπορείς να καθορίσεις διαφορετική συμπεριφορά χρησιμοποιόντας τα [] αντί για το s. Για παράδειγμα η %[Α-z] θα διαβάσει μόνο τους χαρακτήρες από το Α μέχρι το z (που σημαίνει ότι αν βρεί διαφορετικό χαρακτήρα θα σταματήσει). Στην περίπτωση σου βολεύει να καθορίσεις ποιόν χαρακτήρα δεν θα διαβάσει (εδώ το ',') βάζοντας %[^,] (το string μπορεί να περιέχει οποιοδήποτε χαρακτήρα, συμπεριλαμβανομένου και του κενού, εκτός από το κόμμα)

 

χαχα αυτο δεν το ηξερα, ωραιος bilco

Κοινοποιήστε αυτήν την ανάρτηση


Σύνδεσμος στην ανάρτηση
Κοινοποίηση σε άλλες σελίδες

Μια απλή λύση είναι να ανοίξεις το αρχείο .txt με to notepad και να πας edit->replace. Αντικαθιστάς όλα τα κόμματα με κενό κάνοντας μόνο ένα click!!! Στη συνέχεια χρησιμοποιείς την fscanf(file,"%s %s %d",....klp). Ελπίζω να βοηθήει αυτό.

Κοινοποιήστε αυτήν την ανάρτηση


Σύνδεσμος στην ανάρτηση
Κοινοποίηση σε άλλες σελίδες

αν ξέρεις πως κάθε γραμμη ειναι στανταρ της μορφης

πχ <int>,<string>,<string>

 

μπορεις να χρησιμοποιησεις την sscanf ως εξης

>
// μη ξεχάσεις τα κόμματα αναμεσα στα %d,%s etc
sscanf( buffer, "%d,%s,%s", &intVar1, stringVar1, stringVar2); 

 

όπου buffer ειναι η μεταβλητη που εχει τη σειρα που διαβασες από το αρχειο, intVar1, stringVar1 κτλ ειναι οι μεταβλητες στις οποιες θες να αποθηκευεσεις τις τιμες αναμεσα στα κομματα.

 

επαναλαμβάνεις για οσες γραμμες του αρχειου θες

Κοινοποιήστε αυτήν την ανάρτηση


Σύνδεσμος στην ανάρτηση
Κοινοποίηση σε άλλες σελίδες
Σας ευχαριστώ όλους...

Τα παραπάνω δεδομένα τα παίρνω από ένα αρχείο. Το αρχείο αυτό πρέπει να το ανοίγω για ανάγνωση-εγγραφή αλλά και όταν δεν υπάρχει πρέπει να το δημιουργώ. Μπορεί να γίνονται αυτά ταυτόχρονα ; Έστω ότι για το read-write βάζω mode "r+" ... Άν βάλω "w+" ώστε να δημιουργείται το αρχείο αν δεν υπάρχει, σβήνει όλα τα περιεχόμενά του.:rolleyes: Τί κάνουμε σε αυτήν την περίπτωση ; Μία σκέψη είναι ότι άν το fopen("arxeio.txt","r+") είναι NULL να κάνω ένα fopen("arxeio.txt","w+"). Είναι σωστή η λογική μου ;

 

Απλά άνοιξε το να το διαβάσεις να δεις αν υπάρχει, μία ωραία συναρτησούλα να κάνει την δουλειά είναι αυτή:

>
int FileExists(const char *_filename)
{
FILE *ptrFile = NULL;
if(ptrFile = fopen(_filename, "r")) != NULL)
{
	fclose(ptrFile);
	return 1;
}
return 0;
}

 

Επιστρέφει True (διάφορο του μηδέν) αν όντως υπάρχει και False (μηδέν) αν δεν υπάρχει.

Κοινοποιήστε αυτήν την ανάρτηση


Σύνδεσμος στην ανάρτηση
Κοινοποίηση σε άλλες σελίδες
Αυτό δεν γίνεται και με μία if ; Ποιός ο λόγος να χρησιμοποιήσω επιπλέον συνάρτηση ;

 

Όταν γράφεις κώδικα και πολύ μάλιστα είναι καλό να τον τακτοποιείς με συναρτήσεις που θα σου κάνουν μερική από την δουλειά έτσι ώστε να μην γράφεις τον ίδιο κώδικα κάθε φορά και να είναι το πρόγραμμα σου καλά δομημένο, τώρα εσύ κάνεις ότι θέλεις, δεν είναι δική μου υπόθεση, εγώ απλώς σου πρότεινα ένα τρόπο.

Κοινοποιήστε αυτήν την ανάρτηση


Σύνδεσμος στην ανάρτηση
Κοινοποίηση σε άλλες σελίδες

Ευχαριστώ πολύ και τους δύο... Τελικά το έκανα έτσι:

 

sscanf( buffer, "%d,%s,%s", &intVar1, stringVar1, stringVar2);

 

Βέβαια χρησιμοποίησα δομές αντί για μεταβλητές αλλά αυτό είναι άλλο :-D

Κοινοποιήστε αυτήν την ανάρτηση


Σύνδεσμος στην ανάρτηση
Κοινοποίηση σε άλλες σελίδες
Αυτό δεν γίνεται και με μία if ; Ποιός ο λόγος να χρησιμοποιήσω επιπλέον συνάρτηση ;

 

Μπορεί να γίνει με μια if αν ο compiler σου είναι συμβατός με POSIX και προσφέρει την ρουτίνα access("filename",0) της βιβλιοθήκη io.h, η οποία επιστρέφει 0 όταν υπάρχει το αρχείο "filename" ή -1 όταν δεν υπάρχει -το ",0" ζητά από την access να ελέγξει για την ύπαρξη του αρχείου, μάλιστα γλυτώνεις και από το άγχος το αρχείο να μην έχει read-permissions...

 

πχ.

>
fopen("myfile.txt",(access("myfile.txt")==-1)?"w":"r+");

 

Τώρα αν θέλεις να εξασφαλίσεις πως ο κώδικας σου θα γίνεται compile σε κάθε ANSI-C compiler προφανώς η χρήση της ρουτίνας access είναι επίφοβη, καθώς μπορεί να μην υπάρχει, οπότε γράφεις μια ρουτίνα σαν του Bokarinho.

Κοινοποιήστε αυτήν την ανάρτηση


Σύνδεσμος στην ανάρτηση
Κοινοποίηση σε άλλες σελίδες

λοιπον μια αλλη προσεγγιση

 

παρνεις μια γραμμη απο το αρχειο καθε φορα με την fgets

> 
FILE* fPtr;
char linebuffer[100];  // maximum line length 100-1
char* tmp;
...
tmp = fgets(lienbuffer,100, fPtr);
...

 

αν το tmp==NULL τοτε εφτασε στο EOF χωρις να διαβαστει χαρακτηρας. Εχεις λοιπον τωρα το linebuffer που περιεχει μια γραμμη. Εσυ ξέρεις ακριβως το format καθε γραμμης, εχεις πχ πεδια που χωριζονται με κομματα. Θα χρησιμοποιησουμε την strtok για αυτη τη δουλεια

 

πχ για <int>,<string>,<int>

 

>

while( fgets(linebuffer, 100, fPtr) != NULL)  // για καθε γραμμη
{
    char* tmp1 = strtok(linebuffer,",");  //take portion of string (token)until first comma
    intVar1 = atoi(tmp1);     // get you 1st integer
    tmp1 = strtok(NULL,",");    // get token until 2nd comma (notice that now NULL is passed as argument, meaning that we continue from where we were)
    strcpy( yourstring1, tmp1);  // copy from tmp1 (until 2nd comma)
     tmp1 = strtok(NULL,",");    // get token until the end
    // now get the 2nd integer (after the 2nd comma)
    intVar2 = atoi(tmp1);
}

 

ο κωδικας ειναι απο το μυαλο μου οποτε μπορει να εχει λαθη αλλα ειμαι στη δουλεια τωρα. Κοιτα το documentation της strtok, και customarise τον κωδικα για το δικο σου format

 

ps. η λυση ειναι παρομοια με αυτη του bokarinho , απλα στο εκανα πολυ λιανά ωστε να φτιαξεις κατι που καλυπτει τις αναγκες σου

Κοινοποιήστε αυτήν την ανάρτηση


Σύνδεσμος στην ανάρτηση
Κοινοποίηση σε άλλες σελίδες

η λύση του bokarinho είναι σωστή και δε σου επιβαρύνει το πρόγραμμα. Μη σε τρόμάζει οτι μεγαλώνει ο κώδικας. Καλύτερα σταθερό και δομημένο πρόγραμμα από το να γλυτώσεις μερικά bytes εκτελέσιμου.

Κοινοποιήστε αυτήν την ανάρτηση


Σύνδεσμος στην ανάρτηση
Κοινοποίηση σε άλλες σελίδες

Χρειάζεται προσοχή όταν γίνετε χρήση της scanf (& family) με το %s specifier καθώς δεν γίνεται έλεγχος των ορίων του string/array προορισμού.

 

Ο σωστός τρόπος χρήσης είναι με length specifier.

 

Λάθος τρόπος:

 

>
stest.c
--------

#include <stdio.h>

int main(void) {
 char buf[10];

 scanf("%s", buf);

 printf("buf = %s\n", buf);

 return 0;
}

 

Εκτέλεση:

 

>
# gcc -Wall -O2 -W stest.c -o stest

# ./stest
sdsdsd  <== input
buf = sdsdsd

# ./stest
askldljkasdklasldkaslkdlkasd <== input = buffer overflow
buf = askldljkasdklasldkaslkdlkasd
Segmentation fault

 

Σωστός τρόπος

 

>
stest2.c
----------

#include <stdio.h>

int main(void) {
 char buf[10];

 scanf("%9s", buf);

 printf("buf = %s\n", buf);

 return 0;
}

 

Εκτέλεση:

 

>
# gcc -Wall -O2 -W stest2.c -o stest2

# ./stest2
asdasdasd <== input
buf = asdasdasd

# ./stest2
asjkdjasdasjkdaskdkasdsadjas <== input, no buffer overflow
buf = asjkdjasd

 

Το ίδιο ισχύει και για το specifier %[..]

 

Links:

 

http://securityficus.org/blog/2007/08/11/scanf-is-an-underrated-source-of-security-bugs/

http://en.wikipedia.org/wiki/Scanf

Κοινοποιήστε αυτήν την ανάρτηση


Σύνδεσμος στην ανάρτηση
Κοινοποίηση σε άλλες σελίδες

Μπορείς εξίσου απλά να χρησιμοποιήσεις την fscanf για να διαβάσεις τα αλφαριθμητικά και τους ακέραιους και στην συνέχεια με την χρήση της συνάρτησης strtok να αφαιρέσεις το κόμμα(,) από τα αλφαριθμητικά

Κοινοποιήστε αυτήν την ανάρτηση


Σύνδεσμος στην ανάρτηση
Κοινοποίηση σε άλλες σελίδες

Αν έχω καταλάβει καλά ο σκοπός της άσκησης είναι να τους μάθουν να δουλεύουν με πίνακες χαρακτήρων. Οπότε όποια έκδοση της scanf και να χρησιμοποιήσει δεν είναι ο τρόπος που θέλει ο καθηγητής. Anyway...

Κοινοποιήστε αυτήν την ανάρτηση


Σύνδεσμος στην ανάρτηση
Κοινοποίηση σε άλλες σελίδες
Αν χρησιμοποιήσεις την sscanf αντί της fscanf πάλι θα σε κόψουν διότι είναι ακριβώς το ίδιο πράγμα!!

Μα άμα είπαν μόνο για την fscanf και όχι για την sscanf δικό τους πρόβλημα =P Bέβαια ο δικός σου τρόπος είναι πιο σίγουρος.

Κοινοποιήστε αυτήν την ανάρτηση


Σύνδεσμος στην ανάρτηση
Κοινοποίηση σε άλλες σελίδες
×
×
  • Δημιουργία νέου...