본문 바로가기
교육관련/한화비전 VEDA 수강일지

[VEDA 1기 수강일지] 14일차 - 2인 프로젝트 : to do list

by 김수효 2024. 8. 1.
문제 (요구사항)

 

할 일 목록(To-Do List) 프로그램:


사용자가 할 일을 추가, 수정, 삭제, 조회 기능 구현

 

여러 사용자 이용

 

추가 구현 : Done List 추가

 

문제 구현 / 개선방안

 

설계

- 파일을 사용자 별로 분리. 각 사용자별 할 일 파일과 완료 파일을 가짐.

ㄴ 같은 이름을 가진 파일 생성 불가 처리

- 클래스 2개 선언 (사용자, 할 일)

- switch case 문으로 할 작업 선택

- 헤더파일 2개 (todo, user) 

- 함수cpp 파일 2개로 분리 (협업목적)

 

class

-  사용자 (user) class : 사용자 정보

-  할 일 (todo) class : 할 일을 벡터, 완료 벡터에 저장 -> 관리

 

functions

- 사용자 생성

- 추가 : 할 일 벡터에 추가

- 수정 : 인덱스로 접근, 선택 벡터에 덮어 쓰기

- 삭제 : 선택한 인덱스의 벡터 삭제

- 조회 : 두 벡터 안에 있는 원소들을 모두 출력

- 완료 : 할 일 벡터에서 완료로 처리할 일의 인덱스 선택, 완료 벡터로 복사, 할 일 벡터에서 삭제

- 불러오기 : 사용자 이름과 동일한 txt 파일에서 내용을 읽어와 사용자 클래스 내 벡터에 저장

- 저장 : 클래스에 저장된 정보를 사용자 이름과 동일한 파일에 출력

 

 

개선

- 폴더가 없으면 폴더 생성

ㄴ C++ 17 부터 사용가능한 fliesystem을 include 시켜서 컴파일러 오류 발생 (vs에 설정이 14로 되어있었음)

ㄴ vs에서 컴파일러 설정을 변경하여 해결

 

- 전역으로 선언된 클래스 -> 스마트 포인터로 변환

ㄴ user가 작성중 저장하지 않고 새로운 사용자를 불러오거나, 사용자를 불러오지 않은 상황에서

     저장을 할 때 메모리 반환 문제 발생

-> unique_ptr 이용

   ㄴuser가 새로운 user를 생성하거나 불러올때 이전에 동적으로 생성된 클래스를 자동으로 소멸시킴

 

코드 
(내가 작성한 코드 :  main.cpp, user.h, fun1.cpp)

 

main.cpp

#include <iostream>
#include <string>
#include <vector>
#include <fstream>
#include <filesystem>
#include <windows.h>
using namespace std;
#include "user.h"
#include "To_do.h"
namespace sf = std::filesystem;

//폰트 색 변경
void tbColor(unsigned short textColor, unsigned short backColor) {
	int color = textColor + backColor * 16;

	SetConsoleTextAttribute(GetStdHandle(STD_OUTPUT_HANDLE), color);
}

int main()
{	
	//폴더 없으면 생성 (사용자 정보 저장용)
	if (!(sf::exists(sf::path("./userInfo"))))
	{
		sf::create_directory(sf::path("./userInfo"));
		cout << "create directory" << endl;
	}
	if (!(sf::exists(sf::path("./done"))))
	{
		sf::create_directory(sf::path("./done"));
		cout << "create directory" << endl;
	}

	int menuNum = 0;
	string name; //사용자 이름
	string todo; // 할 일
	unique_ptr<User> pUser; //user class ptr
	string fileName; // 저장할 파일 이름 = 사용자 이름
	ifstream loadFile(fileName);

	do
	{
		cout << "---------------" << endl;
		cout << "1. User : Add " << endl;
		cout << "2. User : select " << endl;
		cout << "3. To-Do : Show List " << endl;
		cout << "4. To-Do : Add Task " << endl;
		cout << "5. To-Do : Edit " << endl;
		cout << "6. To-Do : Delete " << endl;
		cout << "7. To-Do : Clear " << endl;
		cout << "8. Save " << endl;
		cout << endl;
		cout << "9. Quit " << endl;
		cout << "---------------" << endl;

		cout << "Select : "; //실행할 동작 번호 입력
		cin >> menuNum;
		getchar();
		switch (menuNum)
		{
		case 1:
			//사용자 추가
			cout << "Input Name (New) : ";
			getline(cin, name);
			pUser = make_unique <User>();
			//사용자가 이미 있으면 break.
			if (!pUser->U_check(name))
			{
				cout << "This name already exists." << endl;
				break;
			}
			pUser->setName(name);
			fileName = name;

			while (true)
			{
				cout << "Input Task (End Code : end) : ";
				getline(cin, todo);
				if (todo == "end") break;
				pUser->U_insert(todo);
			}
			cout << endl;
			break;

		case 2:
			//사용자 선택
			pUser = make_unique <User>();
			cout << "Input Name (Select) : ";
			getline(cin, name);
			pUser->U_load(name);
			cout << endl;
			break;

		case 3:
			//할 일 조회
			tbColor(14, 0);
			pUser->U_allPrint();
			tbColor(15, 0);
			cout << endl;
			break;

		case 4:
			//할 일 추가
			while (true)
			{
				cout << "Input Task (End Code : end) : ";
				getline(cin, todo);
				if (todo == "end") break;
				pUser->U_insert(todo);
			}
			cout << endl;
			break;

		case 5:
			//할 일 수정
			int editN;
			cout << "Please select the number" << endl;
			tbColor(14, 0);
			pUser->U_allPrint();
			tbColor(15, 0);
			cout << "Input Number : ";
			cin >> editN;
			cout << "Input Task :";
			cin >> todo;
			pUser->U_modify(editN, todo);
			cout << endl;
			break;

		case 6:
			//할 일 삭제
			cout << "Please select the number you want to delete" << endl;
			tbColor(14, 0);
			pUser->U_allPrint();
			tbColor(15, 0);
			cout << "Input Number : ";
			cin >> editN;
			pUser->U_del(editN);
			cout << endl;
			break;

		case 7:
			//완료
			cout << "Choose clear task" << endl;
			tbColor(14, 0);
			pUser->U_allPrint();
			tbColor(15, 0);
			cout << "Input Number : ";
			cin >> editN;
			pUser->U_clear(editN);

		case 8:
			pUser->U_save(name);
			cout << endl;
			break;

		case 9:
			cout << "Quit." << endl;
			cout << endl;
			break;

		defult:
			cout << "Please select again." << endl;
			cout << endl;
			break;
		}
	} while (menuNum != 9);

	return 0;
}

 

user.h

#ifndef _USER_H
#define _USER_H
#include <string>
#include "To_do.h"
using namespace std;

class User
{
	string name;
	ToDo myList;
public:
	User();
	User(string s) { setName(s); }
	void setName(string s);
	void U_insert(string input);
	void U_allPrint() const;
	void U_modify(int idx, string input);
	void U_del(int idx);
	void U_load(string name);
	void U_save(string name) const;
	bool U_check(string name);
	void U_listClear();
	void U_clear(int idx);
};


#endif

 

To_do.h

#include <vector>
#include <string>

#ifndef _TO_DO_H
#define _TO_DO_H
class ToDo
{
private:
	std::vector<std::string> m_list;
	std::vector<std::string> c_list;
public:
	ToDo();
	~ToDo();
	void insert(std::string input);
	void modify(int idx, std::string input);
	void del(int dix);
	void allPrint() const;
	void load(std::string name);
	void save(std::string name) const;
	bool check(std::string name) const;
	void listClear();
	void clear(int dix);
};
#endif

 

user.cpp

#include "user.h"

User::User() : User("dummy") {}

void User::setName(string s)
{
	name = s;
}

void User::U_insert(string input)
{
	myList.insert(input);
}

void User::U_allPrint() const
{
	myList.allPrint();
}

void User::U_modify(int idx, string input)
{
	myList.modify(idx, input);
}

void User::U_del(int idx)
{
	myList.del(idx);
}

void User::U_load(string name)
{
	myList.load(name);
}

void User::U_save(string name) const
{
	myList.save(name);
}

bool User::U_check(string name)
{
	return myList.check(name);
}

void User::U_listClear()
{
	myList.listClear();
}

void User::U_clear(int idx)
{
	myList.clear(idx);
}

 

fun1.cpp (todo 함수)

#include <iostream>
#include <string>
#include <vector>
using namespace std;
#include "To_do.h"
#include "user.h"

void ToDo::insert(std::string input)
{
	m_list.push_back(input);
}
void ToDo::allPrint() const
{
	cout << endl << "To-Do List" << endl;
	for (int i = 0; i < m_list.size(); i++)
	{
		cout << i + 1 << ". " << m_list[i] << endl;
	}

	cout << endl << "Done List" << endl;

	for (int i = 0; i < c_list.size(); i++)
	{
		cout << i + 1 << ". " << c_list[i] << endl;
	}
}

void ToDo::listClear()
{
	m_list.clear();
}

 

fun 2.cpp (todo 함수)

#include <iostream>
#include "To_do.h"
#include <fstream>
#include <filesystem>

ToDo::ToDo()
{
	m_list.clear();
	c_list.clear();
}
ToDo::~ToDo()
{
	m_list.clear();
	c_list.clear();
}

void ToDo::modify(int idx, std::string input)
{
	if (m_list.size() < idx)
		std::cout << "Out of range.\n";
	else
	{
		m_list[idx - 1] = input;
		std::cout << "수정 완료되었습니다.\n";
	}
}

void ToDo::del(int idx)
{
	if (m_list.size() < idx)
		std::cout << "Out of range.\n";
	else
	{
		for (auto it = m_list.begin(); it != m_list.end(); it++)
		{
			if (it == m_list.begin() + idx - 1)
			{
				std::string test = m_list.at(idx - 1);
				m_list.erase(it);
				std::cout << idx << "번 째 할 일 목록 삭제가 완료되었습니다.\n";

				break;
			}
		}
	}
}

void ToDo::load(std::string name)
{
	std::string fileName = ".\\userInfo\\" + name + ".txt";

	std::ifstream loadFile(fileName);
	if (!loadFile)
		std::cout << "이전에 작성 한 기록이 없습니다.\n";

	std::string temp;
	m_list.clear();

	while (std::getline(loadFile, temp))
	{
		m_list.push_back(temp);
	}

	loadFile.close();
	std::cout << "할 일 리스트 불러오기가 완료 되었습니다.\n";

	// ---------------------------------------------------------

	
	fileName = ".\\done\\" + name + "_clear" + ".txt";

	loadFile.open(fileName);
	if (!loadFile)
		std::cout << "이전에 작성 한 기록이 없습니다.\n";

	temp;
	c_list.clear();

	while (std::getline(loadFile, temp))
	{
		c_list.push_back(temp);
	}

	loadFile.close();
	std::cout << "완료한 일 리스트 불러오기가 완료 되었습니다.\n";
	
}

void ToDo::save(std::string name) const
{
	std::string fileName = ".\\userInfo\\" + name + ".txt";
	std::ofstream saveFile(fileName);
	if (!saveFile)
		std::cout << "파일을 열 수 없습니다.\n";

	for (auto& x : m_list)
	{
		saveFile << x << std::endl;
	}

	saveFile.close();
	std::cout << "To-Do List 저장이 완료 되었습니다.\n";

	// ---------------------------------------------------------

	if (c_list.size() > 0)
	{
		fileName = ".\\done\\" + name + "_clear" + ".txt";
		std::ofstream saveFile(fileName);
		if (!saveFile)
			std::cout << "파일을 열 수 없습니다.\n";

		for (auto& x : c_list)
		{
			saveFile << x << std::endl;
		}

		saveFile.close();
		std::cout << "Done List 저장이 완료 되었습니다.\n";
	}
}

bool ToDo::check(std::string name) const
{
	std::string fileName = ".\\userInfo\\" + name + ".txt";
	std::ifstream checkPtr(fileName);
	if (!checkPtr)
		return true; // 최초 작성
	else return false; // 이미 있는 이름
}

void ToDo::clear(int idx)
{
	if (m_list.size() < idx)
		std::cout << "Out of range.\n";
	else
	{
		for (auto it = m_list.begin(); it != m_list.end(); it++)
		{
			if (it == m_list.begin() + idx - 1)
			{
				std::string test = m_list.at(idx - 1);
				m_list.erase(it);
				c_list.push_back(test);
				std::cout << idx << "번 째 일을 완료 상태로 변경하였습니다.\n";

				break;
			}
		}
	}
}

VEDA 바로가기 : www.vedacademy.co.kr

VEDA(한화비전 아카데미) 영상으로 확인하기 : https://url.kr/zy9afd

본 후기는 VEDA(한화비전 아카데미) 1기 학습 기록으로 작성되었습니다.

댓글