2013-03-01 2 views
-1

Я написал случайный генератор путей для моего проекта, и когда он работает, он работает по назначению. Однако он работает только иногда. Это может быть очень много кода, чтобы пройти так голый со мной.Функция работает только половину времени C

В моей основной функции у меня есть простая инструкция switch для вызова моих трех задач для этого проекта.

while(Continue) 
{ 

switch(Example_number) 
    { 
    default: printf("No such program exists.\n"); 
      break; 
    case 1: path(); 
      break; 
    case 2: Caesar_cipher(); 
      break; 
    case 3: anagram(); 
      break; 
    } 

    printf("Would you like to test another?(Y/N)\n"); 
    scanf("\n%c",&ch); 
    if(ch == 'Y' || ch == 'y') 
    { 
     NULL; 
    } 
    else 
    { 
     Continue = false; 
    } 
} 

При вводе 1 он вызывает эту функцию, ведьма создает массив и вызывает две другие функции.

void path(void) 
{ 
    //Creates the array walk. 
    char walk[10][10] = {{'.','.','.','.','.','.','.','.','.','.'}, 
         {'.','.','.','.','.','.','.','.','.','.'}, 
         {'.','.','.','.','.','.','.','.','.','.'}, 
         {'.','.','.','.','.','.','.','.','.','.'}, 
         {'.','.','.','.','.','.','.','.','.','.'}, 
         {'.','.','.','.','.','.','.','.','.','.'}, 
         {'.','.','.','.','.','.','.','.','.','.'}, 
         {'.','.','.','.','.','.','.','.','.','.'}, 
         {'.','.','.','.','.','.','.','.','.','.'}, 
         {'.','.','.','.','.','.','.','.','.','.'}}; 

//Creates a randomly generated path to travel along walk. 
generate_path(walk); 
print_array(walk); 
} 

Функция, которая генерирует путь.

void generate_path(char walk[10][10]) 
{ 
int move_n = 0; 
int row, column, i; 
const char alph[] = {'B','C','D','E','F','G','H','I','J','K','L','M','N','O','P','Q','R','S','T','U','V','W','X','Y','Z'}; 
//Array that holds all previous data. 
int move[3][25] = {0}; 
bool block = false; 

//Allows for a random variable. 
srand((unsigned) time(NULL)); 

row = rand() % 10; 
column = rand() % 10; 

while(!block) 
{ 
    walk[row][column] = 'A'; 
    for(i = 0; i < 25; i++) 
    { 
     //goto comes here 
     restart: 
     move_n = rand() % move_dir; 
     //If space is open continue the alph array one row below. 
     if(move_n == 0 && walk[row+1][column] == '.' && row+1 < 10) 
     { 
      row += 1; 
      move[0][i] = i; 
      move[1][i] = row; 
      move[2][i] = column; 
      walk[row][column] = alph[i]; 
     } 
     else if(move_n == 1 && walk[row][column+1] == '.' && column+1 < 10) //If space is open continue the alph array one column to the right. 
     { 
      column += 1; 
      move[0][i] = i; 
      move[1][i] = row; 
      move[2][i] = column; 
      walk[row][column] = alph[i]; 
     } 
     else if(move_n == 2 && walk[row-1][column] == '.' && row-1 >= 0) //If space is open continue the alph array one row above. 
     { 
      row -= 1; 
      move[0][i] = i; 
      move[1][i] = row; 
      move[2][i] = column; 
      walk[row][column] = alph[i]; 
     } 
     else if(move_n == 3 && walk[row][column-1] == '.' && column-1 >= 0) //If space is open continue the alph array one column to the left.  
     { 
      column -= 1; 
      move[0][i] = i; 
      move[1][i] = row; 
      move[2][i] = column; 
      walk[row][column] = alph[i]; 
     } 
     else if((walk[row][column-1] == '.') || (walk[row-1][column] == '.') || (walk[row][column+1] == '.') || (walk[row+1][column] == '.')) 
     { 
      if(i == 25) 
       break; 
      goto restart; 
     } 
     else 
     { 
      //Resets data to point such that the path can continue. 
      row = move[1][i-1]; 
      column = move[2][i-1]; 
      i--; 
      walk[row][column] = '.'; 
     } 
    } 
    block = true; 
} 
} 

И функция массива печати.

void print_array(char walk[10][10]) 
{ 
int i = 0; 
int k = 0; 
for(i = 0; i < 10; i++) 
{ 
    for(k = 0; k < 10; k++) 
    { 
     printf(" %c", walk[i][k]); 
    } 
    printf("\n"); 
} 
} 

Но по какой-то причине при вводе 1 в оператор switch он работает только иногда. Вызов любой другой функции отлично работает каждый раз.

Благодарим за помощь в этом. Мне кажется, что я написал слишком много кода, но, надеюсь, он читаем.

+1

Где декларация для 'Example_number'? Где вы его назначаете? Offtopic: вы должны придерживаться соглашения об именах, например. переменные всегда начинаются с нижнего регистра. Это сделает ваш код более читаемым. – m0skit0

+1

Кроме того: вызов 'srand ((беззнаковое) время (NULL));' только один раз за запуск, а не каждый раз, когда вы создаете новый 'path()'. –

+0

Вы уверены, что это не должно быть 'scanf ("% c ", & ch)'? почему новая линия? – January

ответ

3

Скорее всего, ваша проблема связана с операциями if, которые у вас есть в generate_path().

Доступ walk[row+1][column], walk[row][column+1] и т.д. row и column генерируются с rand()%10. Так row и columnзначения могут быть0 или 9 в какой-то момент и при доступе индексов row-1column+1 и т.д., это будет доступ вне границ массива, которые могут вызвать всевозможные проблемы.

+0

Это объявлено за пределами того, что я опубликовал, а Даниэль иногда, когда я печатаю 1, и попал в него, переходит в новую строку и сидит. Я собираюсь редактировать номера строк и номера столбцов и видеть, что это делает. – Trevor

+0

@Trevor Ах, если он зависает, это, вероятно, последний 'else' с' i -; 'в' for'-loop. Если вам не повезло, это может привести вас к бесконечному циклу. –

2

Пара предложений от ветерана программирования C в 30 лет ...

  1. Не используйте ключевые слова в качестве имен переменных. «Продолжить» путает других программистов, потому что «продолжить» - это ключевое слово.
  2. Я бы рекомендовал сделать свои пограничные проверки FIRST в стеке if в функции path(). Таким образом, если проверка границы не удалась, другие тесты (включая доступ к памяти за пределами границ) не будут выполняться.
  3. Путь «перезапуска» стека if в пути() имеет NO пограничные проверки!

Наконец, я построил проект из ваших образцов кода, и я обнаружил, что он «застревает» в ветке else стека if в пути(). Это происходит, потому что счетчик внешнего контура (i) уменьшается, строка столбца & обновляется, а затем цикл повторяется. Это заставляет меня увеличиваться, и если выбранная строка/столбец также является точкой, которая не может продолжаться, цикл повторяется бесконечно.

--ammendment--

Я отправил программу, которую я построил из ваших образцов кода в http://www.svalli.com/files/path.7z, так что вы можете проверить, чтобы гарантировать, что я не изменил свою логику.Вот результат я получаю (включая некоторые отладки я добавил, чтобы показать, где/почему цикл висит):

Path ----------------------- 
    . . . . . . . . . . 
    . . . . . F E . A . 
    . . . I H G D C B . 
    . . . J K . . . . . 
    P O N M L . . . . . 
    Q R S . . . . . . . 
    . . T U . . . . . . 
    . . . V . . . . . . 
    . . X W . . . . . . 
    . Z Y . . . . . . . 
    Would you like to test another?(Y/N) 
    y 

    row 2/col 6 
    Path ----------------------- 
    . . . . P O N M L K 
    . . . . Q T U H I J 
    . . . . R S . G . . 
    . . . . . D E F . . 
    . . . A B C . . . . 
    . . . . . . . . . . 
    . . . . . . . . . . 
    . . . . . . . . . . 
    . . . . . . . . . . 
    . . . . . . . . . . 
    Would you like to test another?(Y/N) 

Второй прогон бы висел навсегда, пытаясь найти выход из ячейки 2,6, если мой отладки не разразился, когда зависание было обнаружено. Я надеюсь, что это поможет вам отследить логическую ошибку - я не пытался понять ваш алгоритм пути, только чтобы найти, где он висит и что такое условие зависания. Если я не изменил что-то (что, я сомневаюсь), это ваша проблема. Я надеюсь, что это помогает. О, если вы обнаружите, что я нечаянно изменил вашу логику, пожалуйста, покажите мне, как/где, хорошо? Мне было бы интересно это узнать.

--more--

Для тех, кто заинтересован, я завернул генератор путь в программе Win32, так что он делает одну итерацию каждый второй 1/2 и обновляет путь на экране, как она идет. Он рисует «нормальный» путь с красными символами. Если он застревает, он рисует последний символ, который он проверяет желтым, а затем, если он продолжает застревать, он рисует знак плюса в желтом и зеленом цветах, пока он не отклеится. Собираем! из меню всегда будет запускаться новая, чистая последовательность пути и нажатие Стоп! остановит его, когда застрянет (как будет генерировать! и, конечно же, выйдет из программы.) Вы можете получить исполняемый файл здесь: http://www.svalli.com/files/maze.7z Интересно посмотреть, как он работает, и легко понять, почему и как он застревает. Из этого я уверен, что кто-то поймет, как исправить генератор путей, чтобы он никогда не застревал. Или, может быть, код, который я установил для отладки, чтобы обнаружить «застрявшее» состояние, достаточно? Он просто создал короткий путь, который может не удастся продолжить.

+0

PS: Вот еще одно объяснение передачи многомерных массивов, которые могут помочь, поскольку они используют те же самые размеры и размеры массива, которые вы используете: Удачи! –

+0

@KingsIndian: По крайней мере, его доступ за пределы границ был ** прочитанным **, который, как правило, немного менее подвержен ошибкам. Хотя, по мере улучшения безопасности системы, это будет все меньше и меньше. Была проведена проверка границ в 4 из 5 тестов if(), но она должна была быть перед тестами, которые полагались на значение, находящееся в пределах границ, чтобы воспользоваться оценкой короткого замыкания и ошибки C. –

+1

«Вы не можете передавать многомерный массив в качестве параметра, как вы делаете в C.» Поскольку вы не можете передавать массивы вообще на C, это имеет некоторую техническую правду.Но выражение массива преобразуется в символ 'char (*) [10]', когда его имя указывается как аргумент функции, и это точный тип, который выполняет эти функции. Прототип 'void generate_path (char walk [10] [10])' в точности эквивалентен 'void generate_path (char walk [] [10])' или, точный тип, 'void generate_path (char (* walk) [10 ]) '. У компилятора нет причин жаловаться, и он работает по назначению. –

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