qsort 不排序并且输出奇怪

发布于 2024-11-09 20:23:42 字数 1690 浏览 0 评论 0原文

所以我正在使用C,我似乎无法让它正常工作。它是一个指向包含一些联系信息的结构的指针数组。我似乎无法让 qsort 正确排序。 这是我的代码

#include <stdio.h>
#include <stdlib.h>
#include <string.h>
#define MAX 20
#define ELEMENTS 50

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

typedef struct contactInfo {
char name[MAX];
char street[MAX];
char cityState[MAX];
char zipCode[MAX];
} contacts;


int main() {
int i = 0;
contacts **contactArray = malloc(ELEMENTS * sizeof(contacts *));     

/*  allocate array  */
for (i = 0; i < ELEMENTS; i++) {
    contactArray[i] = malloc(sizeof(contacts));
}
/*  populate array  */
for (i = 0; i < ELEMENTS; i++) {
    fgets(contactArray[i]->name,MAX,stdin);
    fgets(contactArray[i]->street,MAX,stdin);
    fgets(contactArray[i]->cityState,MAX,stdin);
    fgets(contactArray[i]->zipCode,MAX,stdin);

    printf("%s", contactArray[i]->name);
    printf("%s", contactArray[i]->street);
    printf("%s", contactArray[i]->cityState);
    printf("%s", contactArray[i]->zipCode);

}
printf("\n");


/*  qsort((void *)contactArray, ELEMENTS, sizeof(contacts *), sortZips);  */


for (i = 0; i < ELEMENTS; i++) {
    fputs(contactArray[i]->name,stdout);
    fputs(contactArray[i]->street,stdout);
    fputs(contactArray[i]->cityState,stdout);
    fputs(contactArray[i]->zipCode,stdout);
}


}


/*  sortZips() sort function for qsort  */

int sortZips(const void *a, const void *b) {

const contacts *ia = *(contacts **)a;
const contacts *ib = *(contacts **)b;
return strcmp(ia->zipCode, ib->zipCode);



}

输出是打印地址(我在输入文件中有 50 个),然后是一些随机字符,比如一大块,然后是排序后的列表,该列表混乱且排序不正确。

请提供任何帮助,我们将不胜感激。我需要了解这里出了什么问题以及原因。 谢谢。

so I'm using C, I cant seem to get this to work right. It's an array of pointers to structs which contain some contact info. I can't seem to get the qsort to sort correctly.
Here is my code

#include <stdio.h>
#include <stdlib.h>
#include <string.h>
#define MAX 20
#define ELEMENTS 50

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

typedef struct contactInfo {
char name[MAX];
char street[MAX];
char cityState[MAX];
char zipCode[MAX];
} contacts;


int main() {
int i = 0;
contacts **contactArray = malloc(ELEMENTS * sizeof(contacts *));     

/*  allocate array  */
for (i = 0; i < ELEMENTS; i++) {
    contactArray[i] = malloc(sizeof(contacts));
}
/*  populate array  */
for (i = 0; i < ELEMENTS; i++) {
    fgets(contactArray[i]->name,MAX,stdin);
    fgets(contactArray[i]->street,MAX,stdin);
    fgets(contactArray[i]->cityState,MAX,stdin);
    fgets(contactArray[i]->zipCode,MAX,stdin);

    printf("%s", contactArray[i]->name);
    printf("%s", contactArray[i]->street);
    printf("%s", contactArray[i]->cityState);
    printf("%s", contactArray[i]->zipCode);

}
printf("\n");


/*  qsort((void *)contactArray, ELEMENTS, sizeof(contacts *), sortZips);  */


for (i = 0; i < ELEMENTS; i++) {
    fputs(contactArray[i]->name,stdout);
    fputs(contactArray[i]->street,stdout);
    fputs(contactArray[i]->cityState,stdout);
    fputs(contactArray[i]->zipCode,stdout);
}


}


/*  sortZips() sort function for qsort  */

int sortZips(const void *a, const void *b) {

const contacts *ia = *(contacts **)a;
const contacts *ib = *(contacts **)b;
return strcmp(ia->zipCode, ib->zipCode);



}

The output is printing the addresses (I have 50 in an input file) and then some random characters, like a huge block of them, then the sorted list after that which is messed up and not sorted right.

Please any help would be appreciated. I need to learn what's wrong here and why.
Thanx.

如果你对这篇内容有疑问,欢迎到本站社区发帖提问 参与讨论,获取更多帮助,或者扫码二维码加入 Web 技术交流群。

扫码二维码加入Web技术交流群

发布评论

需要 登录 才能够评论, 你可以免费 注册 一个本站的账号。

评论(3

要走就滚别墨迹 2024-11-16 20:23:42

第一条规则:始终检查输入函数 - 在本例中为 fgets()。如果不检查,您就不知道一切是否正常工作。

第二:一般情况下,优先使用 enum 而不是 #define

通过对早期 EOF 的检查,您的代码可以干净地对我的示例数据(6 行)进行排序。它还可以干净地编译 - 这是非常不寻常的(这是一种恭维;我使用严格的警告,甚至我的代码很少第一次就可以干净地编译)。我修改后的代码版本与您的非常相似:

int main(void)
{
    int i = 0;
    int num;
    contacts **contactArray = malloc(ELEMENTS * sizeof(contacts *));

    /*  allocate array  */
    for (i = 0; i < ELEMENTS; i++)
        contactArray[i] = malloc(sizeof(contacts));

    /*  populate array  */
    for (i = 0; i < ELEMENTS; i++)
    {
        if (fgets(contactArray[i]->name,MAX,stdin) == 0 ||
            fgets(contactArray[i]->street,MAX,stdin) == 0 ||
            fgets(contactArray[i]->cityState,MAX,stdin) == 0 ||
            fgets(contactArray[i]->zipCode,MAX,stdin) == 0)
            break;
        printf("%s", contactArray[i]->name);
        printf("%s", contactArray[i]->street);
        printf("%s", contactArray[i]->cityState);
        printf("%s", contactArray[i]->zipCode);
    }
    printf("\n");
    num = i;

    qsort(contactArray, num, sizeof(contacts *), sortZips);

    for (i = 0; i < num; i++)
    {
        fputs(contactArray[i]->name,stdout);
        fputs(contactArray[i]->street,stdout);
        fputs(contactArray[i]->cityState,stdout);
        fputs(contactArray[i]->zipCode,stdout);
    }
    return 0;
}

我使用的数据是 4 行集的简单重复,如下所示:

First LastName7
7 Some Street
City, CA
95437

请注意,我在输入中执行的“错误检查”是“有效”的最低限度。如果输入中的行过长,则一个字段将不包含换行符,下一个字段将包含输入行的下一部分(可能是所有其余部分,也可能不是 - 这取决于该行的过长程度)。

First rule: always check input functions - in this case, fgets(). You don't know whether everything is working correctly or not if you do not check.

Second: use enum in preference to #define in general.

With the check for early EOF in place, your code sorted my sample data (6 rows) cleanly. It also compiled cleanly - which is very unusual (that's a compliment; I use stringent warnings and even my code seldom compiles cleanly the first time). My amended version of your code is very similar to yours:

int main(void)
{
    int i = 0;
    int num;
    contacts **contactArray = malloc(ELEMENTS * sizeof(contacts *));

    /*  allocate array  */
    for (i = 0; i < ELEMENTS; i++)
        contactArray[i] = malloc(sizeof(contacts));

    /*  populate array  */
    for (i = 0; i < ELEMENTS; i++)
    {
        if (fgets(contactArray[i]->name,MAX,stdin) == 0 ||
            fgets(contactArray[i]->street,MAX,stdin) == 0 ||
            fgets(contactArray[i]->cityState,MAX,stdin) == 0 ||
            fgets(contactArray[i]->zipCode,MAX,stdin) == 0)
            break;
        printf("%s", contactArray[i]->name);
        printf("%s", contactArray[i]->street);
        printf("%s", contactArray[i]->cityState);
        printf("%s", contactArray[i]->zipCode);
    }
    printf("\n");
    num = i;

    qsort(contactArray, num, sizeof(contacts *), sortZips);

    for (i = 0; i < num; i++)
    {
        fputs(contactArray[i]->name,stdout);
        fputs(contactArray[i]->street,stdout);
        fputs(contactArray[i]->cityState,stdout);
        fputs(contactArray[i]->zipCode,stdout);
    }
    return 0;
}

The data I used was trivial repetitions of sets of 4 lines like this:

First LastName7
7 Some Street
City, CA
95437

Note that the 'error checking' I do in the input is the bare minimum that 'works'. If you get an over-long line in the input, one field will not contain a newline, and the next will contain the next section of the input line (possibly all the rest, possibly not - it depends on how badly overlong the line is).

高速公鹿 2024-11-16 20:23:42

如果您的地址最后打印出垃圾,那么几乎可以肯定是因为您没有为它们分配足够的空间。对于地址来说,二十个字符有点少。

可能发生的情况是,您的地址如下:

14237 Verylongstreetname Avenue

并且,当您执行 fgets (street,20,stdin); 时,只会读取 14237 Verylongstree (19 个字符,为空终止符留出空间)。

而且,关键在于:文件指针仍然指向 tname Avenue 位,这样,当您尝试读取 cityState 时,您就会得到它。而且,当您尝试读取 zipCode 时,您将得到 cityState 行,从而有效地填充您的排序。

If your addresses are printing out rubbish at the end, then it's almost certainly because you haven't allocated enough space for them. Twenty characters is a little on the low side for addresses.

What's probably happening is that you have an address like:

14237 Verylongstreetname Avenue

and, when you do fgets (street,20,stdin);, only 14237 Verylongstree will be read (19 characters, leaving space for the null terminator).

And, here's the crux: the file pointer will still be pointing at the tname Avenue bit so that, when you try to read the cityState, you'll get that. And, when you try to read the zipCode, you'll get the cityState line, effectively stuffing up your sorting.

一个人的夜不怕黑 2024-11-16 20:23:42

我相信你有足够的空间。由于您使用的是 fgets 且大小为 MAX,因此应剪切字符串以适合并在末尾有一个终止 NUL。

有两件事可能会搞砸:

  • 如果行太长,fgets 将从停止读取的地方读取。这将导致地址“这太长了”,“它将被剪切\n”。然后剩下的输入就会到处都是。
  • 如果您没有足够的输入来填充 ELEMENTS 项,那么您将获得 malloc 内存中的任何随机数据。如果您使用calloc,它会为您清零内存。尽管更好的想法是使用实​​际读取的项目数的计数器,而不是假设会有 ELEMENTS 项目。

I believe that you have enough space. Because you are using fgets and your size of MAX, the strings should be cut to fit and have a terminating NUL at the end.

Two things that might be messing it up:

  • fgets will read from where it stopped reading if the line is too long. That will result in an address of "This is too long so", " it will be cut\n". And then the rest of the input will be all over the place.
  • If you do not have enough input to fill ELEMENTS items then you'll get whatever random data was in the malloc'd memory. If you were to use calloc instead, it would zero the memory for you. Although the better idea would be to use a counter of how many items were actually read, instead of assuming there will be ELEMENTS items.
~没有更多了~
我们使用 Cookies 和其他技术来定制您的体验包括您的登录状态等。通过阅读我们的 隐私政策 了解更多相关信息。 单击 接受 或继续使用网站,即表示您同意使用 Cookies 和您的相关数据。
原文