C ++检查并修改字符串/字符串下标超出范围

时间:2017-02-24 13:50:33

标签: c++ arrays string pointers char

我试图制作一个以特定方式修改单词的程序: 它应首先检查单词的结尾,然后继续修改它们。我不会详细解释它,因为它在英语中没有多大意义。 我写了以下内容:

#include "stdafx.h"
#include <iostream>
#include <string>
using namespace std;

int main()
{
    cout << "Por favor, introduzca los gentilicios separados por la tecla enter, para finalizar, escriba OK" << '\n';
    string name[10];
    string place[10];
    for (int i(0); (i < 10); i++)
    {
        getline(cin, name[i]);
        if (name[i] == "OK")   //Error here
            break;      
    }

    for (int i(0); (i < 10); i++)
    {
        place[i] = name[i];
        if (name[i][name[i].length() - 1] == 'c')
            {
                if (name[i][name[i].length()] == 'a' || (name[i][name[i].length()] == 'o') || (name[i][name[i].length()] == 'u'))
                    place[i][place[i].length() - 1] = 'q';
                    place[i][place[i].length()] = 'u';
                    place[i] = place[i] + "istan";

        }
        else if (name[i][name[i].length()] == 'a' || name[i][name[i].length()] == 'e' || name[i][name[i].length()] == 'i' || name[i][name[i].length()] == 'o' || name[i][name[i].length()] == 'u')
        {
            place[i][place[i].length()] = 'i';
            place[i] = place[i] + "stan";
        }

        if (name[i][name[i].length()] == 's')
            place[i] = place[i] + "tan";
        else {
            place[i] = place[i] + "istan";
        }

        place[i][0] = toupper(place[i][0]);



    }

    for (int i(0); (i < 10); i++)
    {
        cout << place[i] << '\n';
    }

    return 0;
}

现在我收到错误&#34;字符串下标超出范围&#34; 。我想知道错误到底在哪里。我知道它在我写#34; OK&#34;,在#34; 18&#34;线时提示。

6 个答案:

答案 0 :(得分:1)

条件i <= sizeof(name)sizeof(name) bytes 返回数组的大小,其中的元素数。即使它返回了元素数量,<=也是错误的并且会导致越界访问(应该是<)。

要循环遍历数组中的所有元素,可以使用基于范围的for循环:

for(auto& n : name)
{
    getline(cin, n);
    if (n == "OK")
        break;      
}

或者以正确的方式使用C风格的for循环:

for (int i(0); i < sizeof(name)/sizeof(name[0]; i++)
{
    …
}

答案 1 :(得分:0)

下面:

  for (int i(0); (i <= sizeof(name)); i++)

sizeof(name)是数组的字节大小,因为它是std :: string的数组实际上没有意义。如果你想迭代10个项目,那么就这么说(注意这里的小于或等于也是错误的):

  for (int i = 0; i < 10; i++)

在这里:

   getline(cin, name[i]);

无论何时执行输入,都必须检查输入函数的返回值并处理任何错误:

   if( ! getline(cin, name[i]) ) {
       // handle error somehow
   }

在这里:

  string * p;

想要处理指向字符串的指针。如果要访问字符串的内容,可以在字符串上使用operator []或其他字符串成员函数。

答案 2 :(得分:0)

std::string与cstrings不同。你可以使用std::string*抓住其中的一部分。当你这样做

*(p+ (name[i].length()-2))

您实际上是说将p中存储的地址提前name[i].length()-2金额并访问该字符串。如果超过name数组的末尾,那么这是未定义的行为。如果不是,您仍有std::string无法与char进行比较。如果要检查字符串是否以"ca"结尾,则可以使用

if (name[i].substr(name[i].size() - 2) == "ca")

答案 3 :(得分:0)

你最后一个循环是做一些非常时髦的事情。没有必要走那么远。你可以这样做:

if (name[i][name[i].length - 2] == 'c')

将下一个到最后一个字符与c进行比较。还有一个非常相似的测试来比较最后一个和。

为了澄清为什么你做的不行,你首先得到p作为指向当前元素的字符串的指针。然后你做一些指针算术p + (name[i].length - 2),它仍然会产生一个指向字符串的指针。最后,你取消引用它,产生一个字符串。哪个你不能比较char。此外,指针指向内存中的某个任意地址,因此取消引用会产生一个字符串,其中包含非常糟糕的数据。有人可能会说,这很随意。如果您尝试使用它,则会破坏您的程序

您似乎正在使用字符串,就像使用类似C的字符串char*一样。两者并不相同,即使它们代表相同的概念。 C ++字符串通常有一个size字段,里面有一个char*指针,还有一堆其他逻辑可以使用 char -m。

答案 4 :(得分:0)

因为您没有与字符串中的特定字符进行比较,您正在与字符串进行比较

考虑以下代码:

*(p + (name[i].length() - 2))

这会计算为字符串,因为您正在使用 p (字符串*)并将char连接到它。这意味着它的仍然是一个字符串(即使它是一个单字符串),因此等式的另一面将无法与它相比

这里你需要的是:

if (name[i][name[i].length() - 2] == 'c')

由于 name [i] 已经是一个字符串,我们可以使用上面的代码从中获取 char 。这个 返回char,因此它具有可比性。这也允许你删除整个字符串*位,因为它不需要。

答案 5 :(得分:0)

首先,(i <= sizeof(name))是错误的,它应该是i < sizeof(name) / sizeof(*name)sizeof(array)以字节为单位返回array的大小,您需要将array元素的大小除以实际获取数组的最大元素数。如果您发现那么复杂,请使用std::vector

vector<string> name(10);  //a vector of size 10

for (size_t i = 0; i < name.size(); i++)  //name.size(), simple

其次,您需要跟踪name数组中的字符串数。或者你需要检查name[i] == "OK"是否打破第二个循环(类似于第一个循环)。 <{1}}无效后name[i]

第三,不要使用"OK"。如果您想要*(p+ (name[i].length()-2))的倒数第二个字符,可以将其写为name[i]name[i][name[i].size()-2]name[i].end()[-2]

如果您想检查单词是否以“ca”结尾,那么您可以使用substr

end(name[i])[-2]