這是一個最常用的容器中的最常用的方法,可是最近在用的時候卻出現了問題。下面大家看看這是什麼情況吧:
#include "stdafx.h" #include <string> using namespace std; int _tmain(int argc, _TCHAR* argv[]) { string s = "UIPower"; string s2 = "owe"; size_t x = s.find("owe",1); size_t y = s.find(s2,2); return 0; }
猜猜x,y分別是多少吧,有不少人認為是2,1吧,有沒有中槍!反正我開始時這麼認為的,但是經過測試發現不對啊,x,y居然都是3,什麼情況?
跟蹤進去看看find到底是怎麼寫的,發現下面這段代碼
size_type __CLR_OR_THIS_CALL find(const _Elem *_Ptr, size_type _Off, size_type _Count) const { // look for [_Ptr, _Ptr + _Count) beginnng at or after _Off #if _HAS_ITERATOR_DEBUGGING if (_Count != 0) _DEBUG_POINTER(_Ptr); #endif /* _HAS_ITERATOR_DEBUGGING */ if (_Count == 0 && _Off <= _Mysize) return (_Off); // null string always matches (if inside string) size_type _Nm; if (_Off < _Mysize && _Count <= (_Nm = _Mysize - _Off)) { // room for match, look for it const _Elem *_Uptr, *_Vptr; for (_Nm -= _Count - 1, _Vptr = _Myptr() + _Off; (_Uptr = _Traits::find(_Vptr, _Nm, *_Ptr)) != 0; _Nm -= _Uptr - _Vptr + 1, _Vptr = _Uptr + 1) if (_Traits::compare(_Uptr, _Ptr, _Count) == 0) return (_Uptr - _Myptr()); // found a match } return (npos); // no match }
這是xstring文件中的代碼,應該是很底層的東西了這裡的_Ptr是要查找的字符串,這裡就是"owe"了,_Off是偏移量,也就是從哪個字符開始查找的,這裡就是1了,_Count就是要查找的字符串的長度,這裡就是3了,程序走到12行,這裡的_Mysize就是整個字符串的長度,這裡就是7了,這裡要對_Count進行一個判斷,也就是它的長度不能超過整個字符串的長度減去偏移量的大小,超過了就肯定找不到了,下面15行的循環_Vptr就是偏移後的字符,這裡對應的應該是"IPower",_Nm是控制程序循環幾次,這裡處置設置為4,也就是只能有4種可能,"IPo","Pow","owe","wer",這裡這個_Uptr = _Traits::find(_Vptr, _Nm, *_Ptr)) != 0這個函數跟進去看看是這樣的:
static const _Elem *__CLRCALL_OR_CDECL find(_In_count_(_Count) const _Elem *_First, size_t _Count, const _Elem& _Ch) { // look for _Ch in [_First, _First + _Count) // _DEBUG_POINTER(_First); return ((const _Elem *)::memchr(_First, _Ch, _Count)); }
這個函數的意思是在_First中找第一個字符_Ch出現的位置,並把包括_Ch在內的總共_Count個字符返回,所以這裡返回得到的_Uptr是字符串"ower",對這個_Uptr判斷其是否為空,如果為空說明沒有找到以字符_Ch開始的字符串,直接跳出for循環,如果找到了就對這個字符串和_Ptr做比較,函數_Traits::compare(_Uptr, _Ptr, _Count)比較_Ptr和_Uptr的前3個字符,這裡_Count是要查詢的字符串的長度,匹配成功返回_Ptr在_Uptr中首次出現的下標,如果為0就說明正確匹配了,下面看關鍵的返回值,真心不明白這個_Myptr()函數干了說明,但是貌似沒有起到加偏移量的作用,因為最後返回得到的x是3,也就是字符"o"首次出現的下標,所以我在想,這個最後返回的結果是不是應該加上_Off這個開始時候的偏移量!
_Elem *__CLR_OR_THIS_CALL _Myptr() { // determine current pointer to buffer for mutable string return (_BUF_SIZE <= _Myres ? _Bx._Ptr : _Bx._Buf); }
翻譯過來的意思是確定當前的可變的字符串緩沖區的指針,_BUF_SIZE是16,_Myres是15,返回的自然是_Bx._Buf這個字符串指針了,而_Bx._Buf這個字符串就是,最後的return
(_Uptr - _Myptr()); 兩個指針做差返回的是兩個指針的相對位置差,自然會得到3這樣的答案,分析原因,我覺得,可能系統以為_Myptr()返回的會是_Vptr這個指針,但是實際返回的是_Ptr這個指針,這裡涉及到緩沖區的操作,不是很清楚裡面的具體情況,但是根據實際結果看這裡系統確實返回的是_Ptr的地址,所以不奇怪為什麼都會是3這個結果了!
本文出自 “賣萌程序員” 博客,請務必保留此出處http://7677869.blog.51cto.com/7667869/1276225