user-0 提问: 如何用qsort对二维字符数组存的若干字符串排序？

回复:
user: user-0
content: 谢谢兄弟们，尤其是赵哥。 本来想问一下char t[5][100] 不能用于qsort的解决办法，没想到额外收获了赵哥的简洁高效程序。 我用了80万行的倚天屠龙记切分语料来统计无重复词，朝歌的程序跑得非常OK。

user: user-0
content: #include <stdio.h>  #include <stdlib.h>   #include <string.h>    /*---------------------------------------------------------------------     字符指针数组的4个字符串排序函数：升序或降序 and 是否忽略大小写     调用方法： 	    char *s[5]=     {"caTtle","caR","banana","cabet","cap"};           qsort((void*)s, 5, sizeof(char *), 下面所列的4个函数名之一); ---------------------------------------------------------------------*/ int qsort_compare_pstr_asc(const void *a, const void *b);   int qsort_compare_pstr_asc_ignorecase(const void *a, const void *b);   int qsort_compare_pstr_desc(const void *a, const void *b);   int qsort_compare_pstr_desc_ignorecase(const void *a, const void *b);    /*---------------------------------------------------------------------     二位字符数组的4个字符串排序函数：升序或降序 and 是否忽略大小写     调用方法： 	    char t[5][100]= {"caTtle","caR","banana","cabet","cap"};           qsort(t, 5, 100*sizeof(char), 下面所列的4个函数名之一); ---------------------------------------------------------------------*/ int qsort_compare_chararray_asc(const void *arg1, const void *arg2); int qsort_compare_chararray_asc_ignorecase(const void *arg1, const void *arg2); int qsort_compare_chararray_desc(const void *arg1, const void *arg2); int qsort_compare_chararray_desc_ignorecase(const void *arg1, const void *arg2);   /*---------------------------------------------------------------------     8个字符串排序函数的具体定义     按如下三个标准分成8个函数：（1）字符指针数组 or 二维字符数组 	                           （2）升序 or 降序 	                           （3）是否忽略英文字母的大小写 ---------------------------------------------------------------------*/ int qsort_compare_pstr_asc(const void *a, const void *b)                 /* 字符指针数组、升序、区分大小写 */ {       return strcmp(*(char**)a, *(char**)b);  }    int qsort_compare_pstr_asc_ignorecase(const void *a, const void *b)      /* 字符指针数组、升序、忽略大小写 */ {       return stricmp(*(char**)a, *(char**)b);  }    int qsort_compare_pstr_desc(const void *a, const void *b)                /* 字符指针数组、降序、区分大小写 */  {       return -strcmp(*(char**)a, *(char**)b);  }    int qsort_compare_pstr_desc_ignorecase(const void *a, const void *b)     /* 字符指针数组、降序、忽略大小写 */  {       return -stricmp(*(char**)a, *(char**)b);  }  int qsort_compare_chararray_asc(const void *arg1, const void *arg2)               /* 二维字符数组、升序、区分大小写 */ {     return strcmp((char *)arg1, (char *)arg2);  }  int qsort_compare_chararray_asc_ignorecase(const void *arg1, const void *arg2)    /* 二维字符数组、升序、忽略大小写 */ {     return stricmp((char *)arg1, (char *)arg2);  }  int qsort_compare_chararray_desc(const void *arg1, const void *arg2)              /* 二维字符数组、降序、区分大小写 */ {     return -strcmp((char *)arg1, (char *)arg2);  }  int qsort_compare_chararray_desc_ignorecase(const void *arg1, const void *arg2)   /* 二维字符数组、降序、忽略大小写 */ {     return -stricmp((char *)arg1, (char *)arg2);  }      char *s[5]=     {"caTtle","caR","banana","cabet","cap"};   char t[5][100]= {"caTtle","caR","banana","cabet","cap"};   int main()   {      int i;      printf("\ns降序排列：\n");      qsort((void*)s, 5, sizeof(char *), qsort_compare_pstr_desc);      for(i=0; i<5; i++)          printf("%s\n",s[i]);      printf("\ns降序排列（忽略大小写）：\n");      qsort((void*)s, 5, sizeof(char *), qsort_compare_pstr_desc_ignorecase);      for(i=0; i<5; i++)          printf("%s\n",s[i]);   	printf("\ns升序排列：\n");      qsort((void*)s, 5, sizeof(char *), qsort_compare_pstr_asc);      for(i=0; i<5; i++)          printf("%s\n",s[i]);   	printf("\ns升序排列（忽略大小写）：\n");      qsort((void*)s, 5, sizeof(char *), qsort_compare_pstr_asc_ignorecase);      for(i=0; i<5; i++)          printf("%s\n",s[i]);         printf("\nt降序排列：\n");      qsort(t, 5, 100*sizeof(char), qsort_compare_chararray_desc);      for(i=0; i<5; i++)          printf("%s\n",t[i]);         printf("\nt降序排列（忽略大小写）：\n");      qsort(t, 5, 100*sizeof(char), qsort_compare_chararray_desc_ignorecase);      for(i=0; i<5; i++)          printf("%s\n",t[i]);         printf("\nt升序排列：\n");      qsort(t, 5, 100*sizeof(char), qsort_compare_chararray_asc);      for(i=0; i<5; i++)          printf("%s\n",t[i]);         printf("\nt升序排列（忽略大小写）：\n");      qsort(t, 5, 100*sizeof(char), qsort_compare_chararray_asc_ignorecase);      for(i=0; i<5; i++)          printf("%s\n",t[i]);         return 0;  }

user: user-1
content: 如果数据量很大的话，那一般在读取的时候不会用指针常量存的。而且数据量大的时候内存都会出问题，一般采用外部排序。

user: user-2
content: 数据量大的话可以做归并排序 将数据按10万分段做排序，结果存储到文件中，然后作多路归并就可以了

user: user-3
content: 仅供参考//文件1中的内容排序并去重,结果保存到文件2中 #include <stdio.h> #include <stdlib.h> #include <string.h> #define MAXCHARS 128      //能处理的最大行宽,包括行尾的\n和字符串尾的\0 int MAXLINES=10000,MAXLINES2; char *buf,*buf2; int c,n,hh,i,L; FILE *f; char ln[MAXCHARS]; int ignore_case=0; int icompare(const void *arg1,const void *arg2) {    return stricmp((char *)arg1,(char *)arg2); } int compare(const void *arg1,const void *arg2) {    return strcmp((char *)arg1,(char *)arg2); } int main(int argc,char **argv) {     if (argc<3) {         printf("Unique line. Designed by zhao4zhong1@163.com. 2012-08-20\n");         printf("Usage: %s src.txt uniqued.txt [-i]\n",argv[0]);         return 1;     }     if (argc>3) ignore_case=1;//若存在命令行参数3，忽略大小写     f=fopen(argv[1],"r");     if (NULL==f) {         printf("Can not find file %s!\n",argv[1]);         return 1;     }     buf=(char *)malloc(MAXLINES*MAXCHARS);     if (NULL==buf) {         fclose(f);         printf("Can not malloc(%d LINES*%d CHARS)!\n",MAXLINES,MAXCHARS);         return 2;     }     n=0;     hh=0;     i=0;     while (1) {         if (NULL==fgets(ln,MAXCHARS,f)) break;//         hh++;         L=strlen(ln)-1;         if ('\n'!=ln[L]) {//超长行忽略后面内容             printf("%s Line %d too long(>%d),spilth ignored.\n",argv[1],hh,MAXCHARS);             while (1) {                 c=fgetc(f);                 if ('\n'==c || EOF==c) break;//             }         }         while (1) {//去掉行尾的'\n'和空格             if ('\n'==ln[L] || ' '==ln[L]) {                 ln[L]=0;                 L--;                 if (L<0) break;//             } else break;//         }         if (L>=0) {             strcpy(buf+i,ln);i+=MAXCHARS;             n++;             if (n>=MAXLINES) {                 MAXLINES2=MAXLINES*2;                 if (MAXLINES2==1280000) MAXLINES2=2500000;                 buf2=(char *)realloc(buf,MAXLINES2*MAXCHARS);                 if (NULL==buf2) {                     printf("Can not malloc(%d LINES*%d CHARS)!\n",MAXLINES2,MAXCHARS);                     printf("WARNING: Lines >%d ignored.\n",MAXLINES);                     break;//                 }                 buf=buf2;                 MAXLINES=MAXLINES2;             }         }     }     fclose(f);     if (n>1) {         if (ignore_case) qsort(buf,n,MAXCHARS,icompare);         else qsort(buf,n,MAXCHARS,compare);     }     f=fopen(argv[2],"w");     if (NULL==f) {         free(buf);         printf("Can not create file %s!\n",argv[2]);         return 2;     }     fprintf(f,"%s\n",buf);     if (n>1) {         if (ignore_case) {             hh=0;             L=MAXCHARS;             for (i=1;i<n;i++) {                 if (stricmp((const char *)buf+hh,(const char *)buf+L)) {                     fprintf(f,"%s\n",buf+L);                 }                 hh=L;                 L+=MAXCHARS;             }         } else {             hh=0;             L=MAXCHARS;             for (i=1;i<n;i++) {                 if ( strcmp((const char *)buf+hh,(const char *)buf+L)) {                     fprintf(f,"%s\n",buf+L);                 }                 hh=L;                 L+=MAXCHARS;             }         }     }     fclose(f);     free(buf);     return 0; }

user: user-4
content: 引用 2 楼 woshihuzi 的回复:我可以另外设一个字符指针数组char *pt[5] = {t[0],t[1],t[2],t[3],t[4]} 下面只需要用qsort对pt排序，最后pt[0]、pt[1]、……指向的字符串就是有序的。 现在带来一个问题： 如果数据量很大，比如100万个字符串，额外加400万字节的指针，会不会消耗内存很厉害？ 如果我想在pt排序完之后再写段代码让t有序，会不会是多此一举？ 100万个字符串，明显会内存消耗很利害，要考虑其它 的方法了。比如hash. 是多此一举。

user: user-0
content: 我可以另外设一个字符指针数组char *pt[5] = {t[0],t[1],t[2],t[3],t[4]} 下面只需要用qsort对pt排序，最后pt[0]、pt[1]、……指向的字符串就是有序的。 现在带来一个问题： 如果数据量很大，比如100万个字符串，额外加400万字节的指针，会不会消耗内存很厉害？ 如果我想在pt排序完之后再写段代码让t有序，会不会是多此一举？

user: user-1
content: t[i]是指针常量，不能作为左值。所以会在qsort交换数组元素位置时出错。  要qsort排序的话，可以把t的每个元素赋给一个字符指针数组，就像s。