如何从scanf函数获取换行符即使它是唯一的输入 [英] How to get newline character from scanf even if it's the only input

查看:528
本文介绍了如何从scanf函数获取换行符即使它是唯一的输入的处理方法,对大家解决问题具有一定的参考价值,需要的朋友们下面随着小编来一起学习吧!

问题描述

我在做家庭作业,要求我读一个整数 N 重新presenting循环的大小,然后读取一行字符<$ C $ ç> N 时间和用户的输入之后打印出来。所以我用 scanf函数,然后我跟打印的printf 。问题是,如果用户输入只是一个换行符,它应该打印另一 \\ n ,但 scanf函数似乎忽略输入时,它的一个 \\ n

有没有什么办法让这个作业和 scanf函数或者我应该试试别的?

  INT I;
scanf函数(%d个,&安培; I)
对于(INT克拉= 0; CT&LT;我; CT ++)
{
    字符的buff [28];
    scanf函数(%S,浅黄色); //如果我只是preSS进入这里
    PRTINF(%S \\ n,浅黄色); //那么我必须\\ n \\ n这里
}


解决方案

使用与fgets 在一条线上阅读更简单,更强大的:

 如果(!与fgets(BUFF,28,标准输入))
{
    //读取失败,执行相应的错误处理
    //我们只是在这里退出
    出口(EXIT_FAILURE);
}
//我们已成功读取在一条线上,或至少第一27
//行字符。检查全行是否被读取,
//如果是,线路是否是空的
为size_t L = strlen的(BUFF); //&LT;&string.h中GT;必须包含
如果(BUFF [L-1] =='\\ n')
{
    //全线被读取,删除尾随换行符,除非
    //行是空的
    如果(L→1)
    {
        抛光轮[1- 1] = 0;
    }
}
其他
{
    //输入太长,现在该怎么办?
    //离开其余的输入为下一次迭代或
    //清空输入缓冲器?
}
的printf(%S \\ n,浅黄色);

这不符合工作scanf函数(%S,BUFF),因为大多数 scanf函数转换忽略前导空格:


  

输入空白字符(由 isspace为函数指定)被跳过,除非
  该规范包括 [ C N 说明


因此​​,如果用户输入一个空行, scanf函数忽略输入,除非它的格式是例外之一。

您可以使用 scanf函数用字符集格式而不是,

  scanf函数(%27 [^ \\ n]的%* C,浅黄色);

读取所有的字符,直到一个换行符(但不限于 28 - 1 在这里,以避免缓冲区溢出),然后消耗换行而不保存它( * %* C 转换说明燮presses分配),将手柄完全由空白的非空行,其中%S 转换不会。但是,如果输入的第一个字符是换行,那么 27%[^ \\ n] 转换失败(感谢的 chux 提请注意这一点),换行留在输入缓冲区,如果换行不从输入缓冲区取出随后与该格式扫描也不能通过。

一个稍微强大的(但丑;不处理太长输入)使用循环 scanf函数会,就我所看到的,前需要检查一个换行符扫描,如:

 的for(int克拉= 0; CT&LT;我++ CT)
{
    INT CH =的getchar();
    如果(CH == EOF)
    {
        //坏事发生;我们退出
        出口(EXIT_FAILURE);
    }
    如果(CH =='\\ n')
    {
        //我们有一个空行
        的printf(\\ n \\ n);
    }
    其他
    {
        //第一个字符不是一个换行符,扫描
        //使用的字符集的格式将成功。
        //但是我们不知道接下来会发生什么,所以我们把
        //字符回到第一位。
        //虽然推回一个字符的保证,
        如果(与ungetc(CH,标准输入)== EOF)
        {
            //失败后推
            出口(EXIT_FAILURE);
        }
        scanf函数(%27 [^ \\ n]的%* C,浅黄色);
        的printf(%S \\ n,浅黄色);
    }
}

使用与fgets ,真的。这是更好的。

I'm doing homework that asks me to read an integer n representing the size of a loop and then read a line of characters n times and print it right after the user's input. So I used scanf and then I print it with printf. The problem is that if the user's input is only a newline character, it should print another \n, but scanf seems to ignore the input when it's a single \n.

Is there any way to make this assignment with scanf or should I try something else?

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
}

解决方案

Using fgets to read in a line is simpler and more robust:

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);

It doesn't work with scanf("%s",buff) because most scanf conversions ignore leading white space:

Input white-space characters (as specified by the isspace function) are skipped, unless the specification includes a [, c, or n specifier.

So if the user inputs an empty line, scanf ignores that input unless its format is one of the exceptional.

You can use scanf with a character set format instead,

scanf("%27[^\n]%*c", buff);

to read all characters until a newline (but limited to 28 - 1 here to avoid buffer overruns), and then consume a newline without storing it (the * in the %*c conversion specifier suppresses assignment), that would handle non-empty lines consisting entirely of whitespace, which the %s conversion would not. But if the first character of the input is a newline, the %27[^\n] conversion fails (thanks to chux for drawing attention to that), the newline is left in the input buffer, and subsequent scans with that format would also fail if the newline isn't removed from the input buffer.

A somewhat robust (but ugly; and not dealing with too long input) loop using scanf would, as far as I can see, need to check for a newline before scanning, e.g.

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);
    }
}

Use fgets, really. It's better.

这篇关于如何从scanf函数获取换行符即使它是唯一的输入的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持IT屋!

查看全文
登录 关闭
扫码关注1秒登录
发送“验证码”获取 | 15天全站免登陆