• C++ 语言学习 day11 复习(3)


    1.第一个是昨天的作业: 用类实现一个双向循环链表, 完成对应的功能,(增删查改 )

    代码:

    list.h

    1. #ifndef LIST_H
    2. #define LIST_H
    3. #include <iostream>
    4. #include <string.h>
    5. using namespace std;
    6. #define Type int //宏定义
    7. typedef unsigned int u32;//无符号整型
    8. /***** 节点的结构体 ****/
    9. struct Node
    10. {
    11. Node():data(new Type),prev(NULL),next(NULL)
    12. {
    13. memset(data,0,sizeof(Type)); /*清零数据*/
    14. }/*构造函数:申请空间*/
    15. ~Node(){delete data;}/*析构函数:释放空间*/
    16. Type *data; /*数据域*/
    17. Node *prev; /*前驱*/
    18. Node *next; /*后继*/
    19. };
    20. /****** 链表的结构体 ******/
    21. class List
    22. {
    23. public:
    24. List() /*链表构造函数*/
    25. {
    26. /*1.申请空间*/
    27. m_head = new Node;
    28. /*2.更改指向*/
    29. m_head->next = m_head;
    30. m_head->prev = m_head;
    31. /*3.初始化元素个数*/
    32. m_size = 0;
    33. }
    34. // List(const List &list) /*链表拷贝构造*/
    35. // :List()/*1.调用无参构造*/
    36. // {
    37. // /*2.拷贝list表的数据到this表中*/
    38. // /*调用链表尾部增加 push_back()*/
    39. // }
    40. ~List()
    41. {
    42. clear(); /*清空非表头节点*/
    43. delete m_head;/*释放表头*/
    44. }
    45. public: /* 公有接口 */
    46. bool push_back(const Type &value)/*链表尾部增加*/
    47. {
    48. return insert(m_head,value);
    49. // /*1.新增节点*/
    50. // Node *node = new Node;
    51. // /*2.拷贝数据到新节点空间*/
    52. // *node->data = value;
    53. // /*3.找到要插入位置的前后节点*/
    54. // Node *prev = m_head->prev;
    55. // Node *next = m_head;
    56. // /*4.更改指向*/
    57. // node->prev = prev;
    58. // node->next = next;
    59. // prev->next = node;
    60. // next->prev = node;
    61. // /*5.元素个数+1*/
    62. // m_size++;
    63. // return true;
    64. }
    65. bool push_front(const Type &value)/*链表头部增加*/
    66. {
    67. return insert(m_head->next,value);
    68. }
    69. bool insert(Node *insert_node,const Type &value)/*链表任意节点位置插入*/
    70. {
    71. /*1.新增节点*/
    72. Node *node = new Node;
    73. /*2.拷贝数据到新节点空间*/
    74. *node->data = value;
    75. /*3.找到要插入位置的前后节点*/
    76. Node *prev = insert_node->prev;
    77. Node *next = insert_node;
    78. /*4.更改指向*/
    79. node->prev = prev;
    80. node->next = next;
    81. prev->next = node;
    82. next->prev = node;
    83. /*5.元素个数+1*/
    84. m_size++;
    85. return true;
    86. }
    87. bool insert(u32 index,Type &value)/*链表任意插入*/
    88. {
    89. if(index > m_size) index = m_size;
    90. /**** 找到要插入位置的节点 ****/
    91. Node *node = m_head->next;
    92. for(u32 i = 0; i < index;i++)
    93. {
    94. node = node->next;
    95. }
    96. /**** 插入数据 ****/
    97. return insert(node,value);
    98. }
    99. bool pop_back()/*链表尾部删除*/
    100. {
    101. if(m_size == 0) return false;
    102. return erase(m_head->prev);
    103. }
    104. bool pop_front()/*链表头部删除*/
    105. {
    106. if(m_size == 0) return false;
    107. return erase(m_head->next);
    108. }
    109. bool erase(int index)/*链表任意删除节点*/
    110. {
    111. if(m_size == 0 || index >= m_size) return false;
    112. /*** 1.找到要删除的节点 ****/
    113. Node *node = m_head->next;
    114. for(int i = 0; i < index;i++)
    115. {
    116. node = node->next;
    117. }
    118. /*** 2.删除节点 ****/
    119. return erase(node);
    120. }
    121. bool erase(Node *node)
    122. {
    123. /*** 1.找到前驱和后继 ***/
    124. Node *prev = node->prev;
    125. Node *next = node->next;
    126. /*** 2.释放节点 *****/
    127. delete node;
    128. /*** 3.修改指向 ****/
    129. prev->next = next;
    130. next->prev = prev;
    131. /*** 4.元素个数-1 **/
    132. m_size--;
    133. return true;
    134. }
    135. void clear()/*清空链表*/
    136. {
    137. while(m_size != 0)
    138. {
    139. pop_back();/*尾部删除*/
    140. }
    141. }
    142. bool remove(const Type &value)/*删除第一个匹配的值 : 会调用 == 运算符重载*/
    143. {
    144. /*** 1.找到匹配节点 ****/
    145. Node *node = m_head->next;
    146. while(node != m_head)
    147. {
    148. if(*node->data == value)
    149. {
    150. /**** 删除该节点 ****/
    151. return erase(node);
    152. }
    153. node = node->next; /*往后遍历*/
    154. }
    155. return false;
    156. }
    157. template <class _Predicate>/*虚拟类型*/
    158. bool remove_if(_Predicate Predicate) /*删除第一个匹配的值 : 一元谓词: bool func(Type value) */
    159. {
    160. /*** 1.找到匹配节点 ****/
    161. Node *node = m_head->next;
    162. while(node != m_head)
    163. {
    164. if( Predicate(*node->data) == true)
    165. {
    166. /**** 删除该节点 ****/
    167. return erase(node);
    168. }
    169. node = node->next; /*往后遍历*/
    170. }
    171. return false;
    172. }
    173. void remove_all(const Type &value)/*删除所有匹配的值: 会调用 == 运算符重载*/
    174. {
    175. /**** 1.找到匹配节点 ****/
    176. while(remove(value) == true);
    177. }
    178. template <class _Predicate>/*虚拟类型*/
    179. void remove_all_if(_Predicate Predicate)/*删除所有匹配的值: 一元谓词: bool func(Type value)*/
    180. {
    181. /**** 1.找到匹配节点 ****/
    182. while(remove_if(Predicate) == true);
    183. }
    184. Type &front()/*返回链表第一个元素*/
    185. {
    186. return *m_head->next->data;
    187. }
    188. Type &back()/*返回链表最后一个元素*/
    189. {
    190. return *m_head->prev->data;
    191. }
    192. Type &operator [](u32 index) const/*提供随机访问*/
    193. {
    194. if(index >= m_size)
    195. {
    196. cout << "链表没有元素个数,爆出异常" << endl;
    197. throw "异常:链表没有元素个数"; /*报异常*/
    198. }
    199. Node *node = m_head->next; /*第一个元素*/
    200. for(u32 i = 0; i < index;i++)
    201. {
    202. node = node->next; /*往后遍历*/
    203. }
    204. return *node->data;
    205. }
    206. u32 size() const /*获取元素的个数*/
    207. {
    208. return m_size;
    209. }
    210. Type &find(Type value)
    211. {
    212. /*** 1.找到匹配节点 ****/
    213. Node *node = m_head->next;
    214. while(node != m_head)
    215. {
    216. if(*node->data == value)
    217. {
    218. /**** 返回该节点数据 ****/
    219. break;
    220. }
    221. node = node->next; /*往后遍历*/
    222. }
    223. return *node->data;
    224. }
    225. template <class _Predicate>/*虚拟类型*/
    226. Type &find_if(_Predicate Predicate)
    227. {
    228. /*** 1.找到匹配节点 ****/
    229. Node *node = m_head->next;
    230. while(node != m_head)
    231. {
    232. if(Predicate(*node->data))
    233. {
    234. /**** 返回该节点数据 ****/
    235. break;
    236. }
    237. node = node->next; /*往后遍历*/
    238. }
    239. return *node->data;
    240. }
    241. static void sort(int *addr,int len) /*冒泡排序:调用 > 运算符重载 */
    242. {
    243. // int addr[];
    244. // int len = 0;
    245. bool flag = false;/*记录是否排好序,排好序:false,未排好序:true*/
    246. int temp = 0;/*临时变量,用于交换*/
    247. for(int i = 0; i < len - 1;i++)
    248. {
    249. flag = false;/*清空数据,用于下次记录*/
    250. for(int j = 0; j < len - i - 1;j++)
    251. {
    252. if(addr[j] > addr[j+1])
    253. {
    254. flag = true;/*表名没有排好序*/
    255. /*交换*/
    256. temp = addr[j];
    257. addr[j] = addr[j+1];
    258. addr[j+1] = temp;
    259. }
    260. }
    261. if(flag == false) break; /*检测是否排好序,排好需就直接退出*/
    262. }
    263. }
    264. void sort()
    265. {
    266. bool flag = false;/*记录是否排好序,排好序:false,未排好序:true*/
    267. Type *temp = NULL;/*临时指针,用于交换*/
    268. Node *node_i = NULL;
    269. Node *node_j = NULL;
    270. /****** 排序 *******/
    271. for(node_i = m_head->next ; node_i != m_head->prev ; node_i = node_i->next)
    272. {
    273. flag = false;/*清空数据,用于下次记录*/
    274. for(node_j = m_head->next;node_j != m_head->prev ; node_j = node_j->next)
    275. {
    276. if(*node_j->data > *node_j->next->data)
    277. {
    278. flag = true;/*表名没有排好序*/
    279. /*交换*/
    280. temp = node_j->data;
    281. node_j->data = node_j->next->data;
    282. node_j->next->data = temp;
    283. }
    284. }
    285. if(flag == false) break; /*检测是否排好序,排好需就直接退出*/
    286. }
    287. }
    288. /***** 接口使用 *****/
    289. protected:
    290. Node *m_head; /* 节点:表头 */
    291. u32 m_size; /* 元素个数 */
    292. };
    293. #endif // LIST_H

    main.cpp

    1. #include <iostream>
    2. #include "list.h"
    3. using namespace std;
    4. void Print(const List &list);
    5. int main()
    6. {
    7. List list;
    8. for(int i = 0 ; i < 10;i++)
    9. {
    10. list.push_front(i);
    11. }
    12. cout << "排序前:";
    13. for(u32 i = 0; i < list.size();i++)
    14. {
    15. cout << list[i] << ",";
    16. }
    17. cout << endl;
    18. list.sort();
    19. cout << "排序后:";
    20. for(u32 i = 0; i < list.size();i++)
    21. {
    22. cout << list[i] << ",";
    23. }
    24. cout << endl;
    25. return 0;
    26. }
    27. int test2()
    28. {
    29. int addr[10] = {123,1234,236,437,64,51,6,6756,845,85};
    30. int len = 10;
    31. cout << "未排序addr : ";
    32. for(int i = 0; i < len;i++)
    33. {
    34. cout << addr[i] << ",";
    35. }
    36. cout << endl;
    37. List::sort(addr,len);
    38. cout << "已排序addr : ";
    39. for(int i = 0; i < len;i++)
    40. {
    41. cout << addr[i] << ",";
    42. }
    43. cout << endl;
    44. }
    45. int test1()
    46. {
    47. List list;
    48. for(int i = 0; i < 10; i++)
    49. {
    50. //list.push_back(i); /*尾部插入:0,1,2,3,4,5,6,7,8,9*/
    51. //list.insert(0,i);/*头部插入*/
    52. list.insert(list.size(),i);/*尾部插入*/
    53. }
    54. cout << "第一个元素:" << list.front() << endl;
    55. cout << "最后的元素:" << list.back() << endl;
    56. /**** 删除头尾 ****/
    57. list.pop_back();
    58. list.pop_front();
    59. cout << "输出list结构的数据:" << endl;
    60. Print(list);
    61. /**** 删除下标位 3的位置 *****/
    62. list.erase(3);
    63. cout << "输出list结构的数据:" << endl;
    64. /**** 清空 ****/
    65. //list.clear();
    66. //list.remove(6);
    67. list.push_back(5);
    68. list.push_front(5);
    69. //list.remove_all(5);
    70. Print(list);
    71. cout << "调用带 自定义策略的函数" << endl;
    72. bool int_cmp(Type value); /*函数类声明函数*/
    73. list.remove_all_if(int_cmp);
    74. Print(list);
    75. cout << "查询 3" << endl;
    76. int value = list.find(10);
    77. cout << "value = " << value << endl;
    78. cout << "查询大于 5" << endl;
    79. value = list.find_if([/*依赖*/](Type value/*参数列表*/)->bool/*返回值类型*/{
    80. /*匿名函数的函数体*/
    81. if(value > 5) return true;
    82. return false;
    83. });
    84. cout << "value = " << value << endl;
    85. cout << "程序正常结束" << endl;
    86. return 0;
    87. }
    88. bool int_cmp(Type value)
    89. {
    90. if(value > 5) return true;
    91. return false;
    92. }
    93. void Print(const List &list)
    94. {
    95. for(u32 i = 0; i < list.size();i++)
    96. {
    97. cout << list[i] << ",";
    98. }
    99. cout << endl;
    100. }

    2.继承,

    /********* 多继承会造成的问题 *************************
     * 1.父类成员同名问题?
     *      答:使用类域调用解决
     * 2.菱形继承(砖石继承)?:
     *      人类
     *  学生    工人
     *     实习生
     *   答:使用虚继承方式,形成续表索引(32位机:虚指针占4字节)
     * *************************************************/


    父类成员同名问题?
     *      答:使用类域调用解决

    代码:

    1. #include <iostream>
    2. using namespace std;
    3. class Student /*学生*/
    4. {
    5. public:
    6. string m_name; /*姓名*/
    7. int m_age; /*年龄*/
    8. float m_score = 0; /*分数*/
    9. public:
    10. void study(){cout << "学习" << endl;}
    11. void exam(){ cout << "考试" << endl;}
    12. };
    13. class Worker /*工人*/
    14. {
    15. public:
    16. string m_name; /*姓名*/
    17. int m_age; /*年龄*/
    18. int m_salary = 0; /*薪水*/
    19. public:
    20. void wage(int hour)
    21. {
    22. int salary = 20 * hour;
    23. m_salary += salary;
    24. cout << "工作:" << hour << "小时,赚取:" << salary << "薪水" << endl;
    25. }
    26. };
    27. /* 实习生,继承于 学生 和 工人 */
    28. class Trainee : public Student , public Worker
    29. {
    30. public:
    31. void sleep(){ cout << "我是实习生" << endl;}
    32. };
    33. /********* 多继承会造成的问题 *************************
    34. * 1.父类成员同名问题?
    35. * 答:使用类域调用解决
    36. * 2.菱形继承(砖石继承)?:
    37. * 人类
    38. * 学生 工人
    39. * 实习生
    40. * 答:使用虚继承方式,形成续表索引(32位机:虚指针占4字节)
    41. * *************************************************/
    42. int main()
    43. {
    44. Trainee trainee;
    45. cout << "m_score = " << trainee.m_score << endl;
    46. cout << "m_salary = " << trainee.m_salary << endl;
    47. /******** 使用成员同名变量 ********/
    48. trainee.Student::m_name = "王老师";
    49. trainee.Worker::m_name = "王无敌";
    50. cout << "name = " << trainee.Student::m_name << endl;
    51. cout << "name = " << trainee.Worker::m_name << endl;
    52. return 0;
    53. }

    虚继承方式,形成续表索引

    1. #include <iostream>
    2. using namespace std;
    3. class People
    4. {
    5. public:
    6. string m_name; /*姓名*/
    7. int m_age; /*年龄*/
    8. };
    9. class Student : virtual public People /*学生*/
    10. {
    11. public:
    12. float m_score = 0; /*分数*/
    13. public:
    14. void study(){cout << "学习" << endl;}
    15. void exam(){ cout << "考试" << endl;}
    16. };
    17. class Worker : virtual public People /*工人*/
    18. {
    19. public:
    20. int m_salary = 0; /*薪水*/
    21. public:
    22. void wage(int hour)
    23. {
    24. int salary = 20 * hour;
    25. m_salary += salary;
    26. cout << "工作:" << hour << "小时,赚取:" << salary << "薪水" << endl;
    27. }
    28. };
    29. /* 实习生,继承于 学生 和 工人 */
    30. class Trainee : public Student , public Worker
    31. {
    32. public:
    33. void sleep(){ cout << "我是实习生" << endl;}
    34. };
    35. /********* 多继承会造成的问题 *************************
    36. * 1.父类成员同名问题?
    37. * 答:使用类域调用解决
    38. * 2.菱形继承(砖石继承)?:
    39. * 人类
    40. * 学生 工人 -> 这里使用虚继承 virtual public People
    41. * 实习生
    42. * 答:使用 virtual 虚继承方式,形成续表索引(32位机:虚指针占4字节)
    43. * 3.虚继承的好处
    44. * *************************************************/
    45. int main()
    46. {
    47. #if 0
    48. /**** 探讨大小 ***/
    49. cout << "sizeof(string) = " << sizeof(string) << endl; //24字节
    50. cout << "sizeof(People) = " << sizeof(People) << endl; //28字节
    51. cout << "sizeof(Student)= " << sizeof(Student) << endl; //32字节
    52. cout << "sizeof(Worker) = " << sizeof(Worker) << endl; //32字节
    53. cout << "sizeof(Trainee)= " << sizeof(Trainee) << endl; //64字节
    54. #else
    55. /*—— 通过以上可以看出,我共同继承于人类部分多余了,只用一份空间就行,所以照成空间浪费——*/
    56. /*答:使用 virtual 虚继承方式解决多该案例多占用 28 字节,但是 virtual是虚指针所以需要占用 4字节空间*/
    57. /**** 探讨大小 ***/
    58. cout << "sizeof(string) = " << sizeof(string) << endl; //24字节
    59. cout << "sizeof(People) = " << sizeof(People) << endl; //28字节
    60. cout << "sizeof(Student)= " << sizeof(Student) << endl; //32+4字节
    61. cout << "sizeof(Worker) = " << sizeof(Worker) << endl; //32+4字节
    62. cout << "sizeof(Trainee)= " << sizeof(Trainee) << endl; //64+8-28字节
    63. /*———————————— 通过以上案例,得出已经只占用一片空间 ————————————*/
    64. #endif
    65. Trainee trainee;
    66. trainee.m_name = "老师";
    67. cout << "姓名:" << trainee.People::m_name << endl;
    68. cout << "姓名:" << trainee.Student::m_name << endl;
    69. cout << "姓名:" << trainee.Worker::m_name << endl;
    70. cout << "姓名:" << trainee.Trainee::m_name << endl;
    71. return 0;
    72. }

    3.多态 ()

    多态的定义:

    多态是C++面向对象三大特性之一 多态分为两类: ◼静态多态: 函数重载 和 运算符重载属于静态多态,复用函数名 ◼动态多态: 派生类和虚函数实现运行时多态(重写)

    静态多态和动态多态区别: ◼静态多态的函数地址早绑定 - 编译阶段确定函数地址 ◼动态多态的函数地址晚绑定 - 运行阶段确定函数地址

    总结: 多态满足条件: ◼有继承关系 ◼子类重写父类中的虚函数(”虚“会被继承) 多态使用条件: ◼父类指针或引用指向子类对象 重写:函数返回值类型 函数名 参数列表 完全一致称为重写

    多态的优点

    多态的优点: ◼代码组织结构清晰 ◼可读性强 ◼利于前期和后期的扩展以及维护 总结:C++开发提倡利用多态设计程序架构,因为多态优点很多

    代码:(加强版)

    1. #include <iostream>
    2. using namespace std;
    3. class People
    4. {
    5. public:
    6. /**** 虚函数 -> Qt里面 函数名变成斜体字 ****/
    7. virtual void study()
    8. {
    9. cout << "自我摸索学习" << endl;
    10. }
    11. public:
    12. string m_name;
    13. int m_age;
    14. };
    15. class Student : public People
    16. {
    17. public:
    18. void study() /* -> 重写 */
    19. {
    20. cout << "跟着大牛老师学习" << endl;
    21. }
    22. };
    23. class Teacher : public People
    24. {
    25. public:
    26. void study() /* -> 重写 */
    27. {
    28. cout << "看国际论坛博文学习" << endl;
    29. }
    30. };
    31. class Librarian : public People
    32. {
    33. public:
    34. void study() /* -> 重写 */
    35. {
    36. cout << "看图书学习" << endl;
    37. }
    38. };
    39. class Programmer : public Student
    40. {
    41. public:
    42. void study() /* -> 重写 */
    43. {
    44. cout << "百度CP复制学习" << endl;
    45. }
    46. };
    47. #include <list> /*链表 // STL容器*/
    48. void Print_study(People &value1)
    49. {
    50. value1.study();/*打印学习方法*/
    51. }
    52. int main()
    53. {
    54. Student student;
    55. Teacher teacher;
    56. Programmer programmer;
    57. Print_study(student);
    58. Print_study(teacher);
    59. Print_study(programmer);
    60. #if 0
    61. list<People *> list_v;
    62. /******* 插入 *******/
    63. list_v.push_back(new People);
    64. list_v.push_back(new Student);
    65. list_v.push_back(new Programmer);
    66. list_v.push_back(new Librarian);
    67. list_v.push_back(new Teacher);
    68. /******* 遍历 *******/
    69. list<People *>::iterator it;
    70. for(it = list_v.begin();it != list_v.end();it++)
    71. { /** it 遍历出来的指针 **/
    72. (*it)->study();
    73. }
    74. #endif
    75. return 0;
    76. }

    代码(普通版)

    1. #include <iostream>
    2. using namespace std;
    3. /***** 饮品制作的基类 *****/
    4. class Beverage
    5. {
    6. public:
    7. virtual void boil() = 0; /*煮水*/
    8. virtual void brewing() = 0; /*冲泡*/
    9. virtual void with_cup() = 0; /*倒入杯中*/
    10. virtual void ingredients() = 0; /*加入辅料*/
    11. public:
    12. void make()/*制作*/
    13. {
    14. boil();
    15. brewing();
    16. with_cup();
    17. ingredients();
    18. }
    19. };
    20. /***** 制作咖啡 ****/
    21. class Coffee : public Beverage
    22. {
    23. public:
    24. void boil()
    25. {
    26. cout << "煮矿泉水" << endl;
    27. }
    28. void brewing()
    29. {
    30. cout << "冲泡咖啡" << endl;
    31. }
    32. void with_cup()
    33. {
    34. cout << "倒入咖啡杯中" << endl;
    35. }
    36. void ingredients()
    37. {
    38. cout << "加入红糖和牛奶" << endl;
    39. }
    40. };
    41. class Tea : public Beverage
    42. {
    43. public:
    44. void boil()
    45. {
    46. cout << "煮山泉水" << endl;
    47. }
    48. void brewing()
    49. {
    50. cout << "冲泡茶叶" << endl;
    51. }
    52. void with_cup()
    53. {
    54. cout << "倒入茶杯中" << endl;
    55. }
    56. void ingredients()
    57. {
    58. cout << "加入枸杞,人生片" << endl;
    59. }
    60. };
    61. void make(Beverage &beverage)
    62. {
    63. beverage.make();
    64. }
    65. int main()
    66. {
    67. Coffee coffee;
    68. Tea tea;
    69. make(coffee);
    70. make(tea);
    71. return 0;
    72. }

    4.多态的时候,开辟空间需要加上 (虚析构!!)

    虚析构和纯虚析构

    多态使用时,如果子类中有属性开辟到堆区,那么父类指针在释放时无法调用到子类的析构代码 解决方式:将父类中的析构函数改为虚析构或者纯虚析构

    虚析构和纯虚析构共性: ◼可以解决父类指针释放子类对象 ◼都需要有具体的函数实现 虚析构和纯虚析构区别: ◼如果是纯虚析构,该类属于抽象类,无法实例化对象

    虚析构语法:virtual ~类名(){} 纯虚析构语法:virtual ~类名() = 0;

    总结: ◼ 虚析构或纯虚析构就是用来解决通过父类指针释放子类对象 ◼ 如果子类中没有堆区数据,可以不写为虚析构或纯虚析构 ◼ 拥有纯虚析构函数的类也属于抽象类

    代码:

    1. #include <iostream>
    2. using namespace std;
    3. class A
    4. {
    5. public:
    6. A(){cout << __func__ << endl;}
    7. virtual ~A(){cout << __func__ << endl;} //这里可以尝试把 virtual 去掉 调试试试
    8. };
    9. class B :public A
    10. {
    11. public:
    12. B(){cout << __func__ << endl;}
    13. ~B(){cout << __func__ << endl;}
    14. };
    15. /**** 一般在调用多态时会造成内存泄漏,可以使用虚析构或纯虚析构解决实现 ****/
    16. int main()
    17. {
    18. A *a = new B; /* A() */
    19. delete a; /* ~A() */
    20. return 0;
    21. }

    5.文件操作

    C++中对文件操作需要包含头文件 < fstream >

    文件类型分为两种:

    1. 文本文件 - 文件以文本的ASCII码形式存储在计算机中
    2. 二进制文件 - 文件以文本的二进制形式存储在计算机中,用户一般不能直接读懂它们

    操作文件的三大类:

    1. ofstream:写操作
    2. ifstream: 读操作
    3. fstream : 读写操作

    10.1文本文件

    10.1.1写文件


    写文件步骤如下:

    1. 包含头文件

      #include

    2. 创建流对象

      ofstream ofs;

    3. 打开文件

      ofs.open(“文件路径”,打开方式);

    4. 写数据

      ofs << “写入的数据”;

    5. 关闭文件

      ofs.close();



    代码:

    1. #include <iostream>
    2. #include <fstream> /* 文件流类 */
    3. using namespace std;
    4. class Student
    5. {
    6. public:
    7. Student(string name = "",int age = 0):m_name(name),m_age(age){}
    8. string m_name;
    9. int m_age;
    10. };
    11. /********** 操作集 ***************************************************************************
    12. * 打开:
    13. * void open(const char* __s, ios_base::openmode __mode = ios_base::in | ios_base::out)
    14. * void open(const std::string& __s,ios_base::openmode __mode = ios_base::in | ios_base::out)
    15. * 参数:
    16. * @char* __s: C语言风格文件名
    17. * @string s : C++风格文件名
    18. * @ios_base::openmode mode : 打开模式
    19. * ios_base::in 写模式
    20. * ios_base::out 读模式
    21. * ios_base::trunc 创建
    22. * ios_base::binary 二进制
    23. * ios_base::app 追加
    24. *————————————————————————————————————————————————————————————————————————————————————————————
    25. * 关闭:
    26. * void close()
    27. *————————————————————————————————————————————————————————————————————————————————————————————
    28. * 判断是否打开成功:
    29. * bool is_open() const
    30. * 返回值:
    31. * 成功: true
    32. * 失败: false
    33. *——————————————————————————————————————————————————————————————————————————————————————————————
    34. *格式化读取:
    35. * operator >>
    36. *格式化写入:
    37. * operator <<
    38. *——————————————————————————————————————————————————————————————————————————————————————————————
    39. *块写入:
    40. * write(const char_type* __s, streamsize __n)
    41. *块读取:
    42. * read(char_type* __s, streamsize __n)
    43. *——————————————————————————————————————————————————————————————————————————————————————————————
    44. *字节写入:
    45. * put(char_type __c)
    46. *字节读取:
    47. * int_type get()
    48. *———————————————————————————————————————————————————————————————————————————————————————————————
    49. *读取一行:
    50. * getline(char_type* __s, streamsize __n)
    51. * *************************************************************************************************/
    52. #include <string.h>
    53. int main()
    54. {
    55. /* 1.实例化对象 */
    56. fstream fd;
    57. /* 2.打开文件 */
    58. #if 0
    59. fd.open("test.txt",ios_base::trunc | ios_base::in | ios_base::out); /*清空写*/
    60. #else
    61. fd.open("test.txt",ios_base::in | ios_base::out); /*读写操作*/
    62. #endif
    63. /* 3.判断是否打开成功 */
    64. if(fd.is_open() == false)
    65. {
    66. cout << "文件打开失败:文件不存在" << endl;
    67. return -1;
    68. }
    69. /* 4.读写操作 */
    70. #if 0
    71. #else
    72. char buf[128] = "";
    73. fd.getline(buf,128);
    74. cout << "buf = " << buf << endl;
    75. #endif
    76. /* 5.关闭文件 */
    77. fd.close();
    78. return 0;
    79. }
    80. int test3()
    81. {
    82. /* 1.实例化对象 */
    83. fstream fd;
    84. /* 2.打开文件 */
    85. #if 0
    86. fd.open("test.txt",ios_base::trunc | ios_base::in | ios_base::out); /*清空写*/
    87. #else
    88. fd.open("test.txt",ios_base::in | ios_base::out); /*读写操作*/
    89. #endif
    90. /* 3.判断是否打开成功 */
    91. if(fd.is_open() == false)
    92. {
    93. cout << "文件打开失败:文件不存在" << endl;
    94. return -1;
    95. }
    96. /* 4.读写操作 */
    97. #if 0
    98. char buf[128] = "老师xxx";
    99. for(int i = 0; i < strlen(buf);i++)
    100. {
    101. fd.put(buf[i]);
    102. }
    103. #else
    104. char ch = 0;
    105. while(fd.eof() == false)
    106. {
    107. ch = fd.get();
    108. cout << ch;
    109. }
    110. cout << endl;
    111. #endif
    112. /* 5.关闭文件 */
    113. fd.close();
    114. return 0;
    115. }
    116. int test2()
    117. {
    118. /* 1.实例化对象 */
    119. fstream fd;
    120. /* 2.打开文件 */
    121. #if 0
    122. fd.open("test.txt",ios_base::trunc | ios_base::in | ios_base::out); /*清空写*/
    123. #else
    124. fd.open("test.txt",ios_base::in | ios_base::out); /*读写操作*/
    125. #endif
    126. /* 3.判断是否打开成功 */
    127. if(fd.is_open() == false)
    128. {
    129. cout << "文件打开失败:文件不存在" << endl;
    130. return -1;
    131. }
    132. /* 4.读写操作 */
    133. #if 0
    134. char buf[128] = "老师,无敌";
    135. fd.write(buf,128); /*写入一块*/
    136. #else
    137. char buf[128] = "";
    138. fd.read(buf,128);
    139. cout << "buf = " << buf << endl;
    140. #endif
    141. /* 5.关闭文件 */
    142. fd.close();
    143. return 0;
    144. }
    145. int test0()
    146. {
    147. /* 1.实例化对象 */
    148. fstream fd;
    149. /* 2.打开文件 */
    150. #if 0
    151. fd.open("test.txt",ios_base::trunc | ios_base::in | ios_base::out); /*清空写*/
    152. #else
    153. fd.open("test.txt",ios_base::in | ios_base::out); /*读写操作*/
    154. #endif
    155. /* 3.判断是否打开成功 */
    156. if(fd.is_open() == false)
    157. {
    158. cout << "文件打开失败:文件不存在" << endl;
    159. return -1;
    160. }
    161. /* 4.读写操作 */
    162. #if 0
    163. Student stu1("王老师",18);
    164. Student stu2("李老师",19);
    165. fd << stu1.m_name << " " << stu1.m_age << endl;
    166. fd << stu2.m_name << " " << stu2.m_age << endl;
    167. #else
    168. while(fd.eof() == false)
    169. {
    170. Student stu1;
    171. fd >> stu1.m_name >> stu1.m_age;
    172. if(stu1.m_age != 0)
    173. cout << "姓名:" << stu1.m_name << "\t年龄:" << stu1.m_age << endl;
    174. }
    175. #endif
    176. /* 5.关闭文件 */
    177. fd.close();
    178. return 0;
    179. }

  • 相关阅读:
    女性气虚胃寒怎么办 六招可祛寒补气
    单体微服务的测试策略
    「Java核心面试系列」Spring面试核心49问(附答案)
    Redis中SDS简单动态字符串
    面试官上来就让手撕HashMap的7种遍历方式,当场愣住,最后只写出了3种
    毕业了校园卡怎么改套餐?
    服务器环境搭建
    Ceph单节点部署
    软考高级论文真题“论湖仓一体架构及其应用”
    centos7安装k8s 1.24.3版本 Error getting node“ err=“node \“master01\“ not found
  • 原文地址:https://blog.csdn.net/she666666/article/details/128024549