如何使用指针将矩阵文本文件读入C中的链表?
我必须使用矩阵链表阅读字母的文本文件,每个字母周围必须有8个指针 以下是我必须做的: 文本文件如下所示:如何使用指针将矩阵文本文件读入C中的链表?,c,C,我必须使用矩阵链表阅读字母的文本文件,每个字母周围必须有8个指针 以下是我必须做的: 文本文件如下所示: JDCPCPXOAA ZXVOVXFRVV NDLEIRBIEA YTRQOMOIIO FZZAPXERTQ XAUEOEOOTO PORTUOAZLZ CZNOQUPUOP 在我的代码中,我只能读第一行的字母 有人能帮我吗 typedef struct letter ///estrutura para cada letra da sopa { char *l
JDCPCPXOAA
ZXVOVXFRVV
NDLEIRBIEA
YTRQOMOIIO
FZZAPXERTQ
XAUEOEOOTO
PORTUOAZLZ
CZNOQUPUOP
在我的代码中,我只能读第一行的字母
有人能帮我吗
typedef struct letter ///estrutura para cada letra da sopa
{
char *lname;
struct letter *pnext;
}LETTER;
typedef struct soup ///estrutura para a sopa de letras
{
int lin;
int col;
LETTER *pfirst;
}SOUP;
void read_soup_txt(SOUP *pcs,char *fn,int lin,int col)
{
FILE *fp;
fp=fopen(fn,"r");
char c;
if(fp!=NULL)
{
pcs->lin=lin;
pcs->col=col;
LETTER *current=malloc(sizeof(LETTER)),*previous;
pcs->pfirst=current;
for(int i=0;i<pcs->lin;i++) ///linhas
{
for(int j=0;j<pcs->col;j++) ///colunas
{
fscanf(fp,"%c",&c); ///le o char
current->lname=malloc(sizeof(char)); ///aloca espaço para o char
strcpy(current->lname,&c); ///copia o char para a estrutura
previous=current;
if(i==pcs->lin-1)
{
current=NULL;
}
else
current=malloc(sizeof(LETTER));
previous->pnext=current;
}
}
}
else
printf("Erro ao abrir arquivo!");
fclose(fp);
}
typedef结构字母///estrutura para cada letra da sopa
{
char*lname;
结构字母*pnext;
}信件;
typedef struct soup///estrutura para a sopa de letras
{
林英特;
int col;
第一封信;
}汤;
无效读取\u soup\u txt(soup*pcs,char*fn,int-lin,int-col)
{
文件*fp;
fp=fopen(fn,“r”);
字符c;
如果(fp!=NULL)
{
pcs->lin=lin;
pcs->col=col;
字母*当前=malloc(sizeof(字母)),*先前;
pcs->pfirst=电流;
对于(int i=0;ilin;i++)///linhas
{
for(int j=0;jcol;j++)///colunas
{
fscanf(fp、%c、&c);///le o char
当前->lname=malloc(sizeof(char));///aloca espaço para o char
strcpy(当前->名称,&c);///copia o char para a estrutura
先前=当前;
如果(i==pcs->lin-1)
{
电流=零;
}
其他的
当前=malloc(sizeof(字母));
上一个->下一个=当前;
}
}
}
其他的
printf(“Erro ao abrir arquivo!”);
fclose(fp);
}
每个字母周围必须有8个指针
这意味着你的字母结构应该是
struct letter {
struct letter *up_left;
struct letter *up;
struct letter *up_right;
struct letter *left;
struct letter *right;
struct letter *down_left;
struct letter *down;
struct letter *down_right;
int letter;
};
你也不需要信汤。因为您按顺序读取字符,所以可以将它们直接读入图形中。诀窍在于,您需要将一个结构字母
指针保持在图形中左上角的字母;一个struct letter
指针,指向每行的第一个字母;和一个struct-letter
指针,用于您添加的每个新字母
以下是其中的逻辑:
注意输入流中的第一个字符是如何以不同方式处理的(在最开始的时候),以及每个后续行上的第一个字符是如何以不同方式处理的(在函数末尾附近)。这在逻辑上或结构上可能会让人感到奇怪,但这样做可以使代码保持简单
还要注意双向链路是如何构造的。因为我们从上到下,从左到右阅读,我们首先建立链接左,然后左上,然后右上;在前向链接之后立即使用后向链接
这需要一点思考,才能理解它为什么有效。考虑:
up_left │ up │ up_right
──────────┼──────┼───────────
left │ curr │ right
──────────┼──────┼───────────
down_left │ down │ down_right
当我们构造curr
时,我们知道left
是否存在,因为我们分别处理每行的第一个字母
如果curr->left
不为空,并且curr->left->up
不为空,我们知道前面有一行,我们可以指向curr->up_left
。当然,它的->右下
应该指向curr
,以便链接保持一致
如果curr->up\u left
为非空,并且curr->up\u left->right
为非空,则我们知道前一行在同一列中有一个字母。我们可以设置curr->up
指向它,设置->down
指向curr
如果curr->up
为非空,并且curr->up->right
为非空,我们知道前一行在下一列中有一个字母。我们可以设置curr->up\u right
指向它,其->down\u left
指向curr
现在,因为我们从左到右读取每一行,所以每一行上的所有列都会填充到最右边的列。如果继续使用上述逻辑,您将发现第二行填充了从第一行字母到第二行字母的其余链接,依此类推
这还意味着,如果输入文件包含一个特殊字符,例如非字母节点的'*'
,则应在构建图形时创建这些字符,就像它们是普通字母一样,以确保上述链接逻辑正常工作
读取整个图形后,您可以从图形中逐个删除这些非字母节点。要删除节点,首先将指向该节点的反向链接(从其相邻字母)设置为NULL,然后free()
it
我个人在free()
之前对结构“下毒”,将letter
设置为一个已知的不可能值(WEOF
,用于宽输入端),并将所有指向NULL
的链接设置为空,这样如果其他代码在释放后使用该结构(这将是释放bug后的使用),例如,由于它以某种方式缓存了指针,因此更容易检测
(当您free()
指针时,C库通常不会立即将其返回到操作系统,也不会清除它;通常,动态分配的区域只是添加到内部空闲堆中,以便将来的分配可以重用该内存。不幸的是,这意味着如果您不“中毒”被释放的结构,有时它们在释放bug之后仍然可以访问。这种在释放bug之后的使用是非常烦人的,为了帮助调试这些bug而毒害结构的“不必要的工作”绝对值得。)
为了便于中毒,并且如果在某个时候发现中毒是不必要的,为了便于消除中毒,最好使用辅助函数来创建和破坏结构:
static inline struct letter *new_letter(const int letter)
{
struct letter *one;
one = malloc(sizeof *one);
if (!one) {
fprintf(stderr, "new_letter(): Out of memory.\n");
exit(EXIT_FAILURE);
}
one->up_left = NULL;
one->up = NULL;
one->up_right = NULL;
one->left = NULL;
one->right = NULL;
one->down_left = NULL;
one->down = NULL;
one->down_right = NULL;
one->letter = letter;
return one;
}
static inline void free_letter(struct letter *one)
{
if (one) {
one->up_left = NULL;
one->up = NULL;
one->up_right = NULL;
one->left = NULL;
one->right = NULL;
one->down_left = NULL;
one->down = NULL;
one->down_right = NULL;
one->letter = EOF;
free(one);
}
}
我通常在头文件中包含这些函数,该头文件定义了struct letter
;因为它们是微小的类似宏的函数,我将它们标记为静态内联
,告诉C编译器它们只需要在同一个编译单元中访问,它不需要生成函数和调用这些函数,而是可以将代码内联到调用它们的任何地方
就我个人而言,我撰写并验证了上述内容
static inline struct letter *new_letter(const int letter)
{
struct letter *one;
one = malloc(sizeof *one);
if (!one) {
fprintf(stderr, "new_letter(): Out of memory.\n");
exit(EXIT_FAILURE);
}
one->up_left = NULL;
one->up = NULL;
one->up_right = NULL;
one->left = NULL;
one->right = NULL;
one->down_left = NULL;
one->down = NULL;
one->down_right = NULL;
one->letter = letter;
return one;
}
static inline void free_letter(struct letter *one)
{
if (one) {
one->up_left = NULL;
one->up = NULL;
one->up_right = NULL;
one->left = NULL;
one->right = NULL;
one->down_left = NULL;
one->down = NULL;
one->down_right = NULL;
one->letter = EOF;
free(one);
}
}
#include <stdlib.h>
#include <locale.h>
#include <wchar.h>
#include <stdio.h>
struct letter {
struct letter *chain; /* Internal chain of all known letters */
struct letter *up_left;
struct letter *up;
struct letter *up_right;
struct letter *left;
struct letter *right;
struct letter *down_left;
struct letter *down;
struct letter *down_right;
wint_t letter;
};
static struct letter *all_letters = NULL;
struct letter *new_letter(wint_t letter)
{
struct letter *one;
one = malloc(sizeof *one);
if (!one) {
fprintf(stderr, "new_letter(): Out of memory.\n");
exit(EXIT_FAILURE);
}
one->letter = letter;
one->chain = all_letters;
all_letters = one;
one->up_left = NULL;
one->up = NULL;
one->up_right = NULL;
one->left = NULL;
one->right = NULL;
one->down_left = NULL;
one->down = NULL;
one->down_right = NULL;
return one;
}
if (!setlocale(LC_ALL, ""))
fprintf(stderr, "Warning: Current locale is not supported by your C library.\n");
if (fwide(stdin, 1) < 1)
fprintf(stderr, "Warning: Wide standard input is not supported by your C library for current locale.\n");
if (fwide(stdout, 1) < 1)
fprintf(stderr, "Warning: Wide standard output is not supported by your C library for current locale.\n");
int letter_graph(FILE *out)
{
struct letter *one;
/* Sanity check. */
if (!out || ferror(out))
return -1;
/* Wide output. */
if (fwide(out) < 1)
return -1;
fwprintf(out, L"digraph {\n");
for (one = all_letters; one != NULL; one = one->chain) {
fwprintf(out, L" \"%p\" [ label=\"%lc\" ];\n",
(void *)one, one->letter);
if (one->up_left)
fwprintf(out, L" \"%p\" -> \"%p\" [ label=\"↖\" ];\n",
(void *)one, (void *)(one->up_left));
if (one->up)
fwprintf(out, L" \"%p\" -> \"%p\" [ label=\"↑\" ];\n",
(void *)one, (void *)(one->up));
if (one->up_right)
fwprintf(out, L" \"%p\" -> \"%p\" [ label=\"↗\" ];\n",
(void *)one, (void *)(one->up_right));
if (one->left)
fwprintf(out, L" \"%p\" -> \"%p\" [ label=\"←\" ];\n",
(void *)one, (void *)(one->left));
if (one->right)
fwprintf(out, L" \"%p\" -> \"%p\" [ label=\"→\" ];\n",
(void *)one, (void *)(one->right));
if (one->down_left)
fwprintf(out, L" \"%p\" -> \"%p\" [ label=\"↙\" ];\n",
(void *)one, (void *)(one->down_left));
if (one->down)
fwprintf(out, L" \"%p\" -> \"%p\" [ label=\"↓\" ];\n",
(void *)one, (void *)(one->down));
if (one->down_right)
fwprintf(out, L" \"%p\" -> \"%p\" [ label=\"↘\" ];\n",
(void *)one, (void *)(one->down_right));
}
fwprintf(out, L"}\n");
return 0;
}
ABC
DEF
GHI
digraph {
"0x1c542f0" [ label="I" ];
"0x1c542f0" -> "0x1c54170" [ label="↖" ];
"0x1c542f0" -> "0x1c541d0" [ label="↑" ];
"0x1c542f0" -> "0x1c54290" [ label="←" ];
"0x1c54290" [ label="H" ];
"0x1c54290" -> "0x1c54110" [ label="↖" ];
"0x1c54290" -> "0x1c54170" [ label="↑" ];
"0x1c54290" -> "0x1c541d0" [ label="↗" ];
"0x1c54290" -> "0x1c54230" [ label="←" ];
"0x1c54290" -> "0x1c542f0" [ label="→" ];
"0x1c54230" [ label="G" ];
"0x1c54230" -> "0x1c54110" [ label="↑" ];
"0x1c54230" -> "0x1c54170" [ label="↗" ];
"0x1c54230" -> "0x1c54290" [ label="→" ];
"0x1c541d0" [ label="F" ];
"0x1c541d0" -> "0x1c54050" [ label="↖" ];
"0x1c541d0" -> "0x1c540b0" [ label="↑" ];
"0x1c541d0" -> "0x1c54170" [ label="←" ];
"0x1c541d0" -> "0x1c54290" [ label="↙" ];
"0x1c541d0" -> "0x1c542f0" [ label="↓" ];
"0x1c54170" [ label="E" ];
"0x1c54170" -> "0x1c53ff0" [ label="↖" ];
"0x1c54170" -> "0x1c54050" [ label="↑" ];
"0x1c54170" -> "0x1c540b0" [ label="↗" ];
"0x1c54170" -> "0x1c54110" [ label="←" ];
"0x1c54170" -> "0x1c541d0" [ label="→" ];
"0x1c54170" -> "0x1c54230" [ label="↙" ];
"0x1c54170" -> "0x1c54290" [ label="↓" ];
"0x1c54170" -> "0x1c542f0" [ label="↘" ];
"0x1c54110" [ label="D" ];
"0x1c54110" -> "0x1c53ff0" [ label="↑" ];
"0x1c54110" -> "0x1c54050" [ label="↗" ];
"0x1c54110" -> "0x1c54170" [ label="→" ];
"0x1c54110" -> "0x1c54230" [ label="↓" ];
"0x1c54110" -> "0x1c54290" [ label="↘" ];
"0x1c540b0" [ label="C" ];
"0x1c540b0" -> "0x1c54050" [ label="←" ];
"0x1c540b0" -> "0x1c54170" [ label="↙" ];
"0x1c540b0" -> "0x1c541d0" [ label="↓" ];
"0x1c54050" [ label="B" ];
"0x1c54050" -> "0x1c53ff0" [ label="←" ];
"0x1c54050" -> "0x1c540b0" [ label="→" ];
"0x1c54050" -> "0x1c54110" [ label="↙" ];
"0x1c54050" -> "0x1c54170" [ label="↓" ];
"0x1c54050" -> "0x1c541d0" [ label="↘" ];
"0x1c53ff0" [ label="A" ];
"0x1c53ff0" -> "0x1c54050" [ label="→" ];
"0x1c53ff0" -> "0x1c54110" [ label="↓" ];
"0x1c53ff0" -> "0x1c54170" [ label="↘" ];
}
for (one = all_letters; one != NULL; one = one->chain) {
if (one->up_left && one->up_left->down_right != one)
fprintf(stderr, "'%c'->up_left is broken!\n", one->letter);
if (one->up && one->up->down != one)
fprintf(stderr, "'%c'->up is broken!\n", one->letter);
if (one->up_right && one->up_right->down_left != one)
fprintf(stderr, "'%c'->up_right is broken!\n", one->letter);
if (one->left && one->left->right != one)
fprintf(stderr, "'%c'->left is broken!\n", one->letter);
if (one->right && one->right->left != one)
fprintf(stderr, "'%c'->right is broken!\n", one->letter);
if (one->down_left && one->down_left->up_right != one)
fprintf(stderr, "'%c'->down_left is broken!\n", one->letter);
if (one->down && one->down->up != one)
fprintf(stderr, "'%c'->down is broken!\n", one->letter);
if (one->down_right && one->down_right->up_left != one)
fprintf(stderr, "'%c'->down_right is broken!\n", one->letter);
}