《Windows Via C/C++》邊學習,邊翻譯(五)操作字符和字符串-4

Secure String Functions in the C Run-Time Library

 

How to Get More Control When Performing String Operations

怎樣在執行字符串處理時得到更多控制

In addition to the new secure string functions, the C run-time library has some new functions that provide more control when performing string manipulations. For example, you can control the filler values or how truncation is performed. Naturally, the C run time offers both ANSI (A) versions of the functions as well as Unicode (W) versions of the functions. Here are the prototypes for some of these functions (and many more exist that are not shown here):

除了新的安全版本的字符串函數之外,C運行期庫中有一些新函數,在執行字符串操作時能提供更多控制。例如,可以控制填充符的值或是如何執行(字符串)截斷。C運行期既提供ANSI(A)版本又提供Unicode(W)版本的函數。這裏是其中一些函數原型(其它更多函數並未列出):

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,...);

 

You'll notice that all the methods shown have "Cch" in their name. This stands for Count of characters, and you'll typically use the _countof macro to get this value. There is also a set of functions that have "Cb" in their name, such as StringCbCat(Ex), StringCbCopy(Ex), and StringCbPrintf(Ex). These functions expect that the size argument is in count of bytes instead of count of characters. You'll typically use the sizeof operator to get this value.

你注意到所有方法名中都含有"Cch",它表示Count of characters,可以通過宏_countof得到其值。也有一組名稱中含有"Cb"的函數,比如StringCbCat(Ex)StringCbCopy(Ex)StringCbPrintf(Ex)。這些函數通過字節計數而非字符來預計引數長,通過使用sizeof來得到其值。

All these functions return an HRESULT with one of the values shown in Table 2-2.

所有這些函數都返回類型爲HRESULT,返回值爲表2-2中所列值之一。

Table 2-2: HRESULT Values for Safe String Functions

HRESULT Value Description
S_OK

 Success. The destination buffer contains the source string and is terminated by '/0'.

成功。目的buffer存放源字符串並以結束符'/0'結束。

STRSAFE_E_INVALID_PARAMETER

 Failure. The NULL value has been passed as a parameter.

失敗。將空指針NULL傳給了一個參數。

STRSAFE_E_INSUFFICIENT_BUFFER

 Failure. The given destination buffer was too small to contain the entire source string.

失敗。提供的目的buffer太小,無法存放整個源字符串。

 

Unlike the secure (_s suffixed) functions, when a buffer is too small, these functions do perform truncation. You can detect such a situation when STRSAFE_E_INSUFFICIENT_BUFFER is returned. As you can see in StrSafe.h, the value of this code is 0x8007007a and is treated as a failure by SUCCEEDED/FAILED macros. However, in that case, the part of the source buffer that could fit into the destination writable buffer has been copied and the last available character is set to '/0'. So, in the previous example, szBuffer would contain the string "012345678" if StringCchCopy is used instead of _tcscpy_s. Notice that the truncation feature might or might not be what you need, depending on what you are trying to achieve, and this is why it is treated as a failure (by default). For example, in the case of a path that you are building by concatenating different pieces of information, a truncated result is unusable. If you are building a message for user feedback, this could be acceptable. It's up to you to decide how to handle a truncated result.

不同於安全版本(帶_s後綴)函數,當buffer太小時,這些函數執行截斷。此情形下可以檢測到返回值STRSAFE_E_INSUFFICIENT_BUFFER。在StrSafe.h中可以看到,此錯誤碼值爲0x8007007a,它以SUCCEEDED/FAILED宏當作失敗的。但是,源buffer中(長度)合適的部分會複製到可寫的目的buffer中,而最後一個有效字符被置爲'/0'。所以在之前的例子中,如果用函數StringCchCopy代替_tcscpy_s的話,szBuffer將會是"012345678"。注意(字符串)截斷可能是、也可能不是你所需要的,這取決於你要達到什麼目的,這也是它被當作是失敗(默認情況下)的原因。例如,當拼接不同信息段組成一個路徑時,截斷結果是不可用的;當建立一個用於用戶反饋的信息時,截斷操作是容許的。如何把握截斷結果取決於你。

Last but not least, you'll notice that an extended (Ex) version exists for many of the functions shown earlier. These extended versions take three additional parameters, which are described in Table 2-3.

最後但並非最不重要的,你會注意到許多前面出現的函數都存在一個擴展(Ex)版本。這些擴展版本有三個附加參數,如表2-3描述。

Table 2-3: Extended Version Parameters

Parameters and Values Description
size_t* pcchRemaining

 Pointer to a variable that indicates the number of unused characters in the destination buffer. The copied terminating '/0' character is not counted. For example, if one character is copied into a buffer that is 10 characters wide, 9 is returned even though you won't be able to use more than 8 characters without truncation. If pcchRemaining is NULL, the count is not returned.

指向一個變量,該變量指示出目的buffer中未使用字符的個數。複製的結束符'/0'不計。例如,如果向一個10字符長的buffer中複製一個字符,將返回9,儘管在無截斷的情況下不能使用多於8個字符。如果pcchRemainingNULL,計數不返回。

LPTSTR* ppszDestEnd

 If ppszDestEnd is non-NULL, it points to the terminating '/0' character at the end of the string contained by the destination buffer.

如果ppszDestEnd非空,則指向目的buffer中字符串尾的結束符'/0'。

DWORD dwFlags

 One or more of the following values separated by '|'.

一個或多個以下的值,由'|'分隔。

STRSAFE_FILL_BEHIND_NULL

 If the function succeeds, the low byte of dwFlags is used to fill the rest of the destination buffer, just after the terminating '/0' character. (See the comment about STRSAFE_FILL_BYTE just after this table for more details.)

如果函數成功,dwFlags的低字節填入目的buffer中結束符'/0'之後的剩餘部分。(參看此表之後關於STRSAFE_FILL_BYTE的註釋,以獲得更多信息。)

STRSAFE_IGNORE_NULLS

 Treats NULL string pointers like empty strings (TEXT("")).

NULL字符串指針看作空字符串(TEXT(""))。

STRSAFE_FILL_ON_FAILURE

 If the function fails, the low byte of dwFlags is used to fill the entire destination buffer except the first '/0' character used to set an empty string result. (See the comment about STRSAFE_FILL_BYTE just after this table for more details.) In the case of a STRSAFE_E_INSUFFICIENT_BUFFER failure, any character in the string being returned is replaced by the filler byte value.

如果函數失敗,除了首個填入'/0'的字符以確保結果是空字符串之外,用dwFlags的低字節填入整個目的buffer中。(參看此表之後關於STRSAFE_FILL_BYTE的註釋,以獲得更多信息。)當發生STRSAFE_E_INSUFFICIENT_BUFFER失敗的情況,任何所返回字符串中的字符都被填充符替代。

STRSAFE_NULL_ON_FAILURE

 If the function fails, the first character of the destination buffer is set to '/0' to define an empty string (TEXT("")). In the case of a STRSAFE_E_INSUFFICIENT_BUFFER failure, any truncated string is overwritten.

如果函數失敗,目的buffer中的首個字符被置爲'/0'以定義一個孔字符串(TEXT(""))。當發生STRSAFE_E_INSUFFICIENT_BUFFER失敗的情況,任何階段字符串都被改寫。

STRSAFE_NO_TRUNCATION

 As in the case of STRSAFE_NULL_ON_FAILURE, if the function fails, the destination buffer is set to an empty string (TEXT("")). In the case of a STRSAFE_E_INSUFFICIENT_BUFFER failure, any truncated string is overwritten.

STRSAFE_NULL_ON_FAILURE的情況,如果函數失敗,目的buffer被置爲空字符串(TEXT(""))。在STRSAFE_E_INSUFFICIENT_BUFFER的情況下,任何階段字符串都被改寫。

 

  Note  Even if STRSAFE_NO_TRUNCATION is used as a flag, the characters of the source string are still copied, up to the last available character of the destination buffer. Then both the first and the last characters of the destination buffer are set to '/0'. This is not really important except if, for security purposes, you don't want to keep garbage data.

 注意  即使使用STRSAFE_NO_TRUNCATION做標記,原字符串的字符仍會被複制,這取決於目的buffer的最後有效字符。然後目的buffer的首個和最後一個字符被置爲'/0'。如果不是出於安全的目的、你不想保有垃圾數據的話,這樣做並非重要。

There is a last detail to mention that is related to the remark that you read at the bottom of page 21. In Figure 2-4, the 0xfd value is used to replace all the characters after the '/0', up to the end of the destination buffer. With the Ex version of these functions, you can choose whether you want this expensive filling operation (especially if the destination buffer is large) to occur and with which byte value. If you add STRSAFE_FILL_BEHIND_NULL to dwFlag, the remaining characters are set to '/0'. When you replace STRSAFE_FILL_BEHIND_NULL with the STRSAFE_FILL_BYTE macro, the given byte value is used to fill up the remaining values of the destination buffer.

還有最後一個細節需要注意,在圖2-4中,值0xfd替代了目的buffer中'/0'之後的所有字符。這些函數的Ex版本,可以選擇是否要執行這種高昂的填充操作(尤其是目的buffer很大時)以及填充什麼值。如果給dwFlag加上STRSAFE_FILL_BEHIND_NULL值,剩餘字符會被置爲'/0'。如果用宏STRSAFE_FILL_BYTE代替STRSAFE_FILL_BEHIND_NULL,給定的字符會被填入目的buffer的剩餘字節中。

Windows String Functions Windows的字符串函數

Windows also offers various functions for manipulating strings. Many of these functions, such as lstrcat and lstrcpy, are now deprecated because they do not detect buffer overrun problems. Also, the ShlwApi.h file defines a number of handy string functions that format operating system—related numeric values, such as StrFormatKBSize and StrFormatByteSize. See http://msdn2.microsoft.com/en-us/library/ms538658.aspx for a description of shell string handling functions.

Windows同樣提供了各種操作字符串的函數。其中有許多函數,例如lstrcatlstrcpy,由於不檢測緩衝區溢出問題,已經不贊成再使用了。並且,ShlwApi.h文件中定義了許多易於使用的字符串函數,它們對與操作系統相關的字符串進行格式化,例如StrFormatKBSizeStrFormatByteSize。參考http://msdn2.microsoft.com/en-us/library/ms538658.aspx獲得shell字符串處理函數的細節。

It is common to want to compare strings for equality or for sorting. The best functions to use for this are CompareString(Ex) and CompareStringOrdinal. You use CompareString(Ex) to compare strings that will be presented to the user in a linguistically correct manner. Here is the prototype of the CompareString function:

比較字符串是否相等或對其排序是常見的(操作),對這種情況最好的函數是CompareString(Ex)CompareStringOrdinal。使用CompareString(Ex)來比較字符串會在言語角度以修正方式呈現給用戶。以下是函數CompareString的原型:

int CompareString(

   LCID locale,

   DWORD dwCmdFlags,

   PCTSTR pString1,

   int cch1,

   PCTSTR pString2, int cch2);

This function compares two strings. The first parameter to CompareString specifies a locale ID (LCID), a 32-bit value that identifies a particular language. CompareString uses this LCID to compare the two strings by checking the meaning of the characters as they apply to a particular language. A linguistically correct comparison produces results much more meaningful to an end user. However, this type of comparison is slower than doing an ordinal comparison. You can get the locale ID of the calling thread by calling the Windows GetThreadLocale function:

此函數用來比較兩字符串。第一個參數指定一個本地ID(LCID),它是32位的,確定一種特定語言。CompareString檢查LCID所應用的特定語言的字符含義,來進行字符串比較。語言修正比較對最終用戶產生更多的含義。但是這種比較方式比順序比較慢。通過Windows的GetThreadLocale函數可以得到調用線程的本地ID:

LCID GetThreadLocale();

The second parameter of CompareString identifies flags that modify the method used by the function to compare the two strings. Table 2-4 shows the possible flags.

CompareString的第二個參數標記出函數比較兩字符串所使用的方法。圖2-4列出可能的標記:

Table 2-4: Flags Used by the CompareString Function

Flag Meaning
NORM_IGNORECASE LINGUISTIC_IGNORECASE Ignore case difference.  忽略大小寫。
NORM_IGNOREKANATYPE Do not differentiate between hiragana and katakana characters.不區分平假名和片假名。
NORM_IGNORENONSPACE LINGUISTIC_IGNOREDIACRITIC Ignore nonspacing characters.
NORM_IGNORESYMBOLS Ignore symbols.  忽略符號。
NORM_IGNOREWIDTH Do not differentiate between a single-byte character and the same character as a double-byte character.  不區分相同字符的單字節和雙字節字符。
SORT_STRINGSORT Treat punctuation the same as symbols.  將標點按符號處理。

The remaining four parameters of CompareString specify the two strings and their respective lengths in characters (not in bytes). If you pass negative values for the cch1 parameter, the function assumes that the pString1 string is zero-terminated and calculates the length of the string. This also is true for the cch2 parameter with respect to the pString2 string. If you need more advanced linguistic options, you should take a look at the CompareStringEx functions.

函數CompareString剩餘的四個參數指定兩個字符串及它們各自的字符長度(並非字節長度)。如果給參數cch1傳了負值,函數會假定字符串pStirng1是零字符結尾,並計算字符串長度。同樣,字符串pString2和參數cch2也是如此。如果需要更多的語言選項,應該查看函數CompareStringEx

To compare strings that are used for programmatic strings (such as pathnames, registry keys/ values, XML elements/attributes, and so on), use CompareStringOrdinal:

比較提綱性的字符串時(比如路徑名、註冊表鍵/值、XML元素/屬性、等等),應使用CompareStringOrdinal

int CompareStringOrdinal(

  PCWSTR pString1,

  int cchCount1,

  PCWSTR pString2,

  int cchCount2,

  BOOL bIgnoreCase);

This function performs a code-point comparison without regard to the locale, and therefore it is fast. And because programmatic strings are not typically shown to an end user, this function makes the most sense. Notice that only Unicode strings are expected by this function.

此函數不考慮場所直接進行碼點比較,因此速度很快。並且由於提綱性字符串通常不顯示給終端用戶,所以此函數就很有意義。注意此函數只接受Unicode字符串。

The CompareString and CompareStringOrdinal functions' return values are unlike the return values you get back from the C run-time library's *cmp string comparison functions. CompareString(Ordinal) returns 0 to indicate failure, CSTR_LESS_THAN (defined as 1) to indicate that pString1 is less than pString2, CSTR_EQUAL (defined as 2) to indicate that pString1 is equal to pString2, and CSTR_GREATER_THAN (defined as 3) to indicate that pString1 is greater than pString2. To make things slightly more convenient, if the functions succeed, you can subtract 2 from the return value to make the result consistent with the result of the C run-time library functions (-1, 0, and +1).

函數CompareStringCompareStringOrdinal的返回值,不像C運行期庫的*cmp字符串比較函數所返回的值。CompareString(Ordinal)返回0指示失敗,CSTR_LESS_THAN(定義爲1)指示pString1小於pString2CSTR_EQUAL(定義爲2)指示pString1pString2相等,CSTR_GREATER_THAN(定義爲3)指示pString1大於pString2。爲了稍微方便些,如果函數成功,可以用返回值減去2,來使結果與C運行期庫函數的返回值一致(-1,0和+1)。

發佈了22 篇原創文章 · 獲贊 0 · 訪問量 8萬+
發表評論
所有評論
還沒有人評論,想成為第一個評論的人麼? 請在上方評論欄輸入並且點擊發布.
相關文章