本篇介绍stdlib.h头文件安全函数学习之bsearch_s,mbstowcs_s,qsort_s,wcstombs_s。
实验环境 window11 VS2022
bsearch_s / bsearch example
#include <string.h>
#include <stdio.h>
#include <stdlib.h>
#include <errno.h>
#include <locale.h>
#include <wchar.h>
#include <limits.h>
#pragma warning(disable:4996)
struct data {
int nr;
char const* value;
} dat[] = {
{1, "Foo"}, {2, "Bar"}, {3, "Hello"}, {4, "World"}
};
int data_cmp(void const* lhs, void const* rhs)
{
struct data const* const l = lhs;
struct data const* const r = rhs;
if (l->nr < r->nr) return -1;
else if (l->nr > r->nr) return 1;
else return 0;
// return (l->nr > r->nr) - (l->nr < r->nr); // 可行的简洁写法
// return l->nr - r->nr; // 错误的简洁写法(若给出 INT_MIN 就会失败)
}
int str_com(char** str1, char** str2)
{
int ret = strcmp(str1, str2);
return ret;
}
int str_com2(void **str, char** str1, char** str2)
{
int ret = strcmp(str1, str2);
if (ret == 0)
{
//*(char*)str = "equal";
strcpy(str, "equal");
}
else {
//*(char*)str = "not equal";
strcpy(str, "not equal");
}
return ret;
}
int main(void)
{
//void* __cdecl bsearch(
// _In_ void const* _Key,
// _In_reads_bytes_(_NumOfElements * _SizeOfElements) void const* _Base,
// _In_ size_t _NumOfElements,
// _In_ size_t _SizeOfElements,
// _In_ _CoreCrtNonSecureSearchSortCompareFunction _CompareFunction
//);
struct data key = { .nr = 3 };
struct data const* res = bsearch(&key, dat, sizeof dat / sizeof dat[0], sizeof dat[0], data_cmp);
if (res) {
printf("No %d: %s\n", res->nr, res->value);
}
else {
printf("No %d not found\n", key.nr);
}
char* arr[] = { "dog", "pig", "horse", "cat", "human", "rat", "cow", "goat" };
char* key2 = "cat";
char** result;
result = (char **)bsearch(&key2, arr, sizeof arr / sizeof arr[0], sizeof arr[0], str_com);
if (result) {
printf("result: %s\n", *result);
}
else {
printf("result not found\n");
}
//void* __cdecl bsearch_s(
// _In_ void const* _Key,
// _In_reads_bytes_(_NumOfElements * _SizeOfElements) void const* _Base,
// _In_ rsize_t _NumOfElements,
// _In_ rsize_t _SizeOfElements,
// _In_ _CoreCrtSecureSearchSortCompareFunction _CompareFunction,
// _In_opt_ void* _Context
//);
char** result2;
char context2[20] = {'\0'};
result2 = (char**)bsearch_s(&key2, arr, sizeof arr / sizeof arr[0], sizeof arr[0], str_com2, &context2);
if (result2) {
printf("result2: %s\n", *result2);
}
else {
printf("result2 not found\n");
}
printf("context2: %s\n", context2);
char* key3 = "tiger";
char** result3;
char context3[20] = { '\0' };
result3 = (char**)bsearch_s(&key3, arr, sizeof arr / sizeof arr[0], sizeof arr[0], str_com2, &context3);
if (result3) {
printf("result3: %s\n", *result3);
}
else {
printf("result3 not found\n");
}
printf("context3: %s\n", context3);
return 0;
}
运行结果:
参考:
https://zh.cppreference.com/w/c/algorithm/bsearch
https://learn.microsoft.com/zh-cn/cpp/c-runtime-library/reference/bsearch-s?view=msvc-170
mbstowcs / mbstowcs_s example
#include <string.h>
#include <stdio.h>
#include <stdlib.h>
#include <errno.h>
#include <locale.h>
#include <wchar.h>
#include <limits.h>
#pragma warning(disable:4996)
int main(void)
{
setlocale(LC_ALL, "en_US.utf8");
const char* mbstr = u8"z\u00df\u6c34\U0001F34C"; // or u8"zß水🍌"
wchar_t wstr[5] = {'\0'};
//__DEFINE_CPP_OVERLOAD_STANDARD_NFUNC_0_2_SIZE(
// _ACRTIMP, mbstowcs,
// _Out_writes_opt_z_(_MaxCount), wchar_t, _Dest,
// _In_z_ char const*, _Source,
// _In_ size_t, _MaxCount
//)
mbstowcs(wstr, mbstr, 5);
wprintf(L"MB string: %s\n", mbstr);
wprintf(L"Wide string: %ls\n", wstr);
wchar_t wstr2[32] = { '\0' };
const char* mbstr2 = u8"z\u00df\u6c34\U0001F34C"; // or u8"zß水🍌"
//errno_t mbstowcs_s(
// size_t * pReturnValue, //指向转换后的字符串的长度加上结束符(单位wchar_t)
// wchar_t* wcstr, //用于转换所生成的宽字符串的缓冲区地址。
// size_t sizeInWords, //缓冲区大小(以字数为单位)。
// const char* mbstr, //Null 终止的多字节字符序列的地址。
// size_t count //要存储在 wcstr 缓冲区中的宽字符的最大数量,不包括终止 null 或 _TRUNCATE。
//);
size_t pValue = 0;
int ret = mbstowcs_s(&pValue, wstr2, 6, mbstr2, 5);
wprintf(L"Wide2 string: %ls\n", wstr2);
printf("ret = %d\tpValue = %lld\n", ret, pValue);
return 0;
}
运行结果:
参考:
https://learn.microsoft.com/zh-cn/cpp/c-runtime-library/reference/mbstowcs-s-mbstowcs-s-l?view=msvc-170
https://zh.cppreference.com/w/c/string/multibyte/mbstowcs
https://vimsky.com/examples/detail/cpp-ex-----mbstowcs_s-function.html
https://baike.baidu.com/item/mbstowcs_s/18886282?fr=ge_ala
qsort / qsort_s example
#include <string.h>
#include <stdio.h>
#include <stdlib.h>
#include <errno.h>
#include <locale.h>
#include <wchar.h>
#include <limits.h>
#pragma warning(disable:4996)
int compare_ints(const void* a, const void* b)
{
int arg1 = *(const int*)a;
int arg2 = *(const int*)b;
if (arg1 < arg2) return -1;
if (arg1 > arg2) return 1;
return 0;
// return (arg1 > arg2) - (arg1 < arg2); // 可行的简写
// return arg1 - arg2; // 错误的简写:整数溢出时为未定义行为,比如此处使用 INT_MIN 时
}
int compare_ints2(void** str, const void* a, const void* b)
{
int arg1 = *(const int*)a;
int arg2 = *(const int*)b;
if (arg1 < arg2)
{
strcpy(str, "less than");
return -1;
}
if (arg1 > arg2)
{
strcpy(str, "greater than");
return 1;
}
strcpy(str, "equal");
return 0;
// return (arg1 > arg2) - (arg1 < arg2); // 可行的简写
// return arg1 - arg2; // 错误的简写:整数溢出时为未定义行为,比如此处使用 INT_MIN 时
}
int main(void)
{
int ints[] = { -2, 99, 0, -743, 2, INT_MIN, 4 };
int size = sizeof ints / sizeof * ints;
//void __cdecl qsort(
// _Inout_updates_bytes_(_NumOfElements * _SizeOfElements) void* _Base,
// _In_ size_t _NumOfElements,
// _In_ size_t _SizeOfElements,
// _In_ _CoreCrtNonSecureSearchSortCompareFunction _CompareFunction
//);
qsort(ints, size, sizeof(int), compare_ints);
for (int i = 0; i < size; i++)
printf("%d ", ints[i]);
printf("\n");
char context2[20] = { '\0' };
int ints2[] = { 5, 18, 0, -659, 3, INT_MIN, 4 };
int size2 = sizeof ints2 / sizeof * ints2;
//void __cdecl qsort_s(
// _Inout_updates_bytes_(_NumOfElements * _SizeOfElements) void* _Base,
// _In_ rsize_t _NumOfElements,
// _In_ rsize_t _SizeOfElements,
// _In_ _CoreCrtSecureSearchSortCompareFunction _CompareFunction,
// _In_opt_ void* _Context
//);
qsort_s(ints2, size2, sizeof(int), compare_ints2, context2);
for (int i = 0; i < size2; i++)
printf("%d ", ints2[i]);
printf("\n");
printf("context2======%s\n", context2);
return 0;
}
运行结果:
参考:
https://zh.cppreference.com/w/c/algorithm/qsort
https://learn.microsoft.com/zh-cn/cpp/c-runtime-library/reference/bsearch-s?view=msvc-170
https://learn.microsoft.com/zh-cn/cpp/c-runtime-library/reference/qsort-s?view=msvc-170
wcstombs_s /wcstombs example
#include <string.h>
#include <stdio.h>
#include <stdlib.h>
#include <errno.h>
#include <locale.h>
#include <wchar.h>
#include <limits.h>
#pragma warning(disable:4996)
#define BUFFER_SIZE 100
int main(void)
{
// 4 个宽字符
const wchar_t src[] = L"z\u00df\u6c34\U0001f34c";
// 它们于 UTF-8 占用 10 个字节
char dst[11];
setlocale(LC_ALL, "en_US.utf8");
printf("wide-character string: %s\n", src);
wprintf(L"wide-character string: %ls\n", src);
for (size_t ndx = 0; ndx < sizeof src / sizeof src[0]; ++ndx)
printf("src[%2zu] = %#8x\n", ndx, src[ndx]);
//__DEFINE_CPP_OVERLOAD_STANDARD_NFUNC_0_2_SIZE(
// _ACRTIMP, wcstombs,
// _Out_writes_opt_(_MaxCount), char, _Dest,
// _In_z_ wchar_t const*, _Source,
// _In_ size_t, _MaxCount
//)
int rtn_val = wcstombs(dst, src, sizeof dst);
printf("rtn_val = %d\n", rtn_val);
if (rtn_val > 0)
printf("multibyte string: '%s'\n", dst);
for (size_t ndx = 0; ndx < sizeof dst; ++ndx)
printf(" dst[%2zu] = %#2x\n", ndx, (unsigned char)dst[ndx]);
size_t i;
char* pMBBuffer = (char*)malloc(BUFFER_SIZE);
wchar_t* pWCBuffer = L"Hello, world.";
printf("Convert wide-character string:\n");
//errno_t __cdecl wcstombs_s(
// _Out_opt_ size_t * _PtNumOfCharConverted,
// _Out_writes_bytes_to_opt_(_DstSizeInBytes, *_PtNumOfCharConverted) char* _Dst,
// _In_ size_t _DstSizeInBytes,
// _In_z_ wchar_t const* _Src,
// _In_ size_t _MaxCountInBytes
//);
int ret = wcstombs_s(&i, pMBBuffer, (size_t)BUFFER_SIZE, pWCBuffer, (size_t)BUFFER_SIZE); //ret = 0正常, 非0表示失败
// Output
printf("Characters converted: %lld ret = %d\n", i, ret);
printf("Multibyte character: %s\n\n", pMBBuffer);
// Free multibyte character buffer
if (pMBBuffer)
{
free(pMBBuffer);
}
return 0;
}
运行结果:
参考:
https://learn.microsoft.com/zh-cn/cpp/c-runtime-library/reference/wcstombs-s-wcstombs-s-l?view=msvc-170
https://zh.cppreference.com/w/c/string/multibyte/wcstombs