所以,这就是事情。我有这个程序,它将不同的作者存储在链表中,每个作者都有自己的记录,每个记录都保存着他的文本,并在链表中组织。从文件中读取数据。这是代码:
#include <stdio.h>
#include <stdlib.h>
#include <string.h>
#include <stdbool.h>
struct AuthorRecord
{
char textTitle[100];
int NumberOfWords;
long Download;
struct AuthorRecord *next;
};
typedef struct AuthorRecord *AuthorRecordType;
typedef struct
{
char firstName[30];
char lastName[30];
int idNumber;
int textNum;
AuthorRecordType text;
} AuthorType;
struct MemberNodeStruct
{
AuthorType *anAuthor;
struct MemberNodeStruct *next;
};
typedef struct MemberNodeStruct *MemberNodeType;
FILE* input;
FILE* output;
MemberNodeType head;
MemberNodeType member;
int main (void)
{
int authorNum, textNum, i, j;
member = malloc(sizeof(struct MemberNodeStruct));
head = member;
member->next = NULL;
input = fopen("input.txt", "r");
if (input == NULL)
{
printf("Could not open file.\n");
return 1;
}
fscanf(input, "%d", &authorNum);
for (i = 0; i < authorNum; i++)
{
member->anAuthor = malloc(sizeof(AuthorType));
textNum = 0;
if(fscanf(input, "%s %s %d", member->anAuthor->lastName, member->anAuthor->firstName, &member->anAuthor->idNumber) != EOF)
{
fscanf(input, "%d", &member->anAuthor->textNum);
for (j = 0; j < member->anAuthor->textNum; j++)
{
member->anAuthor->text = malloc(sizeof(struct AuthorRecord));
fscanf(input, " %[^\n]", member->anAuthor->text->textTitle);
fscanf(input, "%ld", &member->anAuthor->text->Download);
member->anAuthor->text = member->anAuthor->text->next;
}
member->next = malloc(sizeof(MemberNodeType));
member = member->next;
}
else
member->next = NULL;
}
member = head;
while(true)
{
if (member->next == NULL)
break;
for (i = 0; i < authorNum; i++)
{
printf("%s %s %d\n", member->anAuthor->lastName, member->anAuthor->firstName, member->anAuthor->idNumber);
for (j = 0; j < member->anAuthor->textNum; j++)
{
printf("%s\n", member->anAuthor->text->textTitle);
printf("%ld\n", member->anAuthor->text->Download);
member->anAuthor->text = member->anAuthor->text->next;
}
member = member->next;
}
}
}
我已经通过gdb运行程序,一切都很好。但是,当我到达这一行printf("%s\n", member->anAuthor->text->textTitle);
时,我得到了一个段错误。
显然member->anAuthor->text
字段为空,其地址为0x0。 <{1}}和member
上的数据和内存地址是正确的。
这里有什么问题?
答案 0 :(得分:1)
当您阅读每位作者的文本时,您使用autor节点的text
成员作为迭代器
for (j = 0; j < member->anAuthor->textNum; j++)
{
member->anAuthor->text = malloc(sizeof(struct AuthorRecord));
fscanf(input, " %[^\n]", member->anAuthor->text->textTitle);
fscanf(input, "%ld", &member->anAuthor->text->Download);
member->anAuthor->text = member->anAuthor->text->next;
}
整个街区的逻辑是错误的。 text->next
永远不会有有意义的价值,甚至不是NULL
。并且文本没有链接,它们只是不相关的数据块,一旦循环遍历就无法访问。特别是,您必须先分配,然后将前一个链接的next
指针设置为该内存。
文本列表的text
指针应该与成员列表中的head
类似,并且只能分配一次。 (在用NULL
初始化之后,即。)
也就是说,代码中有各种"smells":
AuthorRecord
明显不同时调用AutorType
?AuthorRecordType
,而不是AuthorPtr
或PAuthor
。在C中,星号标记指针类型;很难表现得那么富有表现力。 (另外,输入更容易。)next
指针)一起使用,以避免可能的意外情况。 malloc
,而不是提前。如果你在读取之前对第一个元素进行malloc,然后将其设置为NULL
,因为事实证明你并不需要它,那么就会造成内存泄漏。malloc
都需要free
。 (我知道你的代码目前还不完整;只是说。)scanf
序列需要进行错误检查。如果输入不正确,很容易进入无限循环。 (旁注:在此处发布一小段示例输入以帮助我们找到错误也很有帮助。)main
。将阅读与创建结构分开也是一个好主意。member->anAuthor->text->next
。考虑使用临时指针。这将使引用更短(text->next
),并希望代码更清晰。答案 1 :(得分:0)
There are several items to note in your code,
such as the definition of struct { fields } name; is depreciated
and should not be used in new code.
Rather use: struct name { fields };
which does require using 'struct' wherever the structure name is referenced.
There are several logic errors in the code that are causing it to fail,
such as not initializing the pointers to malloc'd areas to null.
Note: all the malloc'd areas need to be free'd at each exit point,
without back links, the free processing will be time consuming
Suggest adding a back link to each malloc'd area to simplify that operation
Also, the struct MemberNode is not needed
because a linked list of the struct AuthorType would contain all the relevant data.
#include <stdio.h>
#include <stdlib.h>
#include <string.h>
#include <stdbool.h>
struct AuthorRecord
{
char textTitle[100];
int NumberOfWords;
long Download;
struct AuthorRecord *next;
};
struct AuthorType
{
char firstName[30];
char lastName[30];
int idNumber;
int textNum;
struct AuthorRecord text;
};
struct MemberNode
{
struct AuthorType *anAuthor;
struct MemberNode *next;
};
FILE* input;
struct MemberNode *head = NULL; // head of linked list
struct MemberNode *member = NULL; // ptr to current item in linked list
int main (void)
{
int authorNum, textNum, i, j;
input = fopen("input.txt", "r");
if (NULL == input)
{
perror("fopen(input.txt) %s", strerror(errno) );
return (errno);
}
// read number of authors
fscanf(input, "%d", &authorNum);
// for each author
for (i = 0; i < authorNum; i++)
{
// one of member struct per author
if( NULL == member )
{ // first time
member = (struct MemberNode*)malloc(sizeof(struct MemberNode));
head = member;
member->next = NULL; // initialize
}
else
{ // not first time
// link to new member node
member->next = (struct MemberNode*)malloc(sizeof(struct MemberNode);
if( NULL == member->next )
{
perror( "malloc(MemberNode) %s", strerror( errno ) );
return(errno);
}
//memset( member->next, 0x00, sizeof(struct MemberNode) );
member = member->next; // step to new member node
member->anAuthor = NULL; // initialize ptr to author info list
member->next = NULL; // initialize
}
// set secondary linked list member(author) & point to it
member->anAuthor = (struct AuthorType*)malloc(sizeof(struct AuthorType));
if( NULL == member->anAuthor )
{
perror( "malloc(AuthorType) %s", strerror( errno ) );
return(errno);
}
//memset( member->anAuthor, 0x00, sizeof(struct AuthorType) );
member->anAuthor->next = NULL; // initialize
member->anAuthor->text = NULL; // initialize
// read a line of author info
if(fscanf(input, "%s %s %d",
member->anAuthor->lastName,
member->anAuthor->firstName,
&(member->anAuthor->idNumber) ) != EOF)
{ // then, successful read of author info
// read number of author titles
fscanf(input, "%d", &(member->anAuthor->textNum));
// for each author title
for (j = 0; j < member->anAuthor->textNum; j++)
{
member->anAuthor->text =
(struct AuthorRecord*)malloc(sizeof(struct AuthorRecord));
if( NULL == member->anAuthor->text )
{
perror( "malloc(AuthorRecord) %s", strerror( errno ) );
return(errno);
}
//memset( member->anAuthor->text, 0x00, sizeof(struct AuthorRecord) );
// step to new author/text record
member->anAuthor->text = member->anAuthor->text->next;
member->anAuthor->text->next = NULL; // initialize
// read one title and how many times that title has been downloaded
fscanf(input, " %[^\n]", member->anAuthor->text->textTitle );
fscanf(input, "%ld", &(member->anAuthor->text->Download) );
}
}
}
// recall beginning of linked list
member = head;
//for each entry in linked list
while(NULL != member) // allow for empty list or end of list
{
if( NULL != member->anAuthor )
{
printf("%s %s %d\n",
member->anAuthor->lastName,
member->anAuthor->firstName,
member->anAuthor->idNumber);
// for each author/text
while( NULL != member->anAuthor->text->next )
{
printf("%s\n%ld\n",
member->anAuthor->text->textTitle,
member->anAuthor->text->Download);
// step to next author text/title
member->anAuthor->text = member->anAuthor->text->next;
}
}
// step to next member (I.E next author)
member = member->next;
}
}