Warning: file_get_contents(/data/phpspider/zhask/data//catemap/4/c/59.json): failed to open stream: No such file or directory in /data/phpspider/zhask/libs/function.php on line 167

Warning: Invalid argument supplied for foreach() in /data/phpspider/zhask/libs/tag.function.php on line 1116

Notice: Undefined index: in /data/phpspider/zhask/libs/function.php on line 180

Warning: array_chunk() expects parameter 1 to be array, null given in /data/phpspider/zhask/libs/function.php on line 181
如何使用指针将矩阵文本文件读入C中的链表?_C - Fatal编程技术网

如何使用指针将矩阵文本文件读入C中的链表?

如何使用指针将矩阵文本文件读入C中的链表?,c,C,我必须使用矩阵链表阅读字母的文本文件,每个字母周围必须有8个指针 以下是我必须做的: 文本文件如下所示: JDCPCPXOAA ZXVOVXFRVV NDLEIRBIEA YTRQOMOIIO FZZAPXERTQ XAUEOEOOTO PORTUOAZLZ CZNOQUPUOP 在我的代码中,我只能读第一行的字母 有人能帮我吗 typedef struct letter ///estrutura para cada letra da sopa { char *l

我必须使用矩阵链表阅读字母的文本文件,每个字母周围必须有8个指针

以下是我必须做的:

文本文件如下所示:

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