日韩性视频-久久久蜜桃-www中文字幕-在线中文字幕av-亚洲欧美一区二区三区四区-撸久久-香蕉视频一区-久久无码精品丰满人妻-国产高潮av-激情福利社-日韩av网址大全-国产精品久久999-日本五十路在线-性欧美在线-久久99精品波多结衣一区-男女午夜免费视频-黑人极品ⅴideos精品欧美棵-人人妻人人澡人人爽精品欧美一区-日韩一区在线看-欧美a级在线免费观看

歡迎訪問 生活随笔!

生活随笔

當前位置: 首頁 > 编程语言 > c/c++ >内容正文

c/c++

字符与字符串操作——Windows via C/C++

發布時間:2023/12/18 c/c++ 34 豆豆
生活随笔 收集整理的這篇文章主要介紹了 字符与字符串操作——Windows via C/C++ 小編覺得挺不錯的,現在分享給大家,幫大家做個參考.

在最新版的Windows, Windows Vista,它應該支持Unicode 5.0。在編程中對字符與字符串的操作是很普通的,為新的系統寫代碼,盡可能使用Unicode,它提供了更好的性能,以及可以進行區域化。而且與COM及.Net框架互操作時也有幫助。
緩沖區溢出是系統漏洞的重要來源,Microsoft對此提供的c-runtime中包含了一些新函數用于操作字符串。你應該都使用這些新函數。
在Windows Vista中,每個字符都用UTF-16(UTF是Unicode Transformation Format)進行編碼,它是雙字節的,這里我們所指的Unicode都指UTF-16編碼。但是雙字節還不能表示某些語言中的所有字符,對于這些語言,它支持代理(surrogates),后者是用32位代表一個字符。
還有另外一些UTF編碼,常見的有:
UTF-8:它對一些字符用1byte,一些字符用2byte,一些字符用3或4byte表示。這種編碼目前很流行。
UTF-32:它對每個字符都用4byte表示,這種表示法效率低,很少使用。

一. 數據類型
對于單字節與雙字節字符,它定義分別如下:
char c='a';
char szBuffer[100] = "A string";

wchar_t c=L'a';
wchar_t szBuffer[100] = L"A string";
實際上,wchar_t是unsigned short類型,另外Microsoft還定義了CHAR, PCHAR, TEXT等類型和宏,這些都是條件定義的,它根據是否使用Unicode而決定合適的版本。這些定義可以在WinNT.h文件找到。

二. Unicode和ANSI函數
從Windows NT開始,所有的核心API函數都使用Unicode版本,所以都要求Unicode字符串。如果你傳遞的是ANSI字符串,則它要進行轉換,它會消耗性能的。在之前的Windows版本,很多函數都提供兩個版本:XXXW和WWWA,如CreateWindowExW和CreateWindowExA。到Vista,后者只是起一個轉換層的作用。如果你需要建立DLL讓別人使用,也可以考慮
同樣,C-runtime也提供了Unicode版本的相應字符串函數,如strlen對應的wcslen(wc表示wide character)。但是盡管這樣,c-runtime函數對于字符串操作是非常不安全的,如下:
WCHAR? szBuffer[3] = L"";
wcscpy(szBuffer, L"abc");
上面代碼把四個字符拷貝到只有三個字符長的緩沖區中!這些代碼是緩沖區溢出的最大根源。對此,Microsoft提供了安全字符串函數,它在strsafe.h(在Windows SDK中,而不在VC的目錄中)中聲明(這個頭文件應該在最后包括,因為它使用了其它頭文件)
PTSTR _tcscpy(PTSTR strDes, PCTSTR strSrc); //
errno_t _tcscpy_s(PTSTR strDes, size_t numChars, PCTSTR strSrc);

除了這些函數外,C運行時還提供了對字符串操作有更多控制的函數。如:
HRESULT StringCchCat(PTSTR pszDest, size_t cchDest, PCTSTR pszSrc);
HRESULT StringCchCatEx(PTSTR pszDest, size_t cchDest, PCTSTR pszSrc,
?? PTSTR *ppszDestEnd, size_t *pcchRemaining, DWORD dwFlags);

HRESULT StringCchCopy(PTSTR pszDest, size_t cchDest, PCTSTR pszSrc);
HRESULT StringCchCopyEx(PTSTR pszDest, size_t cchDest, PCTSTR pszSrc,
?? PTSTR *ppszDestEnd, size_t *pcchRemaining, DWORD dwFlags);

HRESULT StringCchPrintf(PTSTR pszDest, size_t cchDest,
?? PCTSTR pszFormat, ...);
HRESULT StringCchPrintfEx(PTSTR pszDest, size_t cchDest,
?? PTSTR *ppszDestEnd, size_t *pcchRemaining, DWORD dwFlags,
?? PCTSTR pszFormat,...);
在這些參數中,Cch表示Count of Characters。另外還有一個以Cb作為函數名的字符串操作函數集,這里Cb指Count of byte,如StringCbCat(Ex), StringCbCopy(Ex)。
在這些函數中,如果緩沖區太小,它不會完成功能并返回STRSAFE_E_INSUFFICIENT_BUFFER。在擴展版本的函數中(Ex),額外的參數的意思如下:
size_t* pcchRemaining: 目標緩沖區中未用字符的數目('\0'不計入),例如把一個字符拷貝到10長度的緩沖區中,就得到9。
LPTSTR* ppszDestEnd: 如果它非空,指向目標緩沖區的'\0'字符。
DWORD dwFlags: 一些枚舉值組合。見SDK文檔。

三. Windows字符串函數
Windows也提供了許多字符串操作函數,一些函數如lstrcat, lstrcpy等已經過時了,因為它們沒有提供緩沖區溢出檢測。另外ShlwApi.h還定義了許多格式化操作的字符串函數,特別是數字值,如StrFormatKBSize和StrFormatByteSize等。見MSDN。
比較字符中的操作很常見,這個任務最好調用CompareString(Ex)和CompareStringOrdinal:
int CompareString(
?? LCID locale,
?? DWORD dwCmdFlags,
?? PCTSTR pString1,
?? int cch1,
?? PCTSTR pString2, int cch2);
它還區域信息作為比較依據,一般會取得正確的比較結果。這里LCID一般通過GetThreadLocale函數取得當前線程的區域ID。當然這個函數效率上會慢,對于比較程序性字符串,如參數,注冊表鍵,XML元素屬性等,可以使用CompareStringOrdinal,這不考慮區域信息。
要注意這兩個函數返回值與C run-time的相應函數不同,它是1(CSTR_LESS_THAN), 2(CSTR_EQUAL)和3(CSTR_GREATER_THAN),你可以減2獲得與c run-time相應的返回值。

四. 編程建議
1. 把字符串作為字符數組,而不是char數組或byte數組
2. 使用通用類型(TCHAR/PTSTR)表示字符和字符串
3. 對于字節,字節指針和數據緩沖區使用直接類型BYTE和PBYTE
4. 使用字符串和字符常量使用TEXT或_T宏
5. 進行全局替換,如用PTSTR替換PSTR
6. 修改字符串相關的數字運算問題,如用_countof(szBuffer)而不是sizeof(szBuffer)取得緩沖區的字符數。分配內存也用malloc(nch*sizeof(TCHAR))而不用malloc(nch),當然可以定義如下的宏:
#define chmalloc(nCharacters) (TCHAR*)malloc(nCharacters * sizeof(TCHAR))
7. 避免printf家族函數,特別是%s和%S類型的參數,具體見轉換部分
8. 要指定UNICODE符號
下面是字符串操作函數的選擇建議
1. 使用安全字符串版本(帶_s后綴或StringCch前綴的)。不使用任何沒有帶目標緩沖區大小的緩沖區操作函數。c run-time提供了memcpy_s, memmove_s等函數使用
2. 利用/GS和/RTCs編譯器選取項來自動檢測緩沖區溢出問題
3. 不使用Kernel32中的字符串操作函數,如lstrcat, lstrcpy

五. 在Unicode和ANSI間轉換
Windows函數MultiByteToWideChar提供了多字節字符(非Unicode的多字節字符)與Unicode字符的轉換。
int MultiByteToWideChar(
?? UINT uCodePage,
?? DWORD dwFlags,
?? PCSTR pMultiByteStr,
?? int cbMultiByte,
?? PWSTR pWideCharStr,
?? int cchWideChar);
int WideCharToMultiByte(
?? UINT uCodePage,
?? DWORD dwFlags,
?? PCWSTR pWideCharStr,
?? int cchWideChar,
?? PSTR pMultiByteStr,
?? int cbMultiByte,
?? PCSTR pDefaultChar,
?? PBOOL pfUsedDefaultChar);

函數的使用過程一般如下:
1. 參數pWideCharStr傳遞NULL,cchWideChar參數傳遞0,cbMultiByte傳遞-1,這樣調用就取轉換后的字符數
2. 根據1返回的字符數(cc)分配內存塊(cc*sizeof(wchar_t))
3. 再調用該函數,傳入相應參數進行字符串轉換
4. 釋放2中產生的內存塊

如果你需要編寫兩種類型的字符串都能操作的DLL函數,你也可以Microsoft一樣提供XXXW和XXXA版本的函數,其中后者的實現在經過上面兩個函數轉換后傳遞給前一個函數的實現。如果要決定某個文件的字符是否是Unicode字符,可用IsTextUnicode函數:
BOOL IsTextUnicode(CONST PVOID pvBuffer, int cb, PINT pResult);
它聲明于AdvApi32.dll中,但是這個函數是基于統計的,這樣可能會返回一個不正確的結果。

轉載于:https://www.cnblogs.com/Adon/archive/2009/10/11/Windows.html

總結

以上是生活随笔為你收集整理的字符与字符串操作——Windows via C/C++的全部內容,希望文章能夠幫你解決所遇到的問題。

如果覺得生活随笔網站內容還不錯,歡迎將生活随笔推薦給好友。