如何从scanf获取换行符,即使它是唯一的输入

use*_*675 7 c scanf

我正在做作业,要求我读取一个n表示循环大小的整数,然后读取一行字符n次,并在用户输入后立即打印.所以我使用scanf然后我用它打印printf.问题是,如果用户的输入只是一个换行符,它应该打印另一个\n,但scanf似乎忽略输入的单个\n.

有没有办法让这个任务scanf或我应该尝试别的吗?

int i;
scanf("%d", &i);
for(int ct=0; ct<i; ct++)
{
    char buff[28];
    scanf("%s", buff); // if I just press enter here
    prtinf("%s\n", buff); // then I must get \n\n here
}
Run Code Online (Sandbox Code Playgroud)

Dan*_*her 12

使用fgets读取行更简单,更健壮:

if (!fgets(buff, 28, stdin))
{
    // reading failed, do appropriate error handling
    // we're just exiting here
    exit(EXIT_FAILURE);
}
// We have successfully read in a line, or at least the first 27
// characters of the line. Check whether a full line was read,
// if it was, whether the line was empty
size_t l = strlen(buff);    // <string.h> must be included
if (buff[l-1] == '\n')
{
    // a full line was read, remove trailing newline unless
    // the line was empty
    if (l > 1)
    {
        buff[l-1] = 0;
    }
}
else
{
    // the input was too long, what now?
    // leave the remaining input for the next iteration or
    // empty the input buffer?
}
printf("%s\n",buff);
Run Code Online (Sandbox Code Playgroud)

它不起作用,scanf("%s",buff)因为大多数scanf转换会忽略前导空格:

输入的空白字符(由指定的isspace功能)被跳过,除非本说明书包括一个[,cn说明符.

因此,如果用户输入一个空行,则scanf忽略该输入,除非其格式是异常之一.

您可以使用scanf字符集格式,

scanf("%27[^\n]%*c", buff);
Run Code Online (Sandbox Code Playgroud)

读取所有字符直到换行符(但28 - 1这里仅限于避免缓冲区溢出),然后使用换行符而不存储换行符(*%*c转换说明符中禁止赋值),这将处理完全由空格组成的非空行,%s转换不会.但是如果输入的第一个字符是换行符,则%27[^\n]转换失败(感谢chux引起注意),换行符保留在输入缓冲区中,如果换行符不是,那么使用该格式的后续扫描也会失败从输入缓冲区中删除.

根据我的意见,使用的一个有点强大(但很难看;并且不处理太长的输入)循环scanf需要在扫描之前检查换行符,例如

for(int ct = 0; ct < i; ++ct)
{
    int ch = getchar();
    if (ch == EOF)
    {
        // something bad happened; we quit
        exit(EXIT_FAILURE);
    }
    if (ch == '\n')
    {
        // we had an empty line
        printf("\n\n");
    }
    else
    {
        // The first character was not a newline, scanning
        // with the character set format would have succeeded.
        // But we don't know what comes next, so we put the
        // character back first.
        // Although one character of pushback is guaranteed,
        if (ungetc(ch,stdin) == EOF)
        {
            // pushback failed
            exit(EXIT_FAILURE);
        }
        scanf("%27[^\n]%*c",buff);
        printf("%s\n",buff);
    }
}
Run Code Online (Sandbox Code Playgroud)

fgets,真的.这样更好.