【问题标题】:String subscript out of range (Visual Studio 2013)字符串下标超出范围(Visual Studio 2013)
【发布时间】:2018-02-28 22:46:19
【问题描述】:

我了解到,与此标题/问题有关的问题之前已被多次询问(herehere 和许多其他人)。这是我的代码,后面是我为消除错误所做的一切:

CaesarCipher.h

#ifndef CAESARCIPHER_H
#define CAESARCIPHER_H

#include <ctime> 
#include <string>

using namespace std;

// Write your class CaesarCipher here.
class CaesarCipher 
{
public:
    CaesarCipher();
    string Encode(string plainString);
    string Decode(string encryptedString);
private:
    int key1, key2;
    char Encode(char normalChar)const;
    char Decode(char encodedChar)const;
};
#endif

CaesarCipher.cpp

#include "stdafx.h"
#include "CaesarCipher.h"

using namespace std;
// Implement the member functions of class CaesarCipher.

CaesarCipher::CaesarCipher()
{
    //Random initialization of integer key1

    //srand(time(0));
    srand((unsigned int)time(0));       
    int value1 = rand() % 10;
    int sign1 = rand() % 2;
    sign1 = sign1 == 0 ? -1 : 1;
    int key1 = value1 * sign1;

    //Random initialization of integer key2

    //srand(time(0));
    srand((unsigned int)time(0));
    int value2 = rand() % 10;
    int sign2 = rand() % 2;
    sign2 = sign2 == 0 ? -1 : 1;
    int key2 = value2 * sign2;
}

char CaesarCipher::Encode(char normalChar) const
{
    int result=0;
    int charValue = normalChar; //get the ASCII decimal value of character
    if (charValue == 32)        // if characeter is a space, we leave it 
{
    result = 32;
}
else
{
    if (key1 > 0)
    {
        result = char(int(charValue + key1 - 97) % 26 + 97);        // find the integer value of char after rotating it with key1(positive)
    }
    if (key1 < 0)
    {
        result = char(int(charValue -key1 - 97) % 26 + 97);         // find the integer value of char after rotating it with key1(negative)
    }
    if (key2 > 0)
    {
        result += char(int(charValue + key2 - 97) % 26 + 97);       // find the updated integer value of char after rotating it with key2(positive)
    }
    if (key2 < 0)
    {
        result += char(int(charValue - key2 - 97) % 26 + 97);       // find the updated integer value of char after rotating it with key2(negative)
    }
}
return result;                                  // returning the integer value which will be typecasted into a char(encoded char)
}

char CaesarCipher::Decode(char encodedChar) const
{
    int result = 0;
    int charValue = encodedChar; //get the ASCII decimal value of encoded character
    if (charValue == 32)        // if characeter is a space, we leave it unchanged
    {
        result = 32;
    }
    else
    {
        if (key1 > 0)
        {
            result = char(int(charValue - key1 - 97) % 26 + 97); // find the integer value of encoded char after rotating it with key1(positive) in opposite direction
        }
        if (key1 < 0)
        {
            result = char(int(charValue + key1 - 97) % 26 + 97); // find the integer value of encoded char after rotating it with key1(negative) in opposite direction
        }
        if (key2 > 0)
        {
            result += char(int(charValue - key2 - 97) % 26 + 97);       // find the updated integer value of encoded char after rotating it with key2(positive) in opposite direction
        }
        if (key2 < 0)
        {
            result += char(int(charValue + key2 - 97) % 26 + 97);       // find the updated integer value of encoded char after rotating it with key2(negative) in opposite direction
        }
    }
    return result;                                  // returning the integer value which will be typecasted into a char(decrypted char)
}

string CaesarCipher::Encode(string plainString)
{
    int length = plainString.length();          //gets the length of the 
    input string
    string encodedString;                       // variable to hold the final encrypted string
    for (int i = 0; i < length; i++)
    {
        encodedString[i] = Encode(plainString[i]); // encrypting the string one character at a time
    }
    return encodedString;                           // return the final encoded string
}

string CaesarCipher::Decode(string encryptedString)
{
    int length = encryptedString.length();  //gets the length of the input encrypted string
    string decodedString;                   // variable to hold the final decrypted string
    for (int i = 0; i < length; i++)
    {
        decodedString[i] = Decode(encryptedString[i]);      // decrypting the string one character at a time
    }
    return decodedString;                                   // return the final decoded string
}

如果有任何帮助,我正在使用两个密钥来加密文本(key1 后跟 key2)。

Main.cpp

#include "stdafx.h"
#include "CaesarCipher.h"
#include <fstream>
#include <iostream>

int main() {
    // File streams
    ifstream fin("input.txt");
    ofstream fout("output.txt");

    if (!fin.good()) {
        cout << "Error: file \"input.txt\" does not exist!" << endl;
        return -1;
    }

    string original[20], encrypted[20], decrypted[20];
    int i = 0;      // will store the number of lines in the input file
    CaesarCipher cipher;    // an object of CaesarCipher class
    // Read the sentences from the input file and save to original[20].
    // Hint: use getline() function.
    while (!fin.eof())
    {
        getline(fin, original[i]);                      // Reading a line from input.txt file 
        encrypted[i] = cipher.Encode(original[i]);      // Encrypt the sentences and save to encrypted[20]
        decrypted[i] = cipher.Decode(encrypted[i]);     // Decrypt the sentences and save to decrypted[20]
        i++;
    } 

    //first output all the encrypted lines
    for (int j = 0; j < i; j++)
    {
        fout << "Encrypted sentences:\n";
        fout << encrypted[j]<<"\n";
    }

    //now output all the decrypted lines
    for (int j = 0; j < i; j++)
    {
        fout << "Decrypted sentences:\n";
        fout << decrypted[j] << "\n";
    }

    // Close the files and end the program.
    fin.close();
    fout.close();
    cout << "done!";
    return 0;
}

我得到的错误是Expression: string subscript out of range。现在我明白我正在尝试迭代超出字符串的限制(可能在编码器或解码器函数的 CaesarCipher.cpp 中的某个地方)。

我试图更改i 的限制,但没有任何效果。

我曾尝试使用size() 而不是length()(尽管知道他们做同样的事情,但还是很绝望)。

如果您能特别指出可能导致此错误的任何事情,我将不胜感激,我会尝试自行更改并查看结果。

如果你也能说出,未来如何避免这样的错误,这对我来说也很有价值。

【问题讨论】:

  • 这里的代码似乎太多了。在调试器中对异常点击 Retry 并查看调用堆栈,您观察到了什么?

标签: c++ string loops for-loop file-handling


【解决方案1】:

CaesarCipher::Encode() 没有为encodedString 的字符数据分配任何内存,因此循环对encodedString[i] 的访问无效。要解决这个问题,可以:

  1. 使用string encodedString = plainString;复制输入字符串,然后循环可以操作复制的数据:

    string CaesarCipher::Encode(string plainString) {
        int length = plainString.length(); //gets the length of the input string
        string encodedString = plainString; // variable to hold the final encrypted string
        for (int i = 0; i < length; i++) {
            encodedString[i] = Encode(encodedString[i]); // encrypting the string one character at a time
        }
        return encodedString; // return the final encoded string
    } 
    
  2. 在进入循环之前使用encodedString.resize(length)预分配输出字符串:

    string CaesarCipher::Encode(string plainString) {
        int length = plainString.length(); //gets the length of the input string
        string encodedString; // variable to hold the final encrypted string
        encodedString.resize(length); // allocate memory for the final encoded string
        for (int i = 0; i < length; i++) {
            encodedString[i] = Encode(plainString[i]); // encrypting the string one character at a time
        }
        return encodedString; // return the final encoded string
    } 
    
  3. 使用encodedString += plainString[i]; 将字符附加到输出字符串并让它根据需要增长:

    string CaesarCipher::Encode(string plainString) {
        int length = plainString.length(); //gets the length of the input string
        string encodedString; // variable to hold the final encrypted string
        for (int i = 0; i < length; i++) {
            encodedString += Encode(plainString[i]); // encrypting the string one character at a time
        }
        return encodedString; // return the final encoded string
    } 
    

CaesarCipher::Decode() 中存在与 decodedString 变量相同的问题。


此外,如果input.txt 中的行数超过 20 行,main() 就会出现缓冲区溢出。考虑更改代码以使用std::vector 而不是固定数组。

还有while (!fin.eof()) is wrong to use。请改用while (getline(...))

// Read the sentences from the input file and save to original[20].
// Hint: use getline() function.
string line;
while (getline(fin, line)) { // Reading a line from input.txt file
    original[i] = line;
    encrypted[i] = cipher.Encode(original[i]); // Encrypt the sentences and save to encrypted[20]
    decrypted[i] = cipher.Decode(encrypted[i]); // Decrypt the sentences and save to decrypted[20]
    i++;
} 

【讨论】:

  • 我尝试了 encodedString.resize(length) 的东西,它正在工作(编译)。你能分享一下你是如何发现没有内存分配的吗?其次,我也有使用向量的想法,但它的部分描述使用数组和输入文件不会包含超过 20 行,所以我认为我可以忽略缓冲区溢出问题(对于这个特定实例)跨度>
  • @PiyushMenghani string encodedString; 默认构造 string,其中没有数据。因此encodedString[i] 尝试访问一个不存在的字符。
猜你喜欢
  • 2021-11-15
  • 2015-03-31
  • 2013-04-22
  • 2012-04-27
  • 1970-01-01
  • 2014-08-04
  • 1970-01-01
  • 1970-01-01
相关资源
最近更新 更多