仅具有变量输入的自定义 sprintf(...) 样式函数

custom sprintf(...) style function with only variable input

唱 Borland C++ Builder 2009。

在与字符串 class 相当的自定义 class 中(至少为了这个 Q)我有一个函数,如下所示:

(为此 Q 做了一些编辑)

MyString &MyString::Sprintf(const wchar_t *Text, ...)
{
    wchar_t ResultStr[1000] ;
    va_list List ;
    va_start  (List, Text) ;
    int cnt = vswprintf (ResultStr, Text, List ) ;
    #ifdef _DEBUG
    if (cnt >= (int)sizeof(ResultStr)) {throw (sizeof(ResultStr)) ;}
    #endif
    va_end (List) ;
    my_internally_handled_string.assign(ResultStr) ;
    return *this;
}

不过,我想调整此函数(或创建另一个函数),它只将变量作为输入,并使用 class' 内部管理的字符串作为 Text 的输入 vswprintf()函数。

像这样:

MyString &MyString::Sprintf(...)
{
    const wchar_t *Text = my_internally_handled_string.c_str() ;
    // ... Rest see above

但这不起作用。 vswprintf 抛出异常。 (在 my_internally_handled_string 中使用完全正常的文本进行测试)

我想知道这是否完全可行 and/or 我需要做什么才能让它按照我设想的方式工作?

变量(或variadic) arguments of va_start() (stdarg.h/cstdarg) are macros继承自C。第二个参数是最后一个non-variable参数(在你的例子中是const wchar_t *Text)。这需要作为计算的参考点后面的可变参数的起始地址。如果在...之前没有最后一个参数那么它就没有找到可变参数的参考点。所以你需要something来给它,比如一个虚拟参数。

您可以保留现有的函数签名

    MyString &MyString::Sprintf(const wchar_t *Text, ...)

并且除了调用 va_start(List, Text) 之外不使用参数 Text。请记住,您可以将任何您想要的传递给vswprintf(),例如

    vswprintf(ResultStr, my_internally_handled_string.c_str(), List);

此外,不要用同名的局部变量隐藏参数 Text,尤其是在调用 va_start() 之前,因为它需要 参数作为起点。

关于 C++ 中可变参数值得一提的另一件事是 don't use a reference variable 作为 ....

之前的最后一个参数