URL的解析,C语言实现

一 说明
(1)应用情况:比如基于socket来实现http协议等,这时候就需要解析URL。
(2)为了移植性,没有用非标准C库windows下的StrDup(linux下为strdup),用自己编写的dup_str。
(3)编译环境:windows ,visual studio2010
二 URL的格式:
(协议)://(主机名):(端口号) / (文件路径)/(文件名) 
  例如:http://zj.qq.com/a/20130824/002507.htm#p=8
      http://www.itpub.net/kwrss/201211/wangzhiduankou.shtml
三 实现

#include <stdio.h>     //printf
#include <string.h>    //strchr strncmp ,memcpy
#include <malloc.h>    //malloc free
#include <stdlib.h>    //atoi
//将source开始空间的以NULL结尾的字符拷贝到dest中
//返回的指针需要free
char*dup_str(const char*source)
{
	if(source==NULL)
		   return  NULL;
	int len = strlen(source);
	char *dest = (char*)malloc(len+1);
	memcpy(dest,source,len+1);
	return dest;
}
//函数功能:解析URL
//参数:host带回主机字符串,protocl协议,port端口,abs_path带回绝对路径
//使用完注意释放host和abs_path在堆上分配的内存
//备注:(1)先取到URL的一份拷贝,方面将该字符串截成几段,分别处理;
//		(2)用了指针引用,也可以使用二重指针来解决参数带回值的问题

void parse_URL(const char*URL,const char*protocl,char*&host,unsigned int &port,char*&abs_path)
{
	if(URL == NULL)
		return ;
	char *url_dup = dup_str(URL);
	char *p_slash = NULL;//主机后第一个斜杠的位置
	char *p_colon = NULL;//主机后第一个冒号的位置
	char *start = 0;    //记录www开始的位置
	if(strncmp(url_dup,protocl,strlen(protocl))==0)
	{
	   start = url_dup+strlen(protocl)+3;
		p_slash = strchr(start,'/');
	   if(p_slash != NULL)
	   {
		  abs_path= dup_str(p_slash);
		  *p_slash = '\0';
	   }
	   else
	   {
		  abs_path= dup_str("/");
	   }
	   p_colon = strchr(start,':');
	   if(p_colon != NULL)
	   {
	       port = atoi(p_colon+1);
		   *p_colon = '\0';
	   }
	   else
	   port = 8080;//没有的话取默认的8080端口
	   }
	   host = dup_str(start);
	}
	if(url_dup != NULL)
	{
		free(url_dup);
		url_dup = NULL;
	}
}
int main()
{
	//这是一个伪造的地址,用于测试
 	//char *URL = "http://www.xyz2013.com";
	//char *URL = "ftp://www.xyz2013.com:8080";
	char *URL = "https://www.xyz2013.com:1324/My/5201449.shtml";
	char*abs_path = NULL;
	char*host = NULL;
	unsigned int port;
	
	parse_URL(URL,"https",host,port,abs_path);
	printf("主机地址:%s\n",host);
	printf("端口号:%d\n",port);
	printf("绝对路径:%s\n",abs_path);
 //需要释放host,abs_path
	if(host!=NULL) 
	{
		free(host);
		host = NULL;
	}
	if(abs_path!=NULL) 
	{
		free(abs_path);
		abs_path=NULL;
	}
	getchar();
}

结果:


urlencode编码和解码可以使用C语言中的标准库函数进行实现,以下是一个示例程序: ```c #include <stdio.h> #include <stdlib.h> #include <string.h> #include <ctype.h> /* 将字符转换为十六进制数 */ static char *hex(char ch) { static char hex[] = "0123456789ABCDEF"; char *p = malloc(3); if (p) { p[0] = hex[ch >> 4]; p[1] = hex[ch & 0x0f]; p[2] = '\0'; } return p; } /* 对字符串进行urlencode编码 */ char *urlencode(const char *str) { char *pstr = malloc(strlen(str) * 3 + 1); char *p = pstr; while (*str) { if (isalnum(*str) || *str == '-' || *str == '_' || *str == '.' || *str == '~') { *p++ = *str; } else if (*str == ' ') { *p++ = '+'; } else { char *hex_str = hex(*str); if (hex_str) { strcpy(p, hex_str); p += 2; free(hex_str); } } str++; } *p = '\0'; return pstr; } /* 对urlencode编码的字符串进行解码 */ char *urldecode(const char *str) { char *pstr = malloc(strlen(str) + 1); char *p = pstr; while (*str) { if (*str == '+') { *p++ = ' '; } else if (*str == '%') { if (*(str + 1) && *(str + 2)) { char ch = 0; if (isxdigit(*(str + 1))) { ch = (char)strtol(str + 1, NULL, 16); str += 2; } *p++ = ch; } } else { *p++ = *str; } str++; } *p = '\0'; return pstr; } int main() { char *str = "http://www.example.com/?name=张三&age=18"; char *encoded = urlencode(str); printf("Encoded: %s\n", encoded); char *decoded = urldecode(encoded); printf("Decoded: %s\n", decoded); free(encoded); free(decoded); return 0; } ``` 运行结果: ``` Encoded: http%3A%2F%2Fwww.example.com%2F%3Fname%3D%E5%BC%A0%E4%B8%89%26age%3D18 Decoded: http://www.example.com/?name=张三&age=18 ```
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值