• c++学习 文件操作,模板


    文件操作

    1. #include
    2. #include
    3. #include
    4. using namespace std;
    5. //文本操作
    6. //程序运行时产生的数据都属于临时数据,程序一旦运行结束都会被释放
    7. //通过文件可以数据持久化
    8. //c++中对文件操作包含头文件
    9. //文件类型分为两种:
    10. //1.文本文件 -文件以文本的ASCLL码形式存储在计算机中
    11. //2.二进制文件 - 文件以文本的二进制形式存储在计算机中,用户一般不能直接读懂它们
    12. //操作文件的三大类
    13. //1.ofstream:写操作
    14. //2.ifstream:读操作
    15. //3.fstream: 读写操作
    16. //写文件
    17. //1.包含头文件
    18. //#include
    19. //2.创建流对象
    20. //ofstream ofs;
    21. //3.打开文件
    22. //ofs.open("文件路径",打开方式);
    23. //文件打开方式:
    24. //ios::in 读文件方式打开
    25. //ios::out 写文件方式打开
    26. //ios::ate 初始位置:文件尾
    27. //ios::app 追加文件方式打开
    28. //ios::trunc 如果文件存在先删除,再创建
    29. //ios::binary 二进制方式
    30. //文件打开方式可以配合使用,利用|操作符
    31. //4.写数据
    32. //ofs<<"写入的数据";
    33. //5.关闭文件
    34. //ofs.close();
    35. void test(){
    36. //1.包含头文件
    37. //2.创建流对象
    38. ofstream ofs;
    39. //3.指定打开方式
    40. ofs.open("text.txt",ios::out);
    41. //4.写内容
    42. ofs<<"姓名:张三"<
    43. ofs<<"性别:男"<
    44. ofs<<"年龄:25"<
    45. //5.关闭文件
    46. ofs.close();
    47. }
    48. //读文件
    49. //1.包含头文件
    50. //#include
    51. //2.创建流对象
    52. //ifstream ifs;
    53. //3.打开文件并判断文件是否打开
    54. //ifs.open("文件路径",打开方式);
    55. //4.读数据
    56. //四种方式读取
    57. //5.关闭文件
    58. //ifs.close()
    59. void test1(){
    60. //1、包含头文件
    61. //2、创建流对象
    62. ifstream ifs;
    63. //3、打开文件并判断文件是否打开
    64. ifs.open("text.txt",ios::in);
    65. if(!ifs.is_open()){
    66. cout<<"文件打开失败"<
    67. return;
    68. }
    69. //4、读数据
    70. //第一种
    71. char buf[1023] = {0};
    72. while(ifs >> buf) {
    73. cout<
    74. }
    75. // //第二种
    76. // char buf[1024] = {0};
    77. // while(ifs.getline(buf,sizeof(buf))) {
    78. // cout<
    79. // }
    80. // //第三种
    81. // string buf;
    82. // while(getline(ifs,buf)){
    83. // cout<
    84. // }
    85. //第四种
    86. // char c;
    87. // while((c = ifs.get()) != EOF){ //EOF end of file
    88. // cout<
    89. // }
    90. //5、关闭文件
    91. ifs.close();
    92. }
    93. //二进制文件
    94. //以二进制的方式对文件进行读写操作
    95. //打开方式要指定为ios::binary
    96. //二进制文件写文件
    97. //二进制方式写文件主要利用流对象调用成员函数write
    98. //函数原型:ostream&write(const char *buffer,int len);
    99. //参数解释:字符指针buffer指向内存中一段存储空间。len是读写的字节数
    100. class Person{
    101. public:
    102. char m_Name[64];
    103. int m_Age;
    104. };
    105. void test2(){
    106. //1.包含头文件
    107. //2.创建流对象
    108. ofstream ofs;
    109. //3.打开文件
    110. ofs.open("person.txt",ios::out|ios::binary);
    111. //创建流对象和打开文件一起
    112. // ofstream ofs("person.txt",ios::out|ios::binary);
    113. //4.写文件
    114. Person p = {"张三",18} ;
    115. ofs.write((const char *)&p, sizeof(p));
    116. //5.关闭文件
    117. ofs.close();
    118. }
    119. //二进制文件读文件
    120. //函数原型:istream&read(char *buffer,int len);
    121. class Person1{
    122. public:
    123. char m_Name[64];
    124. int m_Age;
    125. };
    126. void test3(){
    127. //1.包含头文件
    128. //2.创建流对象
    129. ifstream ifs;
    130. //3.打开文件 判断文件是否打开成功
    131. ifs.open("person.txt",ios::in|ios::binary);
    132. if(! ifs.is_open()){
    133. cout<<"文件打开失败"<
    134. return;
    135. }
    136. //创建流对象和打开文件一起
    137. // ifstream ofs("person.txt",ios::out|ios::binary);
    138. //4.读文件
    139. Person1 p;
    140. ifs.read((char *)&p, sizeof(Person1));
    141. cout<<"姓名:"<" 年龄:"<
    142. //5.关闭文件
    143. ifs.close();
    144. }
    145. int main(){
    146. //文本文件写
    147. test();
    148. //文本文件读
    149. test1();
    150. //二进制文件写
    151. test2();
    152. //二进制文件读
    153. test3();
    154. }

    模板:

    1. #include
    2. #include
    3. using namespace std;
    4. //1.2函数模板语句
    5. //c++另一种编程思想称为泛型编程,主要利用的技术就是模板
    6. //c++提供两种模板机制:函数模板和类模板
    7. //1.2.1函数模板作用:
    8. //建立一个通用函数,其函数返回值类型和形参类型可以不具体制定,用一个虚拟的类型来代表
    9. //语法: template
    10. // 函数声明或定义
    11. //template --- 声明创建模板
    12. //typename --- 表明其后面的符号是一种数据类型,可以用class代替
    13. //T --- 通用的数据类型,名称可以替换,通常为大写字母
    14. //函数模板
    15. template<typename T>
    16. void mySwap(T &a,T &b)
    17. {
    18. T temp = a;
    19. a = b;
    20. b = temp;
    21. }
    22. 两个整型交换函数
    23. //void swapInt(int &a,int &b)
    24. //{
    25. // int temp = a;
    26. // a = b;
    27. // b = temp;
    28. //}
    29. 交换两个浮点型函数
    30. //void swapDouble(double &a,double &b)
    31. //{
    32. // double temp = a;
    33. // a = b;
    34. // b = temp;
    35. // }
    36. void test01()
    37. {
    38. cout<<"************test01**********"<
    39. <<"***********函数模板*********"<
    40. int a = 10;
    41. int b = 20;
    42. // swapInt(a,b);
    43. // cout<<"a = "<
      //
    44. // double c = 1.1;
    45. // double d = 2.2;
    46. // swapDouble(c,d);
    47. // cout<<"c = "<
      //函数模板两种使用方法
    48. //1、自动类型推导
    49. mySwap(a,b);
    50. cout<<"a = "<" b = "<
    51. //2、显示指定类型
    52. mySwap<int>(a,b);
    53. cout<<"a = "<" b = "<
    54. }
    55. //1.2.2 函数模板注意事项
    56. //注意事项:
    57. //1、自动类型推导,必须导出一致的数据类型T,才可以使用
    58. //2、模板必须要确定出T的数据类型,才可以使用
    59. //template
    60. //void func()
    61. // {
    62. // cout<<"func 调用"<
    63. // }
    64. //调用func()是错误的,必须明确func的数据类型
    65. //1.2.3 函数模板案例
    66. //案例描述:
    67. //利用函数模板封装一个排序的函数。可以对不同类型数组进行排序
    68. //排序规则从大到小,排序算法为选择排序
    69. //分别利用char数组和int数组进行测试
    70. //排序算法
    71. template <typename T>
    72. void mySort(T arr[], int len)
    73. {
    74. for(int i = 0;i < len;i++)
    75. {
    76. int max = i;
    77. for(int j = i+1; j
    78. {
    79. if(arr[max]// 此处是max 不是 i,需要实时更新max的值
    80. {
    81. max = j;
    82. }
    83. }
    84. if(max!=i)
    85. {
    86. mySwap(arr[i],arr[max]);
    87. }
    88. }
    89. }
    90. // 6,432,432,32,32
    91. // i = 0; max = 0 j = 1 32
    92. // i = 1; max = 1 j = 2 432
    93. // i = 2; max = 2 j = 3 432
    94. // i = 3; max = 3 j = 4 max = 4 2
    95. // i = 4; max = 4 j = 5 max = 4 1
    96. //打印
    97. template <typename T>
    98. void show(T arr[],int len)
    99. {
    100. for(int i = 0; i < len;i++)
    101. {
    102. cout<" ";
    103. }
    104. cout<
    105. }
    106. void test02()
    107. {
    108. cout<<"************test02**********"<
    109. <<"********函数模板测试排序*******"<
    110. char charArr[] = "fdacbeg";
    111. int intArr[] = {6,432,432,32,32};
    112. int len = sizeof(charArr)/sizeof(charArr[0]);
    113. int size = sizeof(intArr)/sizeof(intArr[0]);
    114. show(charArr,len);
    115. mySort(charArr,len);
    116. show(charArr,len);
    117. show(intArr,size);
    118. mySort(intArr,size);
    119. show(intArr,size);
    120. }
    121. //1.2.4 普通函数与函数模板的区别
    122. //普通函数与函数模板区别
    123. //普通函数调用时可以发生自动类型转换(隐式类型转换)
    124. //函数模板调用时,如果利用自动类型推导,不会发生隐式类型转换
    125. //int myAadd(int a, int b)
    126. //{
    127. // return a + b;
    128. // }
    129. // myAadd(10,"c");//不会报错,隐式类型转换,转为ACI码相加
    130. //template
    131. //T myAdd02(T a, T b)
    132. //{
    133. // return a + b;
    134. //}
    135. // myAadd02(10,"c");//会报错,隐式类型不能转换
    136. //1.2.5普通函数与函数模板的调用规则
    137. //调用规则如下:
    138. //1.如果函数模板和普通函数都可以实现,优先调用普通函数
    139. //2.可通过空模板参数列表来强调调用函数模板
    140. //3.函数模板也可以发生重载
    141. //4.如果函数模板可以产生更好的匹配,优先调用函数模板
    142. //void myPrint(int a,int b)
    143. //{
    144. // cout<<"调用的模板"<
    145. // }
    146. //
    147. //template
    148. //void myPrint(T a,T b)
    149. //{
    150. // cout<<"调用的模板"<
    151. //}
    152. //template
    153. //void myPrint(T a,T b , T c)
    154. //{
    155. // cout<<"调用的重载的模板"<
    156. //
    157. //void test01()
    158. //{
    159. // int a = 10;
    160. // int b = 20;
    161. //
    162. // myPrint(a,b);//优先调用普通函数
    163. //通过空模板参数列表,强制调用函数模板
    164. // myprint<>(a,b);
    165. // myprint(a,b,c); 函数模板也可以发生重载
    166. //如果函数模板产生更好的匹配,优先调用函数模板
    167. // char c1 = "a";
    168. // char c2 = "b";
    169. // myprint(c1,c2); // 调用的是模板
    170. //}
    171. //1.2.6模板的局限性
    172. //模板的通用并不是万能的
    173. //例如
    174. //如果传入的 a 和 b 是一个数组,就无法实现了
    175. //template
    176. //void f(T a,T b)
    177. //{
    178. // a = b;
    179. //}
    180. //再例如:
    181. //template
    182. //void f(T a, T b)
    183. //{
    184. // if(a > b){
    185. //
    186. // }
    187. //}
    188. //在上述代码中,如果T的数据类型传入的是像Person这样的自定义数据类型,也无法正常运行
    189. class person{
    190. public:
    191. person(string name,int age){
    192. this->myname = name;
    193. this->myage = age;
    194. }
    195. string myname;
    196. int myage;
    197. };
    198. template<class T>
    199. bool equals (T &a,T &b)
    200. {
    201. if(a == b)
    202. {
    203. return true ;
    204. }
    205. else
    206. {
    207. return false;
    208. }
    209. }
    210. //利用具体化person的版本实现代码,具体化优先调用
    211. template<>bool equals(person &p1,person &p2){
    212. if(p1.myname == p2.myname && p1.myage == p2.myage){
    213. return true;
    214. }
    215. else{
    216. return false;
    217. }
    218. }
    219. void test03()
    220. {
    221. cout<<"************test03**********"<
    222. <<"********模板的局限性*******"<
    223. int a = 10;
    224. int b = 10;
    225. int ret = equals (a,b);
    226. if(ret){
    227. cout<<"a等于b"<
    228. }
    229. else{
    230. cout<<"a不等于b"<
    231. }
    232. }
    233. void test04()
    234. {
    235. cout<<"************test04**********"<
    236. <<"********模板的局限性*******"<
    237. person p1("tom",10);
    238. person p2("tom",10);
    239. bool ret = equals(p1,p2);
    240. if(ret){
    241. cout<<"p1 等于 p2"<
    242. }
    243. else
    244. {
    245. cout<<"p1 不等于 p2"<
    246. }
    247. }
    248. //1.3类模板
    249. //1.3.1类模板语法
    250. //类模板作用:
    251. //建立一个通用类,类中成员 数据类型可以不具体制定,用一个虚拟的类型来代表
    252. //语法:
    253. template<class NameType,class AgeType>
    254. //类
    255. class Person1{
    256. public:
    257. Person1(NameType name,AgeType age)
    258. {
    259. this->m_Name = name;
    260. this->m_age = age;
    261. }
    262. void showPerson()
    263. {
    264. cout<<"name:"<<this->m_Name<<" age: "<<this->m_age<
    265. }
    266. NameType m_Name;
    267. AgeType m_age;
    268. };
    269. void test05()
    270. {
    271. cout<<"************test05**********"<
    272. <<"************类模板************"<
    273. Person1int>p1("孙悟空",999);
    274. p1.showPerson();
    275. }
    276. //1.3.2类模板与函数模板区别
    277. //类模板与函数模板主要有两点
    278. //1.类模板没有自动类型推导的使用方式
    279. //Person1 p1("孙悟空",999);//错误无法自动类型推导
    280. //2.类模板在模板参数列表中可以有默认参数
    281. //template
    282. //Person1p1("孙悟空",999); // 不会报错,有默认参数
    283. //1.3.3类模板中成员函数创建时机
    284. //类模板中成员函数和普通类中成员函数创建时机是有区别的:
    285. //类模板中的成员函数在调用时才创建
    286. class Person2
    287. {
    288. public:
    289. void showPerson2()
    290. {
    291. cout<<"person2 show"<
    292. }
    293. };
    294. class Person3
    295. {
    296. public:
    297. void showPerson3()
    298. {
    299. cout<<"person3 show"<
    300. }
    301. };
    302. template<class T>
    303. class Myclass
    304. {
    305. public:
    306. T obj;
    307. void fun1()
    308. {
    309. obj.showPerson2();
    310. }
    311. void fun2()
    312. {
    313. obj.showPerson3();
    314. }
    315. };
    316. void test06()
    317. {
    318. cout<<"************test06**********"<
    319. <<"********类模板的创建时机*******"<
    320. Myclass m;
    321. m.fun1();
    322. //m.fun2(); fun2 报错 ,Person2类只能使用fun1函数
    323. }
    324. //1.3.4类模板对象做函数参数
    325. //三种传入方式:
    326. //1.指定传入的类型 --- 直接显示对象的数据类型
    327. template<class T1,class T2>
    328. class Person4
    329. {
    330. public:
    331. Person4(T1 name, T2 age)
    332. {
    333. this->m_name = name;
    334. this->m_age = age;
    335. }
    336. void showPerson()
    337. {
    338. cout<<"姓名:"<" 年龄:"<
    339. }
    340. T1 m_name;
    341. T2 m_age;
    342. };
    343. void printPerson4_0(Person4int>&p) //指定传入的类型
    344. {
    345. p.showPerson();
    346. }
    347. //2.参数模板化 ---将对象中的参数变为模板进行传递
    348. template<class T1,class T2>
    349. void printPerson4_1(Person4&p)
    350. {
    351. p.showPerson();
    352. // cout<<"T1的类型为:"<
    353. }
    354. //3.整个类模板化 ---将这个对象类型模板化进行传递
    355. template<class T>
    356. void printPerson4_2(T &p)
    357. {
    358. p.showPerson();
    359. // cout<<"T1的类型为:"<
    360. }
    361. void test07()
    362. {
    363. cout<<"************test07**********"<
    364. <<"********类模板对象做函数参数*******"<
    365. Person4int>p("天蓬元帅",1999);
    366. printPerson4_0(p);
    367. printPerson4_1(p);
    368. printPerson4_2(p);
    369. }
    370. //1.3.5类模板与继承
    371. //当子类继承的父类是一个类模板时,子类在声明的时候,要指出父类中T的类型
    372. //如果不指定,编译器无法给子类分配内存
    373. //如果想灵活指定出父类中T的类型,子类也需变为类模板
    374. //
    375. //template
    376. //class Base
    377. //{
    378. // T m;
    379. //};
    380. class Son:public Base //错误,必须要知道父类中的T类型,才能继承给子类
    381. //
    382. //class Son:public Base
    383. //{
    384. //
    385. //};
    386. //
    387. //template
    388. //class Son1:public Base
    389. //{
    390. // T1 obj;
    391. //};
    392. //Son1 s; // 调用
    393. //1.3.6 类模板成员函数类外实现
    394. template<class T1,class T2>
    395. class Person5
    396. {
    397. public:
    398. Person5(T1 name, T2 age);
    399. // {
    400. // this->m_name = name;
    401. // this->m_age = age;
    402. // }
    403. void showPerson();
    404. // {
    405. // cout<<"姓名:"<
    406. // }
    407. T1 m_name;
    408. T2 m_age;
    409. };
    410. //构造函数内外实现
    411. template<class T1,class T2>
    412. Person5::Person5(T1 name, T2 age)
    413. {
    414. this->m_name = name;
    415. this->m_age = age;
    416. }
    417. //成员函数类外实现
    418. template<class T1,class T2>
    419. void Person5::showPerson()
    420. {
    421. cout<<"姓名:"<" 年龄:"<
    422. }
    423. void test08()
    424. {
    425. cout<<"************test08**********"<
    426. <<"********类模板成员函数类外实现*******"<
    427. Person5int>p("白骨精",999);
    428. p.showPerson();
    429. }
    430. //1.3.7类模板分文件编写
    431. //问题:
    432. //类模板中成员函数创建时机是在调用阶段,导致分文件编写时链接不到
    433. //解决:
    434. //解决1.直接包含.cpp源文件
    435. //解决2.将声明和实现写到同一个文件中,并更改后缀名.hpp..hpp是约定的名称,不是特定
    436. //1.3.8类模板与友元
    437. //全局函数类内实现-直接在类内声明友元即可
    438. //全局函数类外实现-需要提前让编译器知道全局函数的存在
    439. //类外实现
    440. template<class T1,class T2>
    441. class Person6;
    442. template<class T1,class T2>
    443. void printPerson2(Person6p)
    444. {
    445. cout<<"类外实现--姓名:"<" 类外实现--年龄:"<
    446. }
    447. template<class T1,class T2>
    448. class Person6
    449. {
    450. //全局函数,类内实现
    451. friend void printPerson(Person6p)
    452. {
    453. cout<<"类内实现--姓名:"<" 类内实现--年龄:"<
    454. }
    455. //全局函数 类外实现
    456. //加空模板参数列表
    457. //如果全局函数是类外实现,需要让编译器提前知道这个函数的存在
    458. friend void printPerson2<>(Person6 p);
    459. public:
    460. Person6(T1 name,T2 age)
    461. {
    462. this->m_name = name;
    463. this->m_age = age;
    464. }
    465. private:
    466. T1 m_name;
    467. T2 m_age;
    468. };
    469. void test09()
    470. {
    471. cout<<"************test09**********"<
    472. <<"********全局函数类内实现*******"<
    473. Person6int>p("张飞",456);
    474. printPerson(p);
    475. Person6int>p1("曹操",736);
    476. printPerson2<>(p1);
    477. }
    478. int main()
    479. {
    480. test01();
    481. cout<
    482. test02();
    483. cout<
    484. test03();
    485. cout<
    486. test04();
    487. cout<
    488. test05();
    489. cout<
    490. test06();
    491. cout<
    492. test07();
    493. cout<
    494. test08();
    495. cout<
    496. test09();
    497. cout<
    498. system("pause");
    499. return 0;
    500. }

  • 相关阅读:
    Android 沉浸式状态栏(全透明状态栏)全适配方案。解决透明状态栏后依然有半透明灰色问题。
    成功解决“IndexError: queue index out of range”错误的全面指南
    第2-4-5章 规则引擎Drools高级语法-业务规则管理系统-组件化-中台
    23.2 微服务SpringCloud基础实战(❤❤❤)
    1. 微服务之Eureka服务注册发现
    Oracle客户端工具安装(PL/SQL Developer 和 instantclient)小记
    【Go】令牌桶限流算法
    【算法|动态规划No.32 | 完全背包问题】完全背包模板题
    【MySQL 系列】在 CentOS 上安装 MySQL
    数据结构与算法-二分查找
  • 原文地址:https://blog.csdn.net/qq_50934329/article/details/139761180