C语言实现URL编码
URL编码(也称为百分比编码)是一种将特殊字符转换为安全字符表示的方法,用于在URL中传输数据,下面我将提供一个完整的C语言实现。

(图片来源网络,侵删)
基本实现
#include <stdio.h>
#include <string.h>
#include <ctype.h>
// 需要编码的字符集合
static const char *needs_encoding = " !\"#$%&'()*+,/:;<=>?@[\\]^`{|}~";
// URL编码函数
void url_encode(const char *src, char *dest, int max_len) {
const unsigned char *p = (const unsigned char *)src;
char *d = dest;
int len = 0;
while (*p && len < max_len - 1) {
if (isalnum(*p) || *p == '-' || *p == '_' || *p == '.' || *p == '~') {
// 这些字符不需要编码
*d++ = *p;
len++;
} else if (strchr(needs_encoding, *p)) {
// 特殊字符需要编码
if (len >= max_len - 3) break; // 需要空间存储%XX
sprintf(d, "%%%02X", *p);
d += 3;
len += 3;
} else {
// 其他字符(如非ASCII字符)也需要编码
if (len >= max_len - 3) break;
sprintf(d, "%%%02X", *p);
d += 3;
len += 3;
}
p++;
}
*d = '\0';
}
int main() {
const char *test_str = "Hello World! 你好 123@#$%";
char encoded[256];
url_encode(test_str, encoded, sizeof(encoded));
printf("原始字符串: %s\n", test_str);
printf("编码后字符串: %s\n", encoded);
return 0;
}
更完整的实现(处理非ASCII字符)
#include <stdio.h>
#include <string.h>
#include <ctype.h>
#include <locale.h>
// URL编码函数(处理UTF-8字符)
void url_encode_utf8(const char *src, char *dest, size_t max_len) {
const unsigned char *p = (const unsigned char *)src;
char *d = dest;
size_t len = 0;
while (*p && len < max_len - 1) {
if (isalnum(*p) || *p == '-' || *p == '_' || *p == '.' || *p == '~') {
// 这些字符不需要编码
*d++ = *p;
len++;
} else if (*p < 128) {
// ASCII字符需要编码的特殊字符
if (len >= max_len - 3) break;
sprintf(d, "%%%02X", *p);
d += 3;
len += 3;
} else {
// 非ASCII字符(UTF-8多字节字符)
int bytes = 0;
unsigned int codepoint = 0;
// 确定UTF-8字符的字节数
if ((*p & 0xE0) == 0xC0) { bytes = 2; codepoint = *p & 0x1F; }
else if ((*p & 0xF0) == 0xE0) { bytes = 3; codepoint = *p & 0x0F; }
else if ((*p & 0xF8) == 0xF0) { bytes = 4; codepoint = *p & 0x07; }
else { bytes = 1; codepoint = *p; } // 无效UTF-8,按单字节处理
// 检查是否有足够空间
if (len + bytes * 3 >= max_len) break;
// 处理UTF-8字符的每个字节
for (int i = 0; i < bytes; i++) {
if (len >= max_len - 3) break;
sprintf(d, "%%%02X", *p);
d += 3;
len += 3;
p++;
}
continue; // 已经处理了p的移动
}
p++;
}
*d = '\0';
}
int main() {
setlocale(LC_ALL, ""); // 设置本地化环境以支持宽字符
const char *test_str = "Hello World! 你好 123@#$% 中文测试";
char encoded[512];
url_encode_utf8(test_str, encoded, sizeof(encoded));
printf("原始字符串: %s\n", test_str);
printf("编码后字符串: %s\n", encoded);
return 0;
}
URL解码函数
#include <stdio.h>
#include <string.h>
#include <ctype.h>
#include <stdlib.h>
// URL解码函数
void url_decode(const char *src, char *dest, size_t max_len) {
const char *p = src;
char *d = dest;
size_t len = 0;
while (*p && len < max_len - 1) {
if (*p == '%' && *(p+1) && *(p+2)) {
// 检查是否是有效的十六进制数字
if (isxdigit(*(p+1)) && isxdigit(*(p+2))) {
char hex[3] = {*(p+1), *(p+2), '\0'};
*d++ = (char)strtol(hex, NULL, 16);
len++;
p += 3;
} else {
// 无效的编码,直接复制%
*d++ = *p++;
len++;
}
} else if (*p == '+') {
// 空格在URL中有时被编码为+
*d++ = ' ';
len++;
p++;
} else {
// 普通字符直接复制
*d++ = *p++;
len++;
}
}
*d = '\0';
}
int main() {
const char *encoded_str = "Hello%20World%21%20%E4%BD%A0%E5%A5%BD%20123%40%23%24%25";
char decoded[256];
url_decode(encoded_str, decoded, sizeof(decoded));
printf("编码字符串: %s\n", encoded_str);
printf("解码字符串: %s\n", decoded);
return 0;
}
使用示例
#include <stdio.h>
#include "url_encode.h" // 假设上面的函数定义在这个头文件中
int main() {
// 编码示例
const char *to_encode = "参数值=测试&name=张三";
char encoded[256];
url_encode(to_encode, encoded, sizeof(encoded));
printf("编码: %s -> %s\n", to_encode, encoded);
// 解码示例
const char *to_decode = "%%20%E6%B5%8B%E8%AF%95";
char decoded[256];
url_decode(to_decode, decoded, sizeof(decoded));
printf("解码: %s -> %s\n", to_decode, decoded);
return 0;
}
注意事项
- 编码函数需要确保目标缓冲区足够大,最坏情况下每个字符都会变成3个字符(%XX)
- 对于非ASCII字符(如中文),需要正确处理UTF-8编码
- 空格在URL中通常编码为%20,但有时也会用+表示
- 实际应用中可能需要根据具体需求调整需要编码的字符集
- 考虑添加错误处理,特别是对于无效的UTF-8序列
实现提供了基本的URL编码和解码功能,可以根据具体需求进行扩展和优化。

(图片来源网络,侵删)
