使用C编写类sort命令功能的程序
sort命令是linux系统中常用的命令,它的功能是给标准输入中的行进行排序,默认是通过字典序进行排序的。今天,展示如果通过C语言编写一个类似功能的程序。
# sort <<eof
> Hello Paul.
> How are you going?
> Very well. What about you?
> I'm good.
> eof
Hello Paul.
How are you going?
I'm good.
Very well. What about you?
程序设计思路
实现该程序分三个步骤,分别编写三个函数去实现
- 获取所有的输入行,所有输入行使用字符指针数组。
- 对所有输入行进行排序操作
- 打印排好序的行
这三个函数编写好了,程序也就完成了。
#define MAXLINES 1024
int main (void)
{
int readlines (char *lineptr[], int maxlines);
void qsortlines (char *lineptr[], int left, int right);
void printlines (char *lineptr[], int linenum);
char *lineptr[MAXLINES];
int linenum;
if ((linenum = readlines(lineptr, MAXLINES)) >= 0) {
qsortlines(lineptr, 0, linenum - 1);
printlines(lineptr, linenum);
return 0;
} else {
printf("Input too big to sort\n");
return 1;
}
}
获取所有输入行
这里使用字符指针数组保存所有输入行, 该函数返回一个int类型。我们需要定义最大行数,超过最大行数的话,那么就返回-1,表示输入文本行数过多。
int readlines (char *lineptr[], int maxlines)
{
char line[1024];
int n;
int linenum = 0;
char *tmp;
while ((n = get_line(line)) > 0) {
if (linenum >= maxlines || (tmp = alloc(n)) == 0) {
return -1;
} else {
line[n-1] = 'int readlines (char *lineptr[], int maxlines)
{
char line[1024];
int n;
int linenum = 0;
char *tmp;
while ((n = get_line(line)) > 0) {
if (linenum >= maxlines || (tmp = alloc(n)) == 0) {
return -1;
} else {
line[n-1] = '\0';
str_cpy(tmp, line);
lineptr[linenum ++] = tmp;
}
}
return linenum;
}
';
str_cpy(tmp, line);
lineptr[linenum ++] = tmp;
}
}
return linenum;
}
排序算法
这里我们采用了快速排序算法,来对指定行按字典序进行排序。
void qsortlines (char *lineptr[], int left, int right)
{
if (left >= right)
return;
int tmpn, i;
tmpn = left;
for (i = left + 1; i <= right; i++)
if (str_cmp(lineptr[left], lineptr[i]) > 0)
swapline(lineptr, i, ++tmpn);
swapline(lineptr, left, tmpn);
qsortlines(lineptr, left, tmpn - 1);
qsortlines(lineptr, tmpn + 1, right);
}
打印所有行
这个函数功能就非常的简单了,循环遍历即可。
void printlines(char *lineptr[], int linenum)
{
while (linenum -- > 0){
printf("%s\n", *lineptr++);
}
}
以上就是该程序的主体核心部分,自己在编写这个程序的时候,没有花多久,但在调试错误的时候花费了不少时间。出现bug的原因是关于指针和数组的概念没有搞清。
在C中数组名所代表的就是数组最开始的一个元素的地址,把数组名传递给一个函数时,实际上传递的是该数组第一个元素的地址。指针和数组有紧密联系,但它们还是有区别的。区别在于指针是一个变量,而数组名则不是变量
char str[] = "hello";
char *p = str;
str++; // error
p++; // ok
最后,附上完整代码
#include <stdio.h>
#define ALLOCSIZE 10000 /* ALLOC SIZE */
static char allocbuf[ALLOCSIZE];
static char *allocp = allocbuf; /* next free site */
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;
}
}
int get_line(char *s)
{
int maxlen = 1024;
int c,i;
char *p = s;
for (i = 0; (c = getchar()) != EOF && c != '\n'; i++) {
if (p - s < maxlen -1) {
*p++ = c;
}
}
if (c == '\n') {
if (p-s < maxlen)
*p++ = c;
i++;
}
*p = '#include <stdio.h>
#define ALLOCSIZE 10000 /* ALLOC SIZE */
static char allocbuf[ALLOCSIZE];
static char *allocp = allocbuf; /* next free site */
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;
}
}
int get_line(char *s)
{
int maxlen = 1024;
int c,i;
char *p = s;
for (i = 0; (c = getchar()) != EOF && c != '\n'; i++) {
if (p - s < maxlen -1) {
*p++ = c;
}
}
if (c == '\n') {
if (p-s < maxlen)
*p++ = c;
i++;
}
*p = '\0';
return i;
}
void str_cpy (char *s, char *t)
{
while (*s++ = *t++ )
;
}
int str_cmp (char *s, char *t)
{
for (; *s == *t; s++, t++) {
if (*s == '\0')
return 0;
}
return *s - *t;
}
int readlines (char *lineptr[], int maxlines)
{
char line[1024];
int n;
int linenum = 0;
char *tmp;
while ((n = get_line(line)) > 0) {
if (linenum >= maxlines || (tmp = alloc(n)) == 0) {
return -1;
} else {
line[n-1] = '\0';
str_cpy(tmp, line);
lineptr[linenum ++] = tmp;
}
}
return linenum;
}
void swapline (char *lineptr[], int i, int j)
{
char *tmp = lineptr[i];
lineptr[i] = lineptr[j];
lineptr[j] = tmp;
}
void qsortlines (char *lineptr[], int left, int right)
{
if (left >= right)
return;
int tmpn, i;
tmpn = left;
for (i = left + 1; i <= right; i++)
if (str_cmp(lineptr[left], lineptr[i]) > 0)
swapline(lineptr, i, ++tmpn);
swapline(lineptr, left, tmpn);
qsortlines(lineptr, left, tmpn - 1);
qsortlines(lineptr, tmpn + 1, right);
}
void printlines(char *lineptr[], int linenum)
{
while (linenum -- > 0){
printf("%s\n", *lineptr++);
}
}
#define MAXLINES 1024
int main (void)
{
int readlines (char *lineptr[], int maxlines);
void qsortlines (char *lineptr[], int left, int right);
void printlines (char *lineptr[], int linenum);
char *lineptr[MAXLINES];
int linenum;
if ((linenum = readlines(lineptr, MAXLINES)) >= 0) {
qsortlines(lineptr, 0, linenum - 1);
printlines(lineptr, linenum);
return 0;
} else {
printf("Input too big to sort\n");
return 1;
}
}
';
return i;
}
void str_cpy (char *s, char *t)
{
while (*s++ = *t++ )
;
}
int str_cmp (char *s, char *t)
{
for (; *s == *t; s++, t++) {
if (*s == '#include <stdio.h>
#define ALLOCSIZE 10000 /* ALLOC SIZE */
static char allocbuf[ALLOCSIZE];
static char *allocp = allocbuf; /* next free site */
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;
}
}
int get_line(char *s)
{
int maxlen = 1024;
int c,i;
char *p = s;
for (i = 0; (c = getchar()) != EOF && c != '\n'; i++) {
if (p - s < maxlen -1) {
*p++ = c;
}
}
if (c == '\n') {
if (p-s < maxlen)
*p++ = c;
i++;
}
*p = '\0';
return i;
}
void str_cpy (char *s, char *t)
{
while (*s++ = *t++ )
;
}
int str_cmp (char *s, char *t)
{
for (; *s == *t; s++, t++) {
if (*s == '\0')
return 0;
}
return *s - *t;
}
int readlines (char *lineptr[], int maxlines)
{
char line[1024];
int n;
int linenum = 0;
char *tmp;
while ((n = get_line(line)) > 0) {
if (linenum >= maxlines || (tmp = alloc(n)) == 0) {
return -1;
} else {
line[n-1] = '\0';
str_cpy(tmp, line);
lineptr[linenum ++] = tmp;
}
}
return linenum;
}
void swapline (char *lineptr[], int i, int j)
{
char *tmp = lineptr[i];
lineptr[i] = lineptr[j];
lineptr[j] = tmp;
}
void qsortlines (char *lineptr[], int left, int right)
{
if (left >= right)
return;
int tmpn, i;
tmpn = left;
for (i = left + 1; i <= right; i++)
if (str_cmp(lineptr[left], lineptr[i]) > 0)
swapline(lineptr, i, ++tmpn);
swapline(lineptr, left, tmpn);
qsortlines(lineptr, left, tmpn - 1);
qsortlines(lineptr, tmpn + 1, right);
}
void printlines(char *lineptr[], int linenum)
{
while (linenum -- > 0){
printf("%s\n", *lineptr++);
}
}
#define MAXLINES 1024
int main (void)
{
int readlines (char *lineptr[], int maxlines);
void qsortlines (char *lineptr[], int left, int right);
void printlines (char *lineptr[], int linenum);
char *lineptr[MAXLINES];
int linenum;
if ((linenum = readlines(lineptr, MAXLINES)) >= 0) {
qsortlines(lineptr, 0, linenum - 1);
printlines(lineptr, linenum);
return 0;
} else {
printf("Input too big to sort\n");
return 1;
}
}
')
return 0;
}
return *s - *t;
}
int readlines (char *lineptr[], int maxlines)
{
char line[1024];
int n;
int linenum = 0;
char *tmp;
while ((n = get_line(line)) > 0) {
if (linenum >= maxlines || (tmp = alloc(n)) == 0) {
return -1;
} else {
line[n-1] = '#include <stdio.h>
#define ALLOCSIZE 10000 /* ALLOC SIZE */
static char allocbuf[ALLOCSIZE];
static char *allocp = allocbuf; /* next free site */
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;
}
}
int get_line(char *s)
{
int maxlen = 1024;
int c,i;
char *p = s;
for (i = 0; (c = getchar()) != EOF && c != '\n'; i++) {
if (p - s < maxlen -1) {
*p++ = c;
}
}
if (c == '\n') {
if (p-s < maxlen)
*p++ = c;
i++;
}
*p = '\0';
return i;
}
void str_cpy (char *s, char *t)
{
while (*s++ = *t++ )
;
}
int str_cmp (char *s, char *t)
{
for (; *s == *t; s++, t++) {
if (*s == '\0')
return 0;
}
return *s - *t;
}
int readlines (char *lineptr[], int maxlines)
{
char line[1024];
int n;
int linenum = 0;
char *tmp;
while ((n = get_line(line)) > 0) {
if (linenum >= maxlines || (tmp = alloc(n)) == 0) {
return -1;
} else {
line[n-1] = '\0';
str_cpy(tmp, line);
lineptr[linenum ++] = tmp;
}
}
return linenum;
}
void swapline (char *lineptr[], int i, int j)
{
char *tmp = lineptr[i];
lineptr[i] = lineptr[j];
lineptr[j] = tmp;
}
void qsortlines (char *lineptr[], int left, int right)
{
if (left >= right)
return;
int tmpn, i;
tmpn = left;
for (i = left + 1; i <= right; i++)
if (str_cmp(lineptr[left], lineptr[i]) > 0)
swapline(lineptr, i, ++tmpn);
swapline(lineptr, left, tmpn);
qsortlines(lineptr, left, tmpn - 1);
qsortlines(lineptr, tmpn + 1, right);
}
void printlines(char *lineptr[], int linenum)
{
while (linenum -- > 0){
printf("%s\n", *lineptr++);
}
}
#define MAXLINES 1024
int main (void)
{
int readlines (char *lineptr[], int maxlines);
void qsortlines (char *lineptr[], int left, int right);
void printlines (char *lineptr[], int linenum);
char *lineptr[MAXLINES];
int linenum;
if ((linenum = readlines(lineptr, MAXLINES)) >= 0) {
qsortlines(lineptr, 0, linenum - 1);
printlines(lineptr, linenum);
return 0;
} else {
printf("Input too big to sort\n");
return 1;
}
}
';
str_cpy(tmp, line);
lineptr[linenum ++] = tmp;
}
}
return linenum;
}
void swapline (char *lineptr[], int i, int j)
{
char *tmp = lineptr[i];
lineptr[i] = lineptr[j];
lineptr[j] = tmp;
}
void qsortlines (char *lineptr[], int left, int right)
{
if (left >= right)
return;
int tmpn, i;
tmpn = left;
for (i = left + 1; i <= right; i++)
if (str_cmp(lineptr[left], lineptr[i]) > 0)
swapline(lineptr, i, ++tmpn);
swapline(lineptr, left, tmpn);
qsortlines(lineptr, left, tmpn - 1);
qsortlines(lineptr, tmpn + 1, right);
}
void printlines(char *lineptr[], int linenum)
{
while (linenum -- > 0){
printf("%s\n", *lineptr++);
}
}
#define MAXLINES 1024
int main (void)
{
int readlines (char *lineptr[], int maxlines);
void qsortlines (char *lineptr[], int left, int right);
void printlines (char *lineptr[], int linenum);
char *lineptr[MAXLINES];
int linenum;
if ((linenum = readlines(lineptr, MAXLINES)) >= 0) {
qsortlines(lineptr, 0, linenum - 1);
printlines(lineptr, linenum);
return 0;
} else {
printf("Input too big to sort\n");
return 1;
}
}