C#String.格式,参数与C++;? 我有很多C代码,我必须用C++编写。我在C++方面没有太多的经验。

C#String.格式,参数与C++;? 我有很多C代码,我必须用C++编写。我在C++方面没有太多的经验。,c++,build-process,C++,Build Process,我正在使用Visual Studio 2012来构建。该项目是C++中的一个静态库(不是C++/CLI中的) 在许多地方,他们使用的是String.Format,如下所示: C# 现在,我知道以前也有人问过类似的问题,但我不清楚什么是最标准/安全的方法 使用类似于sprintf或printf的东西是否安全?我读到一些人提到他们不标准。像这样的?(这是C++方式,还是C方式?)< /P> C++(或者是C? 其他人建议做自己的类,我看到了许多不同的实现 目前,我有一个类使用std::to_stri

我正在使用Visual Studio 2012来构建。该项目是C++中的一个静态库(不是C++/CLI中的)

在许多地方,他们使用的是String.Format,如下所示:

C#

现在,我知道以前也有人问过类似的问题,但我不清楚什么是最标准/安全的方法

使用类似于sprintfprintf的东西是否安全?我读到一些人提到他们不标准。像这样的?(这是C++方式,还是C方式?)< /P> C++(或者是C?

其他人建议做自己的类,我看到了许多不同的实现

目前,我有一个类使用std::to_stringostringstreamstd::string.replacestd::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 (&parameters)[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);
    };
模板
静态标准::字符串到字符串(T编号)
{
std::ostringstream stringStream;

stringStream为什么不使用
这里有一个单头库,我就是为了这个目的编写的:

测试:

该库是可配置的,因此您可以从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;
}

如果您只有非对象类型(或者手动将它们转换为C字符串,或者将它们转换为字符串,然后调用),sprintf就可以工作。您可能需要提供额外的缓冲区溢出保护

如果您愿意学习更多内容来完成您必须完成的工作,您可以使用。我相信您可以编写一个脚本来将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().flush())我不能这样做,因为在C代码中,他们用字符串:格式:重载GLILY,而且我的C++会变得杂乱无章。如果我可以使用,我不能使用Boost,因为我不知道我是否能够在我的所有环境中使用它。你的库的版权是什么?麻省理工学院许可证-使用它,你只需要确认使用,我就可以了。投票表决,因为有一个与大多数情况相似的人可能不太担心许可证,发现它是有用的。SaveTf和SNPROTF C++标准SCAFTF是不是。SNPRTNF不是(至少C++中的,可能是C),但是它可能在编译器中。(一旦有权限,我将进行检查).但是如果我正确理解你说的话,并且我使用sprintf,如果我的一个参数的长度比原始字符串长,它将溢出?sprintf不会根据参数的大小使原始字符串变大?Boost是否也有同样的问题?或者Boost处理溢出问题?sprintf是一个C函数E没有对象,称为字符串。你只具有指向内存的某个部分的字符指针,以及函数,这些函数通过读取内存来解释指针,直到它们看到字符0。Boost是C++库的集合,将与实际的字符串一起工作,但不会有C格式。指针是按值传递的,所以改变。函数中的指针不会更改原始值。无法在C中重新分配指针(没有按引用传递)。是的,您必须创建足够大的缓冲区(可以静态分配)来保存结果。如果结果太大,则会出现(静默)缓冲区溢出。snprintf允许您指定限制(缓冲区的大小)。std::to_字符串是C++11。另外,对格式字符串的格式是否有任何已知的限制?它们是否总是文字(带引号的字符串,而不是变量)?您是否使用像{0,1}和{0:0}这样的奇特的东西,或者它们都是{n}?参数的数量是否有限制?是否重复像{0}{0}这样的参数“?是否有任何转义大括号({{”和“}”)?因为现在大多数情况都类似于{0}”当有对象时,我为这个对象创建了一个自定义的ToStand函数。我没有意识到toSype是C++ 11,我尝试过C++ 11的一些东西,但是它们没有工作,所以我认为我很好。我可以使用OSTRIGWORD,我的ToStand函数,那是旧的C++ +。OSTRIGNG是C++ 03,是的。我是添加的。我对我的回答感到惊讶。
REQUIRE(ff::format("{2}ff{1}").with('a').also_with(7).now()=="7ffa");
#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
String.Format("Some Text {0}, some other Text {1}", to_printf(p0), to_printf(p1));
`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();`,