【问题标题】:How to put stringstream contents into char instead string type?如何将字符串流内容放入 char 而不是字符串类型?
【发布时间】:2012-02-04 15:20:35
【问题描述】:

大家都知道stringstream.str()需要一个字符串变量类型来存储stringstream.str()的内容。

我想把stringstream.str()的内容存入char变量或者char数组或者指针中。

有可能吗?

请用你的答案写一个简单的例子。

【问题讨论】:

标签: c++


【解决方案1】:

我想通了。使用命名空间 std 并将 tstingstream 替换为 stringstream。下一步是: stringstream strstream; strstream.imbue(std::locale("C")); string str = strstream.str(); const char *sql= str .c_str(); 现在可以执行sql语句了。

sqlite3_exec(db, sql, callback, (void*)data, &zErrMsg);

也许它对某人有帮助。

【讨论】:

    【解决方案2】:

    为什么不直接

    std::string s = stringstream.str();
    const char* p = s.c_str();
    

    ?

    编辑:请注意,您不能在函数之外随意提供 p:它的生命周期与 s 的生命周期绑定,因此您可能需要复制它。

    Edit 2:正如@David 所建议的那样,上面的 copy 意味着复制内容,而不是指针本身。有几种方法。您可以手动完成(从 C“继承”的传统方式)——这是通过 std::strcpy 之类的函数完成的。这种方式相当复杂,因为它涉及手动资源管理,通常不鼓励这样做,因为它会导致更复杂且容易出错的代码。或者您可以使用智能指针或容器:它可以是std::vector<char>std::unique_ptr/std::shared_ptr

    我个人会选择第二种方式。请参阅对此的讨论和@Oli 的回答,它可能很有用。

    【讨论】:

    • @Oli:哦,确实,刚刚更正了。 (顺便说一句,你为什么删除你的答案?)
    • @David : 是的,但是你需要说明必须使用free 而不是delete[]unique_ptr<>(或boost::scoped_array<> 用于C++03)加上std::copy() 将是 IMO 的正确建议。
    • @ildjarn 如果不知道 OP 实际上想要做什么,很难知道正确的建议是什么。
    • @David:我认为他正在学习正确的 C++,所以我们讨论的所有内容都有帮助。
    • @David:是的,但建议互换 C 和 C++ 内存分配方案很少是一件好事。 deletedelete[] 对大多数初学者来说已经足够混乱了;引入free() 只会让事情变得更糟。
    【解决方案3】:

    如果您想将数据放入char 缓冲区,为什么不立即将其放在那里呢?这是一个流类,它接受一个数组,确定它的大小,用空字符填充它(主要是为了确保结果字符串以空字符结尾),然后设置一个std::ostream 直接写入这个缓冲区。

    #include <iostream>
    #include <algorithm>
    
    struct membuf: public std::streambuf {
        template <size_t Size> membuf(char (&array)[Size]) {
            this->setp(array, array + Size - 1);
            std::fill_n(array, Size, 0);
        }
    };
    
    struct omemstream: virtual membuf, std::ostream {
        template <size_t Size> omemstream(char (&array)[Size]):
            membuf(array),
            std::ostream(this)
        {
        }
    };
    
    int main() {
        char   array[20];
        omemstream out(array);
    
        out << "hello, world";
        std::cout << "the buffer contains '" << array << "'\n";
    }
    

    很明显,这个流缓冲区和流可能会存在于一个合适的命名空间中,并会在某个头文件中实现(将它的任何内容放入 C++ 文件没有多大意义,因为所有函数都是需要实例化的模板) .您也可以使用 [deprecated] 类 std::ostrstream 来做类似的事情,但创建自定义流非常容易,可能不值得打扰。

    【讨论】:

    • 虽然这个答案在技术上是正确的,但它为新手提供了一个固定大小的缓冲区。潜伏在缓冲区溢出的 IME,IYAM。
    • 没有缓冲区溢出的危险:由 membuf 设置的缓冲区具有指定的大小,这是流将停止写入它的位置。真正的危险是没有终止空字符,无论是当用户忘记使用 std::ends 还是缓冲区已满时。我主要指出它是一种避免中间字符串的解决方案。
    • 知道这不会溢出。 IME 在新编写的代码中很少出现缓冲区溢出。总是多年的维护和现有代码的不断变化导致假设不再成立。在 20 LoC 的概念验证/示例代码中使用固定大小的缓冲区是非常好的。我看到的问题只是新手使用这些示例作为他们编码风格的基础。在教 C++ 时,我学到了(艰难的方式)我需要始终在示例中编写完美的代码,这甚至适用于我认为题外话的代码。
    【解决方案4】:

    如果你想要一个字符串的实际副本,你可以这样做(如果 stringstream 对象在某些时候超出范围,这很重要):

    const char *p = new char[ss.str().size()+1];
    strcpy(p, ss.str().c_str());
    
    ...
    
    delete [] p;
    

    正如下面的 cmets 中所讨论的,您应该警惕这样做(手动内存管理容易出错,并且非常不符合 C++ 习惯)。为什么要原始字符数组?

    【讨论】:

    • 呃。这显示了一个新手来处理手动分配和删除的资源。 非常个坏主意。 -1来自我。
    • @sbi:就是这样,或者涉及智能指针等的代码sn-p,我认为这模糊了这里的核心概念。 (无论如何,OP 想要处理原始 C 数组和指针这一事实已经意味着我们正在做非惯用的 C++...)
    • IME 对于新手来说没有什么比手动资源管理更难的了。 (您可以改用std::vector。)
    • 我支持@sbi,但我不会投反对票——智能指针是目前唯一明智的答案,尤其是对于初学者。他们可能会有后续问题询问 unique_ptr&lt;&gt; 或其他什么,但这比鼓励使用原始内存管理要好。
    • @sbi:OP 要求提供“char 变量或 char 数组或指针”。
    猜你喜欢
    • 2011-03-19
    • 2014-07-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 2021-01-10
    • 1970-01-01
    • 2020-10-15
    相关资源
    最近更新 更多