原始碼核心問題
char a[10];
cin >> a; // 讀入字串 "1A3F"
cout.setf(ios::hex); // 只影響「輸出」格式,不影響輸入解析
int val; // 未從 a 轉換
// ... 後續邏輯混亂
誤區澄清
cin >> a 讀的是字元陣列,不會自動按十六進制解析為整數。
cout.setf(ios::hex) 僅改變輸出時的進制顯示,對 cin 無效。
- 輸入 "123" 時,程式無法判斷它是十進制 123 還是十六進制 0x123(291),必須由協議約定或前綴區分。
正確解析十六進制字串
方法一:std::stoul (C++11 推薦)
#include <iostream>
#include <string>
int main() {
std::string s;
std::cin >> s; // 輸入: 1A3F 或 0x1A3F
try {
unsigned long val = std::stoul(s, nullptr, 16); // 基數 16
std::cout << "十進制: " << val << '\n'; // 6719
std::cout << "十六進制: 0x" << std::hex << val << '\n';
} catch (...) {
std::cerr << "非法十六進制字串\n";
}
}
方法二:std::stringstream (舊標準相容)
std::string s; std::cin >> s;
std::stringstream ss;
ss << std::hex << s;
unsigned val; ss >> val;
方法三:掃描字元手動累加(教學用)
unsigned parseHex(const char* s) {
unsigned val = 0;
while (*s) {
char c = *s++;
int digit = (c>='0'&&c<='9') ? c-'0' :
(c>='A'&&c<='F') ? c-'A'+10 :
(c>='a'&&c<='f') ? c-'a'+10 : -1;
if (digit == -1) break; // 非法字元停止
val = val * 16 + digit;
}
return val;
}
完整互動範例
int main() {
std::string input;
std::cout << "輸入十六進制 (可帶 0x): ";
while (std::cin >> input) {
try {
unsigned val = std::stoul(input, nullptr, 16);
std::cout << "DEC: " << val << " HEX: 0x" << std::hex << val << std::dec << '\n';
} catch (...) {
std::cout << "格式錯誤\n";
}
std::cout << "下一個: ";
}
}
總結
- 輸入十六進制必須先讀字串,再指定基數 16 轉換。
ios::hex 僅控制輸出,不影響輸入。
- 推薦
std::stoul(str, nullptr, 16),支援 0x 前綴、大小寫混合、錯誤處理。