现代程序设计 homework-08

1. 理解C++变量的作用域和生命周期

a) 用少于10行代码演示你对局部变量的生命周期的理解

 1 /*------局部变量的生命周期的理解------*/
 2 void test1()//在if代码块中中定义的string局部变量str在超出该代码块时已经无法引用,会报错"未声明标识符str",即str已经被销毁
 3 {
 4     if(true)
 5     {
 6         string str;
 7         str="Hello,World";
 8     }
 9     cout<<str<<endl;
10 }

2. 理解堆和栈,两种内存的申请和释放的方式

a) 用少于30行代码演示你对堆和栈两种内存申请方式的理解

 1 /*---
 2 栈区:由编译器自动分配和释放,存放函数的参数值,局部变量的值等,
 3     甚至函数的调用过程都是用栈来完成
 4 堆区:一般由程序猿手动申请以及释放,若程序猿不释放,程序结束时
 5     可能由操作系统回收
 6 ---*/
 7 void test2()
 8 {
 9     /*---
10     new即分配了一块堆内存,指针p分配一块栈内存
11     即在栈内存中存放了一个指向一块堆内存的指针p
12     ---*/
13     /*---
14     据说这是VC6的汇编码
15     push         14h
16 
17   0040102A    call         operator new (00401060)
18 
19   0040102F    add          esp,4
20    mov          dword ptr [ebp-8],eax
21    mov          eax,dword ptr [ebp-8]
22    mov          dword ptr [ebp-4],eax
23     ---*/
24     int *p=new int[10];
25     delete[] p;
26 }

3. 理解unique_ptr和shared_ptr

a) http://msdn.microsoft.com/en-us/library/vstudio/hh279676.aspx

b) http://msdn.microsoft.com/en-us/library/vstudio/hh279669.aspx

 1 /*------关于shared_ptr和unique_ptr------*/
 2 /*---
 3 shared_ptr实现的是引用计数型的智能指针,可以被自由拷贝赋值,
 4           在任意的地方共享它,当引用计数为0时它才是年初被包装
 5           的动态分配的对象
 6 unique_ptr是独享所有权的智能指针,无法进行复制构造,也无法进行
 7           复制赋值操作,但可以进行移动构造和移动赋值操作当它本身
 8           被删除释放的时候会使用给定的删除器释放它指向的对象
 9 ---*/
10 void test3()
11 {
12     shared_ptr<int> sp(new int(10));            //一个指向整数的shared_ptr
13     assert(sp.unique());                            //现在shared_ptr是指针的唯一持有者   
14     shared_ptr<int> sp2 = sp;                       //第二个shared_ptr,拷贝构造函数   
15     assert(sp == sp2 && sp.use_count() == 2);        //两个shared_ptr相等,指向同一个对象,引用计数为2  
16     *sp2 = 100;                                        //使用解引用操作符修改被指对象  
17     assert(*sp == 100);                                //另一个shared_ptr也同时被修改   
18     sp.reset();                                     //停止shared_ptr的使用  
19     assert(!sp);                                    //sp不再持有任何指针(空指针)
20 }

4. 请尝试用“C++0x”,“C++11 & STL”两种不同的代码风格分割一个url,并上传代码到博客上。

For example:

Input: http://msdn.microsoft.com/en-us/library/vstudio/hh279674.aspx

Output: http, msdn, Microsoft, com, en-us, library, vstudio, hh279674, aspx

  1 // homework-08.cpp : 定义控制台应用程序的入口点。
  2 //
  3 
  4 #include "stdafx.h"
  5 #include<iostream>
  6 #include<cstdio>
  7 #include<cstring>
  8 #include<string>
  9 #include<cstdlib>
 10 #include<algorithm>
 11 #include<vector>
 12 #include<regex>
 13 #include<memory>
 14 #include<cassert>
 15 using namespace std;
 16 const int NumDelimiter=3;
 17 const string delimiter[NumDelimiter]={"://","/","."};
 18 class MyUrl
 19 {
 20 public:
 21     MyUrl();
 22     ~MyUrl();
 23     bool Getstring();//得到输入
 24     void PrintResult();//输出分隔结果
 25     void SeperateUrl();//利用STL分隔URL
 26     void SeperateUrlWithoutSTL();//不用STL分隔URL
 27     bool IsUrl();//判断当前输入是否为URL,利用正则表达式,速度很慢
 28 
 29 private:
 30     string url;//输入
 31     vector<string> result;//分隔结果
 32 };
 33 
 34 MyUrl::MyUrl()
 35 {
 36 }
 37 
 38 MyUrl::~MyUrl()
 39 {
 40 }
 41 void MyUrl::PrintResult()
 42 {
 43     for(vector<string>::size_type i=0;i!=result.size();i++)
 44     {
 45         cout<<result[i];
 46         if(i==result.size()-1)
 47         {
 48             cout<<endl;
 49         }
 50         else
 51         {
 52             cout<<",";
 53         }
 54     }
 55 }
 56 bool MyUrl::IsUrl()
 57 {
 58 //    const regex pattern("^((site)|((ht|f)tp(s?)))\:\/\/[a-zA-Z0-9\u4e00-\u9fa5\-\._]+(\.[a-zA-Z0-9\u4e00-\u9fa5\-\._]+){2,}(\/?)([a-zA-Z0-9\u4e00-\u9fa5\-\.\?\,\'\/\\\+&amp;%\$#_]*)?$");//其中\u4e00-\u9fa5为中文字符unicode编码范围
 59 //    const regex pattern("^(((ht|f)tp(s?))\://)?(www.|[a-zA-Z].)[a-zA-Z0-9\-\.]+\.(com|edu|gov|mil|net|org|biz|info|name|museum|us|ca|uk)(\:[0-9]+)*(/($|[a-zA-Z0-9\.\,\;\?\'\\\+&amp;%\$#\=~_\-]+))*$");    
 60     const regex pattern("^((http|https|site|ftp|ftps)\://)(www.|[a-zA-Z].)[a-zA-Z0-9\-\.]+\.(com|edu|gov|mil|net|org|biz|info|name|museum|us|ca|uk)(\:[0-9]+)*(\/?)([a-zA-Z0-9\u4e00-\u9fa5\-\.\?\,\'\/\\\+&amp;%\$#_]*)?$");
 61     try
 62     {
 63         if(!regex_match(url,pattern))
 64         {
 65             throw("The format of the Url you input is not true");
 66         }
 67     }
 68     catch(char *ExceptionStr)
 69     {
 70         cout<<"Exception: "<<ExceptionStr<<endl;
 71         return false;
 72     }
 73     return true;
 74 }
 75 bool MyUrl::Getstring()
 76 {
 77     cout<<"Please input the Url you want to seperate: "<<endl;
 78     try
 79     {
 80         if(getline(cin,url)==nullptr)
 81         {
 82             throw("Input Error");
 83         }
 84     }
 85     catch(char *ExceptionStr)
 86     {
 87         cout<<"Exception: "<<ExceptionStr<<endl;
 88         return false;
 89     }
 90     return true;
 91 }
 92 void MyUrl::SeperateUrl()
 93 {
 94     size_t lastIndex=0;//截取起始点
 95     size_t templastIndex=0;
 96     size_t index=url.find_first_of(delimiter[0],lastIndex);//截取终止点
 97     size_t tempIndex=string::npos;
 98     int tempPos=0;//记录当前截取的是哪个分隔符
 99     
100     while(index!=string::npos)
101     {
102         result.push_back(url.substr(lastIndex,index-lastIndex));
103         lastIndex=index+delimiter[tempPos].length();
104         tempIndex=string::npos;
105         for(int i=0;i<NumDelimiter;i++)
106         {
107             templastIndex=url.find_first_of(delimiter[i],lastIndex);
108             if(templastIndex<=tempIndex)
109             {
110                 tempIndex=templastIndex;
111                 tempPos=i;
112             }
113         }
114         index=tempIndex;
115     }
116     if(index-lastIndex>0)
117     {
118         result.push_back(url.substr(lastIndex,index-lastIndex));
119     }
120 }
121 void MyUrl::SeperateUrlWithoutSTL()
122 {
123     int begin=0;//记录跳过://后的开始点
124     int length=url.length();
125     string tempStr="";
126     for(int i=0;i<length;i++)
127     {
128         if(url[i]==':'&&url[i+1]=='/'&&url[i+2]=='/')
129         {
130             result.push_back(tempStr);
131             begin=i+3;//跳过://
132             break;
133         }
134         tempStr+=url[i];
135     }
136     tempStr="";
137     for(int i=begin;i<length;i++)
138     {
139         if(i==length-1)
140         {
141             tempStr+=url[i];
142             result.push_back(tempStr);
143         }
144         else if(url[i]=='.'||url[i]=='/')
145         {
146             result.push_back(tempStr);
147             tempStr="";
148         }
149         else
150         {
151             tempStr+=url[i];
152         }
153     }
154 }
155 int _tmain(int argc, _TCHAR* argv[])
156 { 
157     while(true)
158     {
159         MyUrl myUrl=MyUrl::MyUrl();
160         if(!myUrl.Getstring())//未正确输入
161         {
162             continue;
163         }
164         if(!myUrl.IsUrl())//未输入正确格式的URL
165         {
166             continue;
167         }
168         myUrl.SeperateUrl();
169 //        myUrl.SeperateUrlWithoutSTL();
170         myUrl.PrintResult();
171         myUrl.~MyUrl();
172 
173         cout<<"Enter Y to continue Or break"<<endl;
174         char ch=getchar();
175         if(ch=='Y'||ch=='y')
176         {
177             continue;
178         }
179         else
180         {
181             break;
182         }
183     }
184     return 0;
185 }
186 
187 
188 //
189 ///*------局部变量的生命周期的理解------*/
190 //void test1()//在if代码块中中定义的string局部变量str在超出该代码块时已经无法引用,会报错"未声明标识符str",即str已经被销毁
191 //{
192 //    if(true)
193 //    {
194 //        string str;
195 //        str="Hello,World";
196 //    }
197 //    cout<<str<<endl;
198 //}
199 ///*------栈和堆两种内存申请方式------*/
200 ///*---
201 //栈区:由编译器自动分配和释放,存放函数的参数值,局部变量的值等,
202 //    甚至函数的调用过程都是用栈来完成
203 //堆区:一般由程序猿手动申请以及释放,若程序猿不释放,程序结束时
204 //    可能由操作系统回收
205 //---*/
206 //void test2()
207 //{
208 //    /*---
209 //    new即分配了一块堆内存,指针p分配一块栈内存
210 //    即在栈内存中存放了一个指向一块堆内存的指针p
211 //    ---*/
212 //    /*---
213 //    据说这是VC6的汇编码
214 //    push         14h
215 //
216 //  0040102A    call         operator new (00401060)
217 //
218 //  0040102F    add          esp,4
219 //   mov          dword ptr [ebp-8],eax
220 //   mov          eax,dword ptr [ebp-8]
221 //   mov          dword ptr [ebp-4],eax
222 //    ---*/
223 //    int *p=new int[10];
224 //    delete[] p;
225 //}
226 ///*------关于shared_ptr和unique_ptr------*/
227 ///*---
228 //shared_ptr实现的是引用计数型的智能指针,可以被自由拷贝赋值,
229 //          在任意的地方共享它,当引用计数为0时它才是年初被包装
230 //          的动态分配的对象
231 //unique_ptr是独享所有权的智能指针,无法进行复制构造,也无法进行
232 //          复制赋值操作,但可以进行移动构造和移动赋值操作当它本身
233 //          被删除释放的时候会使用给定的删除器释放它指向的对象
234 //---*/
235 //void test3()
236 //{
237 //    shared_ptr<int> sp(new int(10));            //一个指向整数的shared_ptr
238 //    assert(sp.unique());                            //现在shared_ptr是指针的唯一持有者   
239 //    shared_ptr<int> sp2 = sp;                       //第二个shared_ptr,拷贝构造函数   
240 //    assert(sp == sp2 && sp.use_count() == 2);        //两个shared_ptr相等,指向同一个对象,引用计数为2  
241 //    *sp2 = 100;                                        //使用解引用操作符修改被指对象  
242 //    assert(*sp == 100);                                //另一个shared_ptr也同时被修改   
243 //    sp.reset();                                     //停止shared_ptr的使用  
244 //    assert(!sp);                                    //sp不再持有任何指针(空指针)
245 //}

 

测试用例:

考察重点:

1. 类的定义和使用,基本成员是否完整

定义了一个MyUrl类,成员如下

 1 class MyUrl
 2 {
 3 public:
 4     MyUrl();
 5     ~MyUrl();
 6     bool Getstring();//得到输入
 7     void PrintResult();//输出分隔结果
 8     void SeperateUrl();//利用STL分隔URL
 9     void SeperateUrlWithoutSTL();//不用STL分隔URL
10     bool IsUrl();//判断当前输入是否为URL,利用正则表达式,速度很慢
11 
12 private:
13     string url;//输入
14     vector<string> result;//分隔结果
15 };

 

2. 输入参数的检查及其他鲁棒性的考虑

这里对输入是否正确和输入的字符串是否为正确的URL形式进行了检测

对于输入是否为正确的URL形式用了正则表达式来实现,速度有点慢;后来改进了正则表达式的描述,速度很nice

 1 bool MyUrl::IsUrl()
 2 {
 3 //    const regex pattern("^((site)|((ht|f)tp(s?)))\:\/\/[a-zA-Z0-9\u4e00-\u9fa5\-\._]+(\.[a-zA-Z0-9\u4e00-\u9fa5\-\._]+){2,}(\/?)([a-zA-Z0-9\u4e00-\u9fa5\-\.\?\,\'\/\\\+&amp;%\$#_]*)?$");//其中\u4e00-\u9fa5为中文字符unicode编码范围
 4 //    const regex pattern("^(((ht|f)tp(s?))\://)?(www.|[a-zA-Z].)[a-zA-Z0-9\-\.]+\.(com|edu|gov|mil|net|org|biz|info|name|museum|us|ca|uk)(\:[0-9]+)*(/($|[a-zA-Z0-9\.\,\;\?\'\\\+&amp;%\$#\=~_\-]+))*$");    
 5     const regex pattern("^((http|https|site|ftp|ftps)\://)?(www.|[a-zA-Z].)[a-zA-Z0-9\-\.]+\.(com|edu|gov|mil|net|org|biz|info|name|museum|us|ca|uk)(\:[0-9]+)*(\/?)([a-zA-Z0-9\u4e00-\u9fa5\-\.\?\,\'\/\\\+&amp;%\$#_]*)?$");
 6     try
 7     {
 8         if(!regex_match(url,pattern))
 9         {
10             throw("The format of the Url you input is not true");
11         }
12     }
13     catch(char *ExceptionStr)
14     {
15         cout<<"Exception: "<<ExceptionStr<<endl;
16         return false;
17     }
18     return true;
19 }
20 bool MyUrl::Getstring()
21 {
22     cout<<"Please input the Url you want to seperate: "<<endl;
23     try
24     {
25         if(getline(cin,url)==nullptr)
26         {
27             throw("Input Error");
28         }
29     }
30     catch(char *ExceptionStr)
31     {
32         cout<<"Exception: "<<ExceptionStr<<endl;
33         return false;
34     }
35     return true;
36 }

 

3. STL和C++11元素的使用

在分隔字符串操作中使用STL中string中的find()和substr()方法,C++11元素主要是使用了正则表达式

 1 void MyUrl::SeperateUrl()
 2 {
 3     size_t lastIndex=0;//截取起始点
 4     size_t templastIndex=0;
 5     size_t index=url.find_first_of(delimiter[0],lastIndex);//截取终止点
 6     size_t tempIndex=string::npos;
 7     int tempPos=0;//记录当前截取的是哪个分隔符
 8     
 9     while(index!=string::npos)
10     {
11         result.push_back(url.substr(lastIndex,index-lastIndex));
12         lastIndex=index+delimiter[tempPos].length();
13         tempIndex=string::npos;
14         for(int i=0;i<NumDelimiter;i++)
15         {
16             templastIndex=url.find_first_of(delimiter[i],lastIndex);
17             if(templastIndex<=tempIndex)
18             {
19                 tempIndex=templastIndex;
20                 tempPos=i;
21             }
22         }
23         index=tempIndex;
24     }
25     if(index-lastIndex>0)
26     {
27         result.push_back(url.substr(lastIndex,index-lastIndex));
28     }
29 }
1 const regex pattern("^((site)|((ht|f)tp(s?)))\:\/\/[a-zA-Z0-9\u4e00-\u9fa5\-\._]+(\.[a-zA-Z0-9\u4e00-\u9fa5\-\._]+){2,}(\/?)([a-zA-Z0-9\u4e00-\u9fa5\-\.\?\,\'\/\\\+&amp;%\$#_]*)?$");//其中\u4e00-\u9fa5为中文字符unicode编码范围

 

4. 除http://之外, 是否有考虑ftp:// site:// 等情况

考虑了http://   https://   ftp://  site://情况,不过这不是重点,只需要在正则表达式中加需要的前缀即可

1 //    const regex pattern("^((site)|((ht|f)tp(s?)))\:\/\/[a-zA-Z0-9\u4e00-\u9fa5\-\._]+(\.[a-zA-Z0-9\u4e00-\u9fa5\-\._]+){2,}(\/?)([a-zA-Z0-9\u4e00-\u9fa5\-\.\?\,\'\/\\\+&amp;%\$#_]*)?$");//其中\u4e00-\u9fa5为中文字符unicode编码范围
2 //    const regex pattern("^(((ht|f)tp(s?))\://)?(www.|[a-zA-Z].)[a-zA-Z0-9\-\.]+\.(com|edu|gov|mil|net|org|biz|info|name|museum|us|ca|uk)(\:[0-9]+)*(/($|[a-zA-Z0-9\.\,\;\?\'\\\+&amp;%\$#\=~_\-]+))*$");    
3     const regex pattern("^((http|https|site|ftp|ftps)\://)?(www.|[a-zA-Z].)[a-zA-Z0-9\-\.]+\.(com|edu|gov|mil|net|org|biz|info|name|museum|us|ca|uk)(\:[0-9]+)*(\/?)([a-zA-Z0-9\u4e00-\u9fa5\-\.\?\,\'\/\\\+&amp;%\$#_]*)?$");
4     

 

5. 是否考虑url中的中文

中文这里利用中文字符unicode编码范围为\u4e00-\u9fa5的特点,在正则表达式中相应表示

1 //    const regex pattern("^((site)|((ht|f)tp(s?)))\:\/\/[a-zA-Z0-9\u4e00-\u9fa5\-\._]+(\.[a-zA-Z0-9\u4e00-\u9fa5\-\._]+){2,}(\/?)([a-zA-Z0-9\u4e00-\u9fa5\-\.\?\,\'\/\\\+&amp;%\$#_]*)?$");//其中\u4e00-\u9fa5为中文字符unicode编码范围
2 //    const regex pattern("^(((ht|f)tp(s?))\://)?(www.|[a-zA-Z].)[a-zA-Z0-9\-\.]+\.(com|edu|gov|mil|net|org|biz|info|name|museum|us|ca|uk)(\:[0-9]+)*(/($|[a-zA-Z0-9\.\,\;\?\'\\\+&amp;%\$#\=~_\-]+))*$");    
3     const regex pattern("^((http|https|site|ftp|ftps)\://)?(www.|[a-zA-Z].)[a-zA-Z0-9\-\.]+\.(com|edu|gov|mil|net|org|biz|info|name|museum|us|ca|uk)(\:[0-9]+)*(\/?)([a-zA-Z0-9\u4e00-\u9fa5\-\.\?\,\'\/\\\+&amp;%\$#_]*)?$");
4     

 

6. 算法是否简洁高效

正则表达式验证是否为URL,非常简洁,但不高效,

分隔字符串算法复杂度为O(n*m),n为URL长度,m为分隔符数量,非常简洁高效

至于其他匹配算法,不会..

7. 代码风格

命名遵循业界规范命名方式,代码缩进风格良好

posted @ 2013-11-17 23:40  VeryBigMan  阅读(610)  评论(0编辑  收藏  举报