C语言仿Instagram程序菜单输入异常问题排查求助
问题排查与修复:Diogram程序菜单输入异常问题
问题描述
我编写了一个仿Instagram的Diogram程序,正常选择1(创建账户)或2(登录)时功能正常。但输入其他数字后,程序提示需选择1-2,此时再输入1或2,程序直接终止,需排查问题并修复。
原代码如下:
#define CRT_SECURE_NO_WARNINGS #include <stdio.h> #include <stdlib.h> #include <string.h> #define BOARD_SIZE 15 // Setting the board size #define CHAIN 5 void init_board(char board[BOARD_SIZE][BOARD_SIZE], int size); /* Creating the functions */ void print_board(char board[BOARD_SIZE][BOARD_SIZE], int size); struct CREATEacc { char username[16]; // Struct for creating an account char password[20]; }ca; struct signIn { char userACC[16]; // Struct for signing in char kodikos[20]; }si; int main(int argc, char* argv) { struct CREATEacc userchoice; // Users actions stored here struct signIn details; // Users actions stored here int choice, uchoice, uschoice, size, col = 17, row = 19; // Some integers that are needed for below char board[BOARD_SIZE][BOARD_SIZE]; size = BOARD_SIZE; printf("Welcome to Diogram\n"); printf("1. Create an account.\n"); // Diogram menu printf("2. Already have an account? Sign in.\n"); scanf("%d", &choice); // If user selects 1 then this is the code for creating an account if (choice == 1) { printf("Username: \n"); scanf("%15s", &userchoice.username); fgets(ca.username, sizeof(ca.username), stdin); printf("Password: \n"); scanf("%19s", &userchoice.password); fgets(ca.password, sizeof(ca.password), stdin); printf("Username: %s\nPassword: %s\n", userchoice.username, userchoice.password); printf("Account succesfully created!\n\n\n"); printf("Welcome, %s\n"); printf("1.HOME 2.SEARCH 3.PROFILE"); init_board(board, size); print_board(board, size); do { printf("\n\nHOME SEARCH PROFILE\n"); // Printing parts of the app scanf("%d", &uchoice); // Scans what the user selects if (uchoice == 1) { printf("\n\n1.HOME 2.SEARCH 3.PROFILE"); // If selected, User's Diogram Home opens init_board(board, size); // Calling function to initiate the board print_board(board, size); // Printing the board } else if (uchoice == 2) // If selected, User's Diogram Search opens { printf("\n\n1.HOME 2.SEARCH 3.PROFILE"); printf("\nSearch an account here: "); scanf("%s"); printf("Oops! Looks like you're the only one using Diogram :(\nGo back?\n"); } else if (uchoice == 3) // If selected, User's Diogram Profile opens { printf("\n\n1.HOME 2.SEARCH 3.PROFILE 4.EXIT\n"); printf(" ____\n| |\n|____|\n%s\n\nPOSTS\n", userchoice.username); init_board(board, size); // Calling function to initiate the board print_board(board, size); // Printing the board } while (uchoice == 4) // If selected, user has the option to exit, and therefore end the program { char ch; // Character for checking Y/N printf("\n\nAre you sure you want to log out(y/n)?\n"); scanf (" %c", &ch); // Scanning users anwser // If nor y or n pressed, it does nothing until user finally picks y or n while (ch !='y' && ch !='n') { scanf("%c", &ch); } if ( ch == 'y') { printf("Logged out succesfully!\n "); exit(EXIT_SUCCESS); // Use exit() function to terminate the execution of the program } if (ch == 'n') // If user picks 'n' then it reverts back to his Diogram Profile { printf("\n\n1.HOME 2.SEARCH 3.PROFILE 4.EXIT\n"); printf(" ____\n| |\n|____|\n%s\n\nPOSTS\n", userchoice.username); init_board(board, size); print_board(board, size); printf("\n\nHOME SEARCH PROFILE\n EXIT\n"); scanf("%d", &uchoice); } } } while (uchoice !=4); // All of that on a do while loop so it never ends unless user decides to exit } // If user selects 2 then this is the code for signing in else if (choice == 2) { printf("Username: \n"); scanf("%15s", &details.userACC); fgets(si.userACC, sizeof(si.userACC), stdin); printf("Password: \n"); scanf("%s", &details.kodikos); // User details printf("Logged in succesfully!\n"); printf("Welcome back %s!\n", details.userACC); printf("1.HOME 2.SEARCH 3.PROFILE"); init_board(board, size); print_board(board, size); do { printf("\n\nHOME SEARCH PROFILE\n"); // Printing parts of the app scanf("%d", &uschoice); // Scans what the user selects if (uschoice == 1) // If selected, User's Diogram Home opens { printf("\n\n1.HOME 2.SEARCH 3.PROFILE"); // Printing parts of the app init_board(board, size); // Calling function to initiate the board print_board(board, size); // Printing the board } else if (uschoice == 2) // If selected, User's Diogram Search opens { printf("\n\n1.HOME 2.SEARCH 3.PROFILE"); printf("\nSearch an account here: "); scanf("%s"); printf("Oops! Looks like you're the only one using Diogram :(\nGo back?\n"); } else if (uschoice == 3) // If selected, User's Diogram Profile opens { printf("\n\n1.HOME 2.SEARCH 3.PROFILE 4.EXIT\n"); // Printing parts of the app printf(" ____\n| |\n|____|\n%s\n\nPOSTS\n", details.userACC); init_board(board, size); // Calling function to initiate the board print_board(board, size); // Printing the board } while (uschoice == 4) // If selected, user has the option to exit, and therefore end the program { char ch; // Character for checking Y/N printf("\n\nAre you sure you want to log out(y/n)?\n"); scanf (" %c", &ch); // Scanning users anwser // If nor y or n pressed, it does nothing until user finally picks y or n while (ch !='y' && ch !='n') { scanf("%c", &ch); } if ( ch == 'y') { printf("Logged out succesfully!\n "); exit(EXIT_SUCCESS); // Use exit() function to terminate the execution of a program } // If user picks 'n' then it reverts back to his Diogram Profile if (ch == 'n') { printf("\n\n1.HOME 2.SEARCH 3.PROFILE 4.EXIT\n"); printf(" ____\n| |\n|____|\n%s\n\nPOSTS\n", details.userACC); init_board(board, size); print_board(board, size); printf("\n\nHOME SEARCH PROFILE\n EXIT\n"); scanf("%d", &uschoice); } } } while (uschoice !=4); // All of that on a do while loop so it never ends unless user decides to exit } while (choice != 1 && choice != 2) { printf("Oops! Looks like you did something wrong!\n"); printf("Try picking between 1 - 2.\n"); scanf("%d", &choice); } return 0; // End of the main program } void init_board(char board[BOARD_SIZE][BOARD_SIZE], int size) { for (int row = 0; row < BOARD_SIZE; ++row) { for (int col = 0; col < BOARD_SIZE; ++col) // Function for initiating the board { board[row][col] = '+'; } } } // Function for printing the board void print_board(char board[BOARD_SIZE][BOARD_SIZE], int size) { printf("\n "); int row, col; for (int i = 0; i < BOARD_SIZE + 6; ++i) { printf("---"); } printf("\n"); for (int row = 0; row < BOARD_SIZE + 2; ++row) { printf("| "); } printf("\n"); for (int row = 0; row < BOARD_SIZE; ++row) { printf("|--"); for (int col = 0; col < BOARD_SIZE; ++col) { printf("-"); printf("%c", board[row][col]); printf("--"); } printf("-|"); printf("\n"); printf("|"); if (row != BOARD_SIZE - 1) { printf(" | | | | | | | | | | | | | | | |\n"); } if (row == BOARD_SIZE - 1) { for (int i = 0; i < BOARD_SIZE + 1; ++i) { printf(" |"); } printf("\n "); for (int i = 0; i < BOARD_SIZE + 6; ++i) { printf("---"); } } } }
问题根源
核心问题在于代码执行顺序错误:
- 程序先读取用户输入的
choice,直接进入if(choice==1)/else if(choice==2)分支判断 - 当用户第一次输入非1/2的值时,上述分支都不会执行,程序直接走到末尾的输入修正循环
- 修正
choice为1/2后,前面的分支逻辑已经执行完毕,程序直接走到return 0终止,不会再进入创建账户或登录流程
此外还存在scanf与fgets混用导致的缓冲区残留、printf参数缺失、无接收变量的scanf等次要问题。
修复方案
修复后完整代码
#define CRT_SECURE_NO_WARNINGS #include <stdio.h> #include <stdlib.h> #include <string.h> #define BOARD_SIZE 15 // 设置棋盘大小 #define CHAIN 5 void init_board(char board[BOARD_SIZE][BOARD_SIZE], int size); /* 声明函数 */ void print_board(char board[BOARD_SIZE][BOARD_SIZE], int size); struct CREATEacc { char username[16]; // 创建账户的结构体 char password[20]; }ca; struct signIn { char userACC[16]; // 登录的结构体 char kodikos[20]; }si; int main(int argc, char* argv[]) { struct CREATEacc userchoice; // 存储用户操作 struct signIn details; // 存储用户操作 int choice, uchoice, uschoice, size, col = 17, row = 19; // 所需整数变量 char board[BOARD_SIZE][BOARD_SIZE]; size = BOARD_SIZE; printf("Welcome to Diogram\n"); // 将菜单、输入与分支逻辑包裹在循环中,确保输入修正后能重新执行分支 do { printf("1. 创建账户\n"); // Diogram菜单 printf("2. 已有账户?登录\n"); scanf("%d", &choice); // 处理非法输入,直到用户输入1或2 while (choice != 1 && choice != 2) { printf("操作错误!请选择1-2之间的选项\n"); scanf("%d", &choice); } // 创建账户分支 if (choice == 1) { printf("用户名:\n"); scanf("%15s", userchoice.username); // 清除scanf后残留的换行符 while(getchar() != '\n'); printf("密码:\n"); scanf("%19s", userchoice.password); while(getchar() != '\n'); printf("用户名:%s\n密码:%s\n", userchoice.username, userchoice.password); printf("账户创建成功!\n\n\n"); printf("欢迎,%s\n", userchoice.username); printf("1.HOME 2.SEARCH 3.PROFILE\n"); init_board(board, size); print_board(board, size); do { printf("\n\nHOME SEARCH PROFILE\n"); // 打印应用选项 scanf("%d", &uchoice); // 读取用户选择 while(getchar() != '\n'); if (uchoice == 1) { printf("\n\n1.HOME 2.SEARCH 3.PROFILE\n"); // 打开用户主页 init_board(board, size); // 初始化棋盘 print_board(board, size); // 打印棋盘 } else if (uchoice == 2) // 打开搜索页面 { printf("\n\n1.HOME 2.SEARCH 3.PROFILE\n"); printf("\n请输入要搜索的账户:"); char search[16]; scanf("%15s", search); while(getchar() != '\n'); printf("哎呀!目前只有你在使用Diogram :(\n返回主菜单?\n"); } else if (uchoice == 3) // 打开用户个人资料 { printf("\n\n1.HOME 2.SEARCH 3.PROFILE 4.EXIT\n"); printf(" ____\n| |\n|____|\n%s\n\nPOSTS\n", userchoice.username); init_board(board, size); // 初始化棋盘 print_board(board, size); // 打印棋盘 } while (uchoice == 4) // 退出选项 { char ch; // 用于确认Y/N printf("\n\n确定要退出登录吗(y/n)?\n"); scanf (" %c", &ch); // 读取用户选择 while(getchar() != '\n'); // 直到用户输入y或n while (ch !='y' && ch !='n') { scanf(" %c", &ch); while(getchar() != '\n'); } if ( ch == 'y') { printf("退出登录成功!\n "); exit(EXIT_SUCCESS); // 终止程序 } if (ch == 'n') // 如果选择n,返回个人资料页面 { printf("\n\n1.HOME 2.SEARCH 3.PROFILE 4.EXIT\n"); printf(" ____\n| |\n|____|\n%s\n\nPOSTS\n", userchoice.username); init_board(board, size); print_board(board, size); printf("\n\nHOME SEARCH PROFILE\n EXIT\n"); scanf("%d", &uchoice); while(getchar() != '\n'); } } } while (uchoice !=4); // 循环直到用户选择退出 } // 登录分支 else if (choice == 2)
相关产品推荐
相关产品推荐

