Double Linked List based in C++

CK CK 3788 
Created at
Updated at  
800 0 0

Below is the double linked list example that based on console.

Specially this application use macro by define function provided by ANSI C.
It's just like inline function that C++ provides.

#include <stdio.h>
#include <stdlib.h>
/* Constants */
#define EXIT_OK
/* Macros */
#define CHOICE(answer)
printf("Choice: ");
scanf("%i", &answer);
struct nodo
{
	int 	nclient; 	/* primary key of the "record" */
	char    name[40];       /* name */
	float	total;          /* how much this client owes us */
	struct	nodo * next;    /* pointer to the next struct */
	struct	nodo * prev;	/* pointer to the previous struct */
};
/* Functions */
void AddClient 		(struct nodo ** list);
void Exit       	(struct nodo ** list);
void SeeAll		(struct nodo ** list);
void OneByOne		(struct nodo ** list);
void Search		(struct nodo ** list);
void Delete		(struct nodo ** list);
void FreeAll		(struct nodo ** list);
void Flush2File		(struct nodo ** list);
void ReadFile		(struct nodo ** list);
void Money		(struct nodo ** list);
void CalcTotal		(struct nodo ** list);
void HighestTotal       (struct nodo ** list);
void LowestTotal	(struct nodo ** list);
void Average		(struct nodo ** list);
void AddBegin		(struct nodo ** list, struct nodo * add);
void AddEnd		(struct nodo ** list, struct nodo * add);
void AddBetween		(struct nodo ** list, struct nodo * add);
int NumberExists	(struct nodo ** list, int number);
void ShowData		(struct nodo * data);
int  StrCompare		(char * s1, char * s2);
void ErrorOpeningFile 	(void);
int main (void)
{
	struct nodo * list = NULL; 	/* list will be a pointer to the first
					node of the linked list */
	int	choice;
	do
	{
		clrscr();
		textcolor (4);
		cputs ("\nDouble Linked Lists - Nicolas Raitman");
		textcolor (7);
		puts("\n\n0 - Exit");
		puts("1 - New Item");
		puts("2 - See All Items in the Linked List");
		puts("3 - Show Items One by One");
		puts("4 - Search Item");
		puts("5 - Delete Item");
		puts("6 - Delete Entire List");
		puts("7 - Money");
		puts("8 - Flush Linked List to File");
		puts("9 - Read File and Create Linked List");
		CHOICE (choice);
		switch (choice)
		{
			case 0:	Exit(&list); break;
			case 1: AddClient(&list); break;
			case 2: SeeAll(&list); break;
			case 3: OneByOne(&list); break;
			case 4: Search(&list); break;
			case 5: Delete(&list); break;
			case 6: FreeAll(&list); break;
			case 7: Money (&list); break;
			case 8: Flush2File(&list); break;
			case 9: ReadFile(&list); break;
			default: break;
		}
	} while (choice != 0);
	return EXIT_OK;
}
void ReadFile (struct nodo ** list)
{
	/* creates a new linked list from data in 'dlist.bin'
	deleting all repeated entries, filtering by nodo->nclient */
	struct nodo * aux = NULL;
	FILE	* fp;
	int	sizenodo = sizeof(struct nodo);
	/* first we make sure to free all the memory used by the list
	since we are going to create a new one */
	FreeAll (list);
	*list = NULL;
	if ((fp = fopen("dlist.bin", "rb")) == NULL)
	{
		ErrorOpeningFile();
		return;
	}
	/* we read the first record on the file and we add it to the
	beginning of the list */
	aux = (struct nodo *) malloc (sizenodo);
	fread(aux, sizenodo, 1, fp);
	AddBegin (list, aux);
	/* we do the loop while we are not in the end of file */
	while (!feof(fp))
	{
		aux = (struct nodo *) malloc (sizeof(struct nodo));
		if(fread(aux, sizenodo, 1, fp))
		{
			/* if nclient does not exist in our list then
			we add the node to the list */
			if (!NumberExists(list, aux->nclient))
				AddBetween(list, aux);
			else
				/* since I did not add the item to the list
				I free the memory used by it */
				free (aux);
		}
	}
	free (aux);
	printf("Data was read from 'dlist.bin' and Double Linked List was created.
Press any key to continue...");
	getch();
}
void ErrorOpeningFile (void)
{
	/* it shows a message stating that the file could not be opened*/
	printf("
Error while opening file.");
	getch();
}
int NumberExists (struct nodo ** list, int number)
{
	/* searches for number in all act->nclient, and if it finds
	any match it return 1, else it returns 0 */
	struct nodo * act = NULL;
	act = *list;
	while (act)
	{
		if (act->nclient == number)
			return 1;
		act = act->next;
	}
	/* if we reach this point then no match was found */
	return 0;
}
void Flush2File (struct nodo ** list)
{
	/* flushes all the items in the linked list into a file */
	struct nodo * act = NULL;
	FILE	* fp;
	int	choice;
	if (! *list)
		return;
	act = *list;
	printf("

1 - New File");
	printf("
2 - Append Data");
	CHOICE (choice);
	if (choice == 1)
	{
		/* we delete all the contents of the file and open it to write */
		if ((fp = fopen("dlist.bin", "wb")) == NULL)
		{
			ErrorOpeningFile();
			return;
		}
	}
	else
	{
		/* we open the file to append data */
		if ((fp = fopen("dlist.bin", "ab")) == NULL)
		{
			ErrorOpeningFile();
			return;
		}
	}
	/* while we have a node pointing to a differnt address than NULL... */
	while (act)
	{
		/* now we write into the file each node of the linked list */
		fwrite (act, sizeof (struct nodo), 1, fp);
		act = act->next;
	}
	fclose(fp);
	printf("

Data was flushed into 'dlist.bin'. Press any key to continue...");
	getch();
}
void Money (struct nodo ** list)
{
	/* this function shows a loop and it calls different functions to
	perform several calculation with the field "total" in the struct
	Not a big deal, just to show basic arithmetic calculations. Most
	of the functions that are called are described by its name */
	int choice;
	if (! *list)
	{
		printf("
Empty List. No calculations can be performed.");
		getch();
		return;
	}
	do
	{
		puts("
0 - Exit");
		puts("1 - Calculate Total");
		puts("2 - Highest Total");
		puts("3 - Lowest Total");
		puts("4 - Average Total");
		CHOICE(choice);
		switch (choice)
		{
			case 0: break;
			case 1: CalcTotal(list); break;
			case 2: HighestTotal(list); break;
			case 3: LowestTotal(list); break;
			case 4: Average(list); break;
			default: break;
		}
	} while (choice != 0);
}
void Average (struct nodo ** list)
{
	/* calculates the average of all the act->total for each node in the
	linked list */
	struct nodo * act = NULL;
	int	count = 0;
	float	total = 0, average;
	act = *list;
	while (act)
	{
		total += act->total;
		count++;
		act = act->next;
	}
	average = total / count;
	printf ("
Average = %.2f
", average);
}
void LowestTotal (struct nodo ** list)
{
	struct nodo * act = NULL, * lowest = NULL;
	act = *list;
	lowest = *list;
	while (act)
	{
		if (act->total < lowest->total)
			lowest = act;
		act = act->next;
	}
	ShowData(lowest);
}
void HighestTotal (struct nodo ** list)
{
	struct nodo * act = NULL, * highest = NULL;
	act = *list;
	highest = *list;
	while (act)
	{
		if (act->total > highest->total)
			highest = act;
		act = act->next;
	}
	ShowData(highest);
}
void CalcTotal (struct nodo ** list)
{
	struct nodo * act = NULL;
	float	total = 0;
	act = *list;
	while (act)
	{
		total += act->total;
		act = act->next;
	}
	printf("
Total = %.2f
", total);
}
void Delete (struct nodo ** list)
{
	/* this functions deletes a specific node in the list */
	struct nodo * act = NULL, * prev = NULL;
	int number;
	if (! *list)
		return;
	act = *list;
	prev = *list;
	printf("
Number to Delete: "); scanf("%i", &number);
	while (act)
	{
		/* we search until we find a the same number */
		if (act->nclient == number)
		{
			if (prev == act)
			{
				/* if trying to delete the first node
				then the beginning of the list will be the
				address of the next struct... */
				*list = act->next;
				/* so we assign a NULL address to the prev
				field of the next struct */
				act->next->prev = NULL;
			}
			else
			{
				/* this is easy to understand... just
				reordering the pointers to the next and
				previous structures since we deleted one */
				prev->next = act->next;
				act->next->prev = prev;
			}
			free (act);
			printf("
Item Deleted. Press Any Key.");
			getch();
		}
		prev = act;
		act = act->next;
	}
}
int StrCompare (char * s1, char * s2)
{
	/* if the string are equal return 1, otherwise return 0
	just trying to implement something similar to strcmp */
	int cont, lens1, lens2, different;
	lens1 = strlen(s1);
	lens2 = strlen(s2);
	for (cont = 0, different = 1; (cont < lens1) && (cont < lens2); cont++)
		if ( (*(s1 + cont)) != (*(s2 + cont)) )
			/* if I found one different character they are not equal */
			different = 0;
	return different;
}
void Search (struct nodo ** list)
{
	/* this function searches for either a number of a client or for
	its name. We present a menu until the user exits the loop */
	struct nodo * act = NULL;
	int	choice, number, foundit = 0;
	char	name[40];
	if (! *list)
		return;
	do
	{
		act = *list;
		puts("

0 - Exit");
		puts("1 - Search By Name");
		puts("2 - Search By Number");
		CHOICE(choice);
		switch (choice)
		{
			case 1:
				printf("Name: "); scanf("%s", name);
				while (act)
				{
					if (StrCompare(name, act->name))
					{
						foundit = 1;
						break;
					}
					act = act->next;
				}
				if (foundit)
				{
					printf("
	Found it!");
					ShowData(act);
				}
				break;
			case 2:
				printf("
Search Number: "); scanf("%i", &number);
				while (act)
				{
					if (act->nclient == number)
					{
						foundit = 1;
						break;
					}
					act = act->next;
				}
				if (foundit)
				{
					printf("
	Found it!");
					ShowData(act);
				}
				else
					printf("

	No Data was found");
				break;
			default:
				break;
		}
	} while (choice != 0);
}
void OneByOne (struct nodo ** list)
{
	/* this is my favourite function! When this function is called for the
	first time, the first node of the list is shown. Then the user has the
	possibility to look at the next, the previous, the last and the first
	*/
	struct nodo * act = NULL;
	int choice;
	if (! *list)
	{
		printf("
Empty List.");
		return;
	}
	act = *list;
	ShowData(act);
	do
	{
		printf("

0 - Exit");
		printf("
1 - Next");
		printf("
2 - Previous");
		printf("
3 - First");
		printf("
4 - Last");
		CHOICE(choice);
		switch (choice)
		{
			case 0: break;
			case 1:
				if (!act->next)
					/* if we have a NULL address in
					act->next then we are looking at the
					last one */
					printf ("		No more entries.");
				else
				{
					/* we point to the address of the next
					structure and show it */
					act = act->next;
					ShowData(act);
				}
				break;
			case 2:
				if (!act->prev)
					/* if act->prev == NULL then we are
					showing the first one */
					printf("		No previous entries.");
				else
				{
					/* we point to address of the previous
					structure */
					act = act->prev;
					ShowData(act);
				}
				break;
			case 3:
				/* to show the first item */
				while (act->prev)
					act = act->prev;
				ShowData(act);
				break;
			case 4:
				/* to show the last item */
				while (act->next)
					act = act->next;
				ShowData(act);
				break;
			default:
				printf("Invalid Choice");
				break;
		}
	} while (choice != 0);
}
void ShowData (struct nodo * data)
{
	printf("

	Number:		%i", data->nclient);
	printf("
	Name:		%s", data->name);
	printf("
	Total:		%.2f", data->total);
}
void SeeAll (struct nodo ** list)
{
	struct nodo * act = NULL;
	int	itemshown = 0;
	if (! *list)
	{
		printf("
No Data to Show. Empty List.");
		getch();
		return;
	}
	act = *list;
	while (act)
	{
		if (itemshown == 5)
		{
			/* since no more than 5 items can be shown on screen
			we hold until the user presses a key */
			itemshown = 0;
			printf("
Press any key to continue...");
			getch();
		}
		itemshown++;
		ShowData(act);
		act = act->next;
	}
	printf("

Press any key to continue..."); getch();
}
void AddClient (struct nodo ** list)
{
	/* this functions adds a new node to the linked list. The node can
	be added at the beginning, at the end or ordered by number */
	struct nodo * aux = NULL;
	char	temp[40];
	int	number, choice;
	aux = (struct nodo *) malloc (sizeof (struct nodo));
	if (aux)
	{
		/* we ask for the information about the new client */
		printf("
Number: "); scanf("%i", &(aux->nclient));
		printf("Name: "); scanf("%s", aux->name);
		printf("Total: "); scanf("%f", &(aux->total));
		if (! *list)
		{
			/* we are creating the list. There are neither previous
			nor nexts. So, we have to specify it by assigning NULL
			to those addresses */
			*list = aux;
			aux->next = NULL;
			aux->prev = NULL;
		}
		else
		{
			puts("
0 - Cancel");
			puts("1 - Add at the beginning.");
			puts("2 - Add at the end.");
			puts("3 - Add ordered");
			CHOICE(choice);
			switch (choice)
			{
				case 0: free(aux); break;
				case 1: AddBegin(list, aux); break;
				case 2: AddEnd(list, aux); break;
				case 3: AddBetween(list, aux); break;
				default: break;
			}
		}
	}
	else
	{
		puts ("Memory unavailable.");
		getch();
	}
}
void AddEnd (struct nodo ** list, struct nodo * add)
{
	/* we will be adding "add" to the end of "list" */
	struct nodo * prev = NULL, * act = NULL;
	act = *list;
	/* we serch for the last node in the list */
	while (act)
	{
		prev = act;
		act = act->next;
	}
	/* easy to understand... */
	prev->next = add; /* the previous node addressing to the next will be addressing to add */
	add->next = NULL; /* the one we are adding addressing to next will be addressing NULL, since it's the last one */
	add->prev = prev; /* finally, the one we are adding addressing the previous one will address prev */
}
void AddBegin (struct nodo ** list, struct  nodo * add)
{
	/* Add a new node to the beginning of the list */
	struct nodo * act = NULL;
	act = *list;
	act->prev = add;
	add->prev = NULL; /* since it's the first one then there are not any previous one */
	add->next = act;
	*list = add;
}
void AddBetween (struct nodo ** list, struct nodo * add)
{
	struct nodo * act = NULL, * prev = NULL;
	/* this function will add the item in the linked list
	according to nodo->nclient. This function will never create the
	list, since all the functions that call this one, check if they
	have to create the list. The function can add items at the beginning,
	middle or end of the list. */
	act = *list;
	prev = *list;
	while (act && (act->nclient <= add->nclient))
	{
		prev = act;
		act = act->next;
	}
	if (! act)
		AddEnd (list, add);
	else if (prev == act)
		AddBegin (list, add);
	else
	{
		/* once again we rearrange pointers. Easy to get the idea
		if you look at the names */
		prev->next = add;
		add->next = act;
		add->prev = prev;
		act->prev = add;
	}
}
void Exit (struct nodo ** list)
{
	FreeAll (list);
}
void FreeAll (struct nodo ** list)
{
	/* we free the memory allocated for each struct */
	struct nodo * act = NULL, * next = NULL;
	if (! *list)
		return;
	act = *list;
	while (act)
	{
		next = act->next;
		free (act);
		act = next;
	}
	*list = NULL;
}
Tags Ansi C Binary Search C++ Double Linked List Linked List Facebook X
Comments 0
Similar posts
  1. Binary Search Sample Code
    409
  2. How to run shell command by MFC ?
    441
  3. Move window
    551
  4. MFC based World Wide Web HTTP Server Source Code
    463
  5. Creating and Using a CAsyncSocket Object to use CAsyncSocket
    473
  6. Fast and Good Keyboard/Mouse Test without the message handler
    985
  7. Simple CGI Programming in C
    551
  8. C++ CGI Example working on Apache
    491
  9. How to search file on certain directory ?
    634
  10. How to call SetTimer function on MFC CDialog class ?
    652
  11. Makefile to automate the build process for C++
    285
  12. How to load HTML resource on MFC ?
    848
  13. URL Encode, Decode function for MFC
    609
  14. KMP String Matching Algorithm
    676
  1. To load image from file
    457
  2. How to get GM Time as String ?
    424
  3. Finding process name on OS
    414
  4. Convert System.DateTime to UNIX timestamp
    386
  5. Retrieve system information
    498
  6. How to rename(change file name) in C# ?
    1,086
  7. Find Files in certain directory
    936
  8. Implementing C#'s foreach loop in Delphi 8
    463
  9. How to detect resource leaks in a Form
    950
  10. The best way to enable and disable buttons, menu items and toolbar buttons
    668
  11. How to exit from a console application
    816
  12. How to restrict a program to a single instance
    733
  13. Compress and decompress strings in C#
    977
  14. Graphics in C# - Irregular Forms
    914
  15. Extracting the Country from IP Address
    471
  16. String Replace Function For C#
    1,561
  17. How to print character in C# by ASCII code
    480
  18. UDP Send and Receive Using CAsyncSocket
    1,207
  19. Using the shell to receive notification of removable media being inserted or removed
    681
  20. Adding Custom Paper Sizes To Named Printers
    652
  21. Print HTML In C# With Or Without The Web Browser Control And The Print Dialog
    972
  22. A Customizable Printing Text Class
    440
  23. Simplified .NET Printing In C#
    696
  24. How To Print Text In C#
    457
  25. C# Lists
    1,166
  26. Simple Example of IF/THEN using C#
    1,272
  27. Simple C# CGI working on Apache
    488
  28. How to send binary data through C# CGI app?
    999
  29. Interacting With TinyPic From C#
    1,316
  30. Creating A Watched Folder With Assigned Events
    1,672
Recently updated
  1. Google OAuth Token Expiration: Causes and Solutions
    31
  2. Why 100% SEO Guarantees Better User Engagement and How to Achieve It in Your Service
    57
  3. Why SPF and DKIM Are Essential for Linux Email Servers?
    51
  4. How do I create animated background for Google Meet?
    23,244
  5. MaxMind GeoLite2 vs. DB-IP Lite vs. ip-api.com: Choosing the Right Free IP Geolocation Solution
    273
  6. Meet Valkey: Why Redis Changed Its License, Why Valkey is Better, and How to Use It as a Drop-in Replacement
    104
  7. How Rogue Web Scrapers Are Stealing My Content and Destroying My Server
    170
  8. Array of arguments passed to script in PHP
    99
  9. Invalid Auction Storms in Ad Tech
    107
  10. Building MRC-Compliant Instrumentation in Ad Tech: Implementation Steps and Key Challenges
    208
  11. The Two Clocks of Ad Server Architecture
    78
  12. Frequency Cap Architecture Overview
    527
  13. Collecting Proof-of-Play from 100,000 Screens
    153
  14. Vector Search in Relational Databases (RDBs): Trends & Usage Environments
    303
  15. What is RedisVL?
    116
  16. Designing a Skill Registry Architecture: Minimize Token Usage and Maximize AI Performance
    247
  17. TPU & GPU Cluster Management Tools
    258
  18. The Concept of Scaffolding in AI Agents
    245
  19. Beyond Static Pipelines: Architecting LLM Multi-Agent Systems for Autonomous Workflow Orchestration
    598
  20. AI-DLC vs. AI-SDLC: Model-Centric vs. System-Centric AI Development
    269
  21. Fine-Tuning Open-Weight LLMs: Training, Licensing, and Deploying Custom Models with Ollama
    355
  22. Inside the Next-Generation Streaming Architecture: Ultra-Low Latency, SGAI, and AI Codecs
    207
  23. Machine Learning: Training vs. Ranking
    230
  24. The Continuous Learning Machine: Designing a Loop That Actually Turns
    229
  25. The Next-Gen Low-Latency Standards: LL-HLS & MoQ
    204
  26. Designing a Data Curation System Around a Vector Database
    230
  27. Extracting Context from Live Video: The Architecture Got Simpler When We Stopped Building Features
    263
  28. The New Ad Stack Behind Live Sports Streaming: Inside SGAI, EABN, and the Standards Race to Fix Live Monetization
    674
  29. Designing MLOps Architectures to Handle Seasonal Data Drift in EV Fleet Models
    201
  30. From 15 to 40+ FPS: Accelerating PyTorch Object Detection on Automotive ECUs
    233