代碼中 os.setf(initial); 註釋與否運行結果相同,疑似無效。實際上 setf 用於設置流格式標誌位,initial 應為 ios_base::fmtflags 類型變量,保存需保留的格式狀態。
ios_base::fmtflags 是位掩碼類型,每個標誌位控制一項輸出格式:
| 標誌位 | 含義 | 操作符等價 |
|---|---|---|
boolalpha | bool 輸出 true/false | std::boolalpha |
showbase | 顯示進制前綴 (0x, 0) | std::showbase |
hex/oct/dec | 十六/八/十進制 | std::hex 等 |
showpoint | 強制顯示小數點 | std::showpoint |
fixed/scientific | 定點/科學計數法 | std::fixed 等 |
left/right/internal | 對齊方式 | std::left 等 |
skipws | 輸入跳過空白 | std::skipws |
// 1. 設置指定標誌位,其餘不變
fmtflags setf(fmtflags flags); // 如 os.setf(ios::hex);
// 2. 設置標誌位組合,先清除 mask 中的舊位
fmtflags setf(fmtflags flags, fmtflags mask); // 如 os.setf(ios::hex, ios::basefield);
關鍵:第二種形式先 flags() & ~mask 清除相關舊標誌,再 | flags 設置新標誌。常用於互斥組(如 basefield = dec|oct|hex)。
// 典型用法:保存當前格式,臨時修改,最後恢復
ios_base::fmtflags oldFlags = os.flags(); // 保存所有標誌
os.setf(ios::hex | ios::showbase); // 臨時設置十六進制帶前綴
os << 100 << '\n'; // 輸出 0x64
os.flags(oldFlags); // 恢復原格式
若代碼中 initial 只是未修改的變量,則 setf(initial) 相當於「設置為當前值」,**無實際效果**,解釋為何註釋不影響結果。
#include <iostream>
#include <iomanip>
int main() {
std::cout << "Default: " << 100 << '\n'; // 100
// 方法1:操作符鏈式(推薦,現代 C++)
std::cout << std::hex << std::showbase << 100 << '\n'; // 0x64
// 方法2:setf 設置單個標誌
std::cout.setf(std::ios::hex);
std::cout.setf(std::ios::showbase);
std::cout << 100 << '\n'; // 0x64
// 方法3:setf + mask 切換進制(清除舊進制位)
std::cout.setf(std::ios::oct, std::ios::basefield); // 清除 hex, 設置 oct
std::cout << 100 << '\n'; // 0144
// 方法4:fmtflags 變量級操作(底層控制)
std::ios_base::fmtflags ff = std::cout.flags();
ff &= ~std::cout.basefield; // 清除進制位
ff |= std::cout.hex; // 設置十六進制
ff |= std::cout.showbase; // 設置前綴
std::cout.flags(ff);
std::cout << 100 << '\n'; // 0x64
return 0;
}
std::hex, std::fixed 等):可讀性強、异常安全、自動管理狀態。setf(flags, mask),如切換進制必須清除 basefield。os.setf(initial) 若無效果,說明 initial 保存的是當前狀態。fmtflags 是位掩碼,setf 用於設置/清除標誌位。現代 C++ 首選流操作符,底層機制理解有助於調試複雜格式化問題。