1

У меня проблема с правильной печатью 2D-массива для проблемы коммивояжера. Я получаю свой ввод из текстового файла, используя перенаправление ввода. Файл содержит города и дуги с расстоянием между городами. Вот небольшой пример.2D-массив неправильной печати

c 1 
c 2 
a 1 2 1400 

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

0  1  2  3  4  5 

    1  0  1400 1800 4000 3500 

    2  1  0  0  3400 3600 

    3  1800 1200 0  2300 0 

    4  4000 3400 2300 0  2100 

    5  3500 3600 0  2100 0 

EDIT: Я хочу, чтобы сделать вид, как этот

0  1  2  3  4  5 

    1  0  1400 1800 4000 3500 

    2  1400 0  1200 3400 3600 

    3  1800 1200 0  2300 2700 

    4  4000 3400 2300 0  2100 

    5  3500 3600 2700 2100 0 

Я попытался манипулировать цикл различными способами, но я не могу показаться, чтобы выяснить, где моя проблема заключается в цикле или если это где-то еще в моем коде.

// Sets up the array 
int CityArray [6][6] = { {0, 0, 0, 0, 0, 0}, 
         {0, 0, 0, 0, 0, 0}, 
         {0, 0, 0, 0, 0, 0}, 
         {0, 0, 0, 0, 0, 0}, 
         {0, 0, 0, 0, 0, 0}, 
         {0, 0, 0, 0, 0, 0} 
         }; 

int main(void) // Takes in a variable number of arguments 
{ 
    // Sets a string input for the city 
    char Cbuffer[32]; 
    char *b = Cbuffer; 
    size_t cbufsize = 32; 
    size_t cinput; 

    // Other vairables 
    int x = 1; // used to go through the array 
    int n1, n2, n3, n4, cost; // variables to store the value pulled the cost from the arc 

    // Reads in the city and sets the prices for each arc 
    while((cinput = getline(&b, &cbufsize, stdin)) != -1) 
    { 
     if (Cbuffer[0] == 'c') 
     { 
      // Stores the last element as a digit to CityArray 
      if (Cbuffer[2] >= '0' && Cbuffer[2] <= '9') 
      { 
       CityArray[x][0] = Cbuffer[2] - '0'; 
       int z = CityArray[x][0]; 
       // Flips it 
       CityArray[0][x] = Cbuffer[2] - '0'; 
       z = CityArray[0][x]; 
       // printf("CityArray[%d] is '%d' \n", x, z); 
       x++; 
      } 
     } 
     else if (Cbuffer[0] == 'a') 
     { 
      int y = 1; 
      // I know this looks ugly but it's the only way I could think of getting the prices 
      if ((Cbuffer[6] >= '0' && Cbuffer[6] <= '9') && (Cbuffer[7] >= '0' && Cbuffer[7] <= '9') && 
        (Cbuffer[8] >= '0' && Cbuffer[8] <= '9') && (Cbuffer[9] >= '0' && Cbuffer[9] <= '9')) 
      { 
       for (x = 1; x < 6; x++) 
       { 
        for (y; y < 6; y++) 
        { // converts the char to a int 
         n1 = CityArray[x][6] = Cbuffer[6] - '0'; 
         n2 = CityArray[x][7] = Cbuffer[7] - '0'; 
         n3 = CityArray[x][8] = Cbuffer[8] - '0'; 
         n4 = CityArray[x][9] = Cbuffer[9] - '0'; 
        } 
       } // sets all converted ints to = cost 
       cost = (n1 * 1000) + (n2 * 100) + (n3 * 10) + (n4 * 1); 
       x++; 
      } 
      // Checks where the arc is located and plots the distance of the trip 
      if (Cbuffer[2] == '1') 
      { 
       if (Cbuffer[4] == '2') 
       { 
        CityArray[1][2] = cost; 
        CityArray[2][1] = cost; 
       } 
       else if (Cbuffer[4] == '3') 
       { 
        CityArray[1][3] = cost; 
        CityArray[3][1] = cost; 
       } 
       else if (Cbuffer[4] == '4') 
       { 
        CityArray[1][4] = cost; 
        CityArray[4][1] = cost; 
       } 
       else if (Cbuffer[4] == '5') 
       { 
        CityArray[1][5] = cost; 
        CityArray[5][1] = cost; 
       } 
      } 
      else if (Cbuffer[2] == '2') 
      { 
       if (Cbuffer[4] == '3') 
       { 
        CityArray[2][3] = cost; 
        CityArray[3][2] = cost; 
       } 
       else if (Cbuffer[4] == '4') 
       { 
        CityArray[2][4] = cost; 
        CityArray[4][2] = cost; 
       } 
       else if (Cbuffer[4] == '5') 
       { 
        CityArray[2][5] = cost; 
        CityArray[5][2] = cost; 
       } 
      } 
      else if (Cbuffer[2] == '3') 
      { 
       if (Cbuffer[4] == '4') 
       { 
        CityArray[3][4] = cost; 
        CityArray[4][3] = cost; 
       } 
      else if (Cbuffer[4] == '5') 
      { 
        CityArray[4][5] = cost; 
        CityArray[5][4] = cost; 
       } 
      } 
      else if (Cbuffer[2] == '4') 
      { 
       if (Cbuffer[4] == '5') 
       { 
        CityArray[4][5] = cost; 
        CityArray[5][4] = cost; 
       } 
      } 
     } 
    } 

    // Prints the array 
    int i, j; 
    printf("\n\nThe cost list is:\n\n"); 
    for(i = 0; i < 6;i ++) 
    { 
     printf("\n\n"); 
     for(j = 0; j < 6; j++) 
     { 
      printf("\t%d", CityArray[i][j]); 
     } 
     printf("\n"); 
    } 

    return 0; 
} 
+0

«но это выглядит так». - Можете ли вы также объяснить, как вы ожидали, что это будет выглядеть? –

+0

Позвольте мне изменить мой вопрос! – Cheezdue

+1

Если буфер недостаточно велик, то 'getline' будет' free' существующим буфером и выделяет новый, возвращая его. Поэтому вы не должны передавать 'Cbuffer', так как это ошибка, чтобы освободить это; и вы не должны тестировать 'Cbuffer [0] == 'c'' и т. д., потому что строка, возможно, была перераспределена. Вместо этого вы можете установить 'b = NULL' для запуска и использовать' b [0] 'и т. Д. (Или, чтобы избежать многого набора, избавиться от' b' и использовать 'char * Cbuffer = NULL;'). [Вероятно, это не связано с вашей проблемой, так как ваши файловые строки короче 32, но это тикающая временная бомба] –

ответ

1

Ваша проблема здесь:

  for (x = 1; x < 6; x++) 
      { 
       for (y; y < 6; y++) 
       { // converts the char to a int 
        n1 = CityArray[x][6] = Cbuffer[6] - '0'; 
        n2 = CityArray[x][7] = Cbuffer[7] - '0'; 
        n3 = CityArray[x][8] = Cbuffer[8] - '0'; 
        n4 = CityArray[x][9] = Cbuffer[9] - '0'; 
       } 
      } // sets all converted ints to = cost 
      cost = (n1 * 1000) + (n2 * 100) + (n3 * 10) + (n4 * 1); 
      x++; 

Во-первых, вам не нужны петли здесь; looping здесь означает, что вы будете делать преобразование несколько раз. (На самом деле это хуже: потому что вы не инициализируете y, вы вообще не можете конвертировать. Если вы активируете предупреждения, вы можете встретить строки «оператор без эффекта» для standaone y.)

Во-вторых, вы сохраняете преобразованные цифры в CityArray[x][6 ... 9], но индексы 6 и выше выходят за пределы. Это неопределенное поведение. На практике вы переписываете данные для следующего города.

В-третьих, вы не должны использовать x как переменную цикла и как переменную для хранения числа городов. Цикл перезапишет данные. (Но эта проблема исчезнет, ​​когда вы удалите петлю.)

Вобще:

  n1 = Cbuffer[6] - '0'; 
      n2 = Cbuffer[7] - '0'; 
      n3 = Cbuffer[8] - '0'; 
      n4 = Cbuffer[9] - '0'; 

      cost = (n1 * 1000) + (n2 * 100) + (n3 * 10) + (n4 * 1); 

код все еще имеет много проблем. В частности, синтаксический анализ городов и расстояний очень ограничен. Что произойдет, если стоимость города не будет четырехзначным числом? И что произойдет, если первый город будет больше, чем второй город?

Вы также можете использовать преобразование из ASCII в однозначном целое число для городов:

 int from = Cbuffer[2] - '0'; 
     int dest = Cbuffer[4] - '0'; 

     CityArray[from][dest] = cost; 
     CityArray[dest][from] = cost; 

Это позволит избавиться от большого количества кода. Вместо жесткого кодирования всех возможностей ваша энергия лучше тратится при написании значимых сообщений об ошибках, например, если идентификатор города выходит за пределы.

Вы также должны рассмотреть возможность использования стандартных подходов к анализу ввода. getline в сочетании с scanf может быть хорошим подходом.

Редактировать: Ниже приведен пример реализации ввода. Он может занимать не более 10 городов, обозначенных одним символом, который может быть цифрой. Он не имеет никаких ограничений на точный формат линий c и a, а также отслеживает количество фактических городов в переменной ncitiy. Он принимает пустые строки и строки, начинающиеся с # как не-команды.

Несмотря на серьезную проверку ошибок, эта программа немного короче вашей. Здесь:

#define _GNU_SOURCE 

#include <stdlib.h> 
#include <stdio.h> 

#define MAX 10 


int find(int array[], int n, int x) 
{ 
    for (int i = 0; i < n; i++) { 
     if (array[i] == x) return i; 
    } 

    return -1; 
} 

int main(void) 
{ 
    int cost[10][10] = {{0}};  // cost matrix 
    int id[MAX];     // city id; can be any character 
    int ncity = 0;     // number of cities 

    char *line = NULL; 
    size_t nline = 0; 
    int error = 0; 

    while (getline(&line, &nline, stdin) != -1) { 
     char c1, c2; 
     int c; 

     if (sscanf(line, " c %c", &c1) == 1) { 
      if (find(id, ncity, c1) != -1) { 
       fprintf(stderr, "Duplicate city id %c.\n", c1); 
       error = 1; 
       break; 
      } else if (ncity >= MAX) { 
       fprintf(stderr, "Maximum number of cities exceeded\n"); 
       error = 1; 
       break; 
      } else { 
       id[ncity++] = c1; 
      } 
      continue; 
     } 

     if (sscanf(line, " a %c %c %d\n", &c1, &c2, &c) == 3) { 
      int from = find(id, ncity, c1); 
      int dest = find(id, ncity, c2); 

      if (from < 0) { 
       fprintf(stderr, "Unknown city id %c.\n", c1); 
       error = 1; 
       break; 
      } 

      if (dest < 0) { 
       fprintf(stderr, "Unknown city id %c.\n", c2); 
       error = 1; 
       break; 
      } 

      cost[from][dest] = c; 
      cost[dest][from] = c; 

      continue; 
     } 

     if (sscanf(line, " %c", &c1) == 1 && c1 != '#') { 
      fprintf(stderr, "Unknown command: %s", line); 
      error = 1; 
      break; 
     } 
    } 

    free(line); 

    if (error) { 
     fprintf(stderr, "Errors in input. Aborting.\n"); 
     exit(1); 
    } 

    printf("%8s", ""); 
    for (int j = 0; j < ncity; j++) { 
     printf("%8c", id[j]); 
    } 
    puts(""); 

    for(int i = 0; i < ncity; i ++) 
    { 
     printf("%8c", id[i]); 
     for (int j = 0; j < ncity; j++) { 
      printf("%8d", cost[i][j]); 
     } 
     puts(""); 
    } 
    puts(""); 

    return 0; 
} 
+0

Спасибо, ваше предложение сработало! Первоначально я думал, что моя проблема легла в этом разделе моего кода, но я не понял, почему это вызывает мою проблему. Я знал, что мой метод чтения в городах очень ограничен, но я не мог найти лучшего метода. Код, который вы предоставили, - отличный способ читать в городах! – Cheezdue

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