gpt4 book ai didi

c - 跳过第一个输入,直接转到下一个输入

转载 作者:行者123 更新时间:2023-11-30 19:36:17 27 4
gpt4 key购买 nike

我的简单登录程序代码遇到了问题。我面临的问题是,当我使用开关盒或if语句(以管理员或用户身份登录)时,用户名的输入将被跳过并直接输入密码,无论我输入什么,它都会给我我的错误讯息。相反,我希望它先接收我的用户名,然后再接收密码。如果只有“管理员”或“用户”的代码,而只有一个,而没有多个代码,则它不能单独工作。请帮忙。注意:我正在为管理员和用户使用相同的功能,只是为了检查它是否有效。图为输出,我是C新手,所以可能是最小的术语?代码如下:

#include<stdio.h>
#include<conio.h>
#include<stdlib.h>
char username[18];
char pass[16];

void arequest()
{
printf("\nPlease Enter username:");
fflush(stdin);
gets(username);

printf("\nPlease Enter Password:");
fflush(stdin);
gets(pass);
}

void averify()
{
if (strcmp(username, "admin") == 0)
{
if (strcmp(pass, "apass") == 0)
{
printf("Successful Login");
_getch();
}
else
{
printf("Invalid Password");
_getch;
}
}
else
{
printf("Invalid Username");
_getch();
}
}

int choice;
int main()
{
printf("Welcome to Railway Reservation System");
printf("\n1.Admin \n2.User");
printf("\nPlease Enter your selection:");
scanf_s("%d", &choice);
if (choice == 1)
{
arequest();
averify();
}
else if (choice == 2)
{
arequest();
averify();
}
else
{
printf("Invalid Choice");
_getch();
return main;
}
return 1;
}


output

最佳答案

您正在使用fflush()刷新输入流。 fflush(stdin)在大多数情况下是未定义的行为,并且最多取决于实现。要清除输入流中的多余字符,请考虑编写如下这样的小函数:

void clear_stream(void)
{
int c;

while ((c = _getch()) != '\n' && c != EOF)
continue;
}


删除对 fflush()的呼叫。您无需在 gets(username)之后清除流,因为 gets()会丢弃换行符。在 clear_stream()中的此行之后添加对 main()的呼叫:

scanf_s("%d", &choice);


在调用 scanf_s()之后,输入流中可能会留有多余的字符,包括换行符,并且在尝试再次读取用户输入之前需要删除这些字符。在某些情况下, scanf()_s(和 scanf())将在读取输入时跳过初始空格,但 _getch()getchar()不会。这说明了使用 scanf()的危险之一。

printf("\nPlease Enter your selection:");
scanf("%d", &choice);
clear_stream();


另外, gets()被认为是如此危险,以至于根本没有理由将其用于任何用途。请改用 fgets()fgets()确实保留换行符,而 gets()在其中删除它,因此我经常使用安全的 gets()编写自己的 fgets()版本:

char * s_gets(char *st, int n)
{
char *ret;
int ch;

ret = fgets(st, n, stdin);
if (ret) {
while (*st != '\n' && *st != '\0')
++st;
if (*st)
*st = '\0';
else {
while ((ch = getchar()) != '\n' && ch != EOF)
continue; // discard extra characters
}
}
return ret;
}


conio.h是非标准的,函数 _getch()scanf_s()也是非标准的。您应该使用 stdio.h函数 getchar()scanf()scanf()返回的值是成功分配的数量,您应该检查一下以确保输入符合预期。在您的程序中,如果用户在选择提示下输入字母,则不会进行分配,并且 choice的值仍未初始化。该代码继续而不处理此问题。 choice可以初始化为某个合理的值,例如 int choice = -1;。或者,您可以检查 scanf()的返回值以查看是否进行了赋值,然后进行相应的操作。

我注意到您从 returnmain()正在1。除非出现错误,否则您应该 return 0。而且,如果选择无效,我会看到您 return main。也许您是要在这里 return 1?看来您忘记了 #include <string.h>功能。

最后,我不明白为什么 strcmp()usernamepass是全局变量。这是一个坏习惯。这些应该在 choice中声明,并根据需要传递给函数。 main()全局常量 #defineMAXNAME而不是硬编码数组维是一个好主意。

开始时,我并不打算将其作为全面的代码审查,但这就是它的结果。这是程序的修订版本,可实现建议的更改:

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

#define MAXNAME 18
#define MAXPASS 16

void clear_stream(void)
{
int c;

while ((c = getchar()) != '\n' && c != EOF)
continue;
}

char * s_gets(char *st, int n)
{
char *ret;
int ch;

ret = fgets(st, n, stdin);
if (ret) {
while (*st != '\n' && *st != '\0')
++st;
if (*st)
*st = '\0';
else {
while ((ch = getchar()) != '\n' && ch != EOF)
continue; // discard extra characters
}
}
return ret;
}

void arequest(char username[MAXNAME], char pass[MAXPASS])
{
printf("\nPlease Enter username:");
s_gets(username, MAXNAME);

printf("\nPlease Enter Password:");
s_gets(pass, MAXPASS);
}

void averify(char username[MAXNAME], char pass[MAXPASS])
{
if (strcmp(username, "admin") == 0)
{
if (strcmp(pass, "apass") == 0)
{
printf("Successful Login");
getchar();
}
else
{
printf("Invalid Password");
getchar();
}
}
else
{
printf("Invalid Username");
getchar();
}
}


int main(void)
{
char username[MAXNAME];
char pass[MAXPASS];
int choice;

printf("Welcome to Railway Reservation System");
printf("\n1.Admin \n2.User");
printf("\nPlease Enter your selection: ");
if (scanf("%d", &choice) == 1) {
clear_stream();
if (choice == 1)
{
arequest(username, pass);
averify(username, pass);
}
else if (choice == 2)
{
arequest(username, pass);
averify(username, pass);
}
else
{
printf("Invalid Choice: %d\n", choice);
getchar();
return 1;
}
} else {
clear_stream(); // stream has not yet been cleared
printf("Nonnumeric input");
getchar();
}

return 0;
}


编辑

注释中提到的OP MAXPASS在Visual Studio中引起了问题。显然,Visual Studio尝试强制使用 scanf()。此功能的问题不在于它本身是不好的,还在于它是非标准的。一种解决方案可能是使用已经添加到代码中的 scanf_s()函数将用户选择读入字符缓冲区,然后使用 s_gets()提取输入。这样做的优点是,无需在 sscanf()之后调用 clear_stream()函数,因为 s_gets()会在其自身之后清除,因此现在可以将 s_gets()函数从程序中完全删除。只需在 clear_stream()中进行少量更改即可完成:

char choice_buffer[10];
int choice;

...

if (s_gets(choice_buffer, sizeof(choice_buffer)) &&
sscanf(choice_buffer, "%d", &choice) == 1) {
if (choice == 1)

...

} else {
printf("Nonnumeric input");
getchar();
}


main()最多读取用户输入到 s_gets()的一行的前9个字符(在这种情况下),该数组将容纳 choice_buffer s( char中的空间超出了所需的空间)按住一个数字和一个 choice_buffer)。如果存在错误,则 '\0'返回 s_gets()指针,否则返回指向 NULL的第一个 char的指针。如果 choice_buffer的返回值不是- s_gets(),则 NULL将缓冲区中存储的第一个 sscanf()分配给 int。如果在字符串中未找到 choice,则 int返回值0,从而导致条件测试失败。

关于c - 跳过第一个输入,直接转到下一个输入,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/41158761/

27 4 0
Copyright 2021 - 2024 cfsdn All Rights Reserved 蜀ICP备2022000587号
广告合作:1813099741@qq.com 6ren.com