문제 (요구사항)
할 일 목록(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기 학습 기록으로 작성되었습니다.
'교육관련 > 한화비전 VEDA 수강일지' 카테고리의 다른 글
[VEDA 1기 수강일지] 16일차 - Qt / C++ (1) : Qt 튜토리얼, label, PushButton (0) | 2024.08.05 |
---|---|
[VEDA 1기 수강일지] 15일차 - 프로젝트 마무리, 시험 (0) | 2024.08.02 |
[VEDA 1기 수강일지] 13일차 - C++ 기초 (6) / mordern C++ : (0) | 2024.07.31 |
[VEDA 1기 수강일지] 12일차 - C++ 기초 (5) : STL, 람다식 (0) | 2024.07.30 |
[VEDA 1기 수강일지] 11일차 - C++ 기초 (4) : virtual, 추상클래스 (0) | 2024.07.29 |
댓글