将 qsort() 与 3D char 数组一起使用时出现问题
我正在制作一个 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 技术交流群。

绑定邮箱获取回复消息
由于您还没有绑定你的真实邮箱,如果其他用户或者作者回复了您的评论,将不能在第一时间通知您!
发布评论
评论(1)
问题是数组的数组的数组与指向指针的指针不同。
虽然数组确实会衰减为指针(指向它们的第一个元素),但衰减不会传播。您还必须记住,
qsort
将指针传递给数组中的每个元素。因此,
qsort
函数将(有效地)调用您的cmpfunc
,类似于:由于
tabLigne
的每个元素都是数组的数组(类型char [NB_PARAMETER][MAX_STRING_SIZE]
),则指向元素的指针将为 char (*)[NB_PARAMETER][MAX_STRING_SIZE]。这是您需要在函数内部进行转换时使用的类型:
您还将错误的元素大小传递给
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 yourcmpfunc
similar to:Since each element of
tabLigne
is an array of arrays (typechar [NB_PARAMETER][MAX_STRING_SIZE]
) then a pointer to an element will bechar (*)[NB_PARAMETER][MAX_STRING_SIZE]
.That's the type you need to use for the cast inside the function:
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 intabLigne
. And that size is gotten bysizeof tabLigne[0]
.