[英]Reading in an array for maze file in C with an uneven size of cube and extra characters
我試圖弄清楚如何正確地從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多維數據集(a +---+
表示一側, |
表示另一側)
為了回答您的問題和評論中的問題,確定行和列的大小非常簡單。 當您使用fgets
從文件中讀取數組的一行時,可以使用strlen()
確定字符數( 但請注意 ,它也包含'\\n'
字符-因此您需要減去一個-您可以可以與從末尾修剪'\\n'
結合使用)
讀完第一行並說明'\\n'
,請設置一個變量,該變量保存數組中的字符(列)數。 由於您知道數組是一個多維數據集,因此可以將第一行的長度與每隔一行讀取的長度進行比較,以驗證所有行的列數均相同。
在循環和處理每一行的輸入時,您只需保留一個行計數器,當您完成讀取操作后,該計數器將保存數組中的行數。
有兩種方法可以處理陣列的存儲。 您可以聲明一個足夠大的數組以容納最大的預期迷宮(同時保持足夠小的大小以適合堆棧,在Linux和Windoze上都是256x512
都是安全的),也可以使用realloc()
為列和行動態分配存儲空間根據需要分配其他存儲。 (在那里,您可以處理迷宮大小,直到計算機的內存限制-但這確實增加了復雜性)
您對我的陣列的“困惑”必須是可以理解的,例如11x21
。 這一切都從一個事實,即一個終端上的字符大致兩倍高度比寬莖。 因此,要打印一個“立方體”字符,所需的列大約是行的兩倍。 那根本不是問題。 如果您正確編寫了對列和行的讀取的代碼,並且具有跟蹤列和行數的變量,那么區別僅不過是代碼在幾個變量中跟蹤的數字。
以下是一個簡短示例,用於解決讀取未知數量或行和列(最大固定數目)時遇到的絆腳石。 (而不是動態分配和重新分配-我們可以留待以后使用)。 要做到這一點,我們#define
的列的最大數量恆定,然后知道我們需要1/2的行數, #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
以及row
和col
的總數( 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;
}
打開文件流以進行讀取后,現在只需讀取文件中所有數據行即可。 由於您希望所有行都具有偶數個字符,因此迷宮實際上是一個立方體,因此可以將第一行中的字符數保存(修剪'\\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
0 -> nrow-1
的循環以遍歷數組中的每個字符。
連續檢查相鄰單元格時唯一需要注意的皺紋是,當您檢查列的左側而不是迷宮的右邊緣時,必須確保自己不在迷宮的左邊緣當檢查右邊的列時(訪問超出數組范圍的元素將調用Undefined Behavior )
您可以將邊緣檢查作為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
字符的迷宮,您可以執行以下操作:
#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;
}
使用/輸出示例
如所示,代碼僅讀取並輸出原始迷宮,然后在迷宮上進行第二遍輸出,並用'*'
填充路徑
$ ./bin/array2dread <dat/arrmaze.txt
+---+---+---+---+---+
| | |
+---+ + + + +
| | | | | |
+ + + + +---+
| | | | |
+ + + +---+ +
| | | |
+ +---+---+ + +
| | |
+---+---+---+---+---+
replacing path spaces with asterisks
+---+---+---+---+---+
| * * * | * * * * * |
+---+ * + * + * + * +
| * | * | * | * | * |
+ * + * + * + * +---+
| * | * | * | * * * |
+ * + * + * +---+ * +
| * * * | * | * * * |
+ * +---+---+ * + * +
| * * * * * * * | * |
+---+---+---+---+---+
仔細檢查一下,如果您還有其他問題,請告訴我。
聲明:本站的技術帖子網頁,遵循CC BY-SA 4.0協議,如果您需要轉載,請注明本站網址或者原文地址。任何問題請咨詢:yoyou2525@163.com.