繁体   English   中英

如何在 C 中对二维数组中的字符串进行排序

[英]How to sort strings in an 2D array in C

#include <stdio.h>

int main()
{
int N, i, j, k, z, v, x, c;

printf("Determine the number of your words: \n");
scanf("%d", &N);
char dict[N][50];
char tmp[50];
for(i=0; i<N; i++)
{
    printf("Determine your %d. word: \n", i+1);
    scanf("%49s", &dict[i]);
}




for(j=1; j<N; j++)
{
    k=j;
    z=0;
    while(dict[j][z]!= '\0')
    {
        tmp[z]=dict[j][z];
        z=z+1;
    }

    
    while((dict[j][1]<dict[k-1][1]) && (k>0))
    {
        v=0;
        while(dict[k][v]!= '\0')
        {
            dict[k][v] = dict[k-1][v];
            v= v+1;
        }
        k=k-1;
    }
    x=0;
    while(dict[k][x]!= '\0')
    {
        dict[k][x]=tmp[x];
        x=x+1;
    }
    
}


for(c=0; c<N; c++)
{
    
    printf("%s \n", dict[c]);
    
}



return 0;

}

因此,作为一名初级 CE 学生,我们的任务是编写一个 C 代码,仅使用 <stdio.h> 库根据字母表中的第一个字符 position 对二维数组中的字符串进行排序,这是我得到的结果如下(我知道这些变量并不是真的可以忍受,但我有点着急):

Determine the number of your words:
5
Determine your 1. word:
LION
Determine your 2. word:
FISH
Determine your 3. word:
TIGER
Determine your 4. word:
SNAKE
Determine your 5. word:
SEALION
LION
FISH
TIGER
SEALI
SNAKE

我没有收到任何错误,只是结果有问题,我不希望有任何答案。 但我很高兴能了解我得到这个结果的原因

仅限于stdio.h

如果您仅限于使用stdio.h中提供的功能,那么您只需编写与您需要的string.h类似的字符串处理功能。 对于排序,除非您想使用诸如快速排序或归并排序之类的分区排序,否则您将被限制为嵌套循环排序——它更易于编写——但速度要慢得多。 (但对于 1000 个左右的字符串,没关系,100,000 - 那么会有明显的差异)

要比较字符串,您可以编写一个简单的strcmp() ,例如 function,不需要额外的 header,例如

/** string compare without string.h */
int strcmp_nohdr (const char *a, const char *b)
{
    if (!a && !b) return 0;
    if ( a && !b) return 1;
    if (!a &&  b) return -1;

    for (; *a && *a == *b; a++, b++) {}

    return (*a > *b) - (*a < *b);
}

如果您没有声明一组额外的排序指针,那么您将需要在二维数组的行(一维数组)之间复制字符串。 您可以编写一个不需要 header 的简单strcpy() ,例如 function :

/** string copy wihout string.h */
char *strcpy_nohdr (char *dest, const char *src)
{
    char *p = dest;
    
    do {
        *p++ = *src;
    } while (*src++);
    
    return dest;
}

最后,您唯一需要的其他东西是排序 function。 (你将无法编写一个快速的qsort()替换)微不足道的Bubblesort就可以了。 您可以编写 function 将二维字符串数组排序为:

#define NCHR 50

/** bubble sort of strings in 'a' (highly inefficient) */
void bubblesort2D (char (*a)[NCHR], size_t n)
{
    size_t i, j;
    for (i = 0; i < n; i++) {
        for (j = 0; j < (n-1); j++) {
            if (strcmp_nohdr(a[j], a[j + 1]) > 0) {
                char temp[NCHR];
                strcpy_nohdr (temp, a[j + 1]);
                strcpy_nohdr  (a[j + 1], a[j]);
                strcpy_nohdr  (a[j], temp);
            }
        }
    }
}

如果您将它们全部放在一个简短的示例中(与之前使用的相同qsort() ,您将拥有:

#include <stdio.h>

#define NCHR 50

/** string compare without string.h */
int strcmp_nohdr (const char *a, const char *b)
{
    if (!a && !b) return 0;
    if ( a && !b) return 1;
    if (!a &&  b) return -1;

    for (; *a && *a == *b; a++, b++) {}

    return (*a > *b) - (*a < *b);
}

/** string copy wihout string.h */
char *strcpy_nohdr (char *dest, const char *src)
{
    char *p = dest;
    
    do {
        *p++ = *src;
    } while (*src++);
    
    return dest;
}

/** bubble sort of strings in 'a' (highly inefficient) */
void bubblesort2D (char (*a)[NCHR], size_t n)
{
    size_t i, j;
    for (i = 0; i < n; i++) {
        for (j = 0; j < (n-1); j++) {
            if (strcmp_nohdr(a[j], a[j + 1]) > 0) {
                char temp[NCHR];
                strcpy_nohdr (temp, a[j + 1]);
                strcpy_nohdr  (a[j + 1], a[j]);
                strcpy_nohdr  (a[j], temp);
            }
        }
    }
}

int main (void) {
    
    char strings[][NCHR] = { "zebra", "alligators", "frogs", "racoons", "opossums" };
    size_t n = sizeof strings / sizeof *strings;
    
    bubblesort2D (strings, n);
    
    for (size_t i = 0; i < n; i++)
        puts (strings[i]);
}

示例使用/输出

结果和之前一样:

$ ./bin/sort_2d_strings_stdio
alligators
frogs
opossums
racoons
zebra

由于我最初编写了qsort()答案,因此我将其保留在下面,作为您在实践中处理排序(无论您正在排序的数组)的方式。

在实践中使用qsort()

C provides qsort() that will sort arrays of any object based on the compare function you write to tell qsort() how elements of the array are to be compares. 对于字符串,您只想返回strcmp()的结果。 compare function 的每个参数都是指向数组元素的指针 由于它是一个void*指针,因此您必须将指针转换回正确的类型。

在 C 中回想一下,2D 数组只是1D arrays 的数组 在您的情况下,它是 50 个字符的 arrays 数组。 指向 50 个字符数组的指针的类型为char (*)[50] ,因此您的qsort() compare function 可以写成如下:

int cmpstr50 (const void *a, const void *b)
{
    const char  *pa = *(char (*)[50])a,
                *pb = *(char (*)[50])b;
    
    return strcmp (pa, pb);
}

其中每个参数都是指向char [50]数组的指针。 没有什么比这更容易了。 此外, qsort()使用的算法将比您使用嵌套循环编写的算法快几个数量级。

您的案例的完整示例是:

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

int cmpstr50 (const void *a, const void *b)
{
    const char  *pa = *(char (*)[50])a,
                *pb = *(char (*)[50])b;
    
    return strcmp (pa, pb);
}

int main (void) {
    
    char strings[][50] = { "zebra", "alligators", "frogs", "racoons", "opossums" };
    size_t n = sizeof strings / sizeof *strings;
    
    qsort (strings, n, sizeof *strings, cmpstr50);
    
    for (size_t i = 0; i < n; i++)
        puts (strings[i]);
}

在编写compare function 之后,对字符串数组(或任何数组)进行排序所需的只是对qsort()的一次调用:

    qsort (strings, n, sizeof *strings, cmpstr50);

比试图重新发明轮子要简单得多。

示例使用/输出

$ ./bin/qsort_2d_strings
alligators
frogs
opossums
racoons
zebra

如果您还有其他问题,请告诉我。

这种比较是不正确的:

while((dict[j][1]<dict[k-1][1]) && (k>0))

首先,如果要比较每个单词的第一个字符,请使用[0]而不是[1] 这是因为数组索引在 C 中从零开始。 其次,先将k>0比较,然后再使用k-1作为数组的索引。 这将利用“短路”来确保您没有使用无效的数组索引。 结果:

while(k > 0 && dict[j][0] < dict[k-1][0])

另一个问题是,当您复制它们时,您没有确保您的字符串是 null 终止的。 我相信这就是你的“SEALION”出现“SEALI”的原因。 例如,这个循环:

x=0;
while(dict[k][x]!= '\0')
{
    dict[k][x]=tmp[x];
    x=x+1;
}

您正在目标而不是源上检查 null。 此外,您在 null 字符处停止复制,但实际上您也需要复制它,或者至少在末尾添加 null:

x=0;
while(tmp[x]!= '\0')
{
    dict[k][x]=tmp[x];
    x=x+1;
}
dict[k][x] = '\0';

仔细查看每个字符串复制循环是否存在此类错误。

暂无
暂无

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM