一、问题描述
Personal Diary 是一个命令行程序,包含以下四个程序
pdadd pdlist [] pdshow pdremove
1.1 pdadd程序
向日记文件dairy.txt 中添加一个实体,包含日记的时间、内容
1.2 pdlist程序
按照日期的顺序,列出diary.txt 中的日记实体
输入:如果通过命令行参数,输入了开始日期和结束日期,则只输出在这两个日期之间的日记
输出:stdout
1.3 pdshow程序
按照输入的日期,列出diary.txt 中的对应日记实体的内容
1.4 pdremove程序
按照输入的日期,删除diary.txt 中的对应日记
输入:stdin
输出:stdout
返回值:0 表示删除成功,1 表示删除失败
二、实现思路
2.1 定义的类
2.1.1 Date类
成员变量
int year; int month; int day;
成员函数
bool input () ; bool input (ifstream& fin) ; void output () ;void output (ofstream& fout) ;
重载符号
以年、月、日为第一、二、三关键字进行比较
注意,-1/-1/-1 默认为最大值
2.1.2 Diary类
成员变量
Date date; vector<string>content;
成员函数
bool input () ; bool input (ifstream& fin) ; void output () ;void output (ofstream& fout) ;void outputDate () ;Date GetDate () ;
重载符号
以date 为唯一关键字进行比较
2.2 存储
日记文件为./code/diary.txt
按照日期,升序排列所有日记文件
以-1/-1/-1 为文件结尾
2.3 pdadd
用一个vector< Diary
>diary 保存已有的所有日记
首先,从键盘中输入新增日记的信息,放到vector 数组里面,记为diary[0]
然后,从diary.txt 文件读取所有日记,放到vector 数组里面
从diary[1] 开始输出存下的所有日记,分为三种情况
diary[i] =
diary[0] :根据题意,舍弃diary[i] ,将diary[0] 输入到文件中
diary[i] > diary[0] && diary[i] <
diary[0] :由于根据日期升序排列,此时要先输出diary[0] ,后输出diary[i]
其它情况:直接输出diary[i]
2.4 pdlist
与pdadd 类似,从diary.txt 中读取所有日记,保存到diary 数组中
从diary[0] 开始输出存下的所有日记,由于只需要表示日记实体,因此我们只输出日记的日期
至于输出一定范围内的日记,我们只需要在输出的时候,判断一下diary[i] 的日期是否在指定的范围内即可
当没有日记输出时,会输出提示信息
2.5 pdshow
与pdlist 类似,从diary.txt 中读取所有日记,保存到diary 数组中
从diary[0] 开始遍历存下的所有日记,如果日期与输入的相同,则输出当前日记的所有内容
当没有日记输出时,会输出提示信息
2.6 pdremove
与pdadd 类似,从diary.txt 中读取所有日记,保存到diary 数组中
从diary[0] 开始输出存下的所有日记,分为两种情况
diary[i] 的日期与给定的日期相同:跳过该条日记
否则将diary[i] 输入到文件中
当待删除的日期不存在时,会输出提示信息
三、源码
3.0 公共类
3.0.1 Date
#pragma once #include <iostream> #include <fstream> #include "Utils.h" class Date {public : Date () : year (0 ), month (0 ), day (0 ) {} Date (int year, int month, int day) : year (year), month (month), day (day) {} bool input () ; bool input (std::ifstream& fin) ; void output () const ; void output (std::ostream& fout) const ; public : bool operator ==(const Date& A) const ; bool operator <(const Date& A) const ; bool operator >(const Date& A) const ; private : int year, month, day; }; static const Date DATE_MAX = Date (9999 , 12 , 31 );static const Date DATE_MIN = Date (0 , 1 , 1 );
#pragma warning (disable:4996) #include "Date.h" bool Date::input () { printf ("请输入日记的日期:年 月 日\n" ); SetColor (Color::Red); std::cin >> year >> month >> day; SetColor (Color::Blue); if (year == -1 )return false ; return true ; } bool Date::input (std::ifstream& fin) { if (fin.eof ()) return false ; fin >> year >> month >> day; if (year == -1 )return false ; return true ; } void Date::output () const { SetColor (Color::Red); printf ("%04d/%02d/%02d\n" , year, month, day); SetColor (Color::Blue); } void Date::output (std::ostream& fout) const { fout << year << " " << month << " " << day << std::endl; } bool Date::operator ==(const Date& A) const { return year == A.year && month == A.month && day == A.day; } bool Date::operator <(const Date& A) const { if (year == -1 )return false ; if (A.year == -1 )return true ; if (year != A.year)return year < A.year; if (month != A.month)return month < A.month; return day < A.day; } bool Date::operator >(const Date& A) const { return !(*this < A) && !(*this == A); }
3.0.2 Diary
#pragma once #include <vector> #include "Date.h" class Diary {public : Diary () {} Diary (const Date& date) : date (date) {} bool input () ; bool input (std::ifstream& fin) ; void output () const ; void output (std::ostream& fout) const ; void outputDate () const ; public : Date GetDate () const { return date; } public : bool operator ==(const Diary& A) const ; bool operator <(const Diary& A) const ; bool operator >(const Diary& A) const ; private : Date date; std::vector<std::string> content; };
#pragma warning (disable:4996) #include "Diary.h" using namespace std;bool Diary::input () { if (date.input () == false )return false ; printf ("请逐行输入日记的内容,以.或EOF结束\n" ); string s; getline (cin, s); while (1 ) { SetColor (Color::Yellow); printf ("%2d:" , (int )content.size () + 1 ); SetColor (Color::Red); getline (cin, s); if (s.empty ())break ; if (s[0 ] == '.' )break ; content.push_back (s); } content.push_back (".\n" ); SetColor (Color::Yellow); printf ("日记输入成功\n" ); SetColor (Color::Clear); return true ; } bool Diary::input (std::ifstream& fin) { if (date.input (fin) == false )return false ; string s; getline (fin, s); while (1 ) { getline (fin, s); if (s.empty ())break ; if (s[0 ] == '.' )break ; content.push_back (s); } content.push_back ("." ); return true ; } void Diary::output () const { date.output (); for (int i = 0 ; i < content.size () - 1 ; i++) cout << content[i] << endl; cout << endl; } void Diary::output (std::ostream& fout) const { date.output (fout); for (int i = 0 ; i < content.size (); i++) fout << content[i] << endl; } void Diary::outputDate () const { date.output (); } bool Diary::operator ==(const Diary& A) const { return date == A.date; } bool Diary::operator <(const Diary& A) const { return date < A.date; } bool Diary::operator >(const Diary& A) const { return date > A.date; }
3.0.3 DiaryManager
#pragma once #include "Diary.h" #include <set> class DiaryManager {public : static DiaryManager& GetInstance () { static DiaryManager instance; return instance; } public : void InputNewDiary () ; void OutputAllDiary (Date L = DATE_MIN, Date R = DATE_MAX) ; void RemoveDiary (Date now) ; private : void InputAllDiary () ; void StoreDiary () ; private : DiaryManager (); ~DiaryManager (); std::set<Diary> diary; };
#include "DiaryManager.h" using namespace std;void DiaryManager::InputNewDiary () { Diary tmp; tmp.input (); diary.insert (tmp); } void DiaryManager::OutputAllDiary (Date L, Date R) { auto it1 = diary.lower_bound (Diary (L)); auto it2 = diary.upper_bound (Diary (R)); SetColor (Color::Yellow); if (it1 == it2) { cout << "No diary in this period!\n" ; } else { cout << "Diary is as following:\n" ; for (auto it = it1; it != it2; it++) { it->output (); } } SetColor (Color::Clear); } void DiaryManager::RemoveDiary (Date now) { SetColor (Color::Yellow); if (diary.find (Diary (now)) != diary.end ()) { diary.erase (Diary (now)); cout << "Remove success" << endl; } else { cout << "No diary on this day!" << endl; } SetColor (Color::Clear); } void DiaryManager::InputAllDiary () { ifstream fin ("diary.txt" ) ; while (true ) { Diary tmp; if (!tmp.input (fin)) break ; diary.insert (tmp); } fin.close (); } void DiaryManager::StoreDiary () { ofstream fout ("diary.txt" , ios::out) ; for (auto it = diary.begin (); it != diary.end (); it++) { it->output (fout); } fout.close (); } DiaryManager::DiaryManager () { InputAllDiary (); } DiaryManager::~DiaryManager () { StoreDiary (); }
3.0.4 Utils
#pragma once #include <string> #include <Windows.h> enum class Color { Red, Blue, Green, Yellow, Clear }; static void SetColor (Color color) { HANDLE hdl = GetStdHandle (STD_OUTPUT_HANDLE); if (color == Color::Red)SetConsoleTextAttribute (hdl, FOREGROUND_RED | FOREGROUND_INTENSITY); else if (color == Color::Blue)SetConsoleTextAttribute (hdl, FOREGROUND_BLUE | FOREGROUND_GREEN | FOREGROUND_INTENSITY); else if (color == Color::Green)SetConsoleTextAttribute (hdl, FOREGROUND_GREEN | FOREGROUND_INTENSITY); else if (color == Color::Yellow)SetConsoleTextAttribute (hdl, FOREGROUND_RED | FOREGROUND_GREEN | FOREGROUND_INTENSITY); else if (color == Color::Clear)SetConsoleTextAttribute (hdl, FOREGROUND_BLUE | FOREGROUND_GREEN | FOREGROUND_INTENSITY); }
3.1 pdadd
#pragma warning (disable:4996) #include "../Diary/DiaryManager.h" using namespace std;int main (int argc, char * argv[]) { SetColor (Color::Blue); if (argc == 2 ) { freopen (argv[1 ], "r" , stdin); } DiaryManager::GetInstance ().InputNewDiary (); return 0 ; }
3.2 pdlist
#pragma warning (disable:4996) #include "../Diary/DiaryManager.h" using namespace std;bool CheckFormat (int n, char * s[]) { if (n != 3 )return false ; int len = strlen (s[1 ]); int cnt = 0 ; for (int i = 0 ; i < len; i++) { if (s[1 ][i] == '/' )cnt++; else if (s[1 ][i] > '9' || s[1 ][i] < '0' )return false ; } if (cnt != 2 )return false ; len = strlen (s[2 ]); cnt = 0 ; for (int i = 0 ; i < len; i++) { if (s[2 ][i] == '/' )cnt++; else if (s[2 ][i] > '9' || s[2 ][i] < '0' )return false ; } if (cnt != 2 )return false ; return true ; } int main (int argc, char * argv[]) { SetColor (Color::Blue); if (argc == 1 ) { DiaryManager::GetInstance ().OutputAllDiary (); } else { if (!CheckFormat (argc, argv)) { SetColor (Color::Red); printf ("请输入正确的参数格式:xxxx/xx/xx xxxx/xx/xx\n" ); } else { int LYear = 0 , LMonth = 0 , LDay = 0 ; int RYear = 0 , RMonth = 0 , RDay = 0 ; sscanf (argv[1 ], "%d/%d/%d" , &LYear, &LMonth, &LDay); sscanf (argv[2 ], "%d/%d/%d" , &RYear, &RMonth, &RDay); DiaryManager::GetInstance ().OutputAllDiary (Date (LYear, LMonth, LDay), Date (RYear, RMonth, RDay)); } } return 0 ; }
3.3 pdremove
#pragma warning (disable:4996) #include "../Diary/DiaryManager.h" using namespace std;int main (int argc, char * argv[]) { SetColor (Color::Blue); if (argc == 2 ) { freopen (argv[1 ], "r" , stdin); } Date now; now.input (); DiaryManager::GetInstance ().RemoveDiary (now); return 0 ; }
3.4 pdshow
#pragma warning (disable:4996) #include "../Diary/DiaryManager.h" using namespace std;int main (int argc, char * argv[]) { SetColor (Color::Blue); if (argc == 2 ) { freopen (argv[1 ], "r" , stdin); } Date now; now.input (); DiaryManager::GetInstance ().OutputAllDiary (now, now); return 0 ; }
3.5 sample.bat
pdadd sampleAdd.txt pdshow sampleShow.txt pdremove sampleRemove.txt pdlist pdlist 2022/4/10 2022/4/11 pdlist 2025/4/10 2025/4/11 pause
call pdadd.exe < sampleAdd.txt call pdshow.exe < sampleShow.txt call pdremove.exe < sampleRemove.txt pdlist pdlist 2022/4/10 2022/4/11 pdlist 2025/4/10 2025/4/11 pause
3.6 diary.txt
2022 4 10 asd123www asdqw . 2022 4 11 asd1asdqweyuitbladf . 2022 4 13 asd123www asdqweyuitbladf . 2022 4 14 123456789 00000000 14568+423 . 2022 4 15 123456789 00000000 14568+423 .