文章目录
1、数字与字符的对应
48 ----字符0
65----A 差32
97----a
2.字符数组
2.1字符数组的大小
char a[]="c++";
cout<<sizeof(a);
2.2字符数组的输入与输出
scanf 输入字符数组不加& 区地址符号,本身就是地址。
scanf输入字符数组中的一个元素,需要加去地址符号。
对于 s+2不需要去地址符号。
从s[1]开始记录数据,s[0]没有数据。 数组下标从1开始
从s[2]开始记录数据。s[0],s[1]没数据。
2.3字符数组输出易错
对于未定义长度的字符数组和已经定义长度的字符数组。
(1)已经定义长度的会按预期输出。长度未字符长度+1(\0)
(2)对于没有定义长度的,接着下面尾部含有\0的输出
(3)使用字符数组结尾一定写\0,否则程序会有歧义。
(1)
#include<iostream>
#include<cstring>
using namespace std;
int main()
{
//已经定义长度为4
char a[4]={'c','+','+'};
char b[]={'c','+','+','\0'};
char c[]="c++";
cout<<a;
return 0;
}
结果
(2)
#include<iostream>
#include<cstring>
using namespace std;
int main()
{
char a[]={'c','+','+'};
char b[]={'c','+','+','\0'};
char c[]="c++";
cout<<a;
return 0;
}
结果以\0结尾为分割。
(3)歧义
#include<iostream>
#include<cstring>
using namespace std;
int main()
{
char a[]={'c','+','+'};
int d=66;
char b[]={'c','+','+','\0'};
char c[]="c++";
cout<<a;
return 0;
}
int d=66; 则最后输出了B。对于字符数组末尾一定要加\0
2.4 字符数组任意位置输出
2.5 scanf读入字符数组的局限性
当遇到空格、回车、文件结束符时就不能读了。
2.5.1 读入一行字符数组
如何读入一行 且行内包含空格。
使用fgets读入字符数组。fgets(字符数组名,最多几个字符,stdin)
cin.getline 读入一行字符数组(字符数组名称,长度)
2.5.2 读入一行字符串
getline()读入字符串
getline(cin,字符串名称)
2.6字符数组的输出
以上两句话等价。
2.7字符数组常用的操作
也可以直接使用#include
对于 strcmp a>b 输出正数,a<b 输出负数,a=b,输出0.
加入按字典序比较数字。 2与10:
正常比较10>2.
按字典序(ASCII码)比较,2>10 10的第一位是1 ,2的第一位是2。
字典序与贪心相关。
2.7.1合理使用strlen
在初值阶段算出strlen,不能在循环中使用。因为每算一次strlen都会把字符数组遍历一遍。
2.8 练习1
题目:给定一个只包含小写字母的字符串,请你找到第一个仅出现一次的字符。如果没有,输出“no”。
代码
在for循环中 使用str[i]作为循环终止判断,当i为最后一个时,str[i]=’\0’ 循环就直接终止,不需要通过长度判断
字符之间可以执行±操作,且当前边的变量为int时,自动转为整形。
2.9 scanf 面对换行如何应对
3. 字符串处理字符
头文件
有iostream就能使用string iostream包含string
3.1定义和初始化
3.2string 上的操作
(1)string的读写:
注意:不能用printf直接输出string,需要写成:printf(“%s”, s.c_str());
不能用scanf输入string
使用put输出 必须有iostream头文件
string s2=“cdf”;
puts(s2.c_str());
使用put输出字符串和字符数组
string s2=“cdf”;
char a[3]={‘a’,‘b’,’\0’};
puts(s2.c_str());
puts(a);
(2)使用getline读取一整行
(3)string的empty和size操作
字符串为空返回1,不为空返回0。 size返回字符串的长度。
Size 每次返回的是一个存储好的数值,不用像字符数组循环遍历数组后得到长度。
(4)string 的比较:
支持 > < >= <= == !=等所有比较操作,按字典序进行比较。
(5)为string对象赋值:
string s1(10, ‘c’), s2; // s1的内容是 cccccccccc;s2是一个空字符串
s1 = s2; // 赋值:用s2的副本替换s1的副本
// 此时s1和s2都是空字符串
(6)两个string对象相加:
string s1 = “hello, ”, s2 = “world\n”;
string s3 = s1 + s2; // s3的内容是 hello, world\n
s1 += s2; // s1 = s1 + s2
sring 可以加字符串 也可以加字符
(7)字面值和string对象相加:
做加法运算时,字面值和字符都会被转化成string对象,因此直接相加就是将这些字面值串联起来:
string s1 = “hello”, s2 = “world”; // 在s1和s2中都没有标点符号
string s3 = s1 + “, “ + s2 + ‘\n’;
当把string对象和字符字面值及字符串字面值混在一条语句中使用时,必须确保每个加法运算符的两侧的运算对象至少有一个是string:
string s4 = s1 + “, “; // 正确:把一个string对象和有一个字面值相加
string s5 = “hello” +”, “; // 错误:两个运算对象都不是string
string s6 = s1 + “, “ + “world”; // 正确,每个加法运算都有一个运算符是string
string s7 = “hello” + “, “ + s2; // 错误:不能把字面值直接相加,运算是从左到右进行的
3.3 处理string对象中的字符
可以将string对象当成字符数组来处理:
或者使用基于范围的for语句:
不加& c=’a’ 输出c不会改变 加&后改变c输出c会改变
4、auto的使用
5、信息加密
6、字符串长度
不用fgets读入字符数组
7、循环相克令
8.字符串加空格
9.字符串插入
求字符串中的某一段
substr (起始位置,长度/没有的话就到最后)
10.字符串匹配
11.忽略大小写比较字符串大小
一般不用fgets读入。
12、去掉多余的空格
希望i++之后变成j。
双指针算法
13、输出字符串
char 可以去掉 string类型会自动转换。
14、单词替换
使用 stringstream 需要sstream头文件。
将一个字符串放入stringstream后,命名变量的类型。
根据变量的类型,读出不同的数据。
可以一直循环读。
使用sscanf一直读字符数组。 读取字符数组中个人所规定的类型。注意在操作面板中输入数据的类型与sscanf中写的顺序一致。
当不知道一行多少个数时,使用stringstream读入
15、对于streamstring和sscanf
streamstring对于字符串和字符数组都能使用,sscanf只对于字符数组。 不读空格,以空格为间断
两者等价。
16、字符串中最长的连续出现的字符
双指针
17 、最长单词
str.back() 字符串最后一个字符
str.pop_back() 去掉字符串最后一个字符
18、 倒排单词
解法一:字符串数组
解法二:翻转;
#include<iostream>
#include<algorithm>
using namespace std;
int main()
{
string s;
string s1;
while(cin>>s)
{
//字符串翻转的方法
reverse(s.begin(),s.end());
s1+=s+' ';
}
reverse(s1.begin(),s1.end()) ;
for(int i=1 ;i<s1.size();i++) cout<<s1[i];
return 0;
}
19、 字符串移位包含问题
20、字符串乘方
string.substr(起始位置,个数)
21、字符串最大跨距
#include<iostream>
using namespace std;
int main()
{
string s,s1,s2;
char c;
//读入数据
while(cin>>c&&c!=',') s+=c;
while(cin>>c&&c!=',') s1+=c;
while(cin>>c) s2+=c;
//边界值处理
if(s.size()<s1.size()||s.size()<s2.size()) cout<<"-1";
//左边左端点
int l=0;
while(l<=s.size()-s1.size())
{
int k=0;
for(;k<s1.size();k++)
{
if(s[l+k]!=s1[k]) break;
}
if(k==s1.size()) break;
l++;
}
//右边左端点
int r=s.size()-s2.size();
while(r>=0)
{
int k=0;
for(;k<s2.size();k++)
{
if(s[r+k]!=s2[k]) break;
}
if(k==s2.size()) break;
r--;
}
l+=s1.size()-1;
if(l>=r) cout<<"-1";
else cout<<r-l-1;
return 0;
}
22、最长公共字符串后缀
#include<iostream>
using namespace std;
const int N =200;
int n;
string str[N]; //定义个字符串数组
int main(){
while(cin >> n , n)
{
int len = 210 ;
//用来记录公共后缀的长度,写在while中,每次输入更新一次。
for(int i = 0 ; i < n ; i++ )
{
cin >> str[i] ; //输入n个字符串
if(len > str[i].size()) len = str[i].size();
//将公共后缀长度更新为最短的字符串的长度!
}
while(len) //当len>0的时候,也就是有公共后缀的时候
{
bool is_success = true ; //标记是否匹配成功
for(int i = 1 ; i < n ; i++ )
//让所有字符串与第一个字符串比较后缀
{
bool is_same = true ;//标记后缀是否相等
for(int j = 1 ; j <= len ; j++)
// 后缀长度从1到len,每个字符逐个比较
{
if(str[i][str[i].size() - j ] != str[0][str[0].size() - j])
{
is_same = false ;
break ;
}
}
if(!is_same) //后缀不等跳出
{
is_success = false ;
break;
}
}
if(is_success) break ;
//匹配成功跳出while循环,输出长度为len的后缀
len -- ; //匹配失败,长度减1
}
cout << str[0].substr(str[0].size() - len ) << endl ;
}
return 0;
}