如何在不转到下一行的情况下在 C 中使用 printf() 和 scanf()?

How to use printf() and scanf() in C without going to the next line?

我想在一行中获取出生日期:

#include <stdio.h>

int main()
{
    int BirthYear,BirthMonth,BirthDay;
    printf("Please enter your birth date: ");
    scanf("%d",&BirthYear);
    printf("/");
    scanf("%d",&BirthMonth);
    printf("/");
    scanf("%d",&BirthDay);
    return 0;
}

这是我的输出:

Please enter your birth date: YYYY
/MM
/DD

但我想得到这样的东西:

Please enter your birth date: YYYY/MM/DD

在输出中,它在每个 scanf() 之后转到下一行而不使用 \n。 我使用 VS Code 进行 IDM。

#include <stdio.h>

int main()
{
    int BirthYear,BirthMonth,BirthDay;
    printf("Please enter your birth date: ");
    scanf("%d/%d/%d",&BirthYear,&BirthMonth,&BirthDay);
    return 0;
}

您可以从 scanf 中获取多个值,然后用您喜欢的任何文本分隔(在本例中为 /s)。

您可以通过在 scanf 函数的格式说明符中添加 '/' 字符来明确指定应该用 '/' 字符分隔三个输入数字。

然后,您可以通过检查 scanf 返回的值(这将是成功扫描和分配的项目数)来确保用户输入有效;如果该值不是 3,那么您将(可能)需要清除输入缓冲区中的任何 'leftover' 个字符,使用 getchar() 循环直到换行符(或 end-of-file ) 被发现:

#include <stdio.h>

int main()
{
    int BirthYear, BirthMonth, BirthDay;
    int nIns = 0, ch;
    while (nIns != 3) {
        printf("Enter D.O.B. (as YYYY/MM/DD): ");
        nIns = scanf("%d/%d/%d", &BirthYear, &BirthMonth, &BirthDay);
        while ((ch = getchar() != '\n') && (ch != EOF))
            ; // Clear remaining in-buffer on error
    }
    printf("Entered data were: %d %d %d!\n", BirthYear, BirthMonth, BirthDay);
    return 0;
}

这是一个使用 ansi 控制字符的解决方法。我不会这样做,只是为了证明这是可能的:

#define PREVLINE "3[F"
#define MSG "Please enter your birth date: "

int main(void) {
    int BirthYear,BirthMonth,BirthDay;
    
    printf(MSG);
    scanf("%d",&BirthYear);
    printf(PREVLINE MSG "%d/", BirthYear);
    scanf("%d",&BirthMonth);
    printf(PREVLINE MSG "%d/%d/", BirthYear, BirthMonth);
    scanf("%d",&BirthDay);
    printf("You entered: %d/%d/%d\n", BirthYear, BirthMonth, BirthDay);
}

请注意,这不是便携式的。终端需要支持这个才能工作。据我所知,没有 100% 可移植的方法来实现这一点。

如果你真的想做这些东西,我建议你看看the ncurses library

注:

始终检查 scanf 的 return 值以检测错误。

注2:

在每个 printf 语句后添加 fflush(stdout); 可能是个好主意。

其实我今天又写了一篇关于ascii控制字符的回答。这可能很有趣:

您可以像

那样使用 fflush(3) (in particular before all calls to scanf(3))
printf("Please enter your birth date: ");
fflush(NULL);

但你应该阅读 this C reference website, a good book about C programming such as Modern C, and the documentation of your C compiler (perhaps GCC) and debugger (perhaps GDB)。

考虑在编译器中启用所有警告和调试信息。使用 gcc 意味着使用 gcc -Wall -Wextra -g

进行编译

请注意 scanf(3) 可能会失败。

您的代码和问题肯定operating system具体。

在 Linux 考虑使用 ncurses (for a terminal interface) or GTK (for a graphical interface). Read also the tty demystified, then Advanced Linux Programming and syscalls(2) and termios(3)

您也可以考虑使用 ANSI escape codes, but be aware that in 2020 UTF-8 should be used everywhere

扩展我的评论...

您 运行 遇到的问题是您必须为每个输入按 Enter,这会在终端屏幕上写入一个换行符。你无法避免。

不幸的是,您无法用 '\b' 覆盖屏幕上的换行符;您只能退格到当前行的开头,不能退格到上一行。

你基本上不能用 vanilla C 做你想做的事——这种语言只能看到字节流,它没有“屏幕”的概念。

有一些 terminal control sequences 您可以在发送换行符后重新定位光标;我不知道这些对你的效果如何。

除此之外,您还需要使用 ncurses.

这样的库