【问题标题】:How to store a concatenation of ints and characters in a char*?如何在 char* 中存储整数和字符的串联?
【发布时间】:2010-10-02 16:57:45
【问题描述】:

我有一些整数,比如说one twothree。我希望创建一个字符串,例如

char* example = "There are " + one + " bottles of water on " + 
    two + " shelves in room number " + three + "\n".`  

这在 C/C++ 中不起作用。如何将这种类型的值存储在 char* 中?

【问题讨论】:

  • 这就是为什么我事先告诉你它们是整数。你宁愿我写“int one = 3; int two = 6; int three = 1;”吗?
  • 是的。然后我们就会知道它们是整数而不是字符串。
  • 如果您不是偶然标记了这个“C++”,我应该指出,在 C++ 中,使用strings 而不是char*s 几乎总是更好。
  • 另外,没有这样的语言叫 C/C++。它们是不同的语言,您选择的方法取决于您使用的语言。所以选择一种。
  • @John Dibling - int 隐含在问题标题中,通过消除过程...

标签: c++ c string


【解决方案1】:

在 C 中,有不止一种方法可以做到这一点,具体取决于您希望如何分配内存 [*]。对于从堆中分配它的直接选项:

len = snprintf(0, 0, "%d bottles, %d shelves, room %d\n", one, two, three);
char *result = malloc(len+1);
if (result == 0) { /* handle error */ }
snprintf(result, len+1, "%d bottles, %d shelves, room %d\n", one, two, three);

/* some time later */
free(result);

注意snprintf 的非标准实现,当超出缓冲区时不会返回长度。检查您的文档。

在 C++ 中,snprintf 不在标准中,即使它可用,上面的代码也需要转换 malloc[**] 的结果。 C++ 增加了使用字符串流的选项:

std::stringsteam r;
r << one << " bottles, " << two << " shelves, room " << three << "\n";
std::string result = r.str();

// if you absolutely need a char*, use result.c_str(), but don't forget that
// the pointer becomes invalid when the string, "result" ceases to exist.

这避免了缓冲区长度的混乱,使资源管理更容易,并避免printf 和朋友可能为格式说明符传递错误类型的参数的风险。它通常是首选。

然而在某些情况下它不太灵活:格式被硬连接到代码中,而不是包含在格式字符串中,因此更难使文本可配置。它也可能有点难以阅读,例如在任何此类代码行的第一个版本中省略空格字符并不少见。但是,如果您想在 C++ 中使用 snprintf 方法,并且在您的实现中可以使用 snprintf,那么您可以利用 C++ 更简单的内存管理,如下所示:

len = std::snprintf(0, 0, "%d bottles, %d shelves, room %d\n", one, two, three);
std::vector<char> r(len+1);
std::snprintf(&r[0], r.size(), "%d bottles, %d shelves, room %d\n", one, two, three);

char *result = &r[0];
// again, "result" is only valid as long as "r" is in scope

[*] 请注意,您不能在char* 中“存储”字符串,因为char* 只是一个指针。您可以在char* 中存储指向字符串的指针,但字符串本身是完全独立的。

[**] 因为 C 和 C++ 是不同的语言!

【讨论】:

    【解决方案2】:

    C++ 不是 VB。但是你有很多选择。

    字符串流:

    #include <sstream>
    #include <string>
    
    stringstream ss;
    ss<< "There are " << one << " bottles of water on " << two << " shelves in room number " << three;
    string s = ss.str();
    

    提升/格式:

    #include <boost/format.hpp>
    #include <string>
    
    string s = (boost::format("There are %1% bottles on %2% shelves in room number %3%")%one%two%three).str();
    

    老派(老套、不安全、不好,不要这样做)

    char buffer[1024] = {};
    sprintf(buffer, "There are %d bottles on %d shelves in room number %d", one, two, three); 
    

    【讨论】:

    • 你也可以lexical_cast把数字串起来。
    【解决方案3】:

    sprintf 是一个选项(正如 Ólafur 所写),但已弃用。尽可能使用snprintf - 如果您对缓冲区和输入的大小不太小心,sprintf 可能会导致缓冲区溢出并导致严重的崩溃和错误。

    char output[256];
    snprintf(output, sizeof(output), "There are %d bottles of water on %d shelves 
        in room number %d\n", one, two, three);
    

    【讨论】:

    • "sprintf 很好" 是的,好的。你是怎么想出神奇数字256的?够大吗?很浪费吗?您如何确定onetwothreeints?如果某个维护程序员出现并更改了其中一种类型,您准备好爆发了吗?
    • snprintf 在 C++ 中也已弃用
    • @Steve:我不相信它被正式弃用(sprintf 也不是)。人们不喜欢使用它。
    【解决方案4】:
    #include <sstream>
    
    std::stringstream strVal;
    
    strVal << std::string("There are ") << one << std::string(" bottles of water on ") << 
        two << std::string(" shelves in room number ") << three << std::endl;
    
    std::string copyStr(strVal.str());
    const char * example = copyStr.c_str();
    

    【讨论】:

    • 我认为您需要将其放入 string 并使用 c_str()
    • @John - 是的,或者最好完全忘记char*
    • @Steve:但是现在你把它放到一个临时的,在;之后就蒸发了
    • @John,是的,我忘记了strdup 电话。感谢代码审查。
    • 请问这些临时字符串是干什么用的?我的意思是从字符串文字构造的那些。
    【解决方案5】:

    我喜欢 stringstream 方法,但我使用一个类来简化它的使用。有关更多详细信息,请参阅我的 answer 到另一个 SO 问题:

    string myString = MakeString() << "There are " << one << " 
          bottles of water on " << two << " shelves in room number " << three;
    
    char * example = myString.c_str(); // if you really need a char *
    

    【讨论】:

      【解决方案6】:

      我的解决方案:

      template <typename T> std::string toStr(const T& something) {
          std::stringstream ss;
          ss << something;
          return ss.str();
      }
      ...
      std::string example = "There are " + toStr(one) + " bottles of water on " + 
                      toStr(two) + " shelves in room number " + toStr(three) + "\n";
      

      【讨论】:

        猜你喜欢
        • 2014-01-10
        • 1970-01-01
        • 1970-01-01
        • 1970-01-01
        • 2017-04-13
        • 1970-01-01
        • 1970-01-01
        • 2012-02-28
        • 1970-01-01
        相关资源
        最近更新 更多