2010-03-08 50 views
7

Đây có thể là một câu hỏi rất ngớ ngẩn đối với bạn: Làm thế nào (nếu có thể) tôi có thể trả về ifstream từ một hàm không?Trả về ifstream trong một hàm

Về cơ bản, tôi cần lấy tên tệp của cơ sở dữ liệu từ người dùng và nếu cơ sở dữ liệu có tên tệp đó không tồn tại thì tôi cần tạo tệp đó cho người dùng. Tôi biết làm thế nào để làm điều đó, nhưng chỉ bằng cách yêu cầu người dùng khởi động lại chương trình sau khi tạo tệp. Tôi muốn tránh điều đó bất tiện cho người sử dụng nếu có thể, nhưng các chức năng dưới đây không biên dịch trong 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; 
} 

EDIT: xin lỗi, quên nói với bạn ở đâu và những gì các lỗi biên dịch là:

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 

EDIT: Tôi đã thay đổi hàm để trả về con trỏ thay vì Remus đề xuất và thay đổi dòng trong main() thành "ifstream database = * getFile()"; bây giờ tôi nhận được lỗi này một lần nữa, nhưng lần này trong dòng trong 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 
+3

Nội dung bạn liệt kê không phải là lỗi trình biên dịch, đó là "ghi chú". Nhìn vào lỗi thực tế. –

Trả lời

5
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 
    } 
    // ... 
}
+0

Cảm ơn !!! sau khi một chút tinkering với mã của bạn cuối cùng tôi đã có những gì tôi muốn. : D – wrongusername

+1

Mặc dù đoạn mã này có thể giải quyết được câu hỏi, [bao gồm giải thích] (http://meta.stackexchange.com/questions/114762/explaining-entirely-‌ code-based-answers) thực sự giúp cải thiện chất lượng bài đăng của bạn. Hãy nhớ rằng bạn đang trả lời câu hỏi cho người đọc trong tương lai và những người đó có thể không biết lý do cho đề xuất mã của bạn. – NathanOliver

3

ifstream không hỗ trợ sao chép xây dựng ngữ nghĩa (nghĩa gì được thông báo lỗi cơ bản sais), vì vậy bạn không thể trở về một ifstream. Trả về ifstream * thay vào đó và chuyển đến người gọi khả năng chịu trách nhiệm xóa con trỏ được cấp phát.

+0

Được rồi ... Tôi đưa vào "trả lại & thứ ba" và bây giờ nó cảnh báo tôi rằng "địa chỉ của biến địa phương" thứ ba "trở lại." Tôi phải làm gì trong main()? – wrongusername

+0

không bao giờ quay trở lại & stack_variable. Phân bổ ifstream với toán tử mới và trả về con trỏ. –

+0

Ý của bạn là, ví dụ như "ifstream returnStream = &first; return returnStream;"? btw, cũng không hoạt động. nó mang lại cho tôi một lỗi: "main.cpp: 56: error: chuyển đổi từ‘ std :: ifstream * ’thành loại không phải vô hướng‘ std :: ifstream ’yêu cầu chính.cpp: 57: lỗi: chuyển đổi không hợp lệ từ 'void *' sang 'std :: ifstream *' " – wrongusername

14

Không, không thực sự. ifstream không có hàm tạo bản sao và nếu bạn cố gắng trả về một hàm, điều đó có nghĩa là sao chép cá thể trong hàm của bạn ra bất kỳ nơi nào cần trả lại.

Cách giải quyết thông thường là chuyển tham chiếu đến một tham chiếu và sửa đổi tham chiếu đó trong hàm của bạn.

Chỉnh sửa: trong khi điều đó sẽ cho phép mã của bạn hoạt động, mã sẽ không khắc phục được sự cố cơ bản. Ngay bây giờ, bạn đang trộn hai trách nhiệm khá khác nhau vào một hàm duy nhất: 1) lấy tên tệp, 2) mở hoặc tạo tệp đó. Tôi nghĩ rằng nếu bạn tách biệt chúng, mã sẽ đơn giản hơn và giúp bạn dễ dàng loại bỏ nguồn gốc của sự cố mà bạn đang gặp phải.

Chỉnh sửa 2: Sử dụng tham chiếu như thế này hoạt động hoàn toàn tốt mà không cần operator=. Ý tưởng chung là một cái gì đó như:

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

Toán tử gán là không cần thiết cũng không hữu ích trong trường hợp này - chúng tôi chỉ đơn giản sử dụng fstream hiện có thông qua tham chiếu. An operator= sẽ là cần thiết nếu và chỉ khi, chúng tôi phải chuyển đối số đó cho ctor. Với luồng, chúng tôi có thể mặc định tạo luồng không kết nối với tệp và sau đó sử dụng mở để kết nối với tệp sau khi thực tế.

+0

Cảm ơn! Tôi đã làm điều đó, nhưng tiếc là mã vẫn không hoạt động. database = * getFile(); "Tôi gặp lỗi trên dòng" main.cpp: 29: note: synthesized method 'std :: basic_ifstream > :: basic_ifstream (const std :: basic_ifstream > &) 'yêu cầu đầu tiên ở đây " – wrongusername

+0

nhưng tôi nghĩ rằng nó đã làm cho tôi xuống đến một lỗi đó, mặc dù – wrongusername

+0

Các" lừa "đi qua trong một tài liệu tham khảo để tránh trả lại một đối tượng mới sẽ chỉ làm việc cho các loại có một vở opera tor = '. std :: ifstream không có điều đó, vì vậy lời khuyên này sẽ không hoạt động cho bạn. – MSalters

Các vấn đề liên quan