gpt4 book ai didi

c - 在数组中读取迷宫文件的数组,立方体大小不均,多余字符

转载 作者:太空宇宙 更新时间:2023-11-04 07:53:14 26 4
gpt4 key购买 nike

我正试图找出如何正确地读入和存储C.txt文档中的迷宫。这个迷宫的最大大小是40x40“立方体”。读完后,我将需要解决它,通过放置路径从左下角到右下角与*。我习惯于使用二维数组,但这个问题一直困扰着我,因为我不知道如何跟踪行和列,如果它们不完全均匀,或者我甚至不知道如何准确地在每个“立方体”的中间打印一个*。我读过其他由1和0组成的迷宫的例子,甚至所有的迷宫都是为墙壁设计的,这样可以很容易地读入和跟踪,但不需要像这样输入。在解决第一个迷宫后,我需要在同一个文本文件上读取其他迷宫,第一个迷宫将由一个双空格分隔。下面是其中一个迷宫的示例:

+---+---+---+---+---+  
| | |
+---+ + + + +
| | | | | |
+ + + + +---+
| | | | |
+ + + +---+ +
| | | |
+ +---+---+ + +
| | |
+---+---+---+---+---+

这里是我的一些代码,我目前正在做的错误检查和阅读字符。在它中,我试图初始化一个120x120的数组,读取当前字符,并将这些字符转换为-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个立方体(一边是a +---+,另一边是a |

最佳答案

针对您在评论中提出的问题,确定行和列的大小是非常直接的。当您使用fgets从文件中读取数组的一行时,可以使用strlen()来确定字符数(但请注意,它还包含'\n'字符-因此您需要减去一个-这可以与从结尾处修剪'\n'结合使用)
读取第一行并计算'\n'后,设置一个变量来保存数组中的字符数(列)。由于您知道数组是多维数据集,因此可以将第一行的长度与读取的每一行的长度进行比较,以验证所有行具有相同数量的列。
在循环和处理每一行的输入时,您只需保留一个行计数器,当您完成读操作时,该计数器将保存数组中的行数。
有两种方法可以处理阵列的存储。您可以声明一个足够大的数组来容纳最大的预期迷宫(同时保持它足够小以适合堆栈256x512在Linux和Windoze上都是安全的),也可以动态地为列和行分配存储空间,根据需要使用realloc()来分配额外的存储空间。(在那里你可以处理迷宫的大小直到你的计算机的内存限制-但是它确实增加了复杂性)
你对我的数组的“困惑”是可以理解的,例如11x21这一切都源于终端上的字符大约是宽字符的两倍。因此,要打印字符的“立方体”,需要的列数大约是行数的两倍。这根本不是问题。如果对列和行的读取进行了正确的编码,并且让变量跟踪列和行的数量,那么差异就只不过是代码在几个变量中跟踪的数字。
下面是一个简短的例子来解决您在读取未知数或行和列到固定最大值时遇到的绊脚石。(而不是动态分配和重新分配——我们可以稍后再讨论)。要做到这一点,我们#define一个最大列数的常数,然后知道我们需要1/2个行数, 一个行数的常数,例如

#include <stdio.h>
#include <string.h>

#define MAXC 512 /* declare consts for max NxN you can handle */
#define MAXR (MAXC + 1) / 2

然后,声明变量来跟踪当前的 #definerow以及行和列的总数( col)以及声明一个数组来保存迷宫就很简单了。如果文件名是第一个参数,则可以打开文件(如果没有参数,则默认从 nrow, ncol读取)。在这两种情况下,您都可以验证是否打开了一个流以供读取,例如。
    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;
}

打开文件流进行读取后,现在只需读取文件中的所有行数据。由于您希望所有行的字符数都是偶数,因此迷宫实际上是一个立方体,因此您可以保存第一行的字符数(在修剪 a[MAXR][MAXC] = {""};之后),并使用它与每行的字符数进行比较,以验证是否有立方体。在读取行时,还需要保护数组边界,这样就不会试图在数组中存储超过要保存行数的行,因此对 stdin'\n'进行简单的检查将强制执行该限制,例如。
    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 */

现在已经存储了的所有行和列,并且设置了 row < MAXRfgets (a[row], MAXC, fp)值,为您提供 nrow数组。我将留给您的路径逻辑,但我确实想提供一个如何将路径中的 ncol替换为 nrow x ncol的示例。下面的操作只针对每个可能的路径字符执行约束,即每个 ' '都有一个相邻的空间(您可以根据需要进行调整)。这里我们只循环 '*'并在数组中的每个字符上嵌套一个循环。
检查行中相邻单元格时唯一需要注意的问题是,检查列时必须确保不在迷宫的左边缘,检查列时不在迷宫的右边缘(访问超出数组边界的元素将调用未定义的行为)
您可以将边缘检查作为对 '*'语句内部条件的简单添加来处理,例如。
    /* 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');
}

把所有的片段放在一个简短的例子中,阅读任何一个长达 0 -> nrow-1个字符的迷宫,您可以执行如下操作:
#include <stdio.h>
#include <string.h>

#define MAXC 512 /* declare consts for max NxN you can handle */
#define MAXR (MAXC + 1) / 2

int main (int argc, char **argv) {

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;
}

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 */

/* 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');
}

return 0;
}

示例使用/输出
如图所示,代码只是读取并输出原始迷宫,然后在迷宫上进行第二次传递,输出路径为 0 -> ncol-1
$ ./bin/array2dread <dat/arrmaze.txt
+---+---+---+---+---+
| | |
+---+ + + + +
| | | | | |
+ + + + +---+
| | | | |
+ + + +---+ +
| | | |
+ +---+---+ + +
| | |
+---+---+---+---+---+

replacing path spaces with asterisks

+---+---+---+---+---+
| * * * | * * * * * |
+---+ * + * + * + * +
| * | * | * | * | * |
+ * + * + * + * +---+
| * | * | * | * * * |
+ * + * + * +---+ * +
| * * * | * | * * * |
+ * +---+---+ * + * +
| * * * * * * * | * |
+---+---+---+---+---+

再看一遍,如果你还有问题,请告诉我。

关于c - 在数组中读取迷宫文件的数组,立方体大小不均,多余字符,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/52461768/

26 4 0
Copyright 2021 - 2024 cfsdn All Rights Reserved 蜀ICP备2022000587号
广告合作:1813099741@qq.com 6ren.com