数组
目录:
- 数组
- 一维数组
- 一维数组的定义和初始化
- 一维数组数据元素的访问
- 练习1 找小猪
- 练习2 算平均值
- 比较两个数组是否相等
- 一维数组冒泡法排序
- 一维数组操作
- 一维数组查找元素
- **普通查找**:
- 二分查找:
- 二分查找 最小下标
- 最大下标
- 查找元素个数
- 一维数组修改元素
- 通过下标直接修改
- 先查找,再修改
- 一维数组添加元素
- 一维数组删除元素
- 一维数组的合并
- 无需合并
- 有序合并
- 练习
- 字符数组
- 字符数组的操作
- 字符串到数值类型的转换
- 字符检查
- 练习
- 字符串string
- c++中的string类
- string类几种常见的构造函数
- 构造函数
- string的常用操作
- 获取string对象的长度
- 复制string对象
- string 对象的拼接和附加
- 使用 + 操作符拼接两个字符
- 使用 += 操作符在字符串后面附加内容
- 使用 string.append() 函数
- 使用 string.push_back() 函数
- string对象的比较
- 使用string.substr()函数来获取子串
- 访问 string字符串的元素
- string 对象的查找操作
- 使用string.find()方法查找字符
- string.rfind()
- string.find_first_of()
- string.find_last_of()
- string.find_first_not_of()
- string.find_last_not_of()
- string对象的插入操作
- string对象的删除操作
- 判断字符串是否为空
- 使用 swap 函数交换两个字符
- 字符串替换
- 字符串反转
- 练习
- 综合案例 自动点餐系统
一维数组
一维数组的定义和初始化
定义数组
- 数据类型 数组名[数组长度]
int arr_num[5]
- 数据类型 数组名[数组长度] = {数据1,数据2,…}
int arr_num2[5] ={1,2,3,4,5};
数组名
- 只能由字母、数字和下划线组合,但数字不能开头
- 系统关键字不能作为数组名
- 同一作用域下不能重名
- 见其名知其意
数组初始化
int ar2[5] = {10,20};
int ar3[5] = {};
int ar4[] = {1,2,3,4,5};
编译器根据元素个数计算出长度
数组长度
- 整形常量
- 整形常变量
- #define
#define N 100
- const
const int N = 100; int N=100;
- #define
一维数组数据元素的访问
访问数组的元素,使用中括号,即 [] 加上数组索引即可。 但是需要注意的是,C++ 数组的索引是从 0 开始的
语法 : 数组名[索引];
循环遍历
int arr[5] = {1,2,3,4,5};
for(int i: arr){
cout << i << “ “;
}
循环赋值
int arr[5] = {1,2,3,4,5};
for(int i=0; i<5; i++){
cin >> arr[i] ;
}
练习1 找小猪
现有五只小猪,体重分别为764,942,613,476,940。定义一个一维数组,存放五只小猪的体重,找出其中最重的小猪,并打印输出
const int N = 5;
int arr[N];
for (int i = 0; i < N; i++)
{
cin >> arr[i];
}
int max_weight = arr[0];
for (int i = 0; i < N; i++)
{
if (arr[i] > max_weight) {
max_weight = arr[i];
}
}
cout << max_weight << endl
练习2 算平均值
输入n(n<=100)个数保存到数组中,求n个数的和以及平均值
int arr[100], n;
cin >> n;
for (int i = 0; i < n; i++)
{
cin >> arr[i];
}
int sum = 0;
for (int i = 0; i < n; i++)
{
sum += arr[i];
}
cout << sum << endl <<
比较两个数组是否相等
不能直接使用==运算符与两个数组名称来确定数组是否相等
int arr1[5] = { 11, 13, 50, 72, 91 };
int arr2[5] = { 11, 13, 50, 72, 91 };
int arr1Count = sizeof(arr1) / sizeof(arr1[0]);
int arr2Count = sizeof(arr2) / sizeof(arr2[0]);
if (arr1Count != arr2Count)
{
cout << "arr1 != arr2" << endl;
return 0;
}
else if(arr1Count==arr2Count)
{
for (int i = 0; i < arr1Count; i++)
{
if (arr1[i] != arr2[i])
{
cout << "arr1 != arr2" << endl;
return 0;
}
}
}
else
{
cout << "arr1== arr2" << endl;
}
一维数组冒泡法排序
-
比较相邻的元素。如果第一个比第二个大,就交换他们两个。
-
对每一对相邻元素做同样的工作,执行完毕后,找到第一个最大值。
-
重复以上的步骤,每次比较次数-1,直到不需要比较。
int arr[N]={8,7,6,5,3};
// 趟数
for(int i=0;i<N-1;i++)
{
//比较次数
for(int j=0;j<N-i-1;j++)
{
if(arr[j]>arr[j+1])
{
swap(arr[j],arr[j+1]);
}
}
}
for(int i=0;i<N;i++)
{
cout<<arr[i]<<" ";
}
优化版 : 增加标记变量
int arr[N]={8,7,6,5,3};
bool flag = ture;
// 趟数
for(int i=0;i<N-1;i++)
{
//比较次数
flag=ture;
for (int j = 0; j < N - i - 1; j++)
{
if (arr[j] > arr[j + 1])
{
swap(arr[j], arr[j + 1]);
flag = false;
}
}
if(falg)break;
}
一维数组操作
一维数组查找元素
普通查找:
根据值顺序查找
比如在给定数组中查找固定的某个值,就可以从下标为0的元素开始顺序对比查找
案例:
在长度为N(N<=100)的数组中,输入m个元素,查找k元素第一次 出现的位置(位置从1开始),如果找不到k,输出-1
输入案例:
5
1 3 5 6 3
3
输出案例:
2
const int N = 100;//数组长度
int arr[N],m,k,index = -1;
cin >> m;
for(int i=0; i<m; i++){
cin >> arr[i];
}
cin >> k;
for(int i=0; i<m;i++){ //顺序查找
if(k == arr[i]){
index = i + 1;
break;
}
}
cout << index << endl
二分查找:
二分查找也称折半查找(Binary Search),是一种效率较高的查找方 法。
注意点:
- 用于查找的内容逻辑上来说是需要有序的
- 查找的数量只能是一个,而不是多个
int const N = 100; //数组长度
int arr[N]; //声明数组
int m, k; //m元素个数,k查找的元素
cin >> m;
for (int i = 0; i < m; i++) {
cin >> arr[i];
}
cin >> k;
//left起始下标,right最大下标,mid保存中间下标
int left = 0, right = m - 1, mid = 0;
while (left <= right) { //当left小于等于right时查找
mid = (left + right) / 2; //计算中间值mid
if (k == arr[mid]) //查找到k
{
cout << mid + 1 << endl;
break;
}
else if (k < arr[mid]) { //小于的情况,right挪到mid-1
right = mid - 1;
}
else if (k > arr[mid]) { //大于的情况,left挪到mid+1
left = mid + 1;
}
}
if (left > right) //当left <right ,k元素不在数组中
{
cout << -1 << endl;
}
如果需要查找的元素不止一个,怎么办?
二分查找 最小下标
在数组长度为N(N<=100)的数组中,输入m个元素(有序),查找 k元素的最小位置(位置从1开始),如果找不到k,输出-1.
案例输入:
10
11 22 22 22 22 22 22 33 44 55
22
案例输出:
2
if (k == arr[mid]) //查找到k
{
int index = mid;
//使用while往左查找最小下标
while (index >= 0 && arr[index] == k) {
index--;
}
cout << index + 1 << endl;
break;
}
最大下标
if (k == arr[mid]) //查找到k
{
int index = mid;
//使用while往右查找最大下标
while (index <= m -1 && arr[index] == k) {
index++;
}
cout << index + 1 << endl;
break;
}
查找元素个数
在一个有序数组中,相同元素一定是挨着的,所以,只要找到这个元素,在左右寻找,记录个数即可
mid = (left + right) / 2; //计算中间值mid
if (k == arr[mid]) //查找到k
{
int index1 = mid-1,index2 = mid+1;
count = 1;
while (index1 >= 0 && arr[index1] == k) {//扫描左边
index1--;
count++;
}
while (index2 <= m-1 && arr[index2] == k){//扫描右边
index2++;
count++;
}break;
一维数组修改元素
通过下标直接修改
找到对应下标修改
先查找,再修改
根据要求找到对应下标,在进行修改
在一次100百米跑比赛中,有n(5<= n <= 10)个同学进行比赛,输入这n个同学的比赛成绩,把第一名和最后一名的同学的位置进行交换,在输出比赛成绩。
输入用例:
5
10.3 9.8 10.6 9.9 11
输出用例:
10.3 11 10.6 9.9 9.8
double arrScore[20];
int n;
cin >> n;
for (int i = 0; i < n; i++) {
cin >> arrScore[i];
}
double first = arrScore[0], last = arrScore[0];
int first_index = 0, last_index = 0;
for (int i = 0; i < n; i++) {
if (arrScore[i] < first) {
first = arrScore[i];
first_index = i;
}
if (arrScore[i] > last) {
last = arrScore[i];
last_index = i;
}
}
swap(arrScore[first_index], arrScore[last_index]);
for (int i = 0; i < n; i++) {
cout << arrScore[i] << " ";
}
一维数组添加元素
int arr[100];
int n, k, p, m;
cin >> n;
for (int i = 0; i < n; i++)
{
cin >> arr[i];
}
cin >> k;
cin >> p >> m;
int index = n - 1;
if (p) {
while (index >= m - 1)
{
arr[index + 1] = arr[index];
index--;
}
arr[m-1] = k;
}
else {
while (index > m -1)
{
arr[index + 1] = arr[index];
index--;
}
arr[m] = k;
}
for (int i = 0; i < (n + 1); i++) {
cout << arr[i] << " ";
}
一维数组删除元素
int n;
int arr[100];
cin >> n;
for (int i = 0; i < n; i++)
{
cin >> arr[i];
}
int index = -1;
for (int i = 0; i < n; i++)
{
if (arr[i] < 0) {
index = i;
break;
}
}
while (index < n -1)
{
arr[index] = arr[index + 1];
index++;
}
for (int i = 0; i < n -1; i++)
{
cout << arr[i] << " ";
}
一维数组的合并
无需合并
给定两个数组arr1和arr2,数组长度不超过100,合并成arr3.
int n1,n2, arr1[100], arr2[100], arr3[200];
cin >> n1;
for (int i = 0; i < n1; i++) {
cin >> arr1[i];
}
cin >> n2;
for (int i = 0; i < n2; i++) {
cin >> arr2[i];
}
for (int i = 0; i < n1; i++) {
arr3[i] = arr1[i];
}
int index = 0;
for (int i = n1; i < n1 + n2; i++) {
arr3[i] = arr2[index ++];
}
for (int i = 0; i < n1 + n2; i++) {
cout << arr3[i] << " ";
}
有序合并
一般合并之后的数组是有序的
int n1, n2, arr1[100], arr2[100], arr3[200];
cin >> n1;
for (int i = 0; i < n1; i++)
{
cin >> arr1[i];
}
cin >> n2;
for (int i = 0; i < n2; i++)
{
cin >> arr2[i];
}
int index = 0,i=0,j=0;
for (; i < n1 && j < n2;)
{
if (arr1[i] < arr2[j])
{
arr3[index++] = arr1[i++];
}
else if (arr1[i] > arr2[j])
{
arr3[index++] = arr2[j++];
}
else
{
arr3[index++] = arr2[j++];
i++;
}
}
while (i < n1)
{
arr3[index++] = arr1[i++];
}
while (j < n2)
{
arr3[index++] = arr2[j++];
}
for (int i = 0; i < index; i++)
{
cout << arr3[i] << " ";
}
练习
定义一个int型的一维数组,包含10个元素,分别赋值为1~10, .然后 将数组中的元素都向前移一个位置, 即a[0]=a[1],a[1]=a[2]…最后一 个元素的值是原来第一个元素的值,然后输出这个数组。
int arr[10];
for (int i = 0; i < 10; i++)
{
cin >> arr[i];
}
int temp = arr[0];
for (int i = 0; i < 9; i++)
{
arr[i] = arr[i + 1];
}
arr[9] = temp;
for (int i = 0; i < 10; i++)
{
cout << arr[i] << " ";
}
字符数组
C++ 中的字符数组,是用来存放一连串 字符 的 数组,C++ 的字符数组使用与其他数组基本相同,但初始化时,可以直接使用字符串进行初始化。其实就是C语言风格的字符串
字符和字符串的区别
char 是字符,也是 0~127 的无符号整数。通常能用一个 char 表示 的被称为 ASCII 编码。
字符串是以 NULL 结尾的连续地址。日常生活中常用转义字符 ‘\0’ 表示
字符数组的地址
cout在遇到char数组时,会输出整个字符串,直到遇到‘\0’ ,所以就算是普通的char单个字符地址,我们也需要(void*)
来强转他的类型
void 被翻译为"无类型";void * 为"无类型指针" 一般被称为通用指针或叫泛指针
字符数组的输入输出
字符数组输入时最好不要用cin,因为cin默认遇到空格和回车会结束
所以字符数组的输入用:
char arrc[100];
gets(arrc);
到\n截止
puts(arrc);
到‘\0’结束
字符数组的操作
添加头文件#include<csrting>
strlen(p)
) 取字符串长度
strcpy(p,p1)
复制字符串
strncpy(p,p1,n)
复制指定长度字符串
strcat(p,p1)
附加字符串
strncat(p,p1,n)
附加指定长度字符串
…
-
strlen(字符数组名)
返回字符数组的元素个数;终止‘\0’不算在内
-
strcpy(字符串1,字符串2)
将字符串2复制到字符串1,返回字符串1的值。
-
strncpy(字符串1,字符串2,长度n);
将字符串2前n个字符复制到字符串1,返回字符串1的值。
-
strcmp(字符串1,字符串2);
以ASCII码来比较字符串1和字符串2的大小。
字符串1 大于字符串2 返回1
字符串1 等于字符串2 返回0
字符串1 小于字符串2 返回-1
-
strncmp(字符串名1,字符串名2,长度n);
对字符串1和字符串2的前n个字符进行比较
-
stricmp(字符串名1,字符串名2); windows
-
strcasecmp(字符串名1,字符串名2); macos/linu
不区分大小写比较字符串1和字符串2的大小,比较的结果由函数返 回值带回。
-
strcat(字符串名1,字符串名2);
将字符串2拼接到字符串1后(返回字符串1的值)
-
strncat(字符串名1,字符串名2,n);
将字符串2前n个字符连接到字符串1后边(返回字符串1的值)
-
strchr(字符串, c) 在字符串中查找指定字符
-
strrchr(字符串, c) 在字符串中反向查找
返回一个指向该字符串中第一次出现的字符的指针,如果字符串中 不包含该字符则返回NULL空指针。
-
strlwr(字符串名) 将字符串中大写字母换成小写字母
-
strupr(字符串名) 将字符串中小写字母换成大写字母
-
memset(字符串名,初始化值,初始化字节数);
将某一块内存中的内容全部设置为指定的值
字符串到数值类型的转换
- atoi§ 字符串转换到 int 整型
- atof§ 字符串转换到 double 符点数
- atol§ 字符串转换到 long 整型
字符检查
#include
isalpha() 检查是否为字母字符
isupper() 检查是否为大写字母字符
islower() 检查是否为小写字母字符
isdigit() 检查是否为数字
isxdigit() 检查是否为十六进制数字表示的有效字符
isspace() 检查是否为空格类型字符
iscntrl() 检查是否为控制字符
ispunct() 检查是否为标点符号
isalnum() 检查是否为字母和数字
isprint() 检查是否是可打印字符
isgraph() 检查是否是图形字符,等效于 isalnum() | ispunct(
练习
统计数字字符个数
描述输入一行字符,统计出其中数字字符的个数。
输入格式:一行字符串,总长度小于255。
输出格式:输出为1行,输出字符串里面数字字符的个数。
样例输入: dream abc jlje 2022.
样例输出: 4
gets(str);
int n=strlen(str),cnt=0;
for(int i=0;i<n;i++)
{
/**/
if(isdigit(str[i]))
{
cnt++;
}
/**/
if(str[i]>='0'&&str[i]<='9')
{
cnt++;
}
}
cout<<cnt;
字符串string
c++中的string类
C++ 标准库提供了 string 类类型,支持上述所有的操作,另外还增加了其他更多的功能。我们将学习 C++ 标准库中的这个类,现在让 我们先来看看下面这个实例:
#include <iostream>
#include <string>
using namespace std;
int main ()
{
string str1 = "Hello";
string str2 = "World";
string str3;
int len ;
// 复制 str1 到 str3
str3 = str1;
cout << "str3 : " << str3 << endl;
// 连接 str1 和 str2
str3 = str1 + str2;
cout << "str1 + str2 : " << str3 << endl;
// 连接后,str3 的总长度
len = str3.size();
cout << "str3.size() : " << len << endl;
return 0;
}
str3 : Hello
str1 + str2 : HelloWorld
str3.size() : 1
现在您可能还无法透彻地理解这个实例,因为到目前为止我们还没 有讨论类和对象。所以现在您可以只是粗略地看下这个实例,等理解了面向对象的概念之后再回头来理解这个实例。
C++ 中提供了专门的头文件 string(注意不是 string.h,这个是 C 风 格字符串相关函数的头文件),来支持 string 类型。string 类定义 隐藏了字符串的数组性质,让我们可以像处理普通变量那样处理字 符串。string 对象和字符数组之间的主要区别是:可以将 string 对 象声明为简单变量,而不是数组。
string类几种常见的构造函数
构造函数
- string(const char *s) :将 string 对象初始化为 s 指向的字符串
string str(“Hello!”);
- string(size_type n,char c) :创建一个包含 n 个元素的 string 对象,其中每个元素都被初始化为字符 c
string str(10,‘a’)
- string(const string &str) :将一个 string 对象初始化为 string 对象 str(复制构造函数
string str1(“hello!”);
string str2(str1);
- string() :创建一个默认的 string 对象,长度为 0(默认构造函数)
string str; // 创建一个空的 string 对象
string 类的设计允许程序自动处理 string 的大小,因此,上述代码创建了一个长度为 0 的string 对象,但是向 str 中写入数据时,程序会自动调整 str 的长度。因此,与使用数组相比,使用 string 对象更方便,也更安全
string的常用操作
获取string对象的长度
在 C 语言中,使用 strlen 函数获取字符串的长度。在 C++ 中,可以使用 string.size() 函数或 string.length() 函数来获得 string 对象的长度。
string str(“Hello,World!”);
- str.length();
- str.size();
这两个方法是完全一样的,并没有区别。length() 方法是 C 语言习惯保留的,size() 方法则是为了兼容 STL 容器而引入的。
复制string对象
在 C 语言中,使用 strcpy、strncpy 函数来实现字符串的复制。在 C++ 中则方便很多,可以直接将一个string 对象赋值给另一个 string 对象,即
string str1(“Hello,World!”);
string str2;
str2 = str1;
由于 string 类会自动调整对象的大小,因此不需要担心目标数组不够大的问题。
string 对象的拼接和附加
在 C 语言中,使用 strcat、strncat 函数来进行字符串拼接操作。在 C++ 中也有多种方法来实现字符串拼接和附加操作:
使用 + 操作符拼接两个字符
string str1("hello ");
string str2("world!");
string str3 = str1 + str2;
使用 += 操作符在字符串后面附加内容
可以使用 += 来在一个 string 对象后面附加一个 string 对象、字符以及 C 风格的字符串:
string str1("hello ");
string str2("world!\n");
str1 += str2;
str1 += "nice job\n";
str1 += 'a';
使用 string.append() 函数
可以使用 string.append() 函数来在一个 string 对象后面附加一个 string 对象或 C风格的字符串:
string str1 ="hello,world!";
string str2 ="HELLO,WORLD!";
str1.append(str2);
str1.append("C string")
使用 string.push_back() 函数
可以使用 string.push_back() 函数来在一个 string 对象后面附加一个字符串:
string str("Hello");
str.push_back(“abc”);
string对象的比较
在 C 语言中,使用 strcmp、strncmp 函数来进行字符串的比较。在 C++ 中,由于将 string 对象声明为了 简单变量,故而对字符串的比较操作十分简单了,直接使用关系运算符(==、!=、<、<=、>、>=)即可:
string str1("hello");
string str2("hello");
if (str1 == str2)
cout << "str1 = str2" << endl;
else if (str1 < str2)
cout << "str1 < str2" << endl;
else
cout << "str1 > str2" <<endl;
使用类似 strcmp 的函数来进行 string 对象的比较,string 类提供的是 string.compare() 方法,函数原型如下
int compare(const string&str) const;
int compare(size_t pos,size_t len,const string&str)const;
int compare(size_t pos,size_t len,const string&str, size_t subpos,size_t sublen)const;
int compare(const char * s)const;
int compare(size_t pos,size_t len,const char * s)const;
int compare(size_t pos,size_t len,const char * s,size_t n)const;
compare 方法的返回值如下
1)返回 0,表示相等;
2)返回结果小于 0,表示比较字符串中第一个不匹配的字符比源字符串小,或者所有字符都匹配但是比较字符串比源字符串短;
3)返回结果大于 0,表示比较字符串中第一个不匹配的字符比源字符串大,或者所有字符都匹配但是比较字符串比源字符串长。
string str1 ("aBcdef");
string str2 ("AbcdEf");
string str3 ("123456");
string str4 ("123dfg");
//下面是各种比较方法
int m=str1.compare (str2); //完整的A和B的比较
int n=str1.compare(1,5,str2); //"Bcdef"和"AbcdEf"比较
int p=str1.compare(1,5,str2,4,2); //"Bcdef"和"Ef"比较
int q=str3.compare(0,3,str4,0,3); //"123"和"123"比较
使用string.substr()函数来获取子串
可以使用 string.substr() 函数来获取子串,string.substr() 函数的定义如下:
string substr(size_t pos = 0,size_t len = npos)const;
其中,pos 是子字符串的起始位置(索引,第一个字符的索引为 0),len 是子串的长度。这个函数的功能是: 复制一个 string 对象中从 pos 处开始的 len 个字符到 string 对象 substr 中去,并返回 substr。
string str("Hello,World!");
string subStr = str.substr(3,5);//从第三个字符开始,截取5个字符
cout << subStr << endl;
这段代码的输出结果为:“lo,Wo”。
访问 string字符串的元素
可以像 C 语言中一样,将 string 对象当做一个数组,然后使用数组下标的方式来访问字符串中的元素; 也可以使用 string.at(index) 的方式来访问元素(索引号从 0 开始):
string str("Hello,World!");
cout << str[1] << endl; // 使用数组下标的方式访问 string 字符串的元素
cout << str.at(1) << endl; // 使用 at 索引访问 string
string 对象的查找操作
使用string.find()方法查找字符
npos==-1
find方法的函数原形如下:
- 从字符串的pos位置开始(若不指定pos的值,则默认从索引0处开始),查找字符串str。如果找到,则返该字符串首次出现时其首字符的索引;否则,返回string::npos:
size_type find (const string& str, size_type pos
- 从字符串的 pos 位置开始(若不指定 pos 的值,则默认从索引 0 处开始),查找子字符串 s。如果找到,则返回 该子字符串首次出现时其首字符的索引;否则,返回 string::npos:
size_type find (const char *s, size_type pos = 0) const;
- 3)从字符串的 pos 位置开始(若不指定 pos 的值,则默认从索引 0 处开始),查找 s 的前 n 个字符组成的子字符串。 如果找到,则返回该子字符串首次出现时其首字符的索引;否则,返回 string::npos:
size_type find (const char *s, size_type pos, size_type n);
- 从字符串的 pos 位置开始(若不指定 pos 的值,则默认从索引 0 处开始),查找字符 ch 。如果找到,则返回该 字符首次出现的位置;否则,返回 string::npos:
size_type find (char ch, size_type pos = 0) const;
string.rfind()
string.rfind() 与 string.find() 方法类似,只是查找顺序不一样, string.rfind() 是从指定位置 pos (默认为字符串末尾)开始向前查找,直到字符串的首部,并返回第一次查找到匹配项时匹 配项首字符的索引。换句话说,就是查找子字符串或字符最后一次出现的位置。
string.find_first_of()
string.find_first_of() 方法在字符串中从指定位置开始向后(默认为索引 0 处)查找参数中任何一个字符 首次出现的位置。
string str("catjldkjfellmlm");
int pos = str.find_first_of("gat");
if (pos == string::npos) {
printf("没有匹配到\n");
return 0;
}
else
cout << "在索引 " << pos << " 处匹配到"
程序输出结果是:在索引 1 处匹配到。所查找的字符串 gat 中,第一次出现在字符串 str 中的字符是 ‘a’ , 该字符在 str 中的索引是 1.
string.find_last_of()
string.find_last_of() 方法在字符串中查找参数中任何一个字符最后一次出现的位置(也就 是从指定位置开始往前查找,第一个出现的位置)。
string.find_first_not_of()
string.find_first_not_of() 方法在字符串中查找第一个不包含在参数中的字符。
string.find_last_not_of()
string.find_last_not_of() 方法在字符串中查找最后一个不包含在参数中的字符(从指定位 置开始往前查找,第一个不包含在参数中的字符)。
string对象的插入操作
使用string.insert()进行插入操作,函数原型如下:
string&insert(size_t pos,const string&str); // 在位置 pos 处插入字符串 str
string&insert(size_t pos,const string&str,size_t subpos,size_t sublen); // 在位置 pos 处插入字符
串 str 的从位置 subpos 处开始的 sublen 个字符
string&insert(size_t pos,const char * s); // 在位置 pos 处插入字符串 s
string&insert(size_t pos,const char * s,size_t n); // 在位置 pos 处插入字符串 s 的前 n 个字符
string&insert(size_t pos,size_t n,char c); // 在位置 pos 处插入 n 个字符 c
iterator insert (const_iterator p, size_t n, char c); // 在 p 处插入 n 个字符 c,并返回插入后迭代器的位置
iterator insert (const_iterator p, char c); // 在 p 处插入字符 c,并返回插入后迭代器的位置
案例
string str("abcdefgh");
str.insert(1,
"test"); // 在位置 1 处插入字符串 "test"
cout << str << endl;
str.insert(10, 5,
'H'); // 在位置 10 处插入 5 个字符 'H'
cout << str << endl;
string对象的删除操作
使用 string.erase() 进行元素删除操作
函数原型如下:
string& erase (size_t pos = 0, size_t len = npos); // 删除从 pos 处开始的 n 个字符
iterator erase (const_iterator p); // 删除 p 处的一个字符,并返回删除后迭代器的位置
iterator erase (const_iterator first, const_iterator last); // 删除从 first 到 last 之间的字符,并返回删除后迭代器的位置
判断字符串是否为空
使用 empty() 函数判断字符串是否为空
string str;
if(str.empty()){
cout << "字符串为空" << endl;
}
使用 swap 函数交换两个字符
string str1 ="abc";
string str2 ="hjkui";
str1.swap(str2);
或
swap(str1,str2);
cout << str1 << endl;
cout << str2 << endl;
字符串替换
string &replace(int p0, int n0,const char *s);
//删除从p0开始的n0个字符,然后在p0处插入串s
string &replace(int p0, int n0,const char *s, int n);
//删除p0开始的n0个字符,然后在p0处插入字符串s的前n个字符
string &replace(int p0, int n0,const string &s);
//删除从p0开始的n0个字符,然后在p0处插入串s
string &replace(int p0, int n0,const string &s, int pos, int n);
//删除p0开始的n0个字符,然后在p0处插入串s中从pos开始的n个字符
string &replace(int p0, int n0,int n, char c);
//删除p0开始的n0个字符,然后在p0处插入n个字符c
案例
string s1 ="abcedfghijklmn";
s1.replace(1, 3,"HK");
cout << s1 << endl; //aHKdfghijklmn
string s2 ="abcedfghijklmn";
s2.replace(2, 1,"qwerty", 5);
cout << s2 << endl; //abqwertedfghijklmn
string s3 ="hjkbnm";
s3.replace(1,2,3,'a');
cout << s3 << endl; //haaabnm
字符串反转
使用algorithm 头文件里面的reverse函数
#include <iostream>
#include <algorithm>
using namespace std;
int main() {
string s1;
cin >> s1;
reverse(s1.begin(), s1.end());
cout << s1 << endl;
return 0;
}
输入:abc
输出:cba
练习
从键字输入一个字符串(由英文字母组成),将该字符串中所有的字母改成 该字母的下一个字母,如b改成c,字母z改为a要求,大小写不变。
#include <iostream>
using namespace std;
int main() {
string s1,s2;
cin >> s1;
int n=s1.length();
for(int i=0;i<n;i++)
{
if(s1.at(i)=='z')
{
s2+='a';
}
else
{
s2+=s1.at(i)+1;
}
}
cout<<s2<<endl;
return 0;
}
给定一个字符串 s ,找到 它的第一个不重复的字符,并返回它的索引 。如果 不存在,则返回 -1
输入用例:abccga
输出用例:1
#include <iostream>
using namespace std;
int main() {
string s1;
cin>>s1;
int n=s1.length();
int cnt[26]={0};
for(int i=0;i<n;i++)
{
cnt[s1[i]-'a']++;
}
for(int i=0;i<n;i++)
{
if(cnt[s1[i]-'a']==1)
{
cout<<i<<endl;
return 0;
}
}
return -1;
}
综合案例 自动点餐系统
- 打印菜单
- 单点
- 套餐
- 结账
打印菜单
打印出来的显示界面
单点
进入系统后,会提示用户,选择单点,套餐,还是结账
套餐
套餐有两种,套餐A和套餐B,进入每种套餐,在点选
结账
进入结账,如果消费超过100元,提示用户是否参与换购
#include <iostream>
#include <cstdlib>
#include <ctime>
using namespace std;
int main() {
cout << "欢迎光临本店" << endl;
cout << "请收好您的优惠券,面值20元" << endl;
int yhq = 20;
cout << "-------------------自助点餐系统-------------------" << endl;
cout << "菜单:" << endl;
cout << "1火锅 2回锅肉 3宫保鸡丁 4夫妻肺片 5毛血旺 6麻婆豆腐 7东坡肘子 8水煮牛肉" << endl;
cout << "9龙抄手 10钟水饺 11串串香 12肥肠粉 13担担面" << endl;
cout << "14可乐 15雪碧 16脉动 17果缤纷 18果粒橙 19营养快线" << endl;
cout << "套餐A(优惠10):火锅 回锅肉 东坡肘子,任选其一" << endl;
cout << "龙抄手 钟水饺 串串香,任选其一" << endl;
cout << "可乐 雪碧,任选其一" << endl;
cout << "套餐B(优惠12):火锅 回锅肉 东坡肘子 水煮牛肉,任选其一" << endl;
cout << "肥肠粉 担担面,任选其一" << endl;
cout << "脉动 果缤纷 果粒橙,任选其一" << endl;
cout << "本店消费满100元,可加1元,换购一种饮料" << endl;
//选择单点 套餐 结账菜单变量
char c;
//接收菜的编号
int input;
//菜名数组
string name[19] = {"火锅","回锅肉","宫保鸡丁","夫妻肺片","毛血旺","麻婆豆腐","东坡肘子","水煮牛肉","龙抄手","钟水饺",
"串串香","肥肠粉","担担面","可乐","雪碧","脉动","果缤纷","果粒橙","营养快线"};
//价格数组
int price[19] = { 30,20,15,45,21,34,22,23,31,16,18,19,11,9,13,10,9,8,6 };
//数量数组
int cnt[19] = { 0,0,0,0,0,0,0,0,0,0, 0,0,0,0,0, 0,0,0,0 };
int cnt2[19] = { 0,0,0,0,0,0,0,0,0,0, 0,0,0,0,0, 0,0,0,0 };
//总价格 总优惠
int total = 0, fp = 0;
while (true)
{
cout << "A单点 B套餐 C结账" << endl;
cin >> c;
if (c == 'A')
{
//单点
cout << "输入编号点餐,输入0结束点餐" << endl;
while (true)
{
cin >> input;
if (input == 0) {
break;
}
switch (input) {
case 1:
cnt[0]++;
break;
case 2:
cnt[1]++;
break;
case 3:
cnt[2]++;
break;
case 4:
cnt[3]++;
break;
case 5:
cnt[4]++;
break;
case 6:
cnt[5]++;
break;
case 7:
cnt[6]++;
break;
case 8:
cnt[7]++;
break;
case 9:
cnt[8]++;
break;
case 10:
cnt[9]++;
break;
case 11:
cnt[10]++;
break;
case 12:
cnt[11]++;
break;
case 13:
cnt[12]++;
break;
case 14:
cnt[13]++;
break;
case 15:
cnt[14]++;
break;
case 16:
cnt[15]++;
break;
case 17:
cnt[16]++;
break;
case 18:
cnt[17]++;
break;
case 19:
cnt[18]++;
break;
}
}
//每种菜名字,数量和小计
total = 0;
for (int i = 0; i < 19; i++)
{
if (cnt[i] != 0) {
cout << name[i] << price[i] << "元,数量:" << cnt[i] << " 小计:" << price[i] * cnt[i] << "元" << endl;
total += price[i] * cnt[i];
}
}
cout << "单点总计:" << total << "元,优惠:" << fp << "元" << endl;
}
else if (c == 'B') {
//套餐
while(1){
cout << "套餐A 套餐B (输入字母确定)" << endl;
cin >> c;
if (c == 'A') {
//套餐A
fp += 10;
cout << "1火锅 2回锅肉 7东坡肘子" << endl;
cin >> input;
switch (input) {
case 1:
cnt2[0] ++;
break;
case 2:
cnt2[1] ++;
break;
case 7:
cnt2[6] ++;
break;
}
cout << "9龙抄手 10钟水饺 11串串香" << endl;
cin >> input;
switch (input) {
case 9:
cnt2[8] ++;
break;
case 10:
cnt2[9] ++;
break;
case 11:
cnt2[10] ++;
break;
}
cout << "14可乐 15雪碧" << endl;
cin >> input;
switch (input) {
case 14:
cnt2[13] ++;
break;
case 15:
cnt2[14] ++;
break;
}
break;
}
else if (c == 'B') {
//套餐B
fp += 12;
cout << "1火锅 2回锅肉 7东坡肘子 8水煮牛肉" << endl;
cin >> input;
switch (input) {
case 1:
cnt2[0] ++;
break;
case 2:
cnt2[1] ++;
break;
case 7:
cnt2[6] ++;
break;
case 8:
cnt2[7]++;
}
cout << "12肥肠粉 13担担面" << endl;
cin >> input;
switch (input) {
case 12:
cnt2[11] ++;
break;
case 13:
cnt2[12] ++;
break;
}
cout << "16脉动 17果缤纷 18果粒橙" << endl;
cin >> input;
switch (input) {
case 16:
cnt2[15] ++;
break;
case 17:
cnt2[16] ++;
break;
case 18:
cnt2[17]++;
break;
}
break;
}
else {
cout << "请输入正确的大写字母进行套餐选择!!" << endl;
}
}
total = 0; //数量累加的,所以total需要清零
for (int i = 0; i < 19; i++) {
if (cnt2[i] != 0) {
total += price[i] * cnt2[i];
cout << name[i] << price[i] << "元,数量:" << cnt2[i] << " 小计:" << price[i] * cnt2[i] << "元" << endl;
}
}
total -= fp;
cout << "套餐总计:" << total << "元,优惠:" << fp << "元" << endl;
}
else if (c == 'C') {
//结账
total = 0;
cout << "单点消费:" << endl;
for (int i = 0; i < 19; i++) {
if (cnt[i] != 0) {
cout << name[i] << price[i] << "元,数量:" << cnt[i] << " 小计:" << price[i] * cnt[i] << "元" << endl;
total += price[i] * cnt[i];
}
}
cout << "套餐消费:" << endl;
for (int i = 0; i < 19; i++) {
if (cnt2[i] != 0) {
cout << name[i] << price[i] << "元,数量:" << cnt2[i] << " 小计:" << price[i] * cnt2[i] << "元" << endl;
total += price[i] * cnt2[i];
}
}
total -= fp;
cout << "总费用:" << total << "元,优惠" << fp << "元" << endl;
if (total >= 100)
{
cout << "总消费超过了100元,请问是否加1元换购饮料(Y/N)" << endl;
cin >> c;
if (c == 'Y') {
total += 1;
cout << "14可乐 15雪碧 16脉动 17果缤纷 18果粒橙" << endl;
cin >> input;
switch (input)
{
case 14:
fp += price[13] - 1;
break;
case 15:
fp += price[14] - 1;
break;
case 16:
fp += price[15] - 1;
break;
case 17:
fp += price[16] - 1;
break;
case 18:
fp += price[17] - 1;
break;
}
}
}
cout << "您总共消费:" << total << "元,优惠了" << fp << "元" << endl;
cout << "是否使用优惠券(Y/N)" << endl;
cin >> c;
if (c == 'Y') {
total -= yhq;
fp += yhq;
}
cout << "您支付了:" << total << "元,优惠了" << fp << "元" << endl;
break;
}
else {
cout << "请输入正确的大写字母!!" << endl;
}
}
cout << "-----------------------欢迎下次光临!-------------------------" << endl;
return 0;
}