Если OP запрашивает выражения для сортировки по логическому принципу, то не во всех языках встроено выражение natural . Для c я бы пошел на <stdlib.h>
и использовал бы qsort
. Что-то на линии:
/* non-functional mess deleted */
для сортировки аргументов в лексическом порядке. К сожалению, эту идиому довольно сложно разобрать тем, кто не использовал способы c.
Соответственно наказанный понижением, я фактически прочитал связанную статью. Mea culpa.
В любом случае оригинальный код не работал, за исключением одного случая, который я тестировал. Черт. Обычная ваниль с не имеет этой функции, как и ни в одной из обычных библиотек.
Приведенный ниже код сортирует аргументы командной строки natural как связанные. Предостережение emptor , поскольку оно только слегка проверено.
#include <stdio.h>
#include <stdlib.h>
#include <string.h>
#include <ctype.h>
int naturalstrcmp(const char **s1, const char **s2);
int main(int argc, char **argv){
/* Sort the command line arguments in place */
qsort(&argv[1],argc-1,sizeof(char*),
(int(*)(const void *, const void *))naturalstrcmp);
while(--argc){
printf("%s\n",(++argv)[0]);
};
}
int naturalstrcmp(const char **s1p, const char **s2p){
if ((NULL == s1p) || (NULL == *s1p)) {
if ((NULL == s2p) || (NULL == *s2p)) return 0;
return 1;
};
if ((NULL == s2p) || (NULL == *s2p)) return -1;
const char *s1=*s1p;
const char *s2=*s2p;
do {
if (isdigit(s1[0]) && isdigit(s2[0])){
/* Compare numbers as numbers */
int c1 = strspn(s1,"0123456789"); /* Could be more efficient here... */
int c2 = strspn(s2,"0123456789");
if (c1 > c2) {
return 1;
} else if (c1 < c2) {
return -1;
};
/* the digit strings have equal length, so compare digit by digit */
while (c1--) {
if (s1[0] > s2[0]){
return 1;
} else if (s1[0] < s2[0]){
return -1;
};
s1++;
s2++;
};
} else if (s1[0] > s2[0]){
return 1;
} else if (s1[0] < s2[0]){
return -1;
};
s1++;
s2++;
} while ( (s1!='\0') || (s2!='\0') );
return 0;
}
Этот подход довольно грубая сила, но он прост и, вероятно, может быть продублирован на любом императивном языке.