这个程序用来查找被称为url(统一资源地)的万维网地址,输入一行包含url的字符串,程序会帮你识别并输出字符串里所包含的全部url。
url的格式: protocol-name(协议名称)://resource-name(资源名称)
在看这个程序之前,记录一下这一章接触的新的知识点:
1.isalnum(c)函数:
在#<cctype>中定义,如果c是一个字母或者数字则结果是true
其余类似的函数有:
isspace(c) 如果c是一个空白字符则结果为true isalpha(c)如果c是一个字母字符则为true
isdigit(c) 如果是一个数字字符则为true ispunct(c如果是一个标点字符则结果为true
isupper(c) 如果是一个大写字母则结果为true islower(c)如果c 是一个小写字母则为true
toupper(c) 产生一个等于c的大写字母 tolower(c)产生一个等于c的小写字母
2.find_if函数:
find_if(a,b,c) 包含3个参数,前两个参数表示查找范围,是迭代器类型,第三个参数是一个函数指针或者函数对象,它的的作用是在容器范围内,返回一个使第三个参数所指函数为真的元素的迭代器
find函数:
与find_if 有点类似,但和find_if不同,它不会调用第三个参数所给定的值,反而会去查找做给的第三个参数,如果找到,则返回第三个参数的迭代器,没找到,就返回第二个参数的迭代器。
search函数:
search(a,b,c,d) 第一队迭代器指示了一对我们要查找的的序列,第二对指示了一个序列——我们希望为这个序列定位
(三个都是在#include <algorithm>中)
下面先简单介绍程序中的几个函数:
vector<string> find_urls(const string& s) //通过用迭代器d查找“://” 以查找查找全部的url
string::const_iterator url_beg(string::const_iterator b,string::const_iterator e) //查找url的前面部分
string::const_iterator url_end(string::const_iterator b,string::const_iterator e) //查找url的后面部分
bool not_url_char(charc) //如果传过来的字符不可能出现在url中,则返回true
下面是整个函数,外加一个main的测试函数:
#include<iostream> #include<string> #include<vector> #include<cctype> #include<algorithm> using namespace std; bool not_url_char(char c){ //除去字母数字之外,其他可能出现的urlzifu static const string url_ch = "~;/:@=&_.+!'(),"; //static是静态变量,有全局寿命 return !(isalnum(c) || find(url_ch.begin(),url_ch.end(),c) !=url_ch.end()); //检查字符c是否有出现 } string::const_iterator url_beg(string::const_iterator b,string::const_iterator e){ static const string sep = "://"; typedef string::const_iterator iter; //简化字符串的迭代器 iter i = b; //i标记查找到的分隔符: while((i = search(i,e,sep.begin(),sep.end())) !=e) { if(i != b && i+sep.size() != e){ iter beg = i; //beg标记协议的名称的头部 while(beg!=b&&isalpha(beg[-1])) --beg; if(beg!=i && !not_url_char(i[sep.size()])) //分隔符前后至少有一个字符 return beg; } i+=sep.size(); //所找到的分隔符不是一个url的部分 } return e; } string::const_iterator //url_end 函数 url_end(string::const_iterator b,string::const_iterator e){ return find_if(b,e,not_url_char); } vector<string> find_urls(const string& s){ vector<string> ret; typedef string::const_iterator iter; iter b = s.begin(), e = s.end(); while(b!=e){ //检查整个输入 b = url_beg(b,e); //查找一个或多个紧跟着://d 字母 if(b!=e){ //如果查找成功获取此url的其余部分 iter after = url_end(b,e); ret.push_back(string(b,after)); //记住这个url b = after; //向前推进 } } return ret; } int main(){ //用于测试的主函数 string s; getline(cin,s); vector<string> v=find_urls(s); for(vector<string>::size_type i =0;i<v.size();++i) cout<<v[i]<<endl; return 0; }