2017-07-15 3 views
1

Als ein Noob-C++ - Projekt erstelle ich ein CLI-Spiel mit einer Spielschleife, die auf Benutzereingaben beruht. Zu Testzwecken möchte ich gerne einen Dateinamen als Kommandozeilenargument an das Programm übergeben, das bis zum Durchlesen "wie Standardeingabe" behandelt wird.Objekt streamen, um die Dateieingabe und dann die Standardeingabe darzustellen?

Folglich brauche ich eine Möglichkeit, ein Objekt zu kapseln, die den Inhalt einer Datei darstellt und dannstd::cin sobald die Datei durch gelesen wurde - im Grunde den Inhalt einer Datei auf der Standardeingabe vorangestellt wird. Zumindest scheint dies wäre es sehr schön sein, so dass ich etwas mit wie

std::istringstream retrieve_input(std::ifstream &file) { 
    std::string line; 
    if (std::getline(file, line)) 
    return std::istringstream{line}; 
    std::getline(std::cin, line); 
    return std::istringstream{line}; 
} 

ersetzt dies mit irgendeiner Art von benutzerdefinierten Klasse ein guter Ansatz vermeiden kann? Oder kann ich mich irgendwie mit std::cin anlegen, um meinen Dateiinhalt voranzustellen?


Um zu verdeutlichen: Meine Spielschleife könnte sagen, 20 Iterationen. Wenn ich eine Datei mit fünf Zeilen übergebe, möchte ich diese fünf Zeilen für die ersten fünf Iterationen meiner Spielschleife verwenden und dann für die verbleibenden fünfzehn auf die Standardeingabe zurückgehen. Ich verstehe, wie man das mit einer Reihe von Bedingungen macht, aber ich denke, es muss einen Weg geben, um diese Art von Verhalten in einer Klasse zu haben. Mein Problem ist - was sollte es erben? std::streambuf? Ist das grundsätzlich eine gute Idee?

Mein (wahrscheinlich schlechter Versuch)

class InputGrabber { 
public: 
    virtual std::istringstream retrieve_line() = 0; 
    virtual ~InputGrabber() {} 
}; 

class BaseInputGrabber : public InputGrabber { 
public: 
    BaseInputGrabber(std::istream &_in): in{_in} {} 
    std::istringstream retrieve_line() override { 
    std::string line; 
    std::getline(in, line); 
    return std::istringstream{line}; 
    } 

private: 
    std::istream ∈ 
}; 

class VarInputGrabber : public InputGrabber { 
public: 
    VarInputGrabber(std::istream &_in, const std::string &f_name) : 
    in{_in}, init{std::ifstream(f_name)} {} 
    std::istringstream retrieve_line() override { 
    std::string line; 
    if (std::getline(init, line)) { 
     return std::istringstream{line}; 
    } 
    std::getline(in, line); 
    return std::istringstream{line}; 
    } 
private: 
    std::istream ∈ 
    std::ifstream init; 
}; 
+1

@Ron nicht zustimmen. Einige Standardbibliotheksklassen sollen vererbt werden. 'std :: streambuf' ist genau ein Beispiel. –

+1

@Ron Können Sie die Begriffe "einige" und "alle" unterscheiden? –

Antwort

2

Würde der unten Arbeit? Sie öffnen die Datei, umleiten std::cin, um aus der Datei zu lesen. Verwenden Sie std::getline auf std::cin, so dass es aus dem Dateistream liest. Einige Zeit vor dem Ende des Programms oder wenn die Datei gelesen wurde, stellen Sie std::cin in den ursprünglichen Zustand zurück.

#include <iostream> 
#include <fstream> 

int main(int argc, const char * argv[]) { 

    std::fstream file("https://stackoverflow.com/users/Brandon/Desktop/testingInput.txt", std::ios::in); 

    //Redirect cin to a file. 
    std::streambuf* cinBuffer = std::cin.rdbuf(); 
    std::cin.rdbuf(file.rdbuf()); 

    //Read line from std::cin (which points to the file) with std::getline. 
    std::string line; 
    std::getline(std::cin, line); 

    std::cout<<"INPUT LINE: "<<line<<std::endl; 

    //Redirect cin to standard input. 
    std::cin.rdbuf(cinBuffer); 

    //Read some line from the user's input.. 
    std::getline(std::cin, line); 
    std::cout<<"USER INPUT LINE: "<<line<<std::endl; 
    std::cin.get(); 

    return 0; 
} 
-3

Ist das folgende Beispiel das, was du suchst?

Der Stringstream kann durch fstream oder einen anderen Typ ersetzt werden, der std :: istream implementiert.

Sie können es testen hier http://cpp.sh/5iv65

+0

Danke, aber ich denke, das ist effektiv die gleiche erste Funktion, die ich habe, außer dass Sie nicht einen Verweis auf 'std :: cin' übergeben. –

+0

Ok, du hast Recht. Möglicherweise suchen Sie eine Lösung wie diese https://stackoverflow.com/questions/19506444/composite-stdistream-in-c? –

+0

Ja, das sieht vielversprechend aus, ich werde einen Blick darauf werfen, danke! –

-2

Sie können immer von Datei über Argv umleiten. Behandle das Ganze von Anfang an als std :: cin.

Verwandte Themen