【问题标题】:Is there a way to incrementally process format specifier strings in C?有没有办法在 C 中增量处理格式说明符字符串?
【发布时间】:2017-01-30 05:18:39
【问题描述】:

在嵌入式编程中,我经常会得到如下所示的代码:

void debug_terminal_printf(const char* format, va_list ap){
    char tmp[ARBITRARY_LIMITATION];
    vsprintf( tmp, format, ap );
    for(int pos=0; pos<strlen(tmp); pos++){
        if( tmp[pos] == 0 ) break;
        uart_putc( tmp[pos] );
    }
}

我希望我的接口提供字符串格式的便利,但通常格式化字符串的消费者是一次使用几个字节的格式化字符串的东西,如本例中的 UART。所以我最终在我的每个辅助函数中都有这些小的临时缓冲区。使用动态内存并不是很合适,因为动态内存的使用是在系统级别做出的决定,在嵌入式平台代码中使用它是不合适的。

希望能够做的是增量处理字符串,如下所示:

void debug_terminal_printf(const char* format, va_list ap){
    char tmp[MAX_TOKEN_SIZE];
    while(*format){
        int len = single_token_sprintf( tmp, format, ap );
        uart_puts(tmp);
        format += len;
    }
}

这样我就不需要足够的内存来存储整个格式化字符串,我可以等到硬件消耗完最后一个令牌,然后再继续解码下一个令牌。

有没有人见过像这样的(希望可移植的)习语,它可以摆脱对大型临时缓冲区的需求?

【问题讨论】:

  • 在注意到您关于运行时间的评论后,我删除了该评论。但是,您是否对堆栈内存如此紧张以至于无法使用本地缓冲区?
  • 通常串行访问可以通过fopen()处理,即使在嵌入式中,fprintf()是一个选项吗?
  • 我认为没有任何方法可以便携。您需要一些方法来挂钩stdio 流的输出缓冲。
  • @weather-van。现在,使用堆栈正是我正在做的。然而这是一件非常粗鲁的事情,因为一个人可能想要使用“调试打印”从具有数十字节堆栈的上下文中打印微小的字符串,而其他人可能想要从另一个上下文中打印一个巨大的 1KB 字符串堆栈不是问题。在我的环境中,变量堆栈转换为对 malloc() 的文字调用,因此这不是一个选项。我可以让调用者明确地提供必要的暂存空间,但是在某些时候我的函数会从“帮助者”变为“阻碍者”。
  • 可以处理寻找"%"format。如果使用的类型是像%d %s 这样的小型子集,那么代码可以使用switch(format_specifier) 处理调试打印一个参数一次

标签: c stream stdio standard-library format-specifiers


【解决方案1】:

非常感谢 @chux 引导我朝着正确的方向前进。

答案是可以挂钩运行时环境的 putc() 实现,以便在调用 fprintf 时,我可以一次使用一个字节的结果字符串。这是非常不便携的。对于每个环境,实现这一点的确切方法会有所不同。

就我而言(Keil 上的 Cortex M),Keil 在此处提供了说明: http://www.keil.com/support/man/docs/gsac/gsac_retargetcortex.htm

【讨论】:

    猜你喜欢
    • 2014-11-19
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 2020-03-01
    • 2020-11-22
    相关资源
    最近更新 更多