2017-06-18 94 views

回答

1

可以使用qsort功能与适当的比较函数。这样的功能必须精心设计以实现传递式排序功能。从弗拉德,乔纳森和我集体的力量导致这种简单便携的实现:

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

int cmpletters(const void *p1, const void *p2) { 
    unsigned char c1, c2, u1, u2; 
    c1 = *(const unsigned char *)p1; 
    c2 = *(const unsigned char *)p2; 
    if (c1 == c2) 
     return 0; 
    u1 = toupper(c1); 
    u2 = toupper(c2); 
    if (u1 != u2) 
     return (u1 > u2) ? 1 : -1; 
    return isupper(c1) ? -1 : 1; 
} 

int main(void) { 
    char buf[] = "baBadxD"; 

    printf("before: %s\n", buf); 
    qsort(buf, strlen(buf), 1, cmpletters); 
    printf("sorted: %s\n", buf); 
    return 0; 
} 

注意,该算法也可以用查找表来实现,否则型char是非常大的。

+0

这似乎是一个复杂的比较函数。 –

+0

@JonathanLeffler:是的,弗拉德写了一个更简单的。这一个唯一的优点是在任何其他符号之前对所有字母进行分组。但即使如此,它太复杂了。 – chqrlie

+0

@JonathanLeffler:我简化了你的函数,并且在没有'''''''假设的情况下工作。 – chqrlie

0

需要仔细编写比较功能,并使用标头<stdlib.h>中声明的C标准分类功能qsort

这是一个示范程序。

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

int cmp_char(const void *lhs, const void *rhs) 
{ 
    unsigned char c1 = *(const unsigned char *)lhs; 
    unsigned char c2 = *(const unsigned char *)rhs; 

    if (c1 == c2) 
    { 
     return 0; 
    } 
    else if ((toupper(c1) < toupper(c2)) || 
     (toupper(c1) == toupper(c2) && isupper(c1) && islower(c2))) 
    { 
     return -1; 
    } 
    else 
    { 
     return 1; 
    } 
} 

int main(void) 
{ 
    char s[] = "baBadxD"; 

    puts(s); 

    qsort(s, strlen(s), sizeof(char), cmp_char); 

    puts(s); 
} 

程序输出是

baBadxD 
aaBbDdx 
+0

好又简单!为了完全的可移植性,我会在'main()'的末尾添加可选的'return 0;'。 upvoted。 – chqrlie

3

必要的比较功能不是很复杂。你可以大小写转换字符并进行比较。如果它们不相等,则使用案例转换值的成语(x > y) - (x < y)返回值。如果它们相同,则使用相同的成语来比较未转换的字符。

该代码确实假设大写字母字符在代码集中的小写字母之前。它使用断言来确保 - 它可能是static_assert()产生编译时错误而不是运行时错误。如果你需要担心重音字符,你需要更复杂的比较,如果只是为了确保áàäâå等组合在一起。

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

static int comparator(const void *v1, const void *v2) 
{ 
    unsigned char c1 = *(unsigned char *)v1; 
    unsigned char c2 = *(unsigned char *)v2; 
    unsigned char u1 = toupper(c1); 
    unsigned char u2 = toupper(c2); 
    if (u1 != u2) 
     return (u1 > u2) - (u1 < u2); 
    return (c1 > c2) - (c1 < c2); 
} 

int main(void) 
{ 
    assert('A' < 'a'); 
    char sample[] = "baBadxD"; 

    printf("Unsorted [%s]\n", sample); 
    qsort(sample, strlen(sample), sizeof(char), comparator); 
    printf("Sorted [%s]\n", sample); 

    char buffer[4096]; 
    while (fgets(buffer, sizeof(buffer), stdin) != 0) 
    { 
     buffer[strcspn(buffer, "\n")] = '\0'; 
     printf("Unsorted [%s]\n", buffer); 
     qsort(buffer, strlen(buffer), sizeof(char), comparator); 
     printf("Sorted [%s]\n", buffer); 
    } 
    return 0; 
} 

测试代码对问题中给出的示例数据进行排序,然后读取更多行数据并对其中的每一行进行排序。给定一个随机文本发生器,一些示例输出是:

Unsorted [baBadxD] 
Sorted [aaBbDdx] 
Unsorted [PvpxixCDvgnkLHQLlBvsJzgQLDmBxUeIhyUMvDiVpjCYvOshnaEvupb] 
Sorted [aBBbCCDDDEeggHhhIiiJjkLLLlMmnnOPpppQQssUUuVvvvvvvxxxYyz] 
Unsorted [rvnsnRcQGUGDyydxrvIhYkQemsqfNtafIZlVQqHvDxkLnxdQouwBrv] 
Sorted [aBcDDddeffGGHhIIkkLlmNnnnoQQQQqqRrrrsstUuVvvvvwxxxYyyZ] 
Unsorted [XZPIDAxazwWQZhxuCVotQPzTHsCQULaEiSPLAQUlnqrBiz] 
Sorted [AAaaBCCDEHhIiiLLlnoPPPQQQQqrSsTtUUuVWwXxxZZzzz] 
Unsorted [NoAsbAzTWivuxSHjBKnGeDxgmWdwNESTZmZauGvmdchoGjMAAEufcZneoWWWN] 
Sorted [AAAAaBbccDddEEeefGGGgHhijjKMmmmNNNnnoooSSsTTuuuvvWWWWWwxxZZZz] 
Unsorted [zcmMqAkXYXrmObgDsloVxVLfmXclNGBmDfrtVEcgHVZlRaycjbnYbSQkS] 
Sorted [AaBbbbccccDDEffGggHjkkLlllMmmmmNnOoQqRrrSSstVVVVXXXxYYyZz] 
Unsorted [DHvDBHSsTgAjBaZGCXniiBqzSNkNqgeKStXzDDswSfCcJnJJSAKsmhz] 
Sorted [AAaBBBCCcDDDDefGggHHhiiJJJjKKkmNNnnqqSSSSSsssTtvwXXZzzz] 
Unsorted [MGKtMuBlwdXTjysBPDhHntdGvsjRPOWlGvKTCTs] 
Sorted [BBCDddGGGHhjjKKllMMnOPPRsssTTTttuvvWwXy] 
Unsorted [ChNiqW] 
Sorted [ChiNqW] 
+0

的确更简单一些,但是假设'A'<'a''和字母在字符集中按字母顺序排列。少一个测试:'if(u1!= u2)return(u1> u2)? 1:-1;' – chqrlie

+0

我认为迄今为止显示的所有比较器都假定'A'在其他字母之前排序。我确实注意到重音字符会成为这个代码的问题。是的,代码可以按照您的建议进行简化。 –

+0

ASCII和ISO-Latin-x字符集遵循此规则(''A'<'a''),但MacRoman不适用于某些重音字符,EBCDIC甚至不适用于普通罗马字符。 – chqrlie

相关问题