Changes a wide-character string such that the changed string can be passed to the wcscmp function and produce the same result as passing the unchanged string to the wcscoll function.
#include <wchar.h> size_t wcsxfrm (wchar_t *ws1, const wchar_t *ws2, size_t maxchar);
If the value of maxchar is less than the required size to store the transformed string (including the terminating null), the contents of the array pointed to by ws1 is indeterminate. In such a case, the function returns the size of the transformed string.
If maxchar is zero, then, ws1 is allowed to be a NULL pointer, and the function returns the required size of the ws1 array before making the transformation.
The wide-character string comparison functions, wcscoll and wcscmp, can produce different results given the same two wide-character strings to compare. This is because wcscmp does a straightforward comparison of the code point values of the characters in the strings, whereas wcscoll uses the locale information to do the comparison. Depending on the locale, the wcscoll comparison can be a multi-pass operation, which is slower than wcscmp.
The wcsxfrm function transforms wide character strings in such a way that if you pass two transformed strings to the wcscmp function, the result is the same as passing the two original strings to the wcscoll function. The wcsxfrm function is useful in applications that need to do a large number of comparisons on the same wide- character strings using wcscoll. In this case, it may be more efficient (depending on the locale) to transform the strings once using wcsxfrm and then use the wcscmp function to do comparisons.
x | Length of the resulting string pointed to by ws1, not including the terminating null character. |
(size_t) -1 | Indicates an error occurred. The function sets errno to EINVAL - The string pointed to by ws2 contains characters outside the domain of the collating sequence. |
#include <wchar.h> #include <stdio.h> #include <stdlib.h> #include <locale.h> /* This test verifies that two transformed strings, when passed */ /* through wcsxfrm and then compared, provide the same result as */ /* if passed through wcscoll without any transformation. */ #define BUFF_SIZE 20 main() { wchar_t w_string1[BUFF_SIZE]; wchar_t w_string2[BUFF_SIZE]; wchar_t w_string3[BUFF_SIZE]; wchar_t w_string4[BUFF_SIZE]; int errno; int coll_result; int wcscmp_result; size_t wcsxfrm_result1; size_t wcsxfrm_result2; /* setlocale to French locale */ if(setlocale(LC_ALL,"fr_FR.ISO8859-1") == NULL) { perror("setlocale"); exit(EXIT_FAILURE); } /* Convert each of the strings into wide-character format. */ if (mbstowcs(w_string1, "àbcd", BUFF_SIZE) == -1) { perror("mbstowcs"); exit(EXIT_FAILURE); } if (mbstowcs(w_string2, "abcz", BUFF_SIZE) == -1) { perror("mbstowcs"); exit(EXIT_FAILURE); } /* Collate string 1 and string 2 and store the result. */ errno = 0; coll_result = wcscoll(w_string1, w_string2); if (errno) { perror("wcscoll"); exit(EXIT_FAILURE); } else { /* Transform the strings (using wcsxfrm) into w_string3 */ /* and w_string4. */ wcsxfrm_result1 = wcsxfrm(w_string3,w_string1,BUFF_SIZE); if (wcsxfrm_result1 == ((size_t)-1)) perror("wcsxfrm"); else if (wcsxfrm_result1 > BUFF_SIZE) { perror("\n** String is too long **\n"); exit(EXIT_FAILURE); } else { wcsxfrm_result2 = wcsxfrm(w_string4,w_string2,BUFF_SIZE); if (wcsxfrm_result2 == ((size_t)-1)) { perror("wcsxfrm"); exit(EXIT_FAILURE); } else if (wcsxfrm_result2 > BUFF_SIZE) { perror("\n** String is too long **\n"); exit(EXIT_FAILURE); } /* Compare the two transformed strings and verify that */ /* the result is the same as the result from wcscoll on */ /* the original strings. */ else { wcscmp_result = wcscmp(w_string3,w_string4); if (wcscmp_result == 0 && (coll_result == 0)) { printf("\nReturn value from wcscoll() and return value \ from wcscmp() are both zero."); printf("\nTest successful\n\n"); } else if ((wcscmp_result < 0) && (coll_result < 0)) { printf("\nReturn value from wcscoll() and return value \ from wcscmp() are less than zero."); printf("\nTest successful\n\n"); } else if ((wcscmp_result > 0) && (coll_result > 0)) { printf("\nReturn value from wcscoll() and return value \ from wcscmp() are greater than zero."); printf("\nTest successful\n\n"); } else { printf("** Error **\n"); printf("\nReturn values are not of the same type"); } } } } }
Running the example program produces the following result:
Return value from wcscoll() and return value from wcscmp() are less than zero. Test successful