C语言实现文件排序
Posted
tags:
篇首语:本文由小常识网(cha138.com)小编为大家整理,主要介绍了C语言实现文件排序相关的知识,希望对你有一定的参考价值。
读入1个学生信息文件,进行排序,写入文件,用C语言怎么实现;
例如只读:姓名和学分;
例:lifei 45
liyang 32
lijing 98
用C语言怎么实现高手指点下。
还有其他答案吗?我下周一要交,刚到公司搞不出来,就OVER了。 对了是按各个学生的学分排,学分是FLOAT型的,初学者大家见晾,感激不禁
要实现这几种算法的关键是要熟悉算法的思想。简单的说,冒泡排序,就如名字说的,每经过一轮排序,将最大的数沉到最底部。选择排序的思想是将整个数列,分为有序区和无序区。每轮排序,将无序区里的最小数移入到有序区。快速排序的思想是以一个数为中心,通常这个数是该数列第一个数,将整个数列分为两个部分,一个部分是大于这个数的区域,一个部分是小于这个数的区域。然后再对这两个部分的数列分别排序。如果将数列分为两个部分是通过,一方面从后向前的搜索,另一方面从前向后的搜索来实现的。具体的参考后面的来自百度百科的文档。
从这几个简单的排序算法上看,有几个特点:
冒泡排序是最简单的,也是最稳定的算法。
选择排序不太稳定,但是效率上较冒泡还是有较大的提升。其实在分析的过程中就能发现,选择排序和冒泡排序相比,中间少了很多的交换过程,和比较的次数,这个应该是时间较少的原因。选择排序能够满足一般的使用。当比较的数超过以万为单位时,选择排序也还是要一点时间的。
快速排序据说是最快的。这个可以从思想上看的出来。,当记录较多的时候,快速排序的比较循环次数比上面2个都要少。但是在具体的实现过程中,并不见得如此。这是因为递归效率的低下导致的。当然,估计在实际使用过的过程,快速排序估计都会使用非递归操作栈的方式来实现。那样应该会效率高伤不少。估计我会在后期出一个快速排序的非递归实现来真正比较它们3个性能。在下面的程序中,可以通过调高N的数字就能看的出来冒泡排序和选择排序性能的差异。在N较小,大概几百的时候,是看不出来的。N较大的的时候,比如N=1000或者N=10000的时候,快速排序的递归实现就会卡死在那里了,出不了结果。
以下是具体的代码:
/*
** 常见排序算法比较
*/
#include <stdio.h>
#include <stdlib.h>
#include <time.h>
#include <windows.h>
#define N 10
#define Demo 1
void BubbleSort(int arr[], int n);
void SelectSort(int arr[], int n);
void QuickSort(int arr[], int n);
void PrintArray(int arr[], int n);
void GenerateArray(int arr[], int n);
int main(int argc, char *argv[])
int arr[N];
GenerateArray(arr, N);
#if Demo
printf("Before the bubble sort------------------------\n");
PrintArray(arr, N);
#endif
printf("Start Bubble sort----------------------\n");
clock_t start_time1=clock(); //开始计时
BubbleSort(arr, N);
clock_t end_time1=clock(); // 结束计时
printf("Running time is: %lf ms\n", (double)(end_time1-start_time1)/CLOCKS_PER_SEC*1000); //输出运行时间
#if Demo
printf("After the bubble sort------------------------\n");
PrintArray(arr, N);
#endif
printf("-----------------------------------------------------------\n");
sleep(1000); // 单位是毫秒即千分之一秒
GenerateArray(arr, N);
#if Demo
printf("Before the selection sort------------------------\n");
PrintArray(arr, N);
#endif
printf("Start selection sort----------------------\n");
clock_t start_time2=clock(); //开始计时
SelectSort(arr, N);
clock_t end_time2=clock(); // 结束计时
printf("Running time is: %lf ms\n", (double)(end_time2-start_time2)/CLOCKS_PER_SEC*1000); //输出运行时间
#if Demo
printf("After the selection sort------------------------\n");
PrintArray(arr, N);
#endif
printf("-----------------------------------------------------------\n");
sleep(1000); // 单位是毫秒即千分之一秒
GenerateArray(arr, N);
#if Demo
printf("Before the quick sort------------------------\n");
PrintArray(arr, N);
#endif
printf("Start quick sort----------------------\n");
clock_t start_time3=clock(); //开始计时
QuickSort(arr, N);
clock_t end_time3=clock(); // 结束计时
printf("Running time is: %lf ms\n", (double)(end_time3-start_time3)/CLOCKS_PER_SEC*1000); //输出运行时间
#if Demo
printf("After the quick sort------------------------\n");
PrintArray(arr, N);
#endif
system("PAUSE");
return 0;
// 产生随机列表
void GenerateArray(int arr[], int n)
int i;
srand((unsigned)time(0));
for(i = 0; i <N; i++)
arr[i] = rand(); // 生成随机数 范围在0-32767之间
// 打印列表
void PrintArray(int arr[], int n)
int i = 0;
for(i = 0; i < n; i++)
printf("%6d", arr[i]);
printf("\n");
// 经典冒泡排序
void BubbleSort(int arr[], int n)
int i = 0, j =0;
for(i = 0; i < n; i++)
for(j = 0; j < n - 1 - i; j++)
if(arr[j] > arr[j + 1])
arr[j] = arr[j] ^ arr[j+1];
arr[j+1] = arr[j] ^ arr[j+1];
arr[j] = arr[j] ^ arr[j+1];
// 快速排序的递归实现
void QuickSort(int arr[], int n)
if(n <= 1)
return;
int i =0 , j = n - 1;
int key = arr[0];
int index = 0;
while(i < j)
// 从后向前搜索
while(j > i && arr[j] > key)
j--;
if(j == i)
break;
else
//交换 a[j] a[i]
arr[j] = arr[j] ^arr[i];
arr[i] = arr[j] ^arr[i];
arr[j] = arr[j] ^arr[i];
index = j;
// 从前向后搜索
while(i < j && arr[i] <key)
i++;
if(i == j)
break;
else
// 交换 a[i] a[j]
arr[j] = arr[j] ^arr[i];
arr[i] = arr[j] ^arr[i];
arr[j] = arr[j] ^arr[i];
index = i;
QuickSort(arr, index);
QuickSort(arr + index + 1, n - 1 - index);
// 选择排序
void SelectSort(int arr[], int n)
int i, j;
int min;
for(i = 0; i < n - 1; i++)
int index = 0;
min = arr[i];
for(j = i + 1; j < n; j++) //找出 i+1 - n 无序区的最小者与arr[i]交换
if(arr[j] < min)
min = arr[j];
index = j;
if(index != 0) //表明无序区有比arr[i]小的元素
arr[i] = arr[i]^arr[index];
arr[index] = arr[i]^arr[index];
arr[i] = arr[i]^arr[index];
程序里有几点注意的地方:
一,在程序里,交换2个数,我使用了异或来处理。这个可以根据个人喜好。为了避免产生临时变量,可以使用如下几种方式来交换2个数:
a=a^b;
b=a^b;
a=a^b;
或者
a=a+b;
b=a-b;
a=a-b;
使用第二种也挺好的。第一种异或的方式,只适用于,2个数都为int型的,a,b可以正可以负,这个没有关系,但是必须是int类型。
二, sleep()函数是包含在windows.h里面的,要加入 #include <window.h>
三, 关于随机数生成的2个函数 srand()种子发生器函数,还有rand()随机数生成器函数,自己可以参考相关文档。
四, Demo宏来控制是演示还是比较性能用的。当把N调整的很小,比如10的时候,可以设置Demo为1,那样就能打印数组了,可以看到比较前后的情况。当把N调整到很大比如10000的时候,就把Demo设置为0,那样就不打印数组,直接比较性能。
具体的算法文档参考下面的:
冒泡排序
基本概念
冒泡排序(BubbleSort)的基本概念是:依次比较相邻的两个数,将小数放在前面,大数放在后面。即在第一趟:首先比较第1个和第2个数,将小数放前,大数放后。然后比较第2个数和第3个数,将小数放前,大数放后,如此继续,直至比较最后两个数,将小数放前,大数放后。至此第一趟结束,将最大的数放到了最后。在第二趟:仍从第一对数开始比较(因为可能由于第2个数和第3个数的交换,使得第1个数不再小于第2个数),将小数放前,大数放后,一直比较到倒数第二个数(倒数第一的位置上已经是最大的),第二趟结束,在倒数第二的位置上得到一个新的最大数(其实在整个数列中是第二大的数)。如此下去,重复以上过程,直至最终完成排序。
由于在排序过程中总是小数往前放,大数往后放,相当于气泡往上升,所以称作冒泡排序。
用二重循环实现,外循环变量设为i,内循环变量设为j。外循环重复9次,内循环依次重复9,8,...,1次。每次进行比较的两个元素都是与内循环j有关的,它们可以分别用a[j]和a[j+1]标识,i的值依次为1,2,...,9,对于每一个i, j的值依次为1,2,...10-i。
产生
在许多程序设计中,我们需要将一个数列进行排序,以方便统计,而冒泡排序一直由于其简洁的思想方法而倍受青睐。
排序过程
设想被排序的数组R[1..N]垂直竖立,将每个数据元素看作有重量的气泡,根据轻气泡不能在重气泡之下的原则,从下往上扫描数组R,凡扫描到违反本原则的轻气泡,就使其向上"漂浮",如此反复进行,直至最后任何两个气泡都是轻者在上,重者在下为止。
算法示例
A[0] 、 A[1]、 A[2]、 A[3]、 A[4]、 A[5]、 A[6]:
49 38 65 97 76 13 27
第一趟冒泡排序过程
38 49 65 97 76 13 27
38 49 65 97 76 13 27
38 49 65 97 76 13 27
38 49 65 76 97 13 27
38 49 65 76 13 97 27
38 49 65 76 13 27 97 – 这是第一趟冒泡排序完的结果
第二趟也是重复上面的过程,只不过不需要比较最后那个数97,因为它已经是最大的
38 49 65 13 27 76 97 – 这是结果
第三趟继续重复,但是不需要比较倒数2个数了
38 49 13 27 65 76 97
….
选择排序
基本思想
n个记录的文件的直接选择排序可经过n-1趟直接选择排序得到有序结果:
①初始状态:无序区为R[1..n],有序区为空。
②第1趟排序
在无序区R[1..n]中选出关键字最小的记录R[k],将它与无序区的第1个记录R[1]交换,使R[1..1]和R[2..n]分别变为记录个数增加1个的新有序区和记录个数减少1个的新无序区。
……
③第i趟排序
第i趟排序开始时,当前有序区和无序区分别为R[1..i-1]和R(1≤i≤n-1)。该趟排序从当前无序区中选出关键字最小的记录 R[k],将它与无序区的第1个记录R交换,使R[1..i]和R分别变为记录个数增加1个的新有序区和记录个数减少1个的新无序区。
这样,n个记录的文件的直接选择排序可经过n-1趟直接选择排序得到有序结果。
常见的选择排序细分为简单选择排序、树形选择排序(锦标赛排序)、堆排序。上述算法仅是简单选择排序的步骤。
排序过程
A[0] 、 A[1]、 A[2]、 A[3]、 A[4]、 A[5]、 A[6]:
49 38 65 97 76 13 27
第一趟排序后 13 [38 65 97 76 49 27]
第二趟排序后 13 27 [65 97 76 49 38]
第三趟排序后 13 27 38 [97 76 49 65]
第四趟排序后 13 27 38 49 [76 97 65]
第五趟排序后 13 27 38 49 65 [97 76]
第六趟排序后 13 27 38 49 65 76 [97]
最后排序结果 13 27 38 49 49 65 76 97
快速排序算法
算法过程
设要排序的数组是A[0]……A[N-1],首先任意选取一个数据(通常选用第一个数据)作为关键数据,然后将所有比它小的数都放到它前面,所有比它大的数都放到它后面,这个过程称为一趟快速排序。一趟快速排序的算法是:
1)设置两个变量I、J,排序开始的时候:I=0,J=N-1;
2)以第一个数组元素作为关键数据,赋值给key,即 key=A[0];
3)从J开始向前搜索,即由后开始向前搜索(J=J-1),找到第一个小于key的值A[J],并与A[I]交换;
4)从I开始向后搜索,即由前开始向后搜索(I=I+1),找到第一个大于key的A[I],与A[J]交换;
5)重复第3、4、5步,直到 I=J; (3,4步是在程序中没找到时候j=j-1,i=i+1,直至找到为止。找到并交换的时候i, j指针位置不变。另外当i=j这过程一定正好是i+或j+完成的最后另循环结束)
例如:待排序的数组A的值分别是:(初始关键数据:X=49) 注意关键X永远不变,永远是和X进行比较,无论在什么位子,最后的目的就是把X放在中间,小的放前面大的放后面。
A[0] 、 A[1]、 A[2]、 A[3]、 A[4]、 A[5]、 A[6]:
49 38 65 97 76 13 27
进行第一次交换后: 27 38 65 97 76 13 49
( 按照算法的第三步从后面开始找)
进行第二次交换后: 27 38 49 97 76 13 65
( 按照算法的第四步从前面开始找>X的值,65>49,两者交换,此时:I=3 )
进行第三次交换后: 27 38 13 97 76 49 65
( 按照算法的第五步将又一次执行算法的第三步从后开始找
进行第四次交换后: 27 38 13 49 76 97 65
( 按照算法的第四步从前面开始找大于X的值,97>49,两者交换,此时:I=4,J=6 )
此时再执行第三步的时候就发现I=J,从而结束一趟快速排序,那么经过一趟快速排序之后的结果是:27 38 13 49 76 97 65,即所以大于49的数全部在49的后面,所以小于49的数全部在49的前面。
快速排序就是递归调用此过程——在以49为中点分割这个数据序列,分别对前面一部分和后面一部分进行类似的快速排序,从而完成全部数据序列的快速排序,最后把此数据序列变成一个有序的序列,根据这种思想对于上述数组A的快速排序的全过程如图6所示:
初始状态 49 38 65 97 76 13 27
进行一次快速排序之后划分为 27 38 13 49 76 97 65
分别对前后两部分进行快速排序 27 38 13 经第三步和第四步交换后变成 13 27 38 完成排序。
76 97 65 经第三步和第四步交换后变成 65 76 97 完成排序。 参考技术A 设置链表或大数组或二叉排序树等结构,存放char* 和int组成的结构体。
打开文件
按行读入,按空格分开数据并存入到链表或数组中
按名字或成绩排序(二叉排序树已经有顺序了)
写入文件,释放char *。 参考技术B 只需要将stdinf结构体中的sc改为float类型,并修改对应的fscanf()/fprintf()中的格式符即可,如下:
//---------------------------------------------------------------------------
#include <stdio.h>
#include <stdlib.h>
typedef struct
char name[80];
float sc;
stdinf;
int cmp(const void *a,const void *b)
return ((const stdinf*)b)->sc-((const stdinf *)a)->sc;
int main(void)
FILE *fp;
stdinf *sts=NULL;
int i,n;
fp=fopen("1.txt","r"); /*打开文件*/
for (n = 0; !feof(fp); n++) /*读取信息到sts数组*/
if (i) sts=(stdinf*)realloc(sts,sizeof(stdinf)*(n+1));
else sts=(stdinf*)malloc(sizeof(stdinf));
fscanf(fp,"%s %f",sts[n].name,&sts[n].sc);
fclose(fp);
qsort(sts,i,sizeof(stdinf),cmp); /*排序*/
fp=fopen("1.txt","w"); /*重新打开文件*/
for (i = 0; i<n; i++) /*写入有序信息*/
fprintf(fp,"%s %f\n",sts[i].name,sts[i].sc);
fclose(fp);
return 0;
//---------------------------------------------------------------------------本回答被提问者采纳 参考技术C 楼主看看下面的代码把 :我是按学号和姓名进行排序的!!但都是换汤不换药!!!
/* 定义按学号排序信息管理系统的函数 */
void sort_num()
int i,j,k,n=0;
char c;
struct student record[N],*p,temp;
FILE *fp;
fp=fopen("f:\\shuju.dat","r");
if(fp==NULL)
printf("\n 打开文件失败!\n");
return;
p=record;
while(feof(fp)==0)
fscanf(fp,"%23s%15s%15s\n",p->num,p->name,p->tel);
p++;
n++;
fclose(fp);
printf("\n 按升序(s),还是按降序(j)?");
c=getch();
if(c=='s'||c=='S') /* 按学号的升序排列 */
for(i=0;i<n-1;i++) /* 选择法排序 */
k=i;
for(j=i+1;j<n;j++)
if(strcmp((p+k)->num,(p+j)->num)>0)
k=j;
temp=*(p+k);
*(p+k)=*(p+i);
*(p+i)=temp;
else
if(c=='j'||c=='J') /* 按学号的降序排列 */
for(i=0;i<n-1;i++) /* 选择法排序 */
k=i;
for(j=i+1;j<n;j++)
if(strcmp((p+k)->num,(p+j)->num)<0)
k=j;
temp=*(p+k);
*(p+k)=*(p+i);
*(p+i)=temp;
else
printf("\n 非法字符!\n");
return;
fp=fopen("f:\\shuju.dat","w");
if(fp==NULL)
printf("\n 打开文件失败!\n");
return;
for(p=record;p<record+n;p++)
fprintf(fp,"%23s%15s%15s\n",p->num,p->name,p->tel);
printf("%23s%15s%15s\n",p->num,p->name,p->tel);
fclose(fp);
/* 定义按姓名排序信息管理系统的函数 */
void sort_name()
int i,j,k,n=0;
char c;
struct student record[N],*p,temp;
FILE *fp;
fp=fopen("f:\\shuju.dat","r+");
if(fp==NULL)
printf("\n 打开文件失败!\n");
return;
p=record;
while(feof(fp)==0)
fscanf(fp,"%23s%15s%15s\n",p->num,p->name,p->tel);
p++;
n++;
fclose(fp);
printf("\n 按升序(s),还是按降序(j)?");
c=getch();
if(c=='s'||c=='S') /* 按姓名的升序排列 */
for(i=0;i<n-1;i++) /* 选择法排序 */
k=i;
for(j=i+1;j<n;j++)
if(strcmp((p+k)->name,(p+j)->name)>0)
k=j;
temp=*(p+k);
*(p+k)=*(p+i);
*(p+i)=temp;
else
if(c=='j'||c=='J') /* 按姓名的降序排列 */
for(i=0;i<n-1;i++) /* 选择法排序 */
k=i;
for(j=i+1;j<n;j++)
if(strcmp((p+k)->name,(p+j)->name)<0)
k=j;
temp=*(p+k);
*(p+k)=*(p+i);
*(p+i)=temp;
else
printf("\n 非法字符!\n");
return;
fp=fopen("f:\\shuju.dat","w");
if(fp==NULL)
printf("\n 打开文件失败!\n");
return;
for(p=record;p<record+n;p++)
fprintf(fp,"%23s%15s%15s\n",p->num,p->name,p->tel);
fclose(fp);
c语言 通讯录系统 增删改查 排序 动态内存开辟及文件保存与读取
c语言 通讯录系统 动态内存开辟及文件的保存与读取
一个最基本的通讯录系统,我们要实现的基本功能包括增删改查,并要在此基础上然后在对其进行各种扩充,比如排序,以及动态开辟内存进行存储,还有实现通讯录的文件保存和从文件中将已存的联系人加载并展示出来等等。
对其进行分析,我们需要以下三个不同文件
Contact.h 声明函数
#define _CRT_SECURE_NO_WARNINGS 1
#define DEFAULT_SZ 5 //初始动态开辟五个数据的空间
#define MAX_NAME 20
#define MAX_SEX 5
#define MAX_PHONE 16
#define MAX_ADDR 30
#include <stdio.h>
#include <string.h>
#include<stdlib.h>
#include<errno.h>
enum OP_ENUM //避免魔鬼数字的出现
QUIT, //停止
ADD, //增加
DEL, //删除
SEEK, //查找
ALTER, //修改
SHOW, //显示
DELALL, //删除所有联系人
SORT, //排序
SAVE, //保存文件
;
typedef struct Info
char name[MAX_NAME];
char sex[MAX_SEX];
int age;
char phone[MAX_PHONE];
char addr[MAX_ADDR];
Info;
//通讯录类型
typedef struct Contact
struct Info *data; //存放信息
int size; //记录当前已经有的元素个数
int capacity; //当前通讯录的最大容量
Contact;
//声明函数
void InitContact(Contact *ps);//初始化通讯录
void addpeo(Contact *ps);//增加一个联系人信息
void showpeo(const Contact *ps);//打印所有联系人信息
//int findname(struct Contact *ps, char name[MAX_NAME]);//查找函数,根据姓名查找
void delpeo(Contact *ps);//调用查找函数删除指定联系人信息
void seekpeo(Contact *ps); //调用查找函数查找指定联系人信息
void alterpeo(Contact *ps); ///调用查找函数修改指定联系人信息
void sortpeo(Contact *ps); //排序通讯录联系人信息
void delall(Contact *ps); //删除所有联系人
void sortpeo(Contact *ps); //对联系人信息进行排序
void savepeo(Contact *ps); //保存数据到文件中
void LoadContact(Contact *ps); //加载文件中的信息至通讯录
Contact.c 实现函数的具体功能
这里要实现我们具体函数的功能,所以我们来定义一个Contact.c文件
Contact.c
#define _CRT_SECURE_NO_WARNINGS 1
#include<assert.h>
#include"contact.h"
void LoadContact(Contact *ps);
// 1.查找联系人的位置, static 表示只能在本程序内部使用
static int findname(const Contact *ps, char name[MAX_NAME])
int i = 0;
for (i = 0; i < ps->size; i++)
if (0 == strcmp(ps->data[i].name, name))
return i;
return -1;//找不到返回-1
void InitContact(Contact *ps)
ps->data = (struct Info*)malloc(DEFAULT_SZ * sizeof(Info));
if (ps->data == NULL)
return;
ps->size = 0;
ps->capacity = DEFAULT_SZ;
//把文件中已经存放的数据读取至通讯录中
LoadContact(ps);
void CheckCapacity(Contact *ps)
assert(ps != NULL);
if (ps->size == ps->capacity)
//增容
struct Info* ptr = realloc(ps->data, (ps->capacity + 5)*sizeof(Info));
if (ptr != NULL)
ps->data = ptr;
ps->capacity += 5;
printf("增容成功!\\n");
else
printf("增容失败!\\n");
void LoadContact(Contact *ps)
Info tmp = 0 ; //定义一个临时的空间来存放文件中读取的数据
FILE* pfread = fopen("contact.txt", "rb");
if (pfread == NULL)
printf("%s\\n", strerror(errno));
return;
//读取文件至通讯录中
while ((fread(&tmp, sizeof(Info), 1, pfread)) == 1)
CheckCapacity(ps);
ps->data[ps->size] = tmp;
ps->size++;
fclose(pfread);
pfread = NULL;
void addpeo(Contact *ps)
assert(ps != NULL);
//检测当前通讯录容量
//容量已满就增容,反之则不用理会
CheckCapacity(ps);
//增加数据
printf("请输入联系人姓名:");
scanf("%s", ps->data[ps->size].name);
printf("请输入联系人性别:");
scanf("%s", ps->data[ps->size].sex);
printf("请输入联系人年龄:");
scanf("%d", &(ps->data[ps->size].age));
printf("请输入联系人电话:");
scanf("%s", ps->data[ps->size].phone);
printf("请输入联系人地址:");
scanf("%s", ps->data[ps->size].addr);
ps->size++;
printf("添加成功\\n");
void showpeo(const Contact *ps)
if (ps->size == 0)
printf("通讯录为空\\n");
else
//打印标题
printf("%-20s\\t%-5s\\t%-3s\\t%-16s\\t%-30s\\n", "姓名", "性别", "年龄", "电话", "地址");
for (int i = 0; i < ps->size; i++)
//打印数据
printf("%-20s\\t%-5s\\t%-3d\\t%-16s\\t%-30s\\n",
ps->data[i].name,
ps->data[i].sex,
ps->data[i].age,
ps->data[i].phone,
ps->data[i].addr);
void delpeo(Contact *ps)
printf("请输入要删除的联系人姓名:");
char name[MAX_NAME];
scanf("%s", name);
//找到返回姓名所在元素下标, 找不到返回-1
int pos = findname(ps, name);
//2.删除
if (pos == -1)
printf("要删除的人不存在.\\n");
else
//删除数据
int j = 0;
for (j = pos; j <ps->size - 1; j++)
ps->data[j] = ps->data[j + 1];
ps->size--;
printf("删除成功\\n");
void seekpeo(Contact *ps)
char name[MAX_NAME];
printf("请输入要查找人的姓名:");
scanf("%s", name);
int pos = findname(ps, name);
if (pos == -1)
printf("查无此人.\\n");
else
printf("%-20s\\t%-5s\\t%-3s\\t%-16s\\t%-30s\\n", "姓名", "性别", "年龄", "电话", "地址");
//打印数据
printf("%-20s\\t%-5s\\t%-3d\\t%-16s\\t%-30s\\n",
ps->data[pos].name,
ps->data[pos].sex,
ps->data[pos].age,
ps->data[pos].phone,
ps->data[pos].addr);
void alterpeo(Contact *ps)
char name[MAX_NAME];
printf("请输入要修改人的姓名:");
scanf("%s", name);
int pos = findname(ps, name);
if (pos == -1)
printf("要修改的人不存在.\\n");
else
printf("请输入联系人姓名:");
scanf("%s", ps->data[pos].name);
printf("请输入联系人性别:");
scanf("%s", ps->data[pos].sex);
printf("请输入联系人年龄:");
scanf("%d", &(ps->data[pos].age));
printf("请输入联系人电话:");
scanf("%s", ps->data[pos].phone);
printf("请输入联系人地址:");
scanf("%s", ps->data[pos].addr);
printf("修改完成\\n");
void delall(Contact *ps)
free(ps->data); //删除所有人的的性质等同于释放data空间
ps->data = NULL;
void sortpeo(Contact *ps)
//此处使用冒泡排序,也可以使用快排
//这里也只是对其进行了简单排序,如果名字相同也可以对比年龄性别等进行二次排序,具体实现方案我也就不一一列举了
for (int i = 0; i < ps->size -1; i++)
for (int j = 0; j < ps->size - 1 - i; j++)
if (strcmp(ps->data[j].name, ps->data[j + 1].name) > 0)
Info temp = ps->data[j];
ps->data[j] = ps->data[j + 1];
ps->data[j + 1] = temp;
printf("%-20s\\t%-5s\\t%-3s\\t%-16s\\t%-30s\\n", "姓名", "性别", "年龄", "电话", "地址");
for (int i = 0; i < ps->size; i++)
//打印数据
printf("%-20s\\t%-5s\\t%-3d\\t%-16s\\t%-30s\\n",
ps->data[i].name,
ps->data[i].sex,
ps->data[i].age,
ps->data[i].phone,
ps->data[i].addr);
void savepeo(Contact *ps)
FILE* pfwrite = fopen("contact.txt", "wb");
if (pfwrite == NULL)
printf("%s\\n", strerror(errno));
return;
//将通讯录中的数据写入文件
for (int i = 0; i < ps->size; i++)
fwrite(&(ps->data[i]), sizeof(Info), 1, pfwrite);
fclose(pfwrite);
pfwrite = NULL;
test.c 进行测试
#define _CRT_SECURE_NO_WARNINGS 1
#include <stdio.h>
#include <string.h>
#include <stdlib.h>
#include <math.h>
#include <time.h>
#include <Windows.h>
#include<assert.h>
#include"contact.h"
void menu() //菜单
printf("***************************\\n");
printf(" * 1.增加联系人 \\n");
printf(" * 2.删除指定联系人 \\n");
printf(" * 3.查询联系人 \\n");
printf(" * 4.修改联系人 \\n");
printf(" * 5.显示所有联系人 \\n");
printf(" * 6.清空所有联系人 \\n");
printf(" * 7.按名字进行排序 \\n");
printf(" * 8.保存信息到文件 \\n");
printf(" * 0.退出 \\n");
printf("***************************\\n");
//
//1.此处由于showpeo()函数的形参与其他函数参数类型有所不同,所以在此使用转移表会出现warning警告
//2.其内部函数类型为void,但此处定义为void*与其不兼容也会出现warning警告
//void *(*Contact_table[])(Contact *) = NULL, addpeo, delpeo, seekpeo, alterpeo, showpeo, delall, sortpeo, savepeo ;//转移表
//
int main()
int select = 1;
Contact con; //con就是通讯录,里面包含n(不确定要录入多少个,所以用n代替) 个元素的数据和size和capacity
//初始化通讯录,
InitContact(&con);//结构体传参,传址调用
while (select)
menu();
printf("请选择:");
scanf("%d", &select);
//void *tmp = Contact_table[select](&con);
switch (select)
case ADD:
addpeo(&con);
break;
case DEL:
delpeo(&con);
break;
case SEEK:
seekpeo(&con);
break;
case ALTER:
alterpeo(&con);
break;
case SHOW:
showpeo(&con);
break;
case DELALL:
delall(&con);//销毁通讯录——释放动态开辟的内存
break;
case SORT:
sortpeo(&con);
break;
case SAVE:
savepeo(&con);
break;
case QUIT:
savepeo(&con);//退出之前也可以先执行savepeo函数保存数据,避免忘记保存而出现差错
printf("谢谢使用!\\n");
break;
default:
printf("选择错误!\\n");
break;
system("pause");
return 0;
码完这么多字已经到了凌晨一点多了,期间我回顾了很多小的知识点,不过运用的程度连熟悉可能都算不上,最多可能也只是了解,可现在是并不代表以后也是,我还是会好好努力,加油,奥里给。
努力活成别人的信仰,共勉!
以上是关于C语言实现文件排序的主要内容,如果未能解决你的问题,请参考以下文章