platform: vs2012

Code#include <iostream>
#include <thread>
using namespace std;
void Fun()
{
cout<<"Say hi from thread\n";
}
int main()
{
std::thread th(Fun);
cout<<"Say hi from main\n";
th.join();
return 0;
}

输出结果

使用C++11的lambda语法

Code#include <iostream>
#include <thread>
using namespace std;
int main()
{
std::thread th([](){
cout<<"Sai hi from thread\n";
});
cout<<"Say hi from main\n";
th.join();
return 0;
}

创建多个线程运行

Code#include <iostream>
#include <thread>
#include <algorithm>
#include <vector>
using namespace std;
int main()
{
vector<thread> workers;
for (int i = 0; i < 10; ++i)
{
workers.push_back(std::thread([i](){
cout<<"Sai hi from thread "<<i<<endl;
}));
}
cout<<"Say hi from main\n";
for_each(workers.begin(), workers.end(), [](std::thread& th){
th.join();
});
return 0;
}


注意thread不具备copy constructor所以不能使用如下代码,否则会获取C2248错误

Code	for (int i = 0; i < 10; ++i)
{
thread th([i](){
cout<<"Sai hi from thread "<<i<<endl;
});
workers.push_back(th);
}

只能使用move semantics或者称为rvalue reference

Code	for (int i = 0; i < 10; ++i)
{
thread th([i](){
cout<<"Sai hi from thread "<<i<<endl;
});
workers.push_back(std::move(th));
}

Code#include <iostream>
#include <thread>
#include <vector>
#include <algorithm>
#include <cctype>
#include <string>
#include <iterator>
#include <ctime>
#include <functional>
using namespace std;
using namespace std::placeholders; // for _1, _2
#define LENGTH 10000
vector<int> doubleValues (vector<int>& v)
{
vector<int> new_values( v.size() );
for (vector<int>::iterator itr = v.begin(), end_itr = v .end(); itr != end_itr; ++itr )
{
new_values.push_back( 2 * *itr );
}
return new_values;
}
string upperString(const string& s)
{
string temp;
//temp.reserve(s.length());
std::transform(s.begin(), s.end(), std::back_inserter(temp), [](const int c){
return std::toupper(c);
});
return temp;
}
vector<string> upperStrings(const vector<string>& v)
{
vector<string> temp(v.size());
transform(v.begin(), v.end(), back_inserter(temp), std::bind(upperString, _1));
return temp;
}
vector<string> upperStringsR(const vector<string>& v)
{
vector<string> temp(v.size());
transform(v.begin(), v.end(), back_inserter(temp), move(std::bind(upperString, _1)));
return temp;
}
int main()
{
vector<string> in(LENGTH, "abc*def=ghi"); //cout<<"===Copy Sample==="<<endl;
//std::clock_t bgn = clock();
//vector<string> out = upperStrings(in);
//cout<<"Using "<<(clock() - bgn)<<" mini seconds"<<endl; //cout<<"===Move Semantics==="<<endl;
//bgn = clock();
//vector<string> out2 = move(upperStringsR(in));
//cout<<"Using "<<(clock() - bgn)<<" mini seconds"<<endl;
//copy(out2.begin(), out2.end(), ostream_iterator<string>(cout, "\n")); vector<int> v;
for ( int i = 0; i < LENGTH; i++ )
{
v.push_back( i );
}
cout<<"===Copy Sample==="<<endl;
std::clock_t bgn = clock();
v = doubleValues( v );
cout<<"Using "<<(clock() - bgn)<<" mini seconds"<<endl; cout<<"===Move Sample==="<<endl;
bgn = clock();
v = move(doubleValues( v ));
cout<<"Using "<<(clock() - bgn)<<" mini seconds"<<endl; return 0;
} //vector<thread> workers;
//for (int i = 0; i < 10; ++i)
//{
// thread th([i](){
// cout<<"Sai hi from thread "<<i<<endl;
// });
// workers.push_back(std::move(th));
//}
//cout<<"Say hi from main\n";
//for_each(workers.begin(), workers.end(), [](std::thread& th){
// th.join();
//});

Code#include <vector>
#include <iostream>
#include <time.h>
#include <set>
#include <algorithm> const unsigned N = 3001; extern bool some_test; std::set<int>
get_set(int)
{
std::set<int> s;
for (int i = 0; i < N; ++i)
while (!s.insert(std::rand()).second)
;
if (some_test)
return s;
return std::set<int>();
} std::vector<std::set<int> >
generate()
{
std::vector<std::set<int> > v;
for (int i = 0; i < N; ++i)
v.push_back(get_set(i));
if (some_test)
return v;
return std::vector<std::set<int> >();
} float time_it()
{
clock_t t1, t2, t3, t4;
clock_t t0 = clock();
{
std::vector<std::set<int> > v = generate();
t1 = clock();
std::cout << "construction took " << (float)((t1 - t0)/(double)CLOCKS_PER_SEC) << std::endl;
std::sort(v.begin(), v.end());
t2 = clock();
std::cout << "sort took " << (float)((t2 - t1)/(double)CLOCKS_PER_SEC) << std::endl;
std::rotate(v.begin(), v.begin() + v.size()/2, v.end());
t3 = clock();
std::cout << "rotate took " << (float)((t3 - t2)/(double)CLOCKS_PER_SEC) << std::endl;
}
t4 = clock();
std::cout << "destruction took " << (float)((t4 - t3)/(double)CLOCKS_PER_SEC) << std::endl;
std::cout << "done" << std::endl;
return (float)((t4-t0)/(double)CLOCKS_PER_SEC);
} int main()
{
std::cout << "N = " << N << '\n';
float t = time_it();
std::cout << "Total time = " << t << '\n';
} bool some_test = true;

同一段代码在vs2012与gcc4.8.1中表现不一样

Code
#include <iostream>
#include <thread>
#include <memory>
#include <vector>
#include <cassert>
#include <algorithm>
using namespace std;
void thFun(int &i)
{
cout<<"Hi from worker "<<i<<"!\n";
}
void Init(vector<thread> &workers)
{
for (int i = 0; i < 8; i++)
{
//auto th = std::thread(&thFun, std::ref(i));
auto th = std::thread(&thFun, std::ref(i));
workers.push_back(std::move(th));
assert(!th.joinable());
}
}
int main()
{
vector<thread> workers;
Init(workers); cout<<"Hi from main!\n"<<endl;
for_each(workers.begin(), workers.end(), [](std::thread&th){
assert(th.joinable());
th.join();
}); return 0;
}

前者是不管使用std::ref还是不使用都能编译通过且运行正确,后者是则必须使用std::ref才能编译通过,且运行不正确。

	typedef std::vector<std::string> StringVector;
typedef StringVector::iterator StringVectorIter; enum EPackageNodeType
{
NodeUnKnown = 0,
NodeNew,
NodeDownloaded,
NodeFinished,
NodeFailed,
}; enum CapsuleAnalyzeResult
{
ANALYZE_OK = 0,
INVALID_FILTER,
INVALID_CLOSE,
OTHER_ERROR
}; struct ISATZipFile
{
trwfUInt64 Size; // compress size
trwfUInt8 Tries; // tries downloaad times
trwfUInt8 State; // donwload state
std::string Name; // name of rictable
std::string File; // full path
std::string URL; // full url
ISATZipFile(): Size(0), Tries(0), State(NodeUnKnown){}
}; //typedef std::vector<ISATZipFile*, Framework::MFAlloc<ISATZipFile*> > ISATPackageVector;
typedef std::vector<ISATZipFile*> ISATPackageVector;
typedef ISATPackageVector::iterator ISATPackageVecotrIter;
typedef ISATPackageVector* PISATPackageVector; inline void ReleaseISATPackageVector(ISATPackageVector& coll)
{
ISATPackageVecotrIter itEnd = coll.end();
for (ISATPackageVecotrIter itPos = coll.begin(); itPos != itEnd; itPos++)
{
if (*itPos)
{
delete (*itPos);
*itPos = nullptr;
}
}
coll.clear();
} inline void ReleaseISATPackageVector(PISATPackageVector& pcoll)
{
if (pcoll)
{
ReleaseISATPackageVector(*pcoll);
delete pcoll;
pcoll = nullptr;
}
} struct ISATIncrement
{
ISATPackageVector* Inserts;
ISATPackageVector* Deletes;
ISATPackageVector* Updates;
ISATPackageVector* AliasInserts;
ISATPackageVector* AliasDeletes;
ISATPackageVector* AliasUpdates;
ISATIncrement()
: Inserts(new ISATPackageVector)
, Deletes(new ISATPackageVector)
, Updates(new ISATPackageVector)
, AliasInserts(new ISATPackageVector)
, AliasDeletes(new ISATPackageVector)
, AliasUpdates(new ISATPackageVector)
{}
~ISATIncrement()
{
ReleaseISATPackageVector(Inserts);
ReleaseISATPackageVector(Deletes);
ReleaseISATPackageVector(Updates);
ReleaseISATPackageVector(AliasInserts);
ReleaseISATPackageVector(AliasDeletes);
ReleaseISATPackageVector(AliasUpdates);
}
};
//typedef std::vector<ISATIncrement*, Framework::MFAlloc<ISATIncrement*> > ISATIncrementBuilds;
typedef std::vector<ISATIncrement*> ISATIncrementBuilds;
typedef ISATIncrementBuilds::iterator ISATIncrementBuildsIter;
typedef ISATIncrementBuilds * PISATIncrementBuilds; inline void ReleaseISATIncrementBuilds(PISATIncrementBuilds pcoll)
{
BOOST_FOREACH(ISATIncrement*& elem, *pcoll)
{
if (elem->Inserts) ReleaseISATPackageVector(*(elem->Inserts));
if (elem->Deletes) ReleaseISATPackageVector(*(elem->Deletes));
if (elem->Updates) ReleaseISATPackageVector(*(elem->Updates));
if (elem->AliasInserts) ReleaseISATPackageVector(*(elem->AliasInserts));
if (elem->AliasDeletes) ReleaseISATPackageVector(*(elem->AliasDeletes));
if (elem->AliasUpdates) ReleaseISATPackageVector(*(elem->AliasUpdates));
}
} typedef struct _isatSummary
{
std::string strTimeStamp;
ISATPackageVector* Image;
ISATPackageVector* AliasImage;
ISATIncrementBuilds* Increments;
bool IsWeeklyBuild;
_isatSummary():IsWeeklyBuild(false), Image(new ISATPackageVector), AliasImage(new ISATPackageVector),Increments(new ISATIncrementBuilds){
Increments->reserve(7 * 24 * 60);
}
~_isatSummary(){
ReleaseISATPackageVector(Image);
ReleaseISATPackageVector(AliasImage);
if (Increments)
{
delete Increments;
Increments = nullptr;
}
}
} ISATSummary; #include "stdafx.h"
#include "SummaryParser.h"
#include <sstream>
#include <boost/regex.hpp>
#include <boost/foreach.hpp>
#include <boost/algorithm/string.hpp>
#include <ctime>
namespace IDH
{
CSummaryParser::CSummaryParser(void)
: m_iCurPos(0)
, m_iTotalIncrement(0)
, m_pszFileRoot(0)
, m_pszURLRoot(0)
{
m_Elements.reserve(400000);
} CSummaryParser::~CSummaryParser(void)
{
} int CSummaryParser::Parse(const char * pBuffer, const char * pszURLRoot, const char * pszFileRoot, ISATSummary* pSummary)
{
_ASSERT(pBuffer && pszURLRoot && pszFileRoot &&pSummary);
if (!pBuffer || !pszURLRoot || !pszFileRoot ||!pSummary) return 1; m_pszFileRoot = pszFileRoot;
m_pszURLRoot = pszURLRoot; if (0 != RetrieveElements(pBuffer))
{
cerr<<"Failed to retrieve elements from summary buffer."<<endl;
return 1;
} if (0 != ParseElements(pSummary))
{
cerr<<"Failed to parse elements from summary buffer."<<endl;
return 1;
} return 0;
} int CSummaryParser::RetrieveElements(const char * pBuffer)
{
_ASSERT(pBuffer);
PERFORMANCE_BEGIN
clock_t _bgn = clock();
static boost::regex rex("([^\\s=]*)", boost::regex::icase|boost::regex::perl); boost::cmatch what; boost::cregex_iterator itBgn = boost::make_regex_iterator(pBuffer, rex);
boost::cregex_iterator itEnd; m_Elements.clear();
m_iCurPos = 0;
m_iTotalIncrement = 0; for_each(itBgn, itEnd, [this](const boost::cmatch& what){
if (what[1].str().length() > 0)
this->m_Elements.push_back((what[1].str()));
}); BOOST_FOREACH(std::string& elem, m_Elements)
{
boost::trim(elem);
}
cout<<__FUNCTION__<<"using "<<clock()-_bgn<<" mini seconds"<<endl;
PERFORMANCE_END
return 0;
} int CSummaryParser::ParseElements(ISATSummary* pSummary)
{
int ret = 0;
PERFORMANCE_BEGIN
for (;m_iCurPos < m_Elements.size();)
{
if (boost::iequals(m_Elements[m_iCurPos], ISATGRABBERCONST::SUM_FULLBUILD) == true)
{
if (ParseFullBuildElement(*pSummary) != 0)
{
wcout<<L"Fail to parse [FullBuild]"<<endl;
ret = 1;
break;
}
}
else if (boost::iequals(m_Elements[m_iCurPos], ISATGRABBERCONST::SUM_TABLES) == true)
{
if (ParseTablesElement(*(pSummary->Image)) != 0)
{
wcout<<L"Fail to parse [Tables]"<<endl;
ret = 1;
break;
}
}
else if (boost::iequals(m_Elements[m_iCurPos], ISATGRABBERCONST::SUM_RAWALIASTABLES) == true)
{
if (ParseTablesElement(*(pSummary->AliasImage)) != 0)
{
wcout<<L"Fail to parse [RawAliasTables]"<<endl;
ret = 1;
break;
}
}
else if (boost::iequals(m_Elements[m_iCurPos], ISATGRABBERCONST::SUM_INCREMENTALBUILD) == true)
{
if (ParseIncrementalBuildElement(*pSummary) != 0)
{
wcout<<L"Fail to parse [IncrementalBuild]"<<endl;
return 1;
}
}
else if (boost::istarts_with(m_Elements[m_iCurPos], ISATGRABBERCONST::SUM_INCREMENTALBUILDEACH) == true)
{
if (ParseIncrementalBuildEachElement(*pSummary) != 0)
{
wcout<<L"Fail to parse [IncrementalBuild_Each]"<<endl;
ret = 1;
break;
}
}
else
{
cerr<<"Detect unknown node: "<<m_Elements[m_iCurPos]<<": at "<<m_iCurPos<<endl;
m_iCurPos++;
} }
PERFORMANCE_END
return ret;
} int CSummaryParser::ParseFullBuildElement(ISATSummary& full)
{
if (m_iCurPos + ISATGRABBERCONST::SUM_FULLBUILDLENGTH >= m_Elements.size())
return 1;
if (boost::iequals(m_Elements[++m_iCurPos], ISATGRABBERCONST::SUM_LATEST) == false)
return 1; if (full.strTimeStamp.compare(m_Elements[++m_iCurPos]) != 0)
{
// new full build
ReleaseISATPackageVector(*(full.Image));
ReleaseISATPackageVector(*(full.AliasImage));
ReleaseISATIncrementBuilds(full.Increments);
full.strTimeStamp = m_Elements[m_iCurPos];
full.IsWeeklyBuild = true;
} m_iCurPos++;
return 0;
} int CSummaryParser::ParseTablesElement(ISATPackageVector& coll)
{
if (m_iCurPos + ISATGRABBERCONST::SUM_TABLESLENGTH >= m_Elements.size())
return 1;
if (boost::iequals(m_Elements[++m_iCurPos], ISATGRABBERCONST::SUM_NUMBEROFTABLES) == false)
return 1;
int number = atoi(m_Elements[++m_iCurPos].c_str()); // get all tables
for (int i = 1; i <= number && m_iCurPos + ISATGRABBERCONST::SUM_GERNERICLENGTH < m_Elements.size(); i++)
{
int numFile = 0, numSize = 0;
numFile = atoi(m_Elements[++m_iCurPos].c_str() + strlen(ISATGRABBERCONST::SUM_TABLE));
std::string name = m_Elements[++m_iCurPos];
numSize = atoi(m_Elements[++m_iCurPos].c_str() + strlen(ISATGRABBERCONST::SUM_CMPSIZETABLE));
int size = atoi(m_Elements[++m_iCurPos].c_str());
if (numFile != numSize ||
numFile != i)
return 1;
ReplaceFileName(name, ISATGRABBERCONST::SUM_FILE_TXT, ISATGRABBERCONST::SUM_FILE_Z);
if (coll.size() < i)
{
ISATZipFile* ptable = new ISATZipFile;
ptable->State = NodeNew;
ptable->Name = name;
ptable->Size = size;
coll.push_back(ptable);
}
else
{
if (coll[i-1]->Size != size ||
boost::iequals(coll[i-1]->Name, name) == false)
{
}
}
}
m_iCurPos++;
return 0;
} int CSummaryParser::ParseIncrementalBuildElement(ISATSummary& full)
{
if (m_iCurPos + ISATGRABBERCONST::SUM_INCREMENTALBUILDLENGTH > m_Elements.size())
return 1;
if (boost::iequals(m_Elements[++m_iCurPos], ISATGRABBERCONST::SUM_NUMBEROFBUILDS) == false)
return 1; m_iTotalIncrement = atoi(m_Elements[++m_iCurPos].c_str());
m_iCurPos++;
return 0;
} int CSummaryParser::ParseIncrementalBuildEachElement(ISATSummary& full)
{
int iIncrementtalNumber = atoi(m_Elements[m_iCurPos].c_str() + strlen(ISATGRABBERCONST::SUM_INCREMENTALBUILDEACH));
if (iIncrementtalNumber > m_iTotalIncrement)
return 1;
if (iIncrementtalNumber > full.Increments->size())
full.Increments->push_back(new ISATIncrement());
while (++m_iCurPos < m_Elements.size() && m_Elements[m_iCurPos][0] != ISATGRABBERCONST::SUM_PREFIX_PATTERN)
{
if (boost::istarts_with(m_Elements[m_iCurPos], ISATGRABBERCONST::SUM_NUMBEROFUPDATETABLES) == true)
{
if (ParseIncremental(ISATGRABBERCONST::SUM_UPDATETABLE, ISATGRABBERCONST::SUM_CMPSIZEUPDATETABLE, (*(full.Increments))[iIncrementtalNumber-1]->Updates) != 0)
{
wcout<<L"Fail to parse [UPDATETABLE]"<<endl;
return 1;
}
}
else if (boost::istarts_with(m_Elements[m_iCurPos], ISATGRABBERCONST::SUM_NUMBEROFADDTABLES) == true)
{
if (ParseIncremental(ISATGRABBERCONST::SUM_ADDTABLE, ISATGRABBERCONST::SUM_CMPSIZEADDTABLE, (*(full.Increments))[iIncrementtalNumber-1]->Inserts) != 0)
{
wcout<<L"Fail to parse [ADDTABLE]"<<endl;
return 1;
}
}
else if (boost::istarts_with(m_Elements[m_iCurPos], ISATGRABBERCONST::SUM_NUMBEROFDELETETABLES) == true)
{
if (ParseIncremental(ISATGRABBERCONST::SUM_DELETETABLE, ISATGRABBERCONST::SUM_CMPSIZEDELETETABLE, (*(full.Increments))[iIncrementtalNumber-1]->Deletes) != 0)
{
wcout<<L"Fail to parse [DELETETABLE]"<<endl;
return 1;
}
}
else if (boost::istarts_with(m_Elements[m_iCurPos], ISATGRABBERCONST::SUM_NUMBEROFRAWALIASUPDATETABLES) == true)
{
if (ParseIncremental(ISATGRABBERCONST::SUM_RAWALIASUPDATETABLE, ISATGRABBERCONST::SUM_CMPSIZERAWALIASUPDATETABLE, (*(full.Increments))[iIncrementtalNumber-1]->AliasUpdates) != 0)
{
wcout<<L"Fail to parse [RAWALIASUPDATETABLE]"<<endl;
return 1;
}
}
else if (boost::istarts_with(m_Elements[m_iCurPos], ISATGRABBERCONST::SUM_NUMBEROFRAWALIASADDTABLES) == true)
{
if (ParseIncremental(ISATGRABBERCONST::SUM_RAWALIASADDTABLE, ISATGRABBERCONST::SUM_CMPSIZERAWALIASADDTABLE, (*(full.Increments))[iIncrementtalNumber-1]->AliasInserts) != 0)
{
wcout<<L"Fail to parse [RAWALIASADDTABLE]"<<endl;
return 1;
}
}
else if (boost::istarts_with(m_Elements[m_iCurPos], ISATGRABBERCONST::SUM_NUMBEROFRAWALIASDELETETABLES) == true)
{
if (ParseIncremental(ISATGRABBERCONST::SUM_RAWALIASDELETETABLE, ISATGRABBERCONST::SUM_CMPSIZERAWALIASDELETETABLE, (*(full.Increments))[iIncrementtalNumber-1]->AliasDeletes) != 0)
{
wcout<<L"Fail to parse [RAWALIASDELETETABLE]"<<endl;
return 1;
}
}
else
{
cerr<<"Invalide line:"<<m_Elements[m_iCurPos]<<endl;
}
}
return 0;
} int CSummaryParser::ParseIncremental(std::string namepattern, std::string sizepattern, PISATPackageVector& pcoll)
{
if (++m_iCurPos >= m_Elements.size())
return 1;
int number = atoi(m_Elements[m_iCurPos].c_str()); if (number == 0)
return 0; for (int i = 1; i <= number && m_iCurPos + ISATGRABBERCONST::SUM_GERNERICLENGTH < m_Elements.size(); i++)
{
int numFile = 0, numSize = 0;
numFile = atoi(m_Elements[++m_iCurPos].c_str() + namepattern.size());
std::string name = m_Elements[++m_iCurPos];
numSize = atoi(m_Elements[++m_iCurPos].c_str() + sizepattern.size());
int size = atoi(m_Elements[++m_iCurPos].c_str());
if (numFile != numSize ||
numFile != i)
return 1;
ReplaceFileName(name, ISATGRABBERCONST::SUM_FILE_TXT, ISATGRABBERCONST::SUM_FILE_Z);
if (pcoll->size() < i)
{
ISATZipFile * pnode = new ISATZipFile;
pnode->Name = name;
pnode->Size = size;
pnode->State = NodeNew;
pcoll->push_back(pnode);
}
else
{
if ((*pcoll)[i-1]->Size != size ||
boost::iequals((*pcoll)[i-1]->Name, name) == false)
return 1;
}
} return 0;
} void CSummaryParser::ReplaceFileName(std::string& inout, const std::string& s1, const std::string& s2)
{
boost::to_lower(inout);
size_t pos = inout.rfind(s1);
if (pos != std::string::npos)
inout.replace(pos, s1.length(), s2);
} int CSummaryParser::RetrieveElements2(string& buffer)
{
clock_t _bgn=clock();
m_Elements.clear();
list<boost::iterator_range<string::iterator> > l;
boost::split(l, buffer, boost::is_any_of("\n="), boost::token_compress_on);
for (auto pos = l.begin(); pos != l.end(); pos++)
{
m_Elements.push_back(string(pos->begin(), pos->end()));
}
cout<<__FUNCTION__<<"using "<<clock()-_bgn<<" mini seconds"<<endl;
return 0;
}
}

最新文章

  1. Markdown 新手指南
  2. (十二)select()函数以及FD_ZERO、FD_SET、FD_CLR、FD_ISSET
  3. flex中下拉框的实现
  4. 【C++自绘控件】如何用GDI+来显示图片
  5. Daily Scrum 12.9
  6. LiLinux系统下如何修改主机名
  7. php里session的用法
  8. web 模板 类似京东左侧的导航栏
  9. TKinter布局之pack
  10. Brackets 配置
  11. 高性能MySql进化论(一):数据类型的优化_上
  12. SpringMVC框架(四)文件的上传下载,上下文路径
  13. js-location应用
  14. 关于java字节流的read()方法返回值为int的思考
  15. 第一次使用mybatis
  16. Ubuntu开机时提示“piix4_smbus 0000:00:07.3: SMBus Host controller not enabled”
  17. B - Tree Rotations HYSBZ - 2212 (线段树合并)
  18. 兼容ie,火狐的判断回车键js脚本
  19. webpack热更新和常见错误处理
  20. maven测试时中文乱码问题解决方法

热门文章

  1. 【转】git bash here 右键菜单失效后的修复方法
  2. Python属性描述符(二)
  3. CentOS-文件操作
  4. [转] immutability-helper 插件的基本使用(附源码)
  5. selenium - 常用页面操作
  6. dubbo控制台在tomcat上的部署
  7. Leetcode 435.无重叠区间
  8. 九度oj 题目1374:所有员工年龄排序
  9. 刷题总结——pole(uva 1638 dp)
  10. scrapy的调试方法