C 循环时链表中的分段错误?

C 循环时链表中的分段错误?,c,C,我正在尝试用C语言设置一个图形。我尝试了使用用户输入的图形,它工作得非常好。但是,我正在尝试实现从文件读取。最后一条else语句是错误的来源,因为当我注释掉它时,它编译起来没有任何问题。我已经包括了一个评论块,我认为这有问题。如果这个问题还需要什么,请告诉我 #include <stdio.h> #include <stdlib.h> struct node{ int data; struct node* next; }; //int counter

我正在尝试用C语言设置一个图形。我尝试了使用用户输入的图形,它工作得非常好。但是,我正在尝试实现从文件读取。最后一条else语句是错误的来源,因为当我注释掉它时,它编译起来没有任何问题。我已经包括了一个评论块,我认为这有问题。如果这个问题还需要什么,请告诉我

#include <stdio.h>
#include <stdlib.h>

struct node{
    int data;
    struct node* next;
};

//int counter and mainVertex would be used to determine if graph is connected.

// void graphConnection(){
// 
// 
// 
// 
// 
// 
// }


char* deblank(char* input)
{
    int i,j;
    char *output=input;
    for (i = 0, j = 0; i<strlen(input); i++,j++)
    {
        if (input[i]!=' ')
            output[j]=input[i];
        else
            j--;
    }
    output[j]=0;
    return output;
}


struct node *G[1000];
int counter = 0;
char *mainVertex;

void readingEachLine(){

  FILE * fp;
  char * line = NULL;
  size_t len = 0;
  ssize_t read;

  //Read file and exit if fail
  fp = fopen("test.txt", "r");
  if (fp == NULL)
      exit(EXIT_FAILURE);

  while ((read = getline(&line, &len, fp)) != -1) {
    line = deblank(line);
    int i = 0;
    struct node* cursor = malloc(sizeof(struct node));
    struct node* secondcursor = malloc(sizeof(struct node));
    struct node* tempitem;
    while(line[i] != '\n'){

      //If its the first of the line look into the array and set struct cursor to the corresponding
      //array position

      if (i == 0){
        mainVertex[counter] = line[0];
        int convertor = line[i] - '0';
        cursor = G[convertor];
        counter++;
      }
      //if its not the first, then set a struct with that number as data

      else{
        tempitem = malloc(sizeof(struct node));
        int convertor = line[i] - '0';
        tempitem->data = convertor;
        tempitem->next = NULL;
      }
      //if there is no element connected to the struct in array, connect the tempitem

      if (cursor->next == NULL){
        cursor->next = tempitem;
      }
      //If there are already connected elements, loop until the end of the linked list
      //and append the tempitem
      //ERROR: I GET SEGMENTATION FAULT FROM HERE. TRIED AFTER COMMENTING IT OUT

      else{
        secondcursor = cursor;
        while(secondcursor->next != NULL){
          secondcursor = secondcursor->next;
        }
        secondcursor->next = tempitem;
      }
      i++;
    }
    printf("\n");
  }
}

int main(void){
  for (int i = 1; i < 1000; i++)
  {
      G[i]= malloc(sizeof(struct node));
      G[i]->data = i;
      G[i]->next = NULL;
  }
  readingEachLine();
}

您的代码有几个错误选项:

  • 显然,最多可以有1000个节点。您有一个包含1000个指向链接列表的头指针的数组
    G
    。不要在开始时为所有1000个节点分配内存。在开始时,所有列表都是空的,空链表是一个没有节点且其头为
    NULL
    的列表
  • 在您的示例中,
    cursor
    用于迭代已经存在的指针,所以不要为它分配内存。如果您有这样的代码:

    struct node *p = malloc(...);
    
    // next use of p:
    p = other_node;
    
    你不应该分配。您将覆盖
    p
    ,并丢失分配内存的句柄。并非所有指针都必须用
    malloc
    初始化;仅在创建节点时分配

  • 如果有超过9个节点,那么从一行中去掉所有空格然后解析单个数字的想法将失败。(但你需要1000个节点)不要试图自己解析这些数字。有用于此的库函数,例如
    strtol
  • 尚不清楚什么是
    mainVertex
    。当指定给它时,只能使用它一次。您将其视为一个数组,但它是一个全局指针,初始化为
    NULL
    。当您取消引用它时,您会得到未定义的行为,这就是您的分段错误可能来自的地方
这是一个你想做的程序。(为了简单起见,它总是在头部插入节点,并且应该有更多的分配检查。)

#包括
#包括
#包括
枚举{
最大节点数=1000
};
结构节点{
int数据;
结构节点*下一步;
};
结构节点*G[maxNodes];
大小n节点=0;
int read_图(常量字符*fn)
{
文件*fp;
char*line=NULL;
尺寸长度=0;
fp=fopen(fn,“r”);
if(fp==NULL)返回-1;
while(getline(&line,&len,fp)!=-1){
char*p;
字符*结束;
int-id;
int n;
id=strtol(第10行和第10行);
如果(结束==行)继续;
如果(id<1 | | id>maxNodes)中断;
如果(id>nnode)nnode=id;
id--;
p=结束;
n=strtol(p和end,10);
while(p!=结束){
结构节点*nnew=malloc(sizeof(*nnew));
nnew->data=n-1;
nnew->next=G[id];
G[id]=nnew;
p=结束;
n=strtol(p和end,10);
}
}
fclose(fp);
自由线;
返回0;
}
内部主(空)
{
如果(读取图表(“test.txt”)<0){
fprintf(stderr,“无法生成图形。\n”);
出口(1);
}
对于(int i=0;inext){
printf(“%d”,p->data+1);
}
认沽权(“”);
}
}
对于(int i=0;inext;
免费(旧);
}
}
返回0;
}

OT:关于:
if(fp==NULL)退出(退出失败)这会导致程序退出,而不会向用户提供任何发生情况的指示。建议:
if(fp==NULL){perror(“fopen失败”);exit(exit_FAILURE)}
,因为调用
perror()
将输出到
stderr
您的错误消息和系统认为错误发生的文本原因。,OT:调用任何堆分配函数时:
malloc
calloc
realloc
1)始终检查(!=NULL)返回值以确保操作成功。是否可以在回答中发布这些值?非常好的建议,希望解释代码应该写得同样健壮和合理。代码应该写得对用户非常友好。这些“OT”注释不是对您的问题的回答,对代码的执行也不是强制性的,因此它们被赋予前缀“OT”(offtopic),关于:int convertor=line[i]-“0”;在尝试将第一个字符转换为
int
struct node *p = malloc(...);

// next use of p:
p = other_node;
#include <stdio.h>
#include <stdlib.h>
#include <string.h>

enum {
    maxNodes = 1000
};

struct node{
    int data;
    struct node* next;
};

struct node *G[maxNodes];
size_t nnode = 0;

int read_graph(const char *fn)
{
    FILE * fp;
    char * line = NULL;
    size_t len = 0;

    fp = fopen(fn, "r");
    if (fp == NULL) return -1;

    while (getline(&line, &len, fp) != -1) {
        char *p;
        char *end;
        int id;
        int n;

        id = strtol(line, &end, 10);
        if (end == line) continue;

        if (id < 1 || id > maxNodes) break;

        if (id > nnode) nnode = id;
        id--;

        p = end;
        n = strtol(p, &end, 10);

        while (p != end) {
            struct node *nnew = malloc(sizeof(*nnew));

            nnew->data = n - 1;
            nnew->next = G[id];
            G[id] = nnew;

            p = end;
            n = strtol(p, &end, 10);
        }
    }

    fclose(fp);
    free(line);

    return 0;
}

int main(void)
{
    if (read_graph("test.txt") < 0) {
        fprintf(stderr, "Couldn't gread raph.\n");
        exit(1);
    }

    for (int i = 0; i < nnode; i++) {
        struct node *p = G[i];

        if (p) {
            printf("%d:", i + 1);

            for (; p; p = p->next) {
                printf(" %d", p->data + 1);
            }

            puts("");
        }
    }

    for (int i = 0; i < nnode; i++) {
        struct node *p = G[i];

        while (p) {
            struct node *old = p;

            p = p->next;
            free(old);
        }
    }

    return 0;
}