我试图弄清楚如何正确地从C中的.txt文档中读取和存储迷宫。此迷宫的最大大小为40x40“立方体”。阅读完之后,我将需要解决此问题,方法是在路径的左上角到右下角之间加一个*。我习惯于使用2D数组,但是这个问题一直困扰着我,因为我不了解如何跟踪行和列是否不完全均匀,或者如何准确地在中间打印*我解决了每个“多维数据集”的问题。我已经读过其他由1和0组成的迷宫示例,或者什至是墙壁上的所有#迷宫示例,这使它很容易读入并跟踪,但不能像这样输入。解决第一个迷宫,并用双倍空格隔开后,我将需要阅读同一文本文件上的其他迷宫。以下是其中一个迷宫的示例:
+---+---+---+---+---+
| | |
+---+ + + + +
| | | | | |
+ + + + +---+
| | | | |
+ + + +---+ +
| | | |
+ +---+---+ + +
| | |
+---+---+---+---+---+
这是到目前为止我进行错误检查和读取字符的一些代码。在其中,我试图初始化一个120x120的数组,读取当前char,然后将这些字符转换为-1或0以对应于墙或空白空间。 :
/* Read in a grid as parameter of max 120x120 to account for '+' and'-' */
int readLine(int grid2D[120][120])
{
int row = 0;
int col = 0;
int isNewLine = TRUE;
/* Loop through while getchar does not equal EOF */
while ((c = getchar()) != EOF)
{
/* Check for foreign characters, return FALSE if found */
if ((c != '+') || (c != '-') || (c != '|') || (c != ' '))
{
/* If c = \n , avoid tripping error, and do nothing */
if(c == '\n'){}
else
errorFree = FALSE;
}
/* If character is a '+' '-' or '|', it is a wall, set to -1 to
use int's for wall tracking */
else if (row%2 == 0)
{
if(c == '|')
{
grid2D[row][col] = -1;
col++;
}
}
else if((c == '+') || (c == '-'))
{
grid2D[row][col] = -1;
col++;
}
else
{
if(c == '\n')
{
col = 0;
row++;
}
}
isNewLine = TRUE;
return isNewLine;
}
任何指导将不胜感激,我不确定我所采用的方法是否正确。我相信我目前正在正确检查错误,但是我正在努力了解应该如何跟踪每个“多维数据集”,因为每个“多维数据集”的字符都不均匀,它们的尺寸更是如此,大小为5x1多维数据集( {1}}(一侧),+---+
(另一侧)
答案 0 :(得分:2)
针对您在评论中的问题,确定行和列的大小非常简单。当您使用fgets
从文件中读取数组的一行时,可以使用strlen()
确定字符数(但请注意,其中还包含{{1 }}字符-因此您需要减去一个字符-您可以与从末尾修剪'\n'
一起使用)
一旦您已经阅读了第一行并说明了'\n'
,请设置一个变量,该变量保存数组中的字符数(列)。由于您知道数组是一个多维数据集,因此可以将第一行的长度与每隔一行读取的长度进行比较,以验证所有行的列数均相同。
在循环和处理每一行的输入时,您只需保留一个行计数器,当您完成读取操作后,该计数器将保存数组中的行数。
有两种方法可以处理阵列的存储。您可以声明一个足够大的数组以容纳最大的预期迷宫(同时保持足够小以适合堆栈'\n'
在Linux和Windoze上都是安全的),也可以为列和行动态分配存储,使用256x512
根据需要分配其他存储。 (在那里,您可以处理迷宫大小,直到计算机的内存限制-但这确实增加了复杂性)
您对我的阵列的“困惑”必须是realloc()
是可以理解的。这完全是因为终端上的字符大约是 tal 的两倍。因此,要打印一个“立方体”字符,所需的列大约是行的两倍。那根本不是问题。如果您正确地编写了对列和行的读取代码,并且具有跟踪列和行数的变量,那么区别仅不过是代码在几个变量中跟踪的数字。
以下是一个简短示例,用于解决读取未知数字或行和列(最大固定数目)时遇到的绊脚石。 (而不是动态分配和重新分配-我们可以留待以后使用)。为此,我们11x21
一个用于最大列数的常量,然后知道我们需要该行数的1/2,#define
一个用于该行数的常量,例如
#define
这是一个简单的事情,即声明变量以跟踪当前的#include <stdio.h>
#include <string.h>
#define MAXC 512 /* declare consts for max NxN you can handle */
#define MAXR (MAXC + 1) / 2
和row
以及行和列的总数(col
)以及声明数组{{ 1}}来抓住迷宫。然后,如果给定文件名作为第一个参数,则可以打开文件(如果没有给定参数,则默认情况下从nrow, ncol
读取)。无论哪种情况,您都可以验证自己是否有可供阅读的信息流,例如
a[MAXR][MAXC] = {""};
打开文件流以进行读取,现在只需读取文件中所有数据行即可。由于您希望所有行都具有偶数个字符,因此迷宫实际上是一个立方体,因此您可以在第一行中保存字符数(在修剪stdin
之后),然后将其与数字进行比较每隔一行中的一组字符来验证您是否具有多维数据集。读取行时,还需要保护数组边界,以免在数组中存储的行数不超过要容纳的行数,因此对 size_t row = 0, col = 0, nrow = 0, ncol = 0;
char a[MAXR][MAXC+1] = {""}; /* delcare and initialize array */
/* use filename provided as 1st argument (stdin by default) */
FILE *fp = argc > 1 ? fopen (argv[1], "r") : stdin;
if (!fp) { /* validate file open for reading */
perror ("file open failed");
return 1;
}
和{{1} }会施加该限制,例如
'\n'
现在,您已存储了所有行和列,并设置了row < MAXR
和fgets (a[row], MAXC, fp)
值,从而获得了 while (row < MAXR && fgets (a[row], MAXC, fp)) {
size_t len = strlen (a[row]); /* get length of row */
if (len && a[row][len-1] == '\n') /* validate it fits in array */
a[row][--len] = 0; /* remove trailing '\n' char from end */
else if (len == MAXC) {
fprintf (stderr, "error: row exceeds %d chars.\n", MAXC);
return 1;
}
if (!row) /* if 1st row - set expected ncol for each row */
ncol = len;
if (ncol != len) { /* validate all other rows against 1st */
fprintf (stderr, "error: unequal columns (%lu) on row (%lu)\n",
len, row);
return 1;
}
/* your code goes here - example just outputs array */
for (col = 0; col < ncol; col++)
putchar (a[row][col]);
putchar ('\n');
row++; /* advance row counter when done processing row */
}
if (fp != stdin) fclose (fp); /* close file if not stdin */
nrow = row; /* save the total number of rows */
数组。我将留给您的路径逻辑,但是我确实想提供一个示例,说明如何在您的路径中将nrow
替换为ncol
。对于每个可能的路径字符,以下操作只是强制每个nrow x ncol
具有相邻的空间(可以根据需要进行调整)的约束。在这里,我们只循环' '
并从'*'
嵌套一个循环以遍历数组中的每个字符。
当检查相邻单元格时,您唯一需要注意的皱纹是,当您检查左列时,必须确保自己不在迷宫的左边缘并且在检查右边的列时不在迷宫的右边缘(访问超出数组范围的元素将调用未定义行为)
您可以简单地将边缘检查作为对'*'
语句内部条件语句的加法处理,例如
0 -> nrow-1
在一个简短的示例中将所有内容放在一起以读取最多0 -> ncol-1
个字符的迷宫,您可以执行以下操作:
if (...)
使用/输出示例
如所示,代码仅读取并输出原始迷宫,然后在迷宫上进行第二遍输出,并用 /* you can make multiple passes over the array to determine your path.
* below is just an example of replacing the spaces in the path with
* asterisks.
*/
puts ("\nreplacing path spaces with asterisks\n");
for (row = 0; row < nrow; row++) {
for (col = 0; col < ncol; col++) {
/* if adjacents and current ' ', replace with '*' */
if (col && col < ncol - 1 && /* col > 0 && col < ncol-1 */
/* next checks adjacent and current all ' ' */
a[row][col-1] == ' ' && a[row][col] == ' ' &&
a[row][col+1] == ' ')
a[row][col] = '*'; /* if conditions met, set element '*' */
putchar (a[row][col]);
}
putchar ('\n');
}
填充路径
512
仔细检查一下,如果还有其他问题,请告诉我。