C++ 中的 String.Format 替代方案[重复]

问题描述 投票:0回答:7

我没有太多使用 C++ 的经验。相反,我在 C# 方面工作得更多,因此,我想通过与我在 C# 中所做的事情相关来提出我的问题。我必须生成特定格式的字符串,必须将其传递给另一个函数。在 C# 中,我可以通过下面的简单代码轻松生成字符串。

string a = "test";
string b = "text.txt";
string c = "text1.txt";

String.Format("{0} {1} > {2}", a, b, c);

通过生成这样一个上面的字符串,我应该能够将其传递到

system()
。但是,
system
只接受
char*

我使用

Win32 C++
(不是C++/CLI),并且不能使用
boost
,因为它会包含太多包含本身非常小的项目的所有文件。像
sprintf()
这样的东西对我来说看起来很有用,但是
sprintf
不接受
string
作为
a
b
c
参数。有什么建议我可以生成这些格式化字符串以传递到我的程序中的系统吗?

c# c++ string string-formatting
7个回答
45
投票

C++ 方法是将

std::stringstream
对象用作:

std::stringstream fmt;
fmt << a << " " << b << " > " << c;

C 方法是使用

sprintf

C 方法很难正确,因为:

  • 类型不安全
  • 需要缓冲区管理

当然,如果性能是一个问题,您可能想退回到 C 方式(想象一下您正在创建固定大小的数百万个小

stringstream
对象,然后将它们扔掉)。


32
投票

为了完整起见,您可以使用

std::stringstream
:

#include <iostream>
#include <sstream>
#include <string>

int main() {
    std::string a = "a", b = "b", c = "c";
    // apply formatting
    std::stringstream s;
    s << a << " " << b << " > " << c;
    // assign to std::string
    std::string str = s.str();
    std::cout << str << "\n";
}

或者(在本例中)

std::string
自己的字符串连接功能:

#include <iostream>
#include <string>

int main() {
    std::string a = "a", b = "b", c = "c";
    std::string str = a + " " + b + " > " + c;
    std::cout << str << "\n";
}

供参考:


如果你真的想走 C 路,这里是:

#include <iostream>
#include <string>
#include <vector>
#include <cstdio>

int main() {
    std::string a = "a", b = "b", c = "c";
    const char fmt[] = "%s %s > %s";
    // use std::vector for memory management (to avoid memory leaks)
    std::vector<char>::size_type size = 256;
    std::vector<char> buf;
    do {
        // use snprintf instead of sprintf (to avoid buffer overflows)
        // snprintf returns the required size (without terminating null)
        // if buffer is too small initially: loop should run at most twice
        buf.resize(size+1);
        size = std::snprintf(
                &buf[0], buf.size(),
                fmt, a.c_str(), b.c_str(), c.c_str());
    } while (size+1 > buf.size());
    // assign to std::string
    std::string str = &buf[0];
    std::cout << str << "\n";
}

供参考:


从 C++11 开始,您可以将其“简化”为:

#include <iostream>
#include <string>
#include <vector>
#include <cstdio>

int main() {
    std::string a = "a", b = "b", c = "c";
    const char fmt[] = "%s %s > %s";
    // can use std::string as buffer directly (since C++11)
    std::string::size_type size = 256;
    std::string str;
    do {
        str.resize(size+1);
        // use snprintf instead of sprintf (to avoid buffer overflows)
        // snprintf returns the required size (without terminating null)
        // if buffer is too small initially: loop should run at most twice
        size = std::snprintf(
                &str[0], str.size(),
                fmt, a.c_str(), b.c_str(), c.c_str());
    } while (size+1 > str.size());
    // can strip off null-terminator, as std::string adds their own
    str.resize(size);
    // done
    std::cout << str << "\n";
}

供参考:


然后是Boost 格式库。为了你的例子:

#include <iostream>
#include <string>
#include <boost/format.hpp>

int main() {
    std::string a = "a", b = "b", c = "c";
    // apply format
    boost::format fmt = boost::format("%s %s > %s") % a % b % c; 
    // assign to std::string
    std::string str = fmt.str();
    std::cout << str << "\n";
}

19
投票

除了其他人建议的选项之外,我还可以推荐 fmt 库,它实现类似于 Python 中的

str.format
和 C# 中的
String.Format
的字符串格式。这是一个例子:

std::string a = "test";
std::string b = "text.txt";
std::string c = "text1.txt";
std::string result = fmt::format("{0} {1} > {2}", a, b, c);

免责声明:我是这个库的作者。


10
投票

您可以将

sprintf
std::string.c_str()
结合使用。

c_str()
返回
const char*
并与
sprintf
一起使用:

string a = "test";
string b = "text.txt";
string c = "text1.txt";
char* x = new char[a.length() + b.length() + c.length() + 32];

sprintf(x, "%s %s > %s", a.c_str(), b.c_str(), c.c_str() );

string str = x;
delete[] x;

或者如果您知道大小,则可以使用预先分配的

char
数组:

string a = "test";
string b = "text.txt";
string c = "text1.txt";
char x[256];

sprintf(x, "%s %s > %s", a.c_str(), b.c_str(), c.c_str() );

3
投票

为了完整起见,Boost方法是使用

boost::format

cout << boost::format("%s %s > %s") % a % b % c;

随你挑选。 Boost 解决方案具有

sprintf
格式的类型安全优势(对于那些发现
<<
语法有点笨拙的人)。


2
投票

正如已经提到的,C++ 方式是使用字符串流。

#include <sstream>

string a = "test";
string b = "text.txt";
string c = "text1.txt";

std::stringstream ostr;
ostr << a << " " << b << " > " << c;

请注意,您可以像这样从字符串流对象中获取 C 字符串。

std::string formatted_string = ostr.str();
const char* c_str = formatted_string.c_str();

2
投票

您只需连接字符串并构建命令行即可。

std::string command = a + ' ' + b + " > " + c;
system(command.c_str());

您不需要任何额外的库。

© www.soinside.com 2019 - 2024. All rights reserved.