一、printf 格式控制完整指南
格式字串完整語法:%[flags][width][.precision][length]specifier
標誌位
-:左對齊(預設右對齊)
0:數值前導補零(預設空格)
+:正數顯示 + 號
空格:正數前置空格
#:替代形式(八進制前綴 0、十六進制前綴 0x、浮點數強制小數點)
寬度與精度
m:最小欄寬,不足補空格/零
.n:精度。整數→最小位數;浮點→小數位數;字串→最大字元數
*:由參數傳入寬度/精度
長度修飾符
hh:char
h:short
l:long / double / wchar_t*
ll:long long
L:long double
z:size_t
t:ptrdiff_t
j:intmax_t
轉換指示符速查
| 指示符 | 含義 | 範例 |
| d, i | 有號十進制整數 | %d, %5d, %05d |
| u | 無號十進制整數 | %u |
| o | 八進制 | %o, %#o |
| x, X | 十六進制 (小寫/大寫) | %x, %#X |
| f, F | 十進制浮點數 | %.2f, %10.4f |
| e, E | 科學記號 | %.3e |
| g, G | 自動選 f/e 短者 | %g |
| c | 單一字元 | %c |
| s | 字串 | %s, %10s, %.5s |
| p | 指標位址 | %p |
| n | 已輸出字元數存入指標 | %n |
| % | 輸出 % 字元 | %% |
關鍵提醒
float 經預設參數提升為 double,%f 通用;long double 用 %Lf。
%lf 在 printf 中等同 %f(C99 標準化);scanf 則必須區分。
- 輸出
% 必須寫 %%。
二、STL map 實戰完全手冊
基本定義
#include
三種插入方式
// 1. pair
mapStudent.insert(std::pair(1, "student_one"));
// 2. value_type
mapStudent.insert(std::map::value_type(2, "student_two"));
// 3. 下標運算子(可覆蓋)
mapStudent[3] = "student_three";
插入成功判斷
auto ret = mapStudent.insert({1, "new"});
if (ret.second) // true = 成功插入,false = 鍵已存在
std::cout << "Inserted\n";
遍歷方式
// 正向迭代器
for (auto it = mapStudent.begin(); it != mapStudent.end(); ++it)
std::cout << it->first << " " << it->second << "\n";
// 反向迭代器
for (auto it = mapStudent.rbegin(); it != mapStudent.rend(); ++it)
std::cout << it->first << " " << it->second << "\n";
// C++17 結構化綁定
for (auto& [key, val] : mapStudent)
std::cout << key << " " << val << "\n";
查找與範圍操作
// 單鍵查找
auto it = mapStudent.find(2);
if (it != mapStudent.end()) { /* found */ }
// 計數(map 只能 0 或 1)
size_t cnt = mapStudent.count(2);
// 區間查找
auto range = mapStudent.equal_range(2); // pair
auto it_low = mapStudent.lower_bound(2); // 首個 ≥ key
auto it_up = mapStudent.upper_bound(2); // 首個 > key
刪除操作
mapStudent.erase(it); // 迭代器刪除
mapStudent.erase(2); // 鍵刪除,回傳刪除數量
mapStudent.erase(begin, end); // 區間刪除 [begin, end)
mapStudent.clear(); // 全清
自訂排序(鍵為自訂類型)
struct StudentInfo { int id; std::string name; };
// 方法 1:運算子 < 重載
bool operator<(const StudentInfo& a, const StudentInfo& b) {
return a.id < b.id || (a.id == b.id && a.name < b.name);
}
// 方法 2:仿函數
struct StudentCmp {
bool operator()(const StudentInfo& a, const StudentInfo& b) const {
return a.id < b.id || (a.id == b.id && a.name < b.name);
}
};
std::map mapScore;
效能特性
- 查找/插入/刪除:O(log n)
- 節點額外開銷:~16 bytes(父/左右指標 + 紅黑標記)
- 優於通用 STL 算法:
map::find 比 std::find 快(利用樹結構)
三、sizeof 深度解析與常見誤區
sizeof vs strlen
| 表達式 | sizeof | strlen |
char* s = "abc" | 4/8 (指標大小) | 3 |
char s[] = "abc" | 4 (含 \0) | 3 |
char s[100] = "abc" | 100 | 3 |
int a[100] | 400 | 編譯錯誤 |
核心規則
- 編譯期計算:
sizeof 是運算子,非函數,編譯期常數(VLA 除外)。
- 類型參數需括號:
sizeof(int);變數可省略 sizeof x。
- 陣列不退化:
sizeof(arr) 為整個陣列大小;傳參退化為指標,函數內 sizeof(ptr) 為指標大小。
- 結構體對齊:編譯器插入填充位元組,
#pragma pack(n) 控制對齊。
- 不完全類型禁用:
sizeof(void)、sizeof(外部陣列)、sizeof(位域) 皆非法。
實用場景
- 動態配置:
malloc(sizeof(T) * n)
- 記憶體操作:
memset(buf, 0, sizeof(buf))(僅限陣列非指標)
- 序列化/網路傳輸:協議頭包含
sizeof(Struct) 利於版本演進
- 陣列元素計數:
sizeof(arr)/sizeof(arr[0])(僅限陣列非指標)
- 上一篇文章: C++ 回文判斷:從 STL 一行碼到指針雙向掃描
- 下一篇文章: C/C++ 內存洩漏深度解析:類型、成因與檢測策略
Copyright ©
程式碼之家 All Rights Reserved