下面是可能是你一个非常noobish的问题:如何(如果可能的话),我可以从一个函数返回一个ifstream的

基本上,我需要获得来自用户的数据库的文件名,并且如果与该文件名的数据库不存在,然后我需要为用户创建该文件。我知道该怎么做,但只能通过询问用户创建文件后重新启动该程序。我想避免用户可能的话不便,但低于该函数不在GCC编译:

ifstream getFile() {
    string fileName;
    cout << "Please enter in the name of the file you'd like to open: ";
    cin >> fileName;
    ifstream first(fileName.c_str());
    if(first.fail()) {
        cout << "File " << fileName << " not found.\n";
        first.close();
        ofstream second(fileName.c_str());
        cout << "File created.\n";
        second.close();
        ifstream third(fileName.c_str());
        return third; //compiler error here
    }
    else
        return first;
}

编辑:对不起,忘了告诉你,什么编译器错误是:

main.cpp:45: note: synthesized method ‘std::basic_ifstream<char, std::char_traits<char> >::basic_ifstream(const std::basic_ifstream<char, std::char_traits<char> >&)’ first required here 

编辑:我改变该函数返回一个指针,而不是作为瑞摩斯建议,并且在主换了线()为“ifstream的数据库= *的GetFile()”;现在我再次得到这个错误,但这次是在在main()的行:

main.cpp:27: note: synthesized method ‘std::basic_ifstream<char, std::char_traits<char> >::basic_ifstream(const std::basic_ifstream<char, std::char_traits<char> >&)’ first required here
有帮助吗?

解决方案

bool checkFileExistence(const string& filename)
{
    ifstream f(filename.c_str());
    return f.is_open();
}

string getFileName()
{
    string filename;
    cout << "Please enter in the name of the file you'd like to open: ";
    cin >> filename;
    return filename;
}

void getFile(string filename, /*out*/ ifstream& file)
{
    const bool file_exists = checkFileExistence(filename);
    if (!file_exists) {
        cout << "File " << filename << " not found." << endl;
        filename = getFileName();  // poor style to reset input parameter though
        ofstream dummy(filename.c_str();
        if (!dummy.is_open()) {
            cerr << "Could not create file." << endl;
            return;
        }
        cout << "File created." << endl;
    }
    file.open(filename.c_str());
}

int main()
{
    // ...
    ifstream file;
    getFile("filename.ext", file);
    if (file.is_open()) {
        // do any stuff with file
    }
    // ...
}

其他提示

没有,真的没有。 ifstream没有一个拷贝构造函数,如果你试图返回一个,这意味着在复制你的函数实例进行到哪里返回需要去。

在通常的解决方法是在一个引用传递到一个,并且在函数修改参考。

编辑:同时,让你的代码的工作,它不会解决根本问题。现在,你将两种完全不同的责任纳入一个单一的功能:1)获取文件名,2)打开或创建该文件。我想,如果你把这些分开,代码会更简单,使之更容易消除这个问题,你看到的来源。

修改2:使用这样的参考工作得很好而没有operator=。总的想法是这样的:

int open_file(char const *name, fstream &stream) { 
    stream.open(name);
}

赋值运算符是没有必要也有用在这种情况下 - 我们简单地通过参考使用现有fstream的。一个operator=是必要的当且仅当的我们必须传递参数的构造函数。随着甲流,我们可以默认构造不连接到一个文件,然后使用开放式连接到事后的文件流。

ifstream的不支持复制构造语义(那个什么错误讯息基本上赛斯),所以你不能返回ifstream的。返回一个ifstream的*代替,并传递给调用者的责任来删除分配指针。

这注释可能不回答你的问题,我只想问@Corwin先生对他的回答: 就像他的代码,我们有:请求的文件名getFileName块,我觉得应该是这样的代码(这是我认为唯一的):

void getFile(/*out*/ ifstream& file){
    string filename = getFileName();
    const bool file_exist = checkFileExistence(filename);
    if (!file_exist){
       ....
    }
    ....
}

和在int main(),我想:

int main(){
    ifstream file;
    getFile(file);
    if (file.is_open()){
        //some stuff
    }
}

通过这一点,可以在控制台获取从用户输入filename

通过的途径,感谢@Corwin先生代码它的帮助了我很多。

作为一个选项,ifstream的可以被扩展,并加入到新的自定义类的构造函数。

我已经扩展它来创建测试资源流,包封的它测试资源查找内部。

// test_utils.h
class TestResourceStream : public std::ifstream {
    public:
        TestResourceStream(const char* file_path);
};
// test_utils.cpp
namespace fs = std::filesystem;
fs::path test_resource_path(const char* file_path) {
    fs::path path{std::string{"tests/resources/"} + file_path};
    if (!fs::exists(path))
        throw std::runtime_error{std::string{"path "} + 
            fs::absolute(path).c_str() + " does not exist"};
    return path;
}
TestResourceStream::TestResourceStream(const char* file_path)
    :std::ifstream{test_resource_path(file_path).c_str()} {}
// usage in test
TEST_CASE("parse") {
    std::list<GosDump::Expertise> expertises;
    TestResourceStream stream("requests/page_response.json");
    GosDump::Json::parse(expertises, stream);
    REQUIRE(10 == expertises.size());
}
许可以下: CC-BY-SA归因
不隶属于 StackOverflow
scroll top