我是C ++编程的初学者,我遇到了一个问题。 我希望能够将文件的内容转换为char *,并且我使用了文件和字符串流。但是,它无法正常工作。
这是我完成工作的功能:
char* fileToChar(std::string const& file){
std::ifstream in(file);
if (!in){
std::cout << "Error: file does not exist\n";
exit(EXIT_FAILURE);
}
std::stringstream buffer;
buffer << in.rdbuf() << std::flush;
in.close();
return const_cast<char *>(buffer.str().c_str());
}
但是,当我通过将其内容输出到另一个文件来测试方法时,这样:
std::ofstream file("test.txt");
file << fileToChar("fileTest.txt");
我只是得到了很多像这样的奇怪角色:
îþîþîþîþîþîþîþîþîþîþîþîþîþîþîþîþîþ[...etc]
这到底发生了什么?我错过了什么吗? 如果有更好的方法,我会很高兴知道!
答案 0 :(得分:4)
return const_cast<char *>(buffer.str().c_str());
返回指向本地stringstream
的内部缓冲区的临时副本的内部char缓冲区的指针。长话短说:退出函数后,此指针指向垃圾。
顺便说一下,即使这不是问题,const_cast
也是危险的废话,你不能通过指针std::string::c_str
返回。 const_cast
的合法使用非常罕见。
以更好的方式:最好和最简单的方法是返回std::string
。只有在不允许的情况下,std::vector<char>
(首选)或new char[somelength]
(不赞成)才是可行的解决方案。
答案 1 :(得分:3)
char* fileToChar(std::string const& file){
这一行已经表明事情正朝着错误的方向发展。你返回一个指向某个字符串的指针,如果必须释放它,如果可以返回nullptr
那么,对于负责释放已分配内存的函数的用户来说,它是完全不清楚的,等等。
如果你想要一个字符串,那么一定要使用std::string
!
std::string fileToChar(std::string const& file){
return const_cast<char *>(buffer.str().c_str());
应该使所有警报响起的另一条线。 const_cast
始终是解决某些潜在问题(或外部代码的某些问题)的解决方法。
通常有一个很好的理由为什么是const
。通过强制编译器关闭安全检查并允许它尝试修改不可修改的数据,通常会将编译错误转换为难以诊断的运行时错误。
即使如果此函数正常工作,任何修改结果的尝试都将是未定义的行为:
char* file_contents = fileToChar("foo.txt");
file_contents[0] = 'x'; // undefined behaviour
但无论如何它都无法正常工作。 buffer.str()
会返回临时 std::string
对象。 c_str()
返回指向该临时对象内部管理内存的指针。对象的生命周期在评估完整表达式return const_cast<char *>(buffer.str().c_str())
时结束。因此,使用结果指针也是未定义的行为。
问题听起来很复杂,但修复很容易。使函数返回std::string
并将最后一个语句转换为return buffer.str();
。
答案 2 :(得分:-1)
如果您的问题是,如何将文件内容读入缓冲区,请考虑以下建议。但要注意缓冲区对于文件内容来说足够大。在调用fileToChar()
之前,建议对文件大小进行检查并预先分配内存。
bool fileToChar(std::string const& file, char* buffer, unsigned int &buffer_size )
{
FILE *f = fopen( file.c_str(), "rb" );
if( f == nullptr )
{
return false;
}
fseek(f , 0, SEEK_END );
const int size = ftell( f );
rewind( f );
fread( buffer, 1, size, f );
fclose( f );
return true;
}