본문 바로가기

c언어

20. 완료 프로젝트

#define _CRT_SECURE_NO_WARNINGS 
#include <stdio.h>
#include <Windows.h>

typedef enum _COMMAND
{
	Exit,
	Add,
	Search,
	PrintAll,
	Remove,
} COMMAND;

typedef struct _USERDATA
{
	char szName[32];
	char szPhone[32];
	struct _USERDATA* pNext;
}USERDATA;

#define FILE_NAME					"PhoneBook.txt"
#define PRINT_ERR_MSG(msg)			printf("ERROR: %s", msg);

USERDATA* phoneBook = NULL;

COMMAND print_menu() 
{
	COMMAND selectMenu;
	printf("[1]Add\t[2]Search\t[3]Print all\t[4]Remove\t[0]Exit\n: ");
	scanf("%d", &selectMenu);
	getchar();
	return selectMenu;
}

void write_userdate_to_file()
{
	FILE* fp = NULL;
	fp = fopen(FILE_NAME, "w");
	if (fp != NULL)
	{
		int count = 0;
		USERDATA* pCurrent = phoneBook;
		while (pCurrent != NULL)
		{
			count++;
			pCurrent = pCurrent->pNext;
		}
		fwrite(&count, sizeof(int), 1, fp);

		pCurrent = phoneBook;
		while (pCurrent != NULL)
		{
			int nameLength = strlen(pCurrent->szName);
			int phoneLength = strlen(pCurrent->szPhone);
			fwrite(&nameLength, sizeof(int), 1, fp);
			fwrite(pCurrent->szName, sizeof(char), nameLength, fp);
			fwrite(&phoneLength, sizeof(int), 1, fp);
			fwrite(pCurrent->szPhone, sizeof(char), phoneLength, fp);
			pCurrent = pCurrent->pNext;
		}
		fclose(fp);
	}
	return;
}

void load_userdata_from_file()
{
	FILE* fp = NULL;
	fp = fopen(FILE_NAME, "r");
	if (fp != NULL)
	{
		int count = 0;
		fread(&count, sizeof(int), 1, fp);

		int nameLength = 0;
		int phoneLength = 0;
		USERDATA* pUser;
		for (int i = 0; i < count; ++i)
		{
			// 유저데이터 메모리 할당
			pUser = (USERDATA*)malloc(sizeof(USERDATA));
			if (pUser != NULL)
			{
				memset(pUser, 0, sizeof(USERDATA));

				// 이름 로드
				fread(&nameLength, sizeof(int), 1, fp);
				fread(pUser->szName, sizeof(char), nameLength, fp);

				// 전화번호 로드
				fread(&phoneLength, sizeof(int), 1, fp);
				fread(pUser->szPhone, sizeof(char), phoneLength, fp);

				// 폰북에 추가
				USERDATA* pCurrent = phoneBook;
				if (pCurrent == NULL)
				{
					phoneBook = pUser;
				}
				else
				{
					while (pCurrent->pNext != NULL)
					{
						pCurrent = pCurrent->pNext;
					}
					pCurrent->pNext = pUser;
				}
			}
		}
		fclose(fp);
	}

	return;
}
 
void load_userdata()
{
	// 파일 로드
	load_userdata_from_file();
	return;
}

void save_userdata()
{
	// 파일로 저장
	write_userdate_to_file();

	// 메모리 비우기
	USERDATA* pCurrent = phoneBook;
	while (pCurrent != NULL)
	{
		USERDATA* pDelete = pCurrent;
		pCurrent = pCurrent->pNext;
		free(pDelete);
	}
}

void add_userdata() 
{
	USERDATA* pUser = (USERDATA*)malloc(sizeof(USERDATA));
	memset(pUser, 0, sizeof(USERDATA));
	if (pUser != NULL)
	{
		pUser->pNext = NULL;

		// 이름 입력
		printf("Input name : ");
		gets_s(pUser->szName, sizeof(pUser->szName));

		// 전화번호 입력
		printf("Input phone number : ");
		gets_s(pUser->szPhone, sizeof(pUser->szPhone));

		// phoneBook에 추가
		USERDATA* pCurrent = phoneBook;
		if (pCurrent == NULL)
		{
			phoneBook = pUser;
		}
		else
		{
			while (pCurrent->pNext != NULL)
			{
				pCurrent = pCurrent->pNext;
			}
			pCurrent->pNext = pUser;
		}
		
		puts("추가 완료되었습니다.");
	}
}

void print_all_userdata()
{
	USERDATA* pCurrent = phoneBook;
	while (pCurrent != NULL)
	{
		char* szName = pCurrent->szName;
		char* szPhone = pCurrent->szPhone;
		printf("[0x%p]  %s\t%s  [0x%p]\n", szName, szName, szPhone, szPhone);
		pCurrent = pCurrent->pNext;
	}

	return;
}

USERDATA* search_userdata_of_name()
{
	char szName[32] = { 0 };
	printf("Input Name: ");
	gets_s(szName, sizeof(szName));

	USERDATA* pCurrent = phoneBook;
	while (pCurrent != NULL)
	{
		if (strcmp(szName, pCurrent->szName) == 0)
		{
			break;
		}
		pCurrent = pCurrent->pNext;
	}

	return pCurrent;
}

void remove_userdata(const char* pszName)
{
	USERDATA* pPrev = NULL;
	USERDATA* pCurrent = phoneBook;
	while (pCurrent != NULL)
	{
		char* szName = pCurrent->szName;
		if (strcmp(szName, pszName) == 0)
		{
			// 데이터 삭제
			if (pPrev == NULL)
			{
				phoneBook = NULL;
			}
			else
			{
				pPrev->pNext = pCurrent->pNext;
			}
			free(pCurrent);
			break;
		}
		else
		{
			pPrev = pCurrent;
			pCurrent = pCurrent->pNext;
		}
	}

	puts("삭제 완료!");
	return;
}


int process(COMMAND selectMenu)
{
	switch (selectMenu)
	{
	case Exit:
		return -1;
	case Add:
	{
		add_userdata();
		break;
	}
	case Search:
	{
		USERDATA* pUser = search_userdata_of_name();
		if (pUser == NULL)
		{
			puts("검색된 사용자 정보가 없습니다.");
		}
		else
		{
			char* szName = pUser->szName;
			char* szPhone = pUser->szPhone;
			printf("[0x%p]  %s\t%s  [0x%p]\n", szName, szName, szPhone, szPhone);
		}
	}
	break;
	case PrintAll:
		print_all_userdata();
		break;
	case Remove:
	{
		USERDATA* pUser = search_userdata_of_name();
		if (pUser == NULL)
		{
			puts("데이터가 존재하지 않습니다. 다시 선택해 주세요.");
		}
		else
		{
			remove_userdata(pUser->szName);
		}
	}
	break;
	default:
		break;
	}

	return 0;
}

int main(int argc, char* argv[])
{
	load_userdata();
	while (1)
	{
		COMMAND selectMenu = print_menu();
		int result = process(selectMenu);
		if (result == -1) break;
		system("pause");
		system("cls");
	}

	save_userdata();
	puts("프로그램을 종료합니다.");
	return;
}

 

'c언어' 카테고리의 다른 글

19. 전처리기  (0) 2023.08.01
18. 파일 입출력  (0) 2023.08.01
17. 기본 자료구조  (0) 2023.06.28
16. 구조체와 공용체  (0) 2023.06.28
15. 함수에 대한 고급 이론  (0) 2023.06.27