今天刚考完csp才考两百,对c++的很多操作还是不够熟练,c++基本内容前面已经学完了,之后的内容都是进阶,如果想要快速编程(stl),面向实际编程(项目,模版,文件),之后的内容还是值得一看的,由于csp的滑铁卢,之后决定好好刷题,搞个栏记录每一道题的历程。
前言
之前在黑马程序员的零基础课程里系统学习了c++,但是黑马程序员的课程还是太慢了,近四百节课让人很难受 ,基本上前一百节后就已经对C语言了解的差不多了(和c++差不多),两百节之后对c++也基本熟悉了。
总归还是太慢了,其中课程的很多内容都是重复出现的,为了方便我将课程中可以省略的重复步骤省略,将其余内容直接以代码加注释的方式展示出来,在其中还加入了《c++程序设计》机械工业出版社的黑皮书的内容进去作为补充。
c++是非常基础的语言,学习也比较容易,如果减去自己的代码编写时间单纯的看懂就可以的话其实不用一个星期就能基本了解。
但是还是需要多练习,很多程序bug等(有版本不适问题,操作系统不适问题)都在是实操中发现并处理。
简单的学习之后就可以应对csp考试,数据结构等课程了就。
我就是本来用java,考csp前学习回顾一下c++想用c++考。java岗的就业情况也比较饱和,会c++一定是很合算的事。
附上第五部分链接
c++速成(vs)短期学会在vs上使用c++编程(4)-CSDN博客c++速成(vs)短期学会在vs上使用c++编程(5)-CSDN博客c++速成(vs)短期学会在vs上使用c++编程(4)-CSDN博客
本期主要内容
c++的文件读写操作
一个相对大的面向对象多态的案例
多文件项目
这一节主要就介绍了c++类的文件读写相关的一些内容,帮助更好的面向实际开发,个人项目的一些开发,相对于速成来说其实没有明确的必要,其中的案例采用多文件编写的方式,有助于提高读写代码的能力
下面代码可以直接运行,在vs或者dev环境运行,类对象声明都在前面,main中只有测试函数和注释。
代码
xuexic++6.cpp
// xuexiC++6.cpp : 此文件包含 "main" 函数。程序执行将在此处开始并结束。
//
#include <iostream>
#include<string>
#include <fstream>
#include "workManager.h"
#include"worker.h"
#include "employee.h"
#include"boss.h"
#include"manager.h"
using namespace std;
void test1() {
ofstream othisfile;//写文件
othisfile.open("test.txt", ios::out);//打开和打开方式
othisfile << "姓名:xiaoma" << endl;//写入
othisfile << "姓名:sunny" << endl;
othisfile << "姓名:together" << endl;
othisfile.close();//关闭
}
void test02() {
ifstream ithisfile;
ithisfile.open("test.txt", ios::in);
if (!ithisfile.is_open()) {
cout << "打开失败了" << endl;
return;
}
//读数据
//1.循环
char buf[1024] = { 0 };
while (ithisfile >> buf) {
cout << buf << endl;
}
ithisfile.close();
//2.
ifstream ithisfile2;
ithisfile2.open("test.txt", ios::in);
char buf1[1024] = { 0 };
while (ithisfile2.getline(buf1,sizeof(buf1))) {
cout << buf1 << endl;
}
ithisfile2.close();
//3.
ifstream ithisfile3;
ithisfile3.open("test.txt", ios::in);
string buf2;
while (getline(ithisfile3,buf2)) {
cout << buf2 << endl;
}
ithisfile3.close();
//4.不推荐用的 效率太低了
ifstream ithisfile4;
ithisfile4.open("test.txt", ios::in);
char buf3;
while ((buf3=ithisfile4.get())!=EOF) {//end of file 文件尾标志
cout << buf3 ;
}
ithisfile4.close();
}
class Person {
public:
char m_name[64];//不用c++string,避免出问题
int m_age;
};
void test2jin() {
ofstream othisfile2jin;//写文件
othisfile2jin.open("person.txt", ios::out|ios::binary);//打开和打开方式
Person p = { "sunny",18 };
othisfile2jin.write((const char*)&p, sizeof(Person));//写入
othisfile2jin.close();//关闭
//2进制搞的 会乱码,没有关系,可以读回来就可以
}
void test2jinr() {
ifstream ithisfiler;
ithisfiler.open("test.txt", ios::in|ios::binary);
if (!ithisfiler.is_open()) {
cout << "打开失败了" << endl;
return;
}
Person p1;
ithisfiler.read((char*)&p1, sizeof(Person));
//读数据
cout << "姓名:" << p1.m_name << "年龄" << p1.m_age << endl;
ithisfiler.close();
}//读出来是乱码 ,不过应该问题不大哈哈哈哈
//基于多态的职工管理系统
//创建一个类完成整体架构
// 与用户沟通的菜单页面
// 对职工的各种操作
// 与文件的读写交互
/*
* 创建管理类
*/
int main()
{
std::cout << "Hello World!\n";
//文件操作
//对文件操作也是基于类 文件流 要求包含头文件 fstream和那个io流一样
/*两种
文本文件 ascll
二进制文件 用户一般读不懂
ofstream写操作 out
ifstream读文件 in
fstream读写文件 file
*/
/* 1.包含头文件
2.创建流对线
3.打开文件 路径
4.打开方式 读写 iso::in 读 iso::out 写文件 iso::binary二进制的方式 还是有追加方式,存在文件先删除,或者初始位置文件尾等,可以找找看,用的比较少
5.写数据 <<写入数据,往文件输出 之前是往屏幕输出
6.关闭 close()*/
test1();
//写在了文件同目录下面的文件夹里面,没有指定位置的情况
//读文件和写文件差不多一样 ifstream open打开 isopen是否打开成功
//读取方式有四种
test02();
//二进制方式进行操作
//会乱码 但是是正常的
test2jin();
//再读回来
//test2jinr(); //因为执行该程序后后面的程序有影响,由于不是重要的部分,目前先埋个雷
//职工管理系统
//测试项目
//普通员工,经理,老板三层
/*
* 退出
* 显示职工信息
* 删除职工
* 增加职工
* 修改职工信息
* 查找职工信息
* 按编号或者人名 排序(排序方式可选 )
* 清空所有文档(确认的提示)
*/
//测试一下
/*worker* worker1 = NULL;
worker1 = new Employee(1, 2, "xiaoxiaoma", 1);
worker1->showData();
worker* worker2 = NULL;
worker2 = new manager(2, 21, "xiaoma", 2);
worker2->showData();
worker* worker3 = NULL;
worker3 = new boss(3, 31, "sunny", 3);
worker3->showData();
*/
workManager test;
int choice = 0;
while (true) {
test.Show_menu();
cout << "请输入你的选择:" << endl;
cin >> choice;
switch (choice) {
case 0://退出
test.exitSystem();
break;
case 1://增加
//批量添加不同种类的职工 通过一个数组来记录
//用父类指针指向子类对象
test.Add_Emp();
break;
case 2://显示
test.showemp();
break;
case 3://删除
test.deleteEmp();
break;
case 4://修改
test.modify_emp();
break;
case 5://查找
test.findemp();
break;
case 6://排序
test.sortemp();
break;
case 7://清空
test.deleteemp();
break;
default:
system("cls");//清屏
break;
}
}
system("pause");
return 0;
}
案例部分
workManager.h
#pragma once//防止头文件重复包含
#include<iostream>//输入输出流
#include "worker.h"
#include"manager.h"
#include"boss.h"
#include"employee.h"
#include<fstream>
#define FILENAME "emp.txt"
using namespace std;//标准命名空间
class workManager {
public:
workManager();
~workManager();
void Show_menu();//展示菜单
void exitSystem();//退出功能
//记录职工人数
int m_EmpNum;
worker** m_EmpArray;//指向数组的指针的指针
//添加职工
void Add_Emp();
//保存文件
void save_Txt();
//第一次使用文件没创建(搞成空就行)
//文件存在,但是没有用户数据,和第一个一样
//文件存在,保存职工的数据 判断是否为空
//文件不存在的请款下初始化数据
//判断文件是不是空的
bool m_isFileEmpty;
//统计文件中的人数
int m_getFileNumber();
//初始化员工
//专门的初始化
void init_emp();
//显示职工
void showemp();
//判断职工是否存在
int isEmpExit(int id);
//删除职工
void deleteEmp();
//修改职工
void modify_emp();
//查找员工
void findemp();
//排序文件
void sortemp();
//清空文件
void deleteemp();
};
workManager.cpp
#include "workManager.h"
#include <iostream>
#include<string>
#include <fstream>
#define FILENAME "emp.txt"
using namespace std;
workManager::workManager() {
//果然文件中有数据不能这么初始化
/* this->m_EmpNum = 0;
this->m_EmpArray = NULL;*/
//根据文件的请款分三种情况
ifstream ifs;
ifs.open(FILENAME, ios::in);
if (!ifs.is_open()) {//判断文件不存在
cout << "文件不存在" << endl;
this->m_EmpNum = 0;
this->m_EmpArray = NULL;
this->m_isFileEmpty = true;
ifs.close();
return;
}
//判断是否为空文件(第一个字符就是结尾字符)
char ch;
ifs >> ch;
if (ifs.eof()) {//eof文件尾部标志
//文件为空
cout << "文件为空" << endl;
this->m_EmpNum = 0;
this->m_EmpArray = NULL;
this->m_isFileEmpty = true;
ifs.close();
return;
}
//其余情况,文件存在,且不为空
int num = this->m_getFileNumber();
cout << "职工人数是" << num << endl;
this->m_EmpNum = num;//初始化
//开辟空间
this->m_EmpArray = new worker * [this->m_EmpNum];
//将文件中的数据,存到数组中
this->init_emp();
//测试
for (int i = 0; i < this->m_EmpNum; i++) {
cout << "职工编号:" << this->m_EmpArray[i]->m_Id
<< "职工年龄:" << this->m_EmpArray[i]->m_Age
<< "职工姓名:" << this->m_EmpArray[i]->m_Name
<< "职工职位:" << this->m_EmpArray[i]->m_DeptId
<< endl;
}
}
workManager::~workManager() {
if (this->m_EmpArray != NULL) {
delete[] this->m_EmpArray;
this->m_EmpArray = NULL;
}//在析构函数释放
}
void workManager::Show_menu() {
cout << "********************************" << endl;
cout << "******欢迎使用职工管理系统*******" << endl;
cout << "*********0.退出管理程序*********" << endl;
cout << "*********1.增加职工信息*********" << endl;
cout << "*********2.显示职工信息*********" << endl;
cout << "*********3.删除职工信息*********" << endl;
cout << "*********4.修改职工信息*********" << endl;
cout << "*********5.查找职工信息*********" << endl;
cout << "*********6.按照序号排序*********" << endl;
cout << "*********7.清空所有文档*********" << endl;
cout << "********************************" << endl;
cout << endl;
}
void workManager::exitSystem() {
//退出功能
cout << "欢迎下次使用" << endl;
system("pause");
exit(0);//退出程序,在主函数之外结束程序。
}
//保存,写文件
void workManager::save_Txt() {
ofstream ofs;
ofs.open(FILENAME, ios::out);//用输入方式打开
for (int i = 0; i < this -> m_EmpNum; i++) {
ofs << this->m_EmpArray[i]->m_Id << " "
<< this->m_EmpArray[i]->m_Age << " "
<< this->m_EmpArray[i]->m_Name << " "
<< this->m_EmpArray[i]->m_DeptId
<< endl;
}
ofs.close();
}
//统计文件人数
int workManager::m_getFileNumber() {
ifstream ifs;
ifs.open(FILENAME, ios::in);
int id;
int age;
int dSelect;
string name;
int num = 0;//>>右移运算符
while (ifs >> id && ifs >> age && ifs >> name && ifs >> dSelect) {
num++;
}
return num;
}
//初始化
void workManager::init_emp() {
ifstream ifs;
ifs.open(FILENAME, ios::in);
int id;
int age;
int dSelect;
string name;
int index = 0;
while (ifs >> id && ifs >> age && ifs >> name && ifs >> dSelect) {
worker*newworker = NULL;
if (dSelect == 1) {
newworker = new Employee(id, age, name, dSelect);
}
else if (dSelect == 2) {
newworker = new manager(id, age, name, dSelect);
}
else if (dSelect == 3) {
newworker = new boss(id, age, name, dSelect);
}
this->m_EmpArray[index] = newworker;
index++;
}
ifs.close();
}
//判断职工是否存在
int workManager::isEmpExit(int id) {
int index = -1;
for (int i = 0; i < this->m_EmpNum; i++) {
if (this->m_EmpArray[i]->m_Id == id) {
index = i;
break;
}
}
return index;
}
//添加功能
void workManager::Add_Emp() {
cout << "请输入添加职工的数量" << endl;
int addNum=0;
cin >>addNum;
if (addNum > 0) {
int newSize = this->m_EmpNum + addNum;
//新的人数等于原有的加入新的人数
worker** newSpace = new worker * [newSize];
//把原有数据拷贝到新空间
if (this->m_EmpArray != NULL) {
for (int i = 0; i < this->m_EmpNum; i++) {
newSpace[i] = this->m_EmpArray[i];
}
}
for (int i = 0; i < addNum; i++) {
int id;
int age;
int dSelect;
string name;
cout << "请输入第" << i + 1 << "个新职工的编号" << endl;
cin >> id;
cout << "请输入第" << i + 1 << "个新职工的年龄" << endl;
cin >> age;
cout << "请输入第" << i + 1 << "个新职工的姓名" << endl;
cin >> name;
cout << "请输入第" << i + 1 << "个新职工的岗位" << endl;
cout << "1.普通员工" << endl;
cout << "2.经理" << endl;
cout << "3.老板" << endl;
cin >> dSelect;
worker* workernew1 = NULL;
switch (dSelect)
{
case 1:
workernew1 = new Employee(id, age, name, 1);
break;
case 2:
workernew1 = new manager(id, age, name, 2);
break;
case 3:
workernew1 = new boss(id, age, name, 3);
break;
default:
break;
}
newSpace[this->m_EmpNum + i] = workernew1;
}
delete[] this->m_EmpArray;//回收空间,释放原有空间
this->m_EmpArray = newSpace;//改变指向,但是不改变名称,方便多次调用
this->m_EmpNum = newSize;//更新总人数 但是每次调用都会重新调用构造函数变成0这个怎么说
//保存到文件中,本来是存在堆区
this->save_Txt();
this->m_isFileEmpty = false;//文件不再为空了
cout << "成功添加" << addNum << "名员工" << endl;
}
else {
cout << "输入有误" << endl;
}
system("pause");
system("cls");//清屏
}
//显示职工信息
void workManager::showemp() {
if (this->m_isFileEmpty) {
cout << "莫得信息,文件没有或者没记录" << endl;
}
else {
for (int i = 0; i < m_EmpNum; i++) {
//利用多态调用程序接口
this->m_EmpArray[i]->showData();
cout << endl;
}
}
system("pause");
system("cls");
}
//删除职工
void workManager::deleteEmp() {
if (this->m_isFileEmpty) {
cout << "不用找了,里面啥都没有" << endl;
}
cout << "请输入要删除的职工的编号:" << endl;
int delid = 0;
cin >> delid;
if (isEmpExit(delid) == -1) {
cout << "该编号职工不存在" << endl;
}
else if(isEmpExit(delid) != -1) {
int index = isEmpExit(delid);
for (int i =index; i < this->m_EmpNum-1; i++) {
this->m_EmpArray[i] = this->m_EmpArray[i + 1];
}//后面的数据往后前移一位
this->m_EmpNum--;//人员减少一个
this->save_Txt();//保存到文件里面
cout << "删除成功" << endl;
}
system("pause");
system("cls");
}
//修改职工
void workManager::modify_emp() {
if (this->m_isFileEmpty) {
cout << "不用找了,里面啥都没有" << endl;
}
cout << "请输入要修改的职工的编号:" << endl;
int modid = 0;
cin >> modid;
if (isEmpExit(modid) == -1) {
cout << "该编号职工不存在" << endl;
}
else if (isEmpExit(modid) != -1) {
int index = isEmpExit(modid);
//先把原来的堆区清理一下
delete this->m_EmpArray[index];
int newid;
int age;
int newdselect;
string name;
cout << "请输入修改后的职工编号" << endl;
cin >> newid;
cout << "请输入修改后的职工年龄" << endl;
cin >> age;
cout << "请输入修改后的职工姓名" << endl;
cin >> name;
cout << "请输入修改后的职工岗位" << endl;
cout << "1.普通员工" << endl;
cout << "2.经理" << endl;
cout << "3.老板" << endl;
cin >> newdselect;
worker* newworker = NULL;
switch (newdselect)
{
case 1:
newworker = new Employee(newid, age, name, 1);
break;
case 2:
newworker = new manager(newid, age, name, 2);
break;
case 3:
newworker = new boss(newid, age, name, 3);
break;
default:
break;
}
this->save_Txt();//保存到文件里面
cout << "修改成功" << endl;
}
system("pause");
system("cls");
}
//查找员工
void workManager::findemp() {
if (this->m_isFileEmpty) {
cout << "文件不存在或者为空,才找不到呢" << endl;
}
else {
cout << "请输入查找方式" << endl;
cout << "1.按职工编号查找" << endl;
cout << "2.按职工姓名查找" << endl;
}
int select = 0;
cin >> select;
if (select == 1) {
//按编号查
int findid;
cout << "请输入要查找的职工编号" << endl;
cin >> findid;
int result = isEmpExit(findid);
if (result != -1) {
cout << "查找成功,该职工信息如下:" << endl;
this->m_EmpArray[result]->showData();
}
else {
cout << "查找失败" << endl;
}
system("pause");
system("cls");
}
else if (select == 2) {
//按姓名查
string findname;
cout << "请输入要查找的职工姓名" << endl;
cin >> findname;
bool isfinded = false;
for (int i = 0; i < m_EmpNum; i++) {
if (this->m_EmpArray[i]->m_Name == findname) {
cout << "查找成功,职工信息如下" << endl;
this->m_EmpArray[i]->showData();
isfinded = true;
}
}
if (isfinded == false) {
cout << "查找失败" << endl;
}
system("pause");
system("cls");
}
else {
cout << "输入有误" << endl;
}
}
//排序 选择排序
void workManager::sortemp() {
if (this->m_isFileEmpty) {
cout << "没东西给你排啊哥" << endl;
system("pause");
system("cls");
}
else {
cout << "请选择排序的方式:" << endl;
cout << "1.按职工序号升序排列:" << endl;
cout << "2.按职工序号降序排列:" << endl;
int select = 0;
cin >> select;
for (int i = 0; i < this->m_EmpNum; i++) {
int minormax = i;
for (int j = i + 1; j < this->m_EmpNum; j++) {
if (select == 1) {
//升序
if (this->m_EmpArray[i]->m_Id > this->m_EmpArray[j]->m_Id) {
minormax = j;
}//最大值移到右边去
}
else if (select == 2) {
//降序
if (this->m_EmpArray[i]->m_Id < this->m_EmpArray[j]->m_Id) {
minormax = j;
}//最小的移动到右边去
}
else {
cout << "输入有误" << endl;
}
}
if (i != minormax) {
worker* temp = this->m_EmpArray[i];
this->m_EmpArray[i] = this->m_EmpArray[minormax];//交换工作
//确定真的最小最大值
this->m_EmpArray[minormax] = temp;
}
}
cout << "排序成功,排序后的结果是:" << endl;
this->showemp();
}
system("pause");
system("cls");
}
//清空
//要清空所有的内容,包括堆区内存的释放
void workManager::deleteemp() {
cout << "确定清空么?" << endl;
cout << "1.没错" << endl;
cout << "2.点错了" << endl;
int select = 0;
cin >> select;
if (select == 1) {
ofstream ofs(FILENAME, ios::trunc);//删除文件后重新创建
ofs.close();
if (this->m_EmpArray != NULL) {//删除,每个职工对象堆区的内容
for (int i = 0; i < this->m_EmpNum; i++) {
delete this->m_EmpArray[i];
}
}
//删除堆区的指针
delete[] this->m_EmpArray;
this->m_EmpArray = NULL;
this->m_EmpNum = 0;
this->m_isFileEmpty = true;
cout << "清空成功" << endl;
}
system("pause");
system("cls");
}
worker.h
#pragma once
#include<iostream>//输入输出流
#include<string>
using namespace std;//标准命名空间
class worker {
public:
virtual void showData() = 0;//显示个人信息
virtual string getDeptId() = 0;//获取部门号
int m_Id;
int m_Age;
string m_Name;
int m_DeptId;//部门编号
};
employee.h
#pragma once
#include<iostream>//输入输出流
#include<string>
#include "worker.h"
using namespace std;//标准命名空间
class Employee :public worker {
public:
Employee(int id,int age,string name,int did);
virtual void showData();//显示个人信息
virtual string getDeptId();//获取部门号
};
employee.cpp
#include<iostream>//输入输出流
#include<string>
#include"employee.h"
using namespace std;//标准命名空间
Employee::Employee(int id, int age, string name, int did) {
this->m_Id = id;
this->m_Age = age;
this->m_DeptId = did;
this->m_Name = name;
}
void Employee::showData(){
//显示个人信息
cout << "职工编号:" << this->m_Id
<< "\n职工姓名:" << this->m_Name
<< "\n职工年龄:" << this->m_Age
<< "\n职工岗位:" << this->getDeptId()
<<"\n岗位职责:完成经理交给的任务"
<< endl;
}
string Employee::getDeptId() {
return string("员工");
}//获取部门号
manager.h
#pragma once
#include<iostream>//输入输出流
#include<string>
#include "worker.h"
using namespace std;//标准命名空间
class manager :public worker {
public:
manager(int id, int age, string name, int did);
virtual void showData();//显示个人信息
virtual string getDeptId();//获取部门号
};
manager.cpp
#include<iostream>//输入输出流
#include<string>
#include"manager.h"
using namespace std;//标准命名空间
manager::manager(int id, int age, string name, int did) {
this->m_Id = id;
this->m_Age = age;
this->m_DeptId = did;
this->m_Name = name;
}
void manager::showData() {
//显示个人信息
cout << "职工编号:" << this->m_Id
<< "\n职工姓名:" << this->m_Name
<< "\n职工年龄:" << this->m_Age
<< "\n职工岗位:" << this->getDeptId()
<< "\n岗位职责:给员工派发任务,完成老板的任务"
<< endl;
}
string manager::getDeptId() {
return string("经理");
}//获取部门号
boss.h
#pragma once
#include<iostream>//输入输出流
#include<string>
#include "worker.h"
using namespace std;//标准命名空间
class boss :public worker {
public:
boss(int id, int age, string name, int did);
virtual void showData();//显示个人信息
virtual string getDeptId();//获取部门号
};
boss.cpp
#include<iostream>//输入输出流
#include<string>
#include"boss.h"
using namespace std;//标准命名空间
boss::boss(int id, int age, string name, int did) {
this->m_Id = id;
this->m_Age = age;
this->m_DeptId = did;
this->m_Name = name;
}
void boss::showData() {
//显示个人信息
cout << "职工编号:" << this->m_Id
<< "\n职工姓名:" << this->m_Name
<< "\n职工年龄:" << this->m_Age
<< "\n职工岗位:" << this->getDeptId()
<< "\n岗位职责:给经理派发任务"
<< endl;
}
string boss::getDeptId() {
return string("老板");
}//获取部门号