【问题标题】:Treatment of \b in template strings to printf in C将模板字符串中的 \b 处理为 C 中的 printf
【发布时间】:2017-12-06 03:05:24
【问题描述】:

有人可以解释一下或给我一个参考,解释为什么在第一个打印的行下方的代码 sn-ps 中包含整个单词 hello,而在第二个中它只包含字母 he ?我认为无论换行符如何,退格转义字符都会删除最后三个字母。我已经阅读了printf 上的 GNU 文档,但找不到任何相关内容。

int main(void)
{
    printf("hello\b\b\b\n");        
    return 0;
}



int main(void)
{
    printf("hello\b\b\b");
    return 0;
}

【问题讨论】:

    标签: c terminal escaping printf


    【解决方案1】:

    要记住的两个关键事项:

    1. 当您使用printf() 时,不会立即呈现到控制台的输出:输出被缓冲。立即(同步)将输出缓冲区刷新到控制台的两种方法是通过printf("\n") 打印换行符,或通过fflush(stdout) 手动刷新缓冲区。
    2. 如果您使用\b 转义序列,您会将光标向后/向左移动一个“空格”,但打印换行符不一定会清除该行的其余部分。如果您要手动在旧字符上打印新字符(即printf("Hello\b\b\b \n")),输出将更像您的预期。

    Additionally, if you want to do some advanced command-line menus, graphics, etc, you'll need to use something like libncurses.

    最后,以下示例应该有助于更好地了解涉及您的问题的典型行为。

    #include <stdio.h>
    #include <unistd.h>
    
    #define DELAY   (2) /* seconds */
    
    int main(void)
    {
    
        printf("Example DELAY:\n");
        printf("------------------------------------------------------------------------\n");
        printf("hello\b\b\b\n");
        sleep(DELAY);
        printf("\n\n");
    
        printf("Example 2:\n");
        printf("------------------------------------------------------------------------\n");
        printf("hello\b\b\b");
        sleep(DELAY);
        printf("...");
        sleep(DELAY);
        fflush(stdout);
        sleep(DELAY);
        printf("\n\n");
    
        printf("Example 3:\n");
        printf("------------------------------------------------------------------------\n");
        fflush(stdout);
        printf("hello\b\b\b");
        fflush(stdout);
        sleep(DELAY);
        printf("...");
        sleep(DELAY);
        fflush(stdout);
        sleep(DELAY);
        printf("\n\n");
    
        return 0;
    }
    

    【讨论】:

    • 很好的例子。一个快速的后续问题:为什么#define DELAY (2) 语句中的大括号?
    • @BruceM 在这个例子中这有点矫枉过正,但它是为了避免某些情况下宏没有像你期望的那样扩展。类似于多行宏通常包含在do { ... } while(0) 语句中的方式。如果您查看 PC-Lint、MISRA 标准等,您会发现有关此类编码风格的更多信息。
    【解决方案2】:

    这实际上不是关于 C 或 printf 的问题。在每种情况下,代码都完全按照它所说的进行:在第一个示例中,它输出 9 个字符 h e l l o \b \b \b \n,而在第二个示例中,它同样输出 8 个字符。如果您将标准输出写入文件,则该文件将包含该文件。但是,如果您写信给终端,您的终端可能会通过退格处理\b,因此您的问题实际上是关于您的终端的。你还没说你用的是什么终端。

    退格字符的一种常见行为方式是将光标向左移动一个位置,但实际上并未擦除该位置的字符。下一个字符输出将覆盖它。

    在您的第一个示例中,您将光标移回第一个 l,但您永远不会在其上写任何内容或任何其他字符。然后\n 不会改变屏幕上的任何字符,只是将光标移动到下一行。所以你仍然会在前一行看到hello

    在您的第二个示例中,当您的程序终止时,光标留在第一个 l 上。因此,下一个将输出写入终端的程序将覆盖该字符(除非下一个程序的第一个写入是\n 或类似的东西)。下一个程序可能是您的 shell,因此您的 shell 提示符中的字符可能会覆盖 llo,因此您看不到它们。

    【讨论】:

      猜你喜欢
      • 2014-05-04
      • 2021-03-15
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 2018-05-02
      • 1970-01-01
      相关资源
      最近更新 更多