基于文件流的图书管理系统(C/C++实现)

基于文件流的图书管理系统(C/C++实现)

在这里插入图片描述

一、项目背景

在日常的图书馆管理中,图书的管理往往需要涉及到对图书数据的增删查改(CRUD)操作。为了更好地管理图书信息,我们可以利用C++的文件流(fstream)功能,结合简单的结构体和菜单界面,实现一个图书管理系统。本文将详细介绍如何基于文件流实现一个图书管理系统,涵盖图书信息的增、删、改、查操作。

二、项目功能概述

本图书管理系统包括以下主要功能:

  1. 添加图书:用户可以输入图书信息,将图书数据保存到文件中。
  2. 删除图书:支持按图书编号或图书名称删除图书信息。
  3. 修改图书信息:用户可以修改已有图书的信息。
  4. 查询图书:支持按图书编号或名称查询图书信息。
  5. 显示图书列表:展示所有图书的信息。

三、代码剖析

0.实现大致的菜单界面 main(); choose();

//根据用户输入的功能码选择功能函数 
void choose(int input){
	system("cls");
	switch(input){
		case 1: 
		cout << "你选择了添加功能" << endl ; 
			add();
			break;
		case 2: 
		cout << "你选择了删除功能" << endl ; 
			del(); 
			break;
		case 3: 
		cout << "你选择了修改功能" << endl ; 
			modifyBook();
			break;
		case 4: 
		cout << "你选择了列表功能" << endl ; 
			list(); 
			break;
		case 5: 
		cout << "你选择了查询功能" << endl ; 
			searchBook();
			break;
		case 0:     //退出系统也会实现先暂停退出   希望将这个选项排除 
			//1.加判断if  
			//2.修改 break 为 return 
			cout << "退出系统" << endl ;
			return ;
		default:
			cout << "功能码错误" << endl; 
	}
    
   //不管执行什么方法,都会去执行 暂停 以及 清空 
	system("pause"); 
	system("cls");
}



int main(int argc, char** argv) {
	int input = 1;
	 while(input !=0){
	 	
		cout << "1.添加图书"<< endl; 
		cout << "2.删除图书"<< endl; 
		cout << "3.修改图书"<< endl; 
		cout << "4.图书列表"<< endl; 
		cout << "5.图书查询"<< endl;
		cout << "0.退出系统"<< endl;
		cout << "输入选择功能(0-5)"<< endl;
		//用户把输入的值赋值给input  input作为循环条件 
		// 
		cin >> input; 	
		choose (input);
	 	 
	 	
	 }
	
	return 0;
}

1.定义了一个结构体 封装图书信息 添加add() 和 列表list()

首先实现两个比较容易实现的功能 add() 和list()

#include <iostream>
#include <string>
#include<fstream>//引入文件流 

using namespace std;
 

//定义一个结构体用于封装图书信息
struct Book {
    int no;                // 编号
    string bookName;       // 书名
    string author;         // 作者
    string publisher;      // 出版社
    double price;          // 价格
    string category;       // 分类
  
}; 

void add(){
	Book book;
    //添加数据处理 
	book.no = inputNo();
	book.bookName = inputbookName(); 
    
	cout << "请输入图书的编号"<< endl;
	cin >> book.no;
	
	cout << "请输入图书的书名"<< endl;
	cin >>book.bookName;
	
	cout << "请输入图书的作者"<< endl;
	cin >> book.author; 
	
	cout << "请输入图书的出版社"<< endl;
	cin >> book.publisher;
	
	cout << "请输入图书的价格"<< endl;
	cin >> book.price;
	
	cout << "请输入图书的分类"<< endl;
 	cin >> book.category;
	//使用文件流 把数据写入文件中去长期保存 
	//默认以覆盖的形式去打开文件 
	//ios::app 用来设置追加模式 
	ofstream o("book.txt", ios::app);  //把图书信息保存到文件里去 
	o << book.no << " " << book.bookName << " " << book.author <<" "
	  << book.publisher << " " << book.price << " " << book.category <<endl; 
	  
	//关闭流文件 
	o.close(); 
	cout <<"添加成功" <<endl;
	//暂停控制台的执行 
//	system("pause"); 
//	system("cls");
}


//用来打印学生列表的函数 
void list(){
	// 从文件中读取数据打印到控制台
	ifstream in("Book.txt"); 
	Book book;
	cout <<"编号\t书名\t作者\t出版社\t价格\t分类" << endl;  
	//读取的顺序必须和写入顺序相同 
	while(in >> book.no >> book.bookName >> book.author >>book.publisher >> book.price >> book.category ){
		cout <<  book.no << "\t";  
		cout <<  book.bookName << "\t";  
		cout <<  book.author << "\t";  
		cout <<  book.publisher << "\t";  
		cout <<  book.price << "\t";  
		cout <<  book.category << endl;  
	}
 
}

2.数据处理

对于add(); 这里需要对数据的校验进行判断 需要在 add ();的前方定义 多个个方法 实现数据输入的处理

这里我尝试使用递归的形式去判断

1.处理图书的编号

int inputNo(){
    cout << "请输入图书编号(编号必须是7位数, 并且不可以重复)" << endl;
    int no;
    cin >> no;
    while(no <1000000 || 9999999){
        cout << "编号必须是7位数, 并且不可以重复"  << endl;
        return inputNo();//递归调用
    }
    return no;
    //校验图书编号是否重复
	ifstream in ("Book.txt");
	Book book;
	while(in >> book.no >> book.bookName >> book.author >>book.publisher >> book.price >> book.category){
		if(no == book.no){
			cout << "学号已经存在,请重新输入" << endl;
			return inputNo(); 
		}
	}

修改 add book.no = inputNo();

2.处理图书名字

//使用while判断逻辑 不用递归了
string inputbookName(){
	cout << "请输入图书的名称(名称必须1-20字)" <<endl;
    string bookName;
    cin >> bookName;
    while(bookName.size() < 1|| bookName.size() > 20){
    cout << "名字的长度必须是1-20位,请重新输入。" << endl;
    cin >> bookName;
    }
    return bookName;
}

处理

string author;         // 作者
string publisher;      // 出版社
double price;          // 价格
string category;       // 分类

3.判断作者的数据

//使用while判断逻辑 不用递归了
string inputAuthor(){
	cout << "请输入作者的名字(名称必须2-8位)" <<endl;
    string author;
    cin >> author;
    while(author.size() < 1|| author.size() > 20){
    cout << "名字的长度必须是1-20位,请重新输入。" << endl;
    cin >> author;
    }
    return author;
}

4.判断出版社

//使用while判断逻辑  
string inputPublisher(){
	cout << "请输入作者的名字(名称必须2-8位)" <<endl;
    string publisher;
    cin >> publisher;
    while(publisher.size() < 1|| publisher.size() > 20){
    cout << "出版社的长度必须是1-20位,请重新输入。" << endl;
    cin >> publisher;
    }
    return publisher;
}

5.判断价格

double inputPrice(){
    cout << "请输入图书价格(价格1 - 1000)" << endl;
    double price;
    cin >> price;
    while(price < 0 || price > 9999){
        cout << "编号必须是有效数字小于9999位数"  << endl;
        return inputPrice();//递归调用
    }
    return price;
}

double inputPrice(){
    cout << "请输入图书价格(价格1 - 1000)" << endl;
    double price;
    cin >> price;
    while(price < 0 || price > 9999){
        cout << "编号必须是有效数字小于9999位数"  << endl;
        cin >> price;
    }
    return price;
}

6.判断分类 只能是 文学 科学 自然 名著

//使用while判断逻辑 不用递归了
string inputCategory(){
	cout << "请输入图书的类别(文学 科学 自然  名著)" <<endl;
    string category;
    cin >>category;
    while(category !="文学" &&category !="科学" && category !="自然" && category !="名著"){
    cout << "图书的类别(文学 科学 自然  名著),请重新输入。" << endl;
    cin >> category;
    }
    return category;
}

3.实现删除功能del(); 抽象 delByNo(); 以及 delByName();

a. 将编号删除抽象出来单独实现void delByNo();

//根据编号删除  需要从文件删除
void delByNo(){
    cout << "输入需要删除图书的学生学号"<< endl;
    int no;
    cin >> no;
    
    ifstream in("book.txt");
    //泛型用来限制该对象只能存储学生类型的数据
	vector<Book> list; 
    Book book1;
    bool result = false; //判断是否删除成功
    //将数据存储到泛型,再到对象中book1
    while (in >> book1.no >> book1.bookName >> book1.author >>book1.publisher >> book1.price >> book1.category){
        if(book1.no == no){
       	continue;
	   }
        list.push_back(book1);
    }
    in.close();
    //把vector里的数据写入到文件里去,直接覆盖,
	ofstream o("Book.txt"); 
	//使用for循环读取vector数据,在写入 
	for(int i = 0; i<list.size(); i++){
		Book book = list[i];  //将这个写入文件  添加的那个使用过 
	//实现写入 
		o << book.no << " " << book.bookName << " " << book.author <<" "
	  << book.publisher << " " << book.price << " " << book.category <<endl; 
	} 
	//写完之后关闭 输入流
	o.close(); 
    
    //判断bool类型的结果
    if(result){
         cout << "输出成功" << endl;
    }else {
        cout << "输出失败" << endl;
    }
}
3.1修改过程
 这里的功能实现了全部读取全部输出,没有进行逻辑控制添加如下语句后可以实现 

if(book1.no == no){ continue; }

  • 由于cpp不支持删除某一行,需要一个额外的文件来辅助完成,使用一行一行的读取,把需要的读取到新文件里 最后把酒文件删除
    
  •  还可以使用覆盖的操作去间接的实现
    

这里需要引入一个动态数组vector

这个代码虽然可以运行但是,删除以后 知道是否删除成功 这里只要执行到了if语句里边就表示删除成功了

bool result = FALSE;

  //判断bool类型的结果
    if(result){
         cout << "输出成功" << endl;
    }else {
        cout << "输出失败" << endl;
    }

b. void delByName();

// 根据书名删除
void delByName()
{
	cout << "请输入需要删除的图书名称:" << endl;
	string bookName;
	cin >> bookName;

	ifstream in("book.txt");
	vector<Book> list;
	Book book1;
	 
    //记录本次删除的人数
    int count = 0;
    

	// 读取所有图书信息,跳过要删除的图书
	while (in >> book1.no >> book1.bookName >> book1.author >> book1.publisher >> book1.price >> book1.category)
	{
		if (book1.bookName == bookName)
		{
			count ++; // 找到要删除的图书
			continue;
		}
		list.push_back(book1);
	}
	in.close();

	// 将剩余图书信息重新写入文件
	ofstream o("book.txt");
	for (int i = 0; i < list.size(); i++)
	{
		Book book = list[i];
		o << book.no << " " << book.bookName << " " << book.author << " "
		  << book.publisher << " " << book.price << " " << book.category << endl;
	}
	o.close();

	if (count > 0)
	{
		cout << "删除成功,本次删除了" << count  << "本书" << endl;
	}
	else
	{
		cout << "未找到该书名的图书,删除失败" << endl;
	}
}

c. void del();

//删除 
void del() {
    int type;
    while (true) {
        cout << "选择删除方式 1.根据图书编号删除 2.根据图书书名删除" << endl;
        cin >> type;
        if (type == 1) {
            delByNo();
            break;
        } else if (type == 2) {
            delByName();
            break;
        } else {
            cout << "输入错误,请重新选择" << endl;
        }
    }
}

4.实现查询功能searchBook();

a. void searchByNo();

//根据编号查询    使用首先读取文件流  ifstream , 将文件的 内容读取出来  如果有相同的则 跳出循环
void searchByNo(){
    cout << "请输入要查询的图书编号"  << endl;
    int no;
    cin >> no;
    ifstream in ("Book.txt");
    Book book;
    bool result = false;
    while(in >> book.no >> book.bookName >> book.author >> book.publisher >> book.price >> book.category){
		if(no == book.no){
            result = true;
           // 打印表头
            cout << "\n编号\t书名\t作者\t出版社\t价格\t分类" << endl;
        	cout << book.no << "\t";
			cout << book.bookName << "\t";
			cout << book.author << "\t";
			cout << book.publisher << "\t";
			cout << book.price << "\t";
			cout << book.category << endl;
            break; //找到之后退出循环  由于编号不会重复
        }
       
		
    }
    //判断是否存在
    if(!result){
        cout << "该编号不存在" << endl;
    }
}

b. void searchByName();

//按书名查询
void searchByName(){
     cout << "请输入要查询的图书名字"  << endl;
    string bookName;
    cin >> bookName;
    ifstream in ("Book.txt");
    Book book;
    bool result = false;  
    while(in >> book.no >> book.bookName >> book.author >> book.publisher >> book.price >> book.category){
		if(bookName == book.bookName){
           // result = true;
            
            if(!result)
            // 打印表头
            	cout << "\n编号\t书名\t作者\t出版社\t价格\t分类" << endl;   
            
          	 
            /*这里的表头会多次输出,解决方法 
           			 1 放到循环外部  任何时候都会输出
                     2.将 result = true;	反倒后方		*/
        	cout << book.no << "\t";
			cout << book.bookName << "\t";
			cout << book.author << "\t";
			cout << book.publisher << "\t";
			cout << book.price << "\t";
			cout << book.category << endl;
             result = true;
            // break;//这里的书名可能会重复
        }
        
    }
     //判断是否存在
    if(!result){
        cout << "该图书不存在" << endl;
    }
}

c. void searchBook();

//这里同样抽象出两个功能   实现no  和bookName查找
void searchBook(){
	cout << " 请选择查询方式:" << endl;
    cout << "1. 按编号查询" << endl;
	cout << "2.按书名查询" << endl;
    
    int type;
    cin >> type;
    
    if(type == 1){
        searchByNo();
    }else if(type == 2){
       searchByName();
    }else{
        cout << "输入错误,请重新输入" << endl;
        searchBook();
    }
}

5.修改功能void modifyBook();

//修改后成功运行
void modifyBook() {
    cout << "请输入要修改的图书编号:" << endl;
    int no;
    cin >> no;
    ifstream in("book.txt");
    //泛型用来限制该对象只能存储学生类型的数据
    vector<Book> bookList; 
    Book book1;
    bool result = false; // 判断是否找到图书

    // 将文件数据读取到 bookList 中
    while (in >> book1.no >> book1.bookName >> book1.author >> book1.publisher >> book1.price >> book1.category) {
        bookList.push_back(book1);
    }
    in.close();
    
    // 遍历图书列表,查找需要修改的图书
    for (int i = 0; i < bookList.size(); i++) {
        Book& book2 = bookList[i];  // 使用引用来直接修改 bookList 中的数据
        
        // 判断图书编号是否匹配
        if (book2.no == no) {
            // 输出当前图书信息
            cout << "编号\t书名\t作者\t出版社\t价格\t分类" << endl;  
            cout <<  book2.no << "\t";  
            cout <<  book2.bookName << "\t";  
            cout <<  book2.author << "\t";  
            cout <<  book2.publisher << "\t";  
            cout <<  book2.price << "\t";  
            cout <<  book2.category << endl;

            // 修改数据
             //如果可以进入if则可以找到
             //添加数据处理 并输入
            result = true;
            book2.no = inputNo();
            book2.bookName = inputbookName();
            book2.author = inputAuthor();
            book2.publisher = inputPublisher();
            book2.price = inputPrice();
            book2.category = inputCategory();
            break;  // 找到并修改后退出循环
        }
    }

    // 如果没有找到该编号,输出提示信息
    if (!result) {
        cout << "该编号不存在" << endl;
    } else {
        // 将修改后的数据写回到文件   使用文件流  实现覆盖
        ofstream o("book.txt");  // 打开文件进行写入
        if (o.is_open()) {
            // 遍历修改后的 bookList 并写回文件
            for (int i = 0; i < bookList.size(); i++) {
                Book& book2 = bookList[i];
                o << book2.no << " " << book2.bookName << " " << book2.author << " "
                  << book2.publisher << " " << book2.price << " " << book2.category << endl;
            }
            o.close();  // 完成写入后关闭文件流
            cout << "修改成功" << endl;
        } else {
            cout << "文件写入失败!" << endl;
        }
    }
}

四、完整代码

    #include <iostream>
#include <string>
#include<fstream>//引入文件流 
#include<vector> //删除模块使用到 

using namespace std;

//定义一个结构体用于封装图书信息
struct Book {
    int no;                // 编号
    string bookName;       // 书名
    string author;         // 作者
    string publisher;      // 出版社
    double price;          // 价格
    string category;       // 分类
  
}; 


 
//用来获取输入的图书序号进行格式校验  递归 
int inputNo(){
    cout << "请输入图书编号(编号必须是7位数, 并且不可以重复)" << endl;
    int no;
    cin >> no;
    while (no < 1000000 || no > 9999999){
        cout << "编号必须是7位数, 并且不可以重复"  << endl;
        return inputNo();//递归调用
    }
    return no;
    //校验图书编号是否重复
	ifstream in ("Book.txt");
	Book book;
	while(in >> book.no >> book.bookName >> book.author >>book.publisher >> book.price >> book.category){
		if(no == book.no){
			cout << "学号已经存在,请重新输入" << endl;
			return inputNo(); 
		}
	}
    
}

//使用while判断逻辑 不用递归了
string inputbookName(){
	cout << "请输入图书的名称(名称必须1-20字)" <<endl;
    string bookName;
    cin >> bookName;
    while(bookName.size() < 1|| bookName.size() > 20){
    cout << "名字的长度必须是1-20位,请重新输入。" << endl; 
    cin >> bookName;
    }
    return bookName;
}

//使用while判断逻辑 不用递归了
string inputAuthor(){
	cout << "请输入作者的名字(名称必须2-8位)" <<endl;
    string author;
    cin >> author;
    while(author.size() < 1|| author.size() > 20){
    cout << "名字的长度必须是1-20位,请重新输入。" << endl;
    cin >> author;
    }
    return author;
}

//使用while判断逻辑  
string inputPublisher(){
	cout << "请输入作者的名字(名称必须2-8位)" <<endl;
    string publisher;
    cin >> publisher;
    while(publisher.size() < 1|| publisher.size() > 20){
    cout << "出版社的长度必须是1-20位,请重新输入。" << endl;
    cin >> publisher;
    }
    return publisher;
}

double inputPrice(){
    cout << "请输入图书价格(价格1 - 1000)" << endl;
    double price;
    cin >> price;
    while(price < 0 || price > 9999){
        cout << "编号必须是有效数字小于9999位数"  << endl;
        return inputPrice();//递归调用
    }
    return price;
}

//使用while判断逻辑 不用递归了
string inputCategory(){
	cout << "请输入图书的类别(文学 科学 自然  名著)" <<endl;
    string category;
    cin >>category;
    while(category !="文学" &&category !="科学" && category !="自然" && category !="名著"){
    cout << "图书的类别(文学 科学 自然  名著),请重新输入。" << endl;
    cin >> category;
    }
    return category;
}

void add(){
	Book book;
	 //添加数据处理 
	book.no = inputNo();
	book.bookName = inputbookName(); 
	book.author = inputAuthor();
	book.publisher =inputPublisher();
	book.price =  inputPrice();
	book.category = inputCategory();
//	cout << "请输入图书的编号"<< endl;
//	cin >> book.no;
//	
//	cout << "请输入图书的书名"<< endl;
//	cin >>book.bookName;
//	
//	cout << "请输入图书的作者"<< endl;
//	cin >> book.author; 
//	
//	cout << "请输入图书的出版社"<< endl;
//	cin >> book.publisher;
//	
//	cout << "请输入图书的价格"<< endl;
//	cin >> book.price;
//	
//	cout << "请输入图书的分类"<< endl;
// 	cin >> book.category;
	//使用文件流 把数据写入文件中去长期保存 
	//默认以覆盖的形式去打开文件 
	//ios::app 用来设置追加模式 
	ofstream o("book.txt", ios::app);  //把图书信息保存到文件里去 
	o << book.no << " " << book.bookName << " " << book.author <<" "
	  << book.publisher << " " << book.price << " " << book.category <<endl; 
	  
	//关闭流文件 
	o.close(); 
	cout <<"添加成功" <<endl;
	//暂停控制台的执行 
//	system("pause"); 
//	system("cls");
}
//用来打印学生列表的函数 
void list(){
	// 从文件中读取数据打印到控制台
	ifstream in("Book.txt"); 
	Book book;
	cout <<"编号\t书名\t作者\t出版社\t价格\t分类" << endl;  
	//读取的顺序必须和写入顺序相同 
	while(in >> book.no >> book.bookName >> book.author >>book.publisher >> book.price >> book.category ){
		cout <<  book.no << "\t";  
		cout <<  book.bookName << "\t";  
		cout <<  book.author << "\t";  
		cout <<  book.publisher << "\t";  
		cout <<  book.price << "\t";  
		cout <<  book.category << endl;  
	}
 
}


//根据编号删除  需要从文件删除
void delByNo(){
    cout << "输入需要删除图书的学生学号"<< endl;
    int no;
    cin >> no;
    
    ifstream in("book.txt");
    //泛型用来限制该对象只能存储学生类型的数据
	vector<Book> list; 
    Book book1;
    bool result = false; //判断是否删除成功
    //将数据存储到泛型,再到对象中book1
    while (in >> book1.no >> book1.bookName >> book1.author >>book1.publisher >> book1.price >> book1.category){
        if(book1.no == no){
         
       	continue;
	   }
        list.push_back(book1);
    }
    in.close();
    //把vector里的数据写入到文件里去,直接覆盖,
	ofstream o("Book.txt"); 
	//使用for循环读取vector数据,在写入 
	for(int i = 0; i<list.size(); i++){
		Book book = list[i];  //将这个写入文件  添加的那个使用过 
	//实现写入 
		o << book.no << " " << book.bookName << " " << book.author <<" "
	  << book.publisher << " " << book.price << " " << book.category <<endl; 
	} 
	//写完之后关闭 输入流
	o.close(); 
    
    //判断bool类型的结果
    if(result){
         cout << "输出成功" << endl;
    }else {
        cout << "输出失败" << endl;
    }
}

// 根据书名删除
// 根据书名删除
void delByName()
{
	cout << "请输入需要删除的图书名称:" << endl;
	string bookName;
	cin >> bookName;

	ifstream in("book.txt");
	vector<Book> list;
	Book book1;
	 
    //记录本次删除的人数
    int count = 0;
    

	// 读取所有图书信息,跳过要删除的图书
	while (in >> book1.no >> book1.bookName >> book1.author >> book1.publisher >> book1.price >> book1.category)
	{
		if (book1.bookName == bookName)
		{
			count ++; // 找到要删除的图书
			continue;
		}
		list.push_back(book1);
	}
	in.close();

	// 将剩余图书信息重新写入文件
	ofstream o("book.txt");
	for (int i = 0; i < list.size(); i++)
	{
		Book book = list[i];
		o << book.no << " " << book.bookName << " " << book.author << " "
		  << book.publisher << " " << book.price << " " << book.category << endl;
	}
	o.close();

	if (count > 0)
	{
		cout << "删除成功,本次删除了" << count  << "本书" << endl;
	}
	else
	{
		cout << "未找到该书名的图书,删除失败" << endl;
	}
}



//删除 
void del(){
	cout << "选择删除方式 1.根据图书编号删除 2.根据图书书名删除" <<endl; 
	int type;
	cin >> type;
	if(type == 1){	
		delByNo();
	}else if(type == 2){
		delByName();
	}else{
		cout << "输入错误" <<endl; 
		//递归调用
		del(); 
	}
} 

//根据编号查询 
void searchByNo(){
    cout << "请输入要查询的图书编号"  << endl;
    int no;
    cin >> no;
    ifstream in ("Book.txt");
    Book book;
    bool result = false;
    while(in >> book.no >> book.bookName >> book.author >> book.publisher >> book.price >> book.category){
		if(no == book.no){
            result = true;
           // 打印表头
            cout << "\n编号\t书名\t作者\t出版社\t价格\t分类" << endl;
        	cout << book.no << "\t";
			cout << book.bookName << "\t";
			cout << book.author << "\t";
			cout << book.publisher << "\t";
			cout << book.price << "\t";
			cout << book.category << endl;
            break; //找到之后退出循环  由于编号不会重复
        }
       
		
    }
    //判断是否存在
    if(!result){
        cout << "该编号不存在" << endl;
    }
}

//按书名查询
void searchByName(){
     cout << "请输入要查询的图书名字"  << endl;
    string bookName;
    cin >> bookName;
    ifstream in ("Book.txt");
    Book book;
    bool result = false;  
    while(in >> book.no >> book.bookName >> book.author >> book.publisher >> book.price >> book.category){
		if(bookName == book.bookName){
           // result = true;
            
            if(!result)
            // 打印表头
            	cout << "\n编号\t书名\t作者\t出版社\t价格\t分类" << endl;   
            
          	 
            /*这里的表头会多次输出,解决方法 
           			 1 放到循环外部  任何时候都会输出
                     2.将 result = true;	反倒后方		*/
        	cout << book.no << "\t";
			cout << book.bookName << "\t";
			cout << book.author << "\t";
			cout << book.publisher << "\t";
			cout << book.price << "\t";
			cout << book.category << endl;
             result = true;
            // break;//这里的书名可能会重复
        }
        
    }
     //判断是否存在
    if(!result){
        cout << "该图书不存在" << endl;
    }
}
  

void searchBook(){
	cout << " 请选择查询方式:" << endl;
    cout << "1. 按编号查询" << endl;
	cout << "2.按书名查询" << endl;
    
    int type;
    cin >> type;
    
    if(type == 1){
        searchByNo();
    }else if(type == 2){
       searchByName();
    }else{
        cout << "输入错误,请重新输入" << endl;
        searchBook();
    }
}


void modifyBook() {
    cout << "请输入要修改的图书编号:" << endl;
    int no;
    cin >> no;
    ifstream in("book.txt");
    vector<Book> bookList; 
    Book book1;
    bool result = false; // 判断是否找到图书

    // 将文件数据读取到 bookList 中
    while (in >> book1.no >> book1.bookName >> book1.author >> book1.publisher >> book1.price >> book1.category) {
        bookList.push_back(book1);
    }
    in.close();
    
    // 遍历图书列表,查找需要修改的图书
    for (int i = 0; i < bookList.size(); i++) {
        Book& book2 = bookList[i];  // 使用引用来直接修改 bookList 中的数据
        
        // 判断图书编号是否匹配
        if (book2.no == no) {
            // 输出当前图书信息
            cout << "编号\t书名\t作者\t出版社\t价格\t分类" << endl;  
            cout <<  book2.no << "\t";  
            cout <<  book2.bookName << "\t";  
            cout <<  book2.author << "\t";  
            cout <<  book2.publisher << "\t";  
            cout <<  book2.price << "\t";  
            cout <<  book2.category << endl;

            // 修改数据
            result = true;
            book2.no = inputNo();
            book2.bookName = inputbookName();
            book2.author = inputAuthor();
            book2.publisher = inputPublisher();
            book2.price = inputPrice();
            book2.category = inputCategory();
            break;  // 找到并修改后退出循环
        }
    }

    // 如果没有找到该编号,输出提示信息
    if (!result) {
        cout << "该编号不存在" << endl;
    } else {
        // 将修改后的数据写回到文件
        ofstream o("book.txt");  // 打开文件进行写入
        if (o.is_open()) {
            // 遍历修改后的 bookList 并写回文件
            for (int i = 0; i < bookList.size(); i++) {
                Book& book2 = bookList[i];
                o << book2.no << " " << book2.bookName << " " << book2.author << " "
                  << book2.publisher << " " << book2.price << " " << book2.category << endl;
            }
            o.close();  // 完成写入后关闭文件流
            cout << "修改成功" << endl;
        } else {
            cout << "文件写入失败!" << endl;
        }
    }
}





//根据用户输入的功能码选择功能函数 
void choose(int input){
	system("cls");
	switch(input){
		case 1: 
		cout << "你选择了添加功能" << endl ; 
			add();
			break;
		case 2: 
		cout << "你选择了删除功能" << endl ; 
			del(); 
			break;
		case 3: 
		cout << "你选择了修改功能" << endl ; 
			modifyBook();
			break;
		case 4: 
		cout << "你选择了列表功能" << endl ; 
			list(); 
			break;
		case 5: 
		cout << "你选择了查询功能" << endl ; 
			searchBook();
			break;
		case 0:     //退出系统也会实现先暂停退出   希望将这个选项排除 
			//1.加判断if  
			//2.修改 break 为 return 
			cout << "退出系统" << endl ;
			return ;
		default:
			cout << "功能码错误" << endl; 
	}//不管执行什么方法都会去执行暂停以及清空 
	
	system("pause"); 
	system("cls");
}



int main(int argc, char** argv) {
	int input = 1;
	 while(input !=0){
	 	
		cout << "1.添加图书"<< endl; 
		cout << "2.删除图书"<< endl; 
		cout << "3.修改图书"<< endl; 
		cout << "4.图书列表"<< endl; 
		cout << "5.图书查询"<< endl;
		cout << "0.退出系统"<< endl;
		cout << "输入选择功能(0-5)"<< endl;
		//用户把输入的值赋值给input  input作为循环条件 
		// 
		cin >> input; 	
		choose (input);
	 	 
	 	
	 }
	
	return 0;
}

五、总结

本项目实现了一个简单的图书管理系统,展示了如何通过文件流操作实现增、删、改、查等常见的数据库操作。通过本项目,初学者可以深入理解C++的文件流操作、结构体的使用以及基本的算法实现。虽然当前系统较为简单,但可以作为更复杂应用的基础,进一步扩展功能和性能,后续实现数据库的实现。

本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如若转载,请注明出处:/a/939813.html

如若内容造成侵权/违法违规/事实不符,请联系我们进行投诉反馈qq邮箱809451989@qq.com,一经查实,立即删除!

相关文章

方正畅享全媒体新闻采编系统 screen.do SQL注入漏洞复现(附脚本)

0x01 产品描述: 方正畅享全媒体新闻生产系统是以内容资产为核心的智能化融合媒体业务平台,融合了报、网、端、微、自媒体分发平台等全渠道内容。该平台由协调指挥调度、数据资源聚合、融合生产、全渠道发布、智能传播分析、融合考核等多个平台组成,贯穿新闻生产策、采、编、…

启动报错java.lang.NoClassDefFoundError: ch/qos/logback/core/status/WarnStatus

报错信息图片 日志&#xff1a; Exception in thread "Quartz Scheduler [scheduler]" java.lang.NoClassDefFoundError: ch/qos/logback/core/status/WarnStatus先说我自己遇到的问题&#xff0c;我们项目在web设置了自定义的log输出路径&#xff0c;多了一个 / 去…

以ATTCK为例构建网络安全知识图

ATT&CK&#xff08;Adversarial Tactics, Techniques, and Common Knowledge &#xff09;是一个攻击行为知识库和模型&#xff0c;主要应用于评估攻防能力覆盖、APT情报分析、威胁狩猎及攻击模拟等领域。本文简单介绍ATT&CK相关的背景概念&#xff0c;并探讨通过ATT&a…

Linux之多线程互斥

目录 线程互斥的概念 原子性 线程互斥的引入 互斥锁 互斥锁的创建 互斥锁的静态初始化 互斥锁的动态初始化 互斥锁的销毁 互斥锁加锁 互斥锁解锁 互斥锁加锁和解锁的原理 上一期我们学习了线程控制&#xff0c;线程控制就是根据pthread线程库提供的线程接口对线程…

Android4.4 在系统中添加自己的System Service

添加系统service时&#xff0c;源码限制只能添加以android开头的包名&#xff0c;如果不是android开头的&#xff0c;编译时会提示找不到对应的文件。 比如说在系统中添加一个包名为&#xff1a;tel.gateway.connservice的系统服务。 1.在framework/base目录下面创建如下路径&a…

芝法酱学习笔记(2.2)——sql性能优化2

一、前言 在上一节中&#xff0c;我们使用实验的方式&#xff0c;验证了销售单报表的一些sql性能优化的猜想。但实验结果出乎我们的意料&#xff0c;首先是时间查询使用char和datetime相比&#xff0c;char可能更快&#xff0c;使用bigint&#xff08;转为秒&#xff09;和cha…

安装Linux操作系统

确保虚拟机安装成功&#xff0c;接下来开始安装操作系统&#xff0c;通过虚拟光驱安装。 1. 点击图中的 CD/DVD &#xff0c;设置光盘文件&#xff0c;光盘文件下载地址&#xff1a; https://mirrors.tuna.tsinghua.edu.c n/centos-vault/8.5.2111/isos/x86_64/ 说明&#xf…

【网络安全产品大调研系列】1. 漏洞扫描

1. 为什么会出现漏扫技术&#xff1f; 每次黑客攻击事件进行追溯的时候&#xff0c;根据日志分析后&#xff0c;我们往往发现基本都是系统、Web、 弱口令、配置这四个方面中的其中一个出现的安全问题导致黑客可以轻松入侵的。 操作系统的版本滞后&#xff0c;没有更新补丁&am…

Java CountDownLatch 用法和源码解析

&#x1f9d1; 博主简介&#xff1a;CSDN博客专家&#xff0c;历代文学网&#xff08;PC端可以访问&#xff1a;https://literature.sinhy.com/#/literature?__c1000&#xff0c;移动端可微信小程序搜索“历代文学”&#xff09;总架构师&#xff0c;15年工作经验&#xff0c;…

AFL-Fuzz 的使用

AFL-Fuzz 的使用 一、工具二、有源码测试三、无源码测试 一、工具 建议安装LLVM并使用afl-clang-fast或afl-clang-lto进行编译&#xff0c;这些工具提供了更现代和高效的插桩技术。您可以按照以下步骤安装LLVM和afl-clang-fast&#xff1a; sudo apt update sudo apt install…

Java项目--仿RabbitMQ的消息队列--网络通信协议设计

目录 一、引言 二、设计 三、代码 1.Request 2.Response 3.BasicArguments 4.BasicReturns 四、方法类 1.创建交换机 2.删除交换机 3.创建队列 4.删除队列 5.创建绑定 6.删除绑定 7.消息发布 8.消费消息 9.集中返回 五、实现Broker Server类 六、实现连…

MySQL通过binlog日志进行数据恢复

记录一次阿里云MySQL通过binlog日志进行数据回滚 问题描述由于阿里云远程mysql没有做安全策略 所以服务器被别人远程攻击把数据库给删除&#xff0c;通过查看binlog日志可以看到进行了drop操作&#xff0c;下面将演示通过binlog日志进行数据回滚操作。 1、查询是否开始binlog …

王佩丰24节Excel学习笔记——第十二讲:match + index

【以 Excel2010 系列学习&#xff0c;用 Office LTSC 专业增强版 2021 实践】 【本章小技巧】 vlookup与match&#xff0c;index 相结合使用match,index 结合&#xff0c;快速取得引用的值扩展功能&#xff0c;使用match/index函数&#xff0c;结合照相机工具获取照片 一、回顾…

《Time Ghost》的制作:使用 DOTS ECS 制作更为复杂的大型环境

*基于 Unity 6 引擎制作的 demo 《Time Ghost》 开始《Time Ghost》项目时的目标之一是提升在 Unity 中构建大型户外环境的构建标准。为了实现这一目标&#xff0c;我们要有处理更为复杂的场景的能力、有足够的工具支持&#xff0c;同时它对引擎的核心图形、光照、后处理、渲染…

【考前预习】4.计算机网络—网络层

往期推荐 【考前预习】3.计算机网络—数据链路层-CSDN博客 【考前预习】2.计算机网络—物理层-CSDN博客 【考前预习】1.计算机网络概述-CSDN博客 目录 1.网络层概述 2.网络层提供的两种服务 3.分类编址的IPV4 4.无分类编址的IPV4—CIDR 5.IPV4地址应用规划 5.1使用定长子…

解决pip下载慢

使用pip下载大量安装包&#xff0c;下载速度太慢了 1、问题现象 pip安装包速度太慢 2、解决方案 配置国内源 vi /root/.config/pip/pip.conf[global] timeout 6000 index-url https://mirrors.aliyun.com/pypi/simple/ trusted-host mirrors.aliyun.com

【Linux】Linux权限管理:文件与目录的全面指南

在Linux系统中&#xff0c;权限管理是确保数据安全的关键。本文将为大家介绍Linux文件与目录的权限管理&#xff0c;帮助你理解如何设置和管理访问权限。无论你是新手还是有经验的用户&#xff0c;这里都将提供实用的技巧和知识&#xff0c;助你更好地掌握Linux环境。让我们一起…

【模型压缩】原理及实例

在移动智能终端品类越发多样的时代&#xff0c;为了让模型可以顺利部署在算力和存储空间都受限的移动终端&#xff0c;对模型进行压缩尤为重要。模型压缩&#xff08;model compression&#xff09;可以降低神经网络参数量&#xff0c;减少延迟时间&#xff0c;从而实现提高神经…

Android Stduio 2024版本设置前进和后退按钮显示在主界面

Android Studio 2024&#xff08;Ladybug&#xff09;安装后发现前进和后退按钮不显示在主界面的工具栏&#xff0c;且以前在View中设置的办法无效&#xff1a; Android Studio 2024&#xff08;Ladybug&#xff09;的设置方式&#xff1a; File->Settings->Appearance&…

MySQL数据库——门诊管理系统数据库数据表

门诊系统数据库his 使用图形化工具或SQL语句在简明门诊管理系统数据库his中创建数据表&#xff0c;数据表结构见表2-3-9&#xff5e;表2-3-15所示。 表2-3-9 department&#xff08;科室信息表&#xff09; 字段名称 数据类型 长度 是否为空 说明 dep_ID int 否 科室…