C 프로그래밍

C언어 프로젝트 23.12.02

Nohsw 2023. 12. 2. 20:05

 

#include <stdio.h>
#include <conio.h> // getch() 함수를 사용하기 위한 헤더 파일
#include <string.h> //문자열 비교함수인 "strcmp"를 사용하기 위해 string.h 라이브러리를 사용.

enum loginProgram {
    userCreate = 1, // 회원가입
    userLogin = 2,  // 로그인
};

struct userInfo { // struct를 이용하여 로그인 정보 저장
    char userId[100];
    char userPassword[100];
    char userCheckPassword[100];
};

struct userInfoCompare { // struct를 이용하여 로그인 시 아이디, 비밀번호 비교
    char userId[100];
    char userPassword[100];
};

void getPassword(char* password) { //비밀번호 비교를 위한 함수
    char ch;
    int i = 0; //사용자가 입력한 문자열 갯수

    while (1) {
        ch = _getch();

        if (ch == 13) { // Enter 키를 누르면 종료
            break;
        }
        
        else if (ch == 8) {
            if (i > 0) {
                printf("\b \b"); // 백스페이스 키 입력 시, 화면에서 지움
                i--;
            }
        }
        
        else {
            password[i++] = ch; // 비밀번호 배열에 문자 추가
            printf("*"); // 별표 출력
        }
    }

    password[i] = '\0'; // 문자열 종료를 위한 널 문자 추가
    printf("\n");
}

int main() {
    enum loginProgram login_Type; // 사용자의 선택으로 로그인 프로그램 실행.
    struct userInfo userCreateInfo; 
    struct userInfoCompare userLoginInfo;
    
    do {
        printf("로그인 프로그램\nBy.Nohsw");
        printf("\n\n");
        printf("[1. 회원가입]\n[2. 로그인]\n");
        printf("입력: ");
        scanf_s("%d", &login_Type); // 사용자의 선택 값으로 switch 실행.
        printf("\n\n");

        switch (login_Type) { //가독성 향상을 위해 enum 사용하였고, switch case를 작성.
        case userCreate: //회원가입
            printf("회원가입 화면입니다.\n");

            printf("회원가입 할 ID를 입력해주세요.\n");
            printf("입력: ");
            scanf_s("%99s", userCreateInfo.userId, sizeof(userCreateInfo.userId));
            //%99s를 사용한 이유: 버퍼 오버플로우를 방지하기 위해 입력받을 문자열의 크기를 명시를 해야한다.
            // 버퍼 오버플로우: 버퍼 오버플로우는 배열의 크기를 초과하여 데이터를 저장하려고 할 때 발생하는 문제입니다.
            // 이러한 문제를 방지하기 위해서는 배열의 크기를 확인하고, 데이터를 저장하기 전에 배열의 크기를 초과하지 않도록 조치해야 합니다.
            
            //scanf_s 사용을 위해서는 크기 제한을 둔 %s를 사용하는게 좋다. (메모리 누수를 포함한 보안 문제를 방지하기 위함)
            //위에 userId[100]으로 작성하였기에 null값인 \0을 제외한 %99s를 사용.
            
            printf("비밀번호를 입력해주세요.\n");
            printf("입력: ");
            getPassword(userCreateInfo.userPassword);

            printf("비밀번호를 한번 더 입력해주세요.\n");
            printf("입력: ");
            getPassword(userCreateInfo.userCheckPassword); //함수를 이용하여 1차와 2차 비밀번호 비교

            //비밀번호 비교 후 맞으면 회원가입 성공, 틀리면 회원가입 실패 출력.
            if (strcmp(userCreateInfo.userPassword, userCreateInfo.userCheckPassword) == 0) {
                printf("회원가입 성공.\n");
                printf("사용자의 아이디는 %s입니다.\n", userCreateInfo.userId);
            }
            else {
                printf("회원가입 실패.\n");
                printf("사유: 입력한 비밀번호가 다릅니다.\n");
            }

            printf("\n\n");
            break;

        case userLogin: //로그인
            printf("아이디 입력: ");
            scanf_s("%s", userLoginInfo.userId, sizeof(userLoginInfo.userId));
            printf("비밀번호 입력: ");
            getPassword(userLoginInfo.userPassword);

            if (strcmp(userLoginInfo.userId, userCreateInfo.userId) == 0 && strcmp(userLoginInfo.userPassword, userCreateInfo.userPassword) == 0) {
                printf("로그인 성공\n");
                int i = 0;
                int inputNum;
                while (i < 1) {
                    printf("\n\n");
                    printf("%s님 어서오세요.\n", userLoginInfo.userId);
                    printf("종료하시려면 '-1'을 눌러주십시오.\n");
                    printf("입력: ");
                    scanf_s("%d", &inputNum);

                    switch (inputNum) {
                    case -1:
                        printf("\n\n");
                        printf("로그아웃을 진행합니다.\n");
                        i++;
                        printf("\n\n");
                        break;

                    default:
                        printf("\n\n");
                        printf("잘못된 값을 입력하였습니다. 로그아웃을 진행합니다.\n");
                        i++;
                        printf("\n\n");
                        break;
                    }
                }
            }
            else {
                printf("로그인 실패\n");
                if (strcmp(userLoginInfo.userId, userCreateInfo.userId) == 1 && strcmp(userLoginInfo.userPassword, userCreateInfo.userPassword) == 1) {
                    printf("아이디와 비밀번호가 다릅니다. 다시 입력해주세요.\n");
                }
                else if (strcmp(userLoginInfo.userPassword, userCreateInfo.userPassword) == 1) {
                    printf("비밀번호가 다릅니다. 비밀번호를 다시 입력해주세요.\n");
                }
                else if (strcmp(userLoginInfo.userId, userCreateInfo.userId) == 1) {
                    printf("아이디가 다릅니다. 다시 입력해주세요.\n");
                }
                else {
                    printf("ERROR\n");
                }
                printf("\n\n");
            }
            break;
        }

    } while (1);

    return 0;
}

어제의 코드를 살펴본 후 오늘은 로그인 코드를 입력해보았다.

로그인 구현 시 직접 코드를 만들어보았으며, 정상적으로 로그인이 되나 발견된 버그가 생겼다.

버그에 대해 수정 후 코드에 대해 익힌 후에 암호화를 배우는 것이 맞다고 판단하여 암호화는 마지막에 구현 할 예정이다.

 

지금까지 확인 된 버그 내용:

1. 회원가입 후 로그인 시 처음부터 아이디와 비밀번호가 모두 다르면 else문의 에러가 발생.

아이디나 비밀번호 중 하나만 맞으면 이후의 코드는 어떤 문제인지 정상 출력.

2. 로그인 이후 화면에서 defalut를 입력하였고, -1을 제외한 다른 키 입력 시 무한루프 발생.

임시로 default값에 i++ 를 입력하여 로그아웃이 진행되도록 조치.

'C 프로그래밍' 카테고리의 다른 글

C 프로그래밍 우분투 시작  (2) 2023.12.03
C언어 프로젝트 23.12.03  (4) 2023.12.03
C언어 프로젝트 23.12.01 (1)  (5) 2023.12.01
C언어 프로젝트 23.12.01  (0) 2023.12.01
C언어 프로젝트 23.11.30  (0) 2023.11.30