> 文档中心 > 100 Days of Code-day35-灵活排序(集大成于一体)

100 Days of Code-day35-灵活排序(集大成于一体)


Add a field handling capablity, so sorting may be done on the fields within lines,each field sorted according to an independent set of options. ( The index for the K&R Book was sorted with -df for the index category and -n for page number

#include#include#include#define NUMERIC  1 /* numeric sort */#define DECR 2 /* sort in decreasing order */#define FOLD 4 /* fold upper and lower case */#define MDIR 8 /* directory order */#define LINES 100 /* maximum number of lines to be sorted */#define MaxLen 100int charcmp(char *, char *);void error(char *);int numcmp(char *, char *);void readargs(int argc, char *argv[]);int readlines(char *lineptr[], int maxlines);void myqsort(void *v[], int left, int right, int(*comp)(void *, void *));void writelines(char *lineptr[], int nlines, int order);int option = 0;int pos1 = 0; /* field begining with pos 1 */int pos2 = 0;  /* ending just before pos 2 *///那么在这个例子中pos1就是排序字段的起始位置,而pos2就是排序字段的结束位置/* Sort input line */int main(int argc, char *argv[]){char *lineptr[LINES]; /* pointer to text lines */int nlines;  /* number of input lines read */int rc = 0;scanf("%d\n", &argc);for (int i = 1; i < argc; i++){argv[i] = (char *)malloc(MaxLen * sizeof(char));scanf("%s", argv[i]);}getchar();readargs(argc, argv);if ((nlines = readlines(lineptr, LINES)) > 0){if (option & NUMERIC)myqsort((void **)lineptr, 0, nlines - 1, (int(*)(void *, void *))numcmp);elsemyqsort((void **)lineptr, 0, nlines - 1, (int(*)(void *, void *))charcmp);writelines(lineptr, nlines, option & DECR);}else{printf("input too big to sort \n");rc = -1;}return rc;}/* readargs: read programs argument */void readargs(int argc, char *argv[]){int c;int atoi(char *);while (--argc > 0 && (c = (*++argv)[0]) == '-' || c == '+'){//如果输入的参数的第一个字符为'-',或者为'+'if (c == '-' && !isdigit(*(argv[0] + 1)))//首先确定该字符为'-',如果是,那么与此同时看接下来的字符是否为数字while (c = *++argv[0])//如果不是,那么就要根据相应的命令字符,决定具体的排序方式switch (c){case 'd': /* directory order */option |= MDIR;break;case 'f':/* fold upper and lower */option |= FOLD;break;case 'n':/* numeric sort */option |= NUMERIC;break;case 'r':option |= DECR;break;default:printf("sort: illegal option %c \n", c);error("Usage: sort -dfnr [+pos1] [-pos2]");break;}else if (c == '-')//如果'-'之后是数字,将其设置为排序字段的结束位置pos2 = atoi(argv[0] + 1);else if ((pos1 = atoi(argv[0] + 1)) < 0)  //当输入参数的第一个字符为'+'时,将其设置为排序字段的起始位置error("Usage: sort -dfnr [+pos1][-pos2]");//并且看之后的字符是否小于0,如果小于就报错}if (argc || pos1 > pos2)//退出的时候,argc必须等于0,并且起始位置pos1不能大于pos2error("Usage: sort -dfnr [+pos1] [-pos2]");}/* The source file numcmp.c */#include#include#include#define MAXSTR 100void substr(char *s, char *t, int maxstr);/* numcmp: compare s1 and s2 numerically *///由于此时传入的字符串s1,s2并不是像之前一样,只包含数字,或者只包含大小写字母//那么根据题目的要求,根据行内的不同字段进行排序,那么如果进行数字排序,那么我们就需要从每个字符串中//抽取出我们想要的那段只含有数字的子字符串(substring),然后对其进行比较。int numcmp(char *s1, char *s2){double v1, v2;char str[MAXSTR];//用来存储从源字符串s1,s2中抽取出来的子字符串//子字符串可能越界吗???//现在我们不能像之前直接将字符串转化为对应的数字,因为现在的字符串已经不是“单纯”的数字字符串//此时有两个选择//第一个,修改atof函数的调用接口,新增加两个参数,分别是排序字段的起始位置pos1和结束位置pos2//第二个,新增加一个函数提取出子字符串,然后用atof函数将该子字符串转化为对应的数字//相较之下,第二个选择更为简便,因为对于像atof这样常用的函数的调用接口,如果对其修改会带来许多问题//这样即使解决了问题,也会使得程序变得更为冗长复杂substr(s1, str, MAXSTR);v1 = atof(str);substr(s2, str, MAXSTR);v2 = atof(str);if (v1 < v2)return -1;else if (v1 > v2)return 1;elsereturn 0;}#define FOLD 4 /* fold upper and lower cases */#define MDIR 8 /* directory order *//* charcmp: return < 0 if s 0 if s > t */int charcmp(char *s, char *t)//为什么输入换行符会报错,a和b变量未被初始化,在输入换行符时。{//增加了字段处理功能,这使得charcmp可以根据输入命令以及相应限定范围内的子字符串,对源字符串进行排序char a, b;int i, j, endpos;extern int option, pos1, pos2;int fold = (option & FOLD) ? 1 : 0;int dir = (option & MDIR) ? 1 : 0;i = j = pos1;if (pos2 > 0)endpos = pos2;else if ((endpos = strlen(s)) > strlen(t))endpos = strlen(t);do{if (dir){while (i < endpos && !isalnum(s[i]) && s[i] != ' ' && s[i] != '\0')s[i] != ' ' && s[i] != '\0';i++;while (j < endpos && !isalnum(t[j]) && t[j] != ' ' && t[j] != '\0')t[j] != ' ' && t[j] != '\0';j++;}if (i < endpos && j < endpos)//当两字符串均小于排序字段的结束位置时,对它们的各字符进行逐一比较{a = fold ? tolower(s[i]) : s[i];i++;b = fold ? tolower(t[j]) : t[j];j++;if (a == b && a == '\0')return 0;}} while (a == b && i < endpos && j < endpos);return a - b;}/* The source file substr.c */#includevoid error(char *);/* substr: get a substring of S and put in str */void substr(char *s, char *str,int maxstr){int i, j, len;extern int pos1, pos2;len = strlen(s);if (pos2 > 0 && len > pos2)//当排序字段的结束位置大于0,且字符串的长度超出结束位置限制范围len = pos2;//忽略超出范围的字符else if (pos2 > 0 && len < pos2)//但如果其长度小于结束位置,那么该程序就没有继续进行下去的必要了,直接停止error("substr: string too short");for (j = 0, i = pos1; i < len && len < maxstr + pos1; i++, j++)str[j] = s[i];str[j] = '\0';}/* error: print error message and exit */void error(char *s){printf("%s \n", s);exit(1);}void swap(void *v[], int i, int j){void *temp;temp = v[i];v[i] = v[j];v[j] = temp;}/* myqsort: sort v[left] ... v[right] into increasing order */void myqsort(void *v[], int left, int right, int(*comp)(void *, void *)){int i, last;void swap(void *v[], int, int);if (left >= right)  /* do nothing if array contains */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);myqsort(v, left, last - 1, comp);myqsort(v, last + 1, right, comp);}#define MAXLEN 1000  /* max length of any input line  */int mgetline(char *, int);char *alloc(int);/* readlines: read input lines */int readlines(char *lineptr[], int maxlines){int len, nlines;char *p, line[MAXLEN];nlines = 0;while ((len = mgetline(line, MAXLEN)) > 0)if (nlines >= maxlines || (p = alloc(len)) == NULL)return -1;else{line[len - 1] = '\0'; /* delete newline */strcpy(p, line);lineptr[nlines++] = p;}return nlines;}/* writelines: write output lines *//* writelines: write output lines */void writelines(char *lineptr[], int nlines, int decr){int i;if (decr) /* print in decreasing order */for (i = nlines - 1; i >= 0; i--)printf("%s\n", lineptr[i]);elsefor (i = 0; i < nlines; i++)printf("%s\n", lineptr[i]);}#define ALLOCSIZE 10000   /* size of available space */static char allocbuf[ALLOCSIZE]; /* storage for alloc */static char *allocp = allocbuf;  /* next free position */char *alloc(int n)   /* return pointer to n characters */{if (allocbuf + ALLOCSIZE - allocp >= n){allocp += n;return allocp - n; /* old p */}else    /* not enough room */return 0;}void afree(char *p)  /* free storage pointed to by p */{if (p >= allocbuf && p < allocbuf + ALLOCSIZE)allocp = p;}/* mgetline: read a line into s,return length */int mgetline(char *s, int lim){int c, i;for (i = 0; i < lim - 1 && (c = getchar()) != EOF && c != '\n'; ++i)s[i] = c;if (c == '\n'){s[i] = c;++i;}s[i] = '\0';return i;}

医疗百科