对文本行进行排序,新增-d(目录排序),只对字母数字空格排序(TCPL 练习5-16)

来源:互联网 发布:mysql 32位下载安装包 编辑:程序博客网 时间:2024/06/01 07:35
文本行的排序用到了命令行参数以及多级指针,在要求只对字母数字空格进行排序时,关键的问题点是兼容-f命令参数,也就是排序的同时忽略大小写。
由于在之前的练习中,我将忽略大小写的比较方法重新写了一个函数transfercmp(),于是无法再sort排序程序中同时调用他们。
因此,不得不增加一个外部变量uptolow,用来在只对字母数字排序的函数inpuntcmp()中兼容忽略大小写的排序方式。

暂时还没有想到更好的方法。


#include <stdio.h>#include <string.h>/*  编写sort函数,扩充其功能,使得函数只对空格数字和字母排序,-d为指令,还需能和-r,-f等组合使用 */#define MAXLINES 5000/*  待排序的最大行数 */char *lineptr[MAXLINES];/*指向问本行的指针 */int readlines(char *lineptr[], int nlines);void writelines(char *lineptr[], int nlines);int inpuntcmp(char *, char *);          /*  函数inpuntcmp:将忽略除空格字母数字以外的字符比较,如果某行以上三种字符都没有,则判断为最小 */char *alloc(int n);void sort(void *lineptr[], int left, int right, int (*comp)(void *, void *));int numcmp(char *, char *);int transfercmp(char *s1, char *s2);   /* 函数transfercmp:忽略大小写的按字典比较的函数,例如,认为a=A,和numcmp以及strcmp并列的选项 */static char allocbuf[10000];static char *allocp=allocbuf;int post=0,uptolow=0;/*post 为1则逆序排序;uptolow为1,忽略大小写  */main(int argc, char *argv[]){int nlines,nlines2;/*  读入的输入行数*/int numeric=0,nw=0;/*  numeric为1则以数值排序 uptolow为1则转换大小写 */while(argc-->1){if(strcmp(*++argv,"-n")==0)numeric=1;else if(strcmp(*argv,"-r")==0)post=1;else if(strcmp(*argv,"-f")==0)uptolow=1;else if(strcmp(*argv,"-d")==0)nw=1;/*  nw为1只对字母数字空格排序  */elseprintf("error: unkonwn command\n");}if((nlines=readlines(lineptr,MAXLINES))>=0) {if(nw==1){sort((void **)lineptr, post?(nlines-1):0,  post?0:(nlines-1), (int (*)(void*,void*))(inpuntcmp));writelines(lineptr,nlines);return 0;} else {if(uptolow==0)sort((void **)lineptr, post?(nlines-1):0,  post?0:(nlines-1), (int (*)(void*,void*))(numeric?numcmp:strcmp));elsesort((void **)lineptr, post?(nlines-1):0,  post?0:(nlines-1), (int (*)(void*,void*))(numeric?numcmp:transfercmp));writelines(lineptr,nlines);return 0;}}else  {printf("input too big to sort\n");return 1;}}void sort(void *v[], int left, int right, int (*comp)(void *, void *)){if(post==0) {int i, last;void swap(void *v[], int, int);if(left>=right)return;swap(v,left,(left+right)/2);last =left;for(i=left+1;i<=right;i++)if((*comp)(v[i],v[left])<0)swap(v,++last,i);swap(v,left,last);sort(v,left,last-1,comp);sort(v,last+1,right,comp);} else{int i, last;void swap(void *v[], int, int);if(left<=right)return;swap(v,left,(left+right)/2);last =left;for(i=left-1;i>=right;i--)if((*comp)(v[i],v[left])<0)swap(v,--last,i);swap(v,left,last);sort(v,left,last+1,comp);sort(v,last-1,right,comp);}}#include<stdlib.h>int numcmp(char *s1,char *s2){double v1,v2;v1=atof(s1);v2=atof(s2);if(v1<v2)return -1;else if (v1>v2)return  1;elsereturn 0;}void swap(void *v[], int i, int j) {void *temp;temp =v[i];v[i]=v[j];v[j]=temp;}#define MAXLEN 1000int getline(char *, int);int readlines(char *lineptr[], int maxlines) {int len,nlines;char *p,line[MAXLEN];nlines =0;while((len=getline(line,MAXLEN))>0)if (nlines>= maxlines || (p=alloc(len))==0)return -1;else {line[len-1]=0;strcpy(p,line);lineptr[nlines++]=p;}return nlines;}void writelines(char *lineptr[], int nlines){int i;for(i=0; i< nlines; i++)printf("%s\n",lineptr[i]);}int getline(char *s, int lim) {int i=0,c;for(; i<lim && (c=getchar()) != EOF && c!='\n';++i)*(s+i)=c;if(c=='\n') {*(s+i)=c;++i;}*(s+i)=0;return i;}char *alloc(int n) {if(allocbuf +10000-allocp>=n) {allocp +=n;return allocp - n;} elsereturn 0;}#include<ctype.h>int inpuntcmp(char *s1, char *s2){char c,d;while(*s1 !=0 && *s2!=0) {while(ispunct(*s1)) {if(*s1==0)return -1;++s1;}while(ispunct(*s2)) {if(*s2==0)return 1;++s2;}if(uptolow==1) {c=tolower(*s1);d=tolower(*s2);}else {c=*s1;d=*s2;}if(c<d)return -1;else if (c>d)return 1;++s1;++s2;}if(*s1<*s2)return -1;else if (*s1>*s2)return 1;elsereturn 0;}int transfercmp(char *s1, char *s2){char c,d;while(*s1 !=0 && *s2!=0) {c=tolower(*s1);d=tolower(*s2);if(c<d)return -1;else if (c>d)return 1;++s1;++s2;}if(*s1<*s2)return -1;else if (*s1>*s2)return 1;elsereturn 0;}