如何解决倒回文件指针时出现分段错误
当我的文件指针到达第二次倒带时,它会导致段错误。我不知道为什么。我将在顶部包含有问题的主体及其下方的所有代码。
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;
}
}
}
解决方法
例如,您需要通过返回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
)
这可确保仅在x
和y
中的值有效时使用它们。如您所写,x
或y
或两者都可能导致转换失败(出现 matching 或 input 失败),并且您仍在使用比较这些值并根据结果,将这些值分配给*verticies
,而不能保证x
或y
是有效的。
此外,正如您所写的,*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
的指针,并将b
和c
声明为简单整数。
int *a,c;
说清楚。
显然,编译器不在乎,它会忽略'*'
与变量名之间的空格,因此您所拥有的没有错-这更多是人为因素/可读性问题。
其他问题
如果您不使用size
,请从以下位置将其删除:
typedef struct linkedList{
Node* head;
int size;
} LinkedList;
此外,由于edges
和vertices
不能为负,size
或x
或y
也不能为负,因此将它们设置为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 -->
(注意:文件名现在可以作为程序的第一个参数传递)
版权声明:本文内容由互联网用户自发贡献,该文观点与技术仅代表作者本人。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如发现本站有涉嫌侵权/违法违规的内容, 请发送邮件至 dio@foxmail.com 举报,一经查实,本站将立刻删除。