C++String专题——蓝桥杯备战D5

String的类型

C++ 提供了以下两种类型的字符串表示形式:

  • C 风格字符串
  • C++ 引入的 string 类类型

C 风格字符串

字符串实际上是使用 null 字符 \0 终止的一维字符数组。

初始化字符串

char site[7] = {'C', 'S', 'D', 'N', '\0'};

依据数组初始化规则,也可以把写成以下形式

char site[] = "CSDN";

其实C++ 编译器会在初始化数组时,自动把 \0 放在字符串的末尾,无需末尾再加入\0

C++引入的string类类型 

C++ 标准库提供了 string 类类型,支持上述所有的操作,另外还增加了其他更多的功能。

初始化字符串

#include <iostream>
#include <string>    //导入头文件
 
using namespace std;
 
int main ()
{
   string str = "CSDN";     //格式
  
   return 0;
}

一系列输入问题

参考文献:https://blog.csdn.net/Flag_ing/article/details/125209588

cin的原理

cin / cout 是C++在头文件<iostream>中封装的类对象,cin 是 istream类对象,cout是ostream类对象,其输入输出操作符 cin>> 和 cout<< 也是通过重载机制赋予的输入输出功能。

使用 cin 执行输入操作是有一个输入缓冲区的,如果是从键盘获取的输入数据,则在按下 Enter 键(即回车键)之后输入的数据(包括回车键)才会被送到输入缓冲区中执行实际的 I/O 操作。

输入:1[空格]2[空格]3[空格]4[空格]5[回车]
则实际上送入缓冲区的是: 1 2 3 4 5'\n' ,共10个字符。 

为什么设置输入输出缓冲区? 

1、如果每次读入一个字符都直接处理,由于从磁盘文件中读取一个字符需要大量硬件活动,在读取量较大时,这是很耗时间的(硬盘的读写速度远小于内存和CPU)。缓冲的方式是每次从硬盘中读取大量信息放在内存中,然后每次从缓冲区读取字节仅从操作,由于内存的读写速度远高于硬盘,因此这样可以大大提升读写效率。

2、由于C++程序通常在用户键入回车后刷新缓冲区,因此对键盘输入进行缓冲可以再将输入传给程序之前返回并更正。也就是说在你按下回车键前,你输入的数据都是可以删除并重新输入(修改)的。

字符数组的输入方式

cin 使用空白字符作为一次输入的结尾,并忽略该空字符。 

int main(void)
{
    char line[10];
    cout << "input what you want:";
    cin >> line;  // 可以尝试输入 "123 456"
    cout << "what you input is:" << line << endl;  // 只能输出 "123"
                                           //一次只能完成一个单词的输入,其后的单词都会被忽略掉
    return 0;
}
/* 测试用例
input what you want:123 456
what you input is:123
*/

使用 getline() / get() 函数完成面向行的输入

getline() / get() 函数都可以接收一行字符串输入,并以回车作为输入的结尾。区别就是 getline 会在输入结束后丢弃最后的换行符,而 get 则会在输入队列中保留最后的换行符。 

1.cin.getline()

语法:cin.getline(line, nums, (optional)delim)

line:目标数组

nums:数组长度

这样来避免超越数组的边界。从输入队列中获取 nums-1 个字符到 line 中,因为字符串的最后一个字符是 '\0'。如果输入的长度超出 nums-1 个,则 getline 和 get 将把余下的字符留在输入队列中,另外 getline 还会设置失效位,并关闭后面的输入(即后面的所有输入将不可用),此时可以用 cin.clear() 清除标准位就可以恢复后面的输入。

int main(void)
{
    char line1[10];
    char line2[10];
    char line3[10];
    cout << "input what you want:" << endl;
    cin.getline(line1, 10);  // 可以尝试输入 "123 456 789" ('\n') 含有11个字符
    // cin.clear();
    cin.getline(line2, 10);  // 不可用,直接退出
    cin.getline(line3, 10);  // 不可用,直接退出
    cout << "what you input is:" << endl;
    cout << "line1:" << line1 << endl;  // 输出 "123 456 7"
    cout << "line2:" << line2 << endl;  // 输出 空
    cout << "line3:" << line3 << endl;  // 输出 空
    return 0;
}
/*
input what you want:
123 456 789
what you input is:
line1:123 456 7
line2:
line3:
*/
 
 
// 使用 clear
int main(void)
{
    char line1[10];
    char line2[10];
    char line3[10];
    cout << "input what you want:" << endl;
    cin.getline(line1, 10);  // 可以尝试输入 "123 456 789" ('\n') 含有11个字符
    cin.clear();   // 清除标志位
    cin.getline(line2, 10);  // 可用,输出 "89",这是上一步输入队列中的字符
    cin.getline(line3, 10);  // 可用,你输入啥输出啥
    cout << "what you input is:" << endl;
    cout << "line1:" << line1 << endl;  // 输出 "123 456 7"
    cout << "line2:" << line2 << endl;  // 输出 空
    cout << "line3:" << line3 << endl;  // 输出 空
    return 0;
}
/*
input what you want:
123 456 789
123
what you input is:
line1:123 456 7
line2:89
line3:123
*/

cin.getline 还有第三个参数 delim(全称应该是 delimiter,中文意思:定界符/分隔符),作用是指定用作分界符的字符(没有这个参数的版本将以换行符为分界符)

遇到分界符后,当前字符串的输入将停止,即使还未读取最大数目的字符。因此在默认情况下,这种分界符的方式或者到达输入的指定数目都将停止读取输入。和默认情况一样 get() 将分界符留在输入队列中,而 getline() 不保留。

cin.getline(line, nums, delim),也就是以 delim 指定的字符作为一次字符串输入的结束,其后的在 nums-1 范围内的输入会保留在输入队列中作为下一个字符串的开始。

int main(void)
{
    char line1[10];
    char line2[10];
    cout << "input what you want:" << endl;
    cin.getline(line1, 10, 's');  // 可以尝试输入 "123s456" ('\n')
    cin.getline(line2, 10);  // 
    cout << "what you input is:" << endl;
    cout << "line1:" << line1 << endl;  // 输出 "123"
    cout << "line2:" << line2 << endl;  // 输出 "456"
    return 0;
}
/* 测试用例
input what you want:
123s456
what you input is:
line1:123
line2:456
*/

getline 函数每次读取一行,它通过换行符来确定行尾,但不保存换行符。相反,在存储字符串时他用空字符 '\0' 来替换换行符。 

2.cin.get()

语法:cin.get(line, nums, (optional)delim)

get 函数会在输入队列中保留最后的换行符。注意是输入队列,也就是在一个 get()

函数完成输入后,会在输入缓存中保留组后的换行符,如果不做处理在下次运行 get() 时会出问题。

int main(void)
{
    char line1[10];
    char line2[10];
    cout << "input what you want:" << endl;
    cin.get(line1, 10);  // 可以尝试输入 "123" ('\n'), 此时回车符将会留在输入队列中
    cin.get(line2, 10);  // 可以尝试输入 "456",可以发现 line1 输入完后,这步直接被“跳过了”
    cout << "line1:" << line1 << endl;  // 输出 "123"
    cout << "line2:" << line2 << endl;  // 输出空字符,由于 cin.get(line2, 10); 读入的是上一个字符输入结束时留输入队列中的回车符
    return 0;
}
 
/* 测试用例
input what you want:
123
what you input is:
line1:123
line2:
*/

解决措施:

cin.get(line2, 10).get();
\\ 或者
cin.get(line2, 10);
get();

数字和字符串的混合输入问题 

使用 cin 输入一个整数后,最后的回车符会留在输入队列中,类似于get,这会对后续的 getline 和 get 输入产生影响,因为 getline / get 看到换行符后会认为是一个空行,然后会把空字符赋给后面的字符串

int main(void)
{
    int a, b;  // 输入 123 ('\n') 456 ('\n')
    char s[5];
    cin >> a;
    cin >> b;
    cin.getline(s, 5); // 得到换行符,直接赋空值
    cout << a << " " << b << " " << s << endl;
}
/* 测试用例
123
456
123 456 
*/

解决措施:在后面添加 cin.get() 或者 (cin >> b).get() 

​int main(void)
{
    int a, b;  // 输入 123 ('\n') 456 ('\n')
    char s[7];
    cin >> a;
    // cin >> b;
    // cin.get();    
    (cin >> b).get();
    cin.getline(s, 7); // 输入 "string" ('\n')
    cout << a << " " << b << " " << s << endl;
}
/* 测试用例
123
456
string
123 456 string
*/

String对象的输入

使用 cin<<str 的语法来将输入存储到 string 对象中与字符数组的操作是一样的。不同的是当每次读取一行而不是一个单词时使用的语法是不同的。

int main(void)
{
    string str;
    cout << "input what you want:" << endl;
    getline(cin, str);   
//将 cin 作为参数,指出到哪里去查找输入。
//另外也没有指出字符串长度的参数,因为 string 对象将根据字符串的长度自动调整自己的大小。
    cout << "what you input is:" << endl;
    cout << str << endl;
}
/* 测试用例
input what you want:
123 456 789
what you input is:
123 456 789
*/

常见操作及函数

1.定义

    string s1;    // 初始化一个空字符串
    string s2 = s1;   // 初始化s2,并用s1初始化
    string s3(s2);    // 作用同上
    string s4 = "hello world";   // 用 "hello world" 初始化 s4,除了最后的空字符外其他都拷贝到s4中
    string s5("hello world");    // 作用同上
    string s6(6,'a');  // 初始化s6为:aaaaaa
    string s7(s6, 3);  // s7 是从 s6 的下标 3 开始的字符拷贝
    string s8(s6, pos, len);  // s7 是从 s6 的下标 pos 开始的 len 个字符的拷贝

2.查询字符串信息、索引

#include <iostream>
#include <string>
using namespace std;
int main(void)
{
    string s1 = "abc";    // 初始化一个字符串
    cout << s1.empty() << endl;  // s 为空返回 true,否则返回 false
    cout << s1.size() << endl;   // 返回 s 中字符个数,不包含空字符
    cout << s1.length() << endl;   // 作用同上
    cout << s1[1] << endl;  // 字符串本质是字符数组
    cout << s1[3] << endl;  // 空字符还是存在的
    return 0;
}
// 运行结果 //
0
3
3
b

3.拼接、比较等操作

s1+s2          // 返回 s1 和 s2 拼接后的结果。加号两边至少有一个 string 对象,不能都是字面值
s1 == s2       // 如果 s1 和 s2 中的元素完全相等则它们相等,区分大小写
s1 != s2
<, <=, >, >=   // 利用字符的字典序进行比较,区分大小写

4.for 循环遍历

可以使用 c++11 标准的 for(declaration: expression) 形式循环遍历,例子如下:

(如果想要改变 string 对象中的值,必须把循环变量定义为引用类型)

#include <iostream>
#include <string>
#include <cctype>
using namespace std;
int main(void)
{
    string s1 = "nice to meet you~";    // 初始化一个空字符串
    // 如果想要改变 string 对象中的值,必须把循环变量定义为引用类型。引用只是个别名,相当于对原始数据进行操作
    for(auto &c : s1)  
        c = toupper(c); 
    cout << s1 << endl; // 输出
    return 0;
}
// 运行结果 //
NICE TO MEET YOU~

5.修改 string 的操作

pos是一个下标或者迭代器。接受下标的版本返回一个指向 s 的引用;接受迭代器的版本返回一个指向第一个插入字符的迭代器 

在 pos 之前插入 args 指定的字符。

s.insert(pos, args)  
// 在 s 的位置 0 之前插入 s2 的拷贝
s.insert(0, s2)  

删除从 pos 开始的 len 个字符。如果 len 省略,则删除 pos 开始的后面所有字符。返回一个指向 s 的引用。

s.erase(pos, len)  

将 s 中的字符替换为 args 指定的字符。返回一个指向 s 的引用。

s.assign(args)  

replace()函数

#include <iostream>
#include <string>
using namespace std;
int main()
{
    string line = "this@ is@ a test string!";
    line = line.replace(line.find("@"), 1, ""); //从第一个@位置替换第一个@为空
    cout<<line<<endl;
    return 0;
}

将 args 追加到 s 。返回一个指向 s 的引用。args 不能是单引号字符,若是单个字符则必须用双引号表示。如,可以是 s.append("A") 但不能是 s.append('A'

s.append(args)  

将 s 中范围为 range 内的字符替换为 args 指定的字符。range 或者是一个下标或长度,或者是一对指向 s 的迭代器。返回一个指向 s 的引用。

s.replace(range, args) 
// 从位置 3 开始,删除 6 个字符,并插入 "aaa".删除插入的字符数量不必相等
s.replace(3, 6, "aaa")  

字符串反转,使用 <algorithm> 头文件中的 reverse() 方法:

    string s2 = "12345";    // 初始化一个字符串
    reverse(s2.begin(), s2.end()); // 反转 string 定义的字符串 s2 
    cout << s2 << endl; // 输出 54321

交换字符串:swap()函数

#include <iostream>
#include <string>
using namespace std;
int main()
{
    string str1,str2;
    cin>>str1>>str2;
    cout<<"str1:"<<str1<<endl;
    cout<<"str2:"<<str2<<endl;
    swap(str1, str2);
    cout<<"str1:"<<str1<<endl;
    cout<<"str2:"<<str2<<endl;
}

 字符串比较函数:compare()

#include <iostream>
#include <string>
using namespace std;
int main()
{
    string str1,str2;
    cin>>str1>>str2;
    cout<<str1.compare(str2)<<endl;
    return 0;
}

6.string搜索操作

搜索操作返回指定字符出现的下标,如果未找到返回 npos 

s.find(args)  // 查找 s 中 args 第一次出现的位置
s.rfind(args)  // 查找 s 中 args 最后一次出现的位置

在 s 中查找 args 中任何一个字符 最早/最晚 出现的位置

s.find_first_of(args)  // 在 s 中查找 args 中任何一个字符最早出现的位置
s.find_last_of(args)  // 在 s 中查找 args 中任何一个字符最晚出现的位置
例如:
string s1 = "nice to meet you~"; 
cout << s1.find_first_of("mey") << endl; // 输出结果为 3,'e' 出现的最早
 

在 s 中查找 第一个/最后一个 不在 args 中的字符的位置

s.find_first_not_of(args)  // 查找 s 中 第一个不在 args 中的字符的位置
s.find_last_not_of(args)  // 查找 s 中 最后一个不在 args 中的字符的位置
例如:
string s1 = "nice to meet you~";  
cout << s1.find_first_not_of("nop") << endl; // 输出结果为 1 ,'i' 不在 "nop" 里
#include <iostream>
#include <string>
using namespace std;
int main()
{
    string str;
    cin>>str;
    //主要字符串是从0开始计数的
    cout<<"ab在str中的位置:"<<str.find("ab")<<endl;
    //返回第一次出现ab的位置,没有则返回一串乱码
    cout<<"ab在str[2]到str[n-1]中的位置:"<<str.find("ab",2)<<endl;
    //返回第一次从str[2]开始出现ab的位置,没有则返回一串乱码
    cout<<"ab在str[0]到str[2]中的位置:"<<str.rfind("ab",2)<<endl;
    //返回ab在str[0]到str[2]中的位置,没有则返回一串乱码
    return 0;
}

子串substr()函数

#include <iostream>
#include <string>
using namespace std;
int main()
{
    string str;
    cin>>str;
    cout<<"返回str[3]及其以后的子串:"<<str.substr(3)<<endl;
    //若小于限制长度则报错
    cout<<"从ste[2]开始由四个字符组成的子串:"<<str.substr(2,4)<<endl;
    //若小于限制长度则报错
    return 0;
}

 7.string、char 型与数值的转换

将数值 val 转换为 string 。val 可以是任何算术类型(int、浮点型等)

string s = to_string(val)

转换为整数并返回。返回类型分别是 int、long、unsigned long、long long、unsigned long long。b 表示转换所用的进制数,默认为10,即将字符串当作几进制的数转换,最终结果仍然是十进制的表示形式 。p 是 size_t  指针,用来保存 s 中第一个非数值字符的下标,默认为0,即函数不保存下标,该参数也可以是空指针,在这种情况下不使用。

stoi(s)
// 函数原型 int stoi (const string&  str, size_t* idx = 0, int base = 10);
stoi(s, p, b)
stol(s, p, b)
stoul(s, p, b)
stoll(s, p, b)
stoull(s, p, b)
// 例如
string s1 = "11";    // 初始化一个空字符串
int a1 = stoi(s1);
cout << a1 << endl; // 输出 11
int a2 = stoi(s1, nullptr, 8);
cout << a2 << endl; // 输出 9
int a3 = stoi(s1, nullptr, 2);
cout << a3 << endl; // 输出 3

转换为浮点数并返回。返回类型分别是 float、double、long double 。p 是 size_t  指针,用来保存 s 中第一个非数值字符的下标,默认为0,即函数不保存下标,该参数也可以是空指针,在这种情况下不使用。

stof(s)
stof(s, p)
stod(s, p)
stold(s, p)

char 型转数值。注意传入的参数是指针类型,即要对字符取地址

atoi(c)
// 函数原型 int atoi(const char *_Str)
atol(c)
atoll(c)
atof(c)

  • 44
    点赞
  • 39
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值