C++ Fragments

0. 检索 C++API 的无敌好网站: cplusplus
   C++ 惯用法, 介绍在不同情况下 C++ 的 Best Practice: More C++ Idioms

1. %.2f 输出两位小数.

2. atof 转 string 为 double.<stdlib.h>

3. 1/1000 会返回0, 即使写在 double(1/1000) 也一样; 若想得到 0.001, 必须写成 1.0/1000.

4. 不能直接写 string head = 'P' + "="; 也不能写成 string head = "p" + "="; 因为 'P' 是 char 类型, "="是const char[2] 类型(注意不是string类型), 而这两者都是没有重载.

5. cin 与 getline 混合用会有问题,cin 不会吃掉空白字符,getline 会吃掉空白字符, 所以 cin 完了应该接一个 cin.ignore(), 保证后面的 getline 能正确读取.

6. 字符串的替换, 应使用 string 中的 replace, 不要直接用 <algorithm> 中的 replace, 因为 <algorithm> 中的 replace 不会改变空间大小, 所以如果进行替换的字符串长度不一样, 就会导致异常.

7. 使用 string 的 substr 来提取子字符串.

8. string 字符串替换(这样的替换可能会带来歧义, 参看 10115-Automatic Editing)
即对每一个 oldStr 都会替换一次, 包括刚替换成 newStr 后出现的 oldStr; 而不是说从头到尾只遍历一次, 把碰到的 oldStr 替换掉.

// 将 src 中的所有的 oldStr 替换成 newStr
string replaceAll(string src, const string oldStr, const string newStr)
{
	size_t found;
	int len = oldStr.size();
	
	while( (found = src.find(oldStr)) != string::npos ){
		src.replace(found, len, newStr);
	}

	return src;
}

9. 使用  transform (line.begin(), line.end(), line.begin(), ::toupper); 把 line 里的字符都转成大写, 这里要注意 :: toupper , 必须加上全局空间标识符, 因为它不属于 std 命名空间.

10. tolower/toupper 把字母转为小/大写; less<int>(), greater<int>() 比较两个 int 的小/大.

11. 字符串中查找指定字符, 使用以下代码

wrongAnswer.find(guesses[i]) == string::npos

12. 字符串删除指定字符, 使用以下代码 

string::iterator new_end = remove_if(puzzle.begin(), puzzle.end(), bind2nd(equal_to<char>(), guesses[i]));
puzzle.erase(new_end, puzzle.end());

13. STL 容器(包含 string) 都可以使用 empty() 函数来判断其是否为空. 

14. 使用 atoi 转 string 为 int.

15. 使用 getline(cin, str) 逐行读入.

16. 使用 atoi 将字符转化为整数, 或者使用 (int)('c' - '0');.

17. isdigit() 判断是否为数字. (<cctype>).

18. string 的 length() 和 size() 都同样返回字符串长度, 用 length() 是为了保持 C 的风格, 用 size() 则是为了保持 STL 的风格.

19. 引入 #ifndef...#endif 条件编译. 因为 UVa 的系统都是 define 了 ONLINE_JUDGE 的, 所以像以下代码一样写, 可以保证在本地编译时是从文件读取, 而在 UVa judge 系统是按 cin 进行读取的. 这样可以大大提高调试效率, 避免每次都要重新输入所有的 input.

#ifndef ONLINE_JUDGE
	freopen ("445_i.txt", "r", stdin);  
	freopen ("445_o.txt", "w", stdout ); 
#endif

20. isalpha() 判断是否为字母(<cctype>).

21. isspace() 判断是否为空格(<cctype>).

22. C 语言里有 abs(), labs(), fabs() 函数是可以取绝对值.

23. cin.eof() 判断是否读到文件终止符.

24. vector.clear() 不会释放空间, 要释放空间需要 vector<T>().swap(x).

25. 使用 copy(worst.begin(), worst.end(), ostream_iterator<string>(cout, "\n")); 直接输出 vector 中的数据, 每输出一个都以 "\n" 分隔.

26. ostream_iterator 需要添加 <iterator> 头文件,否则会报 error: 'ostream_iterator' was not declared in this scope.

27. 以下代码中的 lowerExcuse 不能默认为空, 因为 transform 不会分配空间, 即写成 string lowerExcuse; 是不对的;

string lowerExcuse = excuses[i]; 
transform(excuses[i].begin(), excuses[i].end(), lowerExcuse.begin(), ::tolower);

28. 求 2 的 N 次方可用函数 pow(2, N); (<math.h>)

29. set_difference 求交集差, 注意两个区间必须先排好序(否则结果会是不正确的); 结果区间也必须先准备好, 因为 set_difference 不会分配空间.
以下代码是求集合 words 与 dictionary 的差, 结果存到 diff 中:

		vector<string> diff;
		diff.resize(words.size());    // 准备好空间

		// 需先排好序
		vector<string>::const_iterator diffEnd;
		sort(dictionary.begin(), dictionary.end(), less<string>());	
		sort(words.begin(), words.end(), less<string>());	

		diffEnd = set_difference(words.begin(), words.end(), dictionary.begin(), dictionary.end(), diff.begin());

30. sort(dictionary.begin(), dictionary.end(), less<string>()); 从小到大排列.(greater<string>()) 从大到小排列.

31. 使用 min 求两数中的较小值; max 求两数中的较大值.(<algorithm>)

32. find 不能使用自定义函数为参数进行查找; search 才可以, 但是 search 要求必须是两个区间段之间的查找.以下代码表示在 group 中查找 line, 其比较函数是自定义的 immediateCompare:

		// 这样写是为了能使用下面的 search 函数
		vector<string> temp;
		temp.push_back(line);

		// 判断 group 中是否有和当前 line 为前缀的字符串, 若有, 则 immediately 为 true 
		if(search(group.begin(), group.end(), temp.begin(), temp.end(), immediateCompare) != group.end())
			immediately = false;

33. 可使用 find_if 函数完成以上功能.

// 判断 group 中是否有和当前 line 为前缀的字符串, 若有, 则 immediately 为 true 
if(find_if(group.begin(), group.end(), bind1st(ptr_fun(immediateCompare), line)) != group.end())
    immediately = false;

34. 使用 bind1st, bind2nd 把 binary 函数转为 unary 函数. 见 644 - Immediate Decodability (Update) 

35. 使用 ptr_fun 把 function pointer 转化为 function object. 见 644 - Immediate Decodability (Update) 

36. 使用 count(guess.begin(), guess.end(), 0) 来计算 0 出现的次数.

37. map 的 key 默认就是字典序, 所以如果要求按 map 的 key 从小到大输出, 就直接输出即可, 无需再进行排序. 见: 10420 - List of Conquests(UPDATE).

38. 最大整数为 numeric_limits<int>::max();  // <limits>

39. printf("%4d", histogram[i]); 输出宽度为4的整数, 右对齐.

40. 使用 sqrt 开根号. // <cmath>

41. 使用 istringstream 从 string 读入. // <sstream>. 见 120 - Stacks of Flapjacks

42. vector 的 erase 操作时, 若其参数是一个 iterator, 必须先判断 iterator 是否为 end(), 否则会出现各种奇怪的问题.

43. string 的 replace 是直接影响原字符串, 而不是返回一个 replace 过的字符串.

44. unique 之前也需要先排序.

45. distance 取两个 iterator 之间的距离.

46. advance(iterator, n); 把一个 iterator 前进 n 步.

47. stl distance 会返回负数吗? 不会, 如果 distance 的第二个参数所指位置在第一个参数之前, 则会绕回来. (在 list 里是这样的, 但是对于其他 container 不是很确定是否会是这样的行为).

48. char c 转 string: string str(1, c); 或 ""+c; 

49.  list insert 时, 若传进来的 iterator 为 end(), 会直接插在最后面吗? 会的!!!

50. 使用 sscanf(b.c_str(), "%4d%2d%2d", &y,&m,&d); 拆分格式为 YYYYMMDD 的字符串到各个整数中.

51. << 运算符优先级比 - 要低; 
     1 << 31 - 1; 会计算 1 << (31-1); 结果为 1073741824
     (1 << 31) - 1; 才会得到最大 32 位整数 2147483647

52. min_elementmax_element(<algorigthm>) 分别返回一个区间内的最小/最大值.如果是 C++11, 则可以直接用 minmax_element 同时返回区间内的最小/最大值.

53. rotate (ForwardIterator first, ForwardIterator middle, ForwardIterator last); 把[first, middle) 的部分与 [middle, last) 的部分进行交换, 即交换后 middle 位于最前方.

54. std::next_permutation(A.begin(), A.end()) 可以取得全排列的下一个.(看一下是怎么实现的)



你可能感兴趣的:(C++,小片段)