C语言常用函数总结

一 进程相关函数

1 exit、_exit和return

  exit(0):正常运行程序并退出程序;exit(1):非正常运行导致退出程序;return:返回函数。
  return是语言级别的,它表示了调用堆栈的返回;而exit是系统调用级别的,它表示了一个进程的结束。
  在stdlib.h中exit函数是这样子定义的:void exit(int status)。这个系统调用是用来终止一个进程的,无论在程序中的什么位置,只要执行exit,进程就会从终止进程的运行。讲到exit这个系统调用,就要提及另外一个系统调用,_exit,_exit()函数位于unistd.h中,相比于exit(),_exit()函数的功能最为简单,直接终止进程的运行,释放其所使用的内存空间,并销毁在内存中的数据结构,而exit()在于在进程退出之前要检查文件的状态,将文件缓冲区中的内容写回文件。
  非主函数中调用return和exit效果很明显,但是在main函数中调用return和exit的现象就很模糊,多数情况下现象都是一致的。

2 assert()宏用法

  assert是宏,而不是函数。在C的assert.h头文件中。原型定义:

#define assert(expr)\
((expr)\
?__ASSERT_VOID_CAST(0)\
:__assert_fail(__STRING(expr),__FILE__,__LINE__,__ASSERT_FUNCTION))
/*DefinedInGlibc2.15*/

  assert的作用是现计算表达式 expression ,如果其值为假(即为0),那么它先向stderr打印一条出错信息,然后通过调用 abort来终止程序运行。windows平台上assert宏只在release模式下有效。Linux上则没有这个限制,无论Debug还是release模式assert都生效,但是如果你想让assert失效,编译的时候加上-DNDEBUG即可。

#define NDEBUG
#include <cstdio>
#include <cstdlib>
#include <iostream>
#include <cassert>
using namespace std;

int main(int argc, char *argv[])
{
	bool is = false;
	assert(is);
	printf("hell");
	return 0;
}
//输出:hell

  这个宏通常原来判断程序中是否出现了明显非法的数据,如果出现了终止程序以免导致严重后果,同时也便于查找错误。

3 sockpair

4 access

  access函数检查调用进程是否可以对指定的文件执行某种操作。原型:

int access(const char * pathname, int mode)

  pathname:需要检测的文件路径名;mode:需要的操作模式,取值如下:

F_OK 值为0,判断文件是否存在
X_OK 值为1,判断对文件是可执行权限
W_OK 值为2,判断对文件是否有写权限
R_OK 值为4,判断对文件是否有读权限
注:后三种可以使用或“|”的方式,一起使用,如W_OK|R_OK

成功执行时,返回0。失败返回-1,errno被设为以下的某个值
EINVAL: 模式值无效
EACCES: 文件或路径名中包含的目录不可访问
ELOOP : 解释路径名过程中存在太多的符号连接
ENAMETOOLONG:路径名太长
ENOENT:路径名中的目录不存在或是无效的符号连接
ENOTDIR: 路径名中当作目录的组件并非目录
EROFS: 文件系统只读
EFAULT: 路径名指向可访问的空间外
EIO:输入输出错误
ENOMEM: 不能获取足够的内核内存
ETXTBSY:对程序写入出错

5 sleep函数

  在linux编程中,有时候会用到定时功能,常见的是用sleep(time)函数来睡眠time秒;但是这个函数是可以被中断的,也就是说当进程在睡眠的过程中,如果被中断,那么当中断结束回来再执行该进程的时候,该进程会从sleep函数的下一条语句执行;这样的话就不会睡眠time秒了。

#include <unistd.h>
unsigned int sleep (unsigned int seconds);//n秒
int usleep (useconds_t usec);//n微秒

  sleep(time)返回值是睡眠剩下的时间。
  以下情况不会中断。

do{
    time = sleep(time);
    }while(time > 0);

二 输出输入

1 C/C++输入输出函数

1. 缓冲区回车符
  在C++中如果采用cin进行输入,则在缓存区留下回车字符,可以使用cin.get()或者是gets()读出。
2. cin类型不符
  istream类重载了抽取运算符<< ,>>, 所以cin >> 支持c++内置的所有基本数据类型。cin对象将标准输入表示为字节流,然后根据抽取运算符<<(本质就是一个函数)的参数类型对字节流进行类型转换,转换为所需的类型。如果输入的前面一部分字符为空白(空格、换行符、和制表符),他们会跳过,直到遇到非空白字符。当输入没有满足程序期望的时候,比如对于一个int类型的变量a,却输入字符H,这种情况下,抽取运算发将不会改变变量a的值,并返回0,经常被放在循环条件中来终止循环。
3. cin.get()
  cin.get()每次读取一整行并把由Enter键生成的换行符留在输入缓冲区中。
4. cin.getline()
  cin.getline()每次读取一整行,并把由Enter键生成的换行符抛弃,回车符并不留在缓冲区。
5. getline()
  getline()每次读取到特定字符,并把特定字符抛弃,特定字符并不留在缓冲区。
  getline()的原型是istream& getline ( istream &is , string &str , char delim );位于头文件<string>中。
  其中 istream &is 表示一个输入流,譬如cin;string&str表示把从输入流读入的字符串存放在这个字符串中(可以自己随便命名,str什么的都可以);char delim表示遇到这个字符停止读入,在不设置的情况下系统默认该字符为’\n’,也就是回车换行符(遇到回车停止读入,且回车符会被丢弃)。

string line;
cout << "please cin a line:";
getline(cin, line, '#');
cout << "The line you give is:" << line <<endl;

参考
  C++中cin的详细用法:https://blog.csdn.net/k346k346/article/details/48213811
6. gets和fgets
  gets函数会报错,所以需要使用fgetsfgets读入的字符里面会包含’\n’,需要注意。
7. sprintf_s和sprintf
  sprintf_ssprintf的区别在于,sprintf只会将数据写入缓冲区,而sprintf_s首先会检查缓冲区大小,然后写入数据,并且将数据后一位置为0,而其他位置为-3,所以在第二个参数缓冲区大小的时候,需要大于写入的数据一个字节。
  sprintf函数是一个变参函数,前两个函数有固定类型,会进行安全检查,后面的参数都不是类型安全的。使用的时候要小心了。
  摘录网上的一个例子来说明:
  假如我们想打印短整数(short)-1的内存16 进制表示形式,在Win32 平台上,一个short 型占2 个字节,所以我们自然希望用4 个16 进制数字来打印它:

short si = -1;
sprintf(s, "%04X", si);

  产生“FFFFFFFF”,怎么回事?因为spritnf 是个变参函数,除了前面两个参数之外,后面的参数都不是类型安全的,函数更没有办法仅仅通过一个“%X”就能得知当初函数调用前参数压栈时被压进来的到底是个4 字节的整数还是个2 字节的短整数,所以采取了统一4 字节的处理方式,导致参数压栈时做了符号扩展,扩展成了32 位的整数-1,打印时4 个位置不够了,就把32 位整数-1 的8 位16 进制都打印出来了。如果你想看si 的本来面目,那么就应该让编译器做0 扩展而不是符号扩展(扩展时二进制左边补0 而不是补符号位):
  sprintf(s, “%04X”, (unsigned short)si);就可以了。

2 变量地址和指针

  1. 普通变量
int a;
cout << &a;
  1. 数组变量
int a[20];
cout << &a;
cout << (int *)a;
cout<< (void *)a;
  1. 指针
int b = 10;
int *a = &b;
cout << (int *)a;
cout<< (void *)a;

3 cout进制输出

cout<<hex<<i<<endl; //输出十六进制数
cout<<oct<<i<<endl; //输出八进制数
cout<<dec<<i<<endl; //输出十进制数

cout << setbase(16) << t << endl;

4 有关缓冲区的注意点

int main()
{
	printf("hello world!!");//此时可以打出hello world!!
	exit(0);			//exit(0);首先会刷新缓冲区,然后调用_exit(0)结束程序
}
int main()
{
	printf("hello world!!");//此时打不出来 hello world
	_exit(0);//其作用就是结束函数
}
int main()
{
	printf("hello world!!\n");//此时可以打出 hello world 因为“\n”也有刷新缓冲区的作用
	_exit(0);
}
int main()
{
	puts("hello world!!");//此时可以打出 hello world 因为 puts()函数自带有“\n”
	_exit(0);
}

三 参数解析函数

1 getopt_long

2 basename(分析路径成员 )

  c语言:#include <libgen.h>
  c++语言:#include <string.h>
  原型:char *basename(char *path);
  函数说明:
  basename把以 null 结尾的路径名分解为目录和文件名。basename 则返回最后一个 ‘/’ 后面的内容。如果路径名以 ‘/’ 结尾, 该 ‘/’ 被认为不是 路径名的一部分。如果路径名 path 不包含斜杠 ‘/’, basename 返回 path 的副本。如果路径名 path 是 “/”,basename均返回 “/”. 如果 路径名 path 是NULL指针或指向空串,则返回 “.”。basename 有可能更改 path 的内容, 因此如果需要保护原有路径名, 应该传送副本作为参数。此外, 返回的指针可能指向一块静态分配的内存, 会被下次调用覆盖。

3 getopt(分析命令行参数)

  头文件:#include<unistd.h>
  原型:int getopt(int argc,char * const argv[ ],const char * optstring);
  函数说明:参数argc和argv是由main()传递的参数个数和内容。参数optstring 则代表欲处理的选项字符串。此函数会返回在argv 中下一个的选项字母,此字母会对应参数optstring 中的字母。如果选项字符串里的字母后接着冒号“:”,则表示还有相关的参数,全域变量optarg 即会指向此额外参数。如果getopt()找不到符合的参数则会印出错信息,并将全域变量optopt设为“?”字符,如果不希望getopt()印出错信息,则只要将全域变量opterr设为0即可。
  短参数的定义:etopt()使用optstring所指的字串作为短参数列表,象"1ac:d::"就是一个短参数列表。短参数的定义是一个’-‘后面跟一个字母或数字,象-a, -b就是一个短参数。每个数字或字母定义一个参数。
  其中短参数在getopt定义里分为三种:
  1. 不带值的参数,它的定义即是参数本身。
  2. 必须带值的参数,它的定义是在参数本身后面再加一个冒号。
  3. 可选值的参数,它的定义是在参数本身后面加两个冒号 。
  在这里拿上面的"1ac:d::"作为样例进行说明,其中的1,a就是不带值的参数,c是必须带值的参数,d是可选值的参数。
  在实际调用中,’-1 -a -c cvalue -d’, ‘-1 -a -c cvalue -ddvalue’, ‘-1a -ddvalue -c cvalue’都是合法的。这里需要注意三点:
  1. 不带值的参数可以连写,象1和a是不带值的参数,它们可以-1 -a分开写,也可以-1a或-a1连写。
  2. 参数不分先后顺序,’-1a -c cvalue -ddvalue’和’-d -c cvalue -a1’的解析结果是一样的。
  3. 要注意可选值的参数的值与参数之间不能有空格,必须写成-ddvalue这样的格式,如果写成-d dvalue这样的格式就会解析错误。
  返回值:
  getopt()每次调用会逐次返回命令行传入的参数。
  当没有参数的最后的一次调用时,getopt()将返回-1。
  当解析到一个不在optstring里面的参数,或者一个必选值参数不带值时,返回’?’。
  当optstring是以’:‘开头时,缺值参数的情况下会返回’:’,而不是’?’ 。
  范例:

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

四 字符操作函数及其实现

1 Strcat函数

char *strcat(char *strDest, const char *strScr) //将源字符串加const,表明其为输入参数
{
    char * address = strDest;             //该语句若放在assert之后,编译出错
    assert((strDest != NULL) && (strScr != NULL)); //对源地址和目的地址加非0断言
    while(*strDest)             //是while(*strDest!=’\0’)的简化形式
    {                        //若使用while(*strDest++),则会出错,因为++是不受循环
           strDest++;               //约束的。所以要在循环体内++;因为要是*strDest最后指
    }                        //向该字符串的结束标志’\0’。
    while(*strDest++ = *strScr++) 
    {
           NULL;                 //该循环条件内可以用++,
    }                          //此处可以加语句*strDest=’\0’;有无必要?
	return address;               //为了实现链式操作,将目的地址返回
}

以下是在VC6.0中调试的例子,函数名用strcata代替。

#include <stdio.h>
#include <assert.h>
char *strcata(char *strDest,const char *strScr)
{
       char * address = strDest;
       assert((strDest != NULL) && (strScr != NULL));
       while(*strDest)
       {
              strDest++;
       }
       while(*strDest++ = *strScr++) //(*strDest++ = *strScr++)!='\0'
       {
              NULL;
       }
       return address;
}
void main()
{
       char str1[100]={"i love"};
       char str2[50]={"China"};
       printf("%s\n",strcata(str1,str2));
}

2 Strcpy函数

char *strcpy(char *strDest, const char *strScr)
{
       char *address=strDest;
       assert((strDest != NULL) && (strScr != NULL));
       while(*strScr)                   //是while(*strScr != ’\0’)的简化形式;
       {
              *strDest++ = *strScr++;
       }
       *strDest = '\0';                       //当strScr字符串长度小于原strDest字符串长度
       return address;                      //时,如果没有改语句,就会出错了。
}

以下是在VC6.0中调试的例子,函数名用strcpya代替。

#include <stdio.h>
#include <assert.h>
char *strcpya(char *strDest, const char *strScr)
{
       char *address = strDest;
       assert((strDest != NULL) && (strScr != NULL));
       while(*strScr)
       {
              *strDest++ = *strScr++;
       }
       *strDest = '\0';
       return address;
}

void main()
{
       char str1[100]={"i love"};
       char str2[50]={"China"};
       printf("%s\n",strcpya(str1,str2));
}

3 Strcmp函数

int strcmp (const char *str1,const char *str2)
{           
       int len = 0;
       assert((str1 != '\0') && (str2 != '\0'));
       while(*str1 && *str2 && (*str1 == *str2))
       {
              str1++;
              str2++;
       }
       return *str1-*str2;
}

以下是在VC6.0中调试的例子,函数名用strcmpa代替。

#include <stdio.h>
#include <assert.h>
int strcmpa (const char *str1,const char *str2)
{           
       int len = 0;
       assert((str1 != '\0') && (str2 != '\0'));
       while(*str1 && *str2 && (*str1==*str2))
       {
              str1++;
              str2++;
       }
       return *str1-*str2;
}
void main()
{
       char str1[100] = {"i love"};
       char str2[50] = {"China "};
       printf("%d\n",strcmpa(str1,str2));
}

4 Strlen函数

int strlen(const char *str)
{
    int len = 0;
       assert(str != NULL);
       while(*str++)
       {
              len++;
       }
       return len;
}

以下是在VC6.0中调试的例子,函数名用strlena代替。

#include <stdio.h>
#include <assert.h>
int strlena(const char *str)
{
    int len = 0;
       assert(str != NULL);
       while(*str++)
       {
              len++;
       }
       return len;
}
void main()
{
       char str1[100] = {"i love"};
       char str2[50] = {"China "};
       printf("%d\n",strlena(str1));
}

1 strstr()

strstr()函数用来检索子串在字符串中首次出现的位置,其原型为:

char *strstr(const char *str, const char *substr);

【参数说明】str为要检索的字符串,substr为要检索的子串。
【返回值】返回字符串str中第一次出现子串substr的地址;如果没有检索到子串,则返回NULL。

2 strcmp()

strcmp()用来比较字符串(区分大小写),其原型为:

int strcmp(const char *s1, const char *s2);

【参数】s1, s2 为需要比较的两个字符串。
【返回值】若参数s1 和s2 字符串相同则返回0。s1 若大于s2 则返回大于0 的值。s1 若小于s2 则返回小于0 的值。

3 strcasecmp()

strcasecmp()用来比较字符串(忽略大小写),其原型为:

int strcasecmp (const char *s1, const char *s2);

【参数】s1, s2 为需要比较的两个字符串。
【返回值】若参数s1 和s2 字符串相同则返回0。s1 若大于s2 则返回大于0 的值。s1 若小于s2 则返回小于0 的值。

4 index()

index()函数查找字符并返回首次出现的位置
相关函数:rindexsrechrstrrchr
头文件:#include <string.h>

char * index(const char *s, int c);

【参数】index()用来找出参数s 字符串中第一个出现的参数c地址,然后将该字符出现的地址返回。字符串结束字符(NULL)也视为字符串一部分。
【返回值】如果找到指定的字符则返回该字符所在地址,否则返回0。

五 随机数

计算机的随机数都是由伪随机数,即是由小M多项式序列生成的,其中产生每个小序列都有一个初始值,即随机种子。(注意: 小M多项式序列的周期是65535,即每次利用一个随机种子生成的随机数的周期是65535,当你取得65535个随机数后它们又重复出现了。)
我们知道rand()函数可以用来产生随机数,但是这不是真正意义上的随机数,是一个伪随机数,是根据一个数(我们可以称它为种子)为基准以某个递推公式推算出来的一系列数,当这系列数很大的时候,就符合正态公布,从而相当于产生了随机数,但这不是真正的随机数,当计算机正常开机后,这个种子的值是定了的,除非你破坏了系统。
1.rand()
功能:随机数发生器
用法:int rand(void)
所在头文件: stdlib.h
rand()的内部实现是用线性同余法做的,它不是真的随机数,因其周期特别长,故在一定的范围里可看成是随机的。
rand()返回一随机数值的范围在0至RAND_MAX 间。RAND_MAX的范围最少是在32767之间(int)。用unsigned int 双字节是65535,四字节是4294967295的整数范围。0~RAND_MAX每个数字被选中的机率是相同的。
用户未设定随机数种子时,系统默认的随机数种子为1。
rand()产生的是伪随机数字,每次执行时是相同的;若要不同,用函数srand()初始化它。
2.srand()
功能:初始化随机数发生器
用法: void srand(unsigned int seed)
所在头文件: stdlib.h
srand()用来设置rand()产生随机数时的随机数种子。参数seed必须是个整数,如果每次seed都设相同值,rand()所产生的随机数值每次就会一样。
3.使用当前时钟作为随机数种子
rand()产生的随机数在每次运行的时候都是与上一次相同的。若要不同,用函数srand()初始化它。可以利用srand((unsigned int)(time(NULL))的方法,产生不同的随机数种子,因为每一次运行程序的时间是不同的。
4.产生随机数的用法

  1. 给srand()提供一个种子,它是一个unsigned int类型;
  2. 调用rand(),它会根据提供给srand()的种子值返回一个随机数(在0到RAND_MAX之间);
  3. 根据需要多次调用rand(),从而不间断地得到新的随机数;
  4. 无论什么时候,都可以给srand()提供一个新的种子,从而进一步“随机化”rand()的输出结果。
//0~RAND_MAX之间的随机数程序
#include <iostream> 
#include <stdlib.h> 
#include <time.h>  
using namespace std; 
int main() 
{ 
    srand((unsigned)time(NULL)); 
    for(int i = 0; i < 10;i++ ) 
            cout << rand() << '/t'; 
    cout << endl; 
    return 0; 
}

5.产生一定范围随机数的通用表示公式
要取得[a,b)的随机整数,使用(rand() % (b-a))+ a;
要取得[a,b]的随机整数,使用(rand() % (b-a+1))+ a;
要取得(a,b]的随机整数,使用(rand() % (b-a))+ a + 1;
通用公式:a + rand() % n;其中的a是起始值,n是整数的范围。
要取得a到b之间的随机整数,另一种表示:a + (int)b * rand() / (RAND_MAX + 1)。
要取得0~1之间的浮点数,可以使用rand() / double(RAND_MAX)。

六 main函数

https://blog.csdn.net/weixin_42078760/article/details/80500048

1 main函数与WinMain函数区别

前者为控制台程序入口主函数,后者为Windows API窗体程序入口函数,在windef.h文件中定义。

2 main函数与wmain函数 | WinMain函数与wWinMain函数的区别

wmain函数式main函数的宽字符版本,一般在Unicode编码下使用。

3 _tmain函数与main/wMain | _tWinMain函数与WinMain/wWinMain的区别

_tmain函数是wmain函数和main函数Unicode版本的别名,_tWinMain函数是wWinMain函数和WinMain函数Unicode版本的别名,二者都是在tchar.h文件中定义,目的是为了自动适应是否定义了Unicode。
如果为Unicode编码,_tmain就是wmain,_tWinMain就是wWinMain;否则,_tmain则为main,_tWinMain就是WinMain。
注意:使用这两个函数时要加入<tchar.h>引用。

七 C++中L和_T()之区别

https://www.cnblogs.com/yaowen/archive/2013/01/15/2861727.html

八 获取执行文件路径

https://www.cnblogs.com/Duck-Quick/p/9102830.html

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值