scanf(“%s”,&str)和scanf(“%s \ n”,&str)有什么区别?

时间:2020-04-16 10:39:43

标签: c scanf

输入

输入中将有几行以包含单个<!DOCTYPE html> <html> <h3>Tekstpiece</h3> <form> <div class="multiselect"> <div class="selectBox" onclick="showCheckboxes()"> <select> <option>Select an option</option> </select> <div class="overSelect"></div> <div id="checkboxes"> <label for="one"> <input type="checkbox" id="one" />First checkbox</label> <label for="two"> <input type="checkbox" id="two" />Second checkbox</label> <label for="three"> <input type="checkbox" id="three" />Third checkbox</label> </div> </div> </div> </form> </html> 的行结尾。最后一行 不应该被处理。每行将包含*Hajj

输出

对于输入的每一行,在单独的行中输出UmrahHajj-e-Akbar 报价。有关确切格式,请参阅示例。

这是我解决这个问题的代码。

Hajj-e-Asghar

对于输入

#include <stdio.h>

int main()
{
    char str[100];
    int i = 1;

    while (scanf("%s", &str))
    {
        if (str[0] == '*')
            break;
        else if (str[0] == 'H')
            printf("Case %d: Hajj-e-Akbar\n", i);
        else
            printf("Case %d: Hajj-e-Asghar\n", i);
        i++;
    }
}

当我一次提供此输入时,程序将通过打印提供预期的输出

Hajj
Umrah
*

但是在获得Hajj Case 1: Hajj-e-Akbar Umrah Case 2: Hajj-e-Asghar * 作为输入之后,程序正在等待*。按下Enter后,程序终止。但是我希望我的程序在得到Enter作为输入时终止,而不是通过按*来终止。请在这里帮助我。但这不是我的问题。我的问题是要输入相同的内容-

Enter

当我接受Hajj Umrah * 的输入时。该程序不会在第一个输入scanf("%s\n", &str)之后打印输出Case 1: Hajj-e-Akbar,但是会在获取第二个输入Hajj之后打印第一个输入的输出。然后,程序正在等待Umrah的输入Enter。 输出是这样的

*

然后按Hajj Umrah Case 1: Hajj-e-Akbar * ,它为第二个输入Enter打印输出Case 2: Hajj-e-Asghar 然后等待其他输入。按下Umrah后,输出看起来像这样。

Enter

我不明白Hajj Umrah Case 1: Hajj-e-Akbar * Case 2: Hajj-e-Asghar \n的影响。

谢谢。

对不起,如果我不能正确解释我的问题。我是编程新手。

2 个答案:

答案 0 :(得分:2)

scanf读取格式化的输入,因此当您使用%s\n”, &str时,字符串将被消耗并存储在str中,换行符也将被存储在“%s\n”, str中,当您按Enter键时,该字符将出现在缓冲区中,该字符串将被存储,而换行符将被丢弃。

请注意,正确的用法是str&已经是一个指针,您不应该使用“%s”, &str

当您使用str时,换行符将保留在缓冲区中并在下一个循环中使用,因此"\n"将存储在第一次迭代中,而str将被存储在下一次迭代中存储在scanf中,只有这样,才会在第三次迭代中再次要求您输入。

为完成操作,如下面的注释中所述,根据scanf的定义:

...格式字符串中的任何单个空格字符都会消耗输入中所有可用的连续空格字符(就像通过循环调用isspace来确定)。请注意,格式字符串中的“ \ n”,“”,“ \ t \ t”或其他空格没有区别。

我也建议您限制%99s所期望的字符串的大小,以避免容器溢出,对于像您这样的100个字符的容器,类似scanf,并检查{{1} }返回,在这种情况下,每个循环必须为= 1

要做的是,我收集的是从stdin获取一个字符而不按回车键,您将需要一种SO特定的方法,这是一个使用<conio.h>库的Windows小示例,并且getch()

#include <stdio.h>
#include <conio.h>

int main()
{
    int i = 1, c;

    while (1)
    {
        if ((c = getch()) == '*')
            return 0;
        else if (c == 'H')
            printf("Case %d: Hajj-e-Akbar\n", i);
        else
            printf("Case %d: Hajj-e-Asghar\n", i);
        i++;
    }
}

对于Linux,一种选择是也使用getch()<ncurses.h>库中的might need to install

PS:不用担心,您的问题是有根据的,特别是仅次于网站的问题。

答案 1 :(得分:1)

\n中结尾的scanf是一个坏主意:格式字符串中的任何空格字符都会导致从输入流中丢弃任何顺序的空格字符。如果要读取文件,则没有必要,但是如果您从终端读取,scanf()不会返回,直到您键入下一个项目,这会在您遇到问题时引起很大的混乱,因为程序的输出将与上一项相对应,而不是刚刚输入的内容。切勿在{{1​​}}格式字符串中添加尾随空格或换行符。

您应该测试scanf()是否返回scanf(),以避免在文件末尾返回1时产生无限循环。

还要注意,传递EOF是不正确的:&str是一个数组,将其传递为str会有效地将指针传递给它的第一个元素,这是正确的。

此外,您应该告诉str可以存储到目标数组中的最大字符数,以避免在输入过长时出现不确定的行为。由于数组的大小为scanf(),因此格式字符串应为100,以留出空终止符。

最后,您需要在最后一个"%99s"之后按 Enter ,这有3个综合原因,每个原因都会导致这种行为:

  • 默认情况下,终端设备驱动程序是行缓冲的,因此,在您键入 Enter 之前,输入才对程序可用。
  • 默认情况下,标准输入流(*)是行缓冲的,因此它将从系统句柄读取数据,直到获得换行符,然后stdin才有机会看到输入行的第一个字符。
  • scanf()将保留其输入流,直到它到达单词的末尾,空白字符或文件的末尾为止,因此当您仅键入scanf("%s", str)时它不会返回。

这是修改后的版本:

*