用于char的Scanf输入一次为空

时间:2015-07-13 06:47:16

标签: c scanf

我想在我编写的代码中引用name的输入,但由于某些原因我在第一个printf()中成功使用它后,第二个printf()无法打印这个名字。

int main()
{
    char name[50]; 
    char q1[1];
    printf( " What is your name?\n");
    scanf("%s", name);
    printf( " Hi %s, Do you want to have some fun? [Y/N]\n",name);
    scanf("%s",q1);

    if(strcmp(q1,"Y") == 0||strcmp(q1,"y")==0)
    {
        printf("Awesome, let's play!\n");
    }
    else
    {
        printf("Fine"); goto endgame;
    }
    printf( "So %s, it's time to get started\n", name);
    endgame:
        getchar();
    return 0;
}

条目的输出'尼克'是:

  你好尼克,你想要玩得开心吗?很棒的让我玩耍所以,   让我们开始吧

我希望它能说:

  

所以尼克,让我们开始吧。

但由于某些原因,第一次正确使用后,char name为空。

2 个答案:

答案 0 :(得分:4)

问题,(我假设正确)是char q1[1];然后使用

 scanf("%s",q1);

它导致内存边界溢出,因为一个char字符数组不足以容纳只有一个元素的字符串,因为它缺少空间终止符所需的空间。 字符串。这会调用undefined behaviour

相反,

  • char q1[1];更改为char q1;
  • scanf("%s",q1);更改为scanf(" %c", &q1);
  • if(strcmp(q1,"Y") == 0||strcmp(q1,"y")==0)更改为if((q1 =='Y') || q1 == 'y')

那说,作为一个说明,

  1. main()的推荐签名为int main(void)
  2. 为了避免更长输入缓冲区溢出的可能性,最好通过写入<{1}}来限制输入的长度{ / p>

    scanf()

答案 1 :(得分:2)

扩展q1缓冲区的大小。 scanf("%s", q1)没有足够的空间存储输入内容。请记住,C使用空字符'\0'来终止字符串。如果您没有考虑到这一点,缓冲区可能会溢出到导致undefined behavior的其他内存中。在这种情况下,它可能会覆盖分配给name的内存,因此name最终会指向&#34; \ 0ick&#34;。这导致printf(%s)查找'\0'知道何时停止打印,认为字符串比实际更短。

如果扩展缓冲区,代码可以正常工作:

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

int main(void)
{
    char name[50];
    char q1[50];
    printf( " What is your name?\n");
    scanf("%49s", name);
    printf( " Hi %s, Do you want to have some fun? [Y/N]\n",name);
    scanf("%49s",q1);

    if(strcmp(q1,"Y") == 0||strcmp(q1,"y")==0)
    {
        printf("Awesome, let's play!\n");
    }
    else
    {
        printf("Fine");
    }
    printf( "So %s, it's time to get started\n", name);
    getchar();
    return 0;
}

输出:

 What is your name?
Nick
 Hi Nick, Do you want to have some fun? [Y/N]
y
Awesome, let's play!
So Nick, it's time to get started

请注意,我已添加限定符%49s以避免此类缓冲区溢出。

您还可以通过将char q1[50]scanf("%49s")更改为char q1scanf("%c%*c", &q1)来完全避开对其他字符串的需求(请注意&#34;&#34;地址&#34 ;运算符,因为q1不再是指针。)

你甚至可能从中获得性能提升(虽然很小),因为琴弦是臭名昭着的记忆障碍物。比较单个字符通常比比较字符串更受欢迎。

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

int main(void)
{
    char name[50];
    char q1;
    printf( " What is your name?\n");
    scanf("%49s%*c", name);
    printf( " Hi %s, Do you want to have some fun? [Y/N]\n",name);
    scanf("%c%*c",&q1);

    if(q1 == 'Y' || q1 == 'y')
    {
        printf("Awesome, let's play!\n");
    }
    else
    {
        printf("Fine");
    }
    printf( "So %s, it's time to get started\n", name);
    getchar();
    return 0;
}
    if(q1 == 'Y' || q1 == 'y')
    {
        printf("Awesome, let's play!\n");
    }
    else
    {
        printf("Fine");
    }
    printf( "So %s, it's time to get started\n", name);
    getchar();
    return 0;
}

如果你走这条路线,你必须使用格式说明符%*c忽略输入键,因为按Enter键也会向流发送一个键。