目录
功能:
1.添加
2.删除
3.查找
4.显示
5.排序
6.修改
7.退出
小编通过构建了一个结构体数组实现了通讯录,只不过该方式不能动态管理通讯录的大小。
1.func.h`
#include
#include
#include
#define MAX 1000
#define name_max 10
#define phone_max 20
#define addr_max 10
void Qsort(struct contact *s);
void Initial(struct contact *s);
void Del(struct contact *s);
int Add(struct contact *s);
void Show(struct contact *s);
void Seacher(struct contact *s);
void Modify(struct contact *s);
struct people
{
char name[name_max];
char phone[phone_max];
char addr[addr_max];
};
struct contact
{
struct people arr[MAX];
int sz;
};
2.function.c
#define _CRT_SECURE_NO_WARNINGS
#include"func.h"
int _compare(const void *elem1, const void *elem2)
{
return strcmp(((struct people*)elem1)->name
,((struct people*)elem2)->name);
}
void Show(struct contact *s)
{
if (s->sz!=0)
{
printf("%-15s\t%-15s\t%-15s\n", "名字", "电话", "地址");
int n = s->sz;
int i = 0;
for (i = 0; i < n ; i++)
{
printf("%-15s\t", (s->arr[i].name));
printf("%-15s\t", (s->arr[i].phone));
printf("%-15s\t\n", (s->arr[i].addr));
}
}
return;
}
int Find(char*a,struct contact *s)
{
int i = 0;
int n = s->sz;
for (i = 0; i < n; i++)
{
if (strcmp(a, s->arr[i].name) == 0)
return i;
}
return -1;
}
void Initial(struct contact *s)
{
s->sz = 0;
memset(s->arr, 0, sizeof(s->arr));
}
int Add(struct contact *s)
{
if (MAX == s->sz)
{
printf("通讯录已满。\n");
return 0;
}
int n = s->sz;
printf("请输入:\n");
printf("请输入名字。\n");
scanf("%s", &(s->arr[n].name));
printf("请输入电话。\n");
scanf("%s", &(s->arr[n].phone));
printf("请输入住址。\n");
scanf("%s", &(s->arr[n].addr));
s->sz++;
return 0;
}
void Modify(struct contact *s)
{
printf("请输入要修改的名字->\n");
char a[name_max] = {0};
scanf("%s", &a);
int pos = Find(a,s);
if (pos >= 0)
{
printf("请输入:\n");
printf("请输入名字。\n");
scanf("%s", &(s->arr[pos].name));
printf("请输入电话。\n");
scanf("%s", &(s->arr[pos].phone));
printf("请输入住址。\n");
scanf("%s", &(s->arr[pos].addr));
}
else
printf("此用户不存在\n");
return;
}
void Del(struct contact *s)
{
int n = 0;
if (0 == s->sz)
{
printf("通讯录没人。\n");
return;
}
else
{
printf("请输入要删除的名字\n");
char sname[10];
scanf("%s", sname);
n = Find(sname, s);
if (n < 0)
{
printf("不存在此人。\n");
return;
}
else
{
for (; n < s->sz - 1; n++)
{
s->arr[n] = s->arr[n + 1];
}
s->sz--;
}
}
return;
}
void Seacher(struct contact *s)
{
if (s->sz == 0)
{
printf("先加加人吧。\n");
return ;
}
printf("请输入人名\n");
char sname[10];
scanf("%s", sname);
int n = Find(sname, s);
if (n >= 0)
{
printf("%-15s\t%-15s\t%s-15\n", "名字", "电话", "地址");
printf("%-15s\t", (s->arr[n].name));
printf("%-15s\t", (s->arr[n].phone));
printf("%-15s\t\n", (s->arr[n].addr));
return;
}
printf("查无此人\n");
return;
}
void Qsort(struct contact *s)
{
qsort(s->arr, s->sz, sizeof(s->arr[0]), _compare);
}
3.test.c
#define _CRT_SECURE_NO_WARNINGS
#include"func.h"
void menu()
{
printf("******************\n");
printf("*1.add****2.del***\n");
printf("*3.seacher*4.show*\n");
printf("*5.qsort**6.modify*\n");
printf("*0.exit***********\n");
printf("******************\n");
}
int main()
{
int input = 0;
struct contact s;
Initial(&s);
do
{
menu();
scanf("%d", &input);
switch (input)
{
case 0:
break;
case 1:
Add(&s);
break;
case 2:
Del(&s);
break;
case 3:
Seacher(&s);
break;
case 4:
Show(&s);
break;
case 5:
Qsort(&s);
break;
case 6:
Modify(&s);
break;
default:
printf("请重试\n");
break;
}
} while (input);
return 0;
}
首先我们来想一想为什么存在动态内存管理呢?目前我们开辟空间的方式主要有创建一个变量或数组,但是这种方式开辟的空间是一定的,一旦我们只有在使用时,才能确定所需要的空间大小,这种方式就满足不了了。那动态内存管理时如何实现的呢?接下来,我们来了解一下几个函数。
Return Value
malloc returns a void pointer to the allocated space, or NULL if there is insufficient memory available.
返回值有两种情况
1.一个类型为 void*的指针,并指向向内存申请的连续空间。
2.NULL空指针,当开辟失败时。
当使用malloc函数时,需搭配free函数使用,不然会造成内存泄漏。
1.指向销毁空间的指针
返回值为void
举个栗子
#include
#include
#include
int main()
{
char *p1 = (char*)malloc(20);
if (p1 != NULL) //判断是否开辟成功
{
strcpy(p1, "hello world");
printf("%s\n", p1);
}
free(p1);
p1 = NULL; //该操作是非常有必要的,因为free过后,p1所指的空间归还,不能被使用
//该操作可避免非法访问内存
return 0;
}
3.calloc
函数功能:开辟一块空间,该空间有num个size字节的元素,并且会将所有字节初始化为0。
函数参数
1.元素个数
2.元素的字节大小
int main()
{
int *arr = (int*)calloc(10, sizeof(int));
if (arr != NULL)
{
int i = 0;
for (i = 0; i < 10; i++)
{
printf("%d ", arr[i]);
}
}
free(arr);
arr = NULL;
return 0;
}
4.realloc
该函数可以灵活的调整内存的大小
函数参数
1.指向要调整空间的指针
2.调整后的大小
返回值
调整后的内存的起始地址
该函数实际运行时会有两种结果:
1.当需调整的内存之后的空间足够时,直接在后面追加
2.当需调整的内存之后的空间不够时,重新开辟一块空间并将原空间的内容拷贝过来,返回新空间的起始地址。
实例:
int main()
{
int i = 0;
int *ps = (int *)calloc(10, sizeof(int)); //此时开辟了40个字节的空间
if (ps != NULL)
{
int* tmp = realloc(ps, 80);//扩充到80字节
if (tmp != NULL)
{
ps = tmp;
}
}
for (i = 0; i < (80) / sizeof(int); i++)
{
ps[i] = i;
}
for (i = 0; i < (80) / sizeof(int); i++)
{
printf("%d ", ps[i]);
}
return 0;
}
1.对NULL指针解引用
int main()
{
int * ps = (int*)malloc(INT_MAX / 4);
*ps = 20;//当ps为NULL会发生什么?
printf("%d\n", ps);
free(ps);
ps = NULL;
return 0;
}
int main()
{
int *ps = (int *)malloc(10 * sizeof(int));
int i = 0;
if (ps != NULL)
{
for (i = 0; i < 12; i++)
{
ps[i] = i; //当i>=10时,就会发生越界。
}
}
free(ps);
ps = NULL;
return 0;
}
当i>=10时,就会发生越界。
3.对非动态开辟的内存进行free
int main()
{
int i = 0;
int *p = &i;
free(p);
return 0;
}
int main()
{
int i = 0;
int *ps = (int *)malloc(40);
if (ps != NULL)
{
for (i = 0; i < 5; i++)
{
*ps = i;
ps++;
}
}
free(ps);
ps = NULL;
return 0;
}
5.对同一内存多次free
int main()
{
int *ps = (int*)malloc(40);
if (ps != NULL)
{
free(ps);
}
free(ps);
return 0;
}
void test()
{
int *ps = (int*)malloc(40);
if (ps != NULL)
{
*ps = 20;
}
}
int main()
{
test();
while (1);
return 0;
}
ps:内存泄漏会导致内存利用率下降,当动态开辟的内存不用时需及时并正确的释放。
1.test.c
#define _CRT_SECURE_NO_WARNINGS
#include"func.h"
void menu()
{
printf("******************\n");
printf("*1.add****2.del***\n");
printf("*3.seacher*4.show*\n");
printf("*5.qsort**6.modify*\n");
printf("*0.exit***********\n");
printf("******************\n");
}
int main()
{
int input = 0;
struct contact s;
Initial(&s);
do
{
menu();
scanf("%d", &input);
switch (input)
{
case 0:
Destroy(&s);
break;
case 1:
Add(&s);
break;
case 2:
Del(&s);
break;
case 3:
Seacher(&s);
break;
case 4:
Show(&s);
break;
case 5:
Qsort(&s);
break;
case 6:
Modify(&s);
break;
default:
printf("请重试\n");
break;
}
} while (input);
return 0;
}
2.function.c
#include"func.h"
int _compare(const void *elem1, const void *elem2)
{
return strcmp(((struct people*)elem1)->name
,((struct people*)elem2)->name);
}
void Destroy(struct contact *s)
{
free(s->arr);
s->arr = NULL;
s->max = 0;
s->sz = 0;
}
void Show(struct contact *s)
{
if (s->sz!=0)
{
printf("%-15s\t%-15s\t%-15s\n", "名字", "电话", "地址");
int n = s->sz;
int i = 0;
for (i = 0; i < n ; i++)
{
printf("%-15s\t", (s->arr[i].name));
printf("%-15s\t", (s->arr[i].phone));
printf("%-15s\t\n", (s->arr[i].addr));
}
}
return;
}
int Find(char*a,struct contact *s)
{
int i = 0;
int n = s->sz;
for (i = 0; i < n; i++)
{
if (strcmp(a, s->arr[i].name) == 0)
return i;
}
return -1;
}
void Initial(struct contact *s)
{
s->sz = 0;
struct people * tmp = (struct people *)malloc(default_num*sizeof(s->arr[0]));
if (tmp != NULL)
{
s->arr = tmp;
s->max = default_num;
}
else
printf("开辟失败\n");
}
int Add(struct contact *s)
{
if (s->max == s->sz)
{
struct people * tmp = (struct people *)realloc
(s->arr, (s->max + 2)*sizeof(s->arr[0]));
if (tmp != NULL)
{
s->arr = tmp;
int n = s->sz;
printf("请输入:\n");
printf("请输入名字。\n");
scanf("%s", &(s->arr[n].name));
printf("请输入电话。\n");
scanf("%s", &(s->arr[n].phone));
printf("请输入住址。\n");
scanf("%s", &(s->arr[n].addr));
s->sz++;
s->max += 2;
}
}
else
{
int n = s->sz;
printf("请输入:\n");
printf("请输入名字。\n");
scanf("%s", &(s->arr[n].name));
printf("请输入电话。\n");
scanf("%s", &(s->arr[n].phone));
printf("请输入住址。\n");
scanf("%s", &(s->arr[n].addr));
s->sz++;
}
return 0;
}
void Modify(struct contact *s)
{
printf("请输入要修改的名字->\n");
char a[name_max] = {0};
scanf("%s", &a);
int pos = Find(a,s);
if (pos >= 0)
{
printf("请输入:\n");
printf("请输入名字。\n");
scanf("%s", &(s->arr[pos].name));
printf("请输入电话。\n");
scanf("%s", &(s->arr[pos].phone));
printf("请输入住址。\n");
scanf("%s", &(s->arr[pos].addr));
}
else
printf("此用户不存在\n");
return;
}
void Del(struct contact *s)
{
int n = 0;
if (0 == s->sz)
{
printf("通讯录没人。\n");
return;
}
else
{
printf("请输入要删除的名字\n");
char sname[10];
scanf("%s", sname);
n = Find(sname, s);
if (n < 0)
{
printf("不存在此人。\n");
return;
}
else
{
for (; n < s->sz - 1; n++)
{
s->arr[n] = s->arr[n + 1];
}
s->sz--;
}
}
return;
}
void Seacher(struct contact *s)
{
if (s->sz == 0)
{
printf("先加加人吧。\n");
return ;
}
printf("请输入人名\n");
char sname[10];
scanf("%s", sname);
int n = Find(sname, s);
if (n >= 0)
{
printf("%-15s\t%-15s\t%s-15\n", "名字", "电话", "地址");
printf("%-15s\t", (s->arr[n].name));
printf("%-15s\t", (s->arr[n].phone));
printf("%-15s\t\n", (s->arr[n].addr));
return;
}
printf("查无此人\n");
return;
}
void Qsort(struct contact *s)
{
qsort(s->arr, s->sz, sizeof(s->arr[0]), _compare);
}
3.func.h
#include
#include
#include
#define MAX 1000
#define name_max 10
#define phone_max 20
#define addr_max 10
#define default_num 3
void Destroy(struct contact *s);
void Qsort(struct contact *s);
void Initial(struct contact *s);
void Del(struct contact *s);
int Add(struct contact *s);
void Show(struct contact *s);
void Seacher(struct contact *s);
void Modify(struct contact *s);
struct people
{
char name[name_max];
char phone[phone_max];
char addr[addr_max];
};
struct contact
{
struct people* arr;
int sz;
int max;
};
ps:只需在静态的基础上修改一下初始化函数和Add函数和结构体contact即可,最后需释放动态内存。
如有错误,还望见谅。