05. string
在线参考手册:https://zh.cppreference.com/
认识string
#include<iostream>
#include<string> //头文件
using namespace std;
int main(){
string s; //字符串变量的定义
cin>>s; //输入字符串
cout<<s; //输出字符串
return 0;
}
标准库类型 string表示可变长的字符序列,
字符串对象是一种特殊类型的容器,专门设计来操作的字符序列。
不像传统的c-strings,只是在数组中的一个字符序列,我们称之为字符数组。
而C++字符串对象属于一个类,这个类有很多内置的特点,在操作方式,更直观,另外还有很多有用的成员函数。
说明:
(1)定义字符串变量格式: string 变量名;
(2)程序必须包含string头文件:#include<string>
(3)输入的字符串可以认为是任意长度,只受计算机内存限制
(4)可以输入中文,cin读入字符串时,空格和换行符都被认为是字符串的结束。
因此输入的数据中间不能有空格。
(5)`getline(cin,s);`` 读入整行,以换行符结束。
连续输入使用 while(cin>>s)`` 格式:
while(cin>>s){ }``
字符串的连接使用 + 或者是方法 append();
string a = "my name is:";
string b = "hello";
string c = a + b;
string d = a.append(b);
需要注意的是这样做复杂度是len(a)+len(b)
如果你只是需要在 a 后面拼接一个 b 的话,直接使用 a+=b 或 a.append(b) 是更好的选择( 复杂度len(b) )
【例】过滤多余的空格。
一个句子中也许有多个连续的空格,过滤掉多余的空格,只留下一个空格。
输入格式:1行,一个字符串(长度不超过200),句子的头和尾都没有空格。
输出格式:过滤之后的句子
输入样例:Hello world.This is c language.
输出样例:Hello world,This is c language.
#include<iostream>
#include<string>
using namespace std;
int main() {
string s,temp; cin>>s;
while(cin>>temp) { //可以实现连续输入,直到文件结束或者 Ctrl+Z 结束
s += ' '+temp; //使用空格连接字符串,等同于 s = s+ ' '+temp;
}
cout<<s;
return 0;
}
char a[50]={'h', 'e', 'l', 'l', 'o'};
char a[50]="hello";
字符数组中用单引号括起来的称为字符,字符'h' 与字符串"h" 是不一样的。
字符数组中后面未赋值部分会被置为'\0',也就是我们所说的结束标志。
#include <cstdio>
int main() {
char name[50]; scanf("%s", &name);
printf("my name is:%s\n", name);
for(int i=0; name[i]!='\0'; i++) printf("%c", name[i]);
return 0;
}
字符数组:char name[5]={'t','e','a','m'};
字符串数组:string name[5]={"team","min","max","pool"};
【例】输入一个 1 到 7 的数字,表示星期一到星期日,输出相应的英文:
"Mon.","Tue.","Wed.","Thur.","Fri.","Sat.","Sun."
#include<iostream>
#include<string>
using namespace std;
int main() {
string dayName[8]={"0","Mon.","Tue.","Wed.","Thur.","Fri.","Sat.","Sun."};
int i; cin>>i;
cout<<dayName[i];
return 0;
}
string的成员函数
string 并不是一个基本数据类型,而是作为一个类存在的,
如果不知道什么是类,暂时可以将string看作一个字符串类型使用即可。
类是对象的一种抽象画描述,比如人类。
而具体的某个人这是一个具体对象,所以对象又是类的实例化描述。
那什么又是对象呢?
有一句话是这么说的:"万物皆对象,对象皆有类"。
个人理解为:意指宇宙间的所有事物皆可依据其本质抽象为一种类型,同时又具有一定的特性。
比如:人,狗,猫,房屋,汽车都是对象,
它们各自具有自己的本质特性,并且不论是虚拟的亦或是客观存在的,都是可以被描述的一类事物。
对于计算机程序设计的世界中,我们也借鉴了这样的特性,创造了面向过程和面向对象的编程方式。
面向过程是指:从问题本身入手,以什么正在发生为主要目标进行编程,是一种以过程为中心的编程思想。
面向对象是指:从问题的根源入手,此根源一定是与某个对象相关联的,从该对象入手。
举个例子:中午时分,小明同学去学校食堂吃饭,但是当他买好饭之后不想吃饭了,现在请你来解决这样一个问题。
出于面向过程的思想我们考虑这样一个问题,小明不吃饭了,那我让你吃就好了,要不一口一口喂。
出于面向对象的思想,如果小明不吃饭,那么问题在哪里?小明人有问题,亦或是饭有问题,那么就对人和饭做处理即可。
- 了解一下
程序语言有多种分类方法,大部分程序语言都是算法描述型语言,如C/C++、Java等,还有一部分是数据描述型语言,如HTML等标记语言。
按照编程技术难易程度可分为低级语言(机器语言、汇编语言)和高级语言;
按照程序语言设计风格可分为命令式语言(过程化语言)、结构化语言、面向对象语言、函数式语言、脚本语言等;
按照语言应用领域可分为通用程序语言(GPPL)和专用程序语言(DSL);
按照程序执行方式,可分为解释型语言(如JavaScript、Python、Perl、R等),编译型语言(如C/C++等),编译+解释型语言(如Java、PHP等)。
机器语言是以二进制代码表示的指令集合,是计算机唯一能直接识别和执行的语言。
机器语言的优点是占用内存少、执行速度快,缺点是难编写、难阅读、难修改、难移植。
汇编语言是将机器语言的二进制代码指令用简单符号(助记符)表示的一种语言。
因此汇编语言与机器语言本质上是相同的,都可以直接对计算机硬件设备进行操作。
汇编语言编程需要对计算机硬件结构有所了解,这无疑大大增加了编程难度。但是汇编语言生成的可执行文件很小,而且执行速度很快。
因此,工业控制领域经常采用汇编语言进行编程。汇编语言与计算机硬件设备(主要是CPU)相关,不同系列CPU(如ARM与Intel的CPU)的机器指令不同,因此它们的汇编语言也不同。
高级程序语言
高级语言将计算机内部的许多相关机器操作指令,合并成一条高级程序指令,并且屏蔽了具体操作细节(如内存分配、寄存器使用等),这样大大简化了程序指令,使编程者不需要专业知识就可以进行编程。
高级程序语言便于人们阅读、修改和调试,而且移植性强,因此高级程序语言已成为目前普遍使用的编程语言。
而程序设计中,程序语言和编程思想是有一定关联的,我们也依据编程思想将程序语言进行了分类:
面向过程的程序语言:C,Pascal,Fortran
面向对象的程序语言:C++, C#, Java, delphi, Visual Basic, Python
注意:面向对象的语言同意可以做面向过程的事情,所以我们可以理解面向对象是面向过程的升级。
哎呀,说多了,我们还是回过头来吧!!!
在线参考手册:https://zh.cppreference.com/
int n=s.size(); 获得字符串的长度
int n=s.length(); 获得字符串的长度
int id=s.find("nos"); 如果在字符串s中找到"nos",则返回第一次出现的位置;否则返回string::npos;
int id=s.find(a); 返回字母在 s[0...n]中的第一个位置(下标),如果没有,返回npos,在int下可以看做-1。
int id=s.find(a, i); 返回字母在 s[i...n]中的第一个位置(下标),如果没有,返回npos,在int下可以看做-1。
s.substr(i, n); 是获得字符串中下标从 i 开始的连续 n 个字符的一段子串
s.append(a); 在字符串s后追加字符串 a
s.append(n, c); 在字符串s后追加 n 个字符 c
s.insert(开始位置,字符串); 指定字符串插入到字符串中的指定位置,把字符串插入指定位置
s.erase(开始位置a,长度b); 删除字符串中从开始位置起,长度为b的字符串
s.replace(i, k, b); 替换 s 从下标 i开始连续 k个字符为 b
s.replace(1,3,"title"); 将字符串s位置1开始,长度为3的字符串替换成字符串"title"的内容
to_string(b); 将数字 b 转为 string 类型
stoi(s), stod(s) 将字符串转为数字
sort(s.begin(),s.end()); 排序(首地址,末地址的后一位);
reverse(s.begin(),s.end()); 翻转(首地址,末地址的后一位);
判断是否为数字以及读入一行字符的使用方法
(1) 判断是否为数字:s[i]>='0'&&s[i]<='9'
(2) getline(cin,s): 读入一行,以回车结束
(1)字符转化成数字:
字符'1'怎么转换为数字1: '1'-'0'
数字字符s[i] 转换为对应数字: s[i]-'0'
(2)数字转化成字符:char强制转换
数字1转化成字符'1': (char)(1+'0');
数字s[i] 转换为对应字符: (char)(s[i]+'0')
实例练习
【例】第一个只出现一次的字符。
给定一个只包含小写字母的字符串,找到第一个仅出现一次的字符。
输入格式:一个字符串,长度小于100000
输出格式:输出第一个仅出现一次的字符,若没有,则输出no
输入样例:abcabd
输出样例:c
#include<iostream>
#include<string>
using namespace std;
int main() {
int temp; string s; cin>>s;
for(int i=0; i<s.size(); i++) {
temp=0;
for(int j=0; j<s.size(); j++) {
if(s[i]==s[j]) temp++;
}
if(temp==1) {
cout<<s[i]<<endl; return 0;
}
}
cout<<"no"<<endl; return 0;
}
【例】统计数字字符个数。
输入一行字符,统计出其中数字字符的个数。
输入格式:1行字符串,总长度不超过255
输出格式:输出为1行,输出字符串里面数字字符的个数
输入样例:Peking University is set up at 1898.
输出样例:4
#include<iostream>
#include<string>
using namespace std;
int main(){
int temp=0;
string s; getline(cin,s);//读入一行字符串
for(int i=0;i<s.size();i++){
if(s[i]>='0' && s[i]<='9') temp++;//判断是否是数字
}
cout<<temp<<endl;
return 0;
}
【例】摘录文字。
输入一行由字母和字符“#”组成的字符串,保证“#”出现偶数次。
从前向后看,每两个“#”字符之间的字符串是要摘录的文字,请编程把摘录的字符串连续输出。
输入格式:1行字符串,总长度不超过1000000
输出格式:“#”号对之间的字符。
输入样例:a#abcd#xyz#efgh#opq.
输出样例:abcdefgh
for(int i=0; i<s.size(); i++) {
if(s[i]=='#'){
p=i+1;
for(i++; s[i]!='#'; i++);
ans += s.substr(p,i-p) ;
}
}
substr()函数的作用:
substr(开始位置,长度)是获得字符串中的一段子串
【例】选择你喜爱的水果。
现有七种水果的名字,要求用户输入一个与水果有关的句子。
程序在已存储的水果名字中搜索,以判断句子中是否包含七种水果的名称。
如果包含,则用词组"Brussels sprouts"替代句子中出现的水果单词,并输出替代后的句子。
如果句子中没有出现这些水果的名字,则输出"You must not enjoy fruit."。
假设七种水果的名字为:"apple","bananas","peaches","cherries","pears","oranges","strawberries".
输入格式:有多行,每行是一个字符串(长度不超过200)。
每行输入中只会有一个水果名称,不会存在一行输入包括多种水果名称或者重复水果名称的情况。
输出格式:如题所言。
输入样例:
I really love peaches on my cereal.
I’d rather have a candy bar.
输出样例:
I really love Brussels sprouts on my cereal.
You must not enjoy fruit.
#include<iostream>
#include<string>
using namespace std;
string s,fruits[7]={"apple","bananas","peaches","cherries","pears","oranges","strawberries"};
int main() {
while(getline(cin,s)) {
int pos,id=-1;
for(int i=0; i<7; i++) {
pos=s.find(fruits[i]);
if(pos!=string::npos) {
id=i; break;
}
}
if(id==-1) cout<<"You must not enjoy fruit."<<endl;
else {
s.replace(pos,fruits[id].size(),"Brussels sprouts");
cout<<s<<endl;
}
}
return 0;
}
【例】提取整数。
有一行由小写字母和数字组成的字符串,请求出其中所有数的和。
输入格式:一个字符串,长度小于1000000
输出格式:一个整数。保证小于2^62
输入样例:ab123ced45enf
输出样例:15
#include<iostream>
#include<string>
using namespace std;
int main() {
int sum=0;
string s; getline(cin,s);
for(int i=0; i<s.size(); i++) {
if(s[i]>='0'&&s[i]<='9') sum+=s[i]-'0';
}
cout<<sum;
return 0;
}
【例】读入1行由0和1字符组成的二进制数字符串,请转换成十六进制数。
输入格式:一个0/1字符串,长度小于100000
输出格式:输出1行转换后的十六进制数。
输入样例:11010100101
输出样例:6A5
#include<iostream>
#include<string>
#include<algorithm>
using namespace std;
int main() {
string s,ans; getline(cin,s);
for(int i=s.size(); i>=0; i=i-4) {
int num=0;
for(int j=max(0,i-4); j<i; j++) num=num*2+(s[j]-'0');
if(num<10) ans=char(num+'0')+ans;
else ans=char('A'+num-10)+ans;
}
cout<<ans;
return 0;
}
【例】有N个人的姓名,请把他们按照姓名的字典序排列输出。
输入格式:N行,每行一个整数,1<=N<=100000;
下面第2行到第N+1行,每行一个姓名。姓名由不超过50的小写字母组成。
输出格式:N行,每行一个姓名。
输入样例 | 输出样例 |
---|---|
3 wang liying anqian |
anqian liying wang |
#include<iostream>
#include<string>
#include<algorithm>
using namespace std;
int main() {
string a[10000];
int n; cin>>n;
for(int i=0; i<n; i++) cin>>a[i];
sort(a,a+n);
for(int i=0; i<n; i++) cout<<a[i]<<endl;
return 0;
}