C++,一个简单的图书管理系统,新手入门专用

时间:2020-12-02 17:44:43

我也是小白啊,先声明!!!

本文参考学习51CTOC++从入门到精通系列视频教程(初级篇)汪恺老师公开课。部分代码与老师课上有出入,因为比方说for each俺的就不能用,哪位大神能告诉我为啥呀?我可是原封不动照着老师代码敲的,编译不通过是必然的,只好靠自己的小聪明咯!公开课地址

话不多说,先po上源代码,可直接编译,不能编译请留言(563969790@qq.com)或者私信补发源代码。vs下编译环境只需要将unicode字符集改为多字节,同时设置为静态MFC。

那么,通过此段代码我们能学习到什么知识呢?

我认为,比较重要的方面有两个部分。

第一,了解编译器的特性,熟悉调试方法。这意味着,在今后的开发中,你有独立的解决bug的能力,当然,前提是你了解基础语法。但语法绝不是你学习编程语言的障碍,如果你这么想,只说明你还太年轻;第二,了解代码的组织结构和逻辑关系,是程序猿永不止步的源泉,宇宙有多么广博,这个坑就有多深。

具体,我认为重要的有一下几个部分:

1、了解C++/C的基本数据结构,同时如何自定义数据结构;

2、了解C++类的定义与功能实现(比如:登录,登出,注册,添加书本等等),什么是构造函数,什么是析构函数、操作符重载(讲道理,这地方我也懵,但是照猫画虎还是能用,哈哈);

3、如何实现默认参数传递,什么是用户接口统一;

4、文件I\o输入输出流,这个就大名鼎鼎了,很好理解但是很难记住(我不管,我知道它咋用就行了,你干嘛对我要求这么高),我用的时候查阅参考手册一般;

5、了解部分windows编程控制台、消息、句柄等逻辑关系;

剩下还有一些奇淫巧巧关于编译,调试,链接,宏定义,编译环境配置的一些技巧。这些不是主要的,但是对你的编程生涯肯定很重要,回报也远比你钻研指针什么的来的多。你知道了这些对你更好地、更快地造房子有用的多,至于材料的特性(也就是代码内在实现的逻辑)则需要时间的积累,当然更有用,但是你可能几年之后才意识到。

下面,好好看,好好学,runoob!

#include <iostream>
#include <stdio.h>
#include <string>
#include <algorithm>
#include <vector>
//#include <Windows.h>
#include <map>
#include <sstream>
#include <afxinet.h>
//#include <direct.h>
#include <Shlwapi.h>
#include <fstream>

//告诉连接器,增加lib的引用
#pragma comment(lib,"Shlwapi.lib")

using namespace std;

#define FG_RED FOREGROUND_INTENSITY | FOREGROUND_RED
#define FG_GREEN FOREGROUND_INTENSITY | FOREGROUND_GREEN
#define FG_GRAY FOREGROUND_RED | FOREGROUND_GREEN | FOREGROUND_BLUE
//#define _AFXDLL

//枚举类 enum
enum LV
{
INFO,
ERR,
OK
};

//log 日志抽象为一个实体 方便验错
class log_level
{
public:

//成员变量,跟着类的实体走
LV m_lv;
HANDLE m_handle;

//构造函数-造房子 函数名与类名一致
log_level(LV log_v)
{
m_lv = log_v;

//windows api
//获取标准输出句柄
m_handle = GetStdHandle(STD_OUTPUT_HANDLE);

if (log_v == ERR)
{
SetConsoleTextAttribute(m_handle,FG_RED);
}
else if (log_v == OK)
{
SetConsoleTextAttribute(m_handle,FG_GREEN);
}
else
{
SetConsoleTextAttribute(m_handle,FG_GRAY);
}
}

//析构函数-拆房子
~log_level()
{
SetConsoleTextAttribute(m_handle,FG_GRAY);
}

// 操作符重载
operator char*()
{
return "";
}
};

enum STATUS
{
IN_STOCK,
ON_LOAN

};
class Book
{
public:
int id;
string name;
STATUS status_book;

//默认参数,此参数只有c++才有,意思是该参数可以不传默认为设定键值
Book(int inputID,string inputName,STATUS status = IN_STOCK)
{
id = inputID;
name = inputName;
status_book = status;

}
//给书装配一些属性
};

//书籍数据库
vector<Book> bookDB;

typedef vector<string> STR_MATRIX;

//用户数据库
map<string,string> userDataBase;

//切割,返回字符数组哟,好强大
vector<string> split(string str)
{
vector<string> totalChunks;
string chunkBuffer = "";
int i;

for(i = 0;i<str.size();i++)
{
char c = str[i];
if(c == ' ')
{
if(chunkBuffer != "")
{
totalChunks.push_back(chunkBuffer);
chunkBuffer = "";
}
}
else
{
chunkBuffer += c;
}
}

if(chunkBuffer != "")
{
totalChunks.push_back(chunkBuffer);

}
return totalChunks;
}

class BookSystem
{
public:

BookSystem()
{
lastID = 0;
}

//设置路径
string getDbpath()
{
//获取自己的路径window下必须用api,获取当前路径
char buff[MAX_PATH];

//获取.exe文件下的目录
GetModuleFileName(NULL, buff, MAX_PATH);
//getcwd(buff, MAX_PATH);

//获取当前目录
//GetCurrentDirectory(MAX_PATH, buff);

//第二个参数需要用到unicode字符集,在工程中修改属性
//在该目录下创建你需要的文件或者文件夹
PathRemoveFileSpec(buff);

//连接数据库名
PathAppend(buff, "booksysdb.txt");

return buff;//string 构造函数支持
}

//抽象动作
void runCommand(string input)
{
//分割输入
vector<string> chunks = split(input);

string cmdName;
cmdName = chunks[0];

if(cmdName == "reg")
{
reg(chunks);
}
else if(cmdName == "login")
{
login(chunks);
}
else if (cmdName == "addbook")
{
addbook(chunks);
}
else if (cmdName == "listbook")
{
listbook(chunks);
}
else if (cmdName == "savedb")
{
savedb(chunks);
}
else if (cmdName == "loaddb")
{
loaddb(chunks);
}

}

//用户功能实现
void reg(vector<string> chunks)
{

if(chunks.size() < 3)
{
cout << log_level(ERR) << "Syntax error:reg command requires 2 parameters:UserName and PassWord" <<endl;
return;
}
else
{
string userName = chunks[1];
string passWord = chunks[2];

//用户验证防止重复注册
if (userDataBase.find(userName) == userDataBase.end())
{
userDataBase[userName] = passWord;
cout << log_level(OK) << "the user" << userName << "has been registered successful" << endl;
}
else
{
cout << log_level(ERR) << "the user" << userName << "has been existed" << endl;
}

}

return;
}

void login(vector<string> chunks)
{
if(chunks.size() < 3)
{
cout << log_level(ERR) << "Syntax error:login command requires 2 parameters:UserName and PassWord" <<endl;
return;
}
else
{
string userName = chunks[1];
string passWord = chunks[2];

//用户验证防止重复注册
if (userDataBase.find(userName) == userDataBase.end())
{
cout << log_level(ERR) << "the user" << userName << "is not found" << endl;
}
else
{
if(userDataBase[userName] == passWord)
{
cout << log_level(OK) << "the user" << userName << "has been logined" << endl;
}
else
{
cout << log_level(ERR) << "the password is correct" << endl;
}
}

}

};

int lastID;
void addbook(vector<string> chunks)
{
//addbook 语文 若干本
string title_name = chunks[1];
string countStr = chunks[2];

//将字符类型string转换成整型
for (int i = 0; i < atoi(countStr.c_str()); i++)
{
lastID++;

Book newBook(lastID, title_name);

bookDB.push_back(newBook);
}
cout << log_level(OK) << "add book successfully" << endl;

}

//
void listbook(vector<string> chunks)
{
for(int i = 0; i < bookDB.size(); i++)
{
Book book = bookDB[i];
cout << log_level(OK) << book.id << " " << book.name << endl;
}
}

//用户接口统一
void loaddb(vector<string> chunks)
{
loadb_internal();
}

void loadb_internal()
{
//加载数据库
//获取当前路径
string dbPath = getDbpath();

//cout << dbPath << endl;

//创建文件的输入文件流
//input file stream
ifstream input(dbPath);

if (input.bad())
{
// Dump the contents of the file to cout.
cout << "数据库打开失败";
input.close();
}
else
{

string currline;
//读取文本每一行,知道结束(eof,只要没结束就继续啦)
while(getline(input,currline))
{
//获取每一行
//切割
auto chunks = split(currline);

//判断内容是否为空白
if (chunks.size() == 0)
{
break;
}

if(chunks[0] == "USER")
{
string userName = chunks[1];
string password = chunks[2];

//插入DB
userDataBase[userName] = password;

}
else if (chunks[0] == "BOOK")
{
string idStr = chunks[1];
string name = chunks[2];
string statusStr = chunks[3];

//转换相应类型后传入参数 istringstream(id)
int id;
istringstream(idStr) >> id;

//enum枚举本质是int
//加& 代表引用
STATUS status;
istringstream(statusStr) >> (int&)status;

Book currBook(id, name, status);
bookDB.push_back(currBook);
}

}

input.close();
}

}

//
void savedb(vector<string> chunks)
{
//获取当前路径
string dbPath = getDbpath();

//文件输出流output file stream
ofstream output(dbPath);

//保存用户信息
//键+值 = 对
map<string, string>::iterator it = userDataBase.begin();
for (;it != userDataBase.end() ;++it)
{
output << "USER" << " " << it->first << " " << it->second << endl;
}

//保存书本信息
vector<Book>::iterator itk = bookDB.begin();
for (; itk != bookDB.end(); ++itk)
{
output << "BOOK" << " " << itk->id << " " << itk->name << " " << itk->status_book << endl;
}

output.close();

}

};

int main(int argc,char* argv[])
{
BookSystem bookSys;

//string dbPath = bookSys.getDbpath();
bookSys.loadb_internal();

cout << ("hello welcome to my world") << endl;

string inputBuffer;
do
{
cout << ("book system>>");

//cin >>inputBuffer;
//输入可包含空格
getline(cin,inputBuffer);

bookSys.runCommand(inputBuffer);

}while(inputBuffer != "exit");

}

记得保持微笑

C++,一个简单的图书管理系统,新手入门专用C++,一个简单的图书管理系统,新手入门专用C++,一个简单的图书管理系统,新手入门专用C++,一个简单的图书管理系统,新手入门专用C++,一个简单的图书管理系统,新手入门专用C++,一个简单的图书管理系统,新手入门专用C++,一个简单的图书管理系统,新手入门专用C++,一个简单的图书管理系统,新手入门专用C++,一个简单的图书管理系统,新手入门专用C++,一个简单的图书管理系统,新手入门专用C++,一个简单的图书管理系统,新手入门专用C++,一个简单的图书管理系统,新手入门专用C++,一个简单的图书管理系统,新手入门专用C++,一个简单的图书管理系统,新手入门专用C++,一个简单的图书管理系统,新手入门专用C++,一个简单的图书管理系统,新手入门专用C++,一个简单的图书管理系统,新手入门专用C++,一个简单的图书管理系统,新手入门专用C++,一个简单的图书管理系统,新手入门专用C++,一个简单的图书管理系统,新手入门专用C++,一个简单的图书管理系统,新手入门专用C++,一个简单的图书管理系统,新手入门专用C++,一个简单的图书管理系统,新手入门专用C++,一个简单的图书管理系统,新手入门专用C++,一个简单的图书管理系统,新手入门专用C++,一个简单的图书管理系统,新手入门专用C++,一个简单的图书管理系统,新手入门专用C++,一个简单的图书管理系统,新手入门专用C++,一个简单的图书管理系统,新手入门专用C++,一个简单的图书管理系统,新手入门专用C++,一个简单的图书管理系统,新手入门专用C++,一个简单的图书管理系统,新手入门专用C++,一个简单的图书管理系统,新手入门专用C++,一个简单的图书管理系统,新手入门专用C++,一个简单的图书管理系统,新手入门专用C++,一个简单的图书管理系统,新手入门专用C++,一个简单的图书管理系统,新手入门专用C++,一个简单的图书管理系统,新手入门专用