通过指针索引到char数组时的分段错误

时间:2013-04-02 20:37:01

标签: 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' position[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 >_<

3 个答案:

答案 0 :(得分:1)

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

如果我正确阅读您的评论,则调用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 local。因此,对位置[0]的检查应该足够了,但您也可以考虑允许用户使用小写字母。但是,从基于position[1]的{​​{1}}转换为基于1的{​​{1}}时,您不会考虑0的情况,这将导致'0' } return charToInt。此外,您错误地在-1的第二个数组下标中再次进行减法。

同样,正如Jite和BLUEPIXY所指出的那样,你在array[i-1][charToInt(position[1])-1]的结果上进行了两次额外的减法:在for循环初始化器(charToInt(position[0]))中有一个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");似乎是行缓冲的,并且没有行结束来刷新它。它通常会在正常程序终止时自动刷新,但是你是段错误的,所以不会发生。

最后,这些只是我注意到的语义错误。在风格上,代码也可以得到改进。例如,您似乎将实施stdoutelse if(position[3] == 'E'else if(position[3] == 'W'子句,其逻辑与您的else if(position[3] == 'S'子句类似。这会增加您通过错误地复制和粘贴引入错误的可能性,并且当您需要在四个位置而不是一个位置进行更改时也会增加您的工作。

答案 1 :(得分:0)

由于术语“分段错误”,我相信你是在Linux机器上。 使用gdb查找错误原因。以下是步骤。

  1. 使用附加的-g标志(例如gcc -g my_prog.c)
  2. 进行编译
  3. 运行调试器:gdb a.out
  4. 使用'list'命令查找断点线(例如,函数的第一行)
  5. 在该行设置断点:b 25(如果25是该行)
  6. 使用'run'命令运行程序
  7. 使用命令'next'执行下一行代码
  8. 现在执行将在该行暂停,您可以检查内存,打印变量内容 和东西。但通常你想确定执行失败的哪一行以及哪个变量。

    只需稍微玩一下内存,您就可以轻松找到问题所在。就个人而言,我的代码不适用于gdb支持。

答案 2 :(得分:0)

可能在array[i-1][charToInt(position[1])-1]

分段错误

i:charToInt(position[0])-1:charToInt('A') - 1:-1&lt; - 数组越界