C++-字符串处理函数-查找-截取-分割-替换-删除-格式化-与数值互转-拼接-正则表达式-常用功能
文章目录
- 1.字符串查找
- 1.1.find-正向查找
- 1.2.rfind-逆向查找
- 2.字符串子字符串截取
- 3.字符串分割
- 4.字符串替换-删除
- 5.字符串裁剪-裁剪空字符串
- 6.字符串格式化
- 7.类型转换-数字转字符串-std::to_string()
- 8.类型转换-字符串转数字
- 8.1.字符串转双精度-std::stod
- 8.2.字符串转单精度-std::stof
- 8.3.字符串转整数-std::stoi
- 8.4.字符串转长整数-std::stol
- 8.5.字符串转长双精度-std::stold
- 8.6.字符串转长长整型-std::stoll
- 8.7.字符串转无符号长整型-std::stoul
- 8.8.字符串转无符号长长整型-std::stoull
- 9.字符串类型判断-是否是数值
- 10.字符串拼接+append
- 11.字符串数组拼接成字符串-Join
- 12.正则表达式
- 12.1.std::regex_match--是否匹配
- 12.2.std::match_results-匹配结果
- 12.3.std::regex_search-搜索匹配
- 12.4.std::regex_search-替换匹配
- 12.5.常用的正则表达式字符串
1.字符串查找
1.1.find-正向查找
第一个参数为待查找的子字符串。第二个参数为开始查找的位置(下标);如果不指明,则从第0个字符开始查找。如果未查找到,该返回值是一个很大的数据。用std::string::npos表示。
#include <iostream>
#include <string>
using namespace std;
int main()
{
std::string str("defgabc");
std::string::size_type pos = str.find("abc");
if (pos == std::string::npos)//未找到
{
cout << "Not find" << endl;
}
return 0;
}
1.2.rfind-逆向查找
用法与find相同。
2.字符串子字符串截取
substr()是C++字符串函数,主要功能是复制子字符串,要求从指定位置开始,并具有指定的长度。如果没有指定长度_Count或_Count+_Off超出了源字符串的长度,则子字符串将延续到源字符串的结尾。
std::string x = s.substr(); //默认时的长度为从开始位置到尾
std::string y = s.substr(5); //获得字符串s中 从第5位开始到尾的字符串
std::string z = s.substr(5, 3); //获得字符串s中 从第5位开始的长度为3的字符串
3.字符串分割
标准C++里面没有带字符串分割函数,但是这个函数非常常用,作者实现并测试这个功能如下:
#include <string>
#include <vector>
std::vector<std::string> SplitWithStl(const std::string str, const std::string pattern)
{
//如果为空则返回
std::vector<std::string> strItems;
if ("" == str)
{
return strItems;
}
//方便截取最后一段数据
std::string strs = str + pattern;
size_t pos = strs.find(pattern);
size_t patternSize = pattern.length();
//循环截取直到最后
while (pos != std::string::npos)
{
//从开始位置到分隔符位置
std::string x = strs.substr(0, pos);
strItems.push_back(x);
//截取剩下的字符串
strs = strs.substr(pos + patternSize);
pos = strs.find(pattern);
}
return strItems;
}
int main()
{
std::string str1 = "45;;okfd;;kujh";
std::string pat = ";;";
std::vector<std::string> strItems = SplitWithStl(str1, pat);
return 0;
}
4.字符串替换-删除
标准C++里面没有带字符串替换函数,但是这个函数非常常用,作者实现并测试这个功能如下:
#include <iostream>
#include <string>
#include <vector>
//字符串替换
std::string ReplaceStr(std::string str, const std::string oldStr, const std::string newStr)
{
size_t newStrLen = newStr.length();
size_t oldStrLen = oldStr.length();
for (std::string::size_type pos(0); pos != std::string::npos; pos += newStrLen)
{
pos = str.find(oldStr, pos);
if (pos != std::string::npos)
str.replace(pos, oldStrLen, newStr);
else
break;
}
return str;
}
int main()
{
std::string str1 = "45;;okfd;;kujh";
std::string pat = ";;";
std::string rlt=ReplaceStr(str1, pat, "+---++");
return 0;
}
注意:如果新字符为空,等同于删除旧的子字符串。
5.字符串裁剪-裁剪空字符串
裁切首尾的空字符,对于一些信息处理系统比较常用,作者实现并测试这个功能如下:
#include <string>
std::string StringTrim(std::string str)
{
if (str.empty()) {
return str;
}
str.erase(0, str.find_first_not_of(" "));
str.erase(str.find_last_not_of(" ") + 1);
return str;
}
int main()
{
std::string str1 = " 45;;okfd;;kujh ";
std::string pat = ";;";
std::string rlt = StringTrim(str1);
return 0;
}
6.字符串格式化
按照Format组合字符串,对于一些信息处理系统比较常用,作者实现并测试这个功能如下:
#include <iostream>
#include <algorithm>
#include <string>
#include <vector>
#include <stdarg.h>
//字符串格式化
std::string StringFormat(const char *pszFmt, ...)
{
std::string str;
va_list args;
va_start(args, pszFmt);
{
int nLength = _vscprintf(pszFmt, args);
nLength += 1; //上面返回的长度是包含\0,这里加上
std::vector<char> vectorChars(nLength);
_vsnprintf_s(vectorChars.data(), nLength, nLength, pszFmt, args);
str.assign(vectorChars.data());
}
va_end(args);
return str;
}
int main()
{
std::string str1 = "45;;okfd;;kujh";
std::string pat = ";;";
std::string rlt = StringFormat("str=%s",str1.c_str());//原理还是对C的封装,不支持C++字符串类型。
return 0;
}
7.类型转换-数字转字符串-std::to_string()
将数值转换为字符串。
std::string to_string( int value ); //与 std::sprintf(buf, "%d", value)
std::string to_string( long value ); //与 std::sprintf(buf, "%ld", value)
std::string to_string( long long value ); //与 std::sprintf(buf, "%lld", value)
std::string to_string( unsigned value ); //与 std::sprintf(buf, "%u", value)
std::string to_string( unsigned long value ); //与 std::sprintf(buf, "%lu", value)
std::string to_string( unsigned long long value ); //与 std::sprintf(buf, "%llu", value)
std::string to_string( float value ); //std::sprintf(buf, "%f", value)
std::string to_string( double value ); //std::sprintf(buf, "%Lf", value)
std::string to_string( long double value );
8.类型转换-字符串转数字
在C++11发布之前我们只能使用C语言的atoi等函数完成字符串到int/float/double等类型的转换,而在C++11中在std::string中自带了stoi/stod等工具函数进行转换。
8.1.字符串转双精度-std::stod
函数原型
double stod (const string& str, size_t* idx = 0);
double stod (const wstring& str, size_t* idx = 0);
代码范例
std::string numStr = "5646545.32";
double number1 = std::stod(numStr);
注意:如果成功则返回转换的double型数值,如果转换失败,则会抛出invalid_argument异常,如果待转换的字符所代表的数值超出数值类型范围的两倍,则会抛出out_of_range异常。
8.2.字符串转单精度-std::stof
函数原型
float stof (const string& str, size_t* idx = 0);
float stof (const wstring& str, size_t* idx = 0);
代码范例
std::string numStr = "5646545.32";
double number1 = std::stof(numStr);
注意:如果成功则返回转换的double型数值,如果转换失败,则会抛出invalid_argument异常,如果待转换的字符所代表的数值超出数值类型范围的两倍,则会抛出out_of_range异常。
8.3.字符串转整数-std::stoi
函数原型
//base : 转换字符所使用的进制数,如果为0,则使用的进制数由字符串的格式决定,默认值为10而不是0
int stoi (const string& str, size_t* idx = 0, int base = 10);
int stoi (const wstring& str, size_t* idx = 0, int base = 10);
代码范例
std::string numStr = "5646545";
int number1 = std::stoi(numStr);
注意:如果成功则返回转换的double型数值,如果转换失败,则会抛出invalid_argument异常,如果待转换的字符所代表的数值超出数值类型范围的两倍,则会抛出out_of_range异常。
8.4.字符串转长整数-std::stol
函数原型
//base : 转换字符所使用的进制数,如果为0,则使用的进制数由字符串的格式决定,默认值为10而不是0
long stol (const string& str, size_t* idx = 0, int base = 10);
long stol (const wstring& str, size_t* idx = 0, int base = 10);
代码范例
std::string numStr = "5646545";
int number1 = std::stol(numStr);
注意:如果成功则返回转换的double型数值,如果转换失败,则会抛出invalid_argument异常,如果待转换的字符所代表的数值超出数值类型范围的两倍,则会抛出out_of_range异常。
8.5.字符串转长双精度-std::stold
long double stold (const string& str, size_t* idx = 0);
long double stold (const wstring& str, size_t* idx = 0);
8.6.字符串转长长整型-std::stoll
long long stoll (const string& str, size_t* idx = 0, int base = 10);
long long stoll (const wstring& str, size_t* idx = 0, int base = 10);
8.7.字符串转无符号长整型-std::stoul
unsigned long stoul (const string& str, size_t* idx = 0, int base = 10);
unsigned long stoul (const wstring& str, size_t* idx = 0, int base = 10);
8.8.字符串转无符号长长整型-std::stoull
unsigned long long stoull (const string& str, size_t* idx = 0, int base = 10);
unsigned long long stoull (const wstring& str, size_t* idx = 0, int base = 10);
9.字符串类型判断-是否是数值
利用C++的输入特性来判断。
#include <sstream>
//是否为数字
static bool IsNum(std::string str)
{
std::stringstream ss(str);
double d;
char c;
if (!(ss >> d))
return false;
if (ss >> c)
return false;
return true;
}
10.字符串拼接+append
直接用+号,或者用string的append函数将字符串附加到末尾。
#include <string>
int main()
{
std::string str1;
str1 = "把握好眼前,";
str1.append("努力");//直接附加到现有字符串末尾。
//把握好眼前,努力
return 0;
}
11.字符串数组拼接成字符串-Join
#include <vector>
#include <string>
//链接字符串
std::string StringJoin(std::vector<std::string>& strs,const std::string pattern)
{
int size = strs.size();
std::string rlt;
for (int i = 0; i < size; i++)
{
if (i == 0)
{
rlt = strs[i] + pattern;
}
else if (i == size - 1)
{
rlt = rlt + strs[i];
}
else
{
rlt = rlt + strs[i] + pattern;
}
}
return rlt;
}
int main()
{
std::vector<std::string> strs = { "54","656" };
std::string rlt=StringJoin(strs,"");
return 0;
}
12.正则表达式
C++11 提供的正则表达式库操作 std::string 对象,模式 std::regex (本质是 std::basic_regex) 进行初始化,通过 std::regex_match 进行匹配,从而产生 std::smatch(本质是 std::match_results 对象)。
12.1.std::regex_match–是否匹配
#include <vector>
#include <iostream>
#include <string>
#include <regex>
int main() {
std::string fnames[] = { "foo.txt", "bar.txt", "test", "a0.txt", "AAA.txt" };
// 在 C++ 中 \ 会被作为字符串内的转义符,为使 \. 作为正则表达式传递进去生效,需要对 \ 进行二次转义,从而有 \\.
std::regex txt_regex("[a-z]+\\.txt"); //表达式
for (const auto &fname : fnames)
std::cout << fname << ": " << std::regex_match(fname, txt_regex) << std::endl;
return 0;
}
12.2.std::match_results-匹配结果
#include<iostream>
#include<string>
#include<regex>
int main()
{
std::string fnames[] = { "foo.txt", "bar.txt", "test", "a0.txt", "AAA.txt" };
// 在 C++ 中 \ 会被作为字符串内的转义符,为使 \. 作为正则表达式传递进去生效,需要
std::regex base_regex("([a-z]+)\\.txt");
std::match_results<std::string::const_iterator> base_match;
for (const auto& fname : fnames)
{
if (std::regex_match(fname, base_match, base_regex))
{
// std::smatch 的第一个元素匹配整个字符串
// std::smatch 的第二个元素匹配了第一个括号表达
if (base_match.size() == 2) {
std::string base = base_match[1].str();
std::cout << "sub-match[0]: " << base_match[0].str() << std::endl;
std::cout << fname << " sub-match[1]: " << base << std::endl;
}
}
}
return 1;
}
12.3.std::regex_search-搜索匹配
#include<regex>
#include<string>
#include<iostream>
int main()
{
std::string str = "hello2012-12-12world!!!!!";
std::match_results<std::string::const_iterator> match;
std::regex pattern("(\\d{4})-(\\d{1,2})-(\\d{1,2})");
if (std::regex_search(str, match, pattern))
{
for (size_t i = 1; i < match.size(); ++i)
{
std::cout << match[i] << std::endl;
}
}
return 0;
}
12.4.std::regex_search-替换匹配
#include<regex>
#include<string>
#include<iostream>
int main()
{
std::string str = "2019-08-07";
std::cout << std::regex_replace(str, std::regex("-"), "/") << std::endl;//2019/08/07
std::cout << str << std::endl;
return 0;
}
12.5.常用的正则表达式字符串
检验数字表达式
数字:^[0-9]*$
n位的数字:^\d{n}$
至少n位的数字:^\d{n,}$
m-n位的数字:^\d{m,n}$
零和非零开头的数字:^(0|[1-9][0-9]*)$
非零开头的最多带两位小数的数字:^([1-9][0-9]*)+(.[0-9]{1,2})?$
带1~2位小数的正数或负数:^(\-)?\d+(\.\d{1,2})?$
正数,负数,和小数:^(\-|\+)?\d+(\.\d+)?$
有两位小数的正实数:^[0-9]+(.[0-9]{2})?$
有1~3位小数的正实数:^[0-9]+(.[0-9]{1,3})?$
非零的正整数:^[1-9]\d*$或^([1-9][0-9]*){1,3}$或^\+?[1-9][0-9]*$
非零的负整数:^\-[1-9][]0-9″*$或^-[1-9]\d*$
非负整数:^\d+$或^[1-9]\d*|0$
非正整数:^-[1-9]\d*|0$或^((-\d+)|(0+))$
非负浮点数:^\d+(\.\d+)?$或^[1-9]\d*\.\d*|0\.\d*[1-9]\d*|0?\.0+|0$
非正浮点数:^((-\d+(\.\d+)?)|(0+(\.0+)?))$或^(-([1-9]\d*\.\d*|0\.\d*[1-9]\d*))|0?\.0+|0$
正浮点数:^[1-9]\d*\.\d*|0\.\d*[1-9]\d*$或^(([0-9]+\.[0-9]*[1-9][0-9]*)|([0-9]*[1-9][0-9]*\.[0-9]+)|([0-9]*[1-9][0-9]*))$
负浮点数:^-([1-9]\d*\.\d*|0\.\d*[1-9]\d*)$或^(-(([0-9]+\.[0-9]*[1-9][0-9]*)|([0-9]*[1-9][0-9]*\.[0-9]+)|([0-9]*[1-9][0-9]*)))$
浮点数:^(-?\d+)(\.\d+)?$或^-?([1-9]\d*\.\d*|0\.\d*[1-9]\d*|0?\.0+|0)$
检验字符串表达式
汉字:^[\u4e00-\u9fa5]{0,}$
英文和数字:^[A-Za-z0-9]+$或^[A-Za-z0-9]{4,40}$
长度为3~20的所有字符:^.{3,20}$
由26个英文字母组成的字符串:^[A-Za-z]+$
由26个大写英文字母组成的字符串:^[A-Z]+$
由26个小写英文字母组成的字符串:^[a-z]+$
由数字和26个英文字母组成的字符串:^[A-Za-z0-9]+$
由数字,26个英文字母或者下划线组成的字符串:^\w+$或^\w{3,20}$
中文,英文,数字包括下划线:^[\u4E00-\u9FA5A-Za-z0-9_]+$
中文,英文,数字但不包括下划线等符号:^[\u4E00-\u9FA5A-Za-z0-9]+$或^[\u4E00-\u9FA5A-Za-z0-9]{2,20}$
可以输入含有^%&',;=?$\"等字符:[^%&',;=?$\x22]+
禁止输入含有~的字符:[^~\x22]+
检验特殊表达式
Email地址:^\w+([-+.]\w+)*@\w+([-.]\w+)*\.\w+([-.]\w+)*$
域名:[a-zA-Z0-9][-a-zA-Z0-9]{0,62}(/.[a-zA-Z0-9][-a-zA-Z0-9]{0,62})+/.?
InternetURL:[a-zA-z]+://[^\s]*或^http://([\w-]+\.)+[\w-]+(/[\w-./?%&=]*)?$
手机号码:^(13[0-9]|14[5|7]|15[0|1|2|3|5|6|7|8|9]|18[0|1|2|3|5|6|7|8|9])\d{8}$
电话号码("XXX-XXXXXXX","XXXX-XXXXXXXX","XXX-XXXXXXX","XXX-XXXXXXXX","XXXXXXX"和"XXXXXXXX):^($$\d{3,4}-)|\d{3.4}-)?\d{7,8}$
国内电话号码(0511-4405222,021-87888822):\d{3}-\d{8}|\d{4}-\d{7}
身份证号(15位,18位数字):^\d{15}|\d{18}$
短身份证号码(数字,字母x结尾):^([0-9]){7,18}(x|X)?$或^\d{8,18}|[0-9x]{8,18}|[0-9X]{8,18}?$
帐号是否合法(字母开头,允许5~16字节,允许字母数字下划线):^[a-zA-Z][a-zA-Z0-9_]{4,15}$
密码(以字母开头,长度在6~18之间,只能包含字母,数字和下划线):^[a-zA-Z]\w{5,17}$
强密码(必须包含大小写字母和数字的组合,不能使用特殊字符,长度在8~10之间):^(?=.*\d)(?=.*[a-z])(?=.*[A-Z]).{8,10}$
日期格式:^\d{4}-\d{1,2}-\d{1,2}
一年的12个月(01~09和1~12):^(0?[1-9]|1[0-2])$
一个月的31天(01~09和1~31):^((0?[1-9])|((1|2)[0-9])|30|31)$