1.memset
memset是计算机中C/C++语言初始化函数。作用是将某一块内存中的内容全部设置为指定的值, 这个函数通常为新申请的内存做初始化工作。
函数介绍
#include<string.h>
void *memset(void *s, int ch, size_t n);
解释:将s中当前位置后面n个字节用ch替换;
作用:在一段内存块中填充某个给定的值,它是对较大的结构体或数组进行清零操作的一种最快方法 。
函数原型:
extern void *memset(void *buffer, int c, int count)
buffer:数组或者指针
c:是赋给buffer的值
count:是buffer的长度
1.函数常用于内存空间初始化
2.用来对一段内存空间全部设置为某个字符,一般用在对定义的字符串进行初始化
3.可以方便的清空一个结构类型的变量或数组
2.strncat
注.(得到的新串后面自动加上NULL字符)
1.函数原型
char * strncat(char *str1,const *char *str2,size_t_n);
2.作用:用于连接字符串,该函数要求指明在原字符串末尾附加的目标字符串的长度。
(1)如果str2的字符数大于n,那么该函数只将str2的前n个字符附加在str1末尾;(2)如果str2的字符数小于n,那么该函数会将str2 的所有字符附加在str1末尾。无论哪种情况,都会在新字符串的末尾添加空字符,必须为str1分配足够的空间以存储新的字符串。
strncat()函数返回指向str1的指针。
#include<stdio.h>
#include<string.h>
int main(int argc,char *argv[])
{
char dest[10]=“demo”;
char src[20]=“strncat”;
strncat(dest,src,7);
printf("%s\n",dest);
return 0;
}
3.strncpy
注.strncpy不拷贝’\0’
strcpy是个不安全函数,需考虑str前者空间大小,如果p指向的串太大则会造成程序崩溃。
1.函数原型
char *strncpy(char *dest, char *src, size_t num);
#include<string.h>
#include<stdio.h>
int main()
{
char str[4]={0};
const char *p="a\0bcdefg";
strncpy(str,p,sizeof(str)-1);
printf("%s\n",str);
return 0;
}
~ 输出结果为a
总结: 1.先定义并初始化 char str[MAX + 1] = {0};
如果程序中间需要再往str中拷贝串,一定要用memset清零。拷贝范式:strncpy(str, p, sizeof(str) - 1);
2.strcnpy拷贝的是字符,不拷贝串,所以最后一个\0不拷贝(若在中间遇到\0则后面不拷贝),拷贝的时候需要对串进行清零处理。
3.strncpy拷贝时,可能会导致截断,但程序不会崩溃。
4.strcnpy的原型,也并不一定 拷贝num个字符也有特殊情况。
#include<stdio.h>
int main(int argc,char *argv[])
{
char str[4]={'x','y','z','b'};
char *p="a\0bcdeadg";
strcnpy(str,p,sizeof(str)-1);
printf("%c\n",(char)str[0]); //'a'
printf("%d\n",(int)str[1]); //'\0'
printf("%d\n",(int)str[2]); //'\0'
printf("%c\n",(char)str[3]); //'b'
return 0;
}
5.关于strncpy,要防止内存重叠
内存重叠问题参考博文
4.strncasecmp
1.定义和用法
strncasecmp() 函数比较两个字符串(不区分大小写)。
strncasecmp() 是二进制安全的,且不区分大小写。
strcasecmp() 没有 length 参数。
2.语法
strncasecmp((const char *str1, const char *str2,size_t n);
str1:需要比较的第一个字符串
str2:需要比较的第二个字符串
n:比较参数str1和str2字符串前n个字符,比较时自动忽略大小写的差异。
返回值:
如果两个字符串相同返回值为0
如果str1>str2返回值为>0
如果str1<str2返回值为<0
#include<stdio.h>
#include<string.h>
int main(int argc,char *argv[])
{
char *a="aBCDEFG";
char *b="aBCDHSD";
printf("%d\n",strncasecmp(a,b,4)); //0
return 0;
}
5.snprintf
1.函数原型
int snprintf(char *str, size_t size, const char *format, ...);
2.函数参数
str:目标字符串;size:拷贝字节数(Bytes); format:源字符串; …格式
最多从源字符串format中拷贝size字节的内容(含字符串结尾标志’\0’)到目标字符串
3.返回值
<1>成功返回源字符串的长度(strlen, 不含’\0’)
<2>失败返回负值
#include<stdio.h>
int main(int argc,char *argv[])
{
char buf[12]={0};
size_t t;
t=snprintf(buf,sizeof(buf),"%d",1234567891); //t=10,buf:1234567891 \0
printf("size=%ld,text:%s\n",t,buf);
return 0;
}
(1) 如果格式化后的字符串长度 < size,则将此字符串全部复制到str中,并给其后添加一个字符串结束符(’\0’);
(2) 如果格式化后的字符串长度 >= size,则只将其中的(size-1)个字符复制到str中,并给其后添加一个字符串结束符(’\0’),返回值为欲写入的字符串长度。
文章二:snprintf/_snprintf 在不同平台间函数差异
6.strtok_r
1.函数原型:
#include <string.h>
char *strtok(char *str, const char *delim);
char *strtok_r(char *str, const char *delim, char **saveptr);
2.函数参数:
char *str是被分割字符串,第一次调用函数strtok_r时此指针一定不能为空,连续分割同一个字符串时,第一次调用之后的调用需将str设置为NULL。
const char *delim是分隔符,也是个字符串指针。
char **saveptr是一个供内部使用的指针,用于保存上次分割剩下的字串。
3.返回值
返回值是个指针,用于返回从被分割字符串中得到的第一个目标子串。
注意:虽然函数strtok_r可以将一个字符串进行分割,但是每次分割只能得到第一个被分割的字串
4.参考博文
strtok与strtok_r实现原理
strtok_r实际上就是将strtok内部隐式保存的this指针,以参数的形式与函数外部进行交互。由调用者进行传递、保存甚至是修改。需要调用者在连续切分相同源字符串时,除了将str参数赋值为NULL,还要传递上次切分时保存下的saveptr。
#include<stdio.h>
#include<string.h>
#define INFO_MAX_SZ 1024
int main(int argc,char *argv[])
{
int in=0;
int i=0;
char name[INFO_MAX_SZ]="FIRST male 22,SECOND males 23,Thrid males 24";
char *p[20];
char *buf=name;
char *outer_ptr=NULL;
char *inner_ptr=NULL;
while((p[in]=strtok_r(buf,",",&outer_ptr))!=NULL)
{
buf=p[in];
while((p[in]=strtok_r(buf," ",&inner_ptr))!=NULL)
{
in++;
buf=NULL;
}
buf=NULL;
}
printf("we hava %d string\n",in);
for(i=0;i<in;i++)
{
printf("%s\n",p[i]);
}
return 0;
}
outer_ptr和inner_ptr。outer_ptr用于标记每个人的提取位置,即外循环;inner_ptr用于标记每个人内部每项信息的提取位置,即内循环。
<1>第一次外循环,outer_ptr忽略,分割符 ",“被修改为 ‘ \0 ’;对整个源串提取,outer_ptr返回指向S。
<2>第一次内循环,innner_ptr忽略,对第一次外循环的提取结果“FIRST male 22”进行提取,提取出"FIRST”。分割符 " “被修改为 ’ \0 ';inner_ptr返回指向m。
<3>第二次内循环,传递第一次内循环返回的inner_ptr,第一个参数为NULL;从inner_ptr指向位置” m “进行提取,提取出” male “。分隔符” “被修改为’\0’;inner_ptr返回指向2;
<4>第三次内循环,传递第二次内循环返回的inner_ptr,第一个参数为NULL;从inner_ptr指向位置” 2 "进行提取,提取出“ 22 ”。因为没有找到“ ”,
inner_ptr返回指向22后面的 ’ \0 ’ ;
<5>第四次内循环,传递第三次内循环返回的inner_ptr,第一个参数为NULL;因为inner_ptr指向的位置为’\0’;无法提取,返回空值结束内循环。
<6>第二次外循环,传递第一次外循环返回的outer_ptr,第一个参数为NULL;从outer_ptr返回的位置S进行提取,提取出“SECOND males 23”,将分割符“,”修改为’\0’;outer_ptr返回指向T;
…以此类推。
7.sccanf
#include<stdio.h>
int main(int argc,char *argv[])
{
char *string;
int ret;
char protocol[255];
char domain[255];
char port[255];
char path[255];
char ip[255];
char username[255];
char password[255];
/*
string="http://www.grandstream.com:8088/cgi?a=fangjia&b=sss";
ret=sscanf(string,"%[^:]://%[^:]:%[^/]/%[^?]",protocol,domain,port,path);
printf("%s\n",protocol);
printf("%s\n",domain);
printf("%s\n",port);
printf("%s\n",path);
*/
/*
string="sips:Alice:s1ptest@grandstream.cn:5060";
ret=sscanf(string,"%[^:]:%[^:]:%[^@]@%[^:]:%s",protocol,username,password,domain,port);
printf("%s\n",protocol);
printf("%s\n",username);
printf("%s\n",password);
printf("%s\n",domain);
printf("%s\n",port);
*/
string="ftp://[8000::2]:9999/filename.tgz";
ret=sscanf(string,"%[^:]://[%[^]]]:%[^/]/%s",protocol,ip,port,domain);
printf("%s\n",protocol);
printf("%s\n",ip);
printf("%s\n",port);
printf("%s\n",domain);
return 0;
}
demo01:
http
www.grandstream.com
8088
cgi
demo02:
sips
Alice
s1ptest
grandstream.cn
5060
demo03:
ftp
8000::2
9999
filename.tgz
参考博文: