目錄
一,動態內存函數的介紹
1.1 malloc和free
1.2 calloc
1.3 realloc
1.4C/C++程序的內存開辟
二,通訊錄管理系統
動態內存函數的介紹
malloc
free
calloc
realloc
一,動態內存函數的介紹
1.1 malloc和free
void* malloc ( size_t size );
這個函數向內存申請一塊連續可用的空間,并返回指向這塊空間的指針。如果開辟成功,則返回一個指向開辟好空間的指針。如果開辟失敗,則返回一個NULL 指針,因此 malloc的返回值一定要做檢查。返回值的類型是 void* ,所以 malloc函數并不知道開辟空間的類型,具體在使用的時候使用者自己來決定。如果參數 size 為 0 , malloc的行為是標準是未定義的,取決于編譯器。
void free ( void* ptr );
free 函數用來釋放動態開辟的內存。如果參數 ptr 指向的空間不是動態開辟的,那 free 函數的行為是未定義的。如果參數 ptr 是 NULL 指針,則函數什么事都不做。




可以看到,free之后將向內存申請的空間給釋放了,當然不要忘了將他設置為NULL防止野指針的使用,當然如果不釋放的話會出現內存泄漏的問題,我們的電腦把程序關了,就退出了,我們申請的空間也就被釋放的,但是有些服務器是一直不關的,那如果在使用時一直內存泄漏會出現問題的。
1.2 calloc
void* calloc ( size_t num , size_t size );
函數的功能是為 num 個大小為 size 的元素開辟一塊空間,并且把空間的每個字節初始化為 0 。與函數 malloc 的區別只在于 calloc 會在返回地址之前把申請的空間的每個字節初始化為全 0 。
例如:
1.3 realloc
realloc 函數的出現讓動態內存管理更加靈活。有時會我們發現過去申請的空間太小了,有時候我們又會覺得申請的空間過大了,那為了合理的時候內存,我們一定會對內存的大小做靈活的調整。那 realloc 函數就可以做到對動態開辟內存大小的調整。
void* realloc ( void* ptr , size_t size );
ptr 是要調整的內存地址size 調整之后新大小返回值為調整之后的內存起始位置。這個函數調整原內存空間大小的基礎上,還會將原來內存中的數據移動到 新 的空間。realloc 在調整內存空間的是存在兩種情況情況 1 :原有空間之后有足夠大的空間情況 2 :原有空間之后沒有足夠大的空間情況 1當是情況 1 的時候,要擴展內存就直接原有內存之后直接追加空間,原來空間的數據不發生變化。情況 2當是情況 2 的時候,原有空間之后沒有足夠多的空間時,擴展的方法是:在堆空間上另找一個合適大小的連續空間來使用。這樣函數返回的是一個新的內存地址。
將剛剛malloc的空間擴大了2唄,當然指針在給p1之前是需要判斷是否開辟成功的,如果沒有足夠的空間去開辟的話,realloc是會返回NULL指針的,如果用p1去接受,那么就會找不到原來的地址進而導致內存泄漏。
1.4C/C++程序的內存開辟
1. 棧區(stack):在執行函數時,函數內局部變量的存儲單元都可以在棧上創建,函數執行結
束時這些存儲單元自動被釋放。棧內存分配運算內置于處理器的指令集中,效率很高,但是
分配的內存容量有限。 棧區主要存放運行函數而分配的局部變量、函數參數、返回數據、返
回地址等。
2. 堆區(heap):一般由程序員分配釋放, 若程序員不釋放,程序結束時可能由OS回收 。分
配方式類似于鏈表。
3. 數據段(靜態區)(static)存放全局變量、靜態數據。程序結束后由系統釋放。
4. 代碼段:存放函數體(類成員函數和全局函數)的二進制代碼
二,通訊錄管理系統
頭文件:
contact.h
#include<stdio.h>
#include<assert.h>
#include<string.h>
#include<stdlib.h>
//通訊錄信息包含姓名,年齡,性別,電話,住址
typedef struct PeoInfo
{char name[20];int age;char sex[10];char tele[12];char addr[30];
}PeoInfo;
typedef struct Contact
{//每個人的信息PeoInfo* data;//當天通訊錄存儲的個數int count;//當前通訊錄的容量int capacity;
}Contact;//銷毀通訊錄
void DestoryContact(Contact* pc);
//初始化通訊錄
void InitContact(Contact* pc);//增加通訊錄信息
void AddContact(Contact* pc);//打印通訊錄的內容
void ShowContact(Contact* pc);
//刪除通訊錄的內容
void DelContact(Contact* pc);
//查找通訊錄的信息
void SearchContact(Contact* pc);
//修改通訊錄的信息
void ModifyContact(Contact* pc);
//排序通訊錄的內容
void SortContact(Contact* pc);
contact.c文件
#include"contact.h"//初始化通訊錄
void InitContact(Contact* pc)
{//斷言,pc不為空assert(pc);//初始時我們給通訊錄兩個大小的空間Contact* temp = (PeoInfo*)calloc(2, sizeof(PeoInfo));//如果開辟成功這將if (temp){pc->data = temp;pc->capacity = 2;pc->count = 0;}
}//檢測通訊錄容量
void Checkcapacity(Contact* pc)
{//如果當前容量等于我們的存放信息的個數那么我們就擴容if (pc->capacity == pc->count){Contact* temp = (Contact*)realloc(pc->data, sizeof(PeoInfo) * 4);if (temp){pc = temp;//每次增容成功會都要增加capacity的值pc->capacity = pc->capacity + 4;printf("增容成功\n");}}
}//增加聯系人
void AddContact(Contact* pc)
{assert(pc);//判斷通訊錄是否已滿Checkcapacity(pc);//添加信息printf("請輸入姓名:>");scanf("%s", pc->data[pc->count].name);printf("請輸入年齡:>");scanf("%d", &pc->data[pc->count].age);printf("請輸入性別:>");scanf("%s", pc->data[pc->count].sex);printf("請輸入電話:>");scanf("%s", pc->data[pc->count].tele);printf("請輸入住址:>");scanf("%s", pc->data[pc->count].addr);//每次添加聯系人之后要將count+1pc->count++;printf("添加成功\n");
}//銷毀通訊錄
void DestoryContact(Contact* pc)
{//釋放我們申請的空間free(pc->data);pc->data = NULL;
}//展示通訊錄的信息
void ShowContact(Contact* pc)
{assert(pc);int i = 0;printf("%-10s%-10s%-10s%-12s%-10s\n", "姓名", "年齡", "性別", "電話", "住址");for (i = 0; i < pc->count; i++){printf("%-10s%-10d%-10s%-20s%-15s", pc->data[i].name,pc->data[i].age,pc->data[i].sex,pc->data[i].tele,pc->data[i].addr);printf("\n");}}//查找通訊錄里面是否有這個 不考慮重名問題
int find_by_name(Contact* pc, char name[])
{assert(pc);int i = 0;for (i = 0; i < pc->count; i++){if (strcmp(pc->data[i].name, name) == 0){return i;}}return -1;
}//刪除通訊錄中某個人的信息
void DelContact(Contact* pc)
{assert(pc);printf("請輸入要刪除人的姓名:>");char name[20] = { 0 };//如果通訊錄中沒有信息if (pc->count == 0){printf("通訊錄中沒有信息可刪除\n");return;}scanf("%s", name);//查找信息int pos = find_by_name(pc, name);if (pos == -1){printf("要刪除的人不存在\n");return;}//刪除信息int i = 0;for (i = pos; i <= pc->count - 1; i++){pc->data[pos] = pc->data[pos + 1];}pc->count--;printf("刪除成功\n");
}//查找通訊錄中的某個人
void SearchContact(Contact* pc)
{assert(pc);if (pc->count == 0){printf("通訊錄中沒有信息可刪除\n");return;}char name[20] = { 0 };printf("請輸入你要查找人的名字:>");scanf("%s", name);int pos = find_by_name(pc, name);if (pos == -1){printf("要刪除的人不存在\n");return;}printf("要查找人的信息如下:>\n");printf("%-10s%-10s%-10s%-12s%-10s\n", "姓名", "年齡", "性別", "電話", "住址");printf("%-10s%-10d%-10s%-20s%-15s", pc->data[pos].name,pc->data[pos].age,pc->data[pos].sex,pc->data[pos].tele,pc->data[pos].addr);printf("\n");
}//修改通訊錄中某個人信息
void ModifyContact(Contact* pc)
{assert(pc);if (pc->count == 0){printf("通訊錄中沒有信息可修改\n");return;}char name[20] = { 0 };//查找printf("請輸入你要修改信息人的名子:>");scanf("%s", name);int pos = find_by_name(pc, name);if (pos == -1){printf("要修改的人的信息不存在\n");return;}//修改printf("請輸入你要修改的內容:\n");printf("請輸入姓名:>");scanf("%s", pc->data[pos].name);printf("請輸入年齡:>");scanf("%d", &pc->data[pos].age);printf("請輸入性別:>");scanf("%s", pc->data[pos].sex);printf("請輸入電話:>");scanf("%s", pc->data[pos].tele);printf("請輸入住址:>");scanf("%s", pc->data[pos].addr);printf("修改成功\n");
}//給qsort函數的比較函數
int cmp_by_name(const void* e1, const void* e2)
{return strcmp(((PeoInfo*)e1)->name, ((PeoInfo*)e2)->name);
}
//排序我們的通訊錄,按照名字排序
void SortContact(Contact* pc)
{assert(pc);qsort(pc->data, pc->count, sizeof(PeoInfo), cmp_by_name);printf("排序成功\n");
}
test.c
#include "contact.h"void menu()
{printf("**************************************\n");printf("**************************************\n");printf("******* 1.add 2.Del **********\n");printf("******* 3.search 4.modify **********\n");printf("******* 5.show 6.sort **********\n");printf("******* 0.exit **********\n");printf("**************************************\n");printf("**************************************\n");
}
int main()
{int input = 0;Contact con;InitContact(&con);do{ //打印菜單做提示menu();printf("請選擇:>");scanf("%d", &input);switch (input){case 1:AddContact(&con);break;case 2:DelContact(&con);break;case 3:SearchContact(&con);break;case 4:ModifyContact(&con);break;case 5:ShowContact(&con);break;case 6:SortContact(&con);break;case 0:printf("退出程序\n");DestoryContact(&con);break;default:printf("選擇錯誤請重新選擇:>");break;}} while (input);return 0;
}