270 likes | 387 Views
Dynamic Allocation. Array variables have fixed size, used to store a fixed and known amount of variables This size can’t be changed after compilation However, we don’t always know in advance how much space we would need for an array or a variable
E N D
Dynamic Allocation • Array variables have fixed size, used to store a fixed and known amount of variables • This size can’t be changed after compilation • However, we don’t always know in advance how much space we would need for an array or a variable • We would like to be able to dynamically allocate memory
The malloc function void *malloc(unsigned int nBytes); • The function malloc is used to dynamically allocate nBytes worth of space • How to determine nBytes? • malloc returns a pointer to the allocated area on success, NULL on failure • You should always check whether memory was successfully allocated • Remember to #include <stdlib.h>
Example dynamic_reverse_array.c
Why casting? The casting in y=(int *) malloc(n*sizeof (int)); is needed because malloc returns void * : void *malloc(unsigned int nbytes); The type void * specifies a general pointer, which can be cast to any pointer type.
What is this ‘sizeof’ ? • The sizeof operator gets a variable or a type as an input and outputs its size in bytes: double x; s1=sizeof(x); /* s1 is 8 */ s2=sizeof(int) /* s2 is 4 */
Free the allocated memory segment void free(void *ptr); • We use free(p) to free the allocated memory pointed to by p • If p doesn’t point to an area allocated by malloc, a run-time error occurs • Always remember to free the allocated memory once you don’t need it anymore • Otherwise, you may run out of memory before you know it!
Another example another_strcpy.c
Exercise • Implement the function my_strcat – • Input – two strings, s1 and s2 • Output – a pointer to a dynamically allocated concatenation (‘shirshur’) • For example: The concatenation of “hello_” and “world!” is the string “hello_world!” • Write a program that accepts two strings from the user and prints their concatenation • Assume input strings are no longer than a 100 chars
Solution my_strcat.c (my_strcat2.c)
What’s wrong with this? char *my_strcat(char *str1, char *str2) { int len; char result[500]; /* Let’s assume this is large enough */ len = strlen(str1); strcpy(result, str1); strcpy(result+len, str2); return result; }
Exiting the program void exit(int status); • Sometimes an error occurs and we want the program to immediately exit • The exit function closes all open files, frees all allocated memory, and exits the program • Equivalent to calling ‘return’ within main • Remember to #include <stdlib.h> • See strcpy_with_exit.c
Exercise • Write the following program: • Input: a sequence of positive integers, until a negative one is input • Output: the largest 20 numbers (not necessarily sorted) • Do this without dynamic allocation
Solution top20.c
Exercise • Extend the previous program so that the number of numbers presented at the end is chosen by the user: • Input: a number N, and a sequence of positive integers, terminated by a negative one • Output: the top N integers
Solution topN.c
Implementing a student package • We want to create (part of) a course-management program. • We need to – • Maintain a list of the participating students • Keep track of their final grade • Be able to add and remove students from the course • And so on…
How will we store a student? • One possible way is using a structure, like - typedefstruct Student_t { char ID[ID_LENGTH+1]; char Name[NAME_LENGTH+1]; int grade; } Student;
Creating a student 1 Student NewStudent(char name[], char ID[], int grade) { Student new; new.Name = name; new.ID = ID; new.grade = grade; return new; }
Creating a student 2 (a better idea) Student NewStudent(char name[], char ID[], int grade) { Student new; strcpy(new.Name, name); strcpy(new.ID, ID); new.grade = grade; return new; }
Storing a list of students • One way to go would be by using an array of student structures (or pointers to structures). • The are problems with this – • we must allocate a big-enough array before accepting students (how do we know what’s big enough?) • How shall we remove students from the list without creating “holes”? • How can we maintain the list sorted by grade? • Insertion and deletion may be problematic
Linking students • A better alternative might be using a linked list, by “self reference”. typedefstruct Student_t { char ID[ID_LENGTH]; char Name[NAME_LENGTH]; int grade; struct Student_t *next; /* A pointer to the next item on the list */ } Student;
Linked lists - searching ! ? ? Head … * A list is always maintained by its head (why is this enough?)
Linked lists - insertion Previous Next Head … Insert new item:
Linked lists - deletion Previous Current Head …
Creating a new kind of student • Usually when using linked lists we don’t know how many elements will be in the list • Therefore we would like to be able to dynamically allocate new elements when the need arises • A possible implementation follows…
Creating a new kind of student Student *create_student(char name[], char ID[], int grade) { Student *std; std = (Student *)malloc(sizeof(Student)); if (std == NULL) { printf(“Memory allocation error!\n”); exit(1); } strcpy(std->Name, name); strcpy(std->ID, ID); std->grade = grade; std->next = NULL; return std; }
Why not this, again? Student *create_student(char name[], char ID[], int grade) { Student std; strcpy(std.Name, name); strcpy(std.ID, ID); std.grade = grade; std.next = NULL; return &std; }