我正在创建一个链表,其中包含带有void指针的“dataItem”的节点。这样做的目的是为了使Node能够包含任何类型的数据。但是,即使将数据转换为正确的类型,我也无法访问void指针的数据。
我的代码如下所示:
#include <stdio.h>
#include <stdlib.h>
#include <string.h>
typedef struct Student
{
char stuName[51];
char stuMajor[5];
double GPA;
char stuID[10];
}student;
typedef struct Node
{
union{
void *dataPtr;
int countr;
}dataItem;
int link;
struct Node* next;
}node;
void readData(struct Node *);
void main(){
node head;
node temp;
readData(&temp);
student *ptr = (student *)(temp.dataItem.dataPtr);
printf("%s %d", ptr->stuName, ptr->GPA);//breaks here because unable to access memory
}
void readData(struct Node *link)
{
link = (node *)malloc(sizeof(node));
student *ptr = (student *)malloc(sizeof(struct Student));
printf("enter the student name : ");
fflush(stdin);
scanf("%[^\n]", ptr->stuName);
printf("enter the student's major : ");
fflush(stdin);
scanf("%[^\n]", ptr->stuMajor);
printf("enter the student GPA : ");
scanf("%lf", &(ptr->GPA));
printf("enter the student ID : ");
fflush(stdin);
scanf("%[^\n]", ptr->stuID);
link->dataItem.dataPtr = ptr;
}
我知道我的指针确实错了,我不确定如何。我的readData
函数中的节点也指向Node的新malloc,因为当我进一步实现链表时,每次调用readData
时我想要一个新节点。
答案 0 :(得分:5)
你的代码非常破碎,
您没有包含任何头文件,stdlib.h
至少malloc()
,stdio.h
和{{1}需要printf()
}。
您的scanf()
定义错误,因为main()
必须返回main()
。
您int
是未定义的行为。
您忽略fflush(stdin)
的返回值。
您认为scanf()
始终返回有效指针。
您调用了尚未声明的malloc()
。
但最重要的错误是,您将readData()
的地址传递给了node temp
并且您readData()
编了它,但您没有返回指针它失去了在malloc()
内所做的所有变化,但这些变化无论如何都不会起作用,因为它在你调用它的那一刻都没有声明。
我修改了你的代码,因为我知道你不喜欢我的答案,但查看与答案相关的修复程序,现在它按预期工作
readData()
我还为#include <stdio.h>
#include <stdlib.h>
#include <string.h>
typedef struct Student
{
char stuName[51];
char stuMajor[5];
double GPA;
char stuID[10];
} student;
typedef struct Node
{
union{
void *dataPtr;
int countr;
} dataItem;
int link;
struct Node* next;
} node;
void readData(struct Node **link);
int main()
{
node *head;
student *ptr;
readData(&head);
ptr = head->dataItem.dataPtr;
if (ptr != NULL)
printf("%s\t%g", ptr->stuName, ptr->GPA);
return 0;
}
void readData(struct Node **link)
{
student *ptr;
if (link == NULL)
return;
*link = malloc(sizeof(node));
if (*link == NULL)
return;
memset(*link, 0, sizeof(node));
ptr = malloc(sizeof(struct Student));
if (ptr == NULL)
return;
printf("enter the student name : ");
if (scanf("%50[^\n]%*c", ptr->stuName) != 1)
ptr->stuName[0] = '\0';
printf("enter the student's major : ");
if (scanf("%4[^\n]%*c", ptr->stuMajor) != 1)
ptr->stuMajor[0] = '\0';
printf("enter the student GPA : ");
if (scanf("%lf%*c", &(ptr->GPA)) != 1)
ptr->GPA = 0;
printf("enter the student ID : ");
if (scanf("%9[^\n]%*c", ptr->stuID) != 1)
ptr->stuID[0] = 0;
(*link)->dataItem.dataPtr = ptr;
}
添加了一些安全修复程序,添加了长度修饰符以防止缓冲区溢出,并且还删除了带有scanf()
说明符的尾随'\n'
,如果跟随多个空格,它将无效值,但你可以测试它,只需按 Enter / Return ,如果你想要更加软化的输入,你应该使用别的而不是"%*c"
。
答案 1 :(得分:2)
此:
void readData(struct Node *link)
{
link = (node *)malloc(sizeof(node));
您丢弃传入的link
参数值,而是通过malloc
为其分配新的分配。我认为这是你最重要的问题。一个简单的解决方法是删除执行malloc
的行。
答案 2 :(得分:0)
您希望将指针传递给指向(或指针的地址)指向readData()函数的节点。 readData分配一个新节点并填充它;你的代码中发生的事情是readData()获取temp地址的副本,用新地址覆盖该地址的副本,该地址是从malloc获得的(对于调用代码是不可见的)在main()中然后填充malloc的对象。从readData返回时,malloc的对象无法访问。
你想要做的是:
void main(){
node head;
node *tempAddr; // pointer
readData(&tempAddr); // pass address of that pointer
然后在main中使用*tempAddr
而不是temp
。
void readData(struct Node **linkAddr)
{
node *link = *linkAddr = (node *)malloc(sizeof(node));
[...]
unwind会抱怨你不应该施放malloc的结果,但我认为没关系。我也不关心main或其参数的返回值。