URL编/解码的C实现
1.1、URL编/解码的接口定义
#ifndef URL_H
#define URL_H

    #include <stdlib.h>
    #include <stdbool.h>

    #ifdef __cplusplus
        extern "C" {
    #endif

    char* url_encode         (unsigned char *bytes, size_t bytesLength, bool isToUpper);
    char* url_encode_to_upper(unsigned char *bytes, size_t bytesLength);
    char* url_encode_to_lower(unsigned char *bytes, size_t bytesLength);

    unsigned char* url_decode(char *input, size_t *outputLength);

    #ifdef __cplusplus
        }
    #endif
#endif
1.2、URL编码实现
#include <string.h>
#include "URL.h"

char* url_encode(unsigned char *bytes, size_t bytesLength, bool isToUpper) {
    const char *table = isToUpper ? "0123456789ABCDEF" : "0123456789abcdef";

    size_t outputLength = 0;
    //以最坏的情况分配内存
    char *output = (char *)calloc(3 * bytesLength + 1, sizeof(char));
    for (size_t i = 0; i < bytesLength; i++) {
        unsigned char byte = bytes[i];
        //这些字符保持原样
        if (('0' <= byte && byte <= '9') ||
            ('a' <= byte && byte <= 'z') ||
            ('A' <= byte && byte <= 'Z') ||
            byte == '.' || byte == '_' || byte == '-' || byte == '*') {
            output[outputLength++] = byte;
        } else if (' ' == byte) { //把空格编码成+
            output[outputLength++] = '+';
        } else { //其他字符都转换成%XY,XY是Base16编码
            //向右移动4bit,获得高4bit
            unsigned char highByte = byte >> 4;
            //与0x0f做位与运算,获得低4bit
            unsigned char lowByte = byte & 0x0F;
            //由于高4bit和低4bit都只有4个bit,他们转换成10进制的数字,范围都在0 ~ 15闭区间内
            //大端模式
            output[outputLength++] = '%';
            output[outputLength++] = table[highByte];
            output[outputLength++] = table[lowByte];
        }
    }
    return output;
}

char* url_encode_to_upper(unsigned char *bytes, size_t bytesLength) {
    return url_encode(bytes, bytesLength, true);
}

char* url_encode_to_lower(unsigned char *bytes, size_t bytesLength) {
    return url_encode(bytes, bytesLength, false);
}
1.3、URL解码实现
#include <string.h>
#include "URL.h"

//把16进制字符转换成10进制表示的数字
short hex2dec(char c) {
    if ('0' <= c && c <= '9') {
        return c - '0';
    } else if ('a' <= c && c <= 'f') {
        return c - 'a' + 10;
    } else if ('A' <= c && c <= 'F') {
        return c - 'A' + 10;
    } else {
        return 0;
    }
}

unsigned char* url_decode(char *input, size_t *outputLength) {
    size_t inputLength = strlen(input);
    size_t outputLength_ = 0;
    //以最坏的情况分配内存
    unsigned char *output = (unsigned char *)calloc(inputLength + 1, sizeof(unsigned char));
    for (size_t i = 0; i < inputLength; i++) {
        char c = input[i];
        if (c == '%') {
            char c1 = input[++i];
            char c0 = input[++i];
            //16进制转10进制
            output[outputLength_++] = (hex2dec(c1) << 4) + hex2dec(c0);
        } else if (c == '+') {
            output[outputLength_++] = ' ';
        } else {
            output[outputLength_++] = c;
        }
    }
    *outputLength = outputLength_;
    return output;
}