简体   繁体   English

c ++ string.length()作为string.at()参数超出范围

[英]c++ string.length() out of range as string.at() parameters

So I've been working on a program that invert it's characters. 因此,我一直在研究一个可以反转字符的程序。 And I've doing it by string.length() and string.at(). 我已经通过string.length()和string.at()做到了。 But, it occur error "out of range" even though it's not out of range (I've checked it by print the pos of at variabele) I suspected it's caused of data types mismatch. 但是,即使它没有超出范围,也会发生错误“超出范围”(我已经通过打印variabele的pos进行检查),我怀疑这是由数据类型不匹配引起的。 Correct me if I'm wrong. 如果我错了纠正我。 This is my code. 这是我的代码。

 #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;
}

The error is here: 错误在这里:

while (temp2 < temp.length() / 2 + 1 || temp2 > temp.length() / 2 - 1) {
                                 ^-- should be -1

But actually the check itself is wrong. 但是实际上检查本身是错误的。 In theory correct would be: 理论上正确的是:

while (temp1 < temp.length() / 2 - 1 || temp2 > temp.length() / 2 - 1) {
           ^-- change here

But even this is too much. 但这甚至太多了。 Just checking 只是检查

while (temp1 < temp.length() / 2 - 1)

Should be enough. 应该足够了。 The reason is you have temp1 and temp2 where one starts from 0 and the other one from the end of the string. 原因是您有temp1temp2 ,其中一个从0开始,另一个从字符串末尾开始。 Each step you increase temp1 and decrease temp2 . 每一步都增加temp1temp2 You have to distinguish 2 cases: 您必须区分2种情况:

  • string length is even 字符串长度是偶数
  • string length is odd 字符串长度是奇数

But for both cases it's enough to just check one of the variables if they are about to pass halfway through the string (even length string) or about to hit the middle character (odd length string) where a switch is pointless. 但是对于这两种情况,仅检查变量之一是要通过字符串(甚至是长度字符串)的一半,还是要碰到中间的字符(奇数长度的字符串),而这是没有意义的,这就足够了。

And as Lightness Races in Orbit mentions in the comments you have to make sure the passed string is not empty. 正如“轨道中的竞速比赛”在评论中提到的那样,您必须确保传递的字符串不为空。 But in that case you can just return. 但是在这种情况下,您可以返回。

Change this: 更改此:

while (temp2 < temp.length() / 2 + 1 || temp2 > temp.length() / 2 - 1)

to: 至:

while (temp2 < temp.length() / 2 - 1 || temp2 > temp.length() / 2 - 1)

Explanation: 说明:

I've checked it by print the pos of at variabele 我已经通过打印variabele的pos检查了它

Your check was insufficient. 您的支票不足。 I did a: 我做了:

cout << temp1 << " " << temp2 << endl;

at the first line of the body of the while loop, and it was obvious that temp2 was underflow ing, which explains the out of range error. 在while循环主体的第一行,很明显temp2 下溢 ,这说明了超出范围的错误。

What you did was to force a size_t (imagine it as an unsigned integer) variable go below 0. Read more in Question about C behaviour for unsigned integer underflow . 您所做的是强制将size_t (将其想象为无符号整数)变量设置为低于0。 有关无符号整数下溢的C行为问题,请参见问题更多。

In order to fix this, you need to understand what allows your temp2 to underflow. 为了解决此问题,您需要了解导致temp2下溢的原因。 At the end of your loop, you do temp2--; 在循环结束时,执行temp2--; ,, which decrements temp2 by 1. ,将temp2减1。

You should control how many times this gets executed, by having a stop condition in your while loop. 您应该通过在while循环中设置停止条件来控制执行此操作的次数。 Thats approach allows us to focus on the stop condition in the while loop. Thats方法使我们可以专注于while循环中的停止条件。

With an input like "bar", and not that big string you use there, you can easily see, that by the time it gets inverted into "rab", temp1 is equal to 2 and temp2 is equal to 0. 使用“ bar”之类的输入,而不是在那里使用的那么大的字符串,您可以轻松地看到,当它变成“ rab”时, temp1等于2,而temp2等于0。

If you allow the body of the loop of to get executed once more, you will then allow temp2 to underflow, invoking Undefined Behavior (UB) , when you try to use temp2 . 如果允许再次执行循环的主体,则将允许temp2下溢,并在尝试使用temp2调用未定义行为(UB)

Checking the stop condition and the values of your counters, you can see that you need to change the first operand of the OR condition, as explained above. 检查停止条件和计数器的值,可以看到您需要更改“或”条件的第一个操作数,如上所述。


Homework: Think how you can simplify your stop condition. 作业:考虑如何简化停止条件。 Take a small string as an example input and see how counters temp1 and temp2 update themselves. 以一个小的字符串作为示例输入,看看计数器temp1temp2如何更新。

Hint: One condition will suffice (you do not need two conditions paired with a logical OR). 提示:一个条件就足够了(您不需要两个条件与逻辑或配对)。


PS: Since we discussed about underflow, it should be natural now for someone to think that temp must be ensured that is not empty. PS:既然我们讨论了下溢,现在应该自然有人认为必须确保temp不为空。 If it is, then this temp2 = temp.length() - 1; 如果是,则此temp2 = temp.length() - 1; would result in temp2 to underflow! 会导致temp2下溢!

So, modify your function to do in its first line if(temp.length() == 0) return ""; 因此,修改您的函数以在其第一行中执行if(temp.length() == 0) return ""; .

This one should be enough (little bit KISS): 这一个就足够了(一点点吻):

#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.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM