案例描述:从终端输入一些字符,每行不超过1000个,一共不超过5000行,对输入的行进行字典排序,并把排序的结果按照顺序输出出来。
案例关键:1.指针数组和二维指针的应用;2.字典排序的算法,用快速排序。3.对输入输出的处理。
实现代码如下:
/***********************************************************************
Copyright (c) 2015,wangzp
All rights no reserved.
Name: Sort the input lines from terminal
ID: The C Programming Language
问题简述: 对输入的文本行按照字母在字典中的顺序进行排序。
Date: Sep 23, 2015
***********************************************************************/
#include
#include
#include
#define MAXLINES 5000 /*能够存储的最大文本行数*/
#define MAXLEN 1000/*每行文本行的长度*/
char *lineptr[MAXLINES];/*指向文本行的指针*/
int readlines(char *lineptr[],int nlines);/*读文本行函数*/
void writelines(char *lineptr[],int nlines);/*写入文本行函数*/
void qsort(char *v[],int left,int right);/*文本行排序函数*/
int getline(char *s,int lim);
void swap(char *v[],int i,int j);
/*主函数*/
int main(void)
{
int nlines;/*输入行数目*/
if ((nlines = readlines(lineptr,MAXLINES)) >= 0)
{
qsort(lineptr,0,nlines - 1);
writelines(lineptr,nlines);
return 0;
}
else
{
printf("error:input too big to sort.\n");
return 1;
}
}
/***********************************************************************
@author : wzp
@Name : getline
@Funcation: 将一行读入s[]中并返回其长度
@Date : Sep 23, 2015
***********************************************************************/
int getline(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;
}
/***********************************************************************
@author : wzp
@Name : readlines
@Funcation: 读入行
@Date : Sep 23, 2015
***********************************************************************/
int readlines(char *lineptr[],int maxlines)
{
int len,nlines;
char *p,line[MAXLINES];
nlines = 0;
while ((len = getline(line,MAXLEN)) > 0)
{
if (nlines >= maxlines || (p = (char *)malloc(len)) == NULL)
{
return -1;
}
else
{
line[len -1] = '\0';//删除每一行的回车
strcpy(p,line);//把终端输入的行内容拷贝到p指针指向的空间中
lineptr[nlines++] = p;//保存当前行的指针,排序时只需要变化指针即可,不需要动行的内容
}
}
return nlines;//返回读取了多少行
}
/***********************************************************************
@author : wzp
@Name : writelines
@Funcation: 写输出行,即打印行
@Date : Sep 23, 2015
***********************************************************************/
void writelines(char *lineptr[],int nlines)
{
int i;
for (i = 0;i < nlines;i++)
{
printf("%s\n",lineptr[i]);
}
}
/***********************************************************************
@author : wzp
@Name : qsort
@Funcation: 按照字典顺序对行进行增序排序 快速排序方法
@Date : Sep 23, 2015
***********************************************************************/
void qsort(char *v[],int left,int right)
{
int i,last;
if (left >= right)//递归结束条件
{
return;
}
swap(v,left,(left + right)/2);
last = left;
for (i = left + 1;i <= right;i++)
{
if (strcmp(v[i],v[left]) < 0)
{
swap(v,++last,i);
}
}
swap(v,left,last);//恢复分区元素后递归调用排序算法
qsort(v,left,last);
qsort(v,last + 1,right);
}
/***********************************************************************
@author : wzp
@Name : swap
@Funcation: 交换两个指针数组中的内容,注意交换的元素为指针
@Date : Sep 23, 2015
***********************************************************************/
void swap(char *v[],int i,int j)
{
char *temp;
temp = v[i];
v[i] = v[j];
v[j] = temp;
}
有一个问题,需要我们注意,我们使用了malloc函数为指针数组开辟了空间,使用完毕后,最好用free()函数把指针数组指向的空间给释放掉。下图调试简单说明了指针的存储情况:地址和内容:
另外需要说明的是free(p)函数只是释放指针p指向的空间内容,而p的地址还在,所以在free之后,需要把这些指针赋值为NULL,如果不赋值为NULL的话,就成了野指针,虽然对结果造不成影响,但如果不处理野指针的话,这样做不是一个好习惯。
实现代码如下:
/***********************************************************************
Copyright (c) 2015,wangzp
All rights no reserved.
Name: Sort the input lines from terminal
ID: The C Programming Language
问题简述: 对输入的文本行按照字母在字典中的顺序进行排序。
Date: Sep 23, 2015
***********************************************************************/
#include
#include
#include
#define MAXLINES 5000 /*能够存储的最大文本行数*/
#define MAXLEN 1000/*每行文本行的长度*/
char *lineptr[MAXLINES];/*指向文本行的指针*/
int readlines(char *lineptr[],int nlines);/*读文本行函数*/
void writelines(char *lineptr[],int nlines);/*写入文本行函数*/
void qsort(char *v[],int left,int right);/*文本行排序函数*/
int getline(char *s,int lim);
void swap(char *v[],int i,int j);
/*主函数*/
int main(void)
{
int nlines;/*输入行数目*/
if ((nlines = readlines(lineptr,MAXLINES)) >= 0)
{
qsort(lineptr,0,nlines - 1);
writelines(lineptr,nlines);
/*查看内存释放情况*/
printf("free内存块之前:\n");
for (int i = 0;i < nlines;i++)
{
printf("%s\n",lineptr[i]);
}
printf("free内存块之后:\n");
for (int i = 0;i < nlines;i++)
{
free(lineptr[i]);
printf("%s\n",lineptr[i]);
}
printf("处理野指针之后:\n");
for (int i = 0;i < nlines;i++)
{
lineptr[i] = NULL;
printf("%s\n",lineptr[i]);
}
return 0;
}
else
{
printf("error:input too big to sort.\n");
return 1;
}
}
/***********************************************************************
@author : wzp
@Name : getline
@Funcation: 将一行读入s[]中并返回其长度
@Date : Sep 23, 2015
***********************************************************************/
int getline(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;
}
/***********************************************************************
@author : wzp
@Name : readlines
@Funcation: 读入行
@Date : Sep 23, 2015
***********************************************************************/
int readlines(char *lineptr[],int maxlines)
{
int len,nlines;
char *p,line[MAXLINES];
nlines = 0;
while ((len = getline(line,MAXLEN)) > 0)
{
if (nlines >= maxlines || (p = (char *)malloc(len)) == NULL)
{
return -1;
}
else
{
line[len -1] = '\0';//删除每一行的回车
strcpy(p,line);//把终端输入的行内容拷贝到p指针指向的空间中
lineptr[nlines++] = p;//保存当前行的指针,排序时只需要变化指针即可,不需要动行的内容
}
}
return nlines;//返回读取了多少行
}
/***********************************************************************
@author : wzp
@Name : writelines
@Funcation: 写输出行,即打印行
@Date : Sep 23, 2015
***********************************************************************/
void writelines(char *lineptr[],int nlines)
{
int i;
for (i = 0;i < nlines;i++)
{
printf("%s\n",lineptr[i]);
}
}
/***********************************************************************
@author : wzp
@Name : qsort
@Funcation: 按照字典顺序对行进行增序排序 快速排序方法
@Date : Sep 23, 2015
***********************************************************************/
void qsort(char *v[],int left,int right)
{
int i,last;
if (left >= right)//递归结束条件
{
return;
}
swap(v,left,(left + right)/2);
last = left;
for (i = left + 1;i <= right;i++)
{
if (strcmp(v[i],v[left]) < 0)
{
swap(v,++last,i);
}
}
swap(v,left,last);//恢复分区元素后递归调用排序算法
qsort(v,left,last);
qsort(v,last + 1,right);
}
/***********************************************************************
@author : wzp
@Name : swap
@Funcation: 交换两个指针数组中的内容,注意交换的元素为指针
@Date : Sep 23, 2015
***********************************************************************/
void swap(char *v[],int i,int j)
{
char *temp;
temp = v[i];
v[i] = v[j];
v[j] = temp;
}