Warning: file_get_contents(/data/phpspider/zhask/data//catemap/3/arrays/13.json): failed to open stream: No such file or directory in /data/phpspider/zhask/libs/function.php on line 167

Warning: Invalid argument supplied for foreach() in /data/phpspider/zhask/libs/tag.function.php on line 1116

Notice: Undefined index: in /data/phpspider/zhask/libs/function.php on line 180

Warning: array_chunk() expects parameter 1 to be array, null given in /data/phpspider/zhask/libs/function.php on line 181
C++获取网格中的单元格的邻居,-1x在检查IF时抛出空异常。无效的 最近从C移到C++,所以我对指针和引用等都很新。_C++_Arrays_Enums_Pointer To Pointer_Pointer To Array - Fatal编程技术网

C++获取网格中的单元格的邻居,-1x在检查IF时抛出空异常。无效的 最近从C移到C++,所以我对指针和引用等都很新。

C++获取网格中的单元格的邻居,-1x在检查IF时抛出空异常。无效的 最近从C移到C++,所以我对指针和引用等都很新。,c++,arrays,enums,pointer-to-pointer,pointer-to-array,C++,Arrays,Enums,Pointer To Pointer,Pointer To Array,我有一个指向指针数组的指针,声明如下 enum Type { Void, DeepWater, Water, ... etc } Tile::Type** tiles; TileManager::TileManager(int width, int height) { this->tiles = new Tile::Type*[width]; for (int w = 0; w < width; w++) {

我有一个指向指针数组的指针,声明如下

enum Type
{
    Void,
    DeepWater,
    Water,
    ... etc }

Tile::Type** tiles;

TileManager::TileManager(int width, int height)
{
    this->tiles = new Tile::Type*[width];

    for (int w = 0; w < width; w++)
    {
        tiles[w] = new Tile::Type[height];

        for (int h = 0; h < height; h++)
        {
            tiles[w][h] = Tile::Type::Dirt;
        }
    }
}
现在,我将组合一个方法,返回tiles数组中一个单元格的邻居,并检查每个邻居是否不等于NULL。 然而,即使在检查它是否为null时,似乎也会抛出一个错误,所以我被难住了

Tile::Type * TileManager::GetNeighbours(int x, int y)
{
    Tile::Type neighbours[8];

    if(tiles[x][y+1] != NULL)
        neighbours[0] = tiles[x    ][y + 1];

    ...etc

    if (tiles[x - 1][y - 1] != NULL)    //<-- Error fires here
        neighbours[5] = tiles[x - 1][y - 1];

    return neighbours;
}
我知道它为什么会抛出错误,但不敢检查X和Y,看它们是否超过极限或低于0。。。我想有一个更实际的方法来防止这种情况,所以我想我最好问一下

编辑:

谢谢你,用户4581301。我在别处找到了大部分代码,并对其进行了修改以反映您建议的更改

std::array<Tile::Type, 8> TileManager::GetNeighbours(int c, int r)
{
    std::array<Tile::Type, 8> neighbours;

    const int y[] = { -1, -1, -1,  1, 1, 1,  0, 0 };// 8 shifts to neighbors
    const int x[] = { -1,  0,  1, -1, 0, 1, -1, 1 };// used in functions 

    for (int i = 0; i < 8; ++i)// visit the 8 spaces around it
        if (inField(r + y[i], c + x[i]))
            neighbours[i] = tiles[r + y[i]][c + x[i]];
        else
            neighbours[i] = Tile::Type::Void;

    return neighbours;
}

bool TileManager::inField(int r, int c)
{
    if (r < 0 || r >= 25) return false;
    if (c < 0 || c >= 25) return false;
    return true;
}
如果y是最大有效值,则平铺[x][y+1]将不为空,除非有宽限值。这超出了界限,一旦你超出了界限,所有的赌注都结束了。你已经调用了,几乎任何事情都可能发生。甚至是你所期望的

这同样适用于报告的坠机地点,即瓦片[x-1][y-1]

编辑:遗漏的解决方案。没有帮助。 除了将整个站点从轨道上起飞并使用核武器外,唯一的方法是在数组上使用索引之前,测试索引以确保它不会刺穿数组边界。您可能需要一个函数来处理此问题

void assign_if(Type & neighbour, int x, int y)
{
    if(x >= 0 && x < width && y >= 0 && y < height)
    neighbour = tiles[x][y];
}
后来

assign_if(neighbours[0], x-1, y-1);
编辑:为了完整起见,从Bob_uuuuu处窃取此内容 从函数返回原始数组是不可能的。数组超出范围,指向它的指针变为无效。可以将数组作为另一个参数传入,也可以使用or,两者都可以返回。多亏了,一个智能编译器可能会消除复制成本

例如:

std::array<Tile::Type, 8> TileManager::GetNeighbours(int x, int y)
{
    std::array<Tile::Type, 8> neighbours;
    ...
    return neighbours;
}
按原始海报编辑。以下是我的解决方案: 编辑:警告 这个答案直接涉及到问题的解决。有关更实用的解决方案的描述,请参见Kaz的答案,该解决方案可以节省一点内存,从而完全消除测试和生成相邻阵列的需要。

tiles[x][y+1],如果y是最大有效值,则除非使用grace of,否则不会为NULL。这超出了界限,一旦你超出了界限,所有的赌注都结束了。你已经调用了,几乎任何事情都可能发生。甚至是你所期望的

这同样适用于报告的坠机地点,即瓦片[x-1][y-1]

编辑:遗漏的解决方案。没有帮助。 除了将整个站点从轨道上起飞并使用核武器外,唯一的方法是在数组上使用索引之前,测试索引以确保它不会刺穿数组边界。您可能需要一个函数来处理此问题

void assign_if(Type & neighbour, int x, int y)
{
    if(x >= 0 && x < width && y >= 0 && y < height)
    neighbour = tiles[x][y];
}
后来

assign_if(neighbours[0], x-1, y-1);
编辑:为了完整起见,从Bob_uuuuu处窃取此内容 从函数返回原始数组是不可能的。数组超出范围,指向它的指针变为无效。可以将数组作为另一个参数传入,也可以使用or,两者都可以返回。多亏了,一个智能编译器可能会消除复制成本

例如:

std::array<Tile::Type, 8> TileManager::GetNeighbours(int x, int y)
{
    std::array<Tile::Type, 8> neighbours;
    ...
    return neighbours;
}
按原始海报编辑。以下是我的解决方案: 编辑:警告
这个答案直接涉及到问题的解决。请参阅Kaz的答案,了解一种更实用的解决方案的描述,该解决方案可以节省一点内存,从而完全消除测试和生成相邻数组的需要。

避免条件检查的更实用的短代码方法是创建平铺数组,这样它就可以在周围包含额外的平铺边界有效面积。如果任何平铺位置位于有效区域中,则为有效,反之亦然

您可以为边框平铺指定一种只有它们才有的特殊类型,只需将这些平铺包含在“邻居”列表中即可。如果您的世界有墙,则边界可以由墙材质组成

不用说,你绝对不能要求一个边界砖邻居的名单。这是由逻辑来保证的,比如不允许边界平铺成为任何东西的有效位置

此磁贴位于边界内的有效区域是一种更容易检查的条件,位置更少,并且您的程序可以结构化,因此此检查实际上只是一个可移动的断言—如果程序正确,则不应发生这种情况的检查,而不是对预期情况的检查

<>在C和C++中,我们可以替换指针,使位置[0 ] [0 ]仍然是有效区域的拐角,但是超出界限的坐标[-1 ] [-1 ]是有效的索引,[W] [H] .< 首先,向列数组分配两个大于所需大小的元素,指针递增1。然后给列分配两个较大的元素,每个指针在分配到主数组之前递增一


使用delete[]释放数组时,必须记住将每个指针减量一。

避免条件检查的较短代码更实用的方法是创建ti 在有效区域周围包含一个额外的瓷砖边框。如果任何平铺位置位于有效区域中,则为有效,反之亦然

您可以为边框平铺指定一种只有它们才有的特殊类型,只需将这些平铺包含在“邻居”列表中即可。如果您的世界有墙,则边界可以由墙材质组成

不用说,你绝对不能要求一个边界砖邻居的名单。这是由逻辑来保证的,比如不允许边界平铺成为任何东西的有效位置

此磁贴位于边界内的有效区域是一种更容易检查的条件,位置更少,并且您的程序可以结构化,因此此检查实际上只是一个可移动的断言—如果程序正确,则不应发生这种情况的检查,而不是对预期情况的检查

<>在C和C++中,我们可以替换指针,使位置[0 ] [0 ]仍然是有效区域的拐角,但是超出界限的坐标[-1 ] [-1 ]是有效的索引,[W] [H] .< 首先,向列数组分配两个大于所需大小的元素,指针递增1。然后给列分配两个较大的元素,每个指针在分配到主数组之前递增一


使用delete[]释放数组时,必须记住将每个指针递减一。

在访问元素之前,应检查索引是否超出范围。此外,邻居是一个局部变量,在返回之后它将无法生存。最近从C移到C++使用容器如STD::vector代替原始指针。使用C++不意味着你必须进入指针的杂草,如果你不需要的话,安东尼请把正确答案转给Kaz的答案。我的想法是直接解决报告中的问题,而Kaz的答案是,交换一点内存以完全避免问题,这对你和其他未来的提问者来说是更好的解决方案。你应该在访问元素之前检查索引是否超出范围。此外,邻居是一个局部变量,在返回之后它将无法生存。最近从C移到C++使用容器如STD::vector代替原始指针。使用C++不意味着你必须进入指针的杂草,如果你不需要的话,安东尼请把正确答案转给Kaz的答案。我的想法是直接解决报告中的问题,而Kaz的答案,用一点内存来完全避免这个问题,对你和其他未来的提问者来说是更好的解决方案。