此专栏为移动机器人知识体系下的编程语言中的 C {\rm C} C++从入门到深入的专栏,参考书籍:《深入浅出 C {\rm C} C++》(马晓锐)和《从 C {\rm C} C到 C {\rm C} C++精通面向对象编程》(曾凡锋等)。
5.C++的自定义类型与字符串
5.1 结构体
-
结构体概念和声明
-
结构体是一个可以包含不同数据类型的结构,其定义语法格式如下:
struct <结构体类型名> { 成员数据类型1 成员名1; 成员数据类型2 成员名2; ...; 成员数据类型n 成员名n; };
-
描述学生信息的结构体实例:
struct student { int studentID; // 学号; char name[20]; // 姓名; int age; // 年龄; int height; // 身高; int weight; // 体重; float score; // 成绩; };
-
企业员工信息的结构体实例:
// 出生日期结构体; struct birthday { short year; short month; short day; }; // 员工信息结构体; struct employee { int employeeID; char name[20]; int age; struct birthday birth; // 结构体类型的变量; float salary; };
-
-
结构体变量的定义
-
结构体类型定义后系统不分配内存,即无法存储数据,只有在程序中定义了结构体类型变量后才能存储数据,结构体类型变量简称结构体变量;
-
声明结构体变量方法 1 1 1:定义结构体类型的同时定义结构体变量;
// 定义结构体类型的同时定义结构体变量语法格式: struct <结构体类型名> { 成员数据类型1 成员名1; 成员数据类型2 成员名2; ...; 成员数据类型n 成员名n; }<变量名表>;
// 定义结构体类型的同时定义结构体变量实例 struct student { int studentID; char name[20]; int height; int weight; int age; }student1,student2; // 声明两个结构体变量student1和student2;
-
声明结构体变量方法 2 2 2:使用无名结构体类型声明结构体变量;
// 使用无名结构体类型声明结构体变量语法格式: struct { 成员数据类型1 成员名1; 成员数据类型2 成员名2; ...; 成员数据类型n 成员名n; }变量名表;
// 使用无名结构体类型声明结构体变量实例 struct { int studentID; char name[20]; int height; int weight; int age; }student1,student2,student3; // 声明两个结构体变量student1、student2、student3;
-
声明结构体变量方法 3 3 3:用结构体类型声明结构体变量;
// 用结构体类型声明结构体变量语法格式: [struct] <结构体类型名> <变量名表>;
// 用结构体类型声明结构体变量实例 struct student { int studentID; char name[20]; int height; int weight; int age; }; struct student student1; // 保留struct关键字声明变量student1; student student2; // 省略struct关键字声明变量student2;
-
-
结构体变量的初始化
-
结构体变量初始化指在定义结构体变量的同时给结构体变量赋初值;
-
初始化方式:一是用由大括号括起来的若干成员值对结构体变量初始化;二是用同类型的变量对结构体变量初始化;
-
结构体变量初始化实例:
struct student { int studentID; char name[20]; int height; int weight; int age; }; struct student student1 = {23,"Willard",170,56,27}; // 用成员值进行初始化; struct student student2 = student1; // 用同类型变量初始化;
-
如果结构体成员的存储类型为静态存储模式,称该结构体成员为静态成员, C {\rm C} C++规定必须在用结构体类型创建对象前为静态成员设置初值,语法格式如下:
数据类型 结构体类型::静态成员 = 初值;
// 结构体赋值实例: struct stu_ { static int a; int b; }stu_1,stu_2; int stu_::a = 2; // 设置静态成员a的值; int main() { stu_1.b = 6; stu_2.b = 18; stu_1.a = 18; // 修改静态成员a的值; }
-
-
结构体的使用
结构体变量.成员名
struct employee emp1; strcpy(emp.name,"Willard"); emp.age = 27; emp.birth.year = 1996;
-
结构体使用实例 1 1 1 ( e x a m p l e 5 _ 1. c p p ) ({\rm example5\_1.cpp}) (example5_1.cpp):
/** * 作者:罗思维 * 时间:2023/10/23 * 描述:设计一段关于输入/输出企业员工基本信息的结构体程序, * 基本信息包括:员工编号、姓名、性别、年龄、出生日期、工资; */ #include <iostream> #include <iomanip> using namespace std; // 定义出生日期的结构体类型; struct birthday { short year; short month; short day; }; // 定义职工信息结构体类型; struct employee { int employeeID; char name[20]; short sex; int age; struct birthday birth; float salary; } emp1; int main() { cout << "输入员工信息:编号、姓名、性别(0男,1女)、年龄、生日(年月日)、收入:" << endl; cin >> emp1.employeeID >> emp1.name >> emp1.sex >> emp1.age; cin >> emp1.birth.year >> emp1.birth.month >> emp1.birth.day >> emp1.salary; cout << setw(5) << "编号" << setw(10) << "姓名" << setw(10) << "性别"; cout << setw(10) << "年龄" << setw(10) << "生日" << setw(15) << "收入" << endl; cout << setw(5) << emp1.employeeID << setw(10) << emp1.name << setw(10) << (emp1.sex == 0 ? "男" : "女"); cout << setw(10) << emp1.age << setw(10) << emp1.birth.year << "." << emp1.birth.month << "." << emp1.birth.day; cout << setw(10) << emp1.salary << endl; return 0; }
-
结构体数组
- 如果数组的数据类型是结构体类型,则称此数组为结构体数组,通过下标访问数组元素;
- 结构体数组需要用下标变量引用结构体成员;
-
结构体数组实例 1 ( e x a m p l e 5 _ 2. c p p ) 1({\rm example5\_2.cpp}) 1(example5_2.cpp):
/** * 作者:罗思维 * 时间:2023/10/23 * 描述:已知5个企业员工的基本信息,输出工资不少于5000元的员工编号和姓名。 */ #include <iostream> #include <iomanip> using namespace std; // 定义出生日期的结构体类型; struct birthday { short year; short month; short day; }; // 定义职工信息结构体类型; struct employee { int employeeID; char name[20]; short sex; int age; struct birthday birth; float salary; }; int main() { struct employee emp[5] = { {1001, "Willard", 0, 27, {1996, 8, 9}, 10000}, {1002, "Chen", 1, 27, {1996, 7, 4}, 12000}, {1003, "Zhang", 1, 26, {1997, 5, 20}, 9800}, {1004, "Huang", 0, 28, {1995, 1, 1}, 3000}, {1005, "Liu", 0, 29, {1994, 6, 7}, 4800}}; cout << "公司超过5000元的员工有:" << endl; cout << "编号" << setw(10) << "姓名" << endl; for (int nCnt = 0; nCnt < 5; nCnt++) { if (emp[nCnt].salary >= 5000) { cout << emp[nCnt].employeeID << setw(10) << emp[nCnt].name << endl; } } return 0; }
-
结构体数组实例 2 ( e x a m p l e 5 _ 3. c p p ) 2({\rm example5\_3.cpp}) 2(example5_3.cpp):
/** * 作者:罗思维 * 时间:2023/10/23 * 描述:已知10个学生的基本信息,输出各科成绩合格学生的班级、ID、姓名、各科成绩、总成绩。 * 基本信息包括:学生班级、学生ID、学生姓名、各科成绩。 */ #include <iostream> #include <iomanip> using namespace std; // 定义学生成绩结构体; struct studentGrade { int math; int Chinese; int history; }; // 定义学生信息结构体; struct studentInfo { char stuClass[20]; char studentID[20]; char stuName[20]; struct studentGrade grade; }; int main() { int totalGrade; struct studentInfo student[10] = { {"class1", "202311411401", "Willard", {100, 95, 98}}, {"class1", "202311411402", "ChenJD", {98, 100, 96}}, {"class2", "202311411403", "ChenXB", {99, 97, 96}}, {"class2", "202311411404", "Zhang", {100, 59, 92}}, {"class3", "202311411405", "LiuTE", {99, 99, 58}}, {"class3", "202311411406", "Liang", {56, 93, 95}}, {"class4", "202311411407", "LanZhi", {99, 99, 98}}, {"class4", "202311411408", "DengJM", {57, 98, 99}}, {"class5", "202311411409", "ChenXin", {100, 98, 99}}, {"class5", "202311411410", "HuangX", {99, 99, 98}}}; cout << "每科课程均合格的学生信息如下:" << endl; cout << endl; cout << setw(10) << "学生班级" << setw(20) << "学生学号" << setw(10) << "学生姓名"; cout << setw(12) << "数学成绩" << setw(10) << "语文成绩" << setw(10) << "历史成绩"; cout << setw(12) << "学生总成绩" << endl; cout << "-------------------------------------------------------------------------------------" << endl; for (int nCnt = 0; nCnt < 10; nCnt++) { if ((student[nCnt].grade.math >= 60) && (student[nCnt].grade.Chinese >= 60) && (student[nCnt].grade.history >= 60)) { totalGrade = student[nCnt].grade.math + student[nCnt].grade.Chinese + student[nCnt].grade.history; cout << setw(10) << student[nCnt].stuClass << setw(20) << student[nCnt].studentID; cout << setw(10) << student[nCnt].stuName << setw(10) << student[nCnt].grade.math; cout << setw(10) << student[nCnt].grade.Chinese << setw(10) << student[nCnt].grade.history; cout << setw(10) << totalGrade << endl; } } return 0; }
5.2 共用体
-
共用体 ( u n i o n ) ({\rm union}) (union)亦称联合体,共用体定义了一块所有数据成员共享的内存空间;
-
共用体类型及其变量
-
共用体类型定义语法格式:
union 共用体类型名 { 成员数据类型1 成员名1; 成员数据类型2 成员名2; ...; 成员数据类型n 成员名n; };
-
C {\rm C} C++允许省略<共用体类型名>定义无名共用体类型,共用体由若干成员组成,每个共用体成员有自己的名字和数据类型;
-
共用体定义实例:
union u_uni { char ch; int i; float f; }; union { char ch; int i; float f; };
-
声明共用体变量的三种方式:
// 1.定义共用体类型的同时声明共用体变量; union u_buffer { char ch[8]; int i; } buf={"com"}; // 2.使用无名共用体类型声明共用体变量; union { int i; char ch[8]; } buf={8}; // 共用体变量buf // 3.用共用体类型声明共用体变量; union u_buffer { char ch[10]; int i; }; u_buffer buf={"com"};
-
-
共用体使用实例 ( e x a m p l e 5 _ 4. c p p ) ({\rm example5\_4.cpp}) (example5_4.cpp):
/** * 作者:罗思维 * 时间:2023/10/24 * 描述:使用共用体输出某学校人员信息。 * 如果是学生,输出所在班级;如果是老师,输出所在办公室名称。 */ #include <iostream> #include <iomanip> using namespace std; union department { float score; int verifyGrade; // 考评等级; }; struct person { char name[20]; int age; char job; // s代表学生;t代表老师; union department dep; }; int main() { struct person per[5] = { {"Willard", 27, 't', {0}}, {"ChenJD", 27, 't', {0}}, {"LinLi", 23, 's', {0}}, {"Wangwu", 22, 's', {0}}, {"ChenXB", 26, 't', {0}}}; for (int nCnt = 0; nCnt < 5; nCnt++) { if (per[nCnt].job == 's') { cout << "输入学生" << per[nCnt].name << "的成绩" << endl; cin >> per[nCnt].dep.score; } else { cout << "输入老师" << per[nCnt].name << "的考评等级" << endl; cin >> per[nCnt].dep.verifyGrade; } } cout << setw(10) << "姓名" << setw(5) << "年龄" << setw(10) << "人员类别" << setw(10) << "分数/等级" << endl; for (int nCnt = 0; nCnt < 5; nCnt++) { if (per[nCnt].job == 's') { cout << setw(10) << per[nCnt].name << setw(5) << per[nCnt].age; cout << setw(10) << per[nCnt].job << setw(10) << per[nCnt].dep.score << endl; } else { cout << setw(10) << per[nCnt].name << setw(5) << per[nCnt].age; cout << setw(10) << per[nCnt].job << setw(10) << per[nCnt].dep.verifyGrade << endl; } } return 0; }
-
共用体特点:
- 同一共用体内的成员共用一个存储区,存储区的大小等于成员占用字节长度的最大值;
- 在任一时刻,在一个共用体变量中只有一个成员起作用;
- 共用体类型中的成员类型可为任意已定义的数据类型;
5.3 枚举类型
-
枚举类型由若干个常量组成的有限集合,枚举是将所有可能的取值一一列举出来,主要适用于变量的值有限的情况;
-
枚举类型定义的语法格式:
enum <枚举类型名> { <枚举元素1> [=整型常量1], <枚举元素2> [=整型变量2], ..., <枚举元素n> [=整型变量n] };
-
强类型枚举一般声明格式:
enum class <枚举类型名> { <枚举元素1> [=整型常量1], <枚举元素2> [=整型变量2], ..., <枚举元素n> [=整型变量n] };
- 强作用域:强类型枚举成员的名称不会被输出到它所在父作用域的空间;
- 转换限制:强类型枚举成员的值不能与整型数值进行隐式转换;
- 可以指定底层类型:强类型枚举默认的底层类型为 i n t {\rm int} int,但可以显式地指定底层类型;
-
枚举变量可以进行算术运算、赋值运算、关系运算、逻辑运算等运算;
-
枚举类型使用实例 ( e x a m p l e 5 _ 5. c p p ) ({\rm example5\_5.cpp}) (example5_5.cpp):
/** * 作者:罗思维 * 时间:2023/10/24 * 描述:从键盘输入月份值,输出该月份属于哪个季节。 */ #include <iostream> using namespace std; int main() { // 定义枚举类型season,声明变量s; enum season { spring = 1, summer, autumn, winter } s; short month; cout << "请输入月份值(1-12):"; cin >> month; // 判断月份属于哪个季节; switch (month) { case 12: case 1: case 2: s = winter; break; case 3: case 4: case 5: s = spring; break; case 6: case 7: case 8: s = summer; break; case 9: case 10: case 11: s = autumn; break; default: exit(-1); } // 根据s值输出相应的季节; switch (s) { case spring: cout << "spring\n"; break; case summer: cout << "summer\n"; break; case autumn: cout << "autumn\n"; break; case winter: cout << "winter\n"; break; default: exit(-1); } return 0; }
5.4 类型定义
-
用户自定义类型说明符,即用户为数据类型取别名,类型定义语法格式如下:
typedef <类型名1> <类型名2>; // 类型名1:C++标准类型名或用户定义的类型名; // 类型名2:用户为<类型名1>起的别名; // 1.变量取别名 typedef float Float; float number1,number2; Float number1,number2; // 和float number1,number2;语句等价; // 2.结构体取别名 typedef struct { int studentID; char name[20]; int age; } STUDENT; STUDENT student[10]; // 用STUDENT声明了1个结构体数组student; // 3.数组取别名 typedef char ARRAY[10]; char arr[10]; ARRAY arr;
5.5 字符串
-
C {\rm C} C风格字符串处理
-
C {\rm C} C语言中没有专门的字符串类型,一般通过字符串数组来操作字符串;
-
s i z e o f ( ) {\rm sizeof()} sizeof()是操作符,用来返回类型的大小, s t r l e n ( ) {\rm strlen()} strlen()是函数,用来返回字符串的长度;
-
s i z e o f ( ) {\rm sizeof()} sizeof()在操作字符数组型字符串时,返回大大小包括字符串结束符"\ 0 0 0", s t r l e n ( ) {\rm strlen()} strlen()函数返回的字符串不包括字符串的结束符;
-
s i z e o f ( ) {\rm sizeof()} sizeof()和 s t r l e n ( ) {\rm strlen()} strlen()实例 ( e x a m p l e 5 _ 6. c p p ) ({\rm example5\_6.cpp}) (example5_6.cpp):
/** * 作者:罗思维 * 时间:2023/10/25 * 描述:sizeof()和strlen()计算字符数组的长度。 */ #include <iostream> #include <string.h> using namespace std; int main() { char str1[] = "Welcome to FUXI.AI."; cout << "sizeof(str1) = " << sizeof(str1) << endl; // 输出20 cout << "strlen(str) = " << strlen(str1) << endl; // 输出19 return 0; }
-
-
用指针操作字符串
-
指针指向字符数组型字符串实例 ( e x a m p l e 5 _ 7. c p p ) ({\rm example5\_7.cpp}) (example5_7.cpp):
/** * 作者:罗思维 * 时间:2023/10/25 * 描述:定义一个字符数组,用字符指针实现对字符串的遍历操作。 */ #include <iostream> using namespace std; int main() { char *p; char str[] = "Welcome to FUXI AI Technology."; p = str; // 指针指向字符数组型字符串; while (*p != '\0') { cout << *p; p++; } return 0; }
-
指针指向字符串常量实例 ( e x a m p l e 5 _ 8. c p p ) ({\rm example5\_8.cpp}) (example5_8.cpp):
/** * 作者:罗思维 * 时间:2023/10/25 * 描述:指针指向字符串常量实例。 */ #include <iostream> using namespace std; int main() { const char *p = "Welcome to FUXI AI Technology."; while (*p != '\0') { cout << *p; p++; } return 0; }
-
利用动态内存来操作字符串
-
如果字符串的长度和内容在运行期间才能确定,可以使用动态开辟内存的方式来存储和操作字符串;
// 1.定义动态字符串 char *p = new char[10]; // 2.当新开辟了内存单元后,内容不确定,最好利用memset()函数将内存单元初始化为0; memset(p,0,sizeof(char)*10);
-
利用动态内存操作字符串时,由于是动态开辟的内存,在使用结束后,需要释放该内存;
-
在动态内存被开辟后,要用 m e m s e t ( ) {\rm memset()} memset()函数将内存单元初始化为 0 0 0,否则会出现问题;
-
利用 s i z e o f ( ) {\rm sizeof()} sizeof()操作符无法返回动态字符串的长度,只能在开辟时确定其长度并记录;
-
字符串的指针不能轻易移动,动态内存不一定是连续的,移动指针会丢失对这个字符串的控制,在内存未消亡时,要有一个指针指向这个动态字符串;
// 1.字符串指针的错误移动实例 char *p = new char[len]; p++; // 错误移动
-
-
利用动态内存操作字符串实例
-
用字符串常量为指针指向动态申请的内存赋值( e x a m p l e 5 _ 9. c p p {\rm example5\_9.cpp} example5_9.cpp):
/** * 作者:罗思维 * 时间:2024/02/29 * 描述:用字符串常量为指针指向动态申请的内存赋值。 */ #include <iostream> #include <string.h> using namespace std; int main() { int len; cout << "输入字符串的长度:"; cin >> len; char *p = new char[len]; // 开辟字符数组; memset(p, 0, sizeof(char)*len); // 设置字符数组中的元素值为空; if (len >= 10) { strcpy(p, "Hello,Willard."); // 将字符串常量赋予指针指向的动态申请的内存; cout << p; // 输出动态内存中的内容; delete p; // 释放申请的动态内存; } return 0; }
-
动态开辟一个字符串,由键盘输入内容,并查找字符串中的大写字母且显示到屏幕上( e x a m p l e 5 _ 10. c p p {\rm example5\_10.cpp} example5_10.cpp):
/** * 作者:罗思维 * 时间:2024/02/29 * 描述:动态开辟一个字符串,由键盘输入内容,并查找字符串中的大写字母且显示到屏幕上。 */ #include <iostream> #include <string.h> using namespace std; int main() { int len; cout << "输入字符串的最大长度:"; cin >> len; char *p = new char[len + 1]; // 动态申请的字符串长度要比实际长度大1; memset(p, 0, sizeof(char) * (len + 1)); // 初始化申请的内存; cout << "输入字符串的内容:"; cin >> p; cout << "输入的字符串是:" << p << endl; cout << "其中大写字母有:"; char* pTemp = p; while (*pTemp != '\0') { // 用指针pTemp遍历字符串,p指针位置不变; if (isupper(*pTemp)) { // isupper函数判断是否为大写字母; cout << *pTemp; } pTemp++; } delete p; // 释放申请的动态资源; return 0; }
-
-
-
C {\rm C} C++字符串处理
-
C {\rm C} C++字符串的基本操作
// 1.使用字符串类型时,需要包含string头文件; #include <string> // 2.string类型的使用需要遵循"先定义后使用"的原则,定义格式: string 变量名; // 定义一个字符串变量; string 变量名 = "字符序列"; // 定义并对其初始化; // 3.声明一个字符串变量; string str; // 4.字符串的赋值; string str1,str2; // 定义两个字符串变量; str1 = "Hello Willard."; // 将字符串常量的值赋予变量; str2 = str1; // 字符串变量之间赋值; // 5.C++中,字符串是使用一维字符数组表示的,数组的每一个下标存储字符串的一个字符; // 和字符数组不一样的是,字符数组是在字符序列后自动添加"\0"作为结束符,字符串没有结束符,只保存字符序列;
-
s t r i n g {\rm string} string类的常用操作函数:
函数名 函数名 函数名 说明 说明 说明 c h a r & a t ( i n t n ) ; {\rm char\ \&at(int\ n)}; char &at(int n); 返回字符串第 n 个元素 返回字符串第{\rm n}个元素 返回字符串第n个元素 c o n s t c h a r ∗ d a t a ( ) c o n s t ; {\rm const\ char\ *data()const}; const char ∗data()const; 返回一个非 N U L L 终止的字符数组 返回一个非{\rm NULL}终止的字符数组 返回一个非NULL终止的字符数组 c o n s t c h a r ∗ c _ s t r ( ) c o n s t ; {\rm const\ char\ *c\_str()const}; const char ∗c_str()const; 返回一个以 N U L L 终止的字符数组 返回一个以{\rm NULL}终止的字符数组 返回一个以NULL终止的字符数组 i n t c a p a c i t y ( ) c o n s t ; {\rm int\ capacity()const}; int capacity()const; 返回当前容量 返回当前容量 返回当前容量 i n t m a x _ s i z e ( ) c o n s t ; {\rm int\ max\_size()const}; int max_size()const; 返回 s t r i n g 对象中的可存放的最大字符串的长度 返回{\rm string}对象中的可存放的最大字符串的长度 返回string对象中的可存放的最大字符串的长度 i n t s i z e ( ) c o n s t ; {\rm int\ size()const}; int size()const; 返回当前字符串的大小 返回当前字符串的大小 返回当前字符串的大小 i n t l e n g t h ( ) c o n s t ; {\rm int\ length()const;} int length()const; 返回当前字符串的长度 返回当前字符串的长度 返回当前字符串的长度 b o o l e m p t y ( ) c o n s t ; {\rm bool\ empty()const}; bool empty()const; 当前字符串是否为空 当前字符串是否为空 当前字符串是否为空 v o i d r e s i z e ( i n t l e n , c h a r c ) ; {\rm void\ resize(int\ len,char\ c)}; void resize(int len,char c); 把字符串当前大小置为 l e n , 并用字符 c 填充不足的部分 把字符串当前大小置为{\rm len},并用字符{\rm c}填充不足的部分 把字符串当前大小置为len,并用字符c填充不足的部分 s t r i n g & a s s i g n ( c o n s t c h a r ∗ s ) ; {\rm string\ \&assign(const\ char\ *s)}; string &assign(const char ∗s); 用 c h a r 类型字符串 s 赋值 用{\rm char}类型字符串{\rm s}赋值 用char类型字符串s赋值 s t r i n g & a s s i g n ( c o n s t c h a r ∗ s , i n t n ) ; {\rm string\ \&assign(const\ char*s,int\ n)}; string &assign(const char∗s,int n); 用 c h a r 类型字符串 s 开始的 n 个字符赋值 用{\rm char}类型字符串{\rm s}开始的{\rm n}个字符赋值 用char类型字符串s开始的n个字符赋值 s t r i n g & a s s i g n ( c o n s t s t r i n g & s ) ; {\rm string\ \&assign(const\ string\ \&s);} string &assign(const string &s); 把字符串 s 赋予当前字符串 把字符串{\rm s}赋予当前字符串 把字符串s赋予当前字符串 s t r i n g & a s s i g n ( i n t n , c h a r c ) ; {\rm string\ \&assign(int\ n,char\ c)}; string &assign(int n,char c); 将 n 个字符 c 赋予当前字符串 将{\rm n}个字符{\rm c}赋予当前字符串 将n个字符c赋予当前字符串 s t r i n g & a s s i g n ( c o n s t s t r i n g & s , i n t s t a r t , i n t n ) {\rm string\ \&assign(const\ string\ \&s,int\ start,int\ n)} string &assign(const string &s,int start,int n) 把 s 中从 s t a r t 开始的 n 个字符赋予当前字符串 把{\rm s}中从{\rm start}开始的{\rm n}个字符赋予当前字符串 把s中从start开始的n个字符赋予当前字符串 s t r i n g & a p p e n d ( i n t n , c h a r c ) ; {\rm string\ \&append(int\ n,char\ c)}; string &append(int n,char c); 在当前字符串结尾添加 n 个字符 c 在当前字符串结尾添加{\rm n}个字符{\rm c} 在当前字符串结尾添加n个字符c i n t c o m p a r e ( c o n s t s t r i n g & s ) c o n s t ; {\rm int\ compare(const\ string\ \&s)\ const}; int compare(const string &s) const; 比较当前字符串和 s 的大小 比较当前字符串和{\rm s}的大小 比较当前字符串和s的大小 i n t f i n d ( c h a r c , i n t p o s = 0 ) c o n s t ; {\rm int\ find(char\ c,int\ pos=0)\ const}; int find(char c,int pos=0) const; 从 p o s 开始查找字符 c 在当前字符串中的位置 从{\rm pos}开始查找字符{\rm c}在当前字符串中的位置 从pos开始查找字符c在当前字符串中的位置 i n t f i n d ( c o n s t c h a r ∗ s , i n t p o s = 0 ) c o n s t ; {\rm int\ find(const\ char\ *s,int\ pos=0)\ const}; int find(const char ∗s,int pos=0) const; 从 p o s 开始查找字符串 s 在当前字符串中的位置 从{\rm pos}开始查找字符串{\rm s}在当前字符串中的位置 从pos开始查找字符串s在当前字符串中的位置 i n t f i n d ( c o n s t c h a r ∗ s , i n t p o s , i n t n ) c o n s t ; {\rm int\ find(const\ char\ *s,int\ pos,int\ n)\ const}; int find(const char ∗s,int pos,int n) const; 从 p o s 开始查找字符串 s 中前 n 字符在当前字符串的位置 从{\rm pos}开始查找字符串{\rm s}中前{\rm n}字符在当前字符串的位置 从pos开始查找字符串s中前n字符在当前字符串的位置 i n t f i n d ( c o n s t s t r i n g & s , i n t p o s = 0 ) c o n s t ; {\rm int\ find(const\ string\ \&s,int\ pos=0)\ const}; int find(const string &s,int pos=0) const; 从 p o s 开始查找字符串 s 在当前字符串中的位置 从{\rm pos}开始查找字符串{\rm s}在当前字符串中的位置 从pos开始查找字符串s在当前字符串中的位置
-
-
常用的字符串操作函数
-
s t r c p y {\rm strcpy} strcpy函数( e x a m p l e 5 _ 11. c p p {\rm example5\_11.cpp} example5_11.cpp)。
// 1.函数原型: char * strcpy(char * destination,const char * source); // 2.函数功能:将字符串source赋予destination;
/** * 作者:罗思维 * 时间:2024/03/01 * 描述:strcpy函数的使用。 */ #include <iostream> #include <string.h> using namespace std; int main() { char str1[] = "Hello."; char str2[] = "Welcome to FUXI AI."; strcpy(str2, str1); cout << "str1 = " << str1 << endl; cout << "str2 = " << str2 << endl; return 0; }
-
s t r c a t {\rm strcat} strcat函数( e x a m p l e 5 _ 12. c p p {\rm example5\_12.cpp} example5_12.cpp)。
// 1.函数原型: char * strcat(char* target,char*source); // 2.函数功能:将字符串source连接在字符串target的后面。
/** * 作者:罗思维 * 时间:2024/03/01 * 描述:strcat函数的使用。 */ #include <iostream> #include <string.h> using namespace std; int main() { char str1[100] = "Hello Willard."; char str2[] = "Welcome to FUXI AI."; strcat(str1, str2); cout << "str1 = " << str1 << endl; cout << "str2 = " << str2 << endl; return 0; }
-
s t r c m p {\rm strcmp} strcmp函数( e x a m p l e 5 _ 13. c p p {\rm example5\_13.cpp} example5_13.cpp)。
// 1.函数原型: int strcmp(const char* str1,const char* str2); // 2.函数功能:将字符串str1和字符串str2做比较,将两个字符串按ASCII码值大小从左向右逐个字符进行比较, // 直到遇到不同的字符或结束,若str1大于str2,返回值大于0;若str1小于str2,返回值小于0; // 当两个字符串相等时,返回值为0;
/** * 作者:罗思维 * 时间:2024/03/01 * 描述:strcmp函数的使用。 */ #include <iostream> #include <string.h> using namespace std; int main() { char str1[] = "Hello Willard."; char str2[] = "Welcome to FUXI AI."; int flag; flag = strcmp(str2, str1); if (flag > 0) { cout << "str2 is greater than str1." << endl; } else if (flag < 0) { cout << "str2 is smaller than str1." << endl; } else { cout << "str2 is the same as str1." << endl; } return 0; }
-
s t r l e n {\rm strlen} strlen函数( e x a m p l e 5 _ 14. c p p {\rm example5\_14.cpp} example5_14.cpp)。
// 1.函数原型: size_t strlen(char* str); // 2.函数功能:size_t是int类型的别名,统计字符串str中字符的个数并返回; // 注:strlen函数计算字符串长度不包含"\0";
/** * 作者:罗思维 * 时间:2024/03/01 * 描述:strlen函数的使用。 */ #include <iostream> #include <string.h> using namespace std; int main() { char str1[] = "Welcome to FUXI AI."; int count; count = strlen(str1); cout << "The lenght of str1 is:" << count << endl; return 0; }
-
5.6 实战
5.6.1 实战1:简单的学生信息管理系统
项目需求: 编写学生信息管理系统,利用结构体来定义学生信息内容,其中包含学生学号、姓名、科目成绩,通过键盘输入学生信息并输出到屏幕上。
代码实现: ( p r o j e c t 5 _ 1. c p p {\rm project5\_1.cpp} project5_1.cpp)
/**
* 作者:罗思维
* 时间:2024/03/03
* 描述:编写简单学生信息管理系统。
*/
#include <iostream>
#include <iomanip>
#include <string>
using namespace std;
struct student {
int student_ID; // 学生学号;
string student_name; // 学生姓名;
float student_score[3]; // 学生分数;
float avg_score; // 平均分数;
student* next; // 指向student指针;
} stu[100], *p; // 定义结构体数组和指针;
void print_score(student* p) {
p->avg_score = (p->student_score[0] + p->student_score[1] + p->student_score[2]) / 3; // 计算平均分;
cout << setw(10) << p->student_name << setw(10) << p->student_ID << setw(10) << p->student_score[0];
cout << setw(10) << p->student_score[1] << setw(10) << p->student_score[2] << setw(10) << p->avg_score << endl;
}
using namespace std;
int main() {
int student_count; // 学生数量;
cout << "请输入学生数量:";
cin >> student_count;
for (int i = 0; i < student_count; i++) {
cout << "请输入学生" << i + 1 << "的信息:" << endl << "学号:";
cin >> stu[i].student_ID;
cout << "学生姓名:";
cin >> stu[i].student_name;
cout << "语文分数:";
cin >> stu[i].student_score[0];
cout << "数学分数:";
cin >> stu[i].student_score[1];
cout << "英语分数:";
cin >> stu[i].student_score[2];
}
for (int i = 0; i < student_count; i++) { // next指针指向下一个学生;
stu[i].next = &stu[i + 1];
}
stu[student_count - 1].next = NULL;
p = &stu[0]; // 当为最后一个学生时,将next指针赋为空;
cout << setw(10) << "学生姓名" << setw(10) << "学生学号" << setw(10) << "语文分数";
cout << setw(10) << "数学分数" << setw(10) << "英语分数" << setw(10) << "平均分" << endl;
do { // 遍历输出每个学生的信息;
print_score(p);
p = p->next; // 指向下一个学生;
} while (p != NULL);
return 0;
}
5.6.2 实战2:字符替换
项目需求: 输入三个字符串,将字符串 1 1 1中所有与字符串 2 2 2相同的字串替换成字符串 3 3 3,例如,输入的字符串 1 1 1为" w e r e r w C P P n i e h j e r C P P {\rm wererwCPPniehjerCPP} wererwCPPniehjerCPP“,字符串 2 2 2为” C P P {\rm CPP} CPP“,字符串 3 3 3为” N E W {\rm NEW} NEW",替换后,字符串 1 1 1为 w e r e r w N E W n i e h j e r N E W {\rm wererwNEWniehjerNEW} wererwNEWniehjerNEW。
代码实现: ( p r o j e c t 5 _ 2. c p p {\rm project5\_2.cpp} project5_2.cpp)
/**
* 作者:罗思维
* 时间:2024/03/03
* 描述:字符替换。
*/
#include <iostream>
using namespace std;
#define MAX_LEN 255
void replace(char chString[], char chOldWord[], char chNewWord[]) {
int i, nStartPos = 0, nLen1 = 0, nLen2 = 0, nLen3 = 0, nFound;
// 计算旧词和新词的长度;
while (chOldWord[nLen2++] != '\0'); // nLen2对应旧词长度;
nLen2--;
while (chNewWord[nLen3++] != '\0'); // nLen3对应新词长度;
nLen3--;
/* chString中可能有多个旧词,均要替换为新词,
利用循环向前移动查找位置,逐次进行比较和替换;
*/
while (chString[nStartPos] != '\0') {
/* 从nStartPos位置开始,判断nLen2长度的字符串是否与旧词相同。 */
nFound = 1;
for (i = 0; i < nLen2; i++) {
if (chString[nStartPos + i] != chOldWord[i]) {
nFound = 0;
break;
}
}
if (nFound == 1) { // 相同,这nLen2个字符需要被替换掉;
while (chString[nLen1++] != '\0');
nLen1--; // nLen1对应输入字符串的长度;
/*
新词、旧词长度可能不同,先将chString长度调至正确的位置,
chString中nStartPos后的字符可能需要前移或后移若干位;
*/
if (nLen3 - nLen2 >= 0) { // 新词比旧词长,从后向前移动;
for (i = nLen1 - 1; i >= nStartPos; i--) {
chString[i + nLen3 - nLen2] = chString[i];
}
} else { // 新词比旧词短,从前向后移动;
for (i = nStartPos + nLen2; i < nLen1; i++) {
chString[i + nLen3 - nLen2] = chString[i];
}
}
chString[nLen1 + nLen3 - nLen2] = '\0';
// 将新词复制到chString,替换原来的旧词;
for (i = 0; i < nLen3; i++) {
chString[nStartPos + i] = chNewWord[i];
}
// 下一次检查的位置,从替换后新词后面的位置开始;
nStartPos += nLen3;
} else {
nStartPos++;
}
}
}
int main() {
char chStr[MAX_LEN], chOld[MAX_LEN], chNew[MAX_LEN];
cout << "输入原始字符串:";
gets(chStr);
cout << "输入被替换字符串:";
gets(chOld);
cout << "输入替换字符串:";
gets(chNew);
replace(chStr, chOld, chNew);
cout << "替换后的字符串为:";
cout << chStr;
return 0;
}