c++実戦(二)図書管理システム

14391 ワード

この実戦を通じて,ソフトウェア全体の設計,クラスの応用,ファイルにデータを格納する方法などを理解する.
このプログラムは、図書の入力、削除、およびすべての図書記録を閲覧する3つのモジュールを完了します.
1.図書類を設計する
#include "stdafx.h"
#include "Book.h"	
#include "string"
#include "fstream"
#include "iostream"
#include "iomanip"
using namespace std;
CBook::CBook(char* cName, char* cIsbn, char* cPrice, char* cAuthor) {
	strncpy(m_cName, cName, NUM1);
	strncpy(m_cIsbn, cIsbn, NUM1);
	strncpy(m_cPrice, cPrice, NUM2);
	strncpy(m_cAuthor, cAuthor, NUM2);
}
char* CBook::GetName() {
	return m_cName;
}
void CBook::SetName(char* cName) {
	strncpy(m_cName, cName, NUM1);
}
char* CBook::GetPrice() {
	return m_cPrice;
}
void CBook::SetPrice(char* cPirce) {
	strncpy(m_cPrice, cPirce, NUM2);
}
char* CBook::GetAuthor() {
	return m_cAuthor;
}
void CBook::SetAuthor(char* cAuthor) {
	strncpy(m_cAuthor, cAuthor, NUM2);
}

void CBook::WriteData() {
	ofstream ofile;
	ofile.open("book.dat", ios::binary|ios::app);
	try {
		ofile.write(m_cName, NUM1);
		ofile.write(m_cIsbn, NUM1);
		ofile.write(m_cPrice, NUM2);
		ofile.write(m_cAuthor, NUM2);
	}
	catch (...) {
		throw "file error occurred";
		ofile.close();
	}
	ofile.close();
}

void CBook::GetBookFromFile(int iCount) {
	char cName[NUM1];
	char cIsbn[NUM1];
	char cPrice[NUM2];
	char cAuthor[NUM2];
	ifstream ifile;
	ifile.open("book.dat", ios::binary);
	try {
		ifile.seekg(iCount*(NUM1 + NUM1 + NUM2 + NUM2), ios::beg);
		ifile.read(cName, NUM1);
		if (ifile.tellg() > 0) {
			strncpy(m_cName, cName, NUM1);
		}
		ifile.read(cIsbn, NUM2);
		if (ifile.tellg() > 0)
			strncpy(m_cIsbn, cIsbn, NUM1);
		ifile.read(cPrice, NUM2);
		if (ifile.tellg() > 0)
			strncpy(m_cPrice, cPrice, NUM2);
		ifile.read(cAuthor, NUM2);
		if (ifile.tellg() > 0)
			strncpy(m_cAuthor, cAuthor, NUM2);
	}
	catch (...) {
		throw "file error occurred";
		ifile.close();
	}
	ifile.close();
}

void CBook::DeleteData(int iCount) {
	long respos;
	int iDataCount = 0;
	fstream file;
	fstream tmpfile;
	ofstream ofile;
	char cTempBuf[NUM1 + NUM1 + NUM2 + NUM2];
	file.open("book.dat", ios::binary | ios::app | ios::out);
	tmpfile.open("temp.dat", ios::binary | ios::in | ios::out | ios::trunc);
	//  ios::trunc	      ,      

	file.seekg(0, ios::end);
	respos = file.tellg();
	//               ,               ,
	//          ,    

	iDataCount = respos / (NUM1 + NUM1 + NUM2 + NUM2);
	//              NUM1 + NUM1 + NUM2 + NUM2   
	//          /                      

	if (iCount < 0 || iCount > iDataCount)
	{
		throw "Input number error";
	}
	else
	{
		// file.seekg((iCount-1)*(NUM1 + NUM1 + NUM2 + NUM2), ios::beg);
		//                    

		file.seekg(0, ios::beg);

		for (int j = 1; j <= iDataCount; j++)
		{
			if (j == iCount)
			{
				file.seekg((iCount)*(NUM1 + NUM1 + NUM2 + NUM2), ios::beg);
			}
			if (!file.eof())
			{
				memset(cTempBuf, 0, NUM1 + NUM1 + NUM2 + NUM2);
				//  NUM1 + NUM1 + NUM2 + NUM2    0     cTempBuf

				file.read(cTempBuf, NUM1 + NUM1 + NUM2 + NUM2);
				//  file                NUM1 + NUM1 + NUM2 + NUM2      
				//         cTempBuf 。

				tmpfile.write(cTempBuf, NUM1 + NUM1 + NUM2 + NUM2);
				//    cTempBuf             tmpfile         
			}
		}
		file.close();

		tmpfile.seekg(0, ios::beg);
		//  tmpfile                  

		ofile.open("book.dat");
		//     "book.dat"   ,     ofile  ,           
		// ofile.seekp((iCount - 1)*(NUM1 + NUM1 + NUM2 + NUM2), ios::beg);

		ofile.seekp(0, ios::beg);
		// seekp:               

		for (int i = 1; i <= iDataCount; i++)
		{
			if (!ofile.eof())
			{
				memset(cTempBuf, 0, NUM1 + NUM1 + NUM2 + NUM2);
				tmpfile.read(cTempBuf, NUM1 + NUM1 + NUM2 + NUM2);
				ofile.write(cTempBuf, NUM1 + NUM1 + NUM2 + NUM2);
			}
		}
	}
	tmpfile.close();
	ofile.close();
	remove("temp.dat");
}

2.メインプログラム、主にインタフェースを設計する
// simATM.cpp :              。
//

#include "stdafx.h"
#include
#include
#include
#include
#include
#include
#include "Book.h"

#define CMD_COLS 80  
#define CMD_LINES 25 

using namespace std;

/*
     ,          ,         :
void SetScreenGrid:           。
void ClearScreen:      。
void SetSysCaption(const char *pText):       。
void Show Welcome:      。
void ShowRootMenu:      。
void WaitView(int iCurPage):           。
void WaitUser:      。
void Guidelnput:          。
int GetSelect:        。
long GetFileLength(ifstream & ifs):      。
void ViewData(int iSelPage):        。
voidDeleteBookFromFile:          。
void mainloop:   。
*/
void SetScreenGrid();
void ClearScreen();
void SetSysCaption();
void SetSysCaption(const char *pText);
void ShowWelcome();
void ShowRootMenu();
void WaitView(int  iCurPage);
void WaitUser();
void GuideInput();
int GetSelect();
long GetFileLength(ifstream & ifs);
void ViewData(int iSelPage);
void DeleteBookFromFile();
void mainloop();



void SetScreenGrid()
/*
       mode               、          。
SetScreenGrid      system     mode  ,
CMD_COLS CMD_LINES       。
*/
{
	char sysSetBuf[80];
	sprintf(sysSetBuf, "mode con cols=%d lines=%d", CMD_COLS, CMD_LINES);
	system(sysSetBuf);
}


void SetSysCaption()
/*
SetSysCaption                 Sample  。
             title     ,
     system     title  。
*/
{
	system("title Sample");
}



void ClearScreen()
/*
  ClearScreen    system     cls  ,
            。
*/
{
	system("cls");
	// system("cls")      #include  ,
	//                
}



void SetSysCaption(const char *pText)
/*
SetSysCaption        ,  SetSysCaption        ,
                    
*/
{
	char sysSetBuf[80];
	sprintf(sysSetBuf, "title %s", pText);
	system(sysSetBuf);
}


void ShowWelcome()
/*
ShowWelcome        “      ”       ,
“      ”               。
*/
{
	for (int i = 0; i<7; i++)
	{
		cout << endl;
	}
	cout << setw(50);
	cout << "*********************" << endl;
	cout << setw(50);
	cout << "*             *" << endl;
	cout << setw(50);
	cout << "*********************" << endl;
	// std::setw(n)             ,     iomanip (#include )
	// setw(int n)          (< ,
	// atoi()             (int),    int atoi(const char* str);
	// atoi()       str   ,         (    ,tab   ,    isspace()     ),
	//                  ,              ('\0')     ,
	//           ;  str     int  str     ,     0。
}


void WaitUser()
/*
WaitUser                   ,        。
           ,         。
*/
{
	int iInputPage = 0;
	cout << "enter     ,q  " << endl;
	char buf[256];
	gets_s(buf);
	if (buf[0] == 'q')
		system("exit");
}






void WaitView(int iCurPage)
{
	char buf[256];
	cin >> buf;
	if (buf[0] == 'q')
		system("exit");
	if (buf[0] == 'm')
		mainloop();
	if (buf[0] == 'n')
		ViewData(iCurPage);
}



long GetFileLength(ifstream& ifs)
/*
  GetFileLength         ,             。
       :1.  ifstream      (           );
2.  seekg get pointer      ,seekg(0, ios_base::end);
3.  tellg      ,       get pointer            ;
4.  get pointer,            ,        ,      seekg(0, ios_base::beg)。
*/
{
	long tmppos;
	long respos;
	tmppos = ifs.tellg();
	// tellg()        ,            
	ifs.seekg(0, ios::end);
	//          ,     0,            。
	// seekg()        ,      :         ,         。
	//        ,       ,        ,        。
	//          :
	// ios::beg:          ,   ;
	// ios::cur:          ;
	// ios::end:          ,   。
	// ifstream,  istream,       get pointer   ,            。
	respos = ifs.tellg();
	//             ,  ifs.tellg()          ,
	//   tellg      ,       get pointer            
	ifs.seekg(tmppos, ios::beg);
	//        ,    tmppos,          
	return respos;
}


void mainloop()
/*
main        ,     SetScreenGrid、SetSysCaption mainloop3   ,
  mainloop      ,         。
*/
{
	ShowWelcome();
	while (1)
	{
		ClearScreen();
		ShowWelcome();
		ShowRootMenu();
		switch (GetSelect())
		{
		case 1:
			ClearScreen();
			GuideInput();
			break;
		case 2:
			ClearScreen();
			ViewData(1);
			break;
		case 3:
			ClearScreen();
			DeleteBookFromFile();
			break;
		default:
			break;           //   GetSelect()        1、2、3    ,     while  。
		}
	}
}


//    
void main()
{
	SetScreenGrid();
	SetSysCaption("      ");
	mainloop();
}

3.図書の追加
void GuideInput()
/*
          GuideInput   ,
          、ISBN  、     ,
    CBook     CBook  ,
  CBook       WriteData         。
*/
{
	char inName[NUM1];
	char inlsdn[NUM1];
	char inPrice[NUM2];
	char inAuthor[NUM2];
	cout << "     :" << endl;
	cin >> inName;
	cout << "   ISBN:" << endl;
	cin >> inlsdn;
	cout << "     :" << endl;
	cin >> inPrice;
	cout << "     :" << endl;
	cin >> inAuthor;
	//   :cin     ,TAB     ,     ,      

	CBook book(inName, inlsdn, inPrice, inAuthor);     //     CBook   ,               
	book.WriteData();
	cout << "Write Finish!" << endl;

	//            
	cout << endl;
	cout << "******************************" << endl;
	cout << "         (   :      ,q :  ):" << endl;
	char buf;
	cin >> buf;
	if (buf == 'q')
		system("exit");
	else
		GuideInput();
}

4.図書を閲覧する
void ViewData(int iSelPage)
/*
            ViewData   。  ViewData         ,
      20   。   ViewData                    book.dat,
             ,             ,
                    ,                    ,
         20   ,          。
*/
{
	int iPage = 0;              // iPage                  
	int iCurPage = 0;           // iCurPage       
	int iDataCount = 0;         // iDataCount            

	char inName[NUM1];
	char inlsbn[NUM1];
	char inPrice[NUM2];
	char inAuthor[NUM2];

	bool bIndex = false;
	int iFileLength;
	iCurPage = iSelPage;

	ifstream ifile;
	//              ,ifstream    #include        
	ifile.open("book.dat", ios::binary);
	//     "book.dat"   ,     ifstream  。
	//      (     ) C               ,   C++   ,
	//           string  ,    C      。
	// open                  ,        ,
	//           ios::binary,       ,       :
	//	ios::in  
	//	ios::out  
	//  ios::app          
	//  ios::binary      
	//  ios::nocreate	       ,       ,     。
	//  ios::noreplace	       ,       ,     
	//  ios::trunc	      ,      
	//  ios::ate	       ,         
	//    :       ;         ,          ;
	//          ,  | (   );    byte   0  ,(      )。

	iFileLength = GetFileLength(ifile);         //               ,    
	iDataCount = iFileLength / (NUM1 + NUM1 + NUM2 + NUM2);  //      ,          
	if (iDataCount >= 1)
		bIndex = true;
	iPage = iDataCount / 20 + 1;

	ClearScreen();                 	//      
	cout << setw(15) << "    :" << iDataCount << " ";
	cout << setw(15) << "    :" << iPage << " ";
	cout << setw(15) << "    :" << iCurPage << " ";
	cout << setw(25) << "n       m   " << endl;
	cout << std::left << setw(15) << "lndex";
	cout << std::left << setw(15) << "Name" << std::left << setw(15) << "Isbn";
	cout << std::left << setw(15) << "Price" << std::left << setw(15) << "Author";
	cout << endl;

	// 
	try
	{
		//                          
		ifile.seekg((iCurPage - 1) * 20 * (NUM1 + NUM1 + NUM2 + NUM2), ios::beg);

		//   IO            ,                 
		//      IO      :
		// ifile.eof():  ifile eofbit  ,   true;
		// ifile.fail():  ifile failbit badbit  ,   true;
		// ifile.bad():  ifile badbit  ,   true;
		// ifile.good():  ifile      ,   true;
		//   good                true, bad、fail eof  
		//            true。  , badbit    ,fail    true。
		//     ,  good fail              ,
		//                : !ifile.fail()       。
		if (!ifile.fail())
		{
			for (int i = 1; i < 21; i++)   //   20 ,   20     
			{

				//     ,                 0
				// memset         ,               。 
				//     :void* memset(void *_Dst, int  _Val, size_t _Size)
				// _Dst       ,_Val     ,_Size        。
				//   ,char inName[128],    memset   inName    “0000...0000(128 0)”,
				//     :memset(inName, 0, sizeof(char) *128);
				//   ,memset       。
				memset(inName, 0, sizeof(char) * 128);
				memset(inlsbn, 0, sizeof(char) * 128);
				memset(inPrice, 0, sizeof(char) * 50);
				memset(inAuthor, 0, sizeof(char) * 50);

				if (ifile.eof())          //             , bIndex  false
				{
					bIndex = false;
				}
				else
					bIndex = true;

				if (bIndex)
					cout << std::right << setw(3) << ((iCurPage - 1) * 20 + i);

				//    read   write             
				// read       :     .read(char *buf,int len);
				// write       :     .write(const char *buf, int len);
				//         ,            ,
				//                       。
				//           ,              。
				ifile.read(inName, NUM1);	   //      
				cout << setw(18) << inName;
				ifile.read(inlsbn, NUM1);	   //     ISBN   
				cout << setw(18) << inlsbn;
				ifile.read(inPrice, NUM2);
				cout << setw(10) << inPrice;
				ifile.read(inAuthor, NUM2);
				cout << setw(15) << inAuthor;
				cout << endl;
			}
		}
	}
	catch (...)
	{
		cout << "throw file exception" << endl;
		throw "file error occurred";
		ifile.close();
	}


	if (iCurPage < iPage)
	{
		iCurPage = iCurPage + 1;
		WaitView(iCurPage);      //       
	}
	else
	{
		WaitView(iCurPage);
	}
	ifile.close();
}

5.図書の削除
void DeleteBookFromFile()
/*
            DeleteBookFromFile   ,
    DeleteBookFromFile      CBook  DeleteData       。
DeleteData                     ,
             。
*/
{
	int iDelCount;
	cout << "Input delete index" << endl;
	cin >> iDelCount;
	CBook tmpbook;
	tmpbook.DeleteData(iDelCount);
	cout << "Delete Finish" << endl;
	WaitUser();
}