【问题标题】:Segmentation fault in 2-d Array二维数组中的分段错误
【发布时间】:2021-07-17 08:41:56
【问题描述】:

我正在解决这个问题:

Coding Problem
Problem Statement: Edit Distance
Problem Level: MEDIUM
Problem Description:
You are given two strings S and T of lengths M and N, respectively. Find the 'Edit Distance' between the strings.
Edit Distance of two strings is the minimum number of steps required to make one string equal to the other. In order to do so, you can perform the following three operations:
1. Delete a character
2. Replace a character with another one
3. Insert a character

Note :
Strings don't contain spaces in between.

Input format :
The first line of input contains the string S of length M.

The second line of the input contains the String T of length N.

Output format :
Print the minimum 'Edit Distance' between the strings.

Constraints :
0 <= M <= 10 ^ 3
0 <= N <= 10 ^ 3

Time Limit: 1 sec

Sample Input 1 :
abc
dc

Sample Output 1 :
2

Explanation to the Sample Input 1 :
 In 2 operations we can make string T to look like string S.
First, insert character 'a' to string T, which makes it "adc".

And secondly, replace the character 'd' of string T with 'b' from the string S. This would make string T as "abc" which is also string S.

Hence, the minimum distance.

Sample Input 2 :
whgtdwhgtdg
aswcfg

Sample Output 2 :
9

我为此编写了以下代码:

#include <iostream>
using namespace std;
int EditDistance(string s, string t, int **arr)
{
    int i = s.size();
    int j = t.size();
    //Base Case
    if (t.size() == 0 || s.size()==0)
    {
        return max (s.size(),t.size());
    }
    int x, y, z, min_num;
    if (arr[i][j] != (-1))
    {
        return arr[i][j];
    }
    //Recursive Case
    if (s[0] == t[0])
    {
        arr[i][j] = EditDistance(s.substr(1), t.substr(1), arr);
        return arr[i][j];
    }
    else
    {
        x = 1 + EditDistance(s.substr(1), t, arr);
        y = 1 + EditDistance(s, t.substr(1), arr);
        z = 1 + EditDistance(s.substr(1), t.substr(1), arr);
        min_num = min(x, min(y, z));
        arr[i][j] = min_num;
    }
    return min_num;
}
int EditDistance(string s, string t)
{
    int a = s.size() + 1; //rows
    int b = t.size() + 1; //columns
    int **arr = new int *[b];
    for (int i = 0; i < b; i++)
    {
        arr[i] = new int[a];
    }
    for (int i = 0; i < a; i++)
    {
        for (int j = 0; j < b; j++)
        {   cout << "Value of i is " << i <<endl;
            cout << "Value of j is " << j <<endl;
            arr[i][j] = (-1);
            cout << "Value of array is " << arr[i][j] <<endl;
        }
    }
    return EditDistance(s, t, arr);
    delete[]arr;
}
int main()
{
    string s1, s2;
    cout << "Enter the two strings" << endl;
    cin >> s1 >> s2;
    cout << EditDistance(s1, s2) << endl;
    return 0;
}

但是,当我尝试输入“abc”和“ab”作为字符串时,它会在函数int EditDistance(string s, string t) 的arr[i][j] = (-1) 行的i=3 和j=0 处出现分段错误。但是,我真正无法理解的是,当我创建了一个大小为 4*3 的二维数组时,为什么我会收到分段错误,然后访问元素 arr[3][0] 不应该给我分段错误。有人可以帮忙吗?

【问题讨论】:

  • 不是问题,但可能是错误的 - if (t.size() == 0 || t.size()==0)。也是很好的做法int x, y, z, min_num;,如果你不能初始化变量,你应该延迟它们的声明,直到你可以。
  • 感谢您指出,但这不是问题@RichardCritten
  • @RichardCritten 谢谢你的建议,但你能回答我问的问题吗?
  • int **arr = new int *[b]; 更喜欢std::vector&lt; std::vector&lt; int &gt; &gt; arr; 尽量不要使用 c 数组。
  • 正在阅读您的代码 - 这几乎不是 minimal reproducible example - 最短的正确答案是 "user a debugger" 并自己发现这不是一项付费服务​​。

标签: c++ debugging segmentation-fault dynamic-programming


【解决方案1】:

好的,Levenshtein 距离。 . .

存在一个语义错误。否则程序正常。

那么你会犯很多风格错误。您正在使用new 和原始指针来获取拥有的内存。在 C++ 中,这样的原始指针被认为是邪恶的,不应使用。在任何情况下。

此外,您忘记了释放拥有的内存。您的 delete 语句是无法访问的代码区域。而且它只删除一个维度。

如果您使用有意义的变量名,那么您会立即看到您的问题。看这里。

 int numberOfRows = s.size() + 1; //rows
    int numberOfColumns = t.size() + 1; //columns

    int **arr = new int *[numberOfColumns];
    for (int columnIndex = 0; columnIndex < numberOfColumns; columnIndex++)
    {
        arr[columnIndex] = new int[numberOfRows];
    }

    for (int rowIndex = 0; rowIndex < numberOfRows; rowIndex++)
    {
        for (int columnIndex = 0; columnIndex < numberOfColumns; columnIndex++)
        {   cout << "Value of i is " << rowIndex << endl;
            cout << "Value of j is " << columnIndex << endl;
            arr[rowIndex][j] = (-1);
            cout << "Value of array is " << arr[rowIndex][columnIndex] <<endl;
        }
    }

您只是混淆了行和列。索引是扭曲的。

更正该问题并将语言切换为 C++,将为您提供以下基本相同的代码:

#include <iostream>
#include <string>
#include <algorithm>


int EditDistanceRecursive(const std::string& stringLeft, const std::string& stringRight, int** arr)
{
    size_t sizeOfStringLeft = stringLeft.size();
    size_t sizeOfStringRight = stringRight.size();

    //Base Case
    if (stringLeft.empty() || stringRight.empty())
    {
        return std::max(stringLeft.size(), stringRight.size());
    }

    int x, y, z, min_num;
    if (arr[sizeOfStringLeft][sizeOfStringRight] != (-1))
    {
        return arr[sizeOfStringLeft][sizeOfStringRight];
    }

    //Recursive Case
    if (stringLeft[0] == stringRight[0])
    {
        arr[sizeOfStringLeft][sizeOfStringRight] = EditDistanceRecursive(stringLeft.substr(1), stringRight.substr(1), arr);
        return arr[sizeOfStringLeft][sizeOfStringRight];
    }
    else
    {
        x = 1 + EditDistanceRecursive(stringLeft.substr(1), stringRight, arr);
        y = 1 + EditDistanceRecursive(stringLeft, stringRight.substr(1), arr);
        z = 1 + EditDistanceRecursive(stringLeft.substr(1), stringRight.substr(1), arr);
        min_num = std::min(x, std::min(y, z));
        arr[sizeOfStringLeft][sizeOfStringRight] = min_num;
    }
    return min_num;
}
int EditDistance(const std::string& stringLeft, const std::string& stringRight)
{
    // Get the dimensions of the dp table
    size_t numberOfRows = stringLeft.size() + 1; //rows
    size_t numberOfColumns = stringRight.size() + 1; //columns

    // Dynamically allocate 2d-array in old C-Style
    int** arr = new int* [numberOfRows];
    for (size_t  rowIndex = 0; rowIndex < numberOfRows; rowIndex++)
    {
        arr[rowIndex] = new int[numberOfColumns];
    }

    // Initialize memory and show debug output
    for (size_t  rowIndex = 0; rowIndex < numberOfRows; rowIndex++)
    {
        for (size_t  columnIndex = 0; columnIndex < numberOfColumns; columnIndex++)
        {
            std::cout << "Value of row is " << rowIndex << '\n';
            std::cout << "Value of column is " << columnIndex << '\n';
            arr[rowIndex][columnIndex] = (-1);
            std::cout << "Value of array at row/column is " << arr[rowIndex][columnIndex] << '\n';
        }
    }
    // Caluclate result
    int result = EditDistanceRecursive(stringLeft, stringRight, arr);

    // Release dynamic allocated memory 
    for (int rowIndex = 0; rowIndex < numberOfRows; rowIndex++)
        delete [] arr[rowIndex];
    delete [] arr;

    // Inform Result to upper function
    return result;
}
int main()
{
    // Tell user what to do
    std::cout << "Enter the two strings:\n";

    // Get 2 strings
    std::string stringLeft, stringRight;
    std::cin >> stringLeft >> stringRight;

    // Calculate and output distance
    int result = EditDistance(stringLeft, stringRight);

    std::cout << "\n\nResult. Distance is: " << result << '\n';
    return 0;
}
  • 我使用了有意义的变量名
  • 修复了小的语义错误
  • 做了一些小的样式优化
  • 在任何地方都使用完全限定名称

如果我们摆脱 C 风格,完全不推荐 new 和原始指针,我们会得到以下 C++ 代码:

#include <iostream>
#include <string>
#include <algorithm>
#include <vector>

using Columns = std::vector<int>;
using Arr = std::vector<Columns>;

int EditDistanceRecursive(const std::string& stringLeft, const std::string& stringRight, Arr& arr)
{
    size_t sizeOfStringLeft = stringLeft.size();
    size_t sizeOfStringRight = stringRight.size();

    //Base Case
    if (stringLeft.empty() || stringRight.empty())
    {
        return std::max(stringLeft.size(), stringRight.size());
    }

    int x, y, z, min_num;
    if (arr[sizeOfStringLeft][sizeOfStringRight] != (-1))
    {
        return arr[sizeOfStringLeft][sizeOfStringRight];
    }

    //Recursive Case
    if (stringLeft[0] == stringRight[0])
    {
        arr[sizeOfStringLeft][sizeOfStringRight] = EditDistanceRecursive(stringLeft.substr(1), stringRight.substr(1), arr);
        return arr[sizeOfStringLeft][sizeOfStringRight];
    }
    else
    {
        x = 1 + EditDistanceRecursive(stringLeft.substr(1), stringRight, arr);
        y = 1 + EditDistanceRecursive(stringLeft, stringRight.substr(1), arr);
        z = 1 + EditDistanceRecursive(stringLeft.substr(1), stringRight.substr(1), arr);
        min_num = std::min(x, std::min(y, z));
        arr[sizeOfStringLeft][sizeOfStringRight] = min_num;
    }
    return min_num;
}
int EditDistance(const std::string& stringLeft, const std::string& stringRight)
{
    // Get the dimensions of the dp table
    size_t numberOfRows = stringLeft.size() + 1; //rows
    size_t numberOfColumns = stringRight.size() + 1; //columns

    // Create and initialize 2d vector
    Arr arr(numberOfRows, Columns(numberOfColumns, -1));

    // Caluclate result
    return  EditDistanceRecursive(stringLeft, stringRight, arr);
}
int main()
{
    // Tell user what to do
    std::cout << "Enter the two strings:\n";

    // Get 2 strings
    std::string stringLeft, stringRight;
    std::cin >> stringLeft >> stringRight;

    // Calculate and output distance
    int result = EditDistance(stringLeft, stringRight);

    std::cout << "\n\nResult. Distance is: " << result << '\n';
    return 0;
}

可惜没人会读到。 . .

【讨论】:

    【解决方案2】:

    我认为您反转了数组下标的索引。您像 [b][a] 一样创建数组,然后像 [a][b] 一样使用它。

    【讨论】:

      猜你喜欢
      • 1970-01-01
      • 2016-05-07
      • 1970-01-01
      • 1970-01-01
      • 2015-11-11
      • 2013-04-05
      • 1970-01-01
      • 2021-10-11
      • 1970-01-01
      相关资源
      最近更新 更多