Problem beim Datei einlesen und Werte zurückgeben

LadyMarion

Mitglied
Hallo,

ich möchte gerne folgendes machen:

Ich habe mehrere Dateien, die eingelesen werden sollen. Die Dateien enthalten Variablen, mit denen anschließend weiter gerechnet werden soll.

Dafür habe ich in der Klasse "test" eine allgemeine read-Funktion zur Verfügung, die alle Dateien einfach nur einliest, sowie eine find-Funktion, die mir anhand eines Schlüsselwortes den jeweiligen Wert zurückgibt.
Früher waren die read- und die find-Funktion in einer zusammengefasst, jetzt wollte ich die Funktionen aber aufteilen, so dass es nur noch eine einzige read-Funktion im ganzen Programm gibt und nur die find-Funktion je nach Datei anders aussieht.

In der main-Funktion rufe ich also folgende Funktionen auf:
Code:
int main()
{
    test frage;
    frage.read("datei.txt");
    frage.find("ABC");
    return 0;
}

Die read-Funktion könnte dann ja so aussehen:
Code:
bool test::read(const string dateiname)
{
    ifstream IN;
    IN.open (dateiname.c_str());
    if (IN.good())
    {
        string zeile;
        while (getline(IN, zeile))
        {
            if (!zeile.empty())
            {
                return true;
            }
        }
    }
    else
    {
        cout<<"FEHLER\n";
        return false;
    }
    IN.close();
}

In der find-Funktion werden später dann mehrere Fälle für die unterschiedlichen Dateien unterschieden, aber bis jetzt sieht es so aus:
Code:
const double test::find(const string& schluesselwort) const
{
    string zeile;
    double wert;
    if (zeile.find(schluesselwort) != string::npos)
    {
        // hier wird dann die entsprechende Zeile zerlegt und der Wert herausgeschrieben
        return wert;
    }
}
Wie muss ich denn jetzt die beiden Funktionen "verknüpfen", dass es dann auch funktioniert? Denn bis jetzt weiß ja die find-Funktion nicht, wo sie eigentlich nach dem Schlüsselwort suchen soll...

Vielen Dank schon mal!
 
Hallo,

du must die eingelesenen Zeilen irgendwo speichern und diese Daten dann an die "find()"-Funktion übergeben. Dafür könntest du z.B. die Klasse "vector" verwenden.

Gruß
MCoder
 
Erstmal danke.

Geht das nur mit vector, oder kann ich die Zeilen nicht auch einfach in einem string speichern?

Code:
bool test::read(const string dateiname)
{
    ifstream IN;
    IN.open (dateiname.c_str());
    if (IN.good())
    {
        string zeile;
        while (getline(IN, zeile))
        {
            if (!zeile.empty())
            {
                test::bsp = line;
            }
        }
        return true;
    }
    else
    {
        cout<<"FEHLER\n";
        return false;
    }
    IN.close();
}


Dementsprechend heißt es dann in der find-funktion:
...
if (test::bsp.find(schluesselwort) != string::npos)
...

Nur wenn ich das so mache, dann steht in dem string "bsp" natürlich nur die letzte Zeile. Geht das nicht auch, dass ich alle Zeilen zur Verfügung hab?
 
Geht das nur mit vector, oder kann ich die Zeilen nicht auch einfach in einem string speichern?
Du kannst die Zeilen natürlich in jeder Form speichern, die du als sinnvoll erachtest (und die technisch machbar ist).
Falls die Zeilen nur aus einem Wort bestehen (etwa dem Variablennamen) kann man auch vernünftig damit arbeiten, wenn alles in einen einzigen String abgelegt wird. Sind die Zeilen selbst noch irgendwie strukturiert, ist es aber besser, diese auch separat zu speichern, weil damit die spätere Verabeitung einfacher wird.

Bei deinem Code musst du die einzelnen Zeilen zum Zielstring aufaddieren:
C++:
bool test::read(const string dateiname)
{
    ifstream IN;
    IN.open (dateiname.c_str());
    if (IN.good())
    {
        test::bsp = "";
    
        string zeile;
        while (getline(IN, zeile))
        {
            if (!zeile.empty())
            {
                test::bsp += (" " + line); // Aufaddieren mit einem Leerzeichen als Trennzeichen
            }
        }
        return true;
    }
    else
    {
        cout<<"FEHLER\n";
        return false;
    }
    IN.close();
}
Gruß
MCoder
 
Zuletzt bearbeitet von einem Moderator:
Ok, danke. Das ist mir jetzt soweit klar. Aber irgendwie funktioniert das so auch nicht...

Die Dateien, die gelesen werden sollen, sind verschieden, sowohl in der Zeilen-, als auch in der Spaltenanzahl. Deshalb wollte ich in der read-Funktion die Datei einfach nur komplett einlesen und dann je nachdem in der find-Funktion nach dem entsprechenden Wert suchen.

Eine Datei sieht z.B. so aus:
ABC|1.2|Kommentar
Über das Schlüsselwort ABC will ich also an den Wert 1.2 kommen, was in der find-Funktion auch funktioniert.

Eine andere Datei sieht nun aber so aus:
AB CD EF GH
1.2 3.2 3.4 a
3.4 4.5 4.8 b
Hier werden, abhängig von einem bestimmten "GH" (hier also a oder b), die anderen Werte in der Zeile eingelesen, was in der find-Funktion auch bereits funktioniert.

Nur funktioniert es eben nicht, dass ich alle Zeilen einlese, ich habe immer nur die letzte Zeile. Ich weiß jetzt grad echt nicht, wie ich das mit einem Vector realisieren kann.
Könnt Ihr mir da vielleicht etwas auf die Sprünge helfen?
 
Hallo,

eigentlich sollte bei der Addition alles in einer Zeile stehen :confused:

Hier ist jedenfalls mal bein Beispiel für die Anwendung eines Vectors. Ich habe auch mal deine Lesefunktion etwas modifiziert, da etwa das "IN.close();" nie aufgerufen wurde.
C++:
// Einlesen
bool test::read(const string dateiname, vector<string>& lines)
{
    ifstream IN(dateiname.str());
    
    if( IN.is_open() )
    {
        string zeile;
        
        while( getline(IN, zeile) )
        {
            if( !zeile.empty() )
            {
                lines.push_back(zeile);
            }
        }
        
        IN.close();
        return true;
    }
    else
    {
        return false;
    }        
}

// Suchen
bool test::find(string str, vector<string> lines)
{
    vector<string>::iterator it;
    
    for( it = lines.begin(); it != lines.end(); ++it )
    {
        string strLine = *it;
        
        if( ... ) // TODO: Zeile auswerten
        {
            return true;
        }    
    }

    return false;
}

// Anwendung
vector<string> lines;    

if( read("C:\\datei.xyz", lines)
{
    if( find("ABC", lines) )
    {
        // ...
    }
}
Gruß
MCoder
 
Hallo,

erstmal vielen, vielen Dank für Deine Hilfe!

Ich hab das jetzt soweit eingebaut und es funktioniert auch alles. Jetzt hätte ich aber nochmal was :-(

Ich habe folgende Datei:
AB CD EF GH
1.2 3.2 3.4 a
3.4 4.5 4.8 b
9.8 7.4 2.4 c

Wenn ich hier jetzt nur eine bestimmte Zeile lesen will, dann muss ich doch die entsprechende Zeile als Parameter in der find-Funktion übergeben, oder?

Ich hab jetzt schon versucht, das an mehreren Stellen irgendwie unterzukriegen, aber irgendwie haut es nicht hin...

Code:
// Einlesen
bool test::read(const string dateiname, vector<string>& lines)
{
    ifstream IN(dateiname.str());
    
    if( IN.is_open() )
    {
        string zeile;
        
        while( getline(IN, zeile) )
        {
            if( !zeile.empty() )
            {
                lines.push_back(zeile);
            }
        }
        
        IN.close();
        return true;
    }
    else
    {
        return false;
    }        
}

// Suchen
bool test::find(string str, vector<string> lines, int i)
{
    vector<string>::iterator it;
    
    for( it = lines.begin(); it != lines.end(); ++it )
    {
        string strLine = *it;

        if (strLine == lines[i]) {
        
        if( ... ) // TODO: Zeile auswerten
        {
            return true;
        }    
        }

    }

    return false;
}

// Anwendung
vector<string> lines;    

if( read("C:\\datei.xyz", lines)
{
    if( find("ABC", lines, 2) )
    {
        // ...
    }
}

So erhalte ich jetzt zwar keine Fehlermeldung mehr beim Compilieren, aber die Werte werden auch nicht ausgegeben...

Wäre wirklich sehr dankbar, wenn ich nochmal ein bißchen Hilfe bekommen könnte...
 
Hallo,

wenn du schon weisst, welche Zeile du ansprechen willst, kannst du auf die Iteration durch den Vector (die for-Schleife) verzichten und die Zeile gleich über ihren Index ansprechen. Dafür würde ich eine separate find-Methode spendieren, die dann drei Parameter hat (Stichwort: Überladen von Methoden).

Bei der Anwendung der Vergleichsoperatoren zum String muss du darauf achten, was du erreichen willst:
C++:
if( strLine == lines[i] ) // strLine ist absolut IDENTISCH zu lines[i]
{

}

if( lines[i].find_first_of(strLine) ) // strLine ist in lines[i] enthalten
{

}

// usw.
Gruß
MCoder
 
Zurück