Warning: file_get_contents(/data/phpspider/zhask/data//catemap/7/user-interface/2.json): failed to open stream: No such file or directory in /data/phpspider/zhask/libs/function.php on line 167

Warning: Invalid argument supplied for foreach() in /data/phpspider/zhask/libs/tag.function.php on line 1116

Notice: Undefined index: in /data/phpspider/zhask/libs/function.php on line 180

Warning: array_chunk() expects parameter 1 to be array, null given in /data/phpspider/zhask/libs/function.php on line 181
使用scanf时意外地执行C程序无限循环_C_Scanf_Infinite Loop - Fatal编程技术网

使用scanf时意外地执行C程序无限循环

使用scanf时意外地执行C程序无限循环,c,scanf,infinite-loop,C,Scanf,Infinite Loop,我到处检查,浪费了大约3个小时寻找解决方案。我的程序只是无限循环本身。这是我的C程序: #include <stdio.h> #include <string.h> int main (void) { int attempts = 0; char password[10]; do { printf("Enter your password:\n"); scanf("%[^\n]s", password)

我到处检查,浪费了大约3个小时寻找解决方案。我的程序只是无限循环本身。这是我的C程序:

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

int main (void)

{
    int attempts = 0;
    char password[10];

    do
    {
        printf("Enter your password:\n");
        scanf("%[^\n]s", password);
        printf("\n");
        attempts++;
    } while (strcmp(password, "awesome 123 ok"));

    printf("You entered a correct password in %d attempts!", attempts);

    return 0;
}
#包括
#包括
内部主(空)
{
int=0;
字符密码[10];
做
{
printf(“输入密码:\n”);
scanf(“%[^\n]s”,密码);
printf(“\n”);
尝试++;
}而(strcmp(密码,“ok”);
printf(“您在%d次尝试中输入了正确的密码!”,次尝试);
返回0;
}

我尝试了
scanf(“%[A-Za-z0-9]s”,password)”
,这样它可以将所有字符和数字(包括空格)作为输入,但它只是循环。我也尝试了使用
getchar()
,但即使我输入了正确的密码,它也会一次又一次地要求输入密码。我们将感谢您的帮助。

您声明
char password[10]
但您可以将其与包含更多字符的
进行比较。

您可以声明
字符密码[10];
但您可以将其与具有更多字符的
awesome 123 ok
进行比较。

awesome 123 ok
的大小为15,包括
\0
。但是您正在为10个字节分配内存。这会导致未定义的行为

当您使用
%[^\n]
格式说明符时,无需使用
s
,它也会自动扫描空格

尝试以下更改-

int main (void)

{
    int attempts = 0;
    char password[20]; // Fix 1

    do
    {
        printf("Enter your password:\n");
        scanf("%[^\n]", password); // Fix 2
        printf("\n");
        attempts++;
    } while (strcmp(password, "awesome 123 ok"));

    printf("You entered a correct password in %d attempts!", attempts);

    return 0;
}

ok
的大小为15,包括
\0
。但您正在为10个字节分配内存。这会导致未定义的行为

当您使用
%[^\n]
格式说明符时,无需使用
s
,它也会自动扫描空格

尝试以下更改-

int main (void)

{
    int attempts = 0;
    char password[20]; // Fix 1

    do
    {
        printf("Enter your password:\n");
        scanf("%[^\n]", password); // Fix 2
        printf("\n");
        attempts++;
    } while (strcmp(password, "awesome 123 ok"));

    printf("You entered a correct password in %d attempts!", attempts);

    return 0;
}
发件人:

在尝试分析输入之前,[、c和n以外的所有转换说明符都会使用并丢弃所有前导空格字符

这意味着在循环中对
scanf
的下一次调用中将包括尾随的换行符(一个空白字符)

解决方案很简单:告诉
scanf
读取并丢弃前导空格:

scanf(" %[^\n]", password);
/*     ^              */
/*     |              */
/* Note leading space */
还要注意的是,我删除了格式中的尾随
s
,因为这告诉
scanf
在输入中预期一个文本
s


您可能还希望限制读取的字符数,以免读取到的缓冲区溢出:

scanf(" %9[^\n]", password);
请注意,上述格式将最大字段宽度设置为九个字符,因为缓冲区还需要包含终止的
'\0'
字符。如果增加缓冲区大小,请修改此数字,但请记住,它(最多)应比缓冲区大小小一个。

From:

在尝试分析输入之前,[、c和n以外的所有转换说明符都会使用并丢弃所有前导空格字符

这意味着在循环中对
scanf
的下一次调用中将包括尾随的换行符(一个空白字符)

解决方案很简单:告诉
scanf
读取并丢弃前导空格:

scanf(" %[^\n]", password);
/*     ^              */
/*     |              */
/* Note leading space */
还要注意的是,我删除了格式中的尾随
s
,因为这告诉
scanf
在输入中预期一个文本
s


您可能还希望限制读取的字符数,以免读取到的缓冲区溢出:

scanf(" %9[^\n]", password);

请注意,上述格式将最大字段宽度设置为九个字符,因为缓冲区还需要包含终止的
'\0'
字符。如果增加缓冲区大小,请修改此数字,但请记住,它最多应比缓冲区大小小一个。

将dec密码[10]更改为密码[20]

将dec密码[10]更改为密码[20]

添加
getchar()
以使用
\n
字符。在下面找到修改后的代码

int main (void)

{
    int attempts = 0;
    char password[10];

    do
    {
        printf("Enter your password:\n");
        scanf("%[^\n]s", password);
        getchar (); // Fix1

        printf("\n");
        attempts++;
    } while (strcmp(password, "awesome 123 ok"));

    printf("You entered a correct password in %d attempts!", attempts);

    return 0;
}
您的代码中未正确使用数组
密码
。因此,请更改其逻辑。用户可以输入N个字符。因此,请将用户输入限制为有限字符,或使用动态内存分配

添加
getchar()
以使用
\N
字符。请在下面找到修改后的代码

int main (void)

{
    int attempts = 0;
    char password[10];

    do
    {
        printf("Enter your password:\n");
        scanf("%[^\n]s", password);
        getchar (); // Fix1

        printf("\n");
        attempts++;
    } while (strcmp(password, "awesome 123 ok"));

    printf("You entered a correct password in %d attempts!", attempts);

    return 0;
}

数组
密码
未在代码中正确使用。因此,请更改其逻辑。用户可以输入N个字符。因此,将用户输入限制为有限字符或使用动态内存分配

问题在于
密码
太窄。因此,程序通常会写入数组末尾y、 导致

您可以通过将
密码
加宽来解决此问题。但是,您的程序仍然会受到以下攻击:攻击者可以通过输入精心编制的长密码字符串来执行任意代码

要解决这个问题,您需要更改
scanf()
格式说明符,以限制它在
password
中可以存储的字符数

以下更改将修复这两个问题:

    char password[32]; /* more space: 31 characters + NUL */
    do {
        ...
        scanf("%31[^\n]%*c", password); /* format specifier */

后者将确保您在
password
中读取的字符数永远不会超过31个;它还会在不存储换行符的情况下使用换行符。

问题在于
password
太窄。因此,程序通常会写入数组末尾,从而导致错误

您可以通过将
密码
加宽来解决此问题。但是,您的程序仍然会受到以下攻击:攻击者可以通过输入精心编制的长密码字符串来执行任意代码

要解决这个问题,您需要更改
scanf()
格式说明符,以限制它在
password
中可以存储的字符数

以下更改将修复这两个问题:

    char password[32]; /* more space: 31 characters + NUL */
    do {
        ...
        scanf("%31[^\n]%*c", password); /* format specifier */
后者将确保您在
密码
;i中读取的字符不会超过31个