基础不牢,地动山摇。
今天小米的笔试编程题,输入格式是一整个字符串,需要从字符串中分割出数据,同时还需要将字符串转换为int数值。
本来用C++写,写到一般想起来了C++中没有split()函数,想到在java中有这个函数,于是又换到了Java语言,但是Java的输入、输出又不方便,唉~~
这波,让我狠狠地补一下string的知识
今天来将C++ STL中,与字符串相关的东西总结一下。
在C++中,用string类变量来表示一个字符串,相比于C中的char[]
,更简单。
创建一个string对象
string s; // 1. 一个空的字符串对象
string s1 = "lmk"; // 2. 创建指定内容的字符串
char st[] = {'1','a','b'};
string s2(st);// 3. 根据char[] 创建字符串
string s3(10, 'c'); // 4. 生成包含n个指定字符的字符串
string字符串本质还是一个char[]
,所以我们可以利用[]
来访问指定位置的字符
string str = "abc";
cout << str[0] << endl;
cout << str[2] << endl;
string重载了+
和+=
运算法,这两个运算符对于string对象,就是字符串拼接操作
string str = "abc";
cout << str + "1234" << endl;
str += "xyz";
cout << str << endl;
str += 'Y';
cout << str << endl;
begin()
用来标识字符串的起始位置,即第一个字符的位置end()
,用来表示字符串的结束位置,即最后一个字符的下一个位置首先是基本的成员方法
size()
或length()
empty()
clear()
string str = "lmkdsb";
cout << str.size() << " || " << str.length() << endl;
str.clear();
cout << str.size() << " || " << str.length() << endl;
cout << str.empty() << endl;
字符串长度增加相关的方法
push_back(char ch)
append(string str)
,此方法的参数是一个字符串,追加字符串后面string str = "lmkdsb";
str.push_back('x'); // 追加单个字符
cout << str << endl;
str.append("123"); // 追加字符串
cout << str << endl;
str.insert(1, "xyz"); // 在指定索引处插入字符串
cout << str << endl;
str.insert(str.end(), 'Y'); // 如果要使用insert()在指定索引处插入一个字符,必须要使用迭代器来指明位置
cout << str << endl;
删除字符串相关的方法
pop_back()
earse()
string str = "lmkdsbxxxw";
str.pop_back(); // 删除末尾的单个字符
cout << str << endl;
str.erase(6);// 从pos索引开始删除,一直到最后
cout << str << endl;
str.erase(2, 3); // 从索引为2的位置开始,删除3个元素
cout << str << endl;
str.erase(str.begin() + 1, str.end() - 1); // 配合迭代器,删除[start, end)之间的元素
cout << str << endl;
字符串查找:
string::npos
,(no position),此成员变量用来表示没有找到目标字符串。long long unsigned int
类型的变量(64位无符号整型),npos
转换为int是会溢出,最终转换为int是-1
string str = "lmkdsbm";
cout << str.find('m') << endl; // 查找单个字符
cout << str.find("mk") << endl; // 查找子字符串
cout << str.find('m',1) << endl; //从指定位置开始查找,从[pos, ]开始查找
// 从右边开始查找
cout << str.rfind('m') << endl;
cout << str.rfind("mk") << endl;
cout << str.rfind('m', 3) << endl; // 从指定位置开始查找
// 找不到会返回npos
cout << str.find('x') << endl; // 结果是 18446744073709551615
int pos = str.find('x'); // 转换为int会溢出,最终结果是-1
cout << pos << endl;
此外,还有两个查找相关的方法,与find()、rfind()相似:
find_first_of
查找第一个出现的位置find_last_of
查找最后出现的位置string str = "lmkdsbmx";
// 查找第一个出现的位置
cout << str.find_first_of('m') << endl;
cout << str.find_first_of('m', 1) << endl; // 从指定位置开始查找
// 查找第一个不包含指定子串的位置
cout << str.find_first_not_of('m', 1) << endl;
cout << str.find_last_of('m') << endl; // 寻找最后出现的位置
cout << str.find_last_not_of('m') << endl; // 寻找最后不出现目标字符串的位置
两个字符串交换内容,swap(string str)
string str = "abc";
string tmp ="1231";
str.swap(tmp); // swap()的参数必须是一个变量,不能是一个字符串常量,str.swap("123")这种写法是不可以的
cout << str << endl;
cout << tmp << endl;
replace(pos, n, string&)
从pos位置开始长度为n的这段区间替换为str。
replace(pos,n, m, char ch)
从pos位置开始长度为n的这段区间替换为m个ch
string str = "abcdef";
str.replace(2,2, "lmk");
cout << str << endl;
string s = "xyzw";
s.replace(1,2,8,'k');
cout << s << endl;
substr(pos, n)从字符串中分割出子串,从pos位置开始,截取n个字符并返回
string str = "abc123";
cout << str.substr(2) << endl; // 从指定位置开始截取,一直到结尾
cout << str.substr(3,3) << endl; // 从指定位置pos开始截取n个字符
在C++中,并没有split()函数,其他语言中都有这个函数,这个函数的作用就是按照指定的字符串作为分割,返回分割后的结果。
例如,string str = "13,2,3"
,按照split()所说的,我们按照逗号,
进行分割,分割后的结果应该是一个数组,["13,"2","3]"
我们可以手动实现这个函数,实现的思路有很多种,我们这里以find()
和substr()
来实现
vector<string> split(string str, string separator){
vector<string> res;
int pos = str.find(separator);
while(pos != -1){
string part = str.substr(0, pos);
res.push_back(part);
str = str.substr(pos + 1);
pos = str.find(separator);
}
if(!str.empty()){
res.push_back(str);
}
return res;
}
关于更多split()方法的实现方式可以看Site Unreachable
char ch = 'a';
ch = toupper(ch); // 转换为大写
cout << ch << endl;
ch = tolower('Q'); // 转换为小写
cout << ch << endl;
ch = tolower('2'); // 如果不能转换,则原样返回
cout << ch << endl;
判断一个字符是不是字母、是不是大/小写字母、是不是数字
cout << isupper('A') << endl; // 是否是大写字母
cout << isupper('a') << endl;
cout << islower('A') << endl; // 是否为小写字母
cout << isdigit('1') << endl; // 是否是数字
cout << isdigit('x') << endl;
cout << isalpha(',') << endl; // 是否为字母
cout << isalpha('X') << endl;
对于string字符串风格的对象来说,将一个string转换为int,可以使用stoi(string& str)
函数,除此之外还有:
string str = "123";
int num = stoi(str); // string 转换为int
cout << num + 5 << endl;
str = "123.456"; // 转换为float
cout << stof(str) + 0.1 << endl;
cout << stod(str) << endl; // 转换为double
str = "123212354312523292";
long long x = stoll(str);
cout << x << endl; // 转换为long long 类型
你可能还听说过C 函数库中有一个atoi()
将字符串转换为int,这个atoi(char* s)
函数的参数是一个C风格的字符串,即一个char的数组,不能传递string对象作为参数。
可以调用to_string()函数,该方法是C++11中新增的,该函数可以将其他所有的基本数据类型转换为字符串
string s = to_string(123);
s.pop_back();
cout << s << endl;
string st = to_string(123.456);
cout << st << endl;
可以直接调用STL中的reverse()
函数,
该函数需要两个参数:
string str = "abcdef";
reverse(str.begin(), str.end());
cout << str << endl;
我们知道STL中,sort()是对容器内元素进行排序的,同样也支持对string对象中字符的排序,因为我们可以把string对象看做盛放字符的容器。
众所周知,sort()函数至少需要两个参数:
string str = "cbadfe";
sort(str.begin(), str.end());
cout << str << endl; // 结果是 abcdef
对于sort()函数来说,如果不传入自定义的比较规则,则会按照从小到大的顺序排序,对于字符来说,会按照字典序排序。
transform()
函数的作用就是将一个容器中的所有元素做出转换。
比如,我的字符串是"abc"
可以利用transform()将字符串中的元素全部转换为大写"ABC"
transform()有多个重载形式,对于string来说,就这种形式比比较常用
transform(begin, end, res, operation)
string str = "abcdefg";
transform(str.begin(), str.end(), str.begin(), ::toupper);// ::这两个冒号不可以省略
cout << str;
当然自定义逻辑也是很简单的
// 是大写就转换为小写,是小写就转换为大写
char myChange(char ch){
if(isupper(ch)){
return tolower(ch);
}else{
return toupper(ch);
}
}
int main()
{
string str = "aBcDeFg";
transform(str.begin(), str.end(), str.begin(), myChange);// ::这两个冒号不可以省略
cout << str;
return 0;
}