【问题标题】:Converting file to char* Issue将文件转换为 char* 问题
【发布时间】:2016-01-31 22:56:21
【问题描述】:

我是 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]

这里到底发生了什么?有什么我错过的吗? 如果有更好的方法来做到这一点,我很高兴知道!

【问题讨论】:

  • C++ 初学者了解char* 真是太遗憾了。
  • 每个问题一个问题。如果您有新问题,请发布新问题。如果上下文相关,您可以包含指向此链接的链接。
  • StackOverflow 阻止我发帖,它说我只能每 90 分钟发帖一次。无论如何,我会在时间过后将另一个问题发布到一个新问题中。
  • @sciencelord:我能理解这让你很困扰。在您的情况下,在更短的时间内解决多个问题绝对没有问题,但正如您可能想象的那样,并非像 SO 这样的庞大网络中的所有新用户都表现得合理。这只是一种质量保证机制。

标签: c++ string file stream


【解决方案1】:
return const_cast<char *>(buffer.str().c_str());

返回指向本地stringstream 的内部缓冲区的临时副本的内部字符缓冲区的指针。长话短说:一旦你退出函数,这个指针就会指向垃圾。

顺便说一句,即使这不是问题,const_cast 也是危险的废话,你不能通过指针std::string::c_str 返回来写。 const_cast 的合法使用非常很少。

还有更好的方法:最好和最简单的方法是返回std::string。只有在不允许这样做的情况下,std::vector&lt;char&gt;(首选)或new char[somelength](皱眉)才是可行的解决方案。

【讨论】:

    【解决方案2】:

    如果您的问题是,如何将文件的内容读入缓冲区,请考虑我的以下建议。但请注意缓冲区对于文件内容来说足够大。建议在调用 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;
    }
    

    【讨论】:

    • @ChristianHackl:显然,今天有人有 -1 天。
    • 首先,你的语气不合适。其次,我确实没有否决这个答案,尽管它包含一些 IMO 有问题的建议并且在 C 和 C++ 之间使用了奇怪的组合。
    • @ChristianHackl:您能否进一步解释一下您认为我的语气不恰当的地方?你能解释一下在这个例子中混合 C 和 C++ 是不是很奇怪。两种语言功能齐头并进,为什么不使用它们呢?
    • 指责某人不合理的匿名投票并对此持愤世嫉俗的态度是我认为不合适的。混合 C 和 C++ 总是一件很奇怪的事情,因为它们是具有不同目标的不同语言,通常只是为了向后兼容而共存。例如,C 意味着更多的指针,没有异常,更少的类型安全,没有通过析构函数自动清理。你得到的不是“不可见”的代码,而是代码和行为之间或多或少的 1:1 映射。
    • @ChristianHackl:啊哈,非常有趣。所以你说要实现一个目标,在这种情况下读取文件内容,使用无需查看文档即可读取的简单 C 函数很奇怪吗?你在我的代码 sn-p 中看到了什么陷阱?
    【解决方案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&lt;char *&gt;(buffer.str().c_str()) 被求值时,对象的生命周期结束。因此,使用结果指针也是未定义的行为。


    问题听起来很复杂,但解决起来很容易。让函数返回std::string,把最后一条语句变成return buffer.str();

    【讨论】:

      猜你喜欢
      • 1970-01-01
      • 2013-01-04
      • 1970-01-01
      • 2019-04-05
      • 2019-03-15
      • 1970-01-01
      • 2012-03-22
      • 2017-01-30
      • 1970-01-01
      相关资源
      最近更新 更多