我最近做了这个问题
规格:
输入格式第一行包含测试用例数T.下一步, T行跟随每个包含长字符串S.
输出格式对于每个长字符串S,显示
SUVO
的次数 并且SUVOJIT
出现在其中。
我为此编写了以下代码:
#include <bits/stdc++.h>
using namespace std;
int main() {
int t;
cin >> t;
while (t--) {
int suvo = 0;
int suvojit = 0;
string s;
cin >> s;
for (int i = 0; i <= s.size() - 7; i++) {
if (s.substr(i, 7) == "SUVOJIT")
suvojit++;
}
for (int i = 0; i <= s.size() - 4; i++) {
if (s.substr(i, 4) == "SUVO")
suvo++;
}
cout << "SUVO = " << suvo - suvojit << ", SUVOJIT = " << suvojit << "\n";
}
return 0;
}
关于此测试用例的substr()
函数的有关超出范围异常的代码:
15
RSUVOYDSUVOJITNSUVOUSUVOJITESUVOSUVOSGSUVOKSUVOJIT
SUVOJITWSUVOSUVOJITTSUVOCKSUVOJITNSUVOSUVOJITSUVOJITSUVOSUVOSUVOJITTSUVOJ
SUVOSUVOSUVOJITASUVOJITGCEBISUVOJITKJSUVORSUVOQCGVHRQLFSUVOOHPFNJTNSUVOJITKSSUVO
SUVOJITSUVOJITJGKSUVOJITISUVOJITKJLUSUVOJITUBSUVOX
MMHBSUVOFSUVOFMSUVOJITUMSUVOJITPSVYBYPMCSUVOJIT
OASUVOSUVOJITSUVOSTDYYJSUVOJITSUVOJITSUVO
RLSUVOCPSUVOJITYSUVOSUVOOGSUVOOESUVOJITMSUVO
WVLFFSUVOJITSUVOVSUVORLESUVOJITPSUVOJITSUVO
RSUVOSUVOJITQWSUVOUMASUVOSUVOJITXNNRRUNUSUVOJIT
HYLSSUVOSUVOSUVOJITPOSUVOJIT
DGMUCSSSUVOJITMJSUVOHSUVOCWTGSUVOJIT
OBNSSUVOYSUVOSUVOJITSUVOJITRHFDSUVODSUVOJITEGSUVOSUVOSUVOJITSUVOSUVOJITSSUVOSUVOSUVOSSUVOJIT
AG
NSUVOJITSUVOSUVOJIT
CGJGDSUVOEASUVOJITSGSUVO
但是,当我不使用s.size()
函数时,我将字符串转换为char
常量并使用strlen
获取它的长度,然后代码没有导致错误和所有内容顺利进行。
所以,我的问题是......为什么会这样?
这是我改变的工作代码:
#include <bits/stdc++.h>
using namespace std;
int main() {
int t;
cin >> t;
while (t--) {
int suvo = 0;
int suvojit = 0;
string s;
cin >> s;
int le = strlen(&s[0]);
for (int i = 0; i <= le - 7; i++) {
if (s.substr(i, 7) == "SUVOJIT")
suvojit++;
}
for (int i = 0; i <= le - 4; i++) {
if (s.substr(i, 4) == "SUVO")
suvo++;
}
cout << "SUVO = " << suvo - suvojit << ", SUVOJIT = " << suvojit << "\n";
}
return 0;
}
答案 0 :(得分:3)
在一种情况下,使用size_t,在另一种情况下使用int。
如果长度是例如6个字符,那么s.size() - 7不是-1,而是一个巨大的数字,一切都出错了。但是如果你写int len = strlen(...),那么len - 7确实是-1,一切都很好。
当我看到从size_t中减去一个数字时,这是一个直接的红旗。写“i +7≤s.size()”,而不是“i≤s.size() - 7”。
答案 1 :(得分:1)
首先,在我的测试中,你的第二个导致了一个问题:
其次,特别是对于较旧的编译器(好吧,库,真的),这可能可怕效率低下,创建了大量的临时字符串,只用于与另一个字符串进行比较 1 < / SUP>
所以,让我们考虑一下应该如何完成工作。对于这种情况,std::string
有一个名为find
的成员。它返回一个字符串在另一个字符串中的位置,如果没有,则返回std::string::npos
。当您不想从头开始时,它允许您指定开始搜索的起始位置。
当然,我们还有两个基本相同的代码实例,一次搜索SUVO
,另一次搜索SUVOJIT
。将搜索代码移入函数后,代码会好得多,因此我们只将搜索代码放在一个位置。
int count_pos(std::string const &haystack, std::string const &needle) {
size_t pos = 0;
int ret = 0;
while ((pos = haystack.find(needle, pos)) != std::string::npos) {
++ret;
++pos;
}
return ret;
}
请注意,这也消除了更多混乱的“东西”,比如必须计算匹配时可能发生的最大位置。
1.为什么编译器/库年龄很重要?较旧的库通常使用COW字符串,为每个字符串动态分配存储空间。最近的那些通常包括所谓的“短字符串优化”,其中短字符串的存储在字符串对象本身内分配,从而避免动态分配。 功能