一、字符串操作
备注:关于字符串操作
_s结尾的是:具备检测缓冲区溢出检测功能,缓冲区溢出时debug版本程序会报错,release直接崩溃
带n的:具备缓冲区溢出时,自动截断功能。
1 _tcsncpy 拷贝n个字符串
2 _tcscpy_s 拷贝字符串
3 _tcscmp 字符串比较
4 _tcsicmp 忽略大小写字符串比较
5 _tcsncmp 字符串比较前n个字符
6 _tcslen 获取字符串长度
7 _tcscat_s 字符串拼接
8 _tcschr 查找字符串中某个字符第一次出现的位置
9 _tcsrchr 查找字符串中某个字符最后一次出现的位置
10 _tcsstr 字符串1在字符串2中首次出现的位置,未出现返回NULL值;
11 _tcsrstr 字符串1在字符串2中最后出现的位置,未出现返回NULL值;
12 _tcstok_s 按标记将字符串拆分
13 _stprintf_s 格式化字符串
_stprintf_s这个函数不推荐用,可以用_sntprintf_s
14 _stscanf_s 分割格式化字符串
15 _sntprintf_s 强烈推荐格式化字符串(以后字符串格式化只使用这个函数),防止缓冲区溢出的最好的函数。
1 2 3 | 使用方法:
TCHAR szLog[MAX_PATH] = {0};
_sntprintf_s(szLog, MAX_PATH, MAX_PATH - 1, _T("GetClassName=%s\n"), szBuff);
|
16 _tcslwr 字符串转小写
1 2 3 | 使用方法:
wstring wstrSql = L"zHONGguoREN";
wstrSql = _wcslwr((WCHAR*)wstrSql.c_str());
|
17 _tcslwr_s 字符串转小写安全版本
1 2 | TCHAR name[] = L"SalAnlei";
_tcslwr_s(name, _tcslen(name) + 1);
|
18 _tcsupr 字符串转大写
19 _tcsupr_s 字符串转大写安全版本
20 string.find() 查找子串
21 int k=str1.find_first_of(str2); k返回的值是"str2字符中任何一个字符"首次在str1中出现的位置,和find有本质区别
22 int k=str1.find_last_of(str2); k返回的值是"str2字符中任何一个字符"首次在str1尾部中出现的位置,和find有本质区别
23 strncpy
注意:strncpy不会自动追加'\0',如果使用strncpy一定要手动追加'\0'
1 2 3 | 正确用法:
strncpy(dst, src, dst_size-1);
dst[dst_size-1] = '\0'; /* Always do this to be safe! */
|
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 | int main()
{
//1、dest中没有被初始化为0,部分拷贝,strncpy不会自动追加\0
char dest[20] = {0};
char src[] = "123456";
memset(dest, 'a', sizeof(dest));//设置dest内容为'a'
strncpy(dest, src, 2);//部分拷贝,strncpy不会自动追加\0。
dest[2] = '\0';//这句非常重要!!!!,否则字符串没有结束标志
//2、src2字符串的长度大于sizeof(dest2),strncpy不会自动追加\0
char dest2[20] = { 0 };
char src2[] = "01234567890123456789123456";
memset(dest2, 'b', sizeof(dest2));
strncpy(dest2, src2, sizeof(dest2));
dest2[sizeof(dest2) - 1] = '\0';//这句非常重要!!!!否则字符串没有结束标志
//3、推荐的写法
char dest3[20];
char src3[] = "123456789";
memset(dest3, 0, sizeof(dest3));//先把dest3初始化为0
strncpy(dest3, src, sizeof(dest3) - 1);
}
|
24 strncpy_s
1 2 3 4 5 6 7 8 9 | int main()
{
char src[] = "1234567890";
char dst[5];
errno_t err = strncpy_s(dst, _countof(dst), src, _TRUNCATE);
if ( err == STRUNCATE )
printf( "truncation occurred!\n" );
printf( "'%s'\n", dst );
}
|
25 int snprintf(charstr, size_t size,constcharformat, ...);
备注:这个函数是安全的,推荐使用,而snprintf是不安全的,千万不要用(前面仅仅比snprintf多个,
snprintf与_snprintf的区别是_snprintf不会末尾置0就不说了)
函数说明:
(1) 如果格式化后的字符串长度 < size,则将此字符串全部复制到str中,并给其后添加一个字符串结束符('\0');
(2) 如果格式化后的字符串长度 >= size,则只将其中的(size-1)个字符复制到str中,并给其后添加一个字符串结束符('\0'),返回值为欲写入的字符串长度。
函数返回值:
若成功则返回欲写入的字符串长度,若出错则返回负值。返回值并不是真正写入字符串的大小。
1 2 3 4 5 6 7 8 9 10 11 12 13 14 | int main()
{
char buf[10] = "";
char src[30] = "hello world! hello world!";
int len = snprintf(buf, sizeof(buf), "%s", src);
printf("return len=%d\n", len);
if(len>sizeof(buf)-1)
{
printf("[Error] Source string length is %d. The buf size %d is not enough. Copy incomplete!\n", len, sizeof(buf));
}else{
printf("buf=%s, bufLen=%d\n", buf, strlen(buf));
}
return 0;
}
|
26 sprintf格式
%d 十进制有符号整数
%u 十进制无符号整数
%f 浮点数
%s 字符串
%c 单个字符
%p 指针的值
%e 指数形式的浮点数
%x, %X 无符号以十六进制表示的整数
%o 无符号以八进制表示的整数
%g 把输出的值按照 %e 或者 %f 类型中输出长度较小的方式输出
%p 输出地址符
%lu 32位无符号整数
%llu 64位无符号整数
%2f是把float的所有位数输出2位,包括小数点,如果不组2位,补0,如果超过2位,按照实际输出
%.2f是float后的小数只输出两位。
%d=int
%ld= long
%lld=long long
27 、sscanf函数是不安全的函数,格式和参数不符,容易造成缓冲区溢出
备注:X代表16进制、04代表不足补0
格式%04X :需要类型“unsigned int ”的参数
格式%hX :需要类型“unsigned short ”的参数
格式%02hhX :需要类型“unsigned char *”的参数
28、 STL string模仿CString的Format函数
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 | template<typename ... Args>
string string_format(const string& format, Args ... args)
{
size_t size = 1 + snprintf(nullptr, 0, format.c_str(), args ...); // Extra space for \0
unique_ptr<char[]> buf(new char[size]);
//char bytes[size];
snprintf(buf.get(), size, format.c_str(), args ...);
return string(buf.get());
}
int main() {
//test the function here
cout << string_format("name=%s, id=%d", "sanganlei", 202412);
//<test>
return 0;
}
|
29、 STL string模仿CString的Format函数
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 | // CMakeProject1.cpp: 定义应用程序的入口点。
//
using namespace std;
//
template<typename ... Args>
string string_format2(const string& format, Args ... args)
{
if (format.empty()) {
return FT("");
}
size_t nLen = 1 + snprintf(NULL, 0, format.c_str(), args ...); // Extra space for \0
char* strBuffer = new(std::nothrow) char[nLen];
if (!strBuffer) {
return "";
}
snprintf(strBuffer, nLen, format.c_str(), args ...);
string strRlst = strBuffer;
delete[] strBuffer;
strBuffer = NULL;
return strRlst;
}
template<typename ... Args>
wstring string_format2(const wchar_t* format, Args ... args)
{
if (!format) {
return L"";
}
va_list vlArgs = NULL;
va_start(vlArgs, format);
size_t nLen = _vscwprintf(format, vlArgs) + 1;
wchar_t* strBuffer = new wchar_t[nLen];
_vsnwprintf_s(strBuffer, nLen, nLen, format, vlArgs);
va_end(vlArgs);
wstring strRlst = strBuffer;
delete[] strBuffer;
strBuffer = NULL;
return strRlst;
}
|
30、 windows版本outputdebugStringEx
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 | void OutputDebugStringEx(const wchar_t *strOutputString, ...)
{
va_list vlArgs = NULL;
va_start(vlArgs, strOutputString);
size_t nLen = _vscwprintf(strOutputString, vlArgs) + 1;
wchar_t *strBuffer = new wchar_t[nLen];
_vsnwprintf_s(strBuffer, nLen, nLen, strOutputString, vlArgs);
va_end(vlArgs);
OutputDebugStringW(strBuffer);
delete[] strBuffer;
}
void OutputDebugStringEx(const char *strOutputString, ...)
{
va_list vlArgs = NULL;
va_start(vlArgs, strOutputString);
size_t nLen = _vscprintf(strOutputString, vlArgs) + 1;
char *strBuffer = new char[nLen];
_vsnprintf_s(strBuffer, nLen, nLen, strOutputString, vlArgs);
va_end(vlArgs);
OutputDebugStringA(strBuffer);
delete[] strBuffer;
}
|
二、内存操作
1、memcpy_s 内存拷贝
2、new和delete、new[]和delete[]要配对使用,否则会造成堆破坏和内存泄漏
三、文件操作
1、fstream、ifstream和ofstream构造函数打开文件
构造函数的主要功能是打开文件,内部调用了fopen函数,和单独调用fopen效果一样。

2、fstream构造函数打开文件方式

a) fstream的std::ios::app打开文件
在每次写操作之前,流指针会定位到文件末尾,只能在文件末尾追加内容。
无论您为写入指针设置什么位置, ios::app您都将始终在最后写入。
打开文件时,若文件不存在,会创建新文件。
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 | int main()
{
//1、在每次写文件时,在文件末尾追加内容(打开文件后tellg和tellp定位到文件末尾,但每次写入时,定位到文件结尾)
//ios::app打开时,若文件不存在,则会创建文件
long lread, lwrite;
long lread2, lwrite2;
fstream fs("1.txt", std::ios::in | std::ios::out | std::ios::app);
if (fs) {
cout << "file exist" << endl;
lread = fs.tellg();//获取读指针
lwrite = fs.tellp();//获取写指针
fs.write("sanganlei", sizeof("sanganlei"));
lread2 = fs.tellg();
lwrite2 = fs.tellp();
fs.seekp(SEEK_SET);
lread2 = fs.tellg();
lwrite2 = fs.tellp();
fs.write("hello", sizeof("hello"));
fs.close();
}
else {
cout << "file not exist" << endl;
}
}
|
b)fstream的std::ios::trunc打开文件
打开文件时,删除文件原有内容。
打开文件时,若文件不存在,会创建新文件。
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 | int main()
{
//2、打开文件后删除原有内容((打开文件后tellg和tellp定位到开头))
//ios::trunc打开时,若文件不存在,则会创建文件
long lread, lwrite;
long lread2, lwrite2;
fstream fs("1.txt", std::ios::in | std::ios::out | std::ios::trunc);
if (fs) {
cout << "file exist" << endl;
lread = fs.tellg();
lwrite = fs.tellp();
fs.write("sanganlei", sizeof("sanganlei"));
lread2 = fs.tellg();
lwrite2 = fs.tellp();
fs.close();
}
else {
cout << "file not exist" << endl;
}
}
|
c)fstream的std::ios::ate打开文件
每次打开文件后,读写指针定位到文件末尾。
打开文件时,若文件不存在,不会创建新文件。
ios::ate好处是可以在文件中自由搜索
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 | int main()
{
//3、每次打开文件后,读写指针定位到文件末尾(打开文件后tellg和tellp定位到文件末尾)
//ios::ate打开时,若文件不存在,不会创建文件
long lread, lwrite;
long lread2, lwrite2;
fstream fs("1.txt", std::ios::in | std::ios::out | std::ios::ate);
if (fs) {
cout << "file exist" << endl;
lread = fs.tellg();
lwrite = fs.tellp();
fs.write("sanganlei", sizeof("sanganlei"));
lread2 = fs.tellg();
lwrite2 = fs.tellp();
fs.close();
}
else {
cout << "file not exist" << endl;
}
}
|
d)文件存在就读取内容,不存在就创建文件ifstream和ofstream联合
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 | int main() {
string fcstrConfigPath;
fcstrConfigPath = ("D:\\111config.json");
std::ifstream fIn(fcstrConfigPath.c_str()); //fin用来判断文件是否存在和读取文件内容
if (!fIn.good()) {//文件不存在
std::ofstream fOut(fcstrConfigPath.c_str(), std::ios::out | std::ios::binary);//创建文件并打开
if (!fOut.is_open()) {//判断文件是否打开
return -1;
}
std::string strTempJson = "Hello";
fOut.write(strTempJson.c_str(), strTempJson.length());//写入内容
fOut.close();
}
else {//存在,读取文件内容
std::string strJson((std::istreambuf_iterator<char>(fIn)), std::istreambuf_iterator<char>());//读取文件内容
fIn.close();//关闭文件
}
return 0;
}
|
3 std::ios::rdstate含义

4 _tfopen 打开文件
r 打开(OPEN)只读文件,该文件必须存在。
r+ 打开(OPEN)可读写的文件,该文件必须存在。
w 打开(OPEN)只写文件,若文件存在则文件长度清为0,即该文件内容会消失。若文件不存在则新建该文件。
w+ 打开(OPEN)可读写文件,若文件存在则文件长度清为零,即该文件内容会消失。若文件不存在则新建该文件。
a 以附加的方式打开(OPEN)只写文件。若文件不存在,则会新建该文件,假如文件存在,输入的数据会被加到文件尾,即文件原先的内容会被保留。
a+ 以附加方式打开(OPEN)可读写的文件。若文件不存在,则会新建该文件,假如文件存在,输入的数据会被加到文件尾后,即文件原先的内容会被保留。
上述的形态字符串都可再加1个b字符,如rb、w+b或ab+等组合,加入b 字符用来告知函数库打开(OPEN)的文件为二进制文件,而非纯文字文件
5 _fclose 关闭文件
6 _size_t fread(void buffer, size_t size, size_t count, FILE stream) 读文件
返回实际读取的单元个数。如果小于count,则可能文件结束或读取出错;可以用ferror()检测是否读取出错,
用feof()函数检测是否到达文件结尾。如果size或count为0,则返回0。
7 _size_t fwrite(void buffer, size_t size, size_t count, FILE stream); 写文件
返回成功写入的单元个数。如果小于count,则说明发生了错误,文件流错误标志位将被设置,随后可以通过ferror()函数判断。
如果 size 或 count 的值为 0,则返回值为 0
8 _ftprintf 文件格式化写
9 _ftscanf 文件格式化读
10 _fgetc 文件中读取一个字符
11 _fputc 将一指定字符写入文件流中
12 _fgets 由文件中读取一字符串,直到出现换行字符、读到文件尾或是已读了size-1个字符为止,最后会加上NULL作为字符串结束
13 _fputs 将一指定的字符串写入文件内,若成功则返回写出的字符个数,返回EOF则表示有错误发生
14 _fflush 缓冲区到文件
15 _fseek(pf,offset,origin) pf:文件指针,offset:以字节为单位的位移量,origin:是起始点,用来指定位移量是以哪个位置为基准的.
16 _feof 判断文件结束函数
17 _ftell 当前位置指针相对于文件开头的字节数
18 _rewind 重设文件流的读写位置为文件开头
19 _ferror 测试给定流 stream 的错误标识符。如果设置了与流关联的错误标识符,该函数返回一个非零值,否则返回一个零值。
20 _void clearerr(FILE *stream) 清除给定流 stream 的文件结束和错误标识符。
21 _PathFindFileName 根据文件路径获取文件名
Path before calling "PathFindFileName ": C:\www.txt
Path after calling "PathFindFileName ": www.txt
22 _PathRemoveFileSpec 根据文件路径获取文件所在目录
Path before calling "PathRemoveFileSpec": C:\TEST\sample.txt
Path after calling "PathRemoveFileSpec": C:\TEST
23 _PathRemoveArgs 移除路径中的参数
Path before calling "PathRemoveArgs": c:\a\b\FileA Arg1 Arg2
Path before calling "PathRemoveArgs": c:\a\b\FileA
24 _PathRemoveBackslash 路径尾部去掉反斜杠
Path before calling "PathRemoveBackslash": c:\a\b\File\
Path after calling "PathRemoveBackslash": c:\a\b\File
25 _PathAddBackslash 路径尾部增加反斜杠
Path before calling "PathAddBackslash": c:\a\b\File
Path after calling "PathAddBackslash": c:\a\b\File\
26 _PathRemoveBlanks删除路径中的空格
Path before calling "PathRemoveBlanks": c:\TEST\File1\File2
Path after calling "PathRemoveBlanks": c:\TEST\File1\File2
27 _PathAddExtension增加扩展名
Path before calling "PathAddExtension": file
Path after calling "PathAddExtension": file.txt
28 _PathRemoveExtension去掉扩展名
Path before calling "PathRemoveExtension": C:\TEST\sample.txt
Path after calling "PathRemoveExtension": C:\TEST\sample
29 _PathRenameExtension重命名扩展名
Path before calling "PathRenameExtension": C:\TEST\sample.txt
Path after calling "PathRenameExtension": C:\TEST\sample.doc
30 _PathUnquoteSpaces 去掉路径的引号
Path before calling "PathUnquoteSpaces": "C:\path1\path2"
Path after calling "PathUnquoteSpaces": C:\path1\path2
31 _PathQuoteSpaces 路径加引号
Path before calling "PathQuoteSpaces ": C:\sample_one\sample two
Path after calling "PathQuoteSpaces ": "C:\sample_one\sample two"
32 _PathStripPath 去掉路径,只留下文件名
Path before calling "PathStripPath ": c:\dir1\file.txt
Path after calling "PathStripPath ": file.txt
33 _PathCompactPath 路径压缩
The un-truncated path is C:\path1\path2\sample.txt
The truncated path at 125 pixels is : C:\pa...\sample.txt
34 _PathCompactPathEx 路径压缩
Path before calling "PathCompactPathEx ": C:\path1\path2\sample.txt
Path after calling "PathCompactPathEx ": ...\sa...
35 _PathFindExtension 查找路径中的扩展名
Path before calling "PathFindExtension ": C:\www.txt
Path after calling "PathFindExtension ": .txt
36 _PathFindNextComponent 返回第一个反斜杠后面的内容
Search a path for the next path component after the root c:\a\b\File
Return the next path component: "a\b\File"
37 _PathMakePretty 转换为小写
The content of the unconverted path is : C:\TEST\FILE
The content of the converted path is : C:\test\file
[培训]传播安全知识、拓宽行业人脉——看雪讲师团队等你加入!
最后于 2022-11-22 20:59
被sanganlei编辑
,原因: