Ответ 1
Фактически я использовал функцию Саула в аналитической программе, которую я писал (анализируя миллионы строк с кодировкой URL), и, хотя она работает, в этом масштабе она очень замедляла мою программу, поэтому я решил написать более быструю версию. Это в тысячу раз быстрее при компиляции с GCC и опцией -O2. Он также может использовать тот же выходной буфер, что и вход (например, urldecode2 (buf, buf) будет работать, если исходная строка была в buf и должна быть перезаписана его декодированной копией).
Изменить: Он не принимает размер буфера в качестве ввода, поскольку предполагается, что буфер будет достаточно большим, это безопасно, поскольку известно, что длина вывода всегда будет be <= the the input, поэтому либо используйте один и тот же буфер для вывода, либо создайте тот, который по меньшей мере имеет размер ввода + 1 для нулевого терминатора, например:
char *output = malloc(strlen(input)+1);
urldecode2(output, input);
printf("Decoded string: %s\n", output);
Изменить 2:. Анонимный пользователь попытался отредактировать этот ответ, чтобы обработать перевод символа "+" на "", который, я думаю, должен это сделать, опять же, это не то, что мне нужно для моего приложения, но я добавил его ниже.
Здесь процедура:
#include <stdlib.h>
#include <ctype.h>
void urldecode2(char *dst, const char *src)
{
char a, b;
while (*src) {
if ((*src == '%') &&
((a = src[1]) && (b = src[2])) &&
(isxdigit(a) && isxdigit(b))) {
if (a >= 'a')
a -= 'a'-'A';
if (a >= 'A')
a -= ('A' - 10);
else
a -= '0';
if (b >= 'a')
b -= 'a'-'A';
if (b >= 'A')
b -= ('A' - 10);
else
b -= '0';
*dst++ = 16*a+b;
src+=3;
} else if (*src == '+') {
*dst++ = ' ';
src++;
} else {
*dst++ = *src++;
}
}
*dst++ = '\0';
}