Autor Thema: C++: Bestimmten String aus Datei lesen  (Gelesen 8480 mal)

DarkThing

  • Beiträge: 652
    • Profil anzeigen
Gespeichert
« am: 04. May 2005, 17:43 »
Ka ob das hier reingehört weil es nichts mit OS Dev zu tun hat sondern eher mit C++ & fstream. Aber man kanns ja mal versuchen.
Also, ich habe eine Datei in der zum Beispiel folgendes steht (nur ein Beispiel):

Testtext
#abc Test.
Hallo

Jetzt möchte ich die Datei Byte für Byte lesen und in einen Outputfile schreiben. Wenn das aktuelle Zeichen aber ein # ist möchte ich die nächsten 4 Bytes auch lesen und checken ob da "abc " steht. Wenn nicht soll das #-Zeichen und die gelesenen 4 Bytes unverändert in die Output Datei geschrieben werden und normal weitergemacht werden. Wenn aber in der Datei "#abc " steht und das erkannt wurde möchte ich alle Zeichen bis zum Punkt in einen neuen String schreiben und den ganzen Teil nicht in die Outputdatei schreiben. Ich hab einen Pointer auf die Inputdatei und einen Pointer auf den Outputfile.

Ich weiß die Erklärung ist nicht gerade top, also wenn jemand Fragen dazu hat werd ich die beantworten (eigentlich logisch ^^).

Der Code bisher:

char ch;
char tmp[4];
char *str;
while(!FileIn->eof())
{
// Zeichen lesen
ch = FileIn->get();

// Wenn Zeichen kein # ist, einfach speichern
if(ch != '#')
{
FileOut->put(ch);
} else {
// Zeichen ist ein #

// Nächsten 4 Zeichen lesen
FileIn->read(&tmp[0], 4);
tmp[4] = '\0';

// Wurde abc erkannt
if(strcmp(tmp, "abc ") == 0)
{
// String dahinter ermitteln
while(ch != '.')
{
ch = FileIn->get();
*str++ = ch;
}
*str= '\0';
// Zum Debuggen String anzeigen
cout << file << endl;
} else {
// Nein, also alles bisher gelesene speichern...
FileOut->put('#');
FileOut->write(tmp, 4);
// ...und weitermachen
continue;
}
}
}

DarkThing

  • Beiträge: 652
    • Profil anzeigen
Gespeichert
« Antwort #1 am: 05. May 2005, 14:31 »
Keiner ne Idee?
Wegen dem Code nochma: Manchmal stürzt das Prog ab, aber ansonsten wird immer der else-Teil vom zweiten if-statement abgearbeitet. Wenn irgendwer nur ne Idee im Ansatz hat oder das ganze völlig anders machen würde, würd mir das auch schon seht helfen.

Jidder

  • Administrator
  • Beiträge: 1 625
    • Profil anzeigen
Gespeichert
« Antwort #2 am: 05. May 2005, 16:09 »
hm ich hab gedacht der code sollte so eine art tutorial sein, weil du keine frage gestellt hast.

also was mir auffällt:

tmp ist 4 bytes groß, aber du schreibst auch in tmp[4] (das ist das 5. byte) was rein. -> buffer overflow

str ist ein zeiger auf einen char, aber du initialierst str nicht. deswegen wird ein x-beliebiges stück memory bei *str++ = ch; und *str= '\0';  getrasht -> noch eine art buffer overflow
Dieser Text wird unter jedem Beitrag angezeigt.

DarkThing

  • Beiträge: 652
    • Profil anzeigen
Gespeichert
« Antwort #3 am: 06. May 2005, 11:53 »
Hab beides eingebaut. Die Abstütze sind logischerweise weg, aber es geht immer noch nicht. In der Zeile
if(strcmp(tmp, "abc ") == 0)
Wird nie erkannt das in tmp abc steht. Das muss aber eigentlich bei der Beispieldatei einmal kommen.

@Tutorial-Code: Der Code hat ja so keine echte verwendbare Funktion. Aber daraus wird noch was.

stultus

  • Beiträge: 486
    • Profil anzeigen
Gespeichert
« Antwort #4 am: 06. May 2005, 13:56 »
kann es evtl. sein das der zweite string ("abc ") nicht automatisch nullterminiert wird? sowas in der art könnt ich mir ganz gut vorstellen...
MSN: planetconquestdm@hotmail.de
ICQ: 190-084-185

... Wayne?

DarkThing

  • Beiträge: 652
    • Profil anzeigen
Gespeichert
« Antwort #5 am: 06. May 2005, 14:37 »
Hab ein \0 angehangen, geht aber trotzdem nicht. Ich hab jetzt auch mal versucht das tmp in einen Pointer umzubauen. Half aber auch nicht.

Svenska

  • Beiträge: 1 792
    • Profil anzeigen
Gespeichert
« Antwort #6 am: 06. May 2005, 20:24 »
Muss die Bedingung nicht umgekehrt werden?
*duckundwech* Kann kein C, geschweige denn Cpp

DarkThing

  • Beiträge: 652
    • Profil anzeigen
Gespeichert
« Antwort #7 am: 07. May 2005, 11:08 »
Also jetz bin ich beim besten willen überfordert. Wenn ich die Zeile in das hier änder: if(strcmp(tmp, "abc ") != 0) , also das ganze umdrehe, komm ich trotzdem nur in den else Teil.

DDR-RAM

  • Beiträge: 184
    • Profil anzeigen
Gespeichert
« Antwort #8 am: 07. May 2005, 14:08 »
Wie ist denn jetzt kein Problem?
Und was ist file?


// Zum Debuggen String anzeigen
cout << file << endl;

DarkThing

  • Beiträge: 652
    • Profil anzeigen
Gespeichert
« Antwort #9 am: 07. May 2005, 15:01 »
file muss natürlich str heißen.  :oops:
Das Problem ist, dass es nicht erkannt wird, wenn hinter einem #-Zeichen "abc " steht.

DDR-RAM

  • Beiträge: 184
    • Profil anzeigen
Gespeichert
« Antwort #10 am: 07. May 2005, 16:06 »

    ch = FileIn->get();


Wenn du auf Fehlermeldungen achten würdest, hättest du bemerkt, das hier etwas nicht stimmt. FileIn->get() gibt kein char zurück ;-)

es muss so heißen:

FileIn->get(ch);


Außerdem, wenn du str ausgibst gibst du nur dein letztes null-terminierungs zeichen aus. das willst du glaube ich nicht sehen ;-)

MfG
DDR-RAM

DarkThing

  • Beiträge: 652
    • Profil anzeigen
Gespeichert
« Antwort #11 am: 07. May 2005, 19:21 »
Da kommen keine Fehlermeldungen, nicht mal Warnungen. In der MSDN steht das das so geht wie ich es mache, und das kopieren von den Chars geht ja auch, aber der strcmp-Teil geht nicht. Das anzeigen wird ja auch erst dann interessant, wenn er überhaupt dahin kommt. Ehal, trotzdem thx.

DDR-RAM

  • Beiträge: 184
    • Profil anzeigen
Gespeichert
« Antwort #12 am: 08. May 2005, 01:21 »
Also ich hab deinen Code umgeschrieben und bei mir klappts ;-)

MfG
DDR-RAM

DarkThing

  • Beiträge: 652
    • Profil anzeigen
Gespeichert
« Antwort #13 am: 08. May 2005, 12:27 »
Was klappt? Nur das compilieren oder geht auch die Logik dahinter?
Wenn das Prog alles richtig macht bitte mal den Code posten, vielleicht hab ich ja was übersehen oder so.

DDR-RAM

  • Beiträge: 184
    • Profil anzeigen
Gespeichert
« Antwort #14 am: 08. May 2005, 13:02 »
Natürlich auch die Logik ;-)

Hier der Code:

/////////////////
// main.cpp

#include <iostream>
#include <fstream>

int main()
{
const char strAbc[] = "abc ";
const int nMaxStrAlloc = 100;

std::ifstream FileIn;
std::ofstream FileOut;

FileIn.open("in.txt");
FileOut.open("out.txt");

char ch;
char tmp[sizeof(strAbc)];
char *str = new char[nMaxStrAlloc + 1];

while(!FileIn.eof())
{
// Zeichen lesen
FileIn.get(ch);
       
// Wenn Zeichen kein # ist, einfach speichern
if(ch != '#')
{
FileOut.put(ch);
} else {
// Zeichen ist ein #
// Nächsten 4 Zeichen lesen
FileIn.read(&tmp[0], sizeof(tmp) - 1);
tmp[sizeof(tmp) - 1] = '\0';
// Wurde abc erkannt
if(strcmp(tmp, strAbc) == 0)
{
// String dahinter ermitteln
int i;
for (i = 0; ch != '.' && i < nMaxStrAlloc; i++)
{
FileIn.get(ch);
str[i] = ch;
}
str[i] = '\0';
// Zum Debuggen String anzeigen
std::cout << str << std::endl;
} else {
// Nein, also alles bisher gelesene speichern...
FileOut.put('#');
FileOut.write(tmp, 4);
// ...und weitermachen
continue;
}
}
}

FileOut.close();
FileIn.close();

delete [] str;

return 0;
}


Bei mir sind FileIn und FileOut übrigens keine Zeiger, deshalb nicht verwundern.

MfG
DDR-RAM

DarkThing

  • Beiträge: 652
    • Profil anzeigen
Gespeichert
« Antwort #15 am: 08. May 2005, 16:15 »
Thx! Werds bei mir einbauen und testen.

DarkThing

  • Beiträge: 652
    • Profil anzeigen
Gespeichert
« Antwort #16 am: 09. May 2005, 19:01 »
Geht perfekt. Thx!! Ich hab aber noch ne Kleinigkeit gefunden: Der Punkt wird bei str mit hinten dran gehangen. Lässt sich aber so beheben: (letzte Zeile):

// String dahinter ermitteln
int   i;
for (i = 0; ch != '.' && i < nMaxStrAlloc; i++)
{
    FileIn.get(ch);
    str[i] = ch;
}
str[i-1]   = '\0';

 

Einloggen