NO.28十六届蓝桥杯备战|string|insert|find|substr|关系运算|stoi|stol|stod|stof|to_string(C++)

insert

如果我们需要在字符串中间的某个位置插⼊⼀个字符串,得掌握⼀个函数就是insert

string& insert (size_t pos, const string& str); 
//pos位置前⾯插⼊⼀个string字符串  
string& insert (size_t pos, const char* s); 
//pos位置前⾯插⼊⼀个C⻛格的字符串  
string& insert (size_t pos, size_t n, char c);
//pos位置前⾯插⼊n个字符c

![[Pasted image 20250306211142.png]]

#include <iostream>  
#include <string>  
using namespace std;  
int main()  
{  
	string s = "abcdefghi";  
	string str = "xxx";  
	cout << s << endl;  
	s.insert(3, str);  
	cout << s << endl;  
	return 0;  
} 

#include <iostream>  
#include <string>  
using namespace std;  
int main()  
{  
	string s = "abcdefghi";  
	cout << s << endl;  
	s.insert(3, "xxx");  
	cout << s << endl;  
	return 0;  
} 

#include <iostream>
#include <string>  
using namespace std;  
int main()  
{  
	string s = "abcdefghi";  
	cout << s << endl;  
	s.insert(3, 3, 'x');  
	cout << s << endl;  
	return 0;  
}
find()

find() 函数⽤于查找字符串中指定⼦串/字符,并返回⼦串/字符在字符串中第⼀次出现的位置
![[Pasted image 20250306211421.png]]

size_t find (const string& str, size_t pos = 0) const;  
//查找string类型的字符串str,默认是从头开始查找,pos可以指定位置开始  
size_t find (const char* s, size_t pos = 0) const;  
//查找C⻛格的字符串s,默认是从头开始查找,pos可以指定位置开始  
size_t find (const char* s, size_t pos, size_t n) const;  
//在字符串的pos这个位置开始查找C⻛格的字符串s中的前n个字符,  
size_t find (char c, size_t pos = 0) const;  
//查找字符c,默认是从头开始,pos可以指定位置开始
  • 若找到。返回⼦串/字符在字符串中第⼀次出现的起始下标位置。
  • 若未找到。返回⼀个整数值 npos (针对 npos 的介绍会在下⾯给出)。通常判断 find() 函数的返回值是否等于 npos 就能知道是否查找到⼦串或者字符。
//代码1  
#include <iostream>  
#include <string> //添加string头⽂件  
using namespace std;  
int main()  
{  
	string s = "hello world hello everyone";  
	string str = "llo";  
	//查找string类型的字符串  
	size_t n = s.find(str);  
	cout << n << endl;  
	n = s.find(str, n + 1); //从n+1这个指定位置开始查找  
	cout << n << endl;  
	//查找C⻛格的字符串  
	n = s.find("llo");  
	cout << n << endl;  
	n = s.find("llo", n + 1); //从n+1这个指定位置开始查找  
	cout << n << endl;  
	
	return 0;  
}  

//代码2  
#include <iostream>  
#include <string> //添加string头⽂件  
using namespace std;  
int main()  
{  
	string s = "hello world hello everyone";  
	//在s中,0这个指定位置开始查找"word"中的前3个字符  
	size_t n = s.find("word", 0, 3);  
	cout << n << endl;  
	n = s.find("everyday", n+1, 5);  
	cout << n << endl;
	
	return 0;  
}  

//代码3  
#include <iostream>  
#include <string> //添加string头⽂件  
using namespace std;  
int main()  
{  
	string s = "hello world hello everyone";  
	size_t n = s.find('o');  
	cout << n << endl;  
	n = s.find('o', n + 1);  
	cout << n << endl;  
	
	return 0;  
}  

//查找不到的情况  
#include <iostream>  
#include <string> //添加string头⽂件  
using namespace std;  
int main()  
{  
	string s = "hello world hello everyone";  
	string str = "bit";  
	size_t n = s.find(str);  
	cout << n << endl;  
	if(n != string::npos)  
	cout << "找到了,位置是:" << n << endl;  
	else  
	cout << "没有找到" << endl;  
	
	return 0;  
}

在字符串中查找字符或者字符串时,有可能查找不到,这时候 find 函数会返回 npos 这个值,该数字并不是⼀个随机的数字,⽽是 string 中定义的⼀个静态常量 npos 。我们通常会判断 find 函数的返回值是否等于 npos 来判断,查找是否成功

static const size_t npos = -1;
#include <iostream>  
#include <string> //添加string头⽂件  
using namespace std;  
int main()  
{  
	//注意:npos是string中定义的,使⽤npos需要带上string::指明是string类中的  
	cout << "npos:" << string::npos << endl;  
	return 0;  
}

![[Pasted image 20250306212530.png]]

substr()

substr() 函数⽤于截取字符串中指定位置指定⻓度的⼦串。函数原型如下

string substr (size_t pos = 0, size_t len = npos) const;  
//pos 的默认值是0,也就是从下标为0的位置开始截取  
//len 的默认值是npos,意思是⼀直截取到字符串的末尾
  • substr() :如果函数不传参数,就是从下标为0的位置开始截取,直到结尾,得到的是整个字符串;
  • substr(pos) :从指定下标 pos 位置开始截取⼦串,直到结尾;
  • substr(pos, len) :从指定下标 pos 位置开始截取⻓度为 len 的⼦串
    ![[Pasted image 20250306213426.png]]

返回值类型: string ,返回的是截取到的字符串,可以使⽤ string 类型的字符串接收

#include <iostream>  
#include<string> //添加string头⽂件  
using namespace std;  
int main()  
{  
	string s = "hello world hello everyone";  
	string s1 = s.substr(7);  
	cout << s1 << endl;  
	string s2 = s.substr(7, 6);  
	cout << s2 << endl;
	
	return 0;  
}

![[Pasted image 20250306214201.png]]

substr() 和 find() 经常是配合使⽤的, find 负责找到位置, substr 从这个位置向后获得字符串

#include <iostream>  
#include<string> //添加string头⽂件  
using namespace std;  
int main()  
{  
	string s = "hello world hello everyone";  
	size_t n = s.find("world");  
	string s2 = s.substr(n, 10);  
	cout << s2 << endl;  
	
	return 0;  
}

![[Pasted image 20250306214235.png]]

string的关系运算

在实际写代码的过程中经常会涉及到两个字符串⽐较⼤⼩,⽐如:判断你输⼊的密码是否正确,就得将输⼊的密码和数据库中正确的密码⽐较。
那么两个 string 类型字符串是否可以⽐较⼤⼩呢?其实是可以的,C++中为string提供了⼀系列的关系运算。

⽀持的关系运算
string s1 = "abc";  
string s2 = "abcd";  
char s3[] = "abcdef"; //C⻛格的字符串  
(1) s1 == s2  
bool operator== (const string& lhs, const string& rhs);//使⽤⽅式:s1 == s2  
bool operator== (const char* lhs, const string& rhs);//使⽤⽅式:s3 == s1  
bool operator== (const string& lhs, const char* rhs);//使⽤⽅式:s1 == s3  
(2) s1 != s2  
bool operator!= (const string& lhs, const string& rhs);//使⽤⽅式:s1 != s2  
bool operator!= (const char* lhs, const string& rhs);//使⽤⽅式:s3 != s1  
bool operator!= (const string& lhs, const char* rhs);//使⽤⽅式:s1 != s3  
(3) s1 < s2  
bool operator< (const string& lhs, const string& rhs);//使⽤⽅式:s1 < s2  
bool operator< (const char* lhs, const string& rhs);//使⽤⽅式:s3 < s1  
bool operator< (const string& lhs, const char* rhs);//使⽤⽅式:s1 < s3  
(4) s1 <= s2  
bool operator<= (const string& lhs, const string& rhs);//使⽤⽅式:s1 <= s2  
bool operator<= (const char* lhs, const string& rhs);//使⽤⽅式:s3 <= s1  
bool operator<= (const string& lhs, const char* rhs);//使⽤⽅式:s1 <= s3  
(5) s1 > s2  
bool operator> (const string& lhs, const string& rhs);//使⽤⽅式:s1 > s2  
bool operator> (const char* lhs, const string& rhs);//使⽤⽅式:s3 > s1  
bool operator> (const string& lhs, const char* rhs);//使⽤⽅式:s1 > s3  
(6) s1 >= s2  
bool operator>= (const string& lhs, const string& rhs);//使⽤⽅式:s1 >= s2  
bool operator>= (const char* lhs, const string& rhs);//使⽤⽅式:s3 >= s1  
bool operator>= (const string& lhs, const char* rhs);//使⽤⽅式:s1 >= s3

字符串的⽐较是基于字典序进⾏的,⽐较是对应位置上字符的ASCII值的⼤⼩;⽐较的不是字符串的⻓度。

"abc" < "aq" //'b'的ascii码值是⼩于'q'的  
"abcdef" < "ff" //'a'的ASCII码值是⼩于'f'的  
"100" < "9" //'1'的ASCII码值是⼩于'9'的
#include <iostream>  
#include<string>  
using namespace std;  
int main()  
{  
	string s1 = "hello world";  
	string s2 = "hello";  
	if (s1 == (s2 + " world"))  
	{  
		cout << "s1 == s2" << endl;  
	}  
	else  
	{  
		cout << "s1 != s2" << endl;  
	}  
	
	return 0;  
}
#include <iostream>  
#include <string>  
using namespace std;  
int main()  
{  
	string s1 = "abcd";  
	string s2 = "abbcdef";  
	char s3[] = "bbc";
	if (s1 > s2)  
	cout << "s1 > s2" << endl;  
	else  
	cout << "s1 <= s2" << endl;  
	if (s1 == s2)  
	cout << "s1 == s2" << endl;  
	else  
	cout << "s1 != s2" << endl;  
	if (s1 <= s3)  
	cout << "s1 <= s3" << endl;  
	else  
	cout << "s1 > s3" << endl;  
	
	return 0;  
}

和string相关的函数

stoi/stol
  • stoi 是将字符串转换成 int 类型的值
  • stol 是将字符串转换成 long int 类型的值

stoi 函数其实可以将⼀个 string 类型的字符串,转化为整型,函数原型如下

int stoi (const string& str, size_t* idx = 0, int base = 10);  
long stol (const string& str, size_t* idx = 0, int base = 10);
  • str 表⽰被转换的 string 类型的字符串
  • idx 是⼀个输出型参数,也就是这个通过这个参数会带回⼀个值。 idx 是⼀个指针,需要在外边创建⼀个 size_t 类型的值,传递它的地址给 idx ,这个参数将会带回 str 中⽆法正确匹配数字的第⼀个字符的位置。
  • base 表⽰被解析的字符串中数字的进制值,可能是 2 , 8 , 10 , 16 或者 0
    • 默认情况下这个值是 10 ,表⽰ 10 进制数字
    • 如果传递的是 2 ,表⽰被解析的字符串中是 2 进制的数字,最终会转换成 10 进制
    • 如果传递的是 8 ,表⽰被解析的字符串中是 8 进制的数字,最终会转换成 10 进制
    • 如果传递的是 16 ,表⽰被解析的字符串中是 16 进制的数字,最终会转换成 10 进制
    • 如果传递的是 0 ,会根据字符串的内容的信息⾃动推导进制,⽐如:字符串中有 0x ,就认为是 16 进制, 0 开头会被认为是 8 进制,最终会转换成 10 进制。
#include <iostream>  
#include<string>  
using namespace std;  
int main()  
{  
	size_t pos = 0;  
	
	string s1 = "11x34";  
	int ret1 = stoi(s1, &pos, 16);  
	cout << ret1 << endl;  
	cout << "pos:" << pos << endl;  
	
	string s2 = "11x34";  
	int ret2 = stoi(s2, &pos, 2);  
	cout << ret2 << endl;  
	cout << "pos:" << pos << endl;  
	
	string s3 = "0x11x34";  
	int ret3 = stoi(s3, &pos, 0);  
	cout << ret3 << endl;  
	cout << "pos:" << pos << endl;  
	
	return 0;  
}

![[Pasted image 20250306215758.png]]

stod/stof

stod 是将字符串转换成 double 类型的值,函数原型如下,和 stoi 函数的⽐较的话,少了描述字符串中数字进制的参数,其他参数⼀致。 stof 是将字符串转换成 flaot 类型的值。

double stod (const string& str, size_t* idx = 0);  
float stof (const string& str, size_t* idx = 0);
#include <iostream>  
#include<string>  
using namespace std;  
int main()  
{  
	string s = "3.14x456";  
	double ret = stod(s, NULL);  
	cout << ret << endl;  
	
	return 0;  
}

![[Pasted image 20250306220100.png]]

to_string
string to_string (int val);  
string to_string (long val);  
string to_string (long long val);  
string to_string (unsigned val);  
string to_string (unsigned long val);
string to_string (unsigned long long val);  
string to_string (float val);  
string to_string (double val);  
string to_string (long double val);

tostring 函数可以将数字转换成字符串,从上述函数原型的⻆度看的话,可以将整型、浮点型的数字转换成字符串的,使⽤起来也⾮常简单。

#include <iostream>  
#include <string>  
using namespace std;  
int main()  
{  
	string pi = "pi is " + to_string(3.14159);  
	cout << pi << endl;  
	return 0;  
}
<think>嗯,用户现在问的是关于使用REGEXP_LIKE函数,具体是REGEXP_LIKE(L.LOTNO, '^' || substr(D.LOT_ID,1,7))。首先,我需要回忆一下这个函数的作用。REGEXP_LIKE在Oracle中是用来进行正则表达式匹配的,对吧?用户可能想通过正则表达式来匹配LOTNO字段的前七位和LOT_ID的前七位是否相同。 先看看用户之前的提问历史,之前他们是在修改一个IN子句,将其改为模糊匹配前七位。现在这个问题看起来是进一步优化或者另一种实现方式。用户可能想比较两种方法的差异,或者想知道这个正则表达式方法是否更有效。 接下来,我需要确认这个正则表达式的写法是否正确。'^' || substr(D.LOT_ID,1,7) 这里是用连接符将^和子字符串拼接起来,形成正则表达式的模式。比如,如果D.LOT_ID的前七位是ABCD123,那么正则表达式就是^ABCD123,这样就能匹配以这些字符开头的字符串。这个逻辑是对的,但需要确认substr函数在Oracle中的起始位置是否正确,因为substr的第二个参数是起始位置,第三个参数是长度,所以substr(D.LOT_ID,1,7)确实是从第一位开始取七个字符。 然后,需要考虑性能问题。正则表达式虽然灵活,但通常比普通的LIKE操作符更消耗资源。尤其是在处理大量数据时,可能会影响查询速度。用户之前用的是LIKE CONCAT(LEFT(...), '%'),现在换成正则表达式是否有必要呢?或者用户可能遇到了某些情况需要更复杂的模式匹配,所以才考虑正则表达式。 另外,用户可能想知道这种写法和之前的LIKE方法有什么区别。比如,正则表达式是否更精确,或者是否更容易扩展。比如,如果以后需要匹配更复杂的模式,正则表达式会更方便。但如果是简单的开头匹配,LIKE可能更高效。 还需要检查语法是否正确。在Oracle中,REGEXP_LIKE的语法是否正确?是的,REGEXP_LIKE(字符串, 模式)。这里的模式是否正确拼接了,比如是否需要用转义字符?比如,如果D.LOT_ID中有特殊字符,比如.或者*,这时候正则表达式可能会有问题。而使用LIKE的话,通配符只有%和_,相对安全。这时候可能需要转义,但用户这里只是取前七位,所以如果LOT_ID中没有正则表达式的特殊字符,那么应该没问题。 用户可能没有意识到正则表达式在这里可能带来的性能问题,或者特殊字符的问题,需要提醒他们注意这些点。同时,比较两种方法的优缺点,帮助他们选择最适合的方案。 另外,是否需要考虑大小写敏感?正则表达式在Oracle中默认是大小写敏感的,而LIKE可能取决于数据库的设置。如果LOTNO和LOT_ID是大小写不一致的,可能需要使用REGEXP_LIKE的修饰符,比如'i'来忽略大小写。 总结一下,用户的问题是要确认REGEXP_LIKE的这种用法是否正确,以及和之前的方法有什么不同。需要解释这个正则表达式的作用,可能的性能影响,特殊字符处理,大小写敏感等问题,并给出建议。</think>--- ### **分步解释:`REGEXP_LIKE(L.LOTNO, '^' || SUBSTR(D.LOT_ID,1,7))`** #### **1. 语法与功能** - **`REGEXP_LIKE`** 是 Oracle 数据库中用于正则表达式匹配的函数。 - **`^`** 是正则表达式中的锚定符,表示匹配字符串的开头。 - **`SUBSTR(D.LOT_ID,1,7)`** 提取 `D.LOT_ID` 的前七位字符。 - **组合逻辑**: 将 `^` 与 `SUBSTR(D.LOT_ID,1,7)` 的结果拼接,形成正则表达式模式,检查 `L.LOTNO` **是否以这七位字符开头**。 --- #### **2. 等价于 `LIKE` 的写法** 上述正则表达式可转换为 `LIKE` 语句: ```sql L.LOTNO LIKE SUBSTR(D.LOT_ID,1,7) || '%' ``` - **`SUBSTR(D.LOT_ID,1,7) || '%'`**:生成一个以 `D.LOT_ID` 前七位开头,后接任意字符的模式(例如 `ABC1234%`)。 --- #### **3. 两种方式的对比** | **特性** | **`REGEXP_LIKE`** | **`LIKE`** | |----------------------|---------------------------------------------|-------------------------------------| | **匹配规则** | 支持正则表达式复杂逻辑(如字符集、量词等) | 仅支持简单通配符(`%`, `_`) | | **性能** | 较慢(正则解析开销) | 更快(适合简单前缀匹配) | | **可读性** | 适合复杂模式 | 适合简单模式 | | **索引利用** | 通常无法利用索引 | 若前缀固定,可能利用索引 | --- #### **4. 使用场景建议** - **推荐 `LIKE`**:若只需匹配固定前缀(如前七位),`LIKE` 更高效。 - **需用 `REGEXP_LIKE`**:若需更复杂的匹配(如特定字符范围、多条件组合)。 --- #### **5. 完整示例** 假设需要关联表 `LOT_TABLE L` 和 `DRB_INFO_CONFIG D`: ```sql SELECT L.* FROM LOT_TABLE L WHERE EXISTS ( SELECT 1 FROM DRB_INFO_CONFIG D WHERE D.STATUS = '0' AND REGEXP_LIKE(L.LOTNO, '^' || SUBSTR(D.LOT_ID,1,7)) ); ``` --- #### **6. 潜在问题与优化** - **特殊字符问题** 如果 `D.LOT_ID` 的前七位包含正则表达式元字符(如 `.`, `*`, `$` 等),可能导致意外匹配。需对字符转义: ```sql AND REGEXP_LIKE(L.LOTNO, '^\Q' || SUBSTR(D.LOT_ID,1,7) || '\E') ``` (`\Q...\E` 表示对中间内容按字面量解析) - **性能优化** 如果数据量大,建议改用 `LIKE` 并结合前缀索引: ```sql CREATE INDEX idx_drb_lot_prefix ON DRB_INFO_CONFIG (SUBSTR(LOT_ID,1,7)); ``` --- ### **总结** - **`REGEXP_LIKE(L.LOTNO, '^' || SUBSTR(D.LOT_ID,1,7))`** 的作用是匹配 `L.LOTNO` 是否以 `D.LOT_ID` 的前七位开头。 - **简单前缀匹配优先选择 `LIKE`**,性能更优;复杂模式可使用 `REGEXP_LIKE`。 - 注意特殊字符和索引优化,以提升查询效率。
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值