失眠网,内容丰富有趣,生活中的好帮手!
失眠网 > C++ 常用生僻函数小记

C++ 常用生僻函数小记

时间:2020-03-29 10:29:24

相关推荐

C++ 常用生僻函数小记

string类find函数find_first_ofsubstr函数 动态载入DLL相关函数LoadLibrary函数GetProcAddress函数FreeLibrary函数 getopt函数判断文件的访问权限localtime函数SetConsoleCtrlHandler控制台处理函数inline函数CreateDirectory创建文件目录整形字符转换strtoul函数_ultoa函数 进程或线程相关函数SetPriorityClass获取当前进程或线程句柄或IDCreateToolhelp32Snapshot进程快照获取进程中的线程或线程枚举OpenThread打开线程SetThreadAffinityMask 指定线程的运行CPU 时间函数获取系统内存信息WSAStartup和WSACleanupInterlockedIncrement16和InterLockedDecrement

string类

find函数

四种函数原型:

(1)size_t find (const string& str, size_t pos = 0) const; //查找对象--string类对象(2)size_t find (const char* s, size_t pos = 0) const; //查找对象--字符串(3)size_t find (const char* s, size_t pos, size_t n) const; //查找对象--字符串的前n个字符(4)size_t find (char c, size_t pos = 0) const; //查找对象--字符

-rfind() 与之类似,只是从反向查找-返回值 :

找到返回 第一个字符的索引没找到返回 string::npos

#include <string> #include <iostream> using namespace std; int main() { string strFirst ( "abced" ),strSecond("abc abc abd def"); cout<<strFirst.find("a")<<endl;//输出结果为0,说明a当前的索引位置为0 //函数原型:size_type find_first_not_of( Char ch, size_type index = 0 ) const; //返回在字符串中首次不匹配 d 的首字符索引,从2开始。 cout<<strFirst.find_first_not_of ( "d" ,2)<<endl; //输出结果为 2cout<<strSecond.length()<<endl;//输出结果为15 cout<<strSecond.find_first_not_of("abc",4)<<endl; //输出结果为7 system("pause"); }

find_first_of

[函数原型]

size_type find_first_of( const basic_string &str, size_type pos= 0 ); size_type find_first_of( const char *str, size_type pos= 0 ); size_type find_first_of( const char *str, size_type pos, size_type num ); size_type find_first_of( char ch, size_type pos= 0 );

[说明]

查找在字符串中第一个与str中的某个字符匹配的字符,返回它的位置。搜索从index开始,如果没找到就返回string::npos ;

查找在字符串中第一个与str中的某个字符匹配的字符,返回它的位置。搜索从index开始,最多搜索num个字符。如果没找到就返回string::npos;

查找在字符串中第一个与ch匹配的字符,返回它的位置。搜索从index开始;

substr函数

原型:

string.substr(size_t startpos, size_tlength);

其中 startpos 是起始字符的序号,length 是[从 startpos 开始]取的字符串长度(包括startpos )。

如果要取得 str 中序号 m 到 n 之间(不包括n)的子字符串需要用str.substr(m, n-m);

示例代码:

#include<string>#include<iostream>using namespace std;main(){string s("12345asdf");string a=s.substr(0,4); //获得字符串s中 从第0位开始的长度为4的字符串cout<<a<<endl;}

输出结果:

1234

动态载入DLL相关函数

DLL是Dynamic Link Library的缩写,意为动态链接库。在Windows中,许多应用程序并不是一个完整的可执行文件,它们被分割成一些相对独立的动态链接库,即DLL文件,放置于系统中。当我们执行某一个程序时,相应的DLL文件就会被调用。

动态载入方式是指在编译之前并不知道将会调用哪些 DLL 函数, 完全是在运行过程中根据需要决定应调用哪些函数。

方法是:用 LoadLibrary 函数加载动态链接库到内存,用 GetProcAddress函数动态获得 DLL 函数的入口地址。当一个 DLL 文件用 LoadLibrary 显式加载后,在任何时刻均可以通过调用 FreeLibrary 函数显式地从内存中把它给卸载。

动态调用使用的 Windows API 函数主要有 3 个, 分别是 LoadLibrary、 GetProcAddress 和FreeLibrary。

实例代码:

#include <stdio.h> #include <stdlib.h> #include <windows.h> //假如CreateDll.dll这个dll中有一个函数Add(int a, int b); //定义一个函数指针 typedef int (*func_Add)(int a, int b); int main(int argc, char *argv[]) { int sum = 0; HMODULE h = NULL; func_Add func_Add_from_dll = NULL; //注意dll的路径,视自己的情况而定 h = LoadLibrary("..\\CreateDll\\CreateDll.dll"); if(NULL == h) { printf("LoadLibrary failed!\n"); return 0; } func_Add_from_dll = (func_Add)GetProcAddress(h, "Add"); if(NULL == func_Add_from_dll) { printf("GetProcAddress failed!\n"); return 0; } sum = (*func_Add_from_dll)(1, 2);printf("%d\n", sum); getchar(); return 0; }

LoadLibrary函数

原型:

HMODULE LoadLibrary(char * LibFileName)

[功能]:加载由参数 LibFileName 指定的 DLL 文件。

[返回值]:返回装载 DLL 库模块的实例句柄。

[说明]:参数 LibFileName 指定了要装载的 DLL 文件名,如果 LibFileName 没有包含一个路径,系统将按照:当前目录、Windows 目录、Windows 系统目录、包含当前任务可执行文件的目录、列在 PATH 环境变量中的目录等顺序查找文件。

如果函数操作成功,将返回装载 DLL 库模块的实例句柄,否则,将返回一个错误代码

注意:假如在应用程序中用 LoadLibrary 函数装入某一个 DLL 前, 其他应用程序已把该 DLL 装入内存中了,则系统将不再装入该 DLL 的另一个实例,而是使该 DLL 的“引用计数”加 1 。

GetProcAddress函数

原型:

func_pointer GetProcAddress(HMODULE h,char * func_name)

[功能]:返回参数 h指定的模块中(由LoadLibrary函数返回的指向DLL模块的参数),由参数 func_name指定的过程或函数的入口地址。

[说明]:参数 h包含被调用函数的 DLL 句柄,这个值由 LoadLibrary 返回, func_name是指向含有函数名的以 nil 结尾的字符串指针,或者可以是函数的次序值,但大多数情况下,用函数名是一种更稳妥的选择。

如果该函数执行成功,则返回 DLL 中由参数 func_name指定的过程或函数的入口地址,否则返回 nil 。

FreeLibrary函数

原型:

FreeLibrary(HMODULE h)

[说明]:将由参数 h指定的 DLL 文件从内存中卸载 1 次。h为 DLL 库的句柄。这个值由 LoadLibrary 返回。由于 DLL 在内存中只装载一次,因此调用 FreeLibrary 首先使 DLL 的引用计数减 1,如果计数减为 0 则卸载该 DLL。

注意:每调用一次 LoadLibrary 函数就应调用一次 FreeLibrary 函数,以保证不会有多余的库模块在应用程序结束后仍留在内存中,否则导致内存泄漏。

getopt函数

示例代码:

#include <stdio.h> #include <unistd.h> int main(int argc,char *argv[]) { int ch; opterr=0; while((ch=getopt(argc,argv,"a:b::cde"))!=-1) { printf("optind:%d\n",optind); printf("optarg:%s\n",optarg); printf("ch:%c\n",ch); switch(ch) { case 'a': printf("option a:'%s'\n",optarg); break; case 'b': printf("option b:'%s'\n",optarg); break; case 'c': printf("option c\n"); break; case 'd': printf("option d\n"); break; case 'e': printf("option e\n"); break; default: printf("other option:%c\n",ch); } printf("optopt+%c\n",optopt); } }

在终端执行以下启动命令:

./a.out -a1234 -b432 -c -d

输出如下:

optind:2 optarg:1234 ch:a option a:'1234' optopt+ optind:3 optarg:432 ch:b option b:'432' optopt+ optind:4 optarg:(null) ch:c option c optopt+ optind:5 optarg:(null) ch:d option d optopt+

main(int argc,char *argv[])中的argc是一个整型,argv是一个指针数组,argc记录argv的大小。上面的例子中。

argc=5;argv[0]=./a.outargv[1]=-a1234argv[2]=-b432argv[3]=-cargv[4]=-d

getopt函数原型:

getopt(int argc,char *const argv[],const char *optstring)

optstring是一段自己规定的选项串,例如本例中的”a:b::cde”,表示可以有,-a,-b,-c,-d,-e这几个参数“:”表示该选项必须带有额外的参数,全域变量optarg会指向此额外参数,“::”标识该额外的参数可选(有些Uinx可能不支持“::”)全域变量optind指示下一个要读取的参数在argv中的位置如果getopt()找不到符合的参数则会印出错信息,并将全域变量optopt设为“?”字符如果不希望getopt()印出错信息,则只要将全域变量opterr设为0即可

判断文件的访问权限

头文件:

int _access( const char *path, int mode ); int _waccess( const wchar_t *path, int mode );

参数:

path 文件或目录路径

ode 访问权限设定

返回值:

如果文件具有指定的访问权限,则函数返回 0

如果文件不存在或者不能访问指定的权限,则返回-1

当path为文件时,_access函数判断文件是否存在,并判断文件是否可以用mode值指定的模式进行访问

当path为目录时,_access只判断指定的目录是否存在

mode的值和含义:

00 检查文件是否存在

02 写权限

04 读权限

06 读写权限

localtime()函数

链接:/shellching/article/details/8114266

SetConsoleCtrlHandler控制台处理函数

链接:/blog/661431

inline函数

在函数声明或定义中函数返回类型前加上关键字inline即把min()指定为内联。

inline int min(int first, int secend) {/****/};

inline 函数对编译器而言必须是可见的,以便它能够在调用点内展开该函数。与非inline函数不同的是,inline函数必须在调用该函数的每个文本文件中定义。当然,对于同一程序的不同文件,如果inline函数出现的话,其定义必须相同。对于由两个文件compute.C和draw.C构成的程序来说,程序员不能定义这样的min()函数,它在compute.C中指一件事情,而在draw.C中指另外一件事情。如果两个定义不相同,程序将会有未定义的行为:

为保证不会发生这样的事情,建议把inline函数的定义放到头文件中。在每个调用该inline函数的文件中包含该头文件。这种方法保证对每个inline函数只有一个定义,且程序员无需复制代码,并且不可能在程序的生命期中引起无意的不匹配的事情

inline 说明这个函数是内联的,在编译过程中内联函数会直接被源代码替换,提高执行效率 如果类中的某个函数会被调用很多次或者放在循环中,那么建议将这个函数声明为内联,可以提高程序的运行效率

CreateDirectory创建文件目录

链接:/s/blog_618a89940101nl41.html

整形字符转换

strtoul函数

将字符串转换成无符号长整型数,类似的函数还有atof,atoi,atol,strtod,strtol

原型:

unsigned long strtoul(const char *nptr,char **endptr,int base);

[说明]strtoul()会将参数nptr字符串根据参数base来转换成无符号的长整型数。参数base范围从2至36,或0。参数base代表采用的进制方式,如base值为10则采用10进制,若base值为16则采用16进制数等。当base值为0时会根据情况选择用哪种进制:如果第一个字符是’0’,就判断第二字符如果是‘x’则用16进制,否则用8进制;第一个字符不是‘0’,则用10进制。一开始strtoul()会扫描参数nptr字符串,跳过前面的空格字符串,直到遇上数字或正负符号才开始做转换,再遇到非数字或字符串结束时(”)结束转换,并将结果返回。若参数endptr不为NULL,则会将遇到不合条件而终止的nptr中的字符指针由endptr返回。[返回值]返回转换后的长整型数,否则返回ERANGE并将错误代码存入errno中

_ultoa函数

转换一个无符号长整型数为字符串

原型:

char *ultoa(unsigned long value, char *string, int radix);

示例:

#include#includeint main( void ){unsigned long lnumber = 3123456789L;char string[25];ultoa(lnumber,string,10);printf("string = %s unsigned long = %lu\n",string,lnumber);return 0;}

将lnumber转换成字符型,然后添加到字符数组string中

进程或线程相关函数

SetPriorityClass

设置进程的优先级

函数原型:

BOOL WINAPI SetPriorityClass(_In_ HANDLE hProcess,_In_ DWORD dwPriorityClass);

【参数】

hProcess

进程句柄,可以通过GetCurrentProcess等函数获取dwPriorityClass

优先级级别,如:ABOVE_NORMAL_PRIORITY_CLASS(在普通优先级之上)

获取当前进程或线程句柄或ID

函数如下:

{返回当前线程的虚拟句柄}

GetCurrentThread: THandle;{返回当前线程 ID}

GetCurrentThreadId: DWORD;{返回当前进程的虚拟句柄}

GetCurrentProcess: THandle;{返回当前进程 ID}

GetCurrentProcessId: DWORD;

详见链接:(/del/archive//03/10/1098311.html)

CreateToolhelp32Snapshot进程快照

获取进程信息为指定的进程、进程使用的堆[HEAP]、模块[MODULE]、线程建立一个快照。

原型:

HANDLE WINAPI CreateToolhelp32Snapshot(DWORD dwFlags, //用来指定“快照”中需要返回的对象,可以是TH32CS_SNAPPROCESS等DWORD th32ProcessID //一个进程ID号,用来指定要获取哪一个进程的快照,当取系统进程列表或获取当前进程快照时可以设为0);

【参数】

1、dwFlags

指定快照中包含的系统内容,这个参数能够使用下列数值(常量)中的一个或多个:

TH32CS_INHERIT - 声明快照句柄是可继承的;TH32CS_SNAPALL - 在快照中包含系统中所有的进程和线程;TH32CS_SNAPHEAPLIST - 在快照中包含在th32ProcessID中指定的进程的所有的堆;TH32CS_SNAPMODULE - 在快照中包含在th32ProcessID中指定的进程的所有的模块;TH32CS_SNAPPROCESS - 在快照中包含系统中所有的进程;TH32CS_SNAPTHREAD -在快照中包含系统中所有的线程;

2、th32ProcessID

指定将要快照的进程ID。如果该参数为0表示快照当前进程。该参数只有在设置了TH32CS_SNAPHEAPLIST或者TH32CS_SNAPMODULE后才有效,在其他情况下该参数被忽略,所有的进程都会被快照;

返回值】

调用成功,返回快照的句柄,调用失败,返回INVALID_HANDLE_VALUE

获取进程中的线程或线程枚举

进程为线程提供生存的空间,线程为进程的存在提供了时间,没有线程的存在进程没有存在的意义,一个进程中可以同时具有多个线程,但必须有一个线程,进程生成时创建的第一个线程被称之为主线程,它可以创建子线程,子线程还可以创建孙线程。

通过函数CreateToolhelp32Snapshot创建进程快照;

通过函数Thread32First获取第一个线程信息;

通过函数Thread32Next获取下一个线程信息;

原型:

BOOL WINAPI Thread32First(HANDLE hSnapshot, LPTHREADENTRY32 lpt2)BOOL WINAPI Thread32Next(HANDLE hSnapshot, LPTHREADENTRY32 lpte);

OpenThread打开线程

用于打开一个现有线程对象。

原型:

HANDLE WINAPI OpenThread(_In_ DWORD dwDesiredAccess,_In_ BOOL bInheritHandle,_In_ DWORD dwThreadId );

【参数】

dwDesiredAccess 线程对象的访问。此访问权限检查线程的安全描述符。这个参数可以是一个或多个线程访问权限;bInheritHandle 如果这个值是true的,这个进程将继承该句柄的进程。否则,进程不继承此句柄;dwThreadId 要打开的线程的标识符;

SetThreadAffinityMask 指定线程的运行CPU

该函数实现为各个线程设置亲缘性屏蔽,即为线程指定运行的CPU

原型:

DWORD_PTR SetThreadAffinityMask ( HANDLEhThread, // handle to thread DWORD_PTR dwThreadAffinityMask // thread affinity mask );

【参数】

hThread 用于指明要限制的线程标识;dwThreadAffinityMask 用于指明线程能够在哪个CPU上运行,必须是进程的亲缘性屏蔽的相应子集,例如,可能有一个包含4个线程的进程,它们在拥有4个CPU的计算机上运行。如果这些线程中的一个线程正在执行非常重要的操作,而你想增加某个CPU始终可供它使用的可能性,为此你对其他3个线程进行了限制,使它们不能在CPU 0上运行,而只能在CPU 1、2和3上运行。因此,若要将3个线程限制到CPU 1、2和3上去运行,可以这样操作:

//线程0只能在cpu 0上运行 SetThreadAffinityMask(hThread0,0x00000001); //线程1,2,3只能在cpu 1,2,3上运行 SetThreadAffinityMask(hThread1,0x0000000E); SetThreadAffinityMask(hThread2,0x0000000E); SetThreadAffinityMask(hThread3,0x0000000E);

【返回值】

线程的前一个亲缘性屏蔽

时间函数

1 得到当前UTC时间

void GetSystemTime(LPSYSTEMTIME lpSystemTime);

2 得到当地时间

void GetLocalTime(LPSYSTEMTIME lpSystemTime);

3 SYSTEMTIME转成FILETIME

BOOL SystemTimeToFileTime(const SYSTEMTIME* lpSystemTime,LPFILETIME lpFileTime);

4 FILETIME转成SYSTEMTIME

BOOL FileTimeToSystemTime(const FILETIME* lpFileTime,LPSYSTEMTIME lpSystemTime);

5 当地时间转成UTC时间

BOOL LocalFileTimeToFileTime(const FILETIME* lpLocalFileTime,LPFILETIME lpFileTime);

6 UTC时间转成当地时间

BOOL FileTimeToLocalFileTime(const FILETIME* lpFileTime,LPFILETIME lpLocalFileTime);

7 获取系统运行时间

CopyBOOL WINAPI GetSystemTimes(__out_opt LPFILETIME lpIdleTime, //空闲时间__out_opt LPFILETIME lpKernelTime, //内核时间__out_opt LPFILETIME lpUserTime //用户时间);

【CUP利用率计算方法】

总时间=内核时间+用户时间;

cpu利用率=(总时间-空闲时间)/总时间

获取系统内存信息

函数GlobalMemoryStatusEx和GlobalMemoryStatus。

当系统内存大于4G时,只能使用函数GlobalMemoryStatusEx获取内存信息。

函数原型:

BOOL WINAPI GlobalMemoryStatusEx(LPMEMORYSTATUS lpBuffer)

参数:是一个指向MEMORYSTATUSEX结构体的指针

MEMORYSTATUSEX结构如下:

typedef struct _MEMORYSTATUSEX {DWORDdwLength; //本结构长度DWORDdwMemoryLoad; //已用内存百分比DWORDLONG ullTotalPhys; //物理内存总量DWORDLONG ullAvailPhys; //可用物理内存DWORDLONG ullTotalPageFile; //页交换文件最多能放的字节数DWORDLONG ullAvailPageFile; //页交换文件中尚未分配给进程的字节数DWORDLONG ullTotalVirtual; //用户区总的虚拟地址空间DWORDLONG ullAvailVirtual; //用户区当前可用的虚拟地址空间DWORDLONG ullAvailExtendedVirtual; //保留值,设为0} MEMORYSTATUSEX, *LPMEMORYSTATUSEX;

ullAvailVirtual这个值是这个结构中唯一一个与该进程有关的成员,所有的其他成员

都适用于整个系统,为了计算这个值GlobalMemoryStatus会把调用进程的地址空间中所有的闲置区域都加起来。

WSAStartup和WSACleanup

通常这两个函数要搭配使用。

WSAStartup的功能是初始化Windows socket DLL,WSACleanup是来解除与Socket库的绑定并且释放Socket库所占用的系统资源。

函数原型:

int PASCAL FAR WSAStartup( WORD wVersionRequested, LPWSADATA lpWSAData );

【参数】

wVersionRequested 欲使用的 Windows Sockets API 版本,高位字节指出副版本(修正)号,低位字节指明主版本号;lpWSAData 指向WSADATA数据结构的指针,用来接收Windows Sockets实现的细节;

【返回值】

成功——0

失败——-WSASYSNOTREADY / WSAVERNOTSUPPORTED / WSAEINVAL

InterlockedIncrement16和InterLockedDecrement

属于互锁函数,用在同一进程内,需要对共享的一个变量做加法或减法的时候,

防止其他线程访问这个变量,是实现线程同步的一种办法

InterlockedIncrement函数可以实现对变量的同步操作,当多个线程或进程操作同一个变量时,此函数可以保证对操作的变量同步,对变量进行加法操作。

如:

变量 Long value =0;

正常情况下的加减操作:value+=1;

1:系统从Value的空间取出值,并动态生成一个空间来存储取出来的值;

2:将取出来的值和1作加法,并且将和放回Value的空间覆盖掉原值。加法结束。

如果此时有两个Thread ,分别记作threadA,threadB;

1:threadA将Value从存储空间取出,为0;

2:threadB将Value从存储空间取出,为0;

3:threadA将取出来的值和1作加法,并且将和放回Value的空间覆盖掉原值。加法结束,Value=1。

4:threadB将取出来的值和1作加法,并且将和放回Value的空间覆盖掉原值。加法结束,Value=1。

最后Value =1 ,而正确应该是2;这就是问题的在,InterLockedIncrement 能够保证在一个线程访问变量时其它线程不能访问。

用于增减变量的并不是常用的Inc/Dec过程,而是用了InterlockedIncrement/InterlockedDecrement这一对过程,它们实现的功能完全一样,都是对变量加一或减一。但它们有一个最大的区别,那就是InterlockedIncrement/InterlockedDecrement是线程安全的。即它们在多线程下能保证执行结果正确,而Inc/Dec不能

如果觉得《C++ 常用生僻函数小记》对你有帮助,请点赞、收藏,并留下你的观点哦!

本内容不代表本网观点和政治立场,如有侵犯你的权益请联系我们处理。
网友评论
网友评论仅供其表达个人看法,并不表明网站立场。