You should understand the maintenance of linked lists as explained in the previous worksheet. The program will thus make more sense. The following program example is a simple line editor though the code is quite long, which allows you to add and delete lines. As in other worksheets and tutorials at Tenouk.com, the program does not do any error checking. Error checking such as usingexception handling, is left out at this stage so that the main logic is easier to understand. The following example quite long, so, take your time to study it thoroughly.
#include<stdio.h>
// for string related functions...
#include<string.h>
// for memory manipulation related functions...
#include<stdlib.h>
#include<malloc.h>
struct Line
{
char Str[64];
struct Line *Next;
};
int GetChoice(struct Line *p);
struct Line * AddLine(struct Line *p);
struct Line * DelLine(struct Line *p);
void main(void)
{
// address of the first node of the list
struct Line *Head;
int x;
// initially the list is empty
Head = NULL;
x = GetChoice(Head);
for( ; x != 3; )
{
if(x == 1)
// add a line and adjust head if needed
Head = AddLine(Head);
else
// delete one and adjust head if needed
Head = DelLine(Head);
x = GetChoice(Head);
}
}
// initially address of first node...
struct Line *DelLine(struct Line *p)
{
// address of the first node
struct Line *pStart, // address of the first node
*pLast; // this follows p as p moves forward
int i, Number;
printf("\tWhich line number lol? ");
// get a line number to delete
scanf_s("%d", &Number, 1);
// if deleting first node, adjust pStart
if(Number == 1)
pStart = p ->Next;
// otherwise, find p, the node to remove
else
{
for(pStart = p, i = 1; i < Number; ++i, p = p -> Next)
pLast = p;
pLast -> Next = p -> Next;
}
// return p to system/memory
free(p);
// return starting address to main()
return (pStart);
}
int GetChoice(struct Line *p)
{
int i, Choice;
printf("\nThis is the start of your file so far...\n");
// print out the list
for(i = 1; p != NULL; ++i, p = p->Next)
printf("%d: %s\n", i, p->Str);
printf("...and this is the end ");
printf("(Enter 1 to Insert, 2 to Delete and 3 to Quit)\n\t");
scanf_s("%d", &Choice, 1);
// get a choice and return it to main()
return Choice;
}
struct Line *AddLine(struct Line *p)
{
int Number, i;
struct Line *pLast, *pNew, *pStart;
char StrNew[64];
pStart = p;
// get enough memory for storage
pNew = (struct Line *) malloc(sizeof(struct Line));
printf("What number will this line be? :");
scanf_s("%d", &Number, 1);
// be careful with the line of text that you enter, do not proceed
// the allocated memory storage....
printf("\tEnter your line of text lol!: ");
// flush out the <return> from last scanf_s()
getchar();
// get line to add
gets_s(StrNew, 64);
for(i = 1; i < Number; ++i, p = p -> Next)
// find p and pLast, the point of insertion
pLast = p;
pNew -> Next = p;
strcpy_s(pNew->Str, 64, StrNew);
// if the new node is the first one...
if(i == 1)
// return that as the starting address...
return (pNew);
// otherwise, complete the link and...
else
{
// Return the starting address
pLast->Next = pNew;
return (pStart);
}
}
Sample output:
This is the start of your file so far...
...This is the end (Enter 1 to Insert, 2 to Delete and 3 to Quit)
1
What number will this line be? :1
Enter your line of text lol!: This is the first line - Line 2
This is the start of your file so far...
1: This is the first line - Line 2
...This is the end (Enter 1 to Insert, 2 to Delete and 3 to Quit)
1
What number will this line be? :1
Enter your line of text lol!: This is the second line of text - Line 1
This is the start of your file so far...
1: This is the second line of text - Line 1
2: This is the first line - Line 2
...This is the end (Enter 1 to Insert, 2 to Delete and 3 to Quit)
1
What number will this line be? :3
Enter your line of text lol!: Hohoho...third line of text - Line 3
This is the start of your file so far...
1: This is the second line of text - Line 1
2: This is the first line - Line 2
3: Hohoho...third line of text - Line 3
...This is the end (Enter 1 to Insert, 2 to Delete and 3 to Quit)
2
Which line number lol?1
This is the start of your file so far...
1: This is the first line - Line 2
2: Hohoho...third line of text - Line 3
...This is the end (Enter 1 to Insert, 2 to Delete and 3 to Quit)
1
What number will this line be? :3
Enter your line of text lol!: The fourth entered line of text Line 4
This is the start of your file so far...
1: This is the first line - Line 2
2: Hohoho...third line of text - Line 3
3: The fourth entered line of text Line 4
...This is the end (Enter 1 to Insert, 2 to Delete and 3 to Quit)
3
Press any key to continue . . .
The Story
Let us start at the screen or the output of the program to see how the program works. The program first shows your file. Initially, there is nothing in the file. From the options provided, we pick option 1, indicating we want to add a line. We also state that we want to add line number 1. The program doesn’t allow the user to type in a wrong line number by mistake (you can try by entering other number!). That kind of logic should exist in a program for security and integrity. We enter the first line of text of our file, the file with one line is shown and then the three options are shown again. Next, we decide to add line number 1, making the previous line of text the second line. Then line number 3 is added to the end and our file is displayed now with its three lines. Next, we delete line number 2 and add another line. This is just an example of the run. We could add and delete any line to our file. The program does this by using four functions includingmain(). In main(), a pointer called Head stores the starting address of the linked list. The function called GetChoice() is called in a loop, until a 3 for Quit is entered by the user of the program. If the user types a "1", the AddLine() function is called and if "2" is typed, then DelLine() is called. For both AddLine() and DelLine(), Head is passed and the new starting address of the list is received in it. After returning from these functions, the starting address of the linked list could be different.
GetChoie()
This function also receives Head from main() and Head is copied into p, a pointer to type struct Line. This function prints the entire file before asking for the choice. p goes through the for loop, each time printing the line number called i and the Str member of the Line. When doing the next iteration of the loop, i or the line number is incremented and p is advanced to the address of the next node in the list. Finally, the choice is obtained from the user and that is returned to main().
AddLine()
This function also receives the beginning address of the list in p.p is assigned to pStart. Using malloc(), a pointer to typestruct Line is obtained in pNew. Then the string and the line number for inserting the string is obtained from the user. Number contains the line that this new line will be. In the for loop, i is incremented until it is one less than Number. As i is incremented, p is advanced to point to the address of each of the nodes of the list. Also,pLast comes right behind p, making available the address of the previous node when we find the insertion point in the list. Once we find the i where it is equal to Number,p will point to the node that will follow the new node. This is done using the pNew->Next = p; statement. The string containing the line of data is also copied into pNew.Str. If the node is at the beginning of the list, then pNew is returned as the address of the start of the list. Otherwise, we have the last node point to the new node and return the same starting address of the list as what we received. |
If the node to be deleted is the first one in the list, then pStart is made to point to the second node in the list. The first node is freed and returns the new starting address. If the node to be deleted is not the first one, then p and pLast are obtained using the same for loop as theAddLine() function. p is the address of the node to be removed. Before it is removed, its next member, which has the address of the next node, is copied into the next member of pLast. Then the node is freed and the starting address of the list is returned.
Exercises
Inpointers worksheet we studied how to store and manipulate addresses of memory locations. In this worksheet we will se how we can use pointers, that is once we have the address of a location, we will access its contents. The asterisk (*) in the declaration indicates that the variable is a pointer, but the next time the asterisk is used in the program it is called the indirection operator.
#include<stdio.h>
void main() { int i = 56, *p1; // Statement 1
p1 = &i; // Statement 2 printf("The address of p1 = %p\nThe value of *p1 = %d\n", p1, *p1); // Statement 3 }
|
|
#include<stdio.h>
void main() { int i = 56, j, *p1, *p2; // Statement 1
p1 = &i; // Statement 2 p2 = p1; // Statement 3 j = *p2; // Statement 4 printf("i = %d, j = %d, *p1 = %d, *p2 = %d\n", i, j, *p1, *p2); }
j = *p2 + 1;
|
|
#include<stdio.h>
void main() { int i = 56, *p1; // Statement 1
p1 = &i; // Statement 2 *p1 = *p1 + 1; // Statement 3 printf("i = %d, *p1 = %d, p1 = %p\n", i, *p1, p1); }
|
|
#include<stdio.h>
void main() { int i = 56, j = 12, k, *p1 = &i, *p2 = &j, *p3 = &k;
printf("p1 = %p, p2 = %p, p3 = %p\n", p1, p2, p3);
*p3 = *p1; // Statement 1 *p1 = *p2; // Statement 2 *p2 = *p3; // Statement 3 printf("p1 = %p, p2 = %p, p3 = %p\n", p1, p2, p3); printf("i = %d, j = %d \n", i, j); }
|
|
#include<stdio.h>
void FunStuff(int *, int *,int *);
void main() { int i = 56, j = 12, k = 99, *p1 = &i, *p2 = &j, *p3;
p3 = &k;
printf("p1 = %p, p2 = %p, p3 = %p\n", p1, p2, p3); FunStuff(&i, p2, p3); printf("\ni = %d, j = %d, k = %d\n", i, j, k); printf("\np1 = %p, p2 = %p, p3 = %p\n", p1, p2, p3); } // the parameter should match with the &i, p2 and p3 in order // or i, j, k void FunStuff(int *q, int *r,int *s) { *q = *r + *s; // Statement 1 *r = *s; // Statement 2 *s = 0; // Statement 3 r = r + 1; // Statement 4 s = s + 1; // Statement 5 }
|
|
#include<stdio.h>
void FunStuff(int *);
void main() { int i[5] = {0, 0, 0, 0, 0};
printf("&i[0] = %p, i = %p\n", &i[0], i); FunStuff(i); printf("\ni[0] = %d, i[1] = %d, i[2] = %d, i[3] = %d\n", i[0], i[1], i[2], i[3]); }
void FunStuff(int *q) // Statement 1 { *q = 10; // Statement 2 ++q; // Statement 3 *q = 20; // Statement 4 *(q + 1) = 30; // Statement 5 printf("\nq = %p\n", q); // Statement 6 q[2] = 40; // Statement 7 }
void FunStuff(int q[ ])
*(q + 3) == q[3]?
*(q + 3) == q[3]? |
------------------------------------------------------
|
#include<stdio.h>
void main(void) { int i, j = 1, k = 2, m = 3, *a[3];
a[0] = &j; a[1] = &k; a[2] = &m; for(i = 0; i <= 2; ++i) printf("*a[%d] = %d, a[%d] = %p\n", i, *a[i], i, a[i]); }
|
|
#include<stdio.h>
void main(void) { int i;
char j[15] = "I", k[15] = "Ain't", m[15] = "Retaliating", *a[3];
a[0] = j; a[1] = k; a[2] = m; printf("j = %s, j = %p, &j[0] = %s, &j[0] = %p\n\n", j, j, &j[0], &j[0]); for(i = 0; i <= 2; ++i) printf("a[i] = %s, a[i] = %p\n", a[i], a[i]); }
|
|
j == &j[0]? j == a[0]?
|
|
#include<stdio.h>
// main() function variation int main(int argc, char *argv[ ]) { printf("argc = %d\n", argc); printf("%p %s \n", argv[0], argv[0]); printf("%p %s \n", argv[1], argv[1]); printf("%p %s \n", argv[2], argv[2]); printf("%p %s \n", argv[3], argv[3]); // return 0 means back to the system/OS return 0; }
Find the executable, run it at command prompt as shown on the right instead of running it through your compiler as usually done. Your project files and the executable is under the debug directory as shown.
"myaddr soon past?"
|
Note: A complete story and working program examples of the command line arguments for C/C++ programs can be found inCommand Line Arguments. |