数组就是一个集合,里面存放了相同类型的数据元素。
数据类型 数组名[数组长度];数据类型 数组名[数组长度] = {值1,值2,...}数据类型 数组名[] = {值1,值2,...}#include
using namespace std;
int main()
{
int arr1[] = {1, 2, 3};
for (int i = 0; i < 3; i++) // 3代表数组中元素的个数
{
cout << arr1[i] << endl;
}
return 0;
}
示例程序1:数组元素逆序(数组元素首位互换)
#include
using namespace std;
void Reverse(int a[], int n)
{
// i为首元素,j为尾元素
for (int i = 0, j = n - 1; i < j; i++, j--)
{
// 首尾交换
int temp = a[i];
a[i] = a[j];
a[j] = temp;
}
}
int main()
{
int arr[] = {1, 3, 2, 5, 4};
int n = sizeof(arr) / sizeof(int);
Reverse(arr, n);
for (int i = 0; i < n; i++)
{
cout << arr[i] << ",";
}
cout << endl;
return 0;
}
示例程序2:冒泡排序
#include
using namespace std;
void Bubble_Sort(int arr[], int n)
{
for (int i = 0; i < n - 1; i++) // 外循环控制循环次数,n个数需要排n-1次
{
bool flag = true; // 没有排序为true,本趟有排序为false
for (int j = 0; j < n - 1 - i; j++) // 每排1次,趟数减1
{
if (arr[j] > arr[j + 1])
{
flag = false;
int temp = arr[j];
arr[j] = arr[j + 1];
arr[j + 1] = temp;
}
}
if (flag) // 已完成全部排序,提前结束
{
break;
}
// 输出每次排序的结果
cout << "第" << i + 1 << "次:";
for (int k = 0; k < n; k++)
{
cout << arr[k] << ",";
}
cout << endl;
}
}
int main()
{
int arr[] = {3,2,1};
int n = sizeof(arr) / sizeof(int);
Bubble_Sort(arr, n);
return 0;
}
二维数组就是在一维数组上,多加一个维度。
二维数组的定义方式:行数可以省略,列数不能省略
#include
using namespace std;
int main()
{
// 数组类型 数组名[行数][列数]
int arr1[2][3] = {{1, 2, 3}, {4, 5, 6}}; // 推荐这种命名方式
int arr2[2][3] = {1, 2, 3, 4, 5, 6};
int arr3[][3] = {1, 2, 3, 4, 5, 6};
// 遍历二维数组,外层循环打印行数,内层循环打印列数
for (int i = 0; i < 2; i++)
{
for (int j = 0; j < 3; j++)
{
cout << arr3[i][j] << " "; // 每一行的元素
}
cout << endl;
}
return 0;
}
二维数组名称的作用与一维数组类似。
#include
using namespace std;
int main()
{
int score[3][3] = {{100, 100, 100}, {90, 90, 90}, {80, 80, 80}};
for (int i = 0; i < 3; i++)
{
int sum = 0;
for (int j = 0; j < 3; j++)
{
sum += score[i][j]; // 每一行的总和
}
cout << "stu" << i+1 << ": " << sum << endl;
}
return 0;
}
函数的声明:声明可以写多次,但是函数的定义只能有一个。
#include
using namespace std;
void swap(int a, int b)
{
int temp = a;
a = b;
b = temp;
cout << "a= " << a << ",b= " << b << endl;
}
int main()
{
int num1 = 1;
int num2 = 2;
swap(num1, num2); // 进行交换
cout << "um1= " << num1 << ",num2= " << num2 << endl; // 没有发生改变,因为值传递时,形参不影响实参
return 0;
}
示例2:地址传递,把实参的存储地址传给形参,形参的变化会影响实参
#include
using namespace std;
void swap(int *a, int *b)
{
int temp = *a;
*a = *b;
*b = temp;
cout << "a= " << *a << ",b= " << *b << endl;
}
int main()
{
int num1 = 1;
int num2 = 2;
swap(&num1, &num2);
cout << "um1= " << num1 << ",num2= " << num2 << endl;
return 0;
}
示例3(重点,常用):引用传参,可以使得对形参的任何操作都能改变相应的数据,又使函数调用方便。与指针传参的效果一样,不过更加易于阅读。
const *#include
using namespace std;
void swap(int &a, int &b) // 引用传参
{
int temp = a;
a = b;
b = temp;
cout << "a= " << a << ",b= " << b << endl;
}
int main()
{
int num1 = 1;
int num2 = 2;
swap(num1, num2);
cout << "um1= " << num1 << ",num2= " << num2 << endl;
return 0;
}
作用:让代码结构更加清晰
函数分文件编写一般有4个步骤:
.h的头文件,写函数的声明.cpp的源文件,写函数的定义2023.5.23
指针就是地址。
const修饰指针:const int *p常量指针const修饰常量:int * const p指针常量const即修饰指针,又修饰常量const int * const a const后面是指针还是常量,是指针就是常量指针,是常量就是指针常量#include
using namespace std;
int main()
{
int arr1[] = {1, 2, 3, 4, 5};
int *p = arr1; // 数组名就是数组首地址,*p代表第一个元素arr[0]
cout << *(p + 1) << endl; // 相当于arr[1]
return 0;
}
数组作为函数参数进行传递时,会退化为指针,必须再传入数组的有效长度,才能正常使用。
结构体属于用户自定义的数据类型,允许用户存储不同的数据类型。
通过结构体创建变量的方式有三种:
struct结构体名 变量名struct结构体名 变量名 = {成员值1,成员值2,…}const可以防止误操作!#include
#include
using namespace std;
struct Stu
{
string name;
int age;
string sex;
};
Stu people[5] = {
{"刘备", 23, "男"},
{"关羽", 22, "男"},
{"张飞", 20, "男"},
{"赵云", 21, "男"},
{"貂蝉", 19, "女"},
};
// 冒泡排序传入结构体的数组
void BubbleSort(struct Stu people[], int n)
{
for (int i = 0; i < n - 1; i++)
{
for (int j = 0; j < n - 1 - i; j++)
{
if (people[j].age > people[j + 1].age)
{
Stu temp = people[j]; // 创建一个临时结构体
people[j] = people[j + 1];
people[j + 1] = temp;
}
}
}
}
int main()
{
for (int i = 0; i < 5; i++)
{
cout << "姓名:" << people[i].name << ",年龄:" << people[i].age << ",性别:" << people[i].sex << endl;
}
BubbleSort(people, 5);
cout << endl; // 换行,打印排序后的结果
for (int i = 0; i < 5; i++)
{
cout << "姓名:" << people[i].name << ",年龄:" << people[i].age << ",性别:" << people[i].sex << endl;
}
return 0;
}
运行结果:
姓名:刘备,年龄:23,性别:男
姓名:关羽,年龄:22,性别:男
姓名:张飞,年龄:20,性别:男
姓名:赵云,年龄:21,性别:男
姓名:貂蝉,年龄:19,性别:女
姓名:貂蝉,年龄:19,性别:女
姓名:张飞,年龄:20,性别:男
姓名:赵云,年龄:21,性别:男
姓名:关羽,年龄:22,性别:男
姓名:刘备,年龄:23,性别:男
C++程序在执行时,将内存分为4个区域:
const修饰的变量、字符串常量),该区域的数据在程序结束后由操作系统释放。new在堆区开辟内存数据类型 &别名 = 原名int &a = 10; // 不合法int * const avoid add(int &a, int &b){
int c = a+b;
}
在C++中,函数的形参列表中的形参是可以有默认值的。
语法:返回值 函数名 (参数=默认值){}
注意事项:
int add(int a, int b = 10); // 函数声明
int add(int a, int b) // 函数实现
{
return a + b;
}
#include
using namespace std;
int add(int a, int b = 10)
{
return a + b;
}
int main()
{
int num1 = 10;
int c = add(num1); // 输入一个参数即可
cout << c;
return 0;
}
C++中函数的形参列表里可以有占位参数,用来占位,调用函数时必须填补该位置。
语法:返回值类型 函数名(数据类型) {}
目前阶段的占位参数,还用不到,后面的课程中会用到。
占位参数也可以有默认参数void func(int a, int = 10)
#include
using namespace std;
void func(int a, int) // 最后一个参数用于占位
{
cout << "test" << endl;
}
int main()
{
func(10, 20); // 占位参数必须填补
return 0;
}
#include
using namespace std;
// 函数重载需要函数都在同一个作用域下
void func()
{
cout << "func 的调用" << endl;
}
void func(int a)
{
cout << "func(int a) 的调用" << endl;
}
int main()
{
func();
func(10);
return 0;
}
函数重载注意事项
#include
using namespace std;
// 1.引用作为重载条件
void func(int &a)
{
cout << "func(int &a) 的调用" << endl;
}
void func(const int &a)
{
cout << "func(const int &a) 的调用" << endl;
}
// 2.函数重载碰到默认参数
void func(int a, int b = 10)
{
cout << "func(int a, int b = 10)的调用" << endl;
}
void func(int a)
{
cout << "func(int a)的调用" << endl;
}
int main()
{
int a = 10;
// 1.引用作为重载条件
// func(a); // 调用func(int &a)
// func(10); // 调用func(const int &a)
// 2.函数重载碰到默认参数
// func(10); // 当函数重载碰到默认参数时,出现二义性(两个函数都可以调用),报错,尽量避免这种情况
func(10,20); // 调用func(int a, int b = 10)
return 0;
}
2023.5.25
C++面向对象的三大特征:封装、继承、多态。
具有相同性质的对象,可以抽象为一个类,比如:人属于人类、车属于车类
struct和class的唯一区别在于默认的访问权限不同:struct默认权限为公共class默认权限为私有封装是C++面向对象三大特性之一。
封装的意义:
class 类名 {访问权限: 属性/行为};class {里面的内容,称为类内}public公共权限,类内可以访问,类外也可以访问protected保护权限,类内可以访问,类外不可以访问,继承:儿子可以访问父亲中的保护内容private私有权限,类内可以访问,类外不可以访问,与protected的区别在于继承。继承:儿子不可以访问父亲中的私有内容。#include
using namespace std;
const float PI = 3.14;
class Circle
{
private:
public:
int R;
float CalculateZC()
{
return 2 * PI * R;
}
};
Circle c1; // 创建一个对象
int main()
{
c1.R = 2;
cout << "圆的周长:" << c1.CalculateZC() << endl;
return 0;
}
示例2:设计一个学生类,属性有姓名和学号,可以给姓名和学号赋值,可以显示学生的姓名和学号。
#include
#include
using namespace std;
class Student
{
private:
string _name;
int _number; // 学号
public:
Student(string name, int number)
{
_name = name;
_number = number;
}
void print()
{
cout << "姓名:" << _name << ",学号:" << _number << endl;
}
};
int main()
{
Student stu1("张三", 2023);
stu1.print();
return 0;
}
构造函数语法:类名() {}
void~类名() {}~void两种分类方式:
深浅拷贝是面试经典问题,也是常见的一个坑。
构造函数():属性1(值1),属性2(值2){}private:
int _a;
int _b;
public:
Person(int a, int b) : _a(a), _b(b)
{
cout << "Person的构造函数调用" << endl;
}
C++类中的成员可以是另一个类的对象,我们称该成员为对象成员。
class A{}
class B{
A a;
}
B类中有对象A作为成员,A为对象成员。
当创建B时,A与B的构造函数和析构函数的执行顺序是什么?
答:构造时先构造类对象,再构造自身,析构的顺序与构造相反。
static
class Person
{
private:
public:
static int a; // 静态成员变量,类内声明,类外初始化操作
};
int Person::a = 10; // 类中静态变量初始化
main()
{
Person p1;
cout << p1.a << endl; // 通过对象访问成员变量
p1.a = 20;
cout << Person ::a << endl; // 通过类名直接访问成员变量
return 0;
}
示例2:静态成员函数
在C++中,类内的成员变量和成员函数分开存储,只有非静态成员变量才属于类的对象上。
class Person
{
private:
public:
int a;
static int b; // 静态成员,不占用类中的内存空间
void func(){} // 非静态成员函数,不属于类对象上,不占用类的内存空间
static void func2(){} // 静态成员函数,也不属于对象上
};
int Person::b = 0;
Person p1;
main()
{
cout << sizeof(p1); // 输出结果4
return 0;
}
总结:在类中,只有非静态成员变量占用内存空间。
this指针的用途:
Worker w1; // 创建一个对象
Worker *pt = &w1; // 创建指向对象的指针
const修饰成员函数常函数:
mutable后,在常函数中仍然可用修改。mutable(可变的)class Person
{
private:
int _a;
public:
int b;
void print() const // 函数体内部的成员不可以进行修改
{
b = 10; // 报错
}
};
class Person
{
private:
int _a;
public:
mutable int b; // 可变的,在常函数中,这个值可以进行修改
// 在成员函数后面加const,修饰的是this指向,让指针指向的值也不可以修改
void print() const // 函数体内部的成员不可以进行修改
{
b = 10; // 有mutable修饰,不会报错
}
};
常对象:
const称该对象为常对象const Person p; // 在对象前加const,变为常对象
在程序里,有些私有属性,也项让类外特殊的一些函数或者类进行访问,就需要用到友元的技术。
友元的目的就是让一个函数或者类,访问另一个类中私有成员。
友元的三种实现:
#include
using namespace std;
class Person
{
private:
int _a;
int _b;
public:
Person(int a, int b)
{
_a = a;
_b = b;
}
friend void func(Person *pt); // 将全局函数声明为友元函数,这样就可以访问私有成员了,也可以访问公有成员
void func2() {}
};
// 全局函数
void func(Person *pt)
{
pt->_a; // 访问私有成员
pt->_b;
pt->func2(); // 访问公有成员
}
int main()
{
Person p1(1,2);
func(&p1); // 调用友元函数
return 0;
}
2023.5.26
运算符重载概念:对已有的运算符重载进行定义,赋予其另一种功能,以适应不同的数据类型。
operator是关键字,专门用于定义重载运算符的函数返回值类型 operator 运算符名称 (形参列表)
{}
作用:实现两个自定义数据类型相加的运算
对于内置的数据类型,编译器知道如何进行运算。
#include
using namespace std;
class Person
{
public:
int a;
int b;
// 成员函数重载
Person operator+(Person &p)
{
Person temp;
temp.a = this->a + p.a;
temp.b = this->b + p.b;
return temp;
}
};
void test1()
{
Person p1;
p1.a = 1;
p1.b = 2;
Person p2;
p2.a = 3;
p2.b = 4;
Person p3 = p1 + p2; // 通过成员函数进行重载
cout << p3.a << endl; // 输出4
}
int main()
{
test1();
return 0;
}
#include
using namespace std;
class Person
{
public:
int a;
int b;
};
// 全局函数重载+号
Person operator+(Person &p1, Person &p2)
{
Person temp;
temp.a = p1.a + p2.a;
temp.b = p2.b + p2.b;
return temp;
}
void test1()
{
Person p1;
p1.a = 1;
p1.b = 2;
Person p2;
p2.a = 3;
p2.b = 4;
Person p3 = p1 + p2; // 通过成员函数进行重载
cout << p3.a << endl; // 输出4
}
int main()
{
test1();
return 0;
}
总结:
继承是面向对象三大特性之一,可用采用继承提高代码的复用率,减少重复的代码。
语法:class 子类:继承方式 父类
子类:也称为派生类
父类:也称为基类
[外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传(img-w3Gwvaxv-1685175894300)(images/1.png)]
继承一共有三种方式:父类中的private成员,不管使用那种继承方式,都不可以被子类继承
public成员于子类中的public,继承父类中的protected成员于子类中的protectedpublic和protected,在子类中为protected成员public和protected,在子类中为private成员在计算子类对象所占内存空间大小时,子类备份了父类所有非静态成员的数据成员。
#include
using namespace std;
class Base
{
public:
int a;
protected:
int b;
private:
int c;
};
class Son : public Base
{
int d;
};
int main()
{
cout << sizeof(Base) << endl; // 输出12
cout << sizeof(Son) << endl; // 输出16,父类中所有的数据成员都被继承下来,备份了一份
return 0;
}
子类构造函数与析构函数:
#include
using namespace std;
class Base
{
public:
int a;
Base()
{
cout << "Base的构造函数" << endl;
}
~Base()
{
cout << "Base的析构函数" << endl;
}
protected:
int b;
private:
int c;
};
class Son : public Base
{
int d;
public:
Son()
{
cout << "son构造函数" << endl;
}
~Son()
{
cout << "son析构函数" << endl;
}
};
int main()
{
Son s1; // 创建子类对象
return 0;
}
问题:当子类与父类出现同名的成员,如何通过子类对象,访问到子类或父类中同名的数据?
#include
using namespace std;
class Base
{
public:
int a = 1;
void func()
{
cout << "Base--func()" << endl;
}
};
class Son : public Base
{
public:
int a = 2;
void func()
{
cout << "Son--func()" << endl;
}
};
int main()
{
Son s1;
cout << s1.a << endl; // 输出子类的成员
cout << s1.Base::a << endl; // 添加父类的作用域,输出父类中的同名成员
// 访问同名函数
s1.func(); // 调用的为子类成员函数
s1.Base::func(); // 调用父类的成员函数
return 0;
}
问题:继承中同名的静态成员在子类对象上如何进行访问?
静态成员和非静态成员出现同名,处理方式一致。
C++允许一个类继承多个类。
语法:class 子类:继承方式1 父类1,继承方式2 父类2,...
#include
using namespace std;
class Base1
{
public:
int a = 1;
};
class Base2
{
public:
int b = 2;
};
// 多继承
class Son : public Base1, public Base2
{
public:
};
int main()
{
Son s1;
cout << s1.a << endl;
cout << s1.b << endl;
return 0;
}
菱形继承(钻石继承)的概念:
virtual变为虚继承。#include
using namespace std;
// 动物类
class Animal
{
public:
int age;
};
// 采用虚继承,解决菱形继承的问题。在继承方式前面加上virtual关键字变为虚继承
// Animal类称为虚基类
// 羊类
class Sheep : virtual public Animal
{
};
// 骆驼
class Camel : virtual public Animal
{
};
// 羊驼多继承
class Alpaca : public Sheep, public Camel
{
};
int main()
{
Alpaca alpaca;
// 当菱形继承时,两个父类拥有相同数据,需要加以作用域区分
// 这份数据需要一份就可以了,菱形继承导致数据有两份,造成资源浪费
alpaca.Sheep::age = 18; // 数据有二义性,需要指定作用域
cout << alpaca.Sheep::age << endl; // 不采用虚继承时,采用这种方式输出
cout << alpaca.age << endl; // 采用虚继承后,采用这种方式即可正常输出
return 0;
}
多态是C++面向对象三大特性之一。
多态分为两类:
动态多态的满足条件:
virtual关键字),重写:函数名和返回值均相同virtual关键字,可写可不写#include
using namespace std;
class Animal
{
public:
virtual void speak() // 父类虚函数
{
cout << "动物在说话" << endl;
}
};
class Cat : public Animal
{
public:
void speak()
{
cout << "小猫在说话" << endl;
}
};
class Dog : public Animal
{
public:
void speak()
{
cout << "小狗在说话" << endl;
}
};
// 执行说话的函数
// 如果想执行让猫说话,那么这个函数地址就不能提前绑定,需要在运行阶段进行绑定,地址晚绑定
// 只需要在父类的同名函数前,加一个virtual关键字即可
void Speaking(Animal &animal)
{
animal.speak();
}
int main()
{
Cat cat;
Speaking(cat);
Dog dog;
Speaking(dog);
return 0;
}
在多态中,通常父类中虚函数的实现是毫无意义的,主要都是调用子类重写的内容。
因此可以将虚函数改为纯虚函数。
纯虚函数语法:virtual 返回值类型 函数名 (参数列表) = 0;
当类中有了纯虚函数,这个类也称为抽象类。
抽象类的特点:
#include
using namespace std;
class Animal
{
public:
// 只要有一个纯虚函数,这个类就称为抽象类
// 抽象类特点:子类必须重写抽象类中的纯虚函数,否则无法实例化对象
virtual void speak() = 0; // 纯虚函数
};
class Cat : public Animal
{
public:
void speak()
{
cout << "小猫在说话" << endl;
}
};
class Dog : public Animal
{
public:
void speak()
{
cout << "小狗在说话" << endl;
}
};
void Speaking(Animal &animal)
{
animal.speak();
}
int main()
{
Cat cat;
Speaking(cat);
Dog dog;
Speaking(dog);
return 0;
}
多态使用时,如果子类中有属性开辟到堆区,那么父类指针在释放时无法调用子类的析构代码。
解决方式:将父类中的析构函数改为虚析构或者纯虚析构。
虚析构和纯虚析构共性:
virtual ~类名(){}virtual ~类名 = 0; 函数实现 类名:: ~类名(){}总结:
new关键字进行内存空间开辟),可以不写虚析构或纯虚析构#include
#include
using namespace std;
class Animal
{
public:
Animal()
{
cout << "Animal 构造函数调用" << endl;
}
// 利用虚析构可以解决,父类指针释放子类对象时,执行不了子类的析构函数问题
// virtual ~Animal()
// {
// cout << "Animal 析构函数调用" << endl;
// }
virtual ~Animal() = 0; // 纯虚析构函数,有了纯虚析构函数后,这个类也属于抽象类,无法实例化对象
virtual void speak() = 0; // 纯虚函数
};
// 纯虚析构函数实现
Animal::~Animal()
{
cout << "Animal 纯虚析构函数调用" << endl;
}
// 子类继承
class Cat : public Animal
{
public:
string *_name;
Cat(string name)
{
cout << "Cat 构造函数调用" << endl;
_name = new string(name); // 在堆区创建一块内存空间,在析构函数中进行释放
}
~Cat()
{
if (_name != NULL)
{
delete _name; // 释放堆区内存
cout << "Cat 析构函数调用" << endl;
}
}
void speak()
{
cout << *_name << "小猫在说话" << endl;
}
};
int main()
{
Animal *animal = new Cat("Tom"); // 创建一个父类的对象指针
animal->speak(); // 输出 小猫在说话
// 父类指针在析构时候,不会调用子类中析构函数,导致子类如果有堆区属性,出现内存泄漏
// 需要在父类析构函数前,加virtual关键字
delete animal;
return 0;
}
C++中对文件操作需要包含头文件。
文件类型分为两种:
ofstream:只写操作ifstream:只读操作fstream:读写操作均可以写文件步骤如下:
#include ofstream ofs;ofs.open("文件路径,打开方式),如果该文件不存在,则在同级目录下创建该文件ofs << "写入的数据";ofs.close();文件打开方式:文件打开方式可以配合使用,利用|操作符,例如采用二进制方式写文件ios::binary | ios::out
| 打开方式 | 描述 |
|---|---|
| ios::in | 为读文件而打开文件 |
| ios::out | 为写文件而打开文件 |
| ios::ate | 初始位置:文件尾 |
| ios::app | 追加方式写文件 |
| ios::trunc | 如果文件存在先删除,再创建 |
| ios::binary | 二进制方式 |
#include
#include // 包含头文件
using namespace std;
void test()
{
ofstream ofs; // 创建流对象
ofs.open("test.txt", ios::out); // 打开文件(如果文件不存在,则在同级目录下创建该文件),往文件中写数据
ofs << "hello,world" << endl; // 写入数据
ofs << "hello,world" << endl;
ofs.close(); // 关闭文件
}
int main()
{
test();
return 0;
}
读文件与写文件步骤相似,但是读取方式相对于比较多。
读文件步骤如下:
#include ifstream ifs;ifs.open("文件路径", 打开方式);ifs.close();#include
#include // 包含头文件
#include
using namespace std;
void test()
{
ifstream ifs; // 创建流对象
ifs.open("test.txt", ios::in);
// 判断文件是否打开成功
if (!ifs.is_open())
{
cout << "文件打开失败" << endl;
return; // 结束,不进行下面的操作了
}
// 读文件方式1
// char buf[1024] = {0};
// while (ifs >> buf)
// {
// cout << buf << endl; // 输出文件中的内容
// }
// 读文件方式2 : 按行读取数据
char buf[1024] = {0};
while (ifs.getline(buf, sizeof(buf)))
{
cout << buf << endl;
}
// 读取方式3:把文件内容存进string中
// string buf;
// while (getline(ifs, buf))
// {
// cout << buf << endl;
// }
// 读取方式4:单个字符读取,不推荐,效率较慢
// char c;
// while ((c = ifs.get()) != EOF) // EOF: end of file,文件尾部
// {
// cout << c;
// }
ifs.close(); // 关闭文件
}
int main()
{
test();
return 0;
}
二进制方式写文件主要利用流对象调用成员函数write
函数原型:ostream& write(const char* buffer, int len);
参数解释:字符指针buffer指向内存中一段存储空间,len是读写的字节数。
#include
#include // 包含头文件
using namespace std;
class Person
{
public:
char name[64]; // 存放字符串
int age;
};
void test()
{
ofstream ofs;
ofs.open("person.txt", ios::out | ios::binary); // 打开文件,采用二进制的方式写文件
Person p1 = {"张三", 18};
ofs.write((const char *)&p1, sizeof(Person)); // 写文件
ofs.close(); // 关闭文件
}
int main()
{
test();
return 0;
}
函数原型:istream& read(char* buffer, int len);
参数解释:字符指针buffer指向内存中一段存储空间,len是读写的字节数。
#include
#include // 包含头文件
using namespace std;
class Person
{
public:
char name[64]; // 存放字符串
int age;
};
void test()
{
ifstream ifs;
ifs.open("person.txt", ios::in | ios::binary); // 打开文件
if (!ifs.is_open())
{
cout << "文件打开失败" << endl;
return;
}
Person p;
ifs.read((char *)&p, sizeof(Person)); // 读取文件
cout << "姓名:" << p.name << " 年龄:" << p.age << endl;
ifs.close();
}
int main()
{
test();
return 0;
}