文件操作
cpp
#include<iostream>
#include<string>
#include<fstream>
using namespace std;
//文本操作
//程序运行时产生的数据都属于临时数据,程序一旦运行结束都会被释放
//通过文件可以数据持久化
//c++中对文件操作包含头文件<fstream>
//文件类型分为两种:
//1.文本文件 -文件以文本的ASCLL码形式存储在计算机中
//2.二进制文件 - 文件以文本的二进制形式存储在计算机中,用户一般不能直接读懂它们
//操作文件的三大类
//1.ofstream:写操作
//2.ifstream:读操作
//3.fstream: 读写操作
//写文件
//1.包含头文件
//#include<fstream>
//2.创建流对象
//ofstream ofs;
//3.打开文件
//ofs.open("文件路径",打开方式);
//文件打开方式:
//ios::in 读文件方式打开
//ios::out 写文件方式打开
//ios::ate 初始位置:文件尾
//ios::app 追加文件方式打开
//ios::trunc 如果文件存在先删除,再创建
//ios::binary 二进制方式
//文件打开方式可以配合使用,利用|操作符
//4.写数据
//ofs<<"写入的数据";
//5.关闭文件
//ofs.close();
void test(){
//1.包含头文件
//2.创建流对象
ofstream ofs;
//3.指定打开方式
ofs.open("text.txt",ios::out);
//4.写内容
ofs<<"姓名:张三"<<endl;
ofs<<"性别:男"<<endl;
ofs<<"年龄:25"<<endl;
//5.关闭文件
ofs.close();
}
//读文件
//1.包含头文件
//#include<fstream>
//2.创建流对象
//ifstream ifs;
//3.打开文件并判断文件是否打开
//ifs.open("文件路径",打开方式);
//4.读数据
//四种方式读取
//5.关闭文件
//ifs.close()
void test1(){
//1、包含头文件
//2、创建流对象
ifstream ifs;
//3、打开文件并判断文件是否打开
ifs.open("text.txt",ios::in);
if(!ifs.is_open()){
cout<<"文件打开失败"<<endl;
return;
}
//4、读数据
//第一种
char buf[1023] = {0};
while(ifs >> buf) {
cout<<buf<<endl;
}
// //第二种
// char buf[1024] = {0};
// while(ifs.getline(buf,sizeof(buf))) {
// cout<<buf<<endl;
// }
// //第三种
// string buf;
// while(getline(ifs,buf)){
// cout<<buf<<endl;
// }
//第四种
// char c;
// while((c = ifs.get()) != EOF){ //EOF end of file
// cout<<c;
// }
//5、关闭文件
ifs.close();
}
//二进制文件
//以二进制的方式对文件进行读写操作
//打开方式要指定为ios::binary
//二进制文件写文件
//二进制方式写文件主要利用流对象调用成员函数write
//函数原型:ostream&write(const char *buffer,int len);
//参数解释:字符指针buffer指向内存中一段存储空间。len是读写的字节数
class Person{
public:
char m_Name[64];
int m_Age;
};
void test2(){
//1.包含头文件
//2.创建流对象
ofstream ofs;
//3.打开文件
ofs.open("person.txt",ios::out|ios::binary);
//创建流对象和打开文件一起
// ofstream ofs("person.txt",ios::out|ios::binary);
//4.写文件
Person p = {"张三",18} ;
ofs.write((const char *)&p, sizeof(p));
//5.关闭文件
ofs.close();
}
//二进制文件读文件
//函数原型:istream&read(char *buffer,int len);
class Person1{
public:
char m_Name[64];
int m_Age;
};
void test3(){
//1.包含头文件
//2.创建流对象
ifstream ifs;
//3.打开文件 判断文件是否打开成功
ifs.open("person.txt",ios::in|ios::binary);
if(! ifs.is_open()){
cout<<"文件打开失败"<<endl;
return;
}
//创建流对象和打开文件一起
// ifstream ofs("person.txt",ios::out|ios::binary);
//4.读文件
Person1 p;
ifs.read((char *)&p, sizeof(Person1));
cout<<"姓名:"<<p.m_Name<<" 年龄:"<<p.m_Age<<endl;
//5.关闭文件
ifs.close();
}
int main(){
//文本文件写
test();
//文本文件读
test1();
//二进制文件写
test2();
//二进制文件读
test3();
}
模板:
cpp
#include<iostream>
#include<string>
using namespace std;
//1.2函数模板语句
//c++另一种编程思想称为泛型编程,主要利用的技术就是模板
//c++提供两种模板机制:函数模板和类模板
//1.2.1函数模板作用:
//建立一个通用函数,其函数返回值类型和形参类型可以不具体制定,用一个虚拟的类型来代表
//语法: template<typename T>
// 函数声明或定义
//template --- 声明创建模板
//typename --- 表明其后面的符号是一种数据类型,可以用class代替
//T --- 通用的数据类型,名称可以替换,通常为大写字母
//函数模板
template<typename T>
void mySwap(T &a,T &b)
{
T temp = a;
a = b;
b = temp;
}
两个整型交换函数
//void swapInt(int &a,int &b)
//{
// int temp = a;
// a = b;
// b = temp;
//}
交换两个浮点型函数
//void swapDouble(double &a,double &b)
//{
// double temp = a;
// a = b;
// b = temp;
// }
void test01()
{
cout<<"************test01**********"<<endl
<<"***********函数模板*********"<<endl;
int a = 10;
int b = 20;
// swapInt(a,b);
// cout<<"a = "<<a<<" b = "<<b<<endl;
//
// double c = 1.1;
// double d = 2.2;
// swapDouble(c,d);
// cout<<"c = "<<c<<" d = "<<d<<endl;
//函数模板两种使用方法
//1、自动类型推导
mySwap(a,b);
cout<<"a = "<<a<<" b = "<<b<<endl;
//2、显示指定类型
mySwap<int>(a,b);
cout<<"a = "<<a<<" b = "<<b<<endl;
}
//1.2.2 函数模板注意事项
//注意事项:
//1、自动类型推导,必须导出一致的数据类型T,才可以使用
//2、模板必须要确定出T的数据类型,才可以使用
//template <class T>
//void func()
// {
// cout<<"func 调用"<<endl;
// }
//调用func()是错误的,必须明确func的数据类型
//1.2.3 函数模板案例
//案例描述:
//利用函数模板封装一个排序的函数。可以对不同类型数组进行排序
//排序规则从大到小,排序算法为选择排序
//分别利用char数组和int数组进行测试
//排序算法
template <typename T>
void mySort(T arr[], int len)
{
for(int i = 0;i < len;i++)
{
int max = i;
for(int j = i+1; j<len; j++)
{
if(arr[max]<arr[j]) // 此处是max 不是 i,需要实时更新max的值
{
max = j;
}
}
if(max!=i)
{
mySwap(arr[i],arr[max]);
}
}
}
// 6,432,432,32,32
// i = 0; max = 0 j = 1 32
// i = 1; max = 1 j = 2 432
// i = 2; max = 2 j = 3 432
// i = 3; max = 3 j = 4 max = 4 2
// i = 4; max = 4 j = 5 max = 4 1
//打印
template <typename T>
void show(T arr[],int len)
{
for(int i = 0; i < len;i++)
{
cout<<arr[i]<<" ";
}
cout<<endl;
}
void test02()
{
cout<<"************test02**********"<<endl
<<"********函数模板测试排序*******"<<endl;
char charArr[] = "fdacbeg";
int intArr[] = {6,432,432,32,32};
int len = sizeof(charArr)/sizeof(charArr[0]);
int size = sizeof(intArr)/sizeof(intArr[0]);
show(charArr,len);
mySort(charArr,len);
show(charArr,len);
show(intArr,size);
mySort(intArr,size);
show(intArr,size);
}
//1.2.4 普通函数与函数模板的区别
//普通函数与函数模板区别
//普通函数调用时可以发生自动类型转换(隐式类型转换)
//函数模板调用时,如果利用自动类型推导,不会发生隐式类型转换
//int myAadd(int a, int b)
//{
// return a + b;
// }
// myAadd(10,"c");//不会报错,隐式类型转换,转为ACI码相加
//template<typename T>
//T myAdd02(T a, T b)
//{
// return a + b;
//}
// myAadd02(10,"c");//会报错,隐式类型不能转换
//1.2.5普通函数与函数模板的调用规则
//调用规则如下:
//1.如果函数模板和普通函数都可以实现,优先调用普通函数
//2.可通过空模板参数列表来强调调用函数模板
//3.函数模板也可以发生重载
//4.如果函数模板可以产生更好的匹配,优先调用函数模板
//void myPrint(int a,int b)
//{
// cout<<"调用的模板"<<endl;
// }
//
//template<class T>
//void myPrint(T a,T b)
//{
// cout<<"调用的模板"<<endl;
//}
//template<class T>
//void myPrint(T a,T b , T c)
//{
// cout<<"调用的重载的模板"<<endl;
//
//void test01()
//{
// int a = 10;
// int b = 20;
//
// myPrint(a,b);//优先调用普通函数
//通过空模板参数列表,强制调用函数模板
// myprint<>(a,b);
// myprint(a,b,c); 函数模板也可以发生重载
//如果函数模板产生更好的匹配,优先调用函数模板
// char c1 = "a";
// char c2 = "b";
// myprint(c1,c2); // 调用的是模板
//}
//1.2.6模板的局限性
//模板的通用并不是万能的
//例如
//如果传入的 a 和 b 是一个数组,就无法实现了
//template<class T>
//void f(T a,T b)
//{
// a = b;
//}
//再例如:
//template<class T>
//void f(T a, T b)
//{
// if(a > b){
//
// }
//}
//在上述代码中,如果T的数据类型传入的是像Person这样的自定义数据类型,也无法正常运行
class person{
public:
person(string name,int age){
this->myname = name;
this->myage = age;
}
string myname;
int myage;
};
template<class T>
bool equals (T &a,T &b)
{
if(a == b)
{
return true ;
}
else
{
return false;
}
}
//利用具体化person的版本实现代码,具体化优先调用
template<>bool equals(person &p1,person &p2){
if(p1.myname == p2.myname && p1.myage == p2.myage){
return true;
}
else{
return false;
}
}
void test03()
{
cout<<"************test03**********"<<endl
<<"********模板的局限性*******"<<endl;
int a = 10;
int b = 10;
int ret = equals (a,b);
if(ret){
cout<<"a等于b"<<endl;
}
else{
cout<<"a不等于b"<<endl;
}
}
void test04()
{
cout<<"************test04**********"<<endl
<<"********模板的局限性*******"<<endl;
person p1("tom",10);
person p2("tom",10);
bool ret = equals(p1,p2);
if(ret){
cout<<"p1 等于 p2"<<endl;
}
else
{
cout<<"p1 不等于 p2"<<endl;
}
}
//1.3类模板
//1.3.1类模板语法
//类模板作用:
//建立一个通用类,类中成员 数据类型可以不具体制定,用一个虚拟的类型来代表
//语法:
template<class NameType,class AgeType>
//类
class Person1{
public:
Person1(NameType name,AgeType age)
{
this->m_Name = name;
this->m_age = age;
}
void showPerson()
{
cout<<"name:"<<this->m_Name<<" age: "<<this->m_age<<endl;
}
NameType m_Name;
AgeType m_age;
};
void test05()
{
cout<<"************test05**********"<<endl
<<"************类模板************"<<endl;
Person1<string, int>p1("孙悟空",999);
p1.showPerson();
}
//1.3.2类模板与函数模板区别
//类模板与函数模板主要有两点
//1.类模板没有自动类型推导的使用方式
//Person1 p1("孙悟空",999);//错误无法自动类型推导
//2.类模板在模板参数列表中可以有默认参数
//template<class NameType,class AgeType = int>
//Person1<string>p1("孙悟空",999); // 不会报错,有默认参数
//1.3.3类模板中成员函数创建时机
//类模板中成员函数和普通类中成员函数创建时机是有区别的:
//类模板中的成员函数在调用时才创建
class Person2
{
public:
void showPerson2()
{
cout<<"person2 show"<<endl;
}
};
class Person3
{
public:
void showPerson3()
{
cout<<"person3 show"<<endl;
}
};
template<class T>
class Myclass
{
public:
T obj;
void fun1()
{
obj.showPerson2();
}
void fun2()
{
obj.showPerson3();
}
};
void test06()
{
cout<<"************test06**********"<<endl
<<"********类模板的创建时机*******"<<endl;
Myclass<Person2> m;
m.fun1();
//m.fun2(); fun2 报错 ,Person2类只能使用fun1函数
}
//1.3.4类模板对象做函数参数
//三种传入方式:
//1.指定传入的类型 --- 直接显示对象的数据类型
template<class T1,class T2>
class Person4
{
public:
Person4(T1 name, T2 age)
{
this->m_name = name;
this->m_age = age;
}
void showPerson()
{
cout<<"姓名:"<<m_name<<" 年龄:"<<m_age<<endl;
}
T1 m_name;
T2 m_age;
};
void printPerson4_0(Person4<string, int>&p) //指定传入的类型
{
p.showPerson();
}
//2.参数模板化 ---将对象中的参数变为模板进行传递
template<class T1,class T2>
void printPerson4_1(Person4<T1, T2>&p)
{
p.showPerson();
// cout<<"T1的类型为:"<<typeid(T1).name()<<endl; // 查看T1的数据类型
}
//3.整个类模板化 ---将这个对象类型模板化进行传递
template<class T>
void printPerson4_2(T &p)
{
p.showPerson();
// cout<<"T1的类型为:"<<typeid(T1).name()<<endl; // 查看T1的数据类型
}
void test07()
{
cout<<"************test07**********"<<endl
<<"********类模板对象做函数参数*******"<<endl;
Person4<string, int>p("天蓬元帅",1999);
printPerson4_0(p);
printPerson4_1(p);
printPerson4_2(p);
}
//1.3.5类模板与继承
//当子类继承的父类是一个类模板时,子类在声明的时候,要指出父类中T的类型
//如果不指定,编译器无法给子类分配内存
//如果想灵活指定出父类中T的类型,子类也需变为类模板
//
//template<class T>
//class Base
//{
// T m;
//};
class Son:public Base //错误,必须要知道父类中的T类型,才能继承给子类
//
//class Son:public Base<int>
//{
//
//};
//
//template<class T1,class T2>
//class Son1:public Base<T2>
//{
// T1 obj;
//};
//Son1<int,char> s; // 调用
//1.3.6 类模板成员函数类外实现
template<class T1,class T2>
class Person5
{
public:
Person5(T1 name, T2 age);
// {
// this->m_name = name;
// this->m_age = age;
// }
void showPerson();
// {
// cout<<"姓名:"<<m_name<<" 年龄:"<<m_age<<endl;
// }
T1 m_name;
T2 m_age;
};
//构造函数内外实现
template<class T1,class T2>
Person5<T1,T2>::Person5(T1 name, T2 age)
{
this->m_name = name;
this->m_age = age;
}
//成员函数类外实现
template<class T1,class T2>
void Person5<T1,T2>::showPerson()
{
cout<<"姓名:"<<m_name<<" 年龄:"<<m_age<<endl;
}
void test08()
{
cout<<"************test08**********"<<endl
<<"********类模板成员函数类外实现*******"<<endl;
Person5<string, int>p("白骨精",999);
p.showPerson();
}
//1.3.7类模板分文件编写
//问题:
//类模板中成员函数创建时机是在调用阶段,导致分文件编写时链接不到
//解决:
//解决1.直接包含.cpp源文件
//解决2.将声明和实现写到同一个文件中,并更改后缀名.hpp..hpp是约定的名称,不是特定
//1.3.8类模板与友元
//全局函数类内实现-直接在类内声明友元即可
//全局函数类外实现-需要提前让编译器知道全局函数的存在
//类外实现
template<class T1,class T2>
class Person6;
template<class T1,class T2>
void printPerson2(Person6<T1,T2>p)
{
cout<<"类外实现--姓名:"<<p.m_name<<" 类外实现--年龄:"<<p.m_age<<endl;
}
template<class T1,class T2>
class Person6
{
//全局函数,类内实现
friend void printPerson(Person6<T1,T2>p)
{
cout<<"类内实现--姓名:"<<p.m_name<<" 类内实现--年龄:"<<p.m_age<<endl;;
}
//全局函数 类外实现
//加空模板参数列表
//如果全局函数是类外实现,需要让编译器提前知道这个函数的存在
friend void printPerson2<>(Person6<T1, T2> p);
public:
Person6(T1 name,T2 age)
{
this->m_name = name;
this->m_age = age;
}
private:
T1 m_name;
T2 m_age;
};
void test09()
{
cout<<"************test09**********"<<endl
<<"********全局函数类内实现*******"<<endl;
Person6<string, int>p("张飞",456);
printPerson(p);
Person6<string, int>p1("曹操",736);
printPerson2<>(p1);
}
int main()
{
test01();
cout<<endl;
test02();
cout<<endl;
test03();
cout<<endl;
test04();
cout<<endl;
test05();
cout<<endl;
test06();
cout<<endl;
test07();
cout<<endl;
test08();
cout<<endl;
test09();
cout<<endl;
system("pause");
return 0;
}