如何用qsort对二维字符数组存的若干字符串排序?

woshihuzi 2014-10-19 02:23:26
我写了一个程序,有点问题:

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

int qsort_compare_str_asc(const void *a, const void *b);

char *s[5]= {"cattle","car","banana","cabet","cap"};
char t[5][100]= {"cattle","car","banana","cabet","cap"};

int main()
{
int i;

printf("s升序排列:\n");
qsort((void*)s, 5, sizeof(char *), qsort_compare_str_asc);
for(i=0; i<5; i++)
printf("%s\n",s[i]);

printf("t升序排列:\n");
qsort((void*)t, 5, sizeof(char *), qsort_compare_str_asc);
for(i=0; i<5; i++)
printf("%s\n",t[i]);

return 0;
}

int qsort_compare_str_asc(const void *a, const void *b)
{
return strcmp(*(char**)a, *(char**)b);
}


程序运行结果:
s是字符指针数组,字符串升序排序成功
t是二维字符数组,字符串升序排序直接崩溃

请教高手:像t[5][100]这样用二位字符数组存储的若干字符串如何用qsort排序成功?
...全文
387 8 打赏 收藏 转发到动态 举报
写回复
用AI写文章
8 条回复
切换为时间正序
请发表友善的回复…
发表回复
woshihuzi 2014-11-01
  • 打赏
  • 举报
回复
谢谢兄弟们,尤其是赵哥。 本来想问一下char t[5][100] 不能用于qsort的解决办法,没想到额外收获了赵哥的简洁高效程序。 我用了80万行的倚天屠龙记切分语料来统计无重复词,朝歌的程序跑得非常OK。
woshihuzi 2014-11-01
  • 打赏
  • 举报
回复

#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; 
} 
cxfustc 2014-10-21
  • 打赏
  • 举报
回复
如果数据量很大的话,那一般在读取的时候不会用指针常量存的。而且数据量大的时候内存都会出问题,一般采用外部排序。
jiuchang 2014-10-21
  • 打赏
  • 举报
回复
数据量大的话可以做归并排序 将数据按10万分段做排序,结果存储到文件中,然后作多路归并就可以了
赵4老师 2014-10-20
  • 打赏
  • 举报
回复
仅供参考
//文件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;
}
勤奋的小游侠 2014-10-20
  • 打赏
  • 举报
回复
引用 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. 是多此一举。
woshihuzi 2014-10-19
  • 打赏
  • 举报
回复
我可以另外设一个字符指针数组char *pt[5] = {t[0],t[1],t[2],t[3],t[4]} 下面只需要用qsort对pt排序,最后pt[0]、pt[1]、……指向的字符串就是有序的。 现在带来一个问题: 如果数据量很大,比如100万个字符串,额外加400万字节的指针,会不会消耗内存很厉害? 如果我想在pt排序完之后再写段代码让t有序,会不会是多此一举?
cxfustc 2014-10-19
  • 打赏
  • 举报
回复
t[i]是指针常量,不能作为左值。所以会在qsort交换数组元素位置时出错。 要qsort排序的话,可以把t的每个元素赋给一个字符指针数组,就像s。

69,371

社区成员

发帖
与我相关
我的任务
社区描述
C语言相关问题讨论
社区管理员
  • C语言
  • 花神庙码农
  • 架构师李肯
加入社区
  • 近7日
  • 近30日
  • 至今
社区公告
暂无公告

试试用AI创作助手写篇文章吧