热爱互联网

sublime配置c++11编译环境

Tools->Build System->New Build System…
把下面代码复制进去。
注意其中在linux下编译thread的时候需要加上 -pthread。

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
{
     "cmd": ["g++", "-std=c++11", "${file}", "-o", "${file_path}/${file_base_name}"], // For GCC On Windows and Linux
     //"cmd": ["CL", "/Fo${file_base_name}", "/O2", "${file}"],     // For CL on Windows Only
     "file_regex": "^(..[^:]*):([0-9]+):?([0-9]+)?:? (.*)$",
     "working_dir": "${file_path}",
     "selector": "source.c, source.c++",
 
     "variants":
     [
          {
               "name": "Run",
               "cmd": ["bash", "-c", "g++ -std=c++11 -pthread '${file}' -o '${file_path}/${file_base_name}' && '${file_path}/${file_base_name}'"]  // Linux Only
               // "cmd": ["CMD", "/U", "/C", "g++ -std=c++11 ${file} -o ${file_base_name} && ${file_base_name}"]  // For GCC On Windows Only
               //"cmd": ["CMD", "/U", "/C", "CL /Fo${file_base_name} /O2 ${file} && ${file_base_name}"]   // For CL On Windows Only
          }
     ]
}

然后保存,在保存文件对话框中把文件名字改成“C++11.sublime-build” 保存即可.
然后选择Tools->Build System->C++11。

有符号数和无符号数之间的操作

说多了都是泪,今天加班只为找到这个bug,………………….fuck


有符号数和无符号数之间的操作,编译器会先将有符号数转换成无符号数再进行运算。

看下面的例子:

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
#include <iostream>
using namespace std;
 
int main()
{
	unsigned int i = 3;
 
	if ( -1 < i )
		cout << "fuck" << endl;
	else
		cout << i << endl;
 
	unsigned int a = 10;
	int b = -20;
 
	cout << a+b << endl;
 
	return 0;
}
 
// output
/*
3
4294967286
*/

2013.8.4 这天也碰到这个问题,丫的,这回真的痛定思痛了。

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
#include<iostream>
#include<string>
#include <vector>
#include <stdlib.h>
using namespace std;
 
int main()
{
	string a = "hello", b = "world";
 
	vector< string > vsTemp;
 
	vsTemp.push_back( a );
	vsTemp.push_back(b );
 
	unsigned int j = -1;
	if ( j >= 0 )
		cout << "j == " << j << endl;     // j == 4294967295
 
 
	// 所以下面写循环是错误的,会死循环。
	// 正确的写法是注意点就是了,比如改成 int,。。。。
	for ( unsigned int i = vsTemp.size()-1 ; i >= 0 ; --i )
	{
		cout << vsTemp[i] << endl;
		cout << " i == " << i << endl;
		system("pause");
	}
 
	return 0;
}

C++11 正则表达式

先看这个入个门:http://www.cnblogs.com/zhuyp1015/archive/2012/04/08/2438191.html

然后详见:http://en.cppreference.com/w/cpp/regex

正则表达式的符号功能见百度百科:http://baike.baidu.com/view/94238.htm

还要考虑支持unicode字符,需要使用wstring,下面regex_match的一个例子:

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
#include <iostream>
#include <regex>
#include <string>
 
 
int main()
{
	std::locale::global(std::locale(""));
	std::wcout.imbue(std::locale());
 
	std::wstring resource = L"哈哈,I love you 就是我爱你的意思!!!";
 
	std::wstring patternStr;   // 例如: ".*就是我.*的意思.*" 或 ".*" 可以匹配 resource
 
	while( std::wcin >> patternStr )
	{
		const std::wregex pattern(patternStr);  // 把 patternStr 作为一个正则表达式在 resource 中去匹配
 
		if( std::regex_match(resource,pattern) )
		{
			std::wcout << L"成功匹配---" << patternStr << "---" << std::endl;
		}
		else
		{
			std::wcout << L"不匹配---" << patternStr << "---" << std::endl;
		}
	}
 
	return 0;
}

下面判断一个字符串中是否存在一个指定的子串,这个子串在程序被当做正则表达式处理。

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
#include <iostream>
#include <string>
#include <regex>
 
/***************************************************************
Description: 判断字符串 wsResource 中是否存在 wsPattern 这样的子表达式
Input:  字符串 wsResource 和 正则表达式 wsPattern
Output:
Return:  若存在则返回 true, 否则返回 false
Others:
****************************************************************/
 
bool ExistSubExpression(const std::wstring& wsResource,const std::wstring& wsPattern)
{
	std::wregex pattern(L".*"+wsPattern+L".*"); // 前缀和后缀可以为'n'之外的任何字符
	return std::regex_match(wsResource,pattern);
}
 
 
int main()
{
	std::locale::global(std::locale(""));
	std::wcout.imbue(std::locale());
 
	std::wstring wsResource = L"哈哈,I love you 就是我爱你的意思!!!";
 
	std::wstring wsPattern;
	wchar_t pTemp[50];
 
	while( std::wcin.getline(pTemp,50) )   // 这样就可以包含空格在wsPattern中
	{
		wsPattern.assign(pTemp);
 
	//	std::wcout << wsPattern << std::endl;
	//	std::wcout << pTemp << std::endl;
 
		if ( ExistSubExpression(wsResource,wsPattern) )
		{
			std::wcout << L"存在---" << wsPattern << std::endl;
		}
		else
		{
			std::wcout << L"不存在---" << wsPattern << std::endl;
		}
	}
 
 
	return 0;
}

locale以及字符串安全函数

strcpy 和 strncpy 等等 都是不安全的函数, 放心,默认情况下,vs2012 会编译报错的。
安全函数一般的后缀为 _s , 例如 宽字符的拷贝函数 wcsncpy_s 。

如果要使用 宽字符 的话需要用到 locale ,详见:c++的本地化库 http://zh.cppreference.com/w/cpp/locale

还有一些 微软 的安全函数 ,包含在 strsafe.h 中, 详见 msdn http://msdn.microsoft.com/zh-CN/library/ms647466.aspx

看下面这个例子,在vs2012下编译运行(在vs2005运行有错),另外 wcsncpy 在 vs2005 中仅仅是给出 deprecated 的 警告错误,而在 vs2012 中却直接给出error, 看来还是 vs2012 靠谱。

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
#include <iostream>
#include <locale>
#include <string>
//#include <strsafe.h>
 
int main()
{
	std::wcout << std::locale("").name().c_str() << std::endl;
	std::wcout << 1000.01 << std::endl;   // 1000.01
 
	std::locale::global(std::locale(""));
	std::wcout.imbue(std::locale());  // use the new global locale for future wide character output
 
	std::wcout << 1000.01 << std::endl; // 1,000.01
 
 
 
	std::wstring str = L"你好a,我是lijie,嘿";
	std::wcout << str << std::endl;  // 你好a
	std::cout << str.length() << std::endl;  // 13
 
	str[2] = L'啊';
 
	for( int i=0; i<str.length(); ++i )  // 你 好 啊
	{
		std::wcout << str[i] << " ";
	}
	std::cout << std::endl;
 
 
	if( L'啊' == str[2] )
	{
		std::cout << "is 啊" << std::endl;
	}
 
	if( std::isalpha('a',std::locale() ) )
	{
		std::cout << "是字母" << std::endl;
	}
 
	wchar_t wc[] = L"我爱你";
	std::wcout << wc << std::endl;
	std::cout << std::wcslen(wc) << std::endl;  // 3
	std::cout << sizeof(wc) << std::endl;   // 8
 
	wchar_t wstemp[4];
	std::cout << std::wcslen(wstemp) << std::endl;  // 1
	std::wcout << sizeof(wstemp) << std::endl; // 8
	std::cout << sizeof(wchar_t) << std::endl; // 2
 
 
	//这是不安全函数,编译器报错,汗
    //std::wcsncpy( wstemp,wc,sizeof(wstemp)/sizeof(wchar_t) );
 
	// 这样可以
    //std::wstring wdest(wc);
 
	//使用安全函数,一般后缀都带有 _s 标记
	std::cout << _countof(wc) << std::endl;  // 4, 包含串结束符
	wcsncpy_s( wstemp, wc, _countof(wc) );
	std::wcout << wstemp << std::endl;
	if( '' == wstemp[3] )
	{
		std::cout << "haha" << std::endl;
	}
 
	std::cout.imbue(std::locale("french_france"));
	double x = 1234567.123456;
 
	std::cout << x << std::endl;  // 1,234566e+006
 
	return 0;
 
}

实习 — 第一周

7.11号入的职,不算周末的话,也在公司呆了7天了,写个一周总结好了。

先叙述一下这段时间的状态。

7.11,7.12 培训,主要是介绍公司文化,制度等。
7.13 (周六)在酒店睡大觉,三星级的酒店就是舒服,嚯嚯。
7.14 和菊花哥一起去找房子了,最后因为定金太贵没谈成。

7.15 星期一, 上午是我们业务开发组的例会,前辈们分享了c++的测试框架GTest和GMock,
好吧,我没听过,回去果断谷歌,下午在VS2005上了搭建了GTest和GMock的环境,
尝鲜了下,感觉GTest和boost里面的test差不多,又接触到了新的东西,很有爱。

7.16– 7.19 期间各种培训,没什么好说的。其余时间在denny大哥的指导下
玩了下python,由于以前接触过python,所以上手很快,主要学了下python的文件操作,
以及Django框架,然后用 Django + python + mysql + html 写了个页面显示mysql数据库
中的数据。

然后 7.20,7.21又是周末了。。。。。

总的来说,这个星期感觉还行,大tx的氛围果然不错。不过还有很多东西都需要去学习。
下个星期就启动 mini项目–QQ搜索 了,非常期待。。

GTest and GMock

分享会上听到的,果断学一下。
Google开源C++单元测试框架的简称为GTest。
GTest详见:http://www.cnblogs.com/coderzh/archive/2009/04/06/1426755.html
GMock详见:http://heuristic-cookbook.appspot.com/Google-Mock-%E5%85%A5%E9%97%A8

c++ 11 —- weak_ptr

详见:http://en.cppreference.com/w/cpp/memory/weak_ptr

weak_ptr 是为配合 shared_ptr 而引入的一种智能指针,它更像是 shared_ptr 的一个助手而不是智能指针,因为它不具有普通指针的行为,
没有重载 operator* 和 -> 。它的最大作用在于协助 shared_ptr 工作,像旁观者那样观测资源的使用情况。(这段话来自于《boost程序库完全开放指南 第二版》)

weak_ptr 保存一个已经被shared_ptr管理了的对象的weak_reference(弱引用),必须转换成shared_ptr 才能访问这个对象(用lock()转化)。
弱引用并不修改该对象的引用计数,这意味这弱引用它并不对对象的内存进行管理,在功能上类似于普通指针,然而一个比较大的区别是,弱引用能检测到所管理的对象是否已经被释放,从而避免访问非法内存。

下面是一个小例子:

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
#include<iostream>
#include<string>
#include<memory>
using namespace std;
 
weak_ptr<int> gw;
 
void f()
{
	if(gw.expired()){ // 用 expired() 也可以判断指针是否过期
		cout << "gw.expired(): gw is expired" <<endl;
	}
 
	if(auto spt = gw.lock()){ // 在使用之前必须copy到一个shared_ptr
		cout << *spt << endl;
	}
	else{
		cout << "gw is expired" <<endl;
	}
}
 
int main()
{
	{
		auto sp = make_shared<int>(42);
		gw = sp;
 
		cout << sp.use_count() <<endl;  // 仍然是 1
 
		f();
	}
 
	f();
 
	auto p = make_shared<int>(10);
 
	weak_ptr<int> q = p;
 
	//cout << *g <<endl;   // 非法,必须用 lock() 转化成 shared_ptr 才可以访问对象
 
	cout << *q.lock() <<endl;
 
	return 0;
}

c++ 11 —- shared_ptr

详见:http://en.cppreference.com/w/cpp/memory/shared_ptr

shared_ptr 是通过指针保持某个对象的共享拥有权的智能指针。若干个 shared_ptr 对象可以拥有同一个对象;最后一个指向该对象的 shared_ptr 被销毁或重置时,该对象被销毁。销毁该对象时使用的是 delete 表达式或者是在构造 shared_ptr 时传入的自定义删除器(deleter)。

下面是个小例子:

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
#include<iostream>
#include<string>
#include<memory>
using namespace std;
 
struct Foo{
	Foo(){
		cout << "Foo..." <<endl;
	}
	~Foo(){
		cout << "~Foo..." <<endl;
	}
};
 
struct D{
	void operator()(Foo* p) const{
		cout << "call delete for Foo object..." <<endl;
		delete p;
	}
};
 
int main()
{
	shared_ptr<foo> sh1;
 
	shared_ptr<foo> sh2(new Foo);
	shared_ptr<foo> sh3(sh2);
 
	cout << sh2.use_count() << endl;
	cout << sh3.use_count() << endl;
 
	shared_ptr<foo> sh4(new Foo,D());
 
	shared_ptr<foo> sh5 = sh4;
 
	cout << "hello world" <<endl;
 
	return 0;
}

c++ 11 —- unique_ptr

详见:
http://en.cppreference.com/w/cpp/memory/unique_ptr

把 en 改成 zh 即可看中文版的,不过是通过google翻译过来的,有一些翻译不是很准确:
http://zh.cppreference.com/w/cpp/memory/unique_ptr

unique_ptr 是一个智能指针:
(1)保留了唯一的一个对象的所有权通用指针,不能拷贝或复制。
(2)在unique_ptr超出作用域后会自动destroy所指向的对象。
下面是个小例子:

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
#include<iostream>
#include<string>
#include<memory>
using namespace std;
 
struct Foo{
	Foo() { cout<<"foo::foo" <<endl; }
	~Foo(){ cout << "Foo::" <<endl; }
	void bar() { cout<< "Foo::bar" <<endl; }
};
 
void f(const Foo& foo)
{
	cout << "f(const Foo& foot)" <<endl;
}
 
int main()
{
	unique_ptr<foo> p1(new Foo);
	if(p1)
		p1->bar();
 
	{
		unique_ptr<foo> p2(move(p1));
 
		if(p1 == nullptr)
			cout << "p1 is nullptr" <<endl;
 
		f(*p2);
 
		p1 = move(p2);
 
		cout << "destroying p2..." <<endl;
	}
 
	if(p1)
		p1->bar();
 
	return 0;
}

c++ 11 —- unordered_set unordered_map

详见: http://www.cplusplus.com/reference/unordered_set/unordered_set/
http://www.cplusplus.com/reference/unordered_set/unordered_multiset/
http://www.cplusplus.com/reference/unordered_map/unordered_map/
http://www.cplusplus.com/reference/unordered_map/unordered_multimap/

unordered_set,unordered_map 的原理是一样的,都是开链哈希,不解释了。
他们不保证任何顺序(包括输出),不能更改key,只能删除和插入。
unorderer_multiset ,unordered_multimap 则允许重复的值。

四种容器大同小异,下面以 unordered_set 作为例子:
基本操作如下

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
#include<iostream>
#include<unordered_set>
#include<unordered_map>
using namespace std;
 
/*
	template< class key,   					 // unordered_set::key_type/value_type
			  class Hash = hash<key>,		 // unordered_set::hasher
			  class Pred = equal_to<key>,	 // unordered_set::key_equal
			  class Alloc = allocator<key>,	 // unordered_set::allocator_type
			> class unordered_set;
*/
 
template<typename T>
T cmerge(T a,T b)
{
	T t(a);
	t.insert(b.begin(),b.end());
	return t;
}
 
int main()
{
	// constructor
	unordered_set<string> us1;
	unordered_set<string> us2 = {"red","green","blue"};
	unordered_set<string> us3(us2);
 
	unordered_set<string> us4 (cmerge(us2,us3));
	unordered_set<string> us5 (us4.begin(),us4.end());
 
	for(auto x : us5)
		cout << x << " ";
	cout << endl;
 
	us1 = us2;
	for(auto x : us1)  // blue red green ,输出并不保证顺序
		cout << x << " ";
	cout << endl;
 
	// capacity and buckets
	cout << us1.empty() <<endl;  // 0
	cout << us1.size() <<endl;   // 3
	cout << us1.max_size() <<endl; // 357913941
 
	unordered_set<int> us6;
	cout << us6.empty() <<endl;   // 1
	cout << us6.max_size() <<endl;  // 536870911
	cout << us6.max_bucket_count() <<endl;  // 536870911
	cout << us6.max_load_factor() <<endl;  // 1
	cout << us6.bucket_count() <<endl;  // 11
	cout << us6.load_factor() <<endl;  // 0
 
	// iterators
	for(auto iter = us5.begin(); iter != us5.end(); ++iter)
		cout << *iter << " ";
	cout << endl;
 
	// element lookup and modifiers
	if( us5.find("lijie") == us5.end() )
		cout << "none" <<endl;
 
	cout << us5.count("lijie") <<endl; // 0
	cout << us5.count("red") <<endl;  // 1
 
	us5.insert("lijie");
	for(auto x : us5)
		cout << x << " ";
	cout <<endl;
 
	us5.erase("lijie");   // erasing by key
	// us5.erase(us5.find("lijie"));  // erasing by iterator
 
	us5.erase( us5.find("red"), us5.end() ); // erasing by range
	for(auto x : us5)
		cout << x << " ";
	cout <<endl;
 
	// hash policy and observers
	unordered_set<string> myset;
	myset.rehash(12);
 
	myset.insert("office");
	myset.insert("house");
	myset.insert("gym");
	myset.insert("parking");
	myset.insert("highway");
 
	cout << myset.bucket_count() <<endl;  // 7
 
	// hash function
	unordered_set<string>::hasher fn = myset.hash_function();
 
	cout << fn("that") << endl;
	cout << fn("than") << endl;
 
	// comparisons
	unordered_set<string>
	a = {"AAPL","MSFT","GOOG"},
	b = {"MSFT","GOOG","AAPL"},
	c = {"MSFT","GOOG","AAPL","ORCL"};
 
	if( a == b ) cout << " a and b are equal " <<endl;
	if( b != c ) cout << " b and c are not equal " <<endl;
 
	return 0;
}

下面是自定义自己的hash函数:

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
#include<iostream>
#include<string>
#include<unordered_set>
using namespace std;
 
struct Node
{
	string a;
	int b;
	char c;
 
	Node(string _a,int _b,char _c): a(_a),b(_b),c(_c) { }
};
 
template<typename T>
struct myhash
{
	int operator()(const T& a) const  // 用 b 来做 key
	{
		return a.b % 100;
	}
};
 
template<typename T>
struct myequal
{
	bool operator()(const T& a,const T& b) const  // 用 c 来作为值比较大小
	{
		return a.c == b.c;
	}
};
 
int main()
{
	unordered_set<node,myhash<node>,myequal<node>> us;
 
	Node a("lijie",520,'c'),b("dou",52,'d');
	us.insert(a);
	us.insert(b);
 
	for(auto x : us)
		cout << x.a << " " << x.b << " " << x.c <<endl;
 
	return 0;
}