C - Writing quick sort procedure with optional argument

分享一个大牛的人工智能教程。零基础!通俗易懂!风趣幽默!希望你也加入到人工智能的队伍中来!请点击人工智能教程

/*
 * Writing quick sort procedure with optional argument:
 *   -r : Sorting in reverse (decreasing) order
 *   -n : Sort the input lines numerically
 *   -f : Fold upper and lower case together
 *   -d : Make comparisons only on letters, numbers and blanks
 *
 * QuickSortWithArgument.c - by FreeMan
 */

#include <stdio.h>
#include <stdlib.h>
#include <string.h>
#include <ctype.h>

int getline(char *, int);
char *alloc(int);
int readlines(char **, int);
void writelines(char **, int);
void quicksort(void **, int, int, int (*)(void *, void *));
int numcmp(char *, char *);
int mystrcmp(char *, char *);

#define MAXLINES 10000
#define MAXLEN 1000

char *lineptr[MAXLINES];  /* Pointers to text lines */
int decreasing = 0;       /* 0 if increasing, 1 if decreasing   -r flag */
int numeric = 0;          /* 1 if numeric sort   -n flag */
int fold = 0;             /* 1 if not case-sensitive   -f flag */
int directory = 0;        /* 1 if directory sort   -d flag */

int main(int argc, char *argv[])
{
	int nlines, i;

	while (--argc > 0)
	{
		++argv;
		if ((*argv)[0] == '-')
		{
			for (i = 1; (*argv)[i]; ++i)
			{
				switch ((*argv)[i])
				{
				case 'n':
					numeric = 1;
					break;
				case 'f':
					fold = 1;
					break;
				case 'r':
					decreasing = 1;
					break;
				case 'd':
					directory = 1;
					break;
				default:
					printf("Usage: sort -dfnr\n");
					return 1;
				}
			}
		}
		else
		{
			printf("Usage: sort -dfnr\n");
			return 1;
		}
	}
	if ((nlines = readlines(lineptr, MAXLINES)) >= 0) {
		if (numeric)
		{
			quicksort((void **)lineptr,
				0,
				nlines - 1,
				(int (*)(void *, void *))numcmp);
		}
		else
		{
			quicksort((void **)lineptr,
				0,
				nlines - 1,
				(int (*)(void *, void *))mystrcmp);
		}
		writelines(lineptr, nlines);
		return 0;
	}
	else
	{
		printf("Input too big to sort\n");
		return 1;
	}
}

/* quicksort: Sort v[left]...v[right] into increasing or decreasing order */
void quicksort(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 fewer than two elements */
	{
		return;
	}
	swap(v, left, (left + right) / 2);  /* Move element to sort left */
	last = left;
	/* Move all elements < or > sort element to the left according to order */
	for (i = left + 1; i <= right; ++i)
	{
		if (!decreasing)
		{
			if ((*comp)(v[i], v[left]) < 0)
			{
				swap(v, ++last, i);
			}
		}
		else
		{
			if ((*comp)(v[i], v[left]) > 0)
			{
				swap(v, ++last, i);
			}
		}
	}
	swap(v, left, last); /* Move sort element to its final position */
	quicksort(v, left, last - 1, comp); /* Sort left subarray */
	quicksort(v, last + 1, right, comp); /* Sort right subarray */
}

/*
 * mystrcmp: Compares s1 and s2 lexicographically.
 * Ignores characters that are not letters, numbers, or whitespace if directory flag
 * is set.
 * If the fold flag is set, it isn't case sensitive.
 */
int mystrcmp(char *s1, char *s2)
{
	if (directory)
	{
		while (!isdigit(*s1) && !isalpha(*s1) && !isspace(*s1) && *s1)
		{
			++s1; /* Ignore bad characters */
		}
		while (!isdigit(*s2) && !isalpha(*s2) && !isspace(*s2) && *s2)
		{
			++s2; /* Ignore bad characters */
		}
	}
	while (fold ? (tolower(*s1) == tolower(*s2)) : (*s1 == *s2))
	{
		if (*s1 == '\0')
		{
			return 0;
		}
		++s1;
		++s2;
		if (directory)
		{
			while (!isdigit(*s1) && !isalpha(*s1) && !isspace(*s1) && *s1)
			{
				++s1; /* Ignore bad characters */
			}
			while (!isdigit(*s2) && !isalpha(*s2) && !isspace(*s2) && *s2)
			{
				++s2; /* Ignore bad characters */
			}
		}
	}
	return fold ? (tolower(*s1) - tolower(*s2)) : (*s1 - *s2);
}

/* numcmp: Compare s1 and s2 numerically */
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;
	}
	else
	{
		return 0;
	}
}

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

	temp = v[i];
	v[i] = v[j];
	v[j] = temp;
}

/* readlines: Read input lines.
 * This version is slightly modified to read longer lines than the limit set by
 * MAXLEN.
 */
int readlines(char *lineptr[], int maxlines)
{
	int len, nlines = 0;
	char *p, line[MAXLEN];
	int longline = 0;

	while ((len = getline(line, MAXLEN)) > 0)
	{
		if (nlines >= maxlines || (p = alloc(len)) == NULL)
		{
			return -1;
		}
		else
		{
			if (line[len - 1] == '\n')
			{
				line[len - 1] = '\0';  /* Delete newline */
				strcpy_s(p, sizeof line, line);
				if (!longline)
				{
					lineptr[nlines++] = p;
				}
				else
				{
					longline = 0;
				}
			}
			else
			{
				strcpy_s(p, sizeof line, line);
				if (!longline)
				{
					lineptr[nlines++] = p;
					longline = 1;
				}
			}
		}
	}
	return nlines;
}

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

int getline(char *s, int max)
{
	int c;
	char *ps = s;
	while (--max && (c = getchar()) != EOF && c != '\n')
	{
		*s++ = c;
	}
	if (c == '\n')
	{
		*s++ = '\n';
	}
	*s = '\0';
	return s - ps;
}

#define ALLOCSIZE 2000000

static char allocbuf[ALLOCSIZE];  /* Storage for alloc */
static char *allocp = allocbuf;    /* Next free position */

char *alloc(int n)
{
	if (allocbuf + ALLOCSIZE - allocp >= n) /* It fits */
	{
		allocp += n;
		return allocp - n; /* Old p */
	}
	else /* Not enough room */
	{
		return 0;
	}
}

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值