2013-04-02 2 views
1

Мой код вызывает ошибку сегментации при доступе к элементу массива, даже если к этому элементу уже обращался без проблем.Ошибка сегментации при индексировании в массив символов с помощью указателя

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 >_<
+0

Проблема не в том, где вы думаете, что это так, stdout может просто не покраснеть, когда он сработает. Вот почему 'printf (" \ n% s "," come on ");' не запускается. Как называется эта функция? Как его параметры получены? Как выглядит определение charToInt? Моя догадка заключается в том, что проблема связана с доступом к 'array' вместо' position'. – jerry

+0

Индексирование массива довольно шатки, и ваш цикл for-loop. Надеюсь, что ваша переменная 'i' обеспечивает небольшое небольшое значение, которое больше или равно« 1 », в противном случае вы находитесь в глубоком упадке с вашим кодом. – Jite

+0

массив является 2-мерным массивом и содержит символы (созданные с помощью malloc) .r и c - 9 и 9 в конкретном примере (столбцы строк). Слоты = 5.я создал позицию char [10] в функции, которая вызывала эту функцию, и с помощью fgets (position, 10, stdin); Я положил A9 N внутри него. int charToInt (char a) и, например: для a = 'A' он возвращает 0. для a = '9' он возвращает 8 (возвращается -1, потому что я пытаюсь создать игру, и пользователь видит 1 2 3 4 ... вместо 0 1 2 3 4 .. –

ответ

0

Поскольку терминология 'Сегментация Fault' Я считаю, что вы на Linux машине. Чтобы узнать причину ошибки, используйте gdb. Вот шаги. (. Ех НКУ -g my_prog.c)

  1. Compile с дополнительным -g флагом
  2. Run отладчик: GDB a.out команда
  3. Используйте 'List', чтобы найти строку для точки останова (например. первая линия вашей функции)
  4. Установить точку останова на этой линии с: б 25 (если 25 является то, что линия)
  5. выполнить программу с «выполнить» команду
  6. Использование команды «Далее», чтобы выполнить следующую строку кода

Теперь выполнение приостанавливается на этой строке, вы можете проверить память, распечатать содержимое переменной и прочее. Но обычно вы хотите определить, на какой строке выполняется выполнение, а что - в какой переменной.

С небольшой игрой с памятью вы легко найдете, где проблема. Лично мой код не будет работать с поддержкой gdb.

+0

GDB не работает по какой-либо причине: / –

0

Возможно, ошибка сегментации на array[i-1][charToInt(position[1])-1]

я: charToInt(position[0])-1: charToInt ('A') - 1: -1 < - Массив недоступный

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 по умолчанию. Поэтому проверки на позицию [0] должны быть достаточными, хотя вы можете подумать о том, чтобы позволить вашим пользователям использовать строчные буквы. При конвертации position[1] из 1-на основе 0 вы не учитываете случай, когда он равен '0', что приведет к возврату charToInt-1. Кроме того, вы ошибочно делаете вычитание снова во втором индексе массива array[i-1][charToInt(position[1])-1].

Точно так же, как отметили Jite и BLUEPIXY, вы делаете два дополнительных вычитания на результате 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");, заключается в том, что ваш stdout выглядит буферизированным по строке, и нет конца линии для его очистки. Обычно он автоматически сбрасывается на нормальный завершение программы, однако вы не уверены в том, что этого не произойдет.

Наконец, это только семантические ошибки, которые я заметил. Стилистически, код также может быть улучшен. Например, кажется, что вы собираетесь использовать else if(position[3] == 'E', else if(position[3] == 'W' и else if(position[3] == 'S' статьи с аналогичной логикой для вашего предложения if(position[3] == 'N'. Это увеличивает вероятность того, что вы представите ошибку, неправильно скопировав и вставив, а также увеличит свою работу позже, когда вам нужно внести изменения в четыре места вместо одного.

Смежные вопросы