C++知识整理day5容器——string容器

0.前置知识–STL简介

STL(standard template libaray-标准模板库):是C++标准库的重要组成部分,不仅是一个可复用的组件库,而且是一个包罗数据结构与算法的软件框架。
STL的六大组件:
在这里插入图片描述
我们之前在数据结构阶段学了很多,包括顺序表、链表、栈、队列、二叉树等等;在之后我们在做算法题时,需要用到哪个数据结构,靠我们手写是不太现实的,C++帮我们封装了很多的容器,本质上他们都是给我们实现好的一个个类,我们直接使用即可。当然我们也要学习他的底层,这是很重要的。
本节我们先来学习一下string类。这里有个小知识点,其实string类是不属于STL里的容器的。因为string类的出现是比容器早很多的,因为需要频繁使用字符串。所以string类在设计的时候,不是设计的很好。
在这里插入图片描述
string类的内容大概是这样,有size,也有capacity,当然里面有很多的成员方法。(其实里面也有buffer数组,了解一下)

1.为什么要学习string类?

C语言中,字符串是以’\0’结尾的一些字符的集合,为了操作方便,C标准库中提供了一些str系列的库函数,但是这些库函数与字符串是分离开的,不太符合OOP的思想,而且底层空间需要用户自己管理,稍不留神可能还会越界访问。比如说strcpy,我们必须有足够的空间让他来拷贝,他的空间大小是固定的,不想string,他的本质就是一个类,是可以自动扩容的。

2.auto关键字和范围for

2.1 auto关键字

  1. 使用auto修饰的变量,是具有自动存储器的局部变量,后来这个不重要了。C++11中,标准委员会变废为宝赋予了auto全新的含义即:auto不再是一个存储类型指示符,而是作为一个新的类型指示符来指示编译器,auto声明的变量必须由编译器在编译时期推导而得。

  2. 用auto声明指针类型时,用auto和auto*没有任何区别,但用auto声明引用类型时则必须加&
    在这里插入图片描述

  3. 当在同一行声明多个变量时,这些变量必须是相同的类型,否则编译器将会报错,因为编译器实际只对第一个类型进行推导,然后用推导出来的类型定义其他变量。
    在这里插入图片描述

  4. auto不能作为函数的参数,可以做返回值,但是建议谨慎使用
    在这里插入图片描述
    在这里插入图片描述

  5. auto不能直接用来声明数组
    在这里插入图片描述
    Q:写了类型本来就不费事,还要使用auto干什么?
    A:等到后面写容器迭代器的,就会很好用。

2.2 范围for

  1. 对于一个有范围的集合而言,由程序员来说明循环的范围是多余的,有时候还会容易犯错误。因此C++11中引入了基于范围的for循环。for循环后的括号由冒号“ :”分为两部分:第一部分是范围内用于迭代的变量,第二部分则表示被迭代的范围,自动迭代,自动取数据,自动判断结束。
  2. 范围for可以作用到数组和容器对象上进行遍历
  3. 范围for的底层很简单,容器遍历实际就是替换为迭代器,这个从汇编层也可以看到

示例:

int a[5] = {
    1, 2, 3, 4 ,5 };
	for (auto x : a)
	{
   
		cout << x << ' ';
	}
	cout << endl;

注意:上面我们写的是auto x : a 其底层是将数组a对应下标的值赋值给x,x只是一个临时拷贝的对象,改变x的值不会影响到数组a,我们若是想改变数组a的值,我们就需要使用引用的概念,示例:
在这里插入图片描述

3.string类常用的接口

推荐大家去C++的官网学习对应的接口:https://cplusplus.com/

3.1 string类对象常见的构造

构造函数名称 功能说明
string s 构造空的string类对象s,即空字符串
string(const string& s) 拷贝构造函数
string(const string& str, size_t pos, size_t len = npos) 从字符串str上,从下标pos开始拷贝npos个字符
string(const char* s) 用C-string来构造string类对象
string(size_t n, char c) string类对象中包含n个字符c
string (const char* s, size_t n) 从C-string中拷贝前n个字符

注:这里解释一下npos,npos默认值是-1,即拷贝到字符串str的末尾,当npos大于字符串长度时不会报错,会拷贝完这个字符串。npos是一个静态成员变量,他的类型是size_t。

示例:

string s1();//构造一个空的字符串
	string s2("hello world!");//用C-string来构造string对象
	string s3(s2);//拷贝构造
	string s4(s2, 6);//npos默认值是-1
	string s5("hello world", 5);//拷贝前五个字符
	string s6(5, 'x');
	cout << s1 << endl;
	cout << s2 << endl;
	cout << s3 << endl;
	cout << s4 << endl;
	cout << s5 << endl;
	cout << s6 << endl;

在这里插入图片描述

3.2 string类对象的访问

函数名称 功能说明
operator[pos] 返回pos位置的字符,即下标访问
at(pos) 返回pos位置的字符
back() 返回最后一个元素
front() 返回第一个元素

示例:

string s("hello world");
	for (int i = 0; i < s.size(); i++)
	{
   
		cout << s[i];
	}
	cout << endl;
	for (int i = 0; i < s.size(); i++)
	{
   
		cout << s.at(i);
	}
	cout << endl;

	cout << "s.front():" << s.front() << endl;
	cout << "s.back():" << s.back() << endl;

在这里插入图片描述
Q:使用下标[]和at()有什么区别吗?
A:对于访问字符串,如果越界了的话,[]会直接报错,终止程序运行,而at可以通过抛异常来解决,示例:

在这里插入图片描述
对于at()访问越界的字符串,我们只要通过捕异常就可以让程序继续运行。
在这里插入图片描述
而通过下标[]来获取越界的字符,会直接终止程序。

3.3 string类对象的遍历–迭代器

通过上面下标的方式也可以遍历字符串,这里我们主要讲解一下通过迭代器来遍历。

Q:既然下标可以遍历,为什么还要使用

### C++ 学生管理系统设计方案 #### 1. 系统模块划分 学生管理系统的开发可以分为多个模块来逐步实现。这些模块包括时间类 `Date` 的设计、学生类 `Student` 的定义、异常处理机制的引入,以及核心功能(如录入、显示、保存、查询、修改和删除)的设计。 #### 2. 时间类 `Date` 的设计 时间类用于存储学生的出生日期或其他与时间相关的属性。该类应具备验证输入的功能,确保日期的有效性。如果用户输入了非法日期,则通过抛出自定义异常提示错误并允许重新输入。 ```cpp #include <stdexcept> #include <iostream> class Date_Exception : public std::logic_error { public: explicit Date_Exception(const std::string& message) : logic_error(message) {} }; class Date { private: int year; int month; int day; bool isValid() const { if (month < 1 || month > 12) return false; // 检查月份范围 if (day < 1 || day > 31) return false; // 基本天数检查 // 更复杂的逻辑可在此处扩展,例如考虑闰年等特殊情况 return true; } public: Date(int y, int m, int d) : year(y), month(m), day(d) { if (!isValid()) throw Date_Exception("Invalid date input"); } }; ``` 上述代码展示了如何创建一个简单的 `Date` 类,并通过自定义异常 `Date_Exception` 来捕获非法输入的情况[^1]。 #### 3. 学生类 `Student` 的设计 学生类是整个系统的核心部分之一,它包含了学生的个人信息和其他相关数据成员。为了增强灵活性,可以在 `Student` 中嵌套使用之前定义好的 `Date` 对象作为其私有成员变量。 ```cpp class Student { private: int id; // 学号 std::string name;// 姓名 double score; // 成绩 Date birthdate; // 出生日期 public: Student(int i, const std::string& n, double s, int by, int bm, int bd) : id(i), name(n), score(s), birthdate(by, bm, bd) {} void displayInfo() const { std::cout << "ID: " << id << ", Name: " << name << ", Score: " << score << ", Birthdate: " << birthdate.getYear() << "-" << birthdate.getMonth() << "-" << birthdate.getDay() << "\n"; } }; ``` 此段代码实现了基本的学生信息结构及其展示方法。 #### 4. 功能模块实现 以下是几个主要功能的具体实现方式: ##### 数据录入 提供菜单让用户依次输入每位学生的各项资料,并将其存入容器中以便后续操作。 ##### 显示所有记录 遍历存储所有学生实例的数据集合并将它们逐一打印出来供查看。 ##### 文件读写支持 利用标准库中的文件流技术完成对学生档案持久化的支持——即能够将现有数据导出到外部文本文件当中去;同样也可以从指定路径加载已有备份回来继续编辑。 ##### 查询服务 按照特定条件查找符合条件的目标个体,比如依据唯一标识符“学号”快速定位某位同学的信息条目;或者是模糊匹配名字字段检索可能存在的候选者列表返回给调用方进一步确认选择哪一条才是真正想要的结果项等等不同形式的需求都可以满足得到妥善解决办法才行得通哦! ##### 修改/删除选项 当发现某些地方存在错误或者不再适用时就可以执行相应的更新动作覆盖旧版本的内容从而保持最新状态呈现于界面上面让使用者随时掌握最新的动态变化情况啦!同时也要记得给予足够的警告提示以防误删重要资源造成不可挽回的重大损失呢😊 --- ### 完整示例代码片段 下面给出了一段综合性的演示样例,涵盖了前面提到的部分关键概念和技术要点: ```cpp #include <vector> #include <algorithm> #include <fstream> std::vector<Student> students; void addStudent() { try { int id, year, month, day; std::string name; double score; std::cout << "Enter student ID: "; std::cin >> id; std::cout << "Enter student name: "; std::cin >> name; std::cout << "Enter student score: "; std::cin >> score; std::cout << "Enter birth year/month/day: "; std::cin >> year >> month >> day; students.emplace_back(id, name, score, year, month, day); std::cout << "Student added successfully.\n"; } catch (const Date_Exception& e) { std::cerr << e.what() << ". Please retry or exit this operation.\n"; } } // 其他函数省略... ``` ---
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值