C进阶:通讯录(动态版本 + 文件操作)附源码
创始人
2024-05-09 19:45:59

本文主要讲解通讯录的代码;

需要拥有结构体,动态内存开辟,文件操作的知识;

目录

🐲一.通讯录思路

🕊️二.三个文件的建立

😼三.所需要使用的变量的创建(包含在头文件contact.h中)

😸四.主函数的书写 (包含在 test.c 中)

🐬五.通讯录功能的实现(在 contact.c 中)

🦄1.添加联系人  addcontact 

🤖2.删除联系人  delcontact

👻3.查询联系人 searchcontact

🦞4.修改联系人信息  modifycontact

🐯5.打印通讯录  printcontact

🦁6.排序通讯录  sortcontact

🦖六.退出通讯录 (即input==0时)

🐲保存函数  savecontact

😸销毁函数  destroycontact

🤖七.源码

👻contact.h

🕊️contact.c

🪶test.c


一.通讯录思路

1.创建结构体类型,其中包含通讯录中联系人的信息;

   该信息可以包括:姓名,年龄,性别,电话,地址等;

2.创建一个结构体存储通讯录;

3.写一个简易的菜单来表明通讯录的功能;

   包括但不限于: 添加add,删除del,查找search,修改modigy,排序sort,打印通讯录print等;

4.通过函数来实现这些功能;

二.三个文件的建立

对于较复杂的一些代码,我们最好分文件写,这样可以使代码更清晰,可读性也更高;

在写通讯录的代码之前,我们需要先建立三个文件,分别是:

1.头文件 :   contact.h (用于函数的声明等)

2.源文件 :contact.c (用于函数的实现)

3.源文件 :   test.c (用于主函数的书写)


三.所需要使用的变量的创建(包含在头文件contact.h中)

为了后面方便改动,我们定义宏来确定一些大小;

代码:

//所需头文件的包含
#include 
#include 
#include //一些定义的表示大小的宏
#define MAX_NAME 20
#define MAX_SEX  10
#define MAX_TEL  20
#define MAX_ADDR 30#define DEFAULT_SZ 3  //默认通讯录容量
#define INC_SZ     2  //每次增容的大小//定义每个联系人的信息
typedef struct peoinfo
{char name[MAX_NAME]; //姓名int age;  //年龄char sex[MAX_SEX];  //性别char tel[MAX_TEL];  //电话char addr[MAX_ADDR];  //地址
}peoinfo;//存储每个联系人
typedef struct contact
{peoinfo* data;  //定义指针变量,方便后续动态内存开辟,进行通讯录扩容操作int sz;     //通过下标访问数组int capacity;  // 记录通讯录容量
}contact;

四.主函数的书写 (包含在 test.c 中)

1.首先要写个简易的菜单来展示通讯录功能;

2.然后利用 do ..... while 结构实现通讯录的操作;

3.还要创建一个通讯录变量  contact con ;

4. 写一个函数 ( Innitcontact (函数的实现在 contact.c 中)(包含文件的读取)) 初始化通讯录变量 con (在此时进行动态内存开辟,使用 calloc/malloc 函数)

主函数代码:

//头文件的包含
#include "contact.h"//菜单
void menu()
{printf("*****************************************************************\n");printf("**********          1.add                 2.del        **********\n");printf("**********          3.search              4.modify     **********\n");printf("**********          5.see                 6.sort       **********\n");printf("**********                    0.exit                   **********\n");printf("*****************************************************************\n");}
//利用枚举变量使代码表达的意思更清晰
enum option
{EXIT, //默认从0开始ADD,  //1DEL,  //2SEARCH,  //3MODIFY,  //4SEE,  //5SORT  //6
};int main()
{int input = 0;contact con;   //通讯录变量创建//初始化联系人数组,包含从文件中读取联系人信息Innitcontact(&con);do{menu();printf("请选择:>");scanf("%d", &input);switch (input){case ADD:addcontact(&con);  //添加break;case DEL:delcontact(&con);  //删除break;case SEARCH:searchcontact(&con);  //查找break;case MODIFY:modifycontact(&con);  //修改break;case SEE:printcontact(&con);  //打印通讯录break;case SORT:sortcontact(&con);  //排序break;case EXIT:savecontact(&con);  //保存通讯录,将联系人信息写入文件中destroycontact(&con);  //销毁通讯录printf("退出通讯录\n");break;default:printf("选择错误,重新选择\n");break;}} while (input);return 0;
}

Innitcontact 函数:

//将文件中的联系人信息读入
void download(contact* pc)
{FILE* pf = fopen("D:\\C\\c-code\\CONTACT\\CONTACT\\contact.txt", "r");  //以只读的方式打开文件if (pf == NULL)  //判断文件是否打开成功{perror("fopen");return;}peoinfo tmp = { 0 };while (fread(&tmp, sizeof(peoinfo), 1, pf)){inccapacity(pc);  //增容函数pc->data[pc->sz] = tmp;  //将联系人信息写入 data 中pc->sz++;  //记录写入联系人的数量}fclose(pf);  //关闭文件pf = NULL;
}//动态初始化联系人
void Innitcontact(contact* pc)
{pc->data = (peoinfo*)calloc(DEFAULT_SZ, sizeof(peoinfo));  //动态内存开辟,实现通讯录的动态if (pc->data == NULL)  //判断内存开辟是否成功{perror("Innitcontact");return;}pc->sz = 0;  //初始化通讯录实时容量,也可用作下标pc->capacity = DEFAULT_SZ;  //初始化容量download(pc);  //加载文件中联系人的信息
}

五.通讯录功能的实现(在 contact.c 中)

1.添加联系人  addcontact 

在添加联系人之前,我们先要判断通讯录是否已满,若已满则调用增容函数,之后在进行联系人信息的添加;

增容函数  inccapacity  代码:

//是否增容
void inccapacity(contact* pc)
{if (pc->sz == pc->capacity){printf("通讯录已满,开始增容\n");peoinfo* ptr = (peoinfo*)realloc(pc->data,(DEFAULT_SZ+INC_SZ)*sizeof(peoinfo));  //利用 realloc 进行内存的再次动态开辟,实现通讯录的增容if(ptr == NULL)  //判断内存是否开辟成功{printf("增容失败\n");perror("inccapacity");return;}else{pc->data = ptr;   //将扩容后的通讯录首地址赋给原来的通讯录pc->capacity += INC_SZ;  //容量增加printf("增容成功\n");}}
}

添加联系人函数 addcontact 代码:

//添加联系人
void addcontact(contact* pc)
{int input = 0;do{printf("按1继续,按0返回:>");  //利用 do ... while 结构实现联系人的多次添加scanf("%d", &input);switch (input){case 1:inccapacity(pc);  //判断容量是否已满,若已满,则进行增容printf("开始添加\n");  //联系人各种信息的录入printf("请输入姓名:>");scanf("%s", pc->data[pc->sz].name);printf("请输入年龄:>");scanf("%d", &(pc->data[pc->sz].age));printf("请输入性别:>");scanf("%s", pc->data[pc->sz].sex);printf("请输入电话:>");scanf("%s", pc->data[pc->sz].tel);printf("请输入地址:>");scanf("%s", pc->data[pc->sz].addr);pc->sz++;  //添加成功后,通讯录实时容量增加1printf("添加成功\n");break;case 0:printf("返回\n");return;break;default:printf("选择错误,重新选择\n");break;}} while (input);
}

2.删除联系人  delcontact

1.在删除前我们需要先判断通讯录中是否有数据,若没有则无法删除;

2.输入要删除的对象,所以我们需要写一个姓名的查找函数,返回其所在的下标,供后续删除使用;

3.删除联系人,即从返回的下标开始,使其之后的每一个元素向前移动一个位置;

查找函数  find  代码:

//查找联系人
int find(char tmp[], contact* pc)
{int i = 0;for (i = 0; i < pc->sz; i++){if (strcmp(tmp, pc->data[i].name) == 0)  //因为姓名是字符串,所以利用字符串比较函数{return i;  //查找成功返回其下标}}return -1;  //失败则返回-1
}

delcontact  代码:

//删除联系人
void delcontact(contact* pc)
{char tmp[MAX_NAME];  int pos = 0, i = 0;if (pc->sz == 0)  //判断通讯录有无数据{printf("通讯录为空,无法删除\n");return;}while (1){again:printf("请输入要删除的人的姓名:>");scanf("%s", tmp);pos = find(tmp, pc);  //查找要删除人的下标if (pos == -1){printf("要删除的人不存在,重新输入\n");goto again;}elsebreak;}printf("开始删除\n");for (i = pos; i < pc->sz - 1; i++)  //从返回的下标 pos 开始 ,之后的每个元素向前移动一位{pc->data[i] = pc->data[i + 1];}pc->sz--;  //删除成功即通讯录的实时容量减去1printf("删除成功\n");
}

3.查询联系人 searchcontact

1.在查询前需要判断通讯录中是否有数据,若无数据,则无法查询;

2.可以调用前面的查找函数;

3.查询到后打印该联系人信息,并提示查询成功;

searchcontact  代码:

//查找联系人
void searchcontact(contact* pc)
{char name[MAX_NAME];int pos = 0;if (pc->sz == 0)    //判断通讯录中是否有数据{printf("通讯录为空,无法查询\n");return;}while (1){again:printf("请输入要查找人的姓名:>");scanf("%s", name);pos = find(name, pc);  //调用 fing 函数,并返回其下标if (pos == -1){printf("查无此人,重新查询\n");  //查询失败则继续goto again;}elsebreak;}printf("查询成功\n");printf("%-20s\t%-5s\t%-10s\t%-20s\t%-30s\n", "姓名", "年龄", "性别", "电话", "地址");   //打印该联系人的信息printf("%-20s\t%-5d\t%-10s\t%-20s\t%-30s\n", pc->data[pos].name,pc->data[pos].age,pc->data[pos].sex,pc->data[pos].tel,pc->data[pos].addr);}

4.修改联系人信息  modifycontact

1.判断通讯录中是否有数据,若无数据,则无法修改;

2.输入要修改人的姓名,调用函数 find ,返回其下标;

3.开始修改,即从新录入该联系人信息;

modifycontact  代码:

//修改联系人
void modifycontact(contact* pc)
{if (pc->sz == 0)  //判断通讯录是否有数据{printf("通讯录为空,无法修改\n");return;}char name[MAX_NAME];int pos = 0;while (1){again:printf("请输入要修改的联系人的姓名:>");scanf("%s", name);pos = find(name, pc);  //返回要修改的联系人的下标if (pos == -1){printf("要修改的联系人不存在,重新输入\n");goto again;}elsebreak;}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].tel);printf("请输入地址:>");scanf("%s", pc->data[pos].addr);printf("修改成功\n");
}

5.打印通讯录  printcontact

这并不难,直接看代码:

//打印通讯录
void printcontact(contact* pc)
{int i = 0;printf("%-20s\t%-5s\t%-10s\t%-20s\t%-30s\n", "姓名", "年龄", "性别", "电话", "地址");  //打印的格式可以根据个人喜好来for (i = 0; i < pc->sz; i++){printf("%-20s\t%-5d\t%-10s\t%-20s\t%-30s\n", pc->data[i].name,pc->data[i].age,pc->data[i].sex,pc->data[i].tel,pc->data[i].addr);}
}

6.排序通讯录  sortcontact

1.首先判断通讯录中的数据是否足以支持排序,若没有数据,或就1个数据,那么都无需排序;

2.利用排序算法,完成通讯录的排序;

3.需要有交换元素的步骤,那么就需要创建中间变量(在 contact.h 中创建)来实现交换;

4.该变量可以设置成结构体变量,成员包括与data 同类型的变量 sort  ,既然与 data 同类型那么就需要对其初始化;

sort 变量的创建:

typedef struct sort
{peoinfo* sort;
}sort;

sortcontact  代码:

//排序通讯录
void sortcontact(contact* pc)
{if (pc->sz < 2){printf("通讯录数据不足,无法排序\n");  //判断是否支持排序return;}int i = 0, j = 0;sort S;  //变量的创建S.sort= (peoinfo*)calloc(pc->capacity, sizeof(peoinfo));  //sort 的初始化if (S.sort == NULL) //判断动态内存是否开辟成功{perror("sortcontact");return;}printf("开始排序\n");for (i = 0; i < pc->sz - 1; i++)   //排序算法{for (j = i + 1; j < pc->sz; j++){if (strcmp(pc->data[i].name, pc->data[j].name) > 0){S.sort[i] = pc->data[i];  //交换元素pc->data[i] = pc->data[j];pc->data[j] = S.sort[i];}}}printf("排序成功\n");free(S.sort);  //排序成功后释放所开辟的内存S.sort = NULL;  //将指针置空,防止使用野指针
}

六.退出通讯录 (即input==0时)

1.在退出通讯录之前需要保存通讯录的数据,写一个保存函数  savecontact;

2.保存好后销毁通讯录,写一个销毁函数  destroycontact;

3.退出通讯录;

保存函数  savecontact

//保存文件中的联系人信息
void savecontact(contact* pc)
{FILE* pf = fopen("D:\\C\\c-code\\CONTACT\\CONTACT\\contact.txt", "w");  //以只写的方式打开文件if (pf == NULL)  //判断文件是否打开成功{perror("savecontact");return;}int i = 0;for (i = 0; i < pc->sz; i++)   {fwrite(pc->data + i, sizeof(peoinfo), 1, pf);  //向文件中写入通讯录的数据}fclose(pf);  //数据写完后,关闭文件pf = NULL;
}

销毁函数  destroycontact

//销毁通讯录
void destroycontact(contact* pc)
{pc->sz = 0;pc->capacity = DEFAULT_SZ;  //容量回复默认值free(pc->data);  //释放之前开辟的内存pc->data = NULL;  //指针置空,防止野指针的出现
}

剩下的步骤很简单了,话不多说直接上源码;

七.源码

contact.h

#pragma once//所需头文件的包含
#include 
#include 
#include //一些定义的表示大小的宏
#define MAX_NAME 20
#define MAX_SEX  10
#define MAX_TEL  20
#define MAX_ADDR 30#define DEFAULT_SZ 3  //默认通讯录容量
#define INC_SZ     2  //每次增容的大小//定义每个联系人的信息
typedef struct peoinfo
{char name[MAX_NAME]; //姓名int age;  //年龄char sex[MAX_SEX];  //性别char tel[MAX_TEL];  //电话char addr[MAX_ADDR];  //地址
}peoinfo;//存储每个联系人
typedef struct contact
{peoinfo* data;  //定义指针变量,方便后续动态内存开辟,进行通讯录扩容操作int sz;     //通过下标访问数组int capacity;  // 记录通讯录容量
}contact;typedef struct sort
{peoinfo* sort;
}sort;//动态初始化通讯录
void Innitcontact(contact* pc);//打印通讯录
void printcontact(contact* pc);//是否增容
void inccapacity(contact* pc);//读入文件中的联系人信息
void download(contact* pc);//保存文件中的联系人信息
void savecontact(contact* pc);//销毁通讯录
void destroycontact(contact* pc);//添加联系人
void addcontact(contact* pc);//删除联系人
void delcontact(contact* pc);//查找联系人
void searchcontact(contact* pc);//修改联系人
void modifycontact(contact* pc);//排序通讯录
void sortcontact(contact* pc);

contact.c

#define _CRT_SECURE_NO_WARNINGS#include "contact.h"//将文件中的联系人信息读入
void download(contact* pc)
{FILE* pf = fopen("D:\\C\\c-code\\CONTACT\\CONTACT\\contact.txt", "r");  //以只读的方式打开文件if (pf == NULL)  //判断文件是否打开成功{perror("fopen");return;}peoinfo tmp = { 0 };while (fread(&tmp, sizeof(peoinfo), 1, pf)){inccapacity(pc);  //增容函数pc->data[pc->sz] = tmp;  //将联系人信息写入 data 中pc->sz++;  //记录写入联系人的数量}fclose(pf);  //关闭文件pf = NULL;
}//保存文件中的联系人信息
void savecontact(contact* pc)
{FILE* pf = fopen("D:\\C\\c-code\\CONTACT\\CONTACT\\contact.txt", "w");  //以只写的方式打开文件if (pf == NULL)  //判断文件是否打开成功{perror("savecontact");return;}int i = 0;for (i = 0; i < pc->sz; i++)   {fwrite(pc->data + i, sizeof(peoinfo), 1, pf);  //向文件中写入通讯录的数据}fclose(pf);  //数据写完后,关闭文件pf = NULL;
}//销毁通讯录
void destroycontact(contact* pc)
{pc->sz = 0;pc->capacity = DEFAULT_SZ;  //容量回复默认值free(pc->data);  //释放之前开辟的内存pc->data = NULL;  //指针置空,防止野指针的出现
}//动态初始化联系人
void Innitcontact(contact* pc)
{pc->data = (peoinfo*)calloc(DEFAULT_SZ, sizeof(peoinfo));  //动态内存开辟,实现通讯录的动态if (pc->data == NULL)  //判断内存开辟是否成功{perror("Innitcontact");return;}pc->sz = 0;  //初始化通讯录实时容量,也可用作下标pc->capacity = DEFAULT_SZ;  //初始化容量download(pc);  //加载文件中联系人的信息
}//打印通讯录
void printcontact(contact* pc)
{int i = 0;printf("%-20s\t%-5s\t%-10s\t%-20s\t%-30s\n", "姓名", "年龄", "性别", "电话", "地址");  //打印的格式可以根据个人喜好来for (i = 0; i < pc->sz; i++){printf("%-20s\t%-5d\t%-10s\t%-20s\t%-30s\n", pc->data[i].name,pc->data[i].age,pc->data[i].sex,pc->data[i].tel,pc->data[i].addr);}
}//是否增容
void inccapacity(contact* pc)
{if (pc->sz == pc->capacity){printf("通讯录已满,开始增容\n");peoinfo* ptr = (peoinfo*)realloc(pc->data,(DEFAULT_SZ+INC_SZ)*sizeof(peoinfo));  //利用 realloc 进行内存的再次动态开辟,实现通讯录的增容if(ptr == NULL)  //判断内存是否开辟成功{printf("增容失败\n");perror("inccapacity");return;}else{pc->data = ptr;   //将扩容后的通讯录首地址赋给原来的通讯录pc->capacity += INC_SZ;  //容量增加printf("增容成功\n");}}
}//查找联系人
int find(char tmp[], contact* pc)
{int i = 0;for (i = 0; i < pc->sz; i++){if (strcmp(tmp, pc->data[i].name) == 0)  //因为姓名是字符串,所以利用字符串比较函数{return i;  //查找成功返回其下标}}return -1;  //失败则返回-1
}//添加联系人
void addcontact(contact* pc)
{int input = 0;do{printf("按1继续,按0返回:>");  //利用 do ... while 结构实现联系人的多次添加scanf("%d", &input);switch (input){case 1:inccapacity(pc);  //判断容量是否已满,若已满,则进行增容printf("开始添加\n");  //联系人各种信息的录入printf("请输入姓名:>");scanf("%s", pc->data[pc->sz].name);printf("请输入年龄:>");scanf("%d", &(pc->data[pc->sz].age));printf("请输入性别:>");scanf("%s", pc->data[pc->sz].sex);printf("请输入电话:>");scanf("%s", pc->data[pc->sz].tel);printf("请输入地址:>");scanf("%s", pc->data[pc->sz].addr);pc->sz++;  //添加成功后,通讯录实时容量增加1printf("添加成功\n");break;case 0:printf("返回\n");return;break;default:printf("选择错误,重新选择\n");break;}} while (input);
}//删除联系人
void delcontact(contact* pc)
{char tmp[MAX_NAME];  int pos = 0, i = 0;if (pc->sz == 0)  //判断通讯录有无数据{printf("通讯录为空,无法删除\n");return;}while (1){again:printf("请输入要删除的人的姓名:>");scanf("%s", tmp);pos = find(tmp, pc);  //查找要删除人的下标if (pos == -1){printf("要删除的人不存在,重新输入\n");goto again;}elsebreak;}printf("开始删除\n");for (i = pos; i < pc->sz - 1; i++)  //从返回的下标 pos 开始 ,之后的每个元素向前移动一位{pc->data[i] = pc->data[i + 1];}pc->sz--;  //删除成功即通讯录的实时容量减去1printf("删除成功\n");
}//查找联系人
void searchcontact(contact* pc)
{char name[MAX_NAME];int pos = 0;if (pc->sz == 0)    //判断通讯录中是否有数据{printf("通讯录为空,无法查询\n");return;}while (1){again:printf("请输入要查找人的姓名:>");scanf("%s", name);pos = find(name, pc);  //调用 fing 函数,并返回其下标if (pos == -1){printf("查无此人,重新查询\n");  //查询失败则继续goto again;}elsebreak;}printf("查询成功\n");printf("%-20s\t%-5s\t%-10s\t%-20s\t%-30s\n", "姓名", "年龄", "性别", "电话", "地址");   //打印该联系人的信息printf("%-20s\t%-5d\t%-10s\t%-20s\t%-30s\n", pc->data[pos].name,pc->data[pos].age,pc->data[pos].sex,pc->data[pos].tel,pc->data[pos].addr);}//修改联系人
void modifycontact(contact* pc)
{if (pc->sz == 0)  //判断通讯录是否有数据{printf("通讯录为空,无法修改\n");return;}char name[MAX_NAME];int pos = 0;while (1){again:printf("请输入要修改的联系人的姓名:>");scanf("%s", name);pos = find(name, pc);  //返回要修改的联系人的下标if (pos == -1){printf("要修改的联系人不存在,重新输入\n");goto again;}elsebreak;}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].tel);printf("请输入地址:>");scanf("%s", pc->data[pos].addr);printf("修改成功\n");
}//排序通讯录
void sortcontact(contact* pc)
{if (pc->sz < 2){printf("通讯录数据不足,无法排序\n");  //判断是否支持排序return;}int i = 0, j = 0;sort S;  //变量的创建S.sort= (peoinfo*)calloc(pc->capacity, sizeof(peoinfo));  //sort 的初始化if (S.sort == NULL) //判断动态内存是否开辟成功{perror("sortcontact");return;}printf("开始排序\n");//qsort(pc, pc->sz, sizeof(peoinfo), cmp);for (i = 0; i < pc->sz - 1; i++)   //排序算法{for (j = i + 1; j < pc->sz; j++){if (strcmp(pc->data[i].name, pc->data[j].name) > 0){S.sort[i] = pc->data[i];  //交换元素pc->data[i] = pc->data[j];pc->data[j] = S.sort[i];}}}printf("排序成功\n");free(S.sort);  //排序成功后释放所开辟的内存S.sort = NULL;  //将指针置空,防止使用野指针
}

test.c

#define _CRT_SECURE_NO_WARNINGS//头文件的包含
#include "contact.h"//菜单
void menu()
{printf("*****************************************************************\n");printf("**********          1.add                 2.del        **********\n");printf("**********          3.search              4.modify     **********\n");printf("**********          5.see                 6.sort       **********\n");printf("**********                    0.exit                   **********\n");printf("*****************************************************************\n");}
//利用枚举变量使代码表达的意思更清晰
enum option
{EXIT, //默认从0开始ADD,  //1DEL,  //2SEARCH,  //3MODIFY,  //4SEE,  //5SORT  //6
};int main()
{int input = 0;contact con;   //通讯录变量创建//初始化联系人数组,包含从文件中读取联系人信息Innitcontact(&con);do{menu();printf("请选择:>");scanf("%d", &input);switch (input){case ADD:addcontact(&con);  //添加break;case DEL:delcontact(&con);  //删除break;case SEARCH:searchcontact(&con);  //查找break;case MODIFY:modifycontact(&con);  //修改break;case SEE:printcontact(&con);  //打印通讯录break;case SORT:sortcontact(&con);  //排序break;case EXIT:savecontact(&con);  //保存通讯录,将联系人信息写入文件中destroycontact(&con);  //销毁通讯录printf("退出通讯录\n");break;default:printf("选择错误,重新选择\n");break;}} while (input);return 0;
}

😼😸通讯录的讲解就到这儿了,如有错误或是建议,欢迎小伙伴们指出;🐲🕊️

🥰🤩希望小伙伴们可以支持支持博主啊,你们的支持对我很重要哦;😆😀

😁😄谢谢你的阅读;😊😍

相关内容

热门资讯

脚上的穴位图 脚面经络图对应的... 人体穴位作用图解大全更清晰直观的标注了各个人体穴位的作用,包括头部穴位图、胸部穴位图、背部穴位图、胳...
demo什么意思 demo版本... 618快到了,各位的小金库大概也在准备开闸放水了吧。没有小金库的,也该向老婆撒娇卖萌服个软了,一切只...
北京的名胜古迹 北京最著名的景... 北京从元代开始,逐渐走上帝国首都的道路,先是成为大辽朝五大首都之一的南京城,随着金灭辽,金代从海陵王...
苗族的传统节日 贵州苗族节日有... 【岜沙苗族芦笙节】岜沙,苗语叫“分送”,距从江县城7.5公里,是世界上最崇拜树木并以树为神的枪手部落...
长白山自助游攻略 吉林长白山游... 昨天介绍了西坡的景点详细请看链接:一个人的旅行,据说能看到长白山天池全凭运气,您的运气如何?今日介绍...