武漢網(wǎng)站建設培訓專業(yè)推廣公司
這段代碼是一個快速讀取整數(shù)的自定義函數(shù),通常用于ACM競賽或高性能計算場景。它通過getchar()
直接讀取字符,比scanf()
和cin
更快,尤其適合處理大規(guī)模數(shù)據(jù)。以下是詳細解析:
一、代碼功能總覽
該函數(shù)實現(xiàn)了從標準輸入讀取一個整數(shù)(支持正負),核心邏輯分為兩步:
- 跳過非數(shù)字字符,識別正負號
- 讀取數(shù)字字符并轉換為整數(shù)
二、逐行解析
inline int read() {int x = 0, f = 1; // x存儲整數(shù)結果,f標記正負(1為正,-1為負)char ch = getchar(); // 讀取第一個字符// 第一步:跳過非數(shù)字字符,處理正負號while (ch < '0' || ch > '9') { // 當字符不是數(shù)字時if (ch == '-') f = -1; // 遇到負號,標記負數(shù)ch = getchar(); // 繼續(xù)讀取下一個字符}// 第二步:讀取數(shù)字字符并轉換為整數(shù)while (ch >= '0' && ch <= '9') { // 當字符是數(shù)字時x = x * 10 + ch - '0'; // 核心轉換:字符轉數(shù)字并累乘ch = getchar(); // 讀取下一個字符}return x * f; // 應用正負號,返回最終結果
}
三、核心轉換原理
1. 字符轉數(shù)字
ch - '0'
:將字符(如'5'
)轉換為對應的整數(shù)(5)。
原理:字符'0'
到'9'
的ASCII碼是連續(xù)的,'5' - '0' = 5
。
2. 逐位累加
x = x * 10 + digit
:按位構建整數(shù)。
例如,讀取'1' '2' '3'
時:- 初始
x=0
,讀取'1'
→x = 0*10 + 1 = 1
- 讀取
'2'
→x = 1*10 + 2 = 12
- 讀取
'3'
→x = 12*10 + 3 = 123
- 初始
四、與scanf/cin的性能對比
函數(shù) | 讀取1e7個整數(shù)的時間(近似) | 優(yōu)勢場景 |
---|---|---|
cin | 約1.5秒 | 簡單場景,代碼可讀性高 |
scanf | 約0.5秒 | 中等數(shù)據(jù)量 |
read() | 約0.2秒 | 超大數(shù)據(jù)量(1e6+) |
性能優(yōu)勢原因:
- 跳過了
scanf
的格式解析和cin
的類型安全檢查 - 直接操作字符,減少函數(shù)調用開銷
inline
關鍵字避免函數(shù)調用棧開銷
五、示例使用
#include <cstdio>
using namespace std;inline int read() {int x = 0, f = 1;char ch = getchar();while (ch < '0' || ch > '9') {if (ch == '-') f = -1;ch = getchar();}while (ch >= '0' && ch <= '9') {x = x * 10 + ch - '0';ch = getchar();}return x * f;
}int main() {int n = read(); // 讀取整數(shù)nint arr[100000];for (int i = 0; i < n; i++) {arr[i] = read(); // 快速讀取數(shù)組}return 0;
}
六、注意事項
-
輸入合法性
- 若輸入非數(shù)字字符(如字母),函數(shù)會跳過直到遇到數(shù)字或EOF。
- 輸入
"-123a456"
會被解析為-123
。
-
溢出處理
- 若輸入超過
int
范圍(如2147483648
),會導致整數(shù)溢出,需改用long long
:inline long long read() { /* 同理,返回long long */ }
- 若輸入超過
-
配合其他輸入函數(shù)
- 若之前使用過
cin
或scanf
,需用getchar()
清除緩沖區(qū)殘留的換行符。
- 若之前使用過
七、擴展:帶錯誤處理的版本
inline bool read(int& x) {x = 0;int f = 1;char ch = getchar();while (ch != EOF && (ch < '0' || ch > '9')) {if (ch == '-') f = -1;ch = getchar();}if (ch == EOF) return false; // 輸入結束while (ch >= '0' && ch <= '9') {x = x * 10 + ch - '0';ch = getchar();}x *= f;return true;
}// 使用:
int a;
if (read(a)) {// 讀取成功
} else {// 輸入結束或格式錯誤
}
這種快速讀取方法是ACM競賽中的常用技巧,能有效解決大數(shù)據(jù)輸入時的超時問題,建議在處理1e5以上數(shù)據(jù)量時使用。