在可变函数内调用snprintf和vsnprintf

时间:2019-05-27 18:51:16

标签: c++

我正在尝试在可变函数内部使用可变函数。我在Internet和Stack Overflow上检查了很多示例,但找不到我的错误。

当我使用Visual Studio运行程序时,调用snprintf时出现访问冲突。

这里的标题:

#pragma once
#include <cstdarg>
class Console
{
   public:
     static void writeLine(const char *s, ...);

   private:
     Console() = delete;
    ~Console() = delete;
};

课程:

#include "Console.h"
#define _CRT_SECURE_NO_WARNINGS
#include <stdio.h>
#include <iostream>

void Console::writeLine(const char *s...)
{
    va_list arg1, arg2;

    // Search the total length
    va_start(arg1, s);
    va_copy(arg2, arg1);
    int length = snprintf(nullptr, 0, s, arg1);
    va_end(arg1);

    size_t size = length + 1;
    char *szBuff = new char[size]; // note +1 for terminating null byte

    // Format the string
    vsnprintf(szBuff, size, s, arg2);
    va_end(arg2);

    std::cout << (const char*)szBuff << std::endl;

   delete(szBuff);
}

主程序:

#include "Console.h"
#include <iostream>

int main()
{
   Console::writeLine("Example with an int (%d) and a string(%s)", 10, "my string");
}

我确定我确实很愚蠢,但是我不明白为什么它不起作用。

编辑

cout调用只是一个例子,我正在使用Windows中的一个函数将其写入Visual Studio的控制台。这就是为什么我要上此类:在将结果写入控制台之前先格式化数据。

1 个答案:

答案 0 :(得分:1)

您使用了错误的函数来计算缓冲区的大小。 snprintf()不接受va_list作为输入。另外,Microsoft的vsnprintf()的实现未定义为像snprintf()那样接受NULL缓冲区作为输入。您需要改用_vscprintf()

  

_vscprintf返回如果使用指定的格式代码打印由参数列表指向的字符串或将其发送到文件或缓冲区时将生成的字符数。返回的值不包含终止的空字符。

此外,您没有正确释放缓冲区。由于您使用new[]进行分配,因此需要使用delete[]来释放它。

尝试以下方法:

void Console::writeLine(const char *s, ...)
{
    va_list arg1, arg2;

    va_start(arg1, s);

    // Search the total length
    va_copy(arg2, arg1);
    size_t size = _vscprintf(s, arg2) + 1; // note +1 for terminating null byte
    va_end(arg2);

    char *szBuff = new char[size];

    // Format the string
    vsnprintf(szBuff, size, s, arg1);

    va_end(arg1);

    std::cout << szBuff << std::endl;

    delete[] szBuff;
}
相关问题