(혹시라도 제 글을 보실 분이 계실까봐 남겨드립니다. 이 블로그는 저의 프로그래밍 기술 습득을 위해 일기장 형식으로 저에게 남기는 글입니다. 그래서 딱딱한 느낌이 들 수 있습니다. 읽어주셔서 고맙습니다.)
#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];
};
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;
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("userLogin\n");
printf("사용자의 아이디: %s\n", userCreateInfo.userId);
printf("사용자의 비밀번호: %s\n", userCreateInfo.userPassword);
printf("사용자의 확인 비밀번호: %s\n", userCreateInfo.userCheckPassword);
printf("\n\n");
break;
}
} while (1);
return 0;
}
지금까지 작성한 코드를 ChatGPT에게 물어보고 답변으로 정리된 프로그램이다.
ChatGPT의 도움을 받은 부분은 비밀번호 입력과 코드 정리이다.
비밀번호 입력은 *을 통해 다른 사람이 볼 수 없도록 작성이 되며, 백스페이스로 잘못 입력된 비밀번호의 지우기가 가능하고 엔터를 통해 비밀번호 입력을 완료할 수 있다.
이 글을 올린 이유는 코드를 모바일로 옮겨서 C언어의 큰 틀을 이해하고, 어떠한 방식으로 작동되는가를 스스로 이해하기 위해서 올린 글이며, 참고용으로 올리게 되었다.
코드를 이해 후 암호화 적용을 시작해야겠다.
정리:
1. 기존의 반복되는 비밀번호 비교 코드는 getPassword()함수를 생성하여 코드 정리.
2. _getch(): 사용자가 키보드를 이용하여 작성한 문자열을 ASKII코드 값으로 변수에 저장하는 함수.
char ch = _getch(); -> 'a'입력 시 ASKII코드 값인 '97'이 ch에 저장.
#include <conio.h>를 이용하여 _getch()함수 사용.
3. 책에서는 scanf 함수를 이용하지만 버퍼 오버플로우에 대해 취약하기에 코드의 보안을 위해 scanf_s를 사용하는 것이 좋다.
버퍼 오버플로우: 버퍼 오버플로우는 배열의 크기를 초과하여 데이터를 저장하려고 할 때 발생하는 문제입니다. 이러한 문제를 방지하기 위해서는 배열의 크기를 확인하고, 데이터를 저장하기 전에 배열의 크기를 초과하지 않도록 조치해야 합니다.
scanf_s에서는 입력받을 입력값?의 크기를 명시해야 한다.
'C 프로그래밍' 카테고리의 다른 글
C 프로그래밍 우분투 시작 (2) | 2023.12.03 |
---|---|
C언어 프로젝트 23.12.03 (4) | 2023.12.03 |
C언어 프로젝트 23.12.02 (2) | 2023.12.02 |
C언어 프로젝트 23.12.01 (0) | 2023.12.01 |
C언어 프로젝트 23.11.30 (0) | 2023.11.30 |