網(wǎng)站首頁 編程語言 正文
最近因為一個字符引發(fā)了 Crash,因為實際的業(yè)務(wù)場景不便描述,這里便用一段測試代碼作說明。
話不多說,直接上代碼:
let testCharacters: Set= ["!", "\"", "$", "%", "&", "'", "+", ",", "<", "=", ">", "@", "[", "]", "`", "{", "}"] let testString = "@`Hello World?!" var result: UInt8 = 0 for character in testString { if testCharacters.contains(character) { result += character.asciiValue! } }
上面的代碼做的事情是:取出 testString 里特定字符的 ASCII 碼,然后相加。
我們來 Review 下這段代碼,有經(jīng)驗的同學(xué)應(yīng)該立馬嗅到了代碼里的壞味道:character.asciiValue! 這里用了強解。
那這里的強解用得合理嗎?因為定義在 testCharacters 里的字符肯定都有對應(yīng)的 ASCII 碼,咋一看這里用強解也沒關(guān)系。
但是,如果我們實際跑一下,就會出現(xiàn)因為 asciiValue 為 nil 的強解 Crash 了。這是為什么呢?
關(guān)鍵在于 testString 里面包含了 全角字符。testString 里的后一個 ? 是一個全角字符,它是沒有 asciiValue 的。
我們可以在 Swift Playgrounds 里執(zhí)行下面的代碼得到答案:
let halfWidth = "`" halfWidth.lengthOfBytes(using: .utf8) // 1 halfWidth.first!.isASCII // true halfWidth.first!.asciiValue // 96 let fullWidth = "?" fullWidth.lengthOfBytes(using: .utf8) // 3 fullWidth.first!.isASCII // false fullWidth.first!.asciiValue // nil // Character 實現(xiàn) Equatable 協(xié)議,判斷出兩個值是相等的。 halfWidth == fullWidth // true
從上面代碼執(zhí)行結(jié)果可以看到,halfWidth 這個半角字符占一個字節(jié)長度,對應(yīng)的 ASCII 碼為 96 而全角字符 fullWidth 占三個字節(jié)長度,其 asciiValue 為空的。
Swift 數(shù)組的 contains 方法利用的是 Equatable 協(xié)議 , 從上面代碼里 halfWidth == fullWidth 的結(jié)果為 true 來看,Character 實現(xiàn)的 Equatable 協(xié)議并沒有考慮字符全角/半角的情況。
用肉眼看,完全看不出字符有何不同,而 contains 方法結(jié)果為 true 也影響了我們的判斷,以為這個強解是 OK 的,稍不注意就導(dǎo)致了 Crash。
最后,從維基百科上整理了關(guān)于全角/半角的歷史知識:
在早期的計算機中,英語或拉丁字母語言使用的系統(tǒng),每一個字母或符號,都是使用一字節(jié)的空間(一字節(jié)由 8 比特組成,共256個編碼空間)來儲存;而漢語、日語及韓語文字,由于數(shù)量大大超過256個,故慣常使用兩字節(jié)來儲存一個字符。所以這原本是編碼層面的“單字節(jié)”“雙字節(jié)”的問題。
當(dāng)時的電腦使用等寬字體(如DOS、部分文字編輯器等)時,字體也就順應(yīng)這種編碼形式,將中日韓文字的寬度繪制成拉丁字母和數(shù)字的兩倍,這樣字符的編碼存儲和顯示寬度可以一一對應(yīng)起來:
- 單字節(jié)文字 顯示成 半寬,
- 雙字節(jié)文字 顯示成 全寬。
因此當(dāng)時的用戶就開始習(xí)慣稱中、日、韓等文字為 全角字符,而稱拉丁字母或數(shù)字為 半角字符。
但是,后來計算機的文字編碼技術(shù)已經(jīng)發(fā)生很大變化,存儲一個字符可能用一個、兩個、四個或者更多的字節(jié)。一個英文字符即使顯示為半寬,依照不同的編碼方式,并不一定是用一個字節(jié)存儲。
因此,現(xiàn)在字符編碼存儲和字符顯示寬度的已經(jīng)沒有一一對應(yīng)關(guān)系。
但是由于字符編碼和字形寬度曾經(jīng)的對應(yīng)關(guān)系,很多用戶一直習(xí)慣性地使用"全角/半角"詞匯。
因此現(xiàn)在的 全角字 可能是指:
- 用兩個字節(jié)存儲的字符
- ASCII(所謂半角英文和數(shù)字)以外所有的字符
- 顯示上字身寬度為一比一正方形的字形。
總結(jié)
原文鏈接:https://juejin.cn/post/7066723364991139870
相關(guān)推薦
- 2022-10-22 Python中的Unittest基本使用_python
- 2021-10-13 linux環(huán)境下恢復(fù)rm誤刪的文件方法_Linux
- 2022-04-15 使用python測試prometheus的實現(xiàn)_python
- 2022-04-28 Python中turtle.write方法使用說明_python
- 2022-12-13 OpenCV視頻流C++多線程處理方法詳細分析_C 語言
- 2023-03-13 Android?Hilt依賴注入的使用講解_Android
- 2022-10-02 Android?Flutter實現(xiàn)搜索的三種方式詳解_Android
- 2022-08-21 Android用Canvas繪制貝塞爾曲線_Android
- 最近更新
-
- window11 系統(tǒng)安裝 yarn
- 超詳細win安裝深度學(xué)習(xí)環(huán)境2025年最新版(
- Linux 中運行的top命令 怎么退出?
- MySQL 中decimal 的用法? 存儲小
- get 、set 、toString 方法的使
- @Resource和 @Autowired注解
- Java基礎(chǔ)操作-- 運算符,流程控制 Flo
- 1. Int 和Integer 的區(qū)別,Jav
- spring @retryable不生效的一種
- Spring Security之認(rèn)證信息的處理
- Spring Security之認(rèn)證過濾器
- Spring Security概述快速入門
- Spring Security之配置體系
- 【SpringBoot】SpringCache
- Spring Security之基于方法配置權(quán)
- redisson分布式鎖中waittime的設(shè)
- maven:解決release錯誤:Artif
- restTemplate使用總結(jié)
- Spring Security之安全異常處理
- MybatisPlus優(yōu)雅實現(xiàn)加密?
- Spring ioc容器與Bean的生命周期。
- 【探索SpringCloud】服務(wù)發(fā)現(xiàn)-Nac
- Spring Security之基于HttpR
- Redis 底層數(shù)據(jù)結(jié)構(gòu)-簡單動態(tài)字符串(SD
- arthas操作spring被代理目標(biāo)對象命令
- Spring中的單例模式應(yīng)用詳解
- 聊聊消息隊列,發(fā)送消息的4種方式
- bootspring第三方資源配置管理
- GIT同步修改后的遠程分支