将 qsort() 与 3D char 数组一起使用时出现问题

发布于 2025-01-15 08:42:30 字数 3705 浏览 4 评论 0原文

我正在制作一个 C 程序,为未来的计划反汇编 .ics 文件,并将其存储在数组中。所以我正在制作一个 3 维数组,其中包含它在文件中找到的每个 VEVENT 的每一行;

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

#define MAX_STRING_SIZE 85
#define LINE_STRING_SIZE 80
#define NB_PARAMETER 12

int cmpfunc(const void* pa, const void* pb){
    /* Comparison function for qsort();
    /* Expected : sort entire array by DTSTART line
     * which strcmp() can do between two elements
     */
    const char *a = ((const char ***) pa)[0][2];
    const char *b = ((const char ***) pb)[0][2];
    return strcmp(a,b);
}

int main(int nbArgs, char *arg[])
{
    //Opening file
    FILE* cal = fopen(arg[1], "r");
    if (cal == NULL)
        exit(EXIT_FAILURE);
    //Counting number of "BEGIN:VEVENT" lines
    int eventNB = 0;
    char ligne[LINE_STRING_SIZE];
    while(strncmp(ligne, "END:VCALENDAR", 13) != 0){
        fgets(ligne, LINE_STRING_SIZE, cal);
        if(strncmp(ligne, "BEGIN:VEVENT", 12) == 0){
            eventNB++;
        }
    }
    rewind(cal);
    //Array creation
    char tabLigne[eventNB][NB_PARAMETER][MAX_STRING_SIZE];
    //Repositionning at first "BEGIN:VEVENT"
    while(strncmp(ligne, "BEGIN:VEVENT", 12) != 0){
        fgets(ligne, LINE_STRING_SIZE, cal);
    }
    int indexLigne = 0;
    int indexEvent = 0;
    while(strncmp(ligne, "END:VCALENDAR", 13) != 0){
        while(strncmp(ligne, "END:VEVENT", 10) != 0){
            strcpy(tabLigne[indexEvent][indexLigne], ligne);
            indexLigne++;
            fgets(ligne, LINE_STRING_SIZE, cal);
            //In case of DESCRIPTION overflow to next line :
            if(indexLigne == 7 && strncmp(ligne, "UID", 3) != 0){
                int previousLineSize = (int)strlen(tabLigne[indexEvent][indexLigne-1])-2;
                for (int k = previousLineSize; k < previousLineSize+(int)strlen(ligne)-1; k++){
                    tabLigne[indexEvent][indexLigne-1][k] = ligne[k-previousLineSize+1];
                } 
                
                //strcat(tabLigne[indexEvent][indexLigne-1], ligne);
                fgets(ligne, LINE_STRING_SIZE, cal);
            }
        }
        strcpy(tabLigne[indexEvent][indexLigne], ligne);
        fgets(ligne, LINE_STRING_SIZE, cal);
        indexEvent++;
        indexLigne = 0;
    }
    //Sorting (what doesn't work like I want it to)
    qsort(tabLigne, eventNB, sizeof(tabLigne[0][2]), cmpfunc);
    
    //Just displaying
    for (int i = 0 ; i < eventNB ; i++){
        for (int j = 0 ; j < 12 ; j++){
            printf("%s", tabLigne[i][j]);
        }
        printf("\n");
    }
    
    return 0;
}

有一个看起来像这样的文件;

BEGIN:VCALENDAR
METHOD:REQUEST
PRODID:-//ADE/version 6.0
VERSION:2.0
CALSCALE:GREGORIAN
BEGIN:VEVENT
DTSTAMP:20220206T080021Z
DTSTART:20220228T100000Z
DTEND:20220228T113000Z
SUMMARY:Evenement 4 -rf
LOCATION:117
DESCRIPTION:\n\nIF S2 TD2\nHGLEP LDTEB QS\n(Exporté le:06/02/2022 09:00)\n
UID:ADE604955542d56616c656e63652d323032312d323032322d313033392d302d34
CREATED:19700101T000000Z
LAST-MODIFIED:20220206T080021Z
SEQUENCE:-2091234875
END:VEVENT
BEGIN:VEVENT
DTSTAMP:20220206T080021Z
DTSTART:20220302T143000Z
DTEND:20220302T160000Z
SUMMARY:Evenement 89 -hg
LOCATION:101
DESCRIPTION:\n\nIF S2 TP2C\nABBY KDJEUTBDOLSP\n(Exporté le:06/02/2022 09:
00)\n
UID:ADE604955542d56616c656e63652d323032312d323032322d3937362d302d32
CREATED:19700101T000000Z
LAST-MODIFIED:20220206T080021Z
SEQUENCE:-2091234875
END:VEVENT
END:VCALENDAR

现在我想按 DTSTART 特性对所有 VEVENT 进行排序(存储在 tabLigne[x][2] 中,我可以使用 strcmp() 在两个元素之间执行此操作)。问题是我不知道 qsort() 是如何工作的,不断出现“分段错误(核心转储)”,并且我花了几周的时间试图让它工作。

I'm making a C program that disassemble a .ics file for future plans, and stores it in a array. So I'm making a 3 dimention array that contains every lines for every VEVENT it finds in the file ;

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

#define MAX_STRING_SIZE 85
#define LINE_STRING_SIZE 80
#define NB_PARAMETER 12

int cmpfunc(const void* pa, const void* pb){
    /* Comparison function for qsort();
    /* Expected : sort entire array by DTSTART line
     * which strcmp() can do between two elements
     */
    const char *a = ((const char ***) pa)[0][2];
    const char *b = ((const char ***) pb)[0][2];
    return strcmp(a,b);
}

int main(int nbArgs, char *arg[])
{
    //Opening file
    FILE* cal = fopen(arg[1], "r");
    if (cal == NULL)
        exit(EXIT_FAILURE);
    //Counting number of "BEGIN:VEVENT" lines
    int eventNB = 0;
    char ligne[LINE_STRING_SIZE];
    while(strncmp(ligne, "END:VCALENDAR", 13) != 0){
        fgets(ligne, LINE_STRING_SIZE, cal);
        if(strncmp(ligne, "BEGIN:VEVENT", 12) == 0){
            eventNB++;
        }
    }
    rewind(cal);
    //Array creation
    char tabLigne[eventNB][NB_PARAMETER][MAX_STRING_SIZE];
    //Repositionning at first "BEGIN:VEVENT"
    while(strncmp(ligne, "BEGIN:VEVENT", 12) != 0){
        fgets(ligne, LINE_STRING_SIZE, cal);
    }
    int indexLigne = 0;
    int indexEvent = 0;
    while(strncmp(ligne, "END:VCALENDAR", 13) != 0){
        while(strncmp(ligne, "END:VEVENT", 10) != 0){
            strcpy(tabLigne[indexEvent][indexLigne], ligne);
            indexLigne++;
            fgets(ligne, LINE_STRING_SIZE, cal);
            //In case of DESCRIPTION overflow to next line :
            if(indexLigne == 7 && strncmp(ligne, "UID", 3) != 0){
                int previousLineSize = (int)strlen(tabLigne[indexEvent][indexLigne-1])-2;
                for (int k = previousLineSize; k < previousLineSize+(int)strlen(ligne)-1; k++){
                    tabLigne[indexEvent][indexLigne-1][k] = ligne[k-previousLineSize+1];
                } 
                
                //strcat(tabLigne[indexEvent][indexLigne-1], ligne);
                fgets(ligne, LINE_STRING_SIZE, cal);
            }
        }
        strcpy(tabLigne[indexEvent][indexLigne], ligne);
        fgets(ligne, LINE_STRING_SIZE, cal);
        indexEvent++;
        indexLigne = 0;
    }
    //Sorting (what doesn't work like I want it to)
    qsort(tabLigne, eventNB, sizeof(tabLigne[0][2]), cmpfunc);
    
    //Just displaying
    for (int i = 0 ; i < eventNB ; i++){
        for (int j = 0 ; j < 12 ; j++){
            printf("%s", tabLigne[i][j]);
        }
        printf("\n");
    }
    
    return 0;
}

With a file that looks like this ;

BEGIN:VCALENDAR
METHOD:REQUEST
PRODID:-//ADE/version 6.0
VERSION:2.0
CALSCALE:GREGORIAN
BEGIN:VEVENT
DTSTAMP:20220206T080021Z
DTSTART:20220228T100000Z
DTEND:20220228T113000Z
SUMMARY:Evenement 4 -rf
LOCATION:117
DESCRIPTION:\n\nIF S2 TD2\nHGLEP LDTEB QS\n(Exporté le:06/02/2022 09:00)\n
UID:ADE604955542d56616c656e63652d323032312d323032322d313033392d302d34
CREATED:19700101T000000Z
LAST-MODIFIED:20220206T080021Z
SEQUENCE:-2091234875
END:VEVENT
BEGIN:VEVENT
DTSTAMP:20220206T080021Z
DTSTART:20220302T143000Z
DTEND:20220302T160000Z
SUMMARY:Evenement 89 -hg
LOCATION:101
DESCRIPTION:\n\nIF S2 TP2C\nABBY KDJEUTBDOLSP\n(Exporté le:06/02/2022 09:
00)\n
UID:ADE604955542d56616c656e63652d323032312d323032322d3937362d302d32
CREATED:19700101T000000Z
LAST-MODIFIED:20220206T080021Z
SEQUENCE:-2091234875
END:VEVENT
END:VCALENDAR

Now I want to sort all of thoses VEVENT by their DTSTART caracteristic (stored in tabLigne[x][2], which I can use strcmp() to do between two elements). Problem is I have no idea how qsort() works, keep getting "segmentation fault (core dumped)" and I've spent weeks trying to make it work.

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

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

发布评论

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

评论(1

帥小哥 2025-01-22 08:42:30

问题是数组的数组的数组与指向指针的指针不同。

虽然数组确实会衰减为指针(指向它们的第一个元素),但衰减不会传播。您还必须记住,qsort 将指针传递给数组中的每个元素。

因此,qsort 函数将(有效地)调用您的 cmpfunc,类似于:

cmpfunc(&tabLigne[0], &tabLigne[1])

由于 tabLigne 的每个元素都是数组的数组(类型 char [NB_PARAMETER][MAX_STRING_SIZE]),则指向元素的指针将为 char (*)[NB_PARAMETER][MAX_STRING_SIZE]。

这是您需要在函数内部进行转换时使用的类型:

const char (*a)[NB_PARAMETER][MAX_STRING_SIZE] = pa;
const char (*b)[NB_PARAMETER][MAX_STRING_SIZE] = pb;

return strcmp((*a)[2], (*b)[2]);

您还将错误的元素大小传递给 qsort 函数。

元素大小(qsort 的第三个参数)应该是 tabLigne 中每个元素的大小。该大小是通过 sizeof tabLigne[0] 获得的。

The problem is that an array of arrays of arrays is not the same as a pointer to a pointer to a pointer.

While it's true that arrays decays to pointers (to their first element) that decay doesn't propagate. You also have to remember that qsort passes pointers to each element in the array.

So the qsort function will (effectively) call your cmpfunc similar to:

cmpfunc(&tabLigne[0], &tabLigne[1])

Since each element of tabLigne is an array of arrays (type char [NB_PARAMETER][MAX_STRING_SIZE]) then a pointer to an element will be char (*)[NB_PARAMETER][MAX_STRING_SIZE].

That's the type you need to use for the cast inside the function:

const char (*a)[NB_PARAMETER][MAX_STRING_SIZE] = pa;
const char (*b)[NB_PARAMETER][MAX_STRING_SIZE] = pb;

return strcmp((*a)[2], (*b)[2]);

You also pass the wrong element size to the qsort function.

Tbe element size (the third argument to qsort) should be the size of each element in tabLigne. And that size is gotten by sizeof tabLigne[0].

~没有更多了~
我们使用 Cookies 和其他技术来定制您的体验包括您的登录状态等。通过阅读我们的 隐私政策 了解更多相关信息。 单击 接受 或继续使用网站,即表示您同意使用 Cookies 和您的相关数据。
原文