一个身份证号码为顺序,将两个电话号码文件合并的问题.(100分)
我有几个文本文件:zonghe1.txt和zonghe2.txt
zonghe1.txt
Name IDNo. dianhuaNo. Home job
wefef 410305198303254025 0625-4512811 。。。
sdsdf 610906198602034426 0388-6452787 。。。
cvds 910545198701126658 0658-1452145 。。。
cvxcv 320145198805054468 0451-5785485 。。。
... ...... ... ..
zonghe1.txt
ffdgdfg IDNo. dianhuaNo. Home job
fgdf 521305198412054025 0545-4512587 。。。
xvxcv 985142198011154488 0315-6458457 。。。ewfewf 112564198701126145 0525-1454145 。。。
dewfew 652302198805051458 0427-5452452 。。。
... ...... ..... ..
我的课程设计的一个小的部分.这又不是数据库.怎么排序?又要合并生成一个新的文件.IDNo.是顺序排列的。用C语言能不能实现?我们一个小组都不是很会c语言.不知道是什么回事.小组长问过指导老师了,老师说:用队列.让我们看书.随便讲了一堆.问我们懂不懂?都不明白.我们女生又不好意思再去问.我们班男生也是不会.
我是新人,让大家照顾了,不好意思了,我们其实也不是很会c语言.给我们把这个环节用队列给做出来吧.我们时间也不多了,全靠大家了.
还有,我们其他步骤都没有问题.这个环节如何在c里面实现.简单一点吧.
能实现就行.(注明:这是c的程序设计.有几个男生从网上抄c++代码,昨天被骂,c++和c是怎么让老师看出来的,我们也不知道,希望前辈多多指点,用简单的,看上去是我们可以完成的,我们不想让老师骂.)
[解决办法]
队列的定义及基本运算:http://student.zjzk.cn/course_ware/data_structure/web/zhanhuoduilie/zhanhuoduilie3.2.1.htm
顺序队列
http://student.zjzk.cn/course_ware/data_structure/web/zhanhuoduilie/zhanhuoduilie3.2.2.1.htm
链队列
http://student.zjzk.cn/course_ware/data_structure/web/zhanhuoduilie/zhanhuoduilie3.2.3.htm
[解决办法]
#include <stdio.h>
#include <stdlib.h>
#define MAX 100 //每个文件中最多的记录数
struct stu
{
char name[20];
char IDNo[20];
char dianhuaNo[16];
/*如果有其他成员,类似如上添加即可*/
};
typedef struct stu elemType;
/************************************************************************/
/* 以下是关于队列链接存储操作的6种算法 */
/************************************************************************/
struct sNode{
elemType data; /* 值域 */
struct sNode *next; /* 链接指针 */
};
struct queueLK{
struct sNode *front; /* 队首指针 */
struct sNode *rear; /* 队尾指针 */
};
/* 1.初始化链队 */
void initQueue(struct queueLK *hq)
{
hq-> front = hq-> rear = NULL; /* 把队首和队尾指针置空 */
return;
}
/* 2.向链队中插入一个元素x */
void enQueue(struct queueLK *hq, elemType x)
{
/* 得到一个由newP指针所指向的新结点 */
struct sNode *newP;
newP = (struct sNode *)malloc(sizeof(struct sNode));
if(newP == NULL){
printf( "内存空间分配失败! ");
exit(1);
}
/* 把x的值赋给新结点的值域,把新结点的指针域置空 */
newP-> data = x;
newP-> next = NULL;
/* 若链队为空,则新结点即是队首结点又是队尾结点 */
if(hq-> rear == NULL){
hq-> front = hq-> rear = newP;
}else{ /* 若链队非空,则依次修改队尾结点的指针域和队尾指针,使之指向新的队尾结点 */
hq-> rear = hq-> rear-> next = newP; /* 注意赋值顺序哦 */
}
return;
}
/* 3.从队列中删除一个元素 */
elemType outQueue(struct queueLK *hq)
{
struct sNode *p;
elemType temp;
/* 若链队为空则停止运行 */
if(hq-> front == NULL){
printf( "队列为空,无法删除! ");
exit(1);
}
temp = hq-> front-> data; /* 暂存队尾元素以便返回 */
p = hq-> front; /* 暂存队尾指针以便回收队尾结点 */
hq-> front = p-> next; /* 使队首指针指向下一个结点 */
/* 若删除后链队为空,则需同时使队尾指针为空 */
if(hq-> front == NULL){
hq-> rear = NULL;
}
free(p); /* 回收原队首结点 */
return temp; /* 返回被删除的队首元素值 */
}
/* 4.读取队首元素 */
elemType peekQueue(struct queueLK *hq)
{
/* 若链队为空则停止运行 */
if(hq-> front == NULL){
printf( "队列为空,无法删除! ");
exit(1);
}
return hq-> front-> data; /* 返回队首元素 */
}
/* 5.检查链队是否为空,若为空则返回1, 否则返回0 */
int emptyQueue(struct queueLK *hq)
{
/* 判断队首或队尾任一个指针是否为空即可 */
if(hq-> front == NULL){
return 1;
}else{
return 0;
}
}
/* 6.清除链队中的所有元素 */
void clearQueue(struct queueLK *hq)
{
struct sNode *p = hq-> front; /* 队首指针赋给p */
/* 依次删除队列中的每一个结点,最后使队首指针为空 */
while(p != NULL){
hq-> front = hq-> front-> next;
free(p);
p = hq-> front;
} /* 循环结束后队首指针已经为空 */
hq-> rear = NULL; /* 置队尾指针为空 */
return;
}
int main()
{
struct queueLK q1, q2;
struct stu s[MAX], tmp;
int i=0, j, len, flag=1;
/*这里操作文件1,读取记录,排序,然后插入队列*/
FILE *fp=fopen( "1.txt ", "r ");
fscanf(fp, "%s%s%s ", s[i].name, s[i].IDNo, s[i].dianhuaNo);
while(!feof(fp)) //读取记录
{
fscanf(fp, "%s%s%s ", s[i].name, s[i].IDNo, s[i].dianhuaNo);
//printf( "%s, %s, %s\n ", s[i].name, s[i].IDNo, s[i].dianhuaNo);
i++;
}
len=i;
for(i=0; i <len-1; i++) //排序
for(j=i+1; j <len; j++)
{
if(strcmp(s[i].IDNo, s[j].IDNo)> 0)
{
tmp=s[i];
s[i]=s[j];
s[j]=tmp;
}
}
initQueue(&q1);
for(i=0; i <len; i++) //插入队列
enQueue(&q1, s[i]),printf( "%s, %s, %s\n ", s[i].name, s[i].IDNo, s[i].dianhuaNo);
fclose(fp);
/*这里操作文件1,读取记录,排序,然后插入队列*/
fp=fopen( "2.txt ", "r ");
i=0;
fscanf(fp, "%s%s%s ", s[i].name, s[i].IDNo, s[i].dianhuaNo);
while(!feof(fp)) //读取记录
{
fscanf(fp, "%s%s%s ", s[i].name, s[i].IDNo, s[i].dianhuaNo);
//printf( "%s, %s, %s\n ", s[i].name, s[i].IDNo, s[i].dianhuaNo);
i++;
}
len=i;
for(i=0; i <len-1; i++) //排序
for(j=i+1; j <len; j++)
{
if(strcmp(s[i].IDNo, s[j].IDNo)> 0)
{
tmp=s[i];
s[i]=s[j];
s[j]=tmp;
}
}
initQueue(&q2);
for(i=0; i <len; i++) //插入队列
enQueue(&q2, s[i]),printf( "%s, %s, %s\n ", s[i].name, s[i].IDNo, s[i].dianhuaNo);
fclose(fp);
/*开始合并*/
fp=fopen( "data.txt ", "w ");
fprintf(fp, "%s\t%s\t\t\t%s ", "Name ", "IDNo ", "dianhuaNo ");
struct stu s1=outQueue(&q1), s2=outQueue(&q2);
while(!emptyQueue(&q1) && !emptyQueue(&q2))
{
if(strcmp(s1.IDNo, s2.IDNo) <0)
{
fprintf(fp, "\n%s\t%s\t%s ", s1.name, s1.IDNo, s1.dianhuaNo);
s1=outQueue(&q1);
}
else
{
fprintf(fp, "\n%s\t%s\t%s ", s2.name, s2.IDNo, s2.dianhuaNo);
s2=outQueue(&q2);
}
}
if(!emptyQueue(&q1))
fprintf(fp, "\n%s\t%s\t%s ", s1.name, s1.IDNo, s1.dianhuaNo);
else
fprintf(fp, "\n%s\t%s\t%s ", s2.name, s2.IDNo, s2.dianhuaNo);
while(!emptyQueue(&q1))
{
s1=outQueue(&q1);
if(strcmp(s1.IDNo, s2.IDNo)> 0 && flag)
{
flag = 0;
fprintf(fp, "\n%s\t%s\t%s ", s2.name, s2.IDNo, s2.dianhuaNo);
}
fprintf(fp, "\n%s\t%s\t%s ", s1.name, s1.IDNo, s1.dianhuaNo);
}
while(!emptyQueue(&q2))
{
s2=outQueue(&q2);
if(strcmp(s1.IDNo, s2.IDNo) <0 && flag)
{
flag = 0;
fprintf(fp, "\n%s\t%s\t%s ", s1.name, s1.IDNo, s1.dianhuaNo);
}
fprintf(fp, "\n%s\t%s\t%s ", s2.name, s2.IDNo, s2.dianhuaNo);
}
system( "PAUSE ");
return 0;
}
[解决办法]
测试文件内容:
1.txt:
Name IDNo dianhuaNo
wefef 410305198303254025 0625-4512811
sdsdf 610906198602034426 0388-6452787
cvds 910545198701126658 0658-1452145
cvxcv 320145198805054468 0451-5785485
2.txt:
NAME IDNo dianhuaNo
fgdf 521305198412054025 0545-4512587
xvxcv 985142198011154488 0315-6458457
ewfewf 112564198701126145 0525-1454145
dewfew 652302198805051458 0427-5452452
结果为data.txt:
NameIDNodianhuaNo
ewfewf1125641987011261450525-1454145
cvxcv3201451988050544680451-5785485
wefef4103051983032540250625-4512811
fgdf5213051984120540250545-4512587
sdsdf6109061986020344260388-6452787
dewfew6523021988050514580427-5452452
cvds9105451987011266580658-1452145
xvxcv9851421980111544880315-6458457
[解决办法]
#include <stdio.h>
#include <stdlib.h>
#define MAX 100 //文件中最多的记录数
struct stu
{
char name[20];
char IDNo[20];
char dianhuaNo[16];
/*如果有其他成员,类似如上添加即可*/
};
int main()
{
struct stu s[MAX], tmp;
int i=0, j, len;
/*这里操作文件1,读取记录*/
FILE *fp=fopen( "1.txt ", "r ");
fscanf(fp, "%s%s%s ", tmp.name, tmp.IDNo, tmp.dianhuaNo);
while(!feof(fp)) //读取记录
{
fscanf(fp, "%s%s%s ", s[i].name, s[i].IDNo, s[i].dianhuaNo);
//printf( "%s, %s, %s\n ", s[i].name, s[i].IDNo, s[i].dianhuaNo);
i++;
}
fclose(fp);
/*这里操作文件2,读取记录*/
fp=fopen( "2.txt ", "r ");
fscanf(fp, "%s%s%s ", s[i].name, s[i].IDNo, s[i].dianhuaNo);
while(!feof(fp)) //读取记录
{
fscanf(fp, "%s%s%s ", s[i].name, s[i].IDNo, s[i].dianhuaNo);
//printf( "%s, %s, %s\n ", s[i].name, s[i].IDNo, s[i].dianhuaNo);
i++;
}
len=i;
for(i=0; i <len-1; i++) //排序
for(j=i+1; j <len; j++)
{
if(strcmp(s[i].IDNo, s[j].IDNo)> 0)
{
tmp=s[i];
s[i]=s[j];
s[j]=tmp;
}
}
for(i=0; i <len; i++)
printf( "%s, %s, %s\n ", s[i].name, s[i].IDNo, s[i].dianhuaNo);
fclose(fp);
fp = fopen( "data.txt ", "w ");
fprintf(fp, "%s\t%s\t\t\t%s ", "Name ", "IDNo ", "dianhuaNo ");
for(i=0; i <len; i++)
fprintf(fp, "\n%s\t%s\t%s ", s[i].name, s[i].IDNo, s[i].dianhuaNo);
system( "PAUSE ");
return 0;
}
直接数组排序,
简单明了啊 ...
搞什么队列,
郁闷 ········
测试文件内容:
1.txt:
Name IDNo dianhuaNo
wefef 410305198303254025 0625-4512811
sdsdf 610906198602034426 0388-6452787
cvds 910545198701126658 0658-1452145
cvxcv 320145198805054468 0451-5785485
2.txt:
NAME IDNo dianhuaNo
fgdf 521305198412054025 0545-4512587
xvxcv 985142198011154488 0315-6458457
ewfewf 112564198701126145 0525-1454145
dewfew 652302198805051458 0427-5452452
结果为data.txt:
Name IDNo dianhuaNo
ewfewf 112564198701126145 0525-1454145
cvxcv 320145198805054468 0451-5785485
wefef 410305198303254025 0625-4512811
fgdf 521305198412054025 0545-4512587
sdsdf 610906198602034426 0388-6452787
dewfew 652302198805051458 0427-5452452
cvds 910545198701126658 0658-1452145
xvxcv 985142198011154488 0315-6458457
[解决办法]
可以不用数组与队列:
struct Node{
char name[20];
char id[20];
char tel[16];
};
bool To1(const char *fname1,const char *fname2,const char *fname3)
{
FILE *f1,*f2,*fo;
if((f1=fopen(fname1, "r "))!=fok)return false;
if((f2=fopen(fname2, "r "))!=fok){
fclose(f1);return false;}
if((fo=fopen(fname3, "w "))!=fok){
fclose(f1);fclose(f2);return false;}
bool k1=true,k2=true;
struct Node d1,d2;
int n = sizeof(struct Node);
if(k1)fread(f1,&d1,n,1);
if(k2)fread(f2,&d2,n,1);
if(feof(f1))k1=false;
if(feof(f2))k2=false;
while(k1||k2){
int key = strcmp(d1.id,d2.id);
if(key <0){
fwrite(fo,&d1,n,1);
if(k1){
fread(f1,&d1,n,1);
if(feof(f1))k1=false;continue;}
else{
do{
fwrite(fo,&d2,n,1);
fread(f2,&d2,n,1);}while(!feof(f2));
break;}
else if(key==0){
fwrite(fo,&d1,n,1);fwrite(fo,&d2,n,1);
fread(f1,&d1,n,1);fread(f2,&d2,n,1);
if(feof(f1))k1=false;
if(feof(f2))k2=false;}
else {
fwrite(fo,&d2,n,1);
if(k2){
fread(f2,&d2,n,1);
if(feof(f2))k2=false;continue;}
else{
do{
fwrite(fo,&d1,n,1);
fread(f2,&d1,n,1);}while(!feof(f1));
break;}
};
fclose(f1);fclose(f2);
fclose(fo);
return true;
}
int main()
{
char f1[80]={0},f2[80]={0},f3[80]={0};
printf( "输入要合并的文件名,中间用空格隔开:\n ");
scanf( "%s%s ",f1,f2);
printf( "输入合成后的文件名\n ");
scanf( "%s ",f3);
To1(f1,f2,f3);
return 0;
}
[解决办法]
哈,忘了看源数据是未排序的啦,加个用于文件格式排列程序就行了。
bool sort(const char *fname)
{
FILE* fi = fopen(fname, "rw ");
if(fi==0)return false;
struct Node d1,d2;
int num,n=sizeof(struct Node);
fseek(fi,0,2);
num = ftell(fi)/n;
for(int i=0;i <num-1;i++){
fseek(fi,i*n,0);
fread(&d1,n,1,fi);
for(int j=i+1;j <num;j++){
fread(&d2,n,1,fi);
if(strcmp(d2.id,d1.id)> 0){
fseek(fi,i*n,0);
fwrite(&d2,n,1,fi);
fseek(fi,j*n,0);
fwrite(&d1,n,1,fi);
strcpy(d1.name,d2.name);
strcpy(d1.id,d2.id);
strcpy(d1.tel,d2.tel);}}}
fclose(fi);
return true;
}
[解决办法]
不知你这个对效率有没有要求?
如果数据量不大,算法倒也无所谓。
但是选最优算法的话,“基数排序”算是最好的了,(如果文件比较大,可以先各个文件排完序,再进行合并排序;否则将所有数据读入内存后再基数排序)
为什么先基数排序:
1、基数排序的时间是线性的(即O(n));
2、此排序的列为0~9的字符,只要定义10个桶即可;
3、排序的列等长,不会对一些记录作无效处理,效率没有任何损失;
此等情况不用基数排序再也没有更好的场景了!
参考:
http://student.zjzk.cn/course_ware/data_structure/web/paixu/paixu8.6.2.htm
