【字符串问题】字符串数组排序(qsort参数 比较函数)

2013-09-14 16:41:21

转自:http://blog.chinaunix.net/uid-15723764-id-3366757.html

 qsort是万能数组排序函数,必须要学会使用,简单的数组自然不用说,这里主要讨论一下字符串数组的使用。

  首先看一下qsort的原型:
    void qsort(void *base, size_t nmemb, size_t size, 
int(*compar)(const void *, const void *));
  正确使用这个函数要注意几点:
1.base要传数组的首地址
2.size传的是每个元素的大小
3.正确编写compare函数
 
下面是实际应用:
    一个字符串数组:*str[MAX],假设里面现在保存了n个字符串了。
    首先要正确理解什么是字符串数组,简单的说,可以理解成它就是一个数组,只不过其中的元素是一串字符串,而访问这些字符串,得用指针,也就是它们的地址,比如*name[]={"james","henry"},那么访问其中的字符串就是name[0],name[1]...这里就有个容易混淆的地方了,对于字符串数组,那么每个元素的大小到底是多少呢?对name[0]来说,到底是字符串“james”的长度5,还是char*的大小4呢?答案应该是4,因为字符串数组里面保存的是各个字符串的指针,所以回到上面所说的第二点注意,用qsort的时候应该要传sizeof(char *);
   第二,编写compar函数比较字符串有地方要注意:
       不能把strcmp本身传给qsort,即不能写strcmp(p,q),因为形参是const void*类型,同理,写成strcmp((char *)p, (char *)q);也是无效的;正确的写法应该是:strcmp(*(char **)p, *(char **)q);先强制转换成char**,在用*减少一层间接寻址操作
      int compar_words(const void *p, const void *q)
      {
return strcmp(*(char **)p, *(char **)q);
      }
大家可以好好体会一下。对于上面的应用,最后使用qsort应该是这样:
qsort(str, n, sizeof(char *), compar);
由此可见,小小的一个qsort使用,对基本概念的理解得比较深刻。由此可见基础扎实的重要性^_^
 

下面转自:http://www.cnblogs.com/buptLizer/archive/2012/04/12/2444565.html

字符串数组排序(qsort参数 比较函数)

这个问题来自一个面试题。

给两个文件,其中一个文件存在一万行左右的文本,将所有数据以行为元素进行排序,输出到文件2中。

拿到这个题,一看数据量大约一万行,内存应该没问题,感觉直接调用库函数qsort,写个cmp函数就

很容易搞定,没想到调试程序发现了一个小问题。

分析程序代码:

const int MAXLINE = 100;
const int MAXLEN = 256;
int mycmp(const void *p1, const void *p2)
{
 char* s1 = (char *)p1;
 char* s2 = (char *)p2;
 cout<<s1<<" "<<s2<<endl;
 return strcmp(s1, s2);
}
bool sort_file(char* file1, char* file2)
{
 ifstream in(file1);
 if(!in)
 {
  cerr<<"open file1 failed"<<endl;
  return false;
 }
 char word[MAXLINE][MAXLEN];
// char *word[MAXLINE];
 cout<<sizeof(word[0])<<endl;
 int line_num = 0;
 while(!in.eof())
 {
 /*
  char *tmp = new char[MAXLEN];
  in.getline(tmp, MAXLEN, '\n');
  word[line_num] = tmp;
 */
  in.getline(word[line_num], MAXLEN, '\n'); 
  line_num++;
 }
 ofstream out(file2);
 if(!out)
 {
  cerr<<"open file2 failed"<<endl;
  return false;
 }
    qsort(word, line_num, sizeof(word[0]), mycmp);
 int i = 0;
 while(i < line_num)
 {
  cout<<word[i]<<endl;
  out<<word[i++]<<'\n';
 }
 in.close();
 out.close();
 return true;
}

在这个代码中word为一个二维数组,那么每一个word[i]表示的其实是一个一维数组,我们知道如果使用一个char*来指向它的话,

那么可以直接利用这个char*来代表这个数组,所以在cmp函数中使用的是char*,看下面的例子。

版本二:

int mycmp(const void *p1, const void *p2)
{
 char** s1 = (char**)p1;
 char** s2 = (char**)p2;
 cout<<*s1<<" "<<*s2<<endl;
 return strcmp(*s1, *s2);
}
bool sort_file(char* file1, char* file2)
{
 ifstream in(file1);
 if(!in)
 {
  cerr<<"open file1 failed"<<endl;
  return false;
 }
// char word[MAXLINE][MAXLEN];
 char *word[MAXLINE];
 cout<<sizeof(word[0])<<endl;
 int line_num = 0;
 while(!in.eof())
 {
 
  char *tmp = new char[MAXLEN];
  in.getline(tmp, MAXLEN, '\n');
  word[line_num] = tmp;
 // in.getline(word[line_num], MAXLEN, '\n'); 
  line_num++;
 }
 ofstream out(file2);
 if(!out)
 {
  cerr<<"open file2 failed"<<endl;
  return false;
 }
    qsort(word, line_num, sizeof(word[0]), mycmp);
 int i = 0;
 while(i < line_num)
 {
  cout<<word[i]<<endl;
  out<<word[i++]<<'\n';
 }
 in.close();
 out.close();
 return true;
}

此时的word表示的是一个指针数组,每个word[i]就是一个char*,那么我们利用qsort的时候传递的是指向这个char* 的指针,即

char**,所以在cmp中需要将void* --> char**,然后用*s来表示char*传递给strcmp。

上面的例子说明,qsort 的比较函数中传递的是数组元素的指针,明白这个就很好理解了。

重复一下qsort 的参数:

void qsort ( void * base, size_t num, size_t size, int ( * comparator ) ( const void *, const void * ) );


base:指向第一个元素的指针,即数组首地址
num:要排序的元素个数,及数组长度
size:数组元素的大小,一般写成sizeof(base[0])
comparator:自己写的比较函数了
posted @ 2013-09-14 16:47  永不止步,永无止境  阅读(1467)  评论(0编辑  收藏  举报