c - 通过指针索引到 char 数组时出现段错误

标签 c arrays pointers segmentation-fault

我的代码在访问数组元素时导致段错误,即使该元素已被毫无问题地访问过。

int charToInt(char a)
{
    int b;
    if(isdigit(a))
    {   
        b = a - '0' - 1;
    }
    if(isalpha(a))
    {
        b = a - 65; 
    }
    return b;   
}

int validPosition(char **array, int r, int c, char* position, int slots)
{
    int i,k;
    if(strlen(position) == 5)
    {
        if(!isalpha(position[0]) || !isdigit(position[1]) || position[2]!=' ' || (position[3]!='N' && position[3]!='E' && position[3]!='W' && position[3]!='S')) //lathos gramma
        {
            printf("\n%s", "Invalid answear.This is an example of a valid answear: A5 N");
            return 2;
        }
        if( charToInt(position[0]) > r - 1 || charToInt(position[1]) > c - 1  )//ama vgainei eksw apo ta oria
        {
            printf("\n%s", "The position you choosed is out of the bountries...");
            return 2;
        }
        printf("\n%s%c%s","position[3] is: ",position[3], " but it doesn't work >_<"); // position[3] is N 
        if(position[3] == 'N') //the problem is here <~~~~~~~~~~~~~~~~~~~<
        {
            printf("\n%s", "come on");
            if(charToInt(position[0]) + slots < r)
            {
                for(i=charToInt(position[0])-1; i<charToInt(position[0])+slots; i++)
                {
                     if(array[i-1][charToInt(position[1])-1] != '.')
                     {
                         printf("\n%s", "The position you choosed is not valid because there is oneother ship there");
                         return 2;
                     }
                }
            }
            else
            {
                printf("\n%s", "The ship is going out of the bountries...");
                return 2;
            }
        }
    }
}

position 保存字符串 "A9 N" 时,printf 正确输出 'N' 位置[3]。出于某种原因,当它尝试执行 if(position[3] == 'N') 时,会发生段错误。

示例程序运行:

Example of positioning: G3 E

Aircraft carrier (5 places), Give location and direction: A9 N

1

position[3] is: N but it doesn't work >_<

最佳答案

好吧,根据您的更新,您似乎遇到了各种问题。为了将来引用,实际添加(可能简化的)代码显示您如何调用相关函数比尝试在评论中使用散文描述它更好。尝试帮助您的人将减少猜测。

如果我没看错您的评论,调用 validPosition 的代码看起来像这样:

// "r and c are 9 and 9 in the specific example(rows columns)."
int rows = 9;
int columns = 9;

// "slots=5."
int slots = 5;

// "array is a 2d array and it contains characters(created with malloc)."
char **array = malloc(rows * columns * sizeof(char));

// "i created char position[10] in the function that called this function"
char position[10];
// "and with fgets(position, 10, stdin); i putted A9 N inside it."
fgets(position, 10, stdin);

validPosition(array, rows, columns, position, slots);

第一个问题是你对数组分配的描述(如果我误解了你的评论,我深表歉意,这实际上不是你在做什么)。对于使用两个下标操作( array[index1][index2] ,如 validPosition )使用的动态大小的二维数组,它应该类似于下面的代码。当您以这种方式访问​​时,指向指针 ( char **array ) 的行为与固定大小的多维数组 ( array[SIZE1][SIZE2] ) 不同。

// each entry in array should be a pointer to an array of char
char **array = malloc(rows * sizeof(char*));
for(i = 0; i < rows; i++)
    array[i] = malloc(columns * sizeof(char));

您还需要注意在 fgets 之后使用位置称呼。您应该检查返回值以确保它不是 NULL (表示 EOF 或错误情况)。该字符串可能不是 \0 - 在这种情况下终止。事实上,所有元素可能仍未初始化(假设您在调用之前没有初始化它们)。这可能会导致未定义的行为。

下一个问题是 validPosition不会在每个代码路径上返回值。一个例子是如果 strlen(position) != 5 .另一种是如果您输入 for循环和 array[i-1][charToInt(position[1])-1] != '.'永远不会为真(即,船舶安置被视为有效)。

尽管英语母语者对希腊语作者这样说很奇怪,但让我们忽略国际化并只关注默认的 C 本地。因此,对 position[0] 的检查应该就足够了,尽管您可能会考虑允许您的用户也使用小写字母。转换时 position[1]来自 1 - 基于 0基于,但是,当它是 '0' 时,您不考虑这种情况。 ,这将导致 charToInt返回 -1 .此外,您在 array[i-1][charToInt(position[1])-1] 的第二个数组下标中再次错误地进行了减法运算。 .

同样,正如 Jite 和 BLUEPIXY 所指出的,您正在对 charToInt(position[0]) 的结果进行 两次 额外减法运算: 一个在 for 循环初始值设定项 ( i=charToInt(position[0])-1 ) 中,一个在 array[i-1][charToInt(position[1])-1] 的第一个数组下标中.

修复该问题后,您可能会发现有时您会错误地告诉用户他们的选择无效。这是因为您正在检查 charToInt(position[0]) + slots < r而不是 <= r .

正如我在评论中提到的,对 array 的访问之一很可能是您违反分段的罪魁祸首,而不是 position[3] == 'N' .您看不到 printf("\n%s", "come on"); 输出的原因是你的stdout似乎是行缓冲的,并且没有行尾可以刷新它。它通常会在正常程序终止时自动刷新,但是您有段错误,因此不会发生这种情况。

最后,这些只是我注意到的语义错误。在文体上,代码也有待改进。例如,您似乎要实现 else if(position[3] == 'E' , else if(position[3] == 'W' , 和 else if(position[3] == 'S'与您的 if(position[3] == 'N' 具有相似逻辑的子句条款。这会增加您因不正确的复制和粘贴而引入错误的可能性,并且还会增加您以后需要在四个地方而不是一个地方进行更改时的工作量。

关于c - 通过指针索引到 char 数组时出现段错误,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/15773880/

相关文章:

c - 在 Windows 平台上使用 ANSI-C 可以获得精确到毫秒的系统时间吗?

c - 从 double 值中提取指数作为无符号值

javascript - 如何动态创建关联数组

c++ - 使用 C++ 将 char 数组转换为 int

string - Win32开发-C++中字符串相关的数据类型

c变量分配内存,指针

c - .so 文件如何查找符号?

python - 在感知器学习模型的 Python 实现中将数组传递给 numpy.dot()

c - 指针、结构和 malloc()

c++ - 父类(super class)的指针如何访问子类的变量?