![](/img/trans.png)
[英]C++ String Subcript Out of Range when using string.length() as end of for loop
[英]c++ string.length() out of range as string.at() parameters
因此,我一直在研究一个可以反转字符的程序。 我已经通过string.length()和string.at()做到了。 但是,即使它没有超出范围,也会发生错误“超出范围”(我已经通过打印variabele的pos进行检查),我怀疑这是由数据类型不匹配引起的。 如果我错了纠正我。 这是我的代码。
#include "pch.h"
#include <iostream>
#include <conio.h>
#include <string>
using namespace std;
string compose(string temp) {
size_t temp1 = 0, temp2 = temp.length() - 1;
string temporary, temporary1;
cout << temp2;
while (temp2 < temp.length() / 2 + 1 || temp2 > temp.length() / 2 - 1) {
temporary1 = temp.at(temp1);
temporary = temp.at(temp2);
temp.replace(temp1, 1, temporary);
temp.replace(temp2, 1, temporary1);
temp1++;
temp2--;
}
return temp;
}
int main()
{
cout << compose("RPL X-1okewphevoiwrwrejfnjjjjjjjjjjjjjjjjjnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnn");
_getch();
return 0;
}
错误在这里:
while (temp2 < temp.length() / 2 + 1 || temp2 > temp.length() / 2 - 1) {
^-- should be -1
但是实际上检查本身是错误的。 理论上正确的是:
while (temp1 < temp.length() / 2 - 1 || temp2 > temp.length() / 2 - 1) {
^-- change here
但这甚至太多了。 只是检查
while (temp1 < temp.length() / 2 - 1)
应该足够了。 原因是您有temp1
和temp2
,其中一个从0
开始,另一个从字符串末尾开始。 每一步都增加temp1
和temp2
。 您必须区分2种情况:
但是对于这两种情况,仅检查变量之一是要通过字符串(甚至是长度字符串)的一半,还是要碰到中间的字符(奇数长度的字符串),而这是没有意义的,这就足够了。
正如“轨道中的竞速比赛”在评论中提到的那样,您必须确保传递的字符串不为空。 但是在这种情况下,您可以返回。
更改此:
while (temp2 < temp.length() / 2 + 1 || temp2 > temp.length() / 2 - 1)
至:
while (temp2 < temp.length() / 2 - 1 || temp2 > temp.length() / 2 - 1)
说明:
我已经通过打印variabele的pos检查了它
您的支票不足。 我做了:
cout << temp1 << " " << temp2 << endl;
在while循环主体的第一行,很明显temp2
下溢 ,这说明了超出范围的错误。
您所做的是强制将size_t
(将其想象为无符号整数)变量设置为低于0。 有关无符号整数下溢的C行为问题,请参见问题更多。
为了解决此问题,您需要了解导致temp2
下溢的原因。 在循环结束时,执行temp2--;
,将temp2
减1。
您应该通过在while循环中设置停止条件来控制执行此操作的次数。 Thats方法使我们可以专注于while循环中的停止条件。
使用“ bar”之类的输入,而不是在那里使用的那么大的字符串,您可以轻松地看到,当它变成“ rab”时, temp1
等于2,而temp2
等于0。
如果允许再次执行循环的主体,则将允许temp2
下溢,并在尝试使用temp2
时调用未定义行为(UB) 。
检查停止条件和计数器的值,可以看到您需要更改“或”条件的第一个操作数,如上所述。
作业:考虑如何简化停止条件。 以一个小的字符串作为示例输入,看看计数器temp1
和temp2
如何更新。
提示:一个条件就足够了(您不需要两个条件与逻辑或配对)。
PS:既然我们讨论了下溢,现在应该自然有人认为必须确保temp
不为空。 如果是,则此temp2 = temp.length() - 1;
会导致temp2
下溢!
因此,修改您的函数以在其第一行中执行if(temp.length() == 0) return "";
。
这一个就足够了(一点点吻):
#include <iostream>
#include <string>
using namespace std;
string compose(string temp) {
size_t temp1 = 0, temp2 = temp.length() - 1;
string temporary, temporary1;
size_t size = temp.length() /2;
size = size %2 == 0? size: size -1;
while (temp1 <= size) {
temporary1 = temp.at(temp1);
temporary = temp.at(temp2);
temp.replace(temp1, 1, temporary);
temp.replace(temp2, 1, temporary1);
temp1++;
temp2--;
}
return temp;
}
int main()
{
cout << compose("RPL X-1okewphevoiwrwrejfnjjjjjjjjjjjjjjjjj123456789");
cout << compose("1234");
cout << compose("12345");
return 0;
}
声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.