实现你自己的 printf

Implementing your own printf

我正在尝试实现 C printf,但我使用 {s} 而不是 %s。而不是 %d ... {d}。而不是 %c ... {c}(有点像 Python/C#/Java 的位置字符串格式参数,但不是数字位置,而是数据类型的规范)。它还应该转义额外的大括号,使 {{} 变为 {。这一切都有效,除非我在 {{ 作为测试的一部分通过。 Valgrind 告诉我 This is probably caused by your program erroneously writing past the end of a heap block and corrupting heap metadata。这是代码:

#include <ctype.h>
#include <stdarg.h>
#include <stdio.h>
#include <stdlib.h>
#include <string.h>

char *mr_asprintf(const char *format, ...) {
    if (strlen(format) == 0) { return calloc(1, sizeof(char)); }
    char buf[strlen(format) * 2];
    memset(buf, 0, sizeof(buf));
    va_list args;
    va_start(args, format);
    while (*format != '[=10=]') {
        if (*format == '{') {
            format++;
            if (*format == '{') {
                sprintf(buf + strlen(buf), "%c", '{');
            } else if (*format == 's') {
                sprintf(buf + strlen(buf), "%s", va_arg(args, const char*));
            } else if (*format == 'i') {
                sprintf(buf + strlen(buf), "%d", va_arg(args, int));
            }
            if (*format++ == '}') {}
        } else if (*format == '}') {
            sprintf(buf + strlen(buf), "%c", '}');
        } else {
            sprintf(buf + strlen(buf), "%c", *format);
        }
        format++;
    }
    va_end(args);
    return strdup(buf);
}

这些是测试:

printf("'%s'\n", mr_asprintf("Gaius Julius Caesar Augustus Germanicus"));
printf("'%s'\n", mr_asprintf("Nickname: {s}", "Caligula")); 
printf("'%s'\n", mr_asprintf("Reign: {i} AD - {i} AD", 37, 41)); 
printf("'%s'\n",
           mr_asprintf("born: {s} {i}, {i} in {s}", "August", 31, 12, "Antium")); 
printf("'%s'\n", mr_asprintf("Roman emperor #{i}", 3)); 
printf("'%s'\n", mr_asprintf("Roman emperor #{i}}", 3)); 
printf("'%s'\n", mr_asprintf(""));
printf("'%s'\n", mr_asprintf("}bae}ccac {i}bdbb{i}bb{i}}dd b", 394603702, 511917921,
                                 721200806)); 
printf("'%s'\n", mr_asprintf("{{"));

预期输出:

'Gaius Julius Caesar Augustus Germanicus'
'Nickname: Caligula'
'Reign: 37 AD - 41 AD'
'born: August 31, 12 in Antium'
'Roman emperor #3'
'Roman emperor #3}'
''
'}bae}ccac 394603702bdbb511917921bb721200806}dd b'
'{'

实际输出:

  1. 海湾合作委员会 10.3.0
'Gaius Julius Caesar Augustus Germanicus'
'Nickname: Caligula'
'Reign: 37 AD - 41 AD'
'born: August 31, 12 in Antium'
'Roman emperor #3'
'Roman emperor #3}'
''
'}bae}ccac 394603702bdbb511917921bb721200806}dd b'
'{Gaius Julius Caesar Augustus Germanicus'
  1. 叮当声 8
'Gaius Julius Caesar Augustus Germanicus'
'Nickname: Caligula'
'Reign: 37 AD - 41 AD'
'born: August 31, 12 in Antium'
'Roman emperor #3'
'Roman emperor #3}'
''
'}bae}ccac 394603702bdbb511917921bb721200806}dd b'
'{}}'

如您所见,除最后一个测试外,所有测试均正常运行。我做错了什么?您还可以建议改进我的代码并减少内存泄漏的方法吗?

经过大量重构,最终起作用的是检查下一个字符是否不是 NUL,然后递增指针。