Utilizzo di qsort() di stdlib per ordinare un array di stringhe
-
27-10-2019 - |
Domanda
Qualche prefazione:Sono uno studente di ingegneria informatica che segue una prima lezione in C dopo 3 semestri di Java (fino a strutture dati).Questa domanda è in relazione a un compito a casa, ma mi mancano alcuni passaggi per risolverlo.
Ho un file di input che leggo in memoria in modo tale che sia archiviato in char[9][500].Ho letto al massimo 500 stringhe di lunghezza massima 8.Sto tentando di ordinare questo array utilizzando la funzione qsort() incorporata di stdlib e riscontro alcuni errori di memoria.
Frammenti di codice importanti:
char data[4][500][60];
char debug[500][9];
size_t count = 0;
/* initialize file, open for reading */
FILE* pUserlog;
pUserlog = fopen("userlog","r");
while(!feof(pUserlog))
{
fscanf(pUserlog, "%9s %8s %16s",debug[count], data[1][count], data[2][count]);
fgets(data[3][count], 60, pUserlog);
count++;
}
Questa sezione legge i dati negli array.L'array di interesse in questa parte è "debug".Questo è l'array specificato sopra.Ecco la mia funzione di confronto per qsort:
int compare(const void* a, const void* b)
{
const char **ia = (const char **)a;
const char **ib = (const char **)b;
puts("I'm in compare!");
return strncmp(*ia, *ib,8);
}
Questo è il mio tentativo di chiamare qsort:
size_t debug_len = sizeof(debug)/sizeof(char*);
printf("debug len: %d, count: %d, sizeof(char*): %d\n",debug_len,count,sizeof(char*));
qsort(debug,count, sizeof(char *), compare);
Ho tentato di sostituire debug_len nella mia chiamata dove si trova count, ma sto ancora effettuando il segfault.Ecco l'output:
$ ./test debug len: 1125, count: 453, sizeof(char*): 4 I'm in compare! Segmentation fault (core dumped)
Grazie!
Soluzione
La funzione di confronto riceverà puntatori agli elementi che vengono confrontati. Stai effettivamente cercando di confrontare i personaggi usando strncmp()
. Dato che hai puntatori a ciascuna delle corde, lanciarlo a a char *
e confronta.
int compare(const void* a, const void* b)
{
const char *ia = (const char *)a;
const char *ib = (const char *)b;
puts("I'm in compare!");
return strncmp(ia, ib, 9);
}
Ricorda anche, è una serie di array, non una serie di suggerimenti. Quindi la dimensione di un elemento dovrebbe avere la dimensione dell'array, 9
e non del puntatore, 4
. A questo punto, sarebbe più facile usare sizeof debug[0]
poiché è un array bidimensionale. Se non lo fai con le dimensioni giuste, qsort()
Distruggerà solo il tuo array.
size_t elemsize = sizeof debug[0]; /* 9 - size of each element */
size_t count = sizeof(debug)/elemsize; /* 500 - number of elements in array */
qsort(debug, count, elemsize, compare);
Altri suggerimenti
Quello che succede qui è:hai 500 corde.Ora passi tutti e 500 a qsort, che a sua volta li passa ciascuno come primo e secondo argomento alla tua funzione di confronto.E' un po' come scrivere questo:
compare(debug[0], debug[1])
Il compilatore C passa gli indirizzi, ovviamente non i valori effettivi.Ma ora interpreti il puntatore a vuoto come puntatore a puntatore a carattere.Il tuo codice ora esegue una dereferenziazione durante la chiamata strncmp
, ma questo rende il valore (i primi 4 byte) essere trattati come un puntatore in strncmp
.Ma strncmp
proverà ora a sua volta a dereferenziare il "puntatore" spazzatura (che consiste in parte di una delle tue stringhe) e questo rende scoppio.
Per risolvere questo problema, utilizzare char *
invece di char **
:
int compare(const void* a, const void* b)
{
puts("I'm in compare!");
return strncmp((const char *)a, (const char *)b, 8);
}