先看个例子:

汉字 一 的UTF-8编码为0xE4 0xb8 0x 80

我们在google里搜索一下“一”,地址栏显示为:

image

可以看到url的字符串里有一个%E4%B8%80

这就是encode之后的值。因此,encode的处理过程也很明显了。

特别是传中文参数时,如果没有encode,很容易出错。

至于为什么要这么传,就不知道了,今天,现来看下C语言如何实现url encode函数.

首先是urlencode的编码规则,可以看这里,搜到一篇文章没有仔细研究,可能有不全的地方:

http://hi.baidu.com/leejun_2005/item/9e0f4e4ba62cde0bc11613b5
解码:

/*
 * =====================================================================================
 *       Filename:  url_decode.cpp
 *    Description:  url decode
 *
 *        Created:  07/06/2012 07:35:14 PM
 *         Author:  zhy (), izualzhy@163.com
 * =====================================================================================
 */

#include <stdio.h>
#include <string.h>

#define NON_NUM '0'

int hex2num(char c)
{
    if (c>='0' && c<='9') return c - '0';
    if (c>='a' && c<='z') return c - 'a' + 10;//这里+10的原因是:比如16进制的a值为10
    if (c>='A' && c<='Z') return c - 'A' + 10;
    
    printf("unexpected char: %c", c);
    return NON_NUM;
}

/**
 * @brief URLDecode 对字符串URL解码,编码的逆过程
 *
 * @param str 原字符串
 * @param strSize 原字符串大小(不包括最后的)
 * @param result 结果字符串缓存区
 * @param resultSize 结果地址的缓冲区大小(包括最后的)
 *
 * @return: >0 result 里实际有效的字符串长度
 *            0 解码失败
 */
int URLDecode(const char* str, const int strSize, char* result, const int resultSize)
{
    char ch,ch1,ch2;
    int i;
    int j = 0;//record result index

    if ((str==NULL) || (result==NULL) || (strSize<=0) || (resultSize<=0)) {
        return 0;
    }

    for ( i=0; (i<strSize) && (j<resultSize); ++i) {
        ch = str[i];
        switch (ch) {
            case '+':
                result[j++] = ' ';
                break;
            case '%':
                if (i+2<strSize) {
                    ch1 = hex2num(str[i+1]);//高4位
                    ch2 = hex2num(str[i+2]);//低4位
                    if ((ch1!=NON_NUM) && (ch2!=NON_NUM))
                        result[j++] = (char)((ch1<<4) | ch2);
                    i += 2;
                    break;
                } else {
                    break;
                }
            default:
                result[j++] = ch;
                break;
        }
    }
    
    result[j] = 0;
    return j;
}

int main(int argc, char* argv[])
{
    char* src = argv[1];
    char obj[100] = {0};

    unsigned int len = strlen(src);
    int resultSize = URLDecode(src, len, obj, 100);
    printf("result: %d, %sn", resultSize, obj);

    return 0;

}

编码:

/*
 * =====================================================================================
 *       Filename:  url_encode.cpp
 *    Description:  url encode
 *
 *        Created:  07/04/2012 08:32:24 PM
 *
 *         Author:  zhy (), izualzhy@163.com
 * =====================================================================================
 */
#include <stdio.h>
#include <string.h>

/**
 * @brief URLEncode 对字符串URL编码
 *
 * @param str 原字符串
 * @param strSize 原字符串长度(不包括最后的)
 * @param result 结果缓冲区的地址
 * @param resultSize 结果缓冲区的大小(包括最后的)
 *
 * @return: >0:resultstring 里实际有效的长度
 *            0: 解码失败.
 */
int URLEncode(const char* str, const int strSize, char* result, const int resultSize)
{
    int i;
    int j = 0;//for result index
    char ch;

    if ((str==NULL) || (result==NULL) || (strSize<=0) || (resultSize<=0)) {
        return 0;
    }

    for ( i=0; (i<strSize)&&(j<resultSize); ++i) {
        ch = str[i];
        if (((ch>='A') && (ch<'Z')) ||
            ((ch>='a') && (ch<'z')) ||
            ((ch>='0') && (ch<'9'))) {
            result[j++] = ch;
        } else if (ch == ' ') {
            result[j++] = '+';
        } else if (ch == '.' || ch == '-' || ch == '_' || ch == '*') {
            result[j++] = ch;
        } else {
            if (j+3 < resultSize) {
                sprintf(result+j, "%%%02X", (unsigned char)ch);
                j += 3;
            } else {
                return 0;
            }
        }
    }

    result[j] = '';
    return j;
}

int main(int argc, char* argv[])
{
    char* src = argv[1];
    unsigned int srclength = strlen(src);
    printf("src length: %dn", strlen(src));
    

    char obj[100] = {0};
    URLEncode(src, srclength, obj, 100);

    printf("obj: %sn", obj);
    printf("obj: %dn", strlen(obj));

    return 0;
}

输出:

y@y-VirtualBox:/mnt/Documents/Training$ ./url_encode 一^abc_二
src length: 11
obj: %E4%B8%80%5Eabc_%E4%BA%8C
obj: 25
y@y-VirtualBox:/mnt/Documents/Training$ ./url_decode %E4%B8%80%5Eabc_%E4%BA%8C
result: 11, 一^abc_二

使用google搜索下:

image

注:

1.AA –> “%AA”,使用sprintf。

2.”%AA” –> AA, 使用位移。

参考:

http://hi.baidu.com/zkheartboy/blog/item/5813a28fa0d224ebf11f363d.html

http://hi.baidu.com/leejun_2005/item/9e0f4e4ba62cde0bc11613b5