在典型的 scanf() 调用中不会使用换行符

当这个程序

#include <stdio.h>
#include <string.h>

int main(void) {
    int num = 0;
    char str[128], *lf;

    scanf("%d", &num);
    fgets(str, sizeof(str), stdin);

    if ((lf = strchr(str, '\n')) != NULL) *lf = '\0';
    printf("%d \"%s\"\n", num, str);
    return 0;
}

使用此输入执行

42
life

输出将是 42 "" 而不是预期的 42 "life"

这是因为在 scanf() 的调用中没有消耗 42 之后的换行符,并且在读取 life 之前它被 fgets() 使用。然后,fgets() 在阅读 life 之前停止阅读。

为了避免这个问题,在知道线的最大长度 - 例如在线判断系统中解决问题时 - 有用的一种方法是避免直接使用 scanf() 并通过 fgets() 读取所有线。你可以使用 sscanf() 来解析读取的行。

#include <stdio.h>
#include <string.h>

int main(void) {
    int num = 0;
    char line_buffer[128] = "", str[128], *lf;

    fgets(line_buffer, sizeof(line_buffer), stdin);
    sscanf(line_buffer, "%d", &num);
    fgets(str, sizeof(str), stdin);

    if ((lf = strchr(str, '\n')) != NULL) *lf = '\0';
    printf("%d \"%s\"\n", num, str);
    return 0;
}

另一种方法是在使用 scanf() 之后和使用 fgets() 之前读取直到你击中换行符。

#include <stdio.h>
#include <string.h>

int main(void) {
    int num = 0;
    char str[128], *lf;
    int c;

    scanf("%d", &num);
    while ((c = getchar()) != '\n' && c != EOF);
    fgets(str, sizeof(str), stdin);

    if ((lf = strchr(str, '\n')) != NULL) *lf = '\0';
    printf("%d \"%s\"\n", num, str);
    return 0;
}