【问题标题】:Weird characters in printfprintf 中的奇怪字符
【发布时间】:2013-11-12 13:48:20
【问题描述】:

我的环境:Xcode5、iOS、Objective-C/Objective-C++ 混合。

我试图找出导致下一个问题的原因。我正在编写自己的日志记录功能:

int _me_log(const char *fmt, ...) {

va_list args;
va_start(args, fmt);

char *c = va_arg(args, char *);

char *message = NULL;

printf(fmt, args);

int n = asprintf(&message, fmt, args);

if (n != -1 && message != NULL) {
 //do something with 'message' like writing to file, etc.
 UPDATE:
//we need to handle memory created for 'message' storage.
free(message); 
}
va_end(args);

return n;

}

那我这样称呼它:

_me_log("socket %s did open", "Socket: 0x1fd1c880");

而不是正确的输出socket Socket: 0x1fd1c880 did open 我在这行printf(fmt, args); 中得到了一些像socket \\323\331/ did open 这样的乱码。

如果我这样称呼它printf("%s", c);,我会得到正确的结果。

我已经用谷歌搜索了几个日志函数和传递可变参数的函数的实现(this 或 this),看来我做的一切都是正确的。

你能告诉我我做错了什么吗?

【问题讨论】:

  • 看起来你想要vasprintf而不是asprintf。

标签: ios objective-c c printf objective-c++


【解决方案1】:

您在这里使用va_list 是正确的想法,但如果您使用va_list,您应该使用vasprintf 而不是asprintf:

int _me_log(const char *fmt, ...)
{
    va_list args;
    char *message = NULL;
    int n;

    va_start(args, fmt);
    n = vasprintf(&message, fmt, args);

    if (n != -1 && message != NULL) {
        // ... use message ...
    }
    free(message);
    va_end(args);

    return n;
}

对于printf 系列的每个例程,都有一个变体采用va_list 而不是可变参数...,其名称以字母v 为前缀,例如:

int printf(const char *format, ...);
int vprintf(const char *format, va_list ap);

存在这些例程,因此您可以为 xprintf 编写自己的(非宏)包装器。

【讨论】:

  • 谢谢,我已经在之前的答案中添加了评论。我接受您的回答,因为它直接回答了我的问题和其中的代码。 trojanfoe的回答也是正确的。
  • @trojanfoe 如果您的意思是泄漏“消息”,那么我当然会处理。为了代码简洁,我省略了它。
  • 更新了释放“消息”内存的问题。以防万一有人复制/粘贴它。
  • 好的,这更有意义,但是现在在这个答案中对free() 的调用是在错误的地方。
  • @trojanfoe:当然必须释放消息缓冲区。 User1264176 打败了我来编辑答案。感谢您的纠正。
【解决方案2】:

似乎是一个非常复杂的实现。试试:

int _me_log(const char *fmt, ...) {
    int ret = 0;
    va_list va;
    va_start(va, fmt);
    ret = vprintf(fmt, va);
    va_end(va);

    putc('\n', stdout);
    return ret;
}

但是,当然,这与 printf() 没有什么不同,除了强制换行。

【讨论】:

  • 现在我明白了我的错误。您不能使用 va_list 作为参数调用 printf,例如“printf(fmt, va);”。您必须改为调用 vprintf() 。谢谢。
猜你喜欢
  • 1970-01-01
  • 1970-01-01
  • 2023-01-19
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 2023-03-12
相关资源
最近更新 更多