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_element 与 max_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()) 可以取得全排列的下一个.(看一下是怎么实现的)