二维数组打印不正确
2D Array incorrectly printing
我在正确打印旅行商问题的二维数组时遇到问题。我正在使用输入重定向从文本文件中获取输入。该文件包含城市和弧线以及城市之间的距离。这是一个小例子。
c 1
c 2
a 1 2 1400
设置数组并绘制城市之间的距离后,我使用嵌套的 for 循环打印出数组,但它看起来像这样。
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
编辑:我想让它看起来像这样
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
我尝试以不同的方式操作 for 循环,但我似乎无法弄清楚我的问题出在循环中的什么地方,或者它是否在我的代码中的其他地方。
// 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;
}
你的问题在这里:
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++;
首先,这里不需要循环;在这里循环意味着您将多次进行转换。 (实际上,更糟糕的是:因为您没有初始化 y
,所以您可能根本不会进行转换。如果您激活警告,您会得到一些类似于 "statement with no effect" 的独立 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;
这会去掉很多代码。与其硬编码所有可能性,不如将精力花在编写有意义的错误消息上,例如,如果城市的 ID 超出范围。
您还应该考虑使用标准方法来解析输入。 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;
}
我在正确打印旅行商问题的二维数组时遇到问题。我正在使用输入重定向从文本文件中获取输入。该文件包含城市和弧线以及城市之间的距离。这是一个小例子。
c 1
c 2
a 1 2 1400
设置数组并绘制城市之间的距离后,我使用嵌套的 for 循环打印出数组,但它看起来像这样。
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
编辑:我想让它看起来像这样
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
我尝试以不同的方式操作 for 循环,但我似乎无法弄清楚我的问题出在循环中的什么地方,或者它是否在我的代码中的其他地方。
// 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;
}
你的问题在这里:
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++;
首先,这里不需要循环;在这里循环意味着您将多次进行转换。 (实际上,更糟糕的是:因为您没有初始化 y
,所以您可能根本不会进行转换。如果您激活警告,您会得到一些类似于 "statement with no effect" 的独立 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;
这会去掉很多代码。与其硬编码所有可能性,不如将精力花在编写有意义的错误消息上,例如,如果城市的 ID 超出范围。
您还应该考虑使用标准方法来解析输入。 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;
}