Read Sams Teach Yourself C in 24 Hours Online
Authors: Tony. Zhang
61: ptr->next_ptr = new_ptr;
62: }
63: }
64: /**
65: ** list_node_delete()
66: **/
67: int list_node_delete(void)
68: {
69: NODE *ptr, *ptr_saved;
70: unsigned long id;
71: int deleted = 0;
72: int reval = 0;
73:
74: if (head_ptr == NULL){
75: printf(“Sorry, nothing to delete.\n”);
76: reval = 1;
77: } else {
78: printf(“Enter the student ID: “);
79: scanf(“%ld”, &id);
80:
81: if (head_ptr->id == id){
82: ptr_saved = head_ptr->next_ptr;
83: free(head_ptr);
84: head_ptr = ptr_saved;
85: if (head_ptr == NULL){
86: printf(“All nodes have been deleted.\n”);
87: reval = 1;
88: }
89: } else {
90: for (ptr=head_ptr;
91: ptr->next_ptr != NULL;
92: ptr=ptr->next_ptr){
93: if (ptr->next_ptr->id == id){
94: ptr_saved = ptr->next_ptr->next_ptr;
95: free(ptr->next_ptr);
96: ptr->next_ptr = ptr_saved;
97: deleted = 1;
98: break;
99: }
100: }
101: if (!deleted){
102: printf(“Can not find the student ID.\n”);
103: }
30 067231861x CH24 1/25/00 10:48 AM Page 413
Where Do You Go From Here?
413
104: }
105: }
106: return reval;
107: }
108: /**
109: ** list_node_print()
110: **/
111: void list_node_print(void)
112: {
113: NODE *ptr;
114:
115: if (head_ptr == NULL){
116: printf(“Nothing to display.\n”);
117: } else {
118: printf(“The content of the linked list:\n”);
119: for (ptr = head_ptr;
120: ptr->next_ptr != NULL;
24
121: ptr = ptr->next_ptr){
122: printf(“%s:%d -> “,
123: ptr->name,
124: ptr->id);
125: }
126: printf(“%s:%d ->|”,
127: ptr->name,
128: ptr->id);
129: printf(“\n”);
130: }
131: }
132: /**
133: ** list_node_free()
134: **/
135: void list_node_free()
136: {
137: NODE *ptr, *ptr_saved;
138:
139: for (ptr=head_ptr; ptr != NULL; ){
140: ptr_saved = ptr->next_ptr;
141: free(ptr);
142: ptr = ptr_saved;
143: }
144: free(ptr);
145: }
146: /**
147: ** ErrorExit()
148: **/
149: void ErrorExit(char *str)
150: {
151: printf(“%s\n”, str);
152: exit(ERR_FLAG);
153: }
30 067231861x CH24 1/25/00 10:48 AM Page 414
414
Hour 24
There is no direct output from the module program in Listing 24.1.
The purpose of the program in Listing 24.1 is to provide a module program that
ANALYSIS
contains all cohesive functions for linked list creation, node addition, and node reduction. Figure 24.2 demonstrates the tasks performed by functions, such as list_node_create(), list_node_add(), and list_node_delete(), from the program.
FIGURE 24.2
head_ptr
next_ptr
Peter
Use functions defined
1 2 3 4
in
24L01.c
(refer to the
(a)
following paragraphs
for explanation).
next_ptr
next_ptr
head_ptr
Peter
Paul
1 2 3 4
5 6 7 8
(b)
Null
next_ptr
next_ptr
head_ptr
next_ptr
Peter
Paul
Mary
1 2 3 4
5 6 7 8
7 7 7 7
(c)
Null
head_ptr
next_ptr
next_ptr
Peter
Mary
1 2 3 4
7 7 7 7
(d)
Null
head_ptr
next_ptr
Mary
7 7 7 7
(e)
Null
As you can see in Figure 24.2 (a), the first linked list node is created by calling the list_node_create() function, and the data items are added with the help of the list_node_add() function. Also, the head_ptr pointer points to the node. Here Peter is the student name; 1234 is his ID number. Because there are no more nodes linked, the next_ptr pointer of the first node is set to be null.
In Figure 24.2 (b), another node is added to the linked list, with Paul as the student name and 5678 as the ID number. Note that the next_ptr pointer of the first node is reset to point to the second node, while the next_ptr pointer of the second node is set to be null.
30 067231861x CH24 1/25/00 10:48 AM Page 415
Where Do You Go From Here?
415
Likewise, in Figure 24.2 (c), the third node is added to the linked list. The next_ptr pointer of the third node is a null pointer. The pointer in the second node is reset to point to the third node.
If you want to delete one of the nodes, you can call the list_node_delete() function.
As shown in Figure 24.2 (d), the second node is deleted, so the pointer of the first node has to be reset to point to the former third node that contains the student name Mary and her ID number, 7777.
In Figure 24.2 (e), the first node is deleted by applying the list_node_delete() function again. There is only one node left in the linked list. The head_ptr pointer has to be reset to point to the last node.
The header file, 24L02.h, included in the module program 24L01.c, is shown in Listing 24.2. (The header file is also included by the driver program in Listing 24.3.)
24
LISTING 24.2
Putting Data Declarations and Function Prototypes into
TYPE
the Header File
1: /* 24L02.h: the header file */
2: #include
3: #include
4:
5: #ifndef LNK_LIST_H
6: #define LNK_LIST_H
7: #define ERR_FLAG 1
8: #define MAX_LEN 16
9:
10: struct lnk_list_struct
11: {
12: char name[MAX_LEN];
13: unsigned long id;
14: struct lnk_list_struct *next_ptr;
15: };
16:
17: typedef struct lnk_list_struct NODE;
18:
19: NODE *list_node_create(void);
20: void list_node_add(void);
21: int list_node_delete(void);
22: void list_node_print(void);
23: void list_node_free(void);
24: void ErrorExit(char *);
25: void main_interface(int);
26:
27: #endif /* for LNK_LIST_H */
30 067231861x CH24 1/25/00 10:48 AM Page 416
416
Hour 24
There is no direct output from the program in Listing 24.2.
The purpose of the program in Listing 24.2 is to declare a structure with the tag
ANALYSIS
name of lnk_list_struct in lines 10–15, and define a new variable name, of the structure NODE, in line 17.
The prototypes of the functions defined in the module program in Listing 24.1, such as list_node_create(), list_node_add(), and list_node_delete(), are listed in lines 19–25.
Note that the #ifndef and #endif preprocessor directives are used in lines 5 and 27. The declarations and definitions located between the two directives are compiled only if the macro name LNK_LIST_H has not been defined. Also, line 6 defines the macro name if it has not been defined. It’s a good idea to put the #ifndef and #endif directives in a header file so as to avoid cross inclusions when the header file is included by more than one source file. In this case, the declarations and definitions in the 24L02.h header file will not be included more than one time.
The module program in Listing 24.3 provides an interface that the user can use to call the functions saved in the source file (24L01.c).
TYPE
LISTING 24.3
Calling Functions Saved in the Module File
1: /* 24L03.c: The driver file */
2: #include “24L02.h” /* include header file */
3:
4: main(void)
5: {
6: int ch;
7:
8: printf(“Enter a for adding, d for deleting,\n”);
9: printf(“p for displaying, and q for exit:\n”);
10: while ((ch=getchar()) != ‘q’){
11: main_interface(ch); /* process input from the user */
12: }
13:
14: list_node_free();
15: printf(“\nBye!\n”);
16:
17: return 0;
18: }
I compile the source files, 24L01.c and 24L03.c, separately with Microsoft Visual C++, and then link their object files and C library functions together to produce a single executable program called 24L03.exe. I have the following output displayed after I run the 30 067231861x CH24 1/25/00 10:48 AM Page 417
Where Do You Go From Here?
417
executable 24L03.exe and enter or delete several student names and their ID numbers (the bold characters or numbers in the output section are what I entered from the keyboard):
Enter a for adding, d for deleting,
OUTPUT
p for displaying, and q for exit:
a
Enter the student name and ID: Peter 1234
a
Enter the student name and ID: Paul 5678
a
Enter the student name and ID: Mary 7777
p
The content of the linked list:
Peter:1234 -> Paul:5678 -> Mary:7777 ->|
d
Enter the student ID: 1234
24
The content of the linked list:
Paul:5678 -> Mary:7777 ->|
d
Enter the student ID: 5678
The content of the linked list:
Mary:7777 ->|
d
Enter the student ID: 7777
All nodes have been deleted.
q
Bye!
The purpose of the program in Listing 24.3 is to provide the user with an inter-ANALYSIS face to call other functions. The functions, such as list_node_create(), list_node_add(), and list_node_delete(), can be invoked through the interface. Also, the main() function is located inside the program of Listing 24.3.
The content of a linked list node can be printed out in the format of
name:id ->
The following is an example:
Peter:1234 -> Paul:5678 -> Mary:7777 ->|
Here the sign | is used to indicate the pointer of the last node is a null pointer.
Figure 24.3 shows the relationship among the 24L01.c, 24L02.h, and 24L03.c files.
30 067231861x CH24 1/25/00 10:48 AM Page 418
418
Hour 24
FIGURE 24.3
24LO2.h
The relationship
among the
24L01.c
,
24L02.h
, and
24L03.c
files.
24LO1.c
24LO3.c
Compiler
24LO1.obj
24LO3.obj
C Library
Functions
Linker
24LO3.exe
To learn to compile separate source files and link their object files together to make a single executable program, you need to check the technical reference from your C compiler vendor.
Programming Style
In this section, I’d like to briefly highlight some points that can help you write clean programs that can easily be read, understood, and maintained.
First, make sure the variable or function names in your program describe the meanings of the variables or tasks of the functions precisely and concisely.
Put comments into your code so that you or the other readers can have clues about what your code is doing, or at least what the code intends to do but might do incorrectly.
Whenever possible, keep using local variables, not global variables. Try to avoid sharing global data among functions; instead, pass the shared data as arguments to functions.
30 067231861x CH24 1/25/00 10:48 AM Page 419
Where Do You Go From Here?
419
You should be careful in the use of C operators which use the same symbols, especially the assignment operator (=) and the conditional operator (==), because any misuse of these two operators can lead to an unexpected result and make debugging very difficult.
Avoid using the goto statement; instead, use other control flow statements whenever needed.
Use named constants in your program, instead of numeric constants, because named constants can make your program more readable, and you will only have to go to one place to update the values of constants.
You should put parentheses around each constant expression or argument defined by a preprocessor directive to avoid side effects.
Also, you should set up a reasonable rule for spacing and indentation so that you can fol-24
low the rule consistently in all the programs you write. The rule should help make your programs easy to read.
Modular Programming
It’s not a good programming practice to try to solve a complex problem with a single function. The proper way to approach it is to break the problem into several smaller and simpler problems that can be understood in more detail, and then start to define and build functions to solve those smaller and simpler problems. Keep in mind that each of your functions should do only one task, but do it well.
When your program becomes larger and larger, you should consider breaking it into several source files, with each source file containing a small group of cohesive functions.
Such source files are also called
modules
. Put data declarations and function prototypes into header files so that any changes to the declarations or prototypes can be automatically signified to all source files that include the header file.