我目前正在研究我一直在读的一本书中的一个问题,标题为"如何在C中编程"。这个问题强化了链表数据结构的使用。根据本书的解释,链表数据结构有3个主要功能"删除","插入"和"打印"。但是,这个问题特别指出我们应该将所有操作保留在"main"函数中(所以我无法直接从书中复制代码)。
这是书中的问题:
假设
startPtr
指向的列表当前由 2 个节点组成 — 一个包含"Jones",另一个包含"Smith"。节点按字母顺序排列。提供在顺序中插入包含以下数据的节点所需的语句 姓氏和等级:
"Adams" 85.0
"Thompson" 73.5
"Pritchard" 66.5
使用指针
previousPtr
、currentPtr
和newPtr
来执行插入操作。陈述什么previousPtr
和currentPtr
指向每次插入之前。假设newPtr
总是 指向新节点,并且已为新节点分配了数据。
这是我目前拥有的代码:
//fig 12_4.c
#include <stdlib.h>
#include <stdio.h>
#include <string.h>
struct gradeNode{
char lastName[20];
double grade;
struct gradeNode *nextPtr;
};
typedef struct gradeNode GradeNode;
typedef GradeNode *GradeNodePtr;
void insert(GradeNodePtr);
int main(void)
{
//part a
GradeNodePtr startPtr = NULL;
//part b
GradeNodePtr newPtr = malloc(sizeof(GradeNode));
startPtr = newPtr;
// checking to see if memory was allocated properly
if(newPtr != NULL)
{
newPtr->grade = 91.5;
strcpy(newPtr->lastName,"Jones");
newPtr->nextPtr = NULL;
}
//part c
//Creating the previousPtr, currentPtr, and NewPtr to make insertions
GradeNodePtr previousPtr = NULL; // intializing both the previousPtr and currentPtr to begin insertion process
GradeNodePtr currentPtr = *startPtr;
for(int i; i>4; i++)
{
if(currentPtr != NULL)
{
puts("Please enter a last name and grade");
scanf("%sn%d",currentPtr->lastName,currentPtr->grade);
previousPtr = currentPtr;
currentPtr = currentPtr->nextPtr;
}
else
{
puts("Critical Error encountered closing program!");
break;
}
}
}
我试图理解两件事:
- 结构关键字"GradeNode"和"*GradeNode"有一个同义词。这部分代码是由书中给出的。为什么间接寻址运算符与"*GradeNode"一起使用?这对使用此结构类型声明的变量有何影响?
- 编译代码时,我收到以下语句的错误:
GradeNodePtr currentPtr = *startPtr;
.编译器声明这两个变量不兼容。我的假设是,您使用间接寻址运算符声明 currentPtr 等于 *startPtr,因为 currentPtr 需要指向 startPtr 内部的数据而不是内存地址。
另外,如果您在阅读问题后认为应该将任何内容添加到代码中,请告诉我。
谢谢!
- 结构关键字"GradeNode"和"*GradeNode"有一个同义词。
不,没有。作为一件小事,"GradeNode"不是一种关键字,而是被声明的类型名称之一。 但重点是*GradeNodePtr
是两个独立的东西,*
和GradeNodePtr
。
这部分代码是由书中给出的。为什么 与"*GradeNode"一起使用的间接运算符?
在这种情况下,它不是间接寻址运算符。 它是类型GradeNode *
名称的一部分,根据前面的typedef
,它是类型struct gradeNode *
的别名。
这是如何影响的 使用此结构类型声明的变量?
它不是结构类型,而是指针(指向结构)类型。 当然,它的效果是使用该类型声明的变量采用指针值,而不是结构值。
- 编译代码时,我收到以下语句的错误:
GradeNodePtr currentPtr = *startPtr;
.编译器是 声明这两个变量不兼容。
确实如此。 这部分体现了我在评论中提到的问题,即隐藏指针性质的 typedef 令人困惑,应该避免。
我的假设是 您声明当前 Ptr 等于 *startPtr 使用 间接寻址运算符,因为当前 Ptr 需要指向 startPtr 中的数据,而不是内存地址。
严格从类型分析的角度考虑它。startPtr
的类型是GradeNodePtr
,也称为struct gradeNode *
。currentPtr
的类型也很GradeNodePtr
。 这些类型对于将一个类型分配给另一个类型是正确的,无需任何取消引用。 取消引用指针的结果具有与指针本身不同的类型(间接寻址级别少一个),因此您的尝试不能类型正确。
但也要从语义上考虑。 你所说的"这似乎是什么意思 startPtr内的数据"是startPtr
(指针)值指向的数据。startPtr
的值是该数据的地址。 您确实希望currentPtr
指向相同的数据。 数据本身是*startPtr
的,所以它的地址是&*startPtr
。 因此,你可以写
GradeNodePtr currentPtr = &*startPtr;
,但写起来是等效的,更惯用
GradeNodePtr currentPtr = startPtr;
瞧!正如我们已经讨论过的,startPtr
具有正确的类型,可以在不取消引用的情况下分配给currentPtr
,因此一切都是一致的。