-
Notifications
You must be signed in to change notification settings - Fork 0
/
list.h
121 lines (111 loc) · 2.91 KB
/
list.h
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
typedef struct list_s
{
struct list_s *next; /* NULL for the last item in a list */
int data;
}
list_t;
/* Counts the number of items in a list.
*/
int count_list_items(const list_t *head) {
// FIXME Absent check NULL != head
// if (NULL == head) {
// return 0;
// }
if (head->next) {
// Recursive call is slower than while loop and can cause a stack overflow
return count_list_items(head->next) + 1;
} else {
return 1;
}
}
/* TODO Variant with loop
int count_list_items(const list_t* head) {
list_t* item = head;
int count = 0;
while (NULL != item) {
item = item->next;
++count;
}
return count;
}
*/
/* Inserts a new list item after the one specified as the argument.
*/
// FIXME It's better to change the return value type to list_t*
// and return a pointer to the created element or NULL if
// something is wrong.
void insert_next_to_list(list_t *item, int data) {
// FIXME Hard to understand code with wrong assignment.
// It is better to break instructions into several lines of code.
// Absent check NULL == item
// Absent check NULL == malloc
// newitem->next = newitem
(item->next = malloc(sizeof(list_t)))->next = item->next;
item->next->data = data;
}
/* TODO Variant with returning created item
list_t* insert_next_to_list(list_t* item, int data) {
list_t* next = malloc(sizeof(list_t));
if (NULL == next) {
return NULL;
}
next->data = data;
next->next = NULL;
if (NULL != item) {
next->next = item->next;
item->next = next;
}
return next;
}*/
/* Removes an item following the one specificed as the argument.
*/
// FIXME It's better to change the return value to list_t*
// and return value of item->next->next or NULL
void remove_next_from_list(list_t* item) {
// FIXME Absent check NULL == item
if (item->next) {
free(item->next);
// FIXME Access to item->next->next after free item->next!
item->next = item->next->next;
}
}
/* TODO Variant with list_t* returning value
list_t* remove_next_from_list(list_t* item) {
if (NULL == item) {
return NULL;
}
if (NULL == item->next) {
return NULL;
}
list_t* next = item->next;
item->next = item->next->next;
free(next);
return item->next;
}*/
/* Returns item data as text.
*/
char* item_data(const list_t* list) {
char buf[12];
// FIXME Absent check NULL != list
// snprintf is safer choice
sprintf(buf, "%d", list->data);
// FIXME return pointer to variable on stack.
// Accessing data at this address outside of this
// function can lead undefined behavior.
return buf;
}
/* TODO Variant with second parameter char* data
char* item_data(const list_t* list, char* data) {
if (NULL == list) {
return NULL;
}
char* buf = data;
if (NULL == buf) {
buf = malloc(12);
}
if (NULL == buf) {
return NULL;
}
snprintf(buf, 12, "%d", list->data);
return buf;
}*/