ThomasD Δημοσ. 22 Ιανουαρίου 2005 Δημοσ. 22 Ιανουαρίου 2005 Έχω δημιουργήσει ένα αρχείο txt και σε κάθε σειρά έχω μια καταχώρηση. 1) Υπάρχει τρόπος να διαγράψω μία σειρά? 2) Ανοίγω το αρχείο για εγγραφή στο τέλος. Μπορώ να διαγράψω τον τελευταίο χαρακτήρα και στη συνέχεια να ακολουθήσει η εγγραφή? Παρακαλώ, όποιος γνωρίζει...
Typhoon Δημοσ. 23 Ιανουαρίου 2005 Δημοσ. 23 Ιανουαρίου 2005 Ποιές είναι οι πιθανότητες να μην υπάρχει ?
ThomasD Δημοσ. 23 Ιανουαρίου 2005 Μέλος Δημοσ. 23 Ιανουαρίου 2005 Μάλλον δεν έκανα σωστά την ερώτηση... Χρησιμοποιώ C++ (MS Visual C++ 6.0) και έχω δημιουργήσει ένα txt αρχείο με μερικές σειρές. Θέλω να διαγράψω μία σειρά. Πως γίνεται αυτό; Ποιος ο κώδικας;
baxter Δημοσ. 23 Ιανουαρίου 2005 Δημοσ. 23 Ιανουαρίου 2005 o pio efkolos kai aplos tropos gia na to kaneis afto einai o exis : estw oti thes na diagrapseis tin 10i grammi. diavase mia mia grammi mehri tin 9i grammi kai adegrapse ti s ena temp arheio. diavase tin 10i grammi. sinehise na diavazeis mia mia grammi mehri to telos kai na tin adigrafeis sto temp arheio. diegrapse to arhiko arheio. metonomase to temp arheio sto onoma tou arhikou arheiou.
Typhoon Δημοσ. 23 Ιανουαρίου 2005 Δημοσ. 23 Ιανουαρίου 2005 Εγώ θα πρότεινα με ένα for να μετράει τους new line χαρακτήρες και όταν φτάσει στον ένατο να διαγράψει από τον επόμενο χαρακτήρα μετά από αυτόν, μέχρι τον επόμενο new line χαρακτήρα. Ότι προτιμάει ο καθένας γενικά τρόποι υπάρχουν πολλοί.
ThomasD Δημοσ. 24 Ιανουαρίου 2005 Μέλος Δημοσ. 24 Ιανουαρίου 2005 Και οι δυο τρόποι που είπατε είναι σωστοί. Ακριβώς τις ίδιες σκέψεις έκανα κι εγώ. Τον τρόπο που λέει ο baxter μπορώ να τον υλοποιήσω σε κώδικα, όμως πιστεύω πως είναι καλύτερα ο τρόπος που λέει ο Typhoon και αυτό ρωτάω από την αρχή. Από τα βιβλία που έχω δεν υπάρχει πουθενά για διαγραφή χαρακτήρα μέσα σε αρχείο. Έκανα αναζήτηση στο google αλλα τίποτα γι'αυτό και ρωτάω εσάς. Υπάρχει κάποια εντολή της C++ για διαγραφή χαρακτήρα; H έστω κάποιο κομμάτι κώδικα που μπορώ να χρησιμοποιήσω; Επίσης δεν μπορώ να δώ στο help γιατί η Visual που έχω απλά δεν έχει. Μου την έδωσαν από το πανεπιστήμιο. Ευχαριστώ πολύ για το ενδιαφέρον σας!
Typhoon Δημοσ. 24 Ιανουαρίου 2005 Δημοσ. 24 Ιανουαρίου 2005 Δηλαδή χρησιμοποιείς Visual Studio χωρίς MSDN ? Αυτό είναι έγκλημα! Πάντως δεν είναι δύσκολο να βρεις ένα MSND.... Όπως και να έχει η αλήθεια είναι ότι δεν θυμάμαι απέξω γιατί έχω κάποια χρόνια να ασχοληθώ με αρχεία μέσω καθαρής C (χωρίς overlying API). Πάντως όταν πάω σπίτι θα κοιτάξω κάτι παλία progs που είχα και θα σου πω!
ThomasD Δημοσ. 24 Ιανουαρίου 2005 Μέλος Δημοσ. 24 Ιανουαρίου 2005 Όντως πολύ σπαστικό να μην έχεις MSDN. Χρησιμοποιούσα μέχρι πριν κανένα μήνα την Borland και όσο μπορώ βλέπω το δικό της help αλλά σε μερικά σημεία είναι φτωχό. Γι' αυτό και άλλαξα σε MS Visual και τώρα σιγά σιγά την μαθαίνω. Έχει πολλά περισσότερα από την Borland. Όμως είμασταν ήδη στις γιορτές και από τότε δεν είχαμε μάθημα για να ρωτήσω αν το έχει κανείς το MSDN. Αλλά που θα μου πάει, κάπου θα το πετύχω! Όταν μπορείς πες μου σε παρακαλώ!
kickeras Δημοσ. 25 Ιανουαρίου 2005 Δημοσ. 25 Ιανουαρίου 2005 Wow....to oti den xrisimopoieis MSDN den kserw pws na to xaraktirisw.....xazo:) i gennaio!!!!xexe.... vasika egw tin exw parei free mazi me Visual Studio kai sxedon oti exei i Microsoft logw tou master mou kai den kserw poso diskola ti vriskeis alla den pistevw oti einai toso diskolo....(mporeis na ti deis kai online) an den mporeis na vreis apantiseis se vivlia pigaine sto IRC sto undernet kai sto kanali C++....kalitera omws mi tous peis oti eisai foititis giati exoun kompleks kai tha se kickaroun... giati na min exeis enan counter gia tous xaraktires kai meta na ksekinas apo mia thesi pio prin wste na to kaneis rewrite? oute temp pou sou trwne xwro oute tpt...de kserw an ginetai de prolavainw na to psaksw giati den exw xrono alla de mou fenetai toso apithano.... elpizw na voithisa
ThomasD Δημοσ. 25 Ιανουαρίου 2005 Μέλος Δημοσ. 25 Ιανουαρίου 2005 Ki ego free tin pira apo to Panepistimio se CD me diafora programmata alla MSDN den exei. Ti na po, de ksero poios o logos na mi to exei. Mexri na to vro anagkastika tha psaxno apo edo kai apo kei. Auto me to rewrite na sou po den to eixa skeftei. Sosto mou fainetai alla stin periptosi mou de mporo na to xrisimopoiiso giati thelo kathe eggrafi na ginetai sto telos. Tha dokimaso kai sto IRC an den petixo kati. Se euxaristo poli gia tis simvoules!
Directx Δημοσ. 25 Ιανουαρίου 2005 Δημοσ. 25 Ιανουαρίου 2005 Μιας και έχω ξανά ακούσει ερωτήματα για το πώς διαγράφουμε μια συγκεκριμένη γραμμή από ένα αρχείο κειμένου αποφάσισα να σχεδιάσω ένα πρόγραμμα που κάνει αυτή την δουλεία στην μνήμη του υπολογιστή εξαλείφοντας την ανάγκη για temporary αρχείο. Η φιλοσοφία του είναι απλή και έχει αναφερθεί πιο πάνω, με δυο λόγια, το πρόγραμμα φορτώνει το κείμενο στην μνήμη του υπολογιστή, ύστερα εντοπίζει την διεύθυνση που αρχίζει και τελειώνει η γραμμή στην μνήμη και αντιγράφει τα αμέσως επόμενα στοιχεία στην διεύθυνση αρχής της προς διαγραφή γραμμής, εάν διαγράφουμε την τελευταία γραμμή τότε απλά μειώνει το μέγεθος της μνήμης μέχρι την διεύθυνση που αρχίζει η προς διαγραφή γραμμή οπότε την εξαλείφει πλήρως. Για να διευκολύνω την παραπάνω διαδικασία έχω σπάσει το «ζητούμενο» σε 5 απλές C ρουτίνες + main που τις χρησιμοποιεί, η σχεδίαση τους είναι γρήγορη (1,5-2 ώρες σύνολο + debug) και ενστικτώδης, οπότε τα λάθει καραδοκούν (!!) Ως παραμέτρους δέχεται το αρχείο που θα επεξεργαστούμε και την τιμή της γραμμής που θα διαγράψουμε (1 = πρώτη γραμμή κτλ). Γράφει τα αποτελέσματα στο αρχείο DUMP.TXT (για καλύτερο & ασφαλέστερο debugging) Το πρόγραμμα έχει σχεδιασθεί σε C/C++ Builder 6 για Windows console environment (32bit) και δεν έχει περάσει εξαντλητικό debug (το δοκίμασα με ένα μικρό ενδεικτικό αρχείο “INPUT.TXT” και ένα μεγαλύτερο ASCII text) οπότε μπορεί να έχει σφάλματα.. επίσης σίγουρα μπορεί να γραφθεί πιο αποδοτικά σε μορφή C++ αλλά δεν έχω περισσότερο κέφι & χρόνο για αυτό.. Τα σχόλια (comments) ελπίζω να είναι κατανοητά καθώς καμία φορά είναι πιο εύκολο να γράψεις C παρά να την εξηγήσεις λεπτομερώς ;-) * Κάποια λάθει τελευταίας στιγμής που εντόπισα τα έχω επισημάνει ως BUGFIX * Δεν παρέχω υποστήριξη κανενός είδους.. ..Ελπίζω να φάνει χρήσιμο κάπου.. Καλή τύχη!! > // DELETE FILE LINE IN-MEMORY EXAMPLE (c) 2005 by Directx #include <stdio.h> #include <stdlib.h> #include <mem.h> #include <io.h> #define BYTE unsigned char BYTE* LoadTextFile (char* pszFilename,long *FileLen); long CountFileLines (BYTE* MemoryBuffer,long lMemLen); long GetLineMemAddr (BYTE* MemoryBuffer,long lMemLen,long lLineIndex); void RemoveLine (BYTE* MemoryBuffer,long *lMemLen,long lLineIndex); int DumpMem (char* pszFilename,BYTE* MemoryBuffer,long lMemLen); BYTE* LoadTextFile(char *pszFilename,long *lFileLen) { // Επιστροφή του αρχείου pszFilename ως BYTE* (unsigned char*) memory block FILE *Stream; BYTE *byMemory = NULL; if((Stream=fopen(pszFilename,"rb"))!=NULL) { if(((long)*lFileLen=filelength(fileno(Stream)))!=-1L) { if((byMemory=(BYTE*)malloc((long)*lFileLen+1))!=NULL) { //+1=> Μετράμε και το κρυφό EOF memset(byMemory,0,(long)*lFileLen+1); if(fread(byMemory,(long)*lFileLen,1,Stream)==1) { fclose(Stream); return byMemory; } } } } if(byMemory!=NULL){ free(byMemory); } fclose(Stream); return NULL; } long CountFileLines(BYTE* MemoryBuffer,long lMemLen) { /* Η συγκεκριμένη ρουτίνα επιστρέφει των αριθμώ των διαθέσιμων γραμμών του MemoryBuffer, εντοπίζοντας του "New Line" χαρακτήρες. Τίποτε το ιδιαίτερο.. */ long lNewLines = 0, lMemAddr; for(lMemAddr=0;lMemAddr<=lMemLen;lMemAddr++) { if(MemoryBuffer[lMemAddr]=='\n'){ lNewLines++; } } return lNewLines; } long GetLineMemAddr(BYTE* MemoryBuffer,long lMemLen,long lLineIndex) { /* Η συγκεκριμένη ρουτίνα επιστρέφει την θέση του "New Line" χαρακτήρα που αντιστοιχεί στην προς ανεύρεση γραμμή που θέλουμε (lLineIndex). Το μέτρημα ομολογώ πως το σχεδίασα κάπως "ανορθόδοξα" καθώς η ρουτίνα επιστρέφει το New Line που τελειώνει η γραμμή πράγμα που κάποιος άλλος μπορεί να θεωρήσει πως ανήκει στην επόμενη γραμμή. Έτσι για παράδειγμα εάν έχουμε 4 γραμμές και θέλουμε το New Line της 3ης τότε: 1]LINE 1<nl> | 2]LINE 2<nl> | 3]LINE 3<nl><+-->Θα επιστραφεί αυτό το New Line ως της Line 3 4]LINE 4<nl> όσο το σκέφτομαι δεν μου αρέσει αλλά κάθισε καλά (οκ, δουλεύει όμορφα με την RemoveLine).. */ long lNewLine = 0, lMemAddr; for(lMemAddr=0;lMemAddr<=lMemLen;lMemAddr++) { if(MemoryBuffer[lMemAddr]=='\n') { if(++lNewLine==lLineIndex) { return lMemAddr; } } } return -1; } void RemoveLine(BYTE* MemoryBuffer,long *lMemLen,long lLineIndex) { /* ΠΡΟΣΟΧΗ: Αυτός ο κώδικας χρησιμοποιεί την lMemLong ως Pointer καθώς η συγκεκριμένη μεταβλητή θα αλλάξει ύστερα από την κλήση της ρουτίνας ανταποκρινόμενη στο νέο μέγεθος της μεταβλητής MemoryBuffer. Στα πλαίσια αυτά όταν θέλουμε να επεξεργαστούμε την τιμή lMemLen πρέπει να κάνουμε cast long pointer οπότε και (long)*lMemLen διαφορετικά ο compiler επιστρέφει την διεύθυνση μνήμης του pointer μας και όχι την αποθηκευμένη τιμή.. */ long lLineIndexAddrA, lLineIndexAddrB, lMemRangeToCopy; /* Ας βρούμε την Αρχή της γραμμής που επιθυμούμε να διαγράψουμε από την μνήμη. Για να το πετύχουμε αυτό, ζητάμε από την GetLineMemAddr να μας επιστρέψει τον 'new line' χαρακτήρα της προηγούμενης γραμμής (-1) οπότε προσθέτοντας +1 στην επιστρεφόμενη τιμή συναντάμε τον πρώτο χαρακτήρα της προς διαγραφή γραμμής.. */ lLineIndexAddrA = GetLineMemAddr(MemoryBuffer,(long)*lMemLen,lLineIndex-1)+1; /* Για να βρούμε το τέλος της γραμμής αναζητούμε τον τελευταίο "New Line" χαρακτήρα της προς διαγραφή γραμμής και προσθέτουμε +1 ώστε να βρούμε τον πρώτο χαρακτήρα της επόμενης γραμμής (εάν υπάρχει διαφορετικά αφού η (GetLineMemAddr=-1) +1 = 0).. */ lLineIndexAddrB = GetLineMemAddr(MemoryBuffer,(long)*lMemLen,lLineIndex)+1; /* Ειδική περίπτωση: Εάν η γραμμή που θέλουμε να σβήσουμε είναι η τελευταία, συνεπώς δεν υπάρχει άλλος "New Line" χαρακτήρας μετά από αυτήν η GetLineMemAddr επιστρέφει μηδέν οπότε δεν μπορεί να βοηθήσει. Σε αυτή την περίπτωση απλά απελευθερώνουμε τόση μνήμη όσο είναι ο αριθμός Bytes που ακολουθούν μετά την προτελευταία γραμμή (ο αριθμός εντοπίζεται με αφαίρεση αυτών των Bytes από το σύνολο των Bytes της δεσμευμένης μνήμης). */ if(CountFileLines(MemoryBuffer,(long)*lMemLen)+1==lLineIndex) { lMemRangeToCopy=(long)*lMemLen-lLineIndexAddrA; MemoryBuffer=realloc(MemoryBuffer, (long)*lMemLen-=lMemRangeToCopy); return; } // Υπολογίζουμε το μέγεθος των στοιχείων που θα αντιγράψουμε lMemRangeToCopy=(long)*lMemLen-lLineIndexAddrB; /* Αντιγράφουμε την διεύθυνση Αρχής της γραμμής που ακολουθεί την γραμμή προς διαγραφή στην διεύθυνση αρχής της διαγραφόμενης γραμμής.. */ memcpy(&MemoryBuffer[lLineIndexAddrA],&MemoryBuffer[lLineIndexAddrB], lMemRangeToCopy); /* Επαναπροσδιορίζουμε το μέγεθος μνήμης του MemoryBuffer ώστε να εξαλείψουμε τα διπλά στοιχεία (κλώνοι) που τώρα έχουν αντιγραφθεί στην διεύθυνση &MemoryBuffer[lLineIndexAddrA].. */ MemoryBuffer=realloc(MemoryBuffer,(long)*lMemLen-=(lLineIndexAddrB-lLineIndexAddrA)); /* Εάν όλα έχουν πάει καλά το MemoryBuffer περιέχει τα στοιχεία μας πλην την γραμμή που διαγράψαμε, διαφορετικά όλο και κάποιο memory error (null pointer termination κτλ) θα φανεί */ } int DumpMem(char* pszFilename,BYTE* MemoryBuffer,long lMemLen) { /* Γράφουμε στο αρχείο pszFilename την μεταβλητή MemoryBuffer μεγέθους lMemLen */ FILE *Stream; if((Stream=fopen(pszFilename,"wb"))!=NULL) { /* BUGFIX Τελευταίας στιγμής: Δεν υπάρχει τίποτε να γράψουμε οπότε απλά μηδενίζουμε το αρχείο.. "Πονηρές" περιπτώσεις όπου σβήνουμε την μοναδική γραμμή.. */ if(!lMemLen) { fclose(Stream); return 0; } if((fwrite(MemoryBuffer,lMemLen,1,Stream))==1) { fclose(Stream); return 1; } fclose(Stream); } return 0; } //////////////////////////////////////////////////// BYTE *byFile; long lFileLen, lFileLines, lLineToRemove; void main(int argc,char *argv[]) { // Έλεγχος παραμέτρων if(argc<3) { printf(" Usage: filename line-number-to-remove\n"); return; } // Δεν δεχόμαστε μηδέν (μετράμε από 1 έστω και αν είμαστε C/C++ fans) if(!(lLineToRemove=atol(argv[2]))) { printf(" Zero is an Invalid line number specifier!!\n"); return; } // Φόρτωμα αρχείου στην μνήμη.. if((byFile=LoadTextFile(argv[1],&lFileLen))==NULL) { printf(" Error loading file - %s\n",argv[1]); return; } // Μέτρηση διαθέσιμων γραμμών (πληροφοριακά) if(!(lFileLines=CountFileLines(byFile,lFileLen))) { printf(" File does not containe any lines - %s\n",argv[1]); return; } printf(" Lines found: %ld\n",lFileLines); // Διαγραφή γραμμής RemoveLine(byFile,&lFileLen,lLineToRemove); // Εγγραφή επεξεργασμένης μνήμης if(!DumpMem("DUMP.TXT",byFile,lFileLen)) { printf(" Memory dump failed - %s\n",argv[1]); } /* Αποδέσμευση μνήμης.. BUGFIX Τελευταίας στιγμής: "Πονηρές" περιπτώσεις όπου έχοντας σβήσει την μοναδική γραμμή το realloc έχει ήδη απελευθερώσει ως 0 το memory block.. */ if(lFileLen>0){ free(byFile); } } INPUT.TXT: > LINE 1 LINE 2 LINE 3 LINE 4 Υ.Γ. Θεωρώ πως το παλιό forum είχε μακράν καλύτερη υλοποίηση για τα στοιχεία εντός Code /Code blocks :sad:
ThomasD Δημοσ. 25 Ιανουαρίου 2005 Μέλος Δημοσ. 25 Ιανουαρίου 2005 Να 'σαι καλά Directx! Αύριο που θα έχω χρόνο θα το ελέγξω. Σε ευχαριστώ πολύ!
Προτεινόμενες αναρτήσεις
Αρχειοθετημένο
Αυτό το θέμα έχει αρχειοθετηθεί και είναι κλειστό για περαιτέρω απαντήσεις.