C程序设计语言 (第二版) 练习 5-15

练习 5-15 增加选项-f,使得排序过程不考虑字母大小写之间的区别。例如,比较a和A时认为它们相等。

注意:代码在win32控制台运行,在不同的IDE环境下,有部分可能需要变更。
IDE工具:Visual Studio 2010

 

代码块:
#include <stdio.h>
#include <stdlib.h>
#include <string.h>
#include <ctype.h>

#define MAXLINES 5000
#define MAXLEN 1000
#define ALLOCSIZE 10000

static char allocbuf[ALLOCSIZE];
static char *allocp = allocbuf;

char *alloc(int n){
	if(allocbuf + ALLOCSIZE - allocp >= n){
		allocp += n;
		return allocp - n;
	}
	else{
		return 0;
	}
}

void afree(char *p){
	if(p >= allocbuf && p < allocbuf + ALLOCSIZE){
		allocp = p;
	}
}

char *lineptr[MAXLINES];

int getline(char *s, int lim){
	int c;
	char *t = s;

	while(--lim > 0 && (c = getchar()) != EOF && c != '\n'){
		*s++= c;
	}
	if(c == '\n'){
		*s++ = c;
	}
	*s = '\0';
	return s - t;
}

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)) == NULL){
			return -1;
		}
		else{
			line[len-1] = '\0';
			strcpy(p, line);
			lineptr[nlines++] = p;
		}
	}
	return nlines;
}

void writelines(char *lineptr[], int nlines){
	while(nlines-- > 0){
		printf("%s\n", *lineptr++);
	}
}

void swap(void *v[], int i, int j){
	void *temp;
	temp = v[i];
	v[i] = v[j];
	v[j] = temp;
}

int numcmp(const void *s1, const void *s2){
	double v1, v2;
	v1 = atof(*(const char **)s1);
	v2 = atof(*(const char **)s2);
	if(v1 < v2){
		return -1;
	}
	else if(v1 > v2){
		return 1;
	}
	else{
		return 0;
	}
}

void toLowerCase(char *newstr, char *str) {
    int i;

	for(i = 0; str[i] != '\0'; i++){
		if(isupper(str[i])){
			newstr[i] = tolower(str[i]);
		}
		else{
			newstr[i] = str[i];
		}
	}

	newstr[i] = '\0';
}

void qsort(void *v[], int left, int right, int(*comp)(const void*, const void*), int sign){
	int i, last;

	if(left >= right){
		return;
	}

	swap(v, left, (left + right) / 2);
	last = left;
	for(i = left + 1; i <= right; i++){
		if(sign == 0){
			if((*comp)(v[i], v[left]) < 0){
				swap(v, ++last, i);
			}
		}
		if(sign == 1){
			if((*comp)(v[i], v[left]) > 0){
				swap(v, ++last, i);
			}
		}
		if(sign == 2){
			char t1[80], t2[80];
			toLowerCase(t1, (char*)v[i]);
			toLowerCase(t2, (char*)v[left]);
			if((*comp)(t1, t2) < 0){
				swap(v, ++last, i);
			}
		}
	}
	swap(v, left, last);
	qsort(v, left, last - 1, comp, sign);
	qsort(v, last + 1, right, comp, sign);
}

int main(int argc, char *argv[]){
	int nlines;
	int numeric = 0;
	int sign = 0;

	if(argc > 1){
		if(strcmp(argv[1], "-n") == 0){
			numeric = 1;
			sign = 0;
		}
		if(strcmp(argv[1], "-n") == 0 && strcmp(argv[2], "-r") == 0){
			numeric = 1;
			sign = 1;
		}
		if(strcmp(argv[1], "-f") == 0){
			numeric = 1;
			sign = 2;
		}
	}

	if((nlines = readlines(lineptr, MAXLINES)) >= 0){
		qsort((void**)lineptr, 0, nlines - 1, (numeric ? numcmp : (int (*)(const void *,const void *))strcmp), 2);
		writelines(lineptr, nlines);
		system("pause");
		return 0;
	}
	else{
		printf("Error: input too big to sort!\n");
		system("pause");
		return 1;
	}

	system("pause");
	return 0;
}
01-13 08:39