My book gives an example of a linked list algorithm. To test my understanding I memorized the logic of "insert" and rewrote it. It looked the same except for one thing. The book example has a double pointer parameter, whereas mine used only a single pointer. My insert didn't work until I modified it to also use two points of indirection. I think I figured out why but I want you guys to confirm or deny.
When I use a single point of indirection and pass the value in a pointer variable it is being passed call by value. When I use a double pointer I get to use the address operator (&) to pass the pointer which tells the compiler it is to be passed call by reference.
If this is the case, it sure wasn't mentioned in the book! Does a primitive type only get passed call by reference when it has the address operator input in the function argument?
Code:
#include <stdio.h>
#include <stdlib.h>
struct listNode {
char data;
struct listNode *nextPtr;
};
typedef struct listNode ListNode;
typedef ListNode *ListNodePtr;
/* Does this mean any structure declared using ListNodePtr
will automatically be a pointer without using the * cast? */
//void insert( ListNodePtr *, char );
void insert( ListNode **sPtr, char value );
char delete( ListNodePtr *, char );
int isEmpty( ListNodePtr );
void printList( ListNodePtr );
void instructions( void );
int main()
{
ListNode *startPtr = NULL;
int choice;
char item;
instructions();
printf( "? " );
scanf( "%d", &choice );
while( choice != 3 ) {
switch( choice ) {
case 1:
printf( "Enter a character: " );
scanf( "\n%c", &item );
/* startPtr is a pointer. What does it mean to use the address operator on a pointer? */
insert( &startPtr, item );
printList( startPtr );
break;
case 2:
if ( !isEmpty( startPtr ) ) {
printf( "Enter character to be deleted: " );
scanf( "\n%c", &item );
if ( delete( &startPtr, item ) ) {
printf( "%c deleted.\n", item );
printList( startPtr );
}
else
printf( "%c not found.\n\n", item );
}
else
printf( "List is empty.\n\n" );
break;
default:
printf( "Invalid choice.\n\n" );
instructions();
break;
}
printf( "? " );
scanf( "%d", &choice );
}
printf( "%c\n", startPtr->data );
printf( "End of run.\n" );
return 0;
}
void insert( ListNode **sPtr, char value )
{
ListNode *newPtr, *previousPtr, *currentPtr;
newPtr = malloc( sizeof( ListNode ) );
if ( newPtr != NULL ) {
newPtr->data = value;
newPtr->nextPtr = NULL;
currentPtr = *sPtr;
previousPtr = NULL;
while ( currentPtr != NULL && value > currentPtr->data ) {
previousPtr = currentPtr;
currentPtr = currentPtr->nextPtr;
}
if ( previousPtr == NULL ) {
newPtr->nextPtr = *sPtr;
*sPtr = newPtr;
}
else {
previousPtr->nextPtr = newPtr;
newPtr->nextPtr = currentPtr;
}
}
}
void instructions( void )
{
printf( "Enter your choice:\n"
" 1 to insert an element into the lsit.\n"
" 2 to delete an element from the list.\n"
" 3 to end.\n" );
}
/*
void insert( ListNode *sPtr, char value )
{
ListNodePtr newPtr, previousPtr, currentPtr;
newPtr = malloc( sizeof( ListNode ) );
if ( newPtr != NULL ) {
// data is not a pointer, why is the -> used to access it then?
newPtr->data = value;
newPtr->nextPtr = NULL;
previousPtr = NULL;
currentPtr = sPtr;
// Is currentPtr pointing to the value at sPtr or the address of sPtr?
while ( currentPtr != NULL && value > currentPtr->data ) {
previousPtr = currentPtr;
currentPtr = currentPtr->nextPtr;
}
if ( previousPtr == NULL ) {
newPtr->nextPtr = sPtr;
sPtr = newPtr;
}
else {
previousPtr->nextPtr = newPtr;
newPtr->nextPtr = currentPtr;
}
}
else
printf( "%c not inserted. No memory available.\n", value );
}
*/
char delete( ListNodePtr *sPtr, char value )
{
ListNodePtr previousPtr, currentPtr, tempPtr;
/* Does this mean the value of a struct name is the memory address? */
/* Could I use a non-pointer struct and change the mem address it points to? */
if ( value == ( *sPtr )->data ) {
tempPtr = *sPtr;
*sPtr = ( *sPtr )->nextPtr;
free( tempPtr );
return value;
}
else {
previousPtr = *sPtr;
currentPtr = ( *sPtr )->nextPtr;
while ( currentPtr != NULL && currentPtr->data != value ) {
previousPtr = currentPtr;
currentPtr = currentPtr->nextPtr;
}
if ( currentPtr != NULL ) {
tempPtr = currentPtr;
previousPtr->nextPtr = currentPtr->nextPtr;
free( tempPtr );
return value;
}
}
return '\0';
}
int isEmpty( ListNodePtr sPtr )
{
return sPtr == NULL;
}
void printList( ListNodePtr currentPtr )
{
if ( currentPtr == NULL )
printf( "List is empty.\n\n" );
else {
printf( "The list is:\n" );
while ( currentPtr != NULL ) {
printf( "%c --> ", currentPtr->data );
currentPtr = currentPtr->nextPtr;
}
printf( "NULL\n\n" );
}
}