C语言简易登录注册系统编译错误求助及功能开发需求
Hey there! Let's work through fixing your code and getting that login/register system up and running. First, let's tackle the compilation error you're hitting, then we'll fix other bugs and add the validation your assignment requires.
1. Fix the "storage size of ‘l’ isn’t known" Error
In C, you need to declare a struct before you use it. Your struct login definition was sitting after the login() function, so when the compiler reached struct login l; inside login(), it had no idea what that type was yet.
Fix this by moving the struct definition to the top, right after your includes:
#include <stdio.h> #include <string.h> #include <stdlib.h> // Move struct definition here so all functions can see it struct login { char fname[30]; char lname[30]; char username[30]; char password[20]; }; // Don't forget the semicolon at the end!
Also, notice the missing semicolon at the end of your original struct definition—another common gotcha that would cause compilation issues.
2. Add Function Return Types
Your login() and registration() functions didn't have return types specified. In standard C, this isn't allowed—declare them as void since they don't need to return a value:
void login() { ... } void registration() { ... }
3. Fix Input Handling Bugs
Your input code had several issues that would break functionality even after compilation:
scanf("%c", ...)is wrong: You used%c(which reads a single character) to read full strings. Usefgetsfor more robust input (and handle the newline character it captures):fgets(l.fname, 30, stdin); l.fname[strcspn(l.fname, "\n")] = '\0'; // Strip the newline characterscanfleaves leftover newlines: After usingscanf("%d", &option)inmain(), the newline character stays in the input buffer, which would cause the nextfgetsto read an empty line. Fix this by flushing the buffer:scanf("%d",&option); while(getchar() != '\n'); // Clear leftover newline- Unused variable: In
registration(), you declaredfirstname[15]but never used it—you meant to usel.fnamein the welcome message.
4. Fix File Handling Issues
- Login file existence check: When opening the login file in
login()with"r", if the file doesn't exist (no users registered yet),fopenreturnsNULL—accessing this will crash your program. Add a safety check:FILE *log = fopen("login.txt","r"); if(log == NULL) { printf("\nNo users registered yet! Please register first.\n"); return; } - Registration overwrites users: Using
"w"infopenfor registration will erase all existing users. Use"a"(append mode) instead to add new users to the file:FILE *log = fopen("login.txt","a"); - Login loop logic: Your current login loop printed "Incorrect Login Details" for every user that didn't match. Instead, track if we found a matching user, then print the result once after the loop:
int login_success = 0; while(fread(&l,sizeof(l),1,log)) { if(strcmp(username,l.username)==0 && strcmp(password,l.password)==0) { login_success = 1; break; // Exit loop once we find a match } } if(login_success) { printf("\nSuccessful Login\n"); } else { printf("\nIncorrect Login Details\n"); }
5. Add Input Validation (Your Assignment Requirement)
Let's add functions to validate username length and password complexity:
// Check username length (<=30 chars) int validate_username(char *user) { if(strlen(user) > 29) { // Since array is 30, max length is 29 + null terminator printf("Username too long! Max 30 characters.\n"); return 0; } return 1; } // Check password meets requirements: min 8 chars, has upper, lower, number, special char int validate_password(char *pass) { int has_upper = 0, has_lower = 0, has_num = 0, has_special = 0; int len = strlen(pass); if(len < 8) { printf("Password too short! Min 8 characters.\n"); return 0; } for(int i=0; i<len; i++) { if(isupper(pass[i])) has_upper = 1; else if(islower(pass[i])) has_lower = 1; else if(isdigit(pass[i])) has_num = 1; else if(!isalnum(pass[i])) has_special = 1; // Special chars are non-alphanumeric } if(!has_upper || !has_lower || !has_num || !has_special) { printf("Password must contain uppercase, lowercase, number, and special character!\n"); return 0; } return 1; }
Then call these functions in registration() before writing to the file:
// After getting username and password if(!validate_username(l.username) || !validate_password(l.password)) { fclose(log); return; }
Full Modified Code
Here's the complete fixed code with all the above changes:
#include <stdio.h> #include <string.h> #include <stdlib.h> #include <ctype.h> struct login { char fname[30]; char lname[30]; char username[30]; char password[20]; }; int validate_username(char *user) { if(strlen(user) > 29) { printf("Username too long! Max 30 characters.\n"); return 0; } return 1; } int validate_password(char *pass) { int has_upper = 0, has_lower = 0, has_num = 0, has_special = 0; int len = strlen(pass); if(len < 8) { printf("Password too short! Min 8 characters.\n"); return 0; } for(int i=0; i<len; i++) { if(isupper(pass[i])) has_upper = 1; else if(islower(pass[i])) has_lower = 1; else if(isdigit(pass[i])) has_num = 1; else if(!isalnum(pass[i])) has_special = 1; } if(!has_upper || !has_lower || !has_num || !has_special) { printf("Password must contain uppercase, lowercase, number, and special character!\n"); return 0; } return 1; } void login() { char username[30],password[20]; FILE *log = fopen("login.txt","r"); if(log == NULL) { printf("\nNo users registered yet! Please register first.\n"); return; } struct login l; printf("\nPlease Enter your login credentials below\n\n"); printf("Username: "); fgets(username, 30, stdin); username[strcspn(username, "\n")] = '\0'; printf("\nPassword: "); fgets(password, 20, stdin); password[strcspn(password, "\n")] = '\0'; int login_success = 0; while(fread(&l,sizeof(l),1,log)) { if(strcmp(username,l.username)==0 && strcmp(password,l.password)==0) { login_success = 1; break; } } if(login_success) { printf("\nSuccessful Login\n"); } else { printf("\nIncorrect Login Details\n"); } fclose(log); } void registration() { FILE *log = fopen("login.txt","a"); if(log == NULL) { printf("Error opening file!\n"); return; } struct login l; printf("\nWelcome to your online course provider. We need to enter some details for registration.\n\n"); printf("Enter First Name: "); fgets(l.fname, 30, stdin); l.fname[strcspn(l.fname, "\n")] = '\0'; printf("Enter Surname: "); fgets(l.lname, 30, stdin); l.lname[strcspn(l.lname, "\n")] = '\0'; printf("\nThank you.\nNow please choose a username and password as credentials for system login.\n"); printf("Ensure the username is no more than 30 characters long.\n"); printf("Ensure your password is at least 8 characters long and contains lowercase, uppercase, numerical and special character values.\n"); printf("\nEnter Username: "); fgets(l.username, 30, stdin); l.username[strcspn(l.username, "\n")] = '\0'; printf("\nEnter Password: "); fgets(l.password, 20, stdin); l.password[strcspn(l.password, "\n")] = '\0'; // Validate inputs if(!validate_username(l.username) || !validate_password(l.password)) { fclose(log); return; } fwrite(&l,sizeof(l),1,log); fclose(log); printf("\nConfirming details...\n...\nWelcome, %s!\n\n", l.fname); printf("Registration Successful!\n"); printf("Press any key to continue..."); getchar(); system("CLS"); login(); } int main() { int option; printf("Press '1' to Register\nPress '2' to Login\n\n"); scanf("%d",&option); while(getchar() != '\n'); // Clear input buffer if(option == 1) { system("CLS"); registration(); } else if(option == 2) { system("CLS"); login(); } else { printf("Invalid option!\n"); } return 0; }
This code should compile cleanly, handle input correctly, avoid file crashes, and include the validation your assignment asks for. Let me know if you need clarification on any part!
内容的提问来源于stack exchange,提问作者slowlearner02

