C# String.Format with Parameters 标准等效于 C++
C# String.Format with Parameters standard equivalent in C++?
我有很多C#代码必须用C++编写。我在C++方面没有太多经验。
我正在使用Visual Studio 2012进行构建。该项目是 C++ 中的静态库(不是 C++/CLI 中的静态库)。
在许多地方,他们使用String.Format,像这样:
C#
String.Format("Some Text {0}, some other Text {1}", parameter0, parameter1);
现在,我知道以前有人问过类似的事情,但我不清楚什么是最标准/最安全的方法。
使用sprintf或printf这样的东西安全吗?我读到有些人提到他们不标准。像这样的东西?(这是C++方式,还是更多的是C方式?
C++(还是C?
char buffer [50];
int n, a=5, b=3;
n=sprintf (buffer, "Some Text %d, some other Text %d", a, b);
其他人建议做自己的类,我看到了许多不同的实现。
目前,我有一个使用std::to_string,ostringstream,std::string.place和std::string.find的类,以及模板。我的类相当有限,但对于我在 C# 代码中遇到的情况,它可以工作。现在我不知道这是最有效的方法(甚至根本不是正确的):
C++
template <typename T>
static std::string ToString(T Number)
{
std::ostringstream stringStream;
stringStream << Number;
std::string string = stringStream.str();
return string;
};
template <typename T,unsigned S>
static std::string Format(const std::string& stringValue, const T (¶meters)[S])
{
std::string stringToReturn = std::string(stringValue);
for (int i = 0; i < S; ++i)
{
std::string toReplace = "{"+ std::to_string(i) +"}";
size_t f = stringToReturn.find(toReplace);
if(std::string::npos != f)
stringToReturn.replace(f, toReplace.length(), ToString(parameters[i]));
}
return stringToReturn;
};
//I have some other overloads that call the Format function that receives an array.
template <typename T>
static std::string Format(const std::string& stringValue, const T parameter, const T parameter2)
{
T parameters[] = {parameter, parameter2};
return Format(stringValue, parameters);
};
我需要我的代码在 Linux 和 Windows 中工作,所以我需要不同的编译器才能构建它,这就是为什么我需要确保我使用的是标准方式。而且我的环境不能那么容易更新,所以我不能使用 C++11。我也不能使用 Boost,因为我不确定我是否能够在我需要它工作的不同环境中添加库。
在这种情况下,我可以采取的最佳方法是什么?
编写的 1 标头库: 假格式
测试:
REQUIRE(ff::format("{2}ff{1}").with('a').also_with(7).now()=="7ffa");
该库是可配置的,因此您可以从 0 开始参数索引。您还可以编写包装器,使其看起来与String.Format
完全相同。
它建立在 Linux 之上,不需要 c++11。
目前还没有标准方法...
这是,索引从 0 开始:
#include ...
struct dotnet_config {
static const char scope_begin='{';
static const char scope_end='}';
static const char separator=',';
static const char equals='=';
static const size_t index_begin=0;
static bool string_to_key(std::string const& to_parse,int& res) {
std::istringstream ss(to_parse);
ss.imbue(std::locale::classic());
ss >> res;
if (!ss.fail() && ss.eof())
return true;
return false;
}
};
template <typename T1>
std::string Format (std::string const& format_string,T1 p1) {
return ff::formatter<dotnet_config>(format_string).with(p1).now();
}
template <typename T1,typename T2>
std::string Format (std::string const& format_string,T1 p1,T2 p2) {
return ff::formatter<dotnet_config>(format_string).with(p1).with(p2).now();
}
int main() {
std::cout<<Format("test={0}",42)<<std::endl;
std::cout<<Format("{0}!={1}",33,42)<<std::endl;
return 0;
}
输出:
test=42
33!=42
如果您拥有的只是非对象类型(或者您手动将它们转换为 C 字符串,或将它们转换为字符串,然后调用 c_str() 成员函数),则 sprintf 有效。您可能需要 snprintf 提供的额外保护,防止缓冲区溢出。
如果您愿意学习更多内容来执行您必须做的事情,则可以使用增强格式库。我相信你可以编写一个脚本来将String.format调用转换为Boost的语法。
如果你不能使用Boost,也不能使用C++11,你必须使用sprintf并小心缓冲区溢出(如果你可以依赖你的编译器,可能是snprintf)。您可能希望编写一个脚本来包装所有参数,以便它们都转换为字符串:
String.Format("Some Text {0}, some other Text {1}", to_printf(p0), to_printf(p1));
另外,请注意,C 的格式不使用大括号。所以这是一个大问题。您可能需要实现自己的可变参数函数。
如果一切都像{0}
这样简单,你可以编写一个脚本来替换大多数 String.Format 实例(而不是更复杂的实例)
`mystring = "Some Text "+tostring(p0)+", some other Text "+tostring(p1);`
这不是最有效的方法,但除非您每秒执行数千种格式,否则很可能无关紧要。或者可能效率稍高(没有中间字符串):
`"mystring = static_cast<std::ostringstream&>(std::ostringstream().flush()<<Some Text "<<p0<<", some other Text "<<p1).str();`,
这创造了一个临时的。同花顺有点诱使编译器认为它不是临时的,这解决了关于无法使用非成员operator<<
的特定问题。
为什么不使用 <<
运算符来格式化字符串?
string strOutput;
stringstream strn;
int i = 10;
float f = 20.0f;
strn << "Sally scored "<<i<< " out of "<<f << ". She failed the test!";
strn >> strOutput;
cout << strOutput;
- 使用CMake检测支持的C++标准
- 如何理解C++标准N3337中的expr.const.cast子句8
- "throw expression code" 1e7 >返回 d 是什么?投掷标准::overflow_error( "too big" ) : d;意味 着?
- 编译标准库类型
- 标准是否使用多余的大括号(例如 T{{{10}}})定义列表初始化?
- 编译器如何在使用SFINAE的函数和标准函数之间确定两者是否可行
- 铸造标准::有没有回到原来的类型
- 标准 N3337 5.2.10 第 7 条中的C++"类型"是什么意思?
- this_thread::sleep_for和计时时钟之间的关系是否由C++11标准指定
- 标准库类型的赋值运算符的引用限定符
- 标准是否严格定义了该程序应该如何编译?
- 如何从Windows应用程序输出到标准?
- 安全到标准:移动会员?
- 如何正确将字符串转换为标准::时间::system_clock::time_point?
- 这是否符合C++标准:双响双响,例如!!(-0.0).
- 标准::变体的赋值运算符
- 捕获标准输出以压缩并使用 CTRL-C 中断会给出损坏的 zip 文件
- 如何在 Mac 上使用 c++17 并行标准库算法?
- 强枚举类型定义:Clang Bug 还是 C++11 标准不确定性?
- 并行标准::复制复杂性