C++基础5:自定义类型与字符串

news/2024/7/24 13:04:55 标签: c++, java, 算法

此专栏为移动机器人知识体系下的编程语言中的 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 chars,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;
}

http://www.niftyadmin.cn/n/5429839.html

相关文章

微信小程序--分享如何与ibeacon蓝牙信标建立联系

ibeacon蓝牙设备 iBeacon是苹果公司2013年9月发布的移动设备用OS&#xff08;iOS7&#xff09;上配备的新功能。其工作方式是&#xff0c;配备有 低功耗蓝牙&#xff08;BLE&#xff09;通信功能的设备使用BLE技术向周围发送自己特有的ID&#xff0c;接收到该ID的应用软件会根…

第六章二叉树——二叉树的最大深度

吾日三省吾身 还记得的梦想吗 正在努力实现它吗 可以坚持下去吗 目录 吾日三省吾身 力扣题号&#xff1a;104. 二叉树的最大深度 - 力扣&#xff08;LeetCode&#xff09; 题目描述&#xff1a; 思路 解法一&#xff1a;递归 实现思路 代码逻辑解释 注意事项 代码实现…

【论文笔记合集】LSTNet之循环跳跃连接

本文作者&#xff1a; slience_me LSTNet 循环跳跃连接 文章仅作为个人笔记 论文链接 文章原文 LSTNet [25] introduces convolutional neural networks (CNNs) with recurrent-skip connections to capture the short-term and long-term temporal patterns. LSTNet [25]引入…

Spring Cloud Gateway如何实现熔断

Spring Cloud Gateway熔断集成 熔断应用&#xff1a; 金融市场中的熔断机制&#xff1a;在金融交易系统中&#xff0c;熔断机制&#xff08;Circuit Breaker&#xff09;是一种市场保护措施&#xff0c;旨在预防市场剧烈波动时可能导致的系统性风险。当某个基准指数&#xff08…

多线程的介绍

一、多线程 1.多线程的常用方法 start&#xff08;&#xff09;&#xff1a;①启动线程②调用线程的run&#xff08;&#xff09; run&#xff08;&#xff09;&#xff1a;将线程要执行的操作声明在run&#xff08;&#xff09;中 currentThread&#xff08;&#xff09;&a…

RuoYi-Vue使用RestTemplate无法通过@Autowired注入报错

A component required a bean of type org.springframework.web.client.RestTemplate that could not be found. 解决方法&#xff1a; 将ruoyi-framework模块下找到ApplicationConfig这个配置类使用Bean注入&#xff1a; /*** RestTemplate配置*/Beanpublic RestTemplate r…

通透!从头到脚讲明白线程锁

线程锁在分布式应用中是重中之重&#xff0c;当谈论线程锁时&#xff0c;通常指的是在多线程编程中使用的同步机制&#xff0c;它可以确保在同一时刻只有一个线程能够访问共享资源&#xff0c;从而避免竞争条件和数据不一致性问题。 在 Java 中&#xff0c;有多种方式可以实现…

mysql数据库:使用 bash脚本 + 定时任务 自动备份数据

mysql数据库&#xff1a;使用 bash脚本 定时任务 自动备份数据 1、前言2、为什么需要自动化备份&#xff1f;3、编写备份脚本4、备份脚本授权5、添加定时任务6、重启 crond / 检查 crond 服务状态7、备份文件检查 &#x1f496;The Begin&#x1f496;点点关注&#xff0c;收藏…