Push-Nachrichten von MacTechNews.de
Würden Sie gerne aktuelle Nachrichten aus der Apple-Welt direkt über Push-Nachrichten erhalten?
Forum>Entwickler>C++: Tutorial für den Umgang mit Streams und Strings gesucht.

C++: Tutorial für den Umgang mit Streams und Strings gesucht.

andreas_g
andreas_g23.06.2120:41
Liebe Community,

ich suche ein Tutorial zum Thema Streams und Strings in C++. Ich beherrsche zwar C, aber leider kein C++ und habe ein konkretes Problem zu lösen:

In einer Textdatei sind mehrere Zeilen vorhanden. Diese bestehen jeweils aus Parameter und Wert, getrennt durch "=". Nun soll kontrolliert werden, ob den Parametern jeweils die richtigen Werte zugeordnet sind. Ist dies nicht der Fall, soll korrigiert werden.

Beispiel:
Dem Parameter HOSTNAME soll der Wert -AUTOMATIC- zugeordnet sein:
HOSTNAME=-AUTOMATIC-

Nun gibt es vier mögliche Szenarien:
HOSTNAME=-AUTOMATIC-
Wert bereits korrekt > keine Aktion

HOSTNAME=
Kein Wert zugeordnet > Wert ergänzen

HOSTNAME=nobody
Falscher Wert zugeordnet > Wert korrigieren


Der Parameter fehlt > Parameter und Wert ergänzen

Erschwerend kommt hinzu, dass die Funktionalität in ein vorliegendes Programm eingebaut werden soll. Der Quelltext ist hier:

Die Funktion "bool NBTHostConfig::run(std::ofstream& out)" erzeugt aktuell eine neue Datei, soll aber eine bestehende lesen und anpassen, damit keine nicht betroffenen Werte verloren gehen.

Folgende Zeilen sollen schlussendlich enthalten sein:
HOSTNAME=-AUTOMATIC-
INETADDR=-AUTOMATIC-
ROUTER=-ROUTED-
IPNETMASK=-AUTOMATIC-
IPBROADCAST=-AUTOMATIC-

Wenn jemand einen guten Tipp hat (oder eine fertige Lösung ), bitte eine Nachricht posten. Freue mich auf eure Rückmeldungen!
0

Kommentare

milk
milk23.06.2121:01
andreas_g
Ich beherrsche zwar C, aber leider kein C++
Wenn es dir nur um eine einzelne Funktion geht, dann kannst du dir die doch in C schreiben und wie folgt in C++ einbauen:

extern "C" void foo(int);
0
andreas_g
andreas_g23.06.2121:06
milk
andreas_g
Ich beherrsche zwar C, aber leider kein C++
Wenn es dir nur um eine einzelne Funktion geht, dann kannst du dir die doch in C schreiben und wie folgt in C++ einbauen:

extern "C" void foo(int);
Ich bin mir nicht sicher, ob das hier so ohne Weiteres funktioniert wegen dem bestehenden Code. Die C-Funktion müsste dann wohl mit dem Stream umgehen können. Außerdem wäre das wohl nicht besonders elegant. Ich würde eine der Struktur entsprechende Funktion in C++ bevorzugen.
0
milk
milk23.06.2121:15
Na dann:
0
gfhfkgfhfk23.06.2123:50
andreas_g
Liebe Community,

ich suche ein Tutorial zum Thema Streams und Strings in C++. Ich beherrsche zwar C, aber leider kein C++ und habe ein konkretes Problem zu lösen:

In einer Textdatei sind mehrere Zeilen vorhanden. Diese bestehen jeweils aus Parameter und Wert, getrennt durch "=". Nun soll kontrolliert werden, ob den Parametern jeweils die richtigen Werte zugeordnet sind. Ist dies nicht der Fall, soll korrigiert werden.
Das C++ Programm schreibt den Zustand des Programms in die Datei, d.h. Du musst die Stelle ändern, an der Zustand des Objekts falsch gesetzt wird, bzw. eingelesen wird.
0
andreas_g
andreas_g24.06.2100:17
Danke für alle Tipps! Das Problem ist gelöst:

bool NBTHostConfig::preRun(VirtualFS& vfs) {
    try {
        string templateconfig = "/usr/template/client/etc/hostconfig";
        ifstream in(vfs.toHostPath(templateconfig).string());
        if(!(in)) return false;
        
        string router = "ROUTER";
        string netmask = "IPNETMASK";
        
        cout << endl;
        cout << "- using template " << templateconfig << endl;
        
        for(string line; getline(in, line);) {
            if(line.compare(0, router.size(), router) == 0 ||
               line.compare(0, netmask.size(), netmask) == 0) {
                cout << "- removing " << line << endl;
                continue;
            }
            lines.push_back(line);
        }
        in.close();
        
        return true;
    } catch(exception& e) {
        cout << e.what() << endl;
        return false;
    }
}

bool NBTHostConfig::run(std::ofstream& out) {
    for(size_t line = 0; line < lines.size(); line++)
        out << lines[line] << '\n';
    addParameter(out, "ROUTER", "-ROUTED-");
    addParameter(out, "IPNETMASK", "-AUTOMATIC-");
    return true;
}

void NBTHostConfig::addParameter(ofstream& out, const std::string& param, const std::string& val) {
    cout << "- adding " << param << "=" << val << endl;
    out << param << "=" << val << '\n';
}

Ein Teil des Problems wird durch die Nutzung des Template gelöst, die verbleibenden problematischen Parameter werden entfernt und dann korrekt wieder hinzugefügt.
+1
gfhfkgfhfk24.06.2113:53
Der zuerst verlinkte Code ist aus C++ Sicht etwas merkwürdig, und was Du hier nun postest ergibt ohne Kontext wenig Sinn.
0
milk
milk24.06.2113:58
gfhfkgfhfk
Der zuerst verlinkte Code ist aus C++ Sicht etwas merkwürdig
Das, was Andreas in seinem Ursprungsposting gezeigt hat, ist der Inhalt der /etc/hostconfig Datei von NEXTSTEP. Schon okay, dass das so aussieht.
0
gfhfkgfhfk24.06.2114:53
milk
Das, was Andreas in seinem Ursprungsposting gezeigt hat, ist der Inhalt der /etc/hostconfig Datei von NEXTSTEP. Schon okay, dass das so aussieht.
Nein, es geht nicht um den Inhalt der Datei, sondern um den C++ Code, der ihn schreibt. Wer schreibt denn bitte C++ Code bei dem nach den Strings nochmals ein "<<' \n' " folgt? Man kann das ganze als eine Ausgabe mit einem String schreiben in dem man
out << "string1\n"
     "string2\n"
     "string3\n"
     "string4\n";
verwendet, und dann erwartet man dann eher, dass dieser code als operator<< definiert wird. Im neuen Code sind alte Schleifen (nun Andreas kennt kein C++ – man merkt es daran) anstatt neuer enthalten. Weshalb ist die main() Funktion als extern C deklariert? usw.
0
andreas_g
andreas_g24.06.2116:58
Das Programm, zu dem das betroffene Tool gehört, ist überwiegend in C geschrieben. Vielleicht war ursprünglich angedacht, das Tool zu integrieren. Was ist mit "alten Schleifen" gemeint?

Insgesamt soll der Code in erster Linie seinen Zweck erfüllen. Das ganz große Problem sehe ich jetzt beispielsweise bei out << "string\n" vs. out << string << '\n' nicht. Aber wie gesagt hätte ich auch nichts gegen eine fertige Lösung einzuwenden gehabt

Jedenfalls erfüllt der Code seinen Zweck und extrahiert Dateien aus einem Image mit NeXTstep (UFS) in einen Ordner und patcht die Konfiguration, so dass aus dem Ordner NeXTstep via simuliertem NFS-Server, simuliertem Router und simulierter Ethernet-Schnittstelle netbooten kann. Der Vorteil dabei ist, dass das gesamte Dateisystem von NeXTstep vom Host aus zugänglich ist und dadurch der Datenaustausch wesentlich vereinfacht wird.

Außerdem ist nun das Gefühl der Unvollständigkeit weg, nachdem NeXTstep jetzt via simulierter Floppy, SCSI-Festplatte, magneto-optical Disk und Ethernet (thin und twisted pair) gebootet werden kann
+1
gfhfkgfhfk25.06.2123:29
andreas_g
Das Programm, zu dem das betroffene Tool gehört, ist überwiegend in C geschrieben. Vielleicht war ursprünglich angedacht, das Tool zu integrieren.
Du kannst in einem Programm immer nur eine main Funktion haben, und wenn die C++ extern "C" deklariert wurde, dann hat sie exakt das gleiche Linkage wie die C main Funktion, d.h. so kannst Du den Code nicht in einem C Programm nutzen. Dafür läuft man Gefahr, dass durch das falsche Linkage globale Objekte z.B. in der Laufzeitbibliothek nicht korrekt initialisiert oder abgeräumt werden. C++ fügt nämlich ggf. Code in das Programm ein, der bereits vor der main() Funktion ausgeführt wird und auch danach!
andreas_g
Was ist mit "alten Schleifen" gemeint?
Es gibt in C++ zig Varianten wie man effektiv und sicher über Container iterieren sollte. Die Version, die Du da gewählt hast zählt nicht mehr dazu. Zwei Varianten wie man über einen Container iterieren kann.
#include <string>
#include <vector>
#include <iostream>
#include <cstdlib>

int main () {
    std::vector<std::string> sv = {"a", "b", "c"};

    std::cout << "for loop\n";
    for (auto s: sv) {
        std::cout << s << "\n";
    }

    std::cout << "\nLambda\n";
    auto print_vector = [](std::string &s) { std::cout << s << "\n"; };

    std::for_each (sv.begin(), sv.end(), print_vector);


    return EXIT_SUCCESS;
}
andreas_g
Insgesamt soll der Code in erster Linie seinen Zweck erfüllen. Das ganz große Problem sehe ich jetzt beispielsweise bei out << "string\n" vs. out << string << '\n' nicht. Aber wie gesagt hätte ich auch nichts gegen eine fertige Lösung einzuwenden gehabt
Es ist eher unsauberer Stil, und für eine fertige Lösung fehlt einfach Kontext.
0
andreas_g
andreas_g26.06.2117:04
gfhfkgfhfk
Es ist eher unsauberer Stil, und für eine fertige Lösung fehlt einfach Kontext.
Den Quelltext hatte ich ja eingangs verlinkt. Er ist frei zugänglich, kann gelesen oder ausprobiert werden. Ich hätte vielleicht noch erwähnen sollen, dass der Code wegen den Zielplatformen nicht über C++11 hinausgehen soll.
0
gfhfkgfhfk26.06.2120:36
andreas_g
Den Quelltext hatte ich ja eingangs verlinkt. Er ist frei zugänglich, kann gelesen oder ausprobiert werden. Ich hätte vielleicht noch erwähnen sollen, dass der Code wegen den Zielplatformen nicht über C++11 hinausgehen soll.
Kontext ist nicht nur die eine Datei sondern soviel, dass man das Programm übersetzen kann. Der Versuch der wenigen Doku zu folgen und das Repository zu clonen war ich natürlich. Nur da gab es dann ganz anderen Sourcecode in dieser Datei.

Das Beispiel funktioniert problemlos mit einem C++11 Compiler, wenn man einen fehlenden "#include<algorithm>" ergänzt. Sorry ich nutze für private Dinge mittlerweile den gcc 11.1.0 mit C++20 Vorgabe, da wird der Code direkt übersetzt.
0

Kommentieren

Diese Diskussion ist bereits mehr als 3 Monate alt und kann daher nicht mehr kommentiert werden.