I'm currently working on a question from a book that I've been reading titled "How to program in C". The question reinforces the use of linked list data structures. From what the book explained, linked list data structures have 3 main functions "delete", "insert", and "print". However, this question specifically states that we should keep all manipulations inside of the "main" function (so I don't have the ability to copy the code directly from the book).
This is the question from the book:
Assume that the list pointed to by
startPtrcurrently consists of 2 nodes—one containing "Jones" and one containing "Smith". The nodes are in alphabetical order. Provide the statements necessary to insert in order nodes containing the following data for lastName and grade:
"Adams" 85.0
"Thompson" 73.5
"Pritchard" 66.5
Use pointers
previousPtr,currentPtrandnewPtrto perform the insertions. State whatpreviousPtrandcurrentPtrpoint to before each insertion. Assume thatnewPtralways points to the new node, and that the new node has already been assigned the data.
This is the code I currently have:
//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("%s\n%d",currentPtr->lastName,currentPtr->grade);
previousPtr = currentPtr;
currentPtr = currentPtr->nextPtr;
}
else
{
puts("Critical Error encountered closing program!");
break;
}
}
}
There are two things I'm trying to understand:
- There is a synonym for the structure keyword "GradeNode" and "*GradeNode". This part of the code was given by the book. Why was the indirection operator used with "*GradeNode"? How does this effect variables that are declared with this structure type?
- Upon compiling the code I receive an error for the following statement:
GradeNodePtr currentPtr = *startPtr;. The compiler is stating that the two variables are incompatible. My assumption was that you declare currentPtr equal to *startPtr with the use of the indirection operator because the currentPtr needed to point to the data inside of the startPtr and not the memory address.
Also, if there's anything that you think should be added to the code after reading the question please let me know.
Thanks!
No, there isn't. As a minor matter, "GradeNode" is no kind of keyword, but rather one of the type names being declared. But the main point is that
*GradeNodePtris two separate things,*andGradeNodePtr.In that context, it is not the indirection operator. It is part of the name of type
GradeNode *, which, in light of the precedingtypedef, is an alias for typestruct gradeNode *.It's not a structure type, it's a pointer (to structure) type. And of course it has the effect that variables declared with that type take pointer values, not structure values.
Indeed so. This is in part a manifestation of the issue I remarked upon in comments, that typedefs that conceal pointer nature are confusing and should be avoided.
Consider it strictly from a type analysis point of view. The type of
startPtrisGradeNodePtr, also known asstruct gradeNode *. The type ofcurrentPtris alsoGradeNodePtr. The types are correct for assignment of one to the other without any dereferencing. The result of dereferencing a pointer has a different type than the pointer itself does (one less level of indirection), so your attempt cannot be type-correct.But also consider it semantically. What you seem to mean by "the data inside of the startPtr" is the data to which
startPtr's (pointer) value points.startPtr's value is the address of that data. You do wantcurrentPtrto point to that same data. The data itself is*startPtr, so its address is&*startPtr. Thus, you could write, but it is equivalent and more idiomatic to write
And lo! As we already discussed,
startPtrhas the correct type for assignment tocurrentPtrwithout dereferencing, so everything is consistent.