倒回文件指针时出现分段错误

当我的文件指针到达第二次倒带时,它会导致段错误。我不知道为什么。我将在顶部包含有问题的主体及其下方的所有代码。

int main(void){
    // creating the file pointer
    FILE *fptr = fopen("input-machine-problem-1.txt","r");
    if (fptr == NULL) {
        printf("Error! opening file");
        return 0;
    }

    int edges;
    int vertices;
    int* edgesPtr = &edges;
    int* verticesPtr = &vertices;
    getNumberOfVerticesAndEdges(fptr,verticesPtr,edgesPtr);

    LinkedList arrayOfLinkedLists[vertices];

    int x,y;
    for(int i = 0; i < vertices; i++){ 
        if(fptr == NULL){
            return 0;
        }
        rewind(fptr);
        for(int j = 0; j < edges; j++){
            
            printf("%d: ",j);
            fscanf (fptr,"%d %d",&x,&y);    
            printf ("%d %d ",x,y);
            if(i == x){
                push(arrayOfLinkedLists[i],y);
            } else if(i == y){
                push(arrayOfLinkedLists[i],x);
            }
            printf("**\n");
        }
    }

    // printAdjacencyLists(arrayOfLinkedLists,vertices);
    fclose (fptr); 
}

要复制和粘贴的整个文件:

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

typedef struct node{
    int vertexNumber;
    struct node *next;
} Node;

typedef struct linkedList{
    Node* head;
    int size;
} LinkedList;

void getNumberOfVerticesAndEdges(FILE* fp,int* vertices,int* edges);
void push(LinkedList linkedList,int vertex);
Node* createNode(int vertexNumber);
void printAdjacencyLists(LinkedList* arrayOfLinkedLists,int vertices);

int main(void){
    // creating the file pointer
    FILE *fptr = fopen("input-machine-problem-1.txt",vertices);
    fclose (fptr); 
}

void push(LinkedList linkedList,int vertex){
    Node* newNode = createNode(vertex);

    Node* cur = linkedList.head;
    Node* prev = cur;
    if(cur == NULL){
        linkedList.head = newNode;
        return;
    }
    while(newNode->vertexNumber > cur->vertexNumber){
        prev = cur;
        cur = cur->next;
    }
    newNode->next = cur;
    prev->next = newNode;


}

Node* createNode(int vertexNumber){
    Node* newNode = malloc(sizeof(Node));
    if(!newNode){
        return NULL;
    }
    newNode->vertexNumber = vertexNumber;
    newNode->next = NULL;
    return newNode;
}

void getNumberOfVerticesAndEdges(FILE* fp,int* edges){
    if (fp == NULL) {
        printf("Error! opening file");
        return;
    } 

    *vertices = 0;
    *edges = 0;
    while(1){
        int x,y;

        fscanf(fp,"%d %d^\n",&y);

        if(x > *vertices){
            *vertices = x;
        } if (y > *vertices){
            *vertices = y;
        }

        *edges = (*edges) + 1;

        if(feof(fp)) { 
            return;
        }
    }
}

void printAdjacencyLists(LinkedList* arrayOfLinkedLists,int vertices){
    for(int i = 0; i < vertices; i++){
        printf("\n%d:  ",i);
        if(arrayOfLinkedLists[i].head == NULL){
            return;
        }
        Node* cur = arrayOfLinkedLists[i].head;
        while(cur != NULL){
            printf("%d --> ",cur->vertexNumber);
            cur = cur->next;
        }
    }
}

Davids168 回答:倒回文件指针时出现分段错误

例如,您需要通过返回fscanf()来控制读循环,

void getNumberOfVerticesAndEdges(FILE* fp,int* vertices,int* edges)
{
    int x,y;
    
    if (fp == NULL) {
        printf("Error! opening file");
        return;
    } 

    *vertices = 0;
    *edges = 0;
    while (fscanf(fp,"%d %d",&x,&y) == 2) {
        if(x > *vertices){
            *vertices = x;
        } if (y > *vertices){
            *vertices = y;
        }

        *edges = (*edges) + 1;
    }
}

注意:您的格式字符串中不需要^\n

这可确保仅在xy中的值有效时使用它们。如您所写,xy或两者都可能导致转换失败(出现 matching input 失败),并且您仍在使用比较这些值并根据结果,将这些值分配给*verticies,而不能保证xy是有效的。

此外,正如您所写的,*edges = (*edges) + 1;fscanf()失败之后并且在检查导致edges偏离太多的流状态之前被执行。

除非您检查退货,否则您将无法正确使用任何输入功能。如果您还有其他问题,请告诉我。您的代码可能还有其他问题,但是一旦读取失败-这可能是您的第一个主要问题。

下一个SegFault

您的下一个SegFault位于push()

while(newNode->vertexNumber > cur->vertexNumber){
    prev = cur;
    cur = cur->next;
}

通过取消引用cur == NULL之前是否检查cur->vertexNumber来检查列表结尾。每次都会这样做。您可以使用以下方法修复它:

while (cur && newNode->vertexNumber > cur->vertexNumber) {

“ *”在哪里?

在代码中,您将间接引用附加到类型而不是变量。可能会产生误导。为什么?

int* a,b,c;

在您上面肯定没有声明三个指向int的指针。相反,您将a声明为指向int的指针,并将bc声明为简单整数。

int *a,c;

说清楚。

显然,编译器不在乎,它会忽略'*'与变量名之间的空格,因此您所拥有的没有错-这更多是人为因素/可读性问题。

其他问题

如果您不使用size,请从以下位置将其删除:

typedef struct linkedList{
    Node* head;
    int size;
} LinkedList;

此外,由于edgesvertices不能为负,sizexy也不能为负,因此将它们设置为size_t int。您将type与变量用途匹配,并且在x86_64上,您获得了另外4个字节的范围。

对您的代码采用另一种方法

理想情况下,您只想读取一次数据文件。如果您动态分配指针而不是对LinkedList arrayOfLinkedLists[vertices];使用VLA,则可以这样做,我将其实现留给您。解决上述问题并稍微清理push()函数,您可以执行以下操作:

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

typedef struct node{
    size_t vertexNumber;
    struct node *next;
} Node;

typedef struct linkedList{
    Node *head;
    size_t size;
} LinkedList;

Node *createNode (size_t vertexNumber)
{
    Node *newNode = malloc (sizeof *newNode);
    
    if (!newNode) {
        perror ("malloc-newNode");
        return NULL;
    }
    
    newNode->vertexNumber = vertexNumber;
    newNode->next = NULL;
    
    return newNode;
}

int getNumberOfVerticesAndEdges (FILE *fp,size_t *vertices)
{
    size_t edges = 0,x,y;
    
    *vertices = 0;
    
    while (fscanf(fp,"%zu %zu",&y) == 2) {
        if (x > *vertices)
            *vertices = x;
        if (y > *vertices)
            *vertices = y;

        edges += 1;
    }
    
    return edges;
}

/* add nodes in order of vertexNumber to each list */
Node *push (LinkedList *list,size_t vertex)
{
    Node *newNode = createNode(vertex);         /* create new node/initialize */
    
    if (!newNode)                               /* validate node */
        return NULL;
    
    list->size += 1;                            /* node allocated,increment count */
    
    if (!list->head) {                          /* if 1st node,node is head/tail */
        list->head = newNode;
        return list->head;
    }
    
    Node **pp = &list->head,/* iterate with address of pointer */
          *p  = list->head;                     /* and pointer to node */
    
    while (p) { /* loop over each node */
        if (vertex < p->vertexNumber) {         /* if new vertext less than current */
            *pp = newNode;                      /* replace current with new */
            newNode->next = p;                  /* set new->next to current */
            return newNode;
        }
        pp = &p->next;                          /* advance to next node */
        p = p->next;
    }
    
    return *pp = newNode;                       /* insert at end */
}

void printAdjacencyLists (LinkedList *arrayOfLinkedLists,size_t vertices)
{
    for (size_t i = 0; i < vertices; i++) {
        printf ("\n%zu:  ",i);
        
        if (arrayOfLinkedLists[i].head == NULL)
            return;
        
        Node *cur = arrayOfLinkedLists[i].head;
        
        while (cur){
            printf("%zu --> ",cur->vertexNumber);
            cur = cur->next;
        }
    }
    putchar ('\n');     /* tidy up with newline */
}

void freelists (LinkedList *a,size_t v)
{
    for (size_t i = 0; i < v; i++) {
        Node *node = a[i].head;
        while (node) {
            Node *victim = node;
            node = node->next;
            free (victim);
        }
    }
}

int main (int argc,char **argv){
    
    size_t edges = 0,vertices = 0,y;
    /* open filename provides as 1st argument,use default if none provided */
    FILE *fptr = fopen (argc > 1 ? argv[1] : "input-machine-problem-1.txt","r");
    
    if (!fptr) {
        perror ("fopen-fptr");
        return 1;
    }

    if (!(edges = getNumberOfVerticesAndEdges (fptr,&vertices))) {
        fputs ("error: failed to read edges.\n",stderr);
        return 1;
    }
    
    /* initialize array of lists all zero/NULL */
    LinkedList arrayOfLinkedLists[vertices];
    memset (arrayOfLinkedLists,sizeof arrayOfLinkedLists);

    for (size_t i = 0; i < vertices; i++) { 
        if (!fptr) {
            return 1;
        }
        rewind(fptr);
        for (size_t j = 0; j < edges; j++) {
            
            printf("%zu: ",j);
            if (fscanf (fptr,&y) != 2) {
                fprintf (stderr,"error reading vertex: %zu,edge: %zu\n",i,j);
                return 1;
            }   
            printf ("%zu %zu ",y);
            
            if (i == x) {
                if (!push (&arrayOfLinkedLists[i],y))
                    return 1;
            }
            else if (i == y) {
                if (!push (&arrayOfLinkedLists[i],x))
                    return 1;
            }
            printf("**\n");
        }
    }
    fclose (fptr);

    printAdjacencyLists (arrayOfLinkedLists,vertices);
    
    freelists (arrayOfLinkedLists,vertices);
}

上面还包括一​​个freelists()函数,用于free()为列表分配的所有内存。始终确保跟踪并释放分配的内存。这样,在分配main()以外的资源时,您不会创建内存泄漏。

由输入/输出组成的示例

使用示例顶点执行代码将得到以下输出:

$ ./bin/getverticies dat/edgelist.txt
0: 0 1 **
1: 2 3 **
2: 3 2 **
3: 1 0 **
0: 0 1 **
1: 2 3 **
2: 3 2 **
3: 1 0 **
0: 0 1 **
1: 2 3 **
2: 3 2 **
3: 1 0 **

0:  1 --> 1 -->
1:  0 --> 0 -->
2:  3 --> 3 -->

注意:文件名现在可以作为程序的第一个参数传递)

本文链接:https://www.f2er.com/1492646.html

大家都在问