gpt4 book ai didi

c++ - 如何让标准文件流返回有用的错误消息?

转载 作者:太空狗 更新时间:2023-10-29 21:16:23 25 4
gpt4 key购买 nike

#include <fstream>
#include <iostream>
#include <exception>


int main(int argc, char **argv)
{ try
{ std::ifstream sFile(argv[1]);
sFile.exceptions(std::ios::badbit | std::ios::failbit);
} catch (const std::exception &_r)
{ std::cerr << "exception: " << _r.what() << std::endl;
}
}

如果传入的文件不存在,此代码将使用 g++ 4.5.2 打印出来(是的,我知道这是一个非常旧的版本,但我没有足够的影响力来更改它):

"exception: basic_ios::clear"

使用 Visual C++ 12:

"exception: ios_base::failbit set: iostream stream error"

考虑到系统错误信息在很久以前就已经引入了,我认为这是 Not Acceptable 。

最佳答案

C++11 解决方案

自 C++11 起,std::ios_base::failure inherits from std::system_error所以我们应该能够捕获该异常并立即从中获取错误消息。

#include <cstdlib>       // EXIT_SUCCESS, EXIT_FAILURE
#include <fstream> // std::ifstream
#include <iostream> // std::cerr, std::endl
#include <system_error> // std::system_error


int
main()
{
const auto filename = std::string {"/no/such/file.txt"};
try
{
auto istr = std::ifstream {filename};
istr.exceptions(std::ios::badbit | std::ios::failbit);
// ...
istr.close();
}
catch (const std::ios_base::failure& e)
{
std::cerr << "error: " << e.what() << std::endl;
//std::cerr << "error: " << e.code().message() << std::endl;
return EXIT_FAILURE;
}
return EXIT_SUCCESS;
}

不幸的是,这还不适用于我的 GCC 5.3.0。 catch 永远不会被激活,而是程序核心转储。更糟糕的是,这意味着我们必须 catch std::exception ,这也将匹配所有其他可能与 I/O 错误无关的异常类型。这真的让我很困扰。

使用 std::strerror(errno)

如果一切都失败了,你可以使用 'ye good ol' errno 并通过 std::strerror 获取人类可读的字符串(这不是线程安全的, 顺便一提)。也不能保证 errno 在错误发生点和您处理异常的点之间没有被清除(或重新分配)。这是因为在 C++ 中,在堆栈展开期间可能会执行任意代码。

#include <cerrno>        // errno
#include <cstdlib> // EXIT_SUCCESS, EXIT_FAILURE
#include <cstring> // std::strerror
#include <exception> // std::exception
#include <fstream> // std::ifstream
#include <iostream> // std::cerr, std::endl


int
main()
{
const auto filename = std::string {"/no/such/file.txt"};
try
{
auto istr = std::ifstream {filename};
istr.exceptions(std::ios::badbit | std::ios::failbit);
// ...
istr.close();
}
catch (const std::exception&)
{
std::cerr << "error: " << std::strerror(errno) << std::endl;
return EXIT_FAILURE;
}
return EXIT_SUCCESS;
}

使用std::error_code

这个解决方案只比使用 std::strerror(errno) 稍微好一点,但至少它看起来更像 C++11。问题是一样的,只是它是线程安全的。

#include <cerrno>        // errno
#include <cstdlib> // EXIT_SUCCESS, EXIT_FAILURE
#include <exception> // std::exception
#include <fstream> // std::ifstream
#include <iostream> // std::cerr, std::endl
#include <system_error> // std::error_code, std::system_category


int
main()
{
const auto filename = std::string {"/no/such/file.txt"};
try
{
auto istr = std::ifstream {filename};
istr.exceptions(std::ios::badbit | std::ios::failbit);
// ...
istr.close();
}
catch (const std::exception&)
{
const auto ec = std::error_code {errno, std::system_category()};
std::cerr << "error: " << ec.message() << std::endl;
return EXIT_FAILURE;
}
return EXIT_SUCCESS;
}

关于c++ - 如何让标准文件流返回有用的错误消息?,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/35190832/

25 4 0