本文转自:http://www.cppblog.com/izualzhy/archive/2012/07/09/182456.html
先看个例子:
汉字 一 的UTF-8编码为0xE4 0xb8 0x 80
我们在google里搜索一下“一”,地址栏显示为:
以看到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 (), [email protected] * ===================================================================================== */ #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 原字符串大小(不包括最后的\0) * @param result 结果字符串缓存区 * @param resultSize 结果地址的缓冲区大小(包括最后的\0) * * @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, %s\n", resultSize, obj); return 0; } 编码: /* * ===================================================================================== * Filename: url_encode.cpp * Description: url encode * * Created: 07/04/2012 08:32:24 PM * * Author: zhy (), [email protected] * ===================================================================================== */ #include <stdio.h> #include <string.h> /** * @brief URLEncode 对字符串URL编码 * * @param str 原字符串 * @param strSize 原字符串长度(不包括最后的\0) * @param result 结果缓冲区的地址 * @param resultSize 结果缓冲区的大小(包括最后的\0) * * @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] = '\0'; return j; } int main(int argc, char* argv[]) { char* src = argv[1]; unsigned int srclength = strlen(src); printf("src length: %d\n", strlen(src)); char obj[100] = {0}; URLEncode(src, srclength, obj, 100); printf("obj: %s\n", obj); printf("obj: %d\n", 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_二
注:
1.AA –> “%AA”,使用sprintf。
2.”%AA” –> AA, 使用位移。
参考:
http://hi.baidu.com/zkheartboy/blog/item/5813a28fa0d224ebf11f363d.html
http://hi.baidu.com/leejun_2005/item/9e0f4e4ba62cde0bc11613b5