源自《The C Programming Language》P102 ex5.11及其后的pr 5-14 ... pr 5-14,代码见pr 5-16:
代码:
#include <stdio.h> #include <string.h> #define MAXLINES 5000 /*进行排序的最大文本行数*/ #define NUMERIC 1 #define DECR 2 #define IGNORE 4 #define DIR 8 //char* lineptr[MAXLINES]; /*指向文本行的指针数组*/ static int option = 0; int readLines(char* lineptr[], int maxlines); void writeLines(char* lineptr[], int nlines, int order); void myQsort(void* lineptr[], int left, int right, int (*comp) (void*, void* ), int option); int numcmp(char*, char* ); int charcmp(char*, char* ); typedef int (*PFUNC) (void*, void*); int main(int argc, char* argv[]) { int nlines; //int option; int c; char* lineptr[MAXLINES]; PFUNC pFunc; nlines = 0; //option = 0; /*本处使用的while switch语句来取命令行参数,比通过if语句来取,要简洁高效易扩展*/ while(--argc > 0 && **(++argv) == '-') /*获取命令行参数,用于操作*/ while(c = *++(*argv)) switch(c) { case 'n': option |= NUMERIC; break; case 'r': option |= DECR; break; case 'f': option |= IGNORE; break; case 'd': option |= DIR; break; default: printf("error: illegal command parameters !\n"); return -1; } if(argc) printf("Usage: sort -dfnr \n"); else if((nlines = readLines(lineptr, MAXLINES)) > 0) { if(nlines <= MAXLINES) /*进行越界判断*/ { if(option & NUMERIC) pFunc = numcmp; else pFunc = charcmp; myQsort((void** )lineptr, 0, nlines-1, pFunc, option); writeLines(lineptr, nlines, option & DECR); return 0; } else { printf("error: the lines overflow the MAXLINES\n"); return -1; } } else { printf("error: fail to get the lines of input\n"); return -1; } } #define MAXLEN 1000 /*每个输入文本行的最大长度*/ int getLine(char* line, int maxlen); char* alloc(int); /*readLines函数:读入输入行*/ int readLines(char* lineptr[], int maxlines) { int len; int nlines; char* p; char line[MAXLEN]; nlines = 0; p = NULL; while((len = getLine(line, MAXLEN)) > 0) if(nlines >= MAXLINES || !(p = alloc(len))) return -1; else { line[len-1] = '\0'; strcpy(p, line); lineptr[nlines++] = p; } return nlines; } /*writeLines函数:打印排序后的文本行*/ void writeLines(char* lineptr[], int nlines, int order) { int i; int j; i = 0; j = nlines - 1; if(order) while(i++ <= nlines - 1) printf("%s\n", lineptr[j--]); else while(nlines-- > 0) printf("%s\n", lineptr[i++]); } /*getLine:从输入终端获取一个文本行*/ int getLine(char* line, int maxlen) { int i; int c; for(i = 0; i < maxlen-1 && (c = getchar()) != EOF && c != '\n'; ++i) line[i] = c; if(c == '\n') line[i++] = c; line[i] = '\0'; return i; } /*myQsort函数:快速排序,按照递增顺序对lineptr[left]...lineptr[right]进行排序 传递comp函数指针,可以处理任何数据类型的排序,而不仅仅是字符串*/ void myQsort(void* lineptr[], int left, int right, int (*comp) (void*, void*), int option) { int last; int i; void swap(void* v[], int i, int j); if(left >= right) /*如果数组元素的个数少于2,则返回*/ return; swap(lineptr, left, (left + right) / 2); last = left; for(i = left+1; i <= right; ++i) if(!(option & DECR)) { if((*comp)(lineptr[i], lineptr[left]) < 0) swap(lineptr, ++last, i); } else if((*comp)(lineptr[i], lineptr[left]) > 0) swap(lineptr, ++last, i); swap(lineptr, left, last); myQsort(lineptr, left, last - 1, comp, option); myQsort(lineptr, last + 1, right, comp, option); } /*swap函数:交换字符指针数组的两个元素*/ void swap(void* v[], int i, int j) { void* tmp; tmp = v[i]; v[i] = v[j]; v[j] = tmp; } #include <stdlib.h> #include <ctype.h> #include <math.h> int numcmp(char* s1, char* s2) { double v1; double v2; v1 = atof(s1); v2 = atof(s2); if(v1 < v2) return -1; else if(v1 > v2) return 1; else return 0; } /*charcmp:可以处理忽略大小写及目录序列这两种情况的字符串之间的比较*/ int charcmp(char*s ,char* t) { char a; char b; int ignore; int dir; ignore = (option & IGNORE) ? 1 : 0; dir = (option & DIR) ? 1 : 0; do { if(dir) { while(!isalnum(*s) && *s != ' ' && *s != '\0') ++s; while(!isalnum(*t) && *t != ' ' && *t != '\0') ++t; } a = ignore ? tolower(*s) : *s; ++s; b = ignore ? tolower(*t) : *t; ++t; if(a == b && a == '\0') /*a == '\0':没有理解?*/ return 0; }while(a == b); return a - b; } #define ALLOCSIZE 10000 static char allocbuf[ALLOCSIZE]; static char* allocp = allocbuf; /*alloc函数:从自定义的缓冲区中分配长度为n字节的空间*/ char* alloc(int n) { if(allocbuf + ALLOCSIZE - allocp >= n) { allocp += n; return allocp - n; } else return 0; }
分析:1,设计流程:
(a) 通过变量option来收集命令行中的所有命令,以供下面排序使用;
(b) 通过函数readLines将输入中所有行存储起来;
(c) 通过函数myQsort对所有的输入按照命令行参数进行排序;
(d) 通过函数writeLines对排序后的输入打印输出;
2,在获取option的值时,采用上述代码中的while switch-case语句组合在可读性及扩展性上优于使用if-else语句,
while switch-case版本:
while(--argc > 0 && **(++argv) == '-') /*获取命令行参数,用于操作*/ while(c = *++(*argv)) switch(c) { case 'n': option |= NUMERIC; break; case 'r': option |= DECR; break; case 'f': option |= IGNORE; break; case 'd': option |= DIR; break; default: printf("error: illegal command parameters !\n"); return -1; }
if-else版本:if(argc == 2 && strcmp(*(argv+1), "-n") == 0) numeric = 1; if(argc == 2 && strcmp(*(argv+1), "-r") == 0) direction = NEGETIVE; if(argc == 2 && (strcmp(*(argv+1), "-rn") == 0 || strcmp(*(argv+1), "-nr") == 0)) { numeric = 1; direction = NEGETIVE; } if(argc == 3 && ((strcmp(*(argv+1), "-n") == 0 && strcmp(*(argv+2), "-r") == 0) || (strcmp(*(argv+1), "-r") == 0 && strcmp(*(argv+2), "-n") == 0) ) ) { numeric = 1; direction = NEGETIVE; }
3,获取输入字符串的函数readLines:通过p = alloc(len)给长度为len的字符串分配相应的空间,通过strcpy(p, line);及lineptr[nlines++] = p;函数将字符串从局部变量line字符数组中拷贝到p所指的空间中,并使指针lineptr[nlines]指向本字符串。
函数alloc:本函数是自定义的动态内存分配函数,简单,易懂,可行(当然输入量特别大时除外)。
通过命令行参数对输入进行排序
最新推荐文章于 2021-05-23 11:15:48 发布