鉴于c++语法和函数众多,希望可以熟悉掌握库函数的用法,以助于提升自己的编程能力和学习水平。主要依托 cplusplus 网站,这是一个非常好的C++学习网站,有语言的一些概念,便于理解。还有读者论坛便于讨论,不过是英文的网站,大家可以用浏览器的翻译功能进行阅读,同时也可以提高自己的英文水平。
这一篇主要是对< cstring >头文件的函数进行学习
< cstring >
一.复制
1.memmove
不同的编码里,字符和字节的对应关系也不同,与编码方式有关
一个英文占一个字节 一个中文占两个字节
先看一个引例
#include<iostream>
#include<cstring>
using namespace std;
int main()
{
char s[]="wang x y";
cout<<s<<endl;
cout<<"s[0]="<<s[0]<<endl;//s[0]=w
cout<<"s[1]="<<s[1]<<endl;//s[1]=a
cout<<"s[4]="<<s[4]<<endl;//s[4]=' '
cout<<"s+2="<<s+2<<endl;//从第三个开始ng x y
cout<<"sizeof(s)="<<sizeof(s)<<endl;//求字节数组后面默认/0
cout<<"strlen(s)="<<strlen(s)<<endl; //求长度 有几个就是几
return 0;
}
memmove用于拷贝字节,如果目标区域和源区域有重叠的话,memmove能够保证源串在被覆盖之前将重叠区域的字节拷贝到目标区域中,但复制后源内容会被更改。
该函数不检查源代码中的任何终止空字符——它总是精确地复制num字节。 为了避免溢出,由目标和源参数指向的数组的大小至少应为num字节。
函数原型:void * memmove ( void * destination, const void * source, size_t num );
有三个参数 void *destination 指向要复制内容的目标数组的指针
const void * source 指向要复制的数据源的指针
size_t num 要复制的字节数。 size_t是一个无符号整型。
举个例子:
#include<iostream>
#include<cstring>
using namespace std;
int main()
{
char s[] = "wang xin yue";
char b[] = "WANG XIN YUE";
memmove(s+5, b+5, 3);//替换中间的字符
memmove(s,"bbbb",4);//也可以
//b+5是要复制的数组开始的地方
//3是复制的字节大小 s+5是目标数组被复制过来代替的地方
cout << s << endl;
return 0;
}
再看一个自身操作的例子
#include<iostream>
#include<cstring>
using namespace std;
int main()
{
//char s[] = "wang xin yue";如果这样写的化会出错 溢出
char s[30] = "wang xin yue";
//对自己进行操作 想实现xin--wang
memmove(s + 8, s + 7, 5);
//这步后变成wang xinn yue 目的是拉长一位
cout << s << endl;
memmove(s + 5, s, 4);
//再把前四位替换掉中间四位
cout << s << endl;
return 0;
}
举个汉字的例子
#include<iostream>
#include<cstring>
using namespace std;
int main()
{
char s[] = "王 wang";
//memmove(s, s + 3, 2); 结果wa wang
memmove(s + 5, s, 2);
cout << s << endl;//王 wa王
return 0;
}
string类的例子
#include<iostream>
using namespace std;
int main()
{
string s = "wang xin yue";
string S = "WANG";
memmove(&s[0], &S[0], 4);
cout << s << endl;
return 0;
}
指针指向数组例子
#include<iostream>
#include<cstring>
using namespace std;
int main()
{
char s[] = "wang nb";
char* w = s;//指向字符的指针
memmove(w,w+5,2 );
cout << *w << endl;//解引用 第一个字符
cout << w << endl;//nbng nb
return 0;
}
整型数组的例子
#include<iostream>
using namespace std;
int main()
{
int a[] = {1,2,3};
int b[] = { 6,7,8 };
cout << "a[1]=" << a[1] << endl;// 2
cout << "sizeof(a)=" << sizeof(a) << endl;//int型占4个字节
cout << a << endl;//a[]是一个整型数组 直接输出是首地址
cout <<& a[1] <<" "<< & a[2] << endl;//可见相邻元素之间地址差一个类型所占字节数
memmove(a+1, b+1, 8);//注意此处第三个参数应是int型字节数
for (int i = 0; i < sizeof(a)/4; i++)//直接输出不能实现 用循环
{
cout << a[i];
}
return 0;
}
2.memcpy
此函数用法和作用与memmove几乎相同但是memmove相对安全,因为memcpy会有内存重叠问题
内存重叠就是:拷贝的目的地址在源地址的范围内,有重叠。
函数原型:void * memcpy ( void * destination, const void * source, size_t num );
看一个例子 与memmove差不多
#include<iostream>
using namespace std;
class person {
public:
char name[20];
int age = 12;
};
int main()
{
person A,B;
char s[] = "wang xin yue";
char b[20];
memcpy(A.name, s, strlen(s)+1);
//A对象name赋值
memcpy(B.name,A.name ,sizeof(A.name));
//用A.name给B.name赋值
//sizeof(A)会提示A.name可读20字节
//但可能从A.name中读取24字节 给B.name时可能溢出 写入24字节
//memcpy(&B, &A, sizeof(A));//这样也可以
cout << B.name << endl;
char m[] = "aaaa";
char n[]=" b";
char c[] = "\0 c";
memcpy(c, m, 1);
cout << c<< endl;
return 0;
}
二.串联
1.strcat
连接字符串 将源字符串的副本追加到目标字符串。目标中的终止空字符被源中的第一个字符覆盖,空字符包含在由目标中的两个字符串联而成的新字符串的末尾。 目的地和来源不应重叠。
函数原型:char * strcat ( char * destination, const char * source );
例:
#include<iostream>
#include<cstring>
using namespace std;
int main()
{
char s[80] = "wang xin yue ";//[]上所占大小 会有接上字符串后溢出的情况
char b[] = "xiao sha sha !";
strcat_s(s, "xiao sha sha!");//strcat会报错建议使用strcat_s
//strcat_s(s, b); 同样的效果
string a= "WANG xin yue ";
string c = "Xiao sha sha";
cout<<a+c<<endl;
cout << s << endl;
return 0;
}
2.strncat
将源的前num个字符追加到目标,加上一个终止空字符。 如果source中字符串的长度小于num,则只复制终止空字符之前的内容。
函数原型:
char * strncat ( char * destination, const char * source, size_t num );
#include<iostream>
#include<cstring>
using namespace std;
int main()
{
char s[20] = "wang xin yue ";
char b[20] = "xiao sha sha !";
//strncat_s(s, b,4); 从源字符复制到目标字符 从目标字符的结尾开始 则不能改变
strncat_s(s, b + 5, 3);//可定义开始的位置和字节长度
cout << s << endl;
return 0;
}
四.搜索
1.memchar
字符查找,在内存块中定位字符
在ptr指向的内存块的第一个num字节中搜索第一个出现的值(解释为无符号字符),并返回指向它的指针。
函数原型:
const void * memchr ( const void * ptr, int value, size_t num );
返回值为指针
字符查找例子:
#include<iostream>
#include<cstring>
using namespace std;
int main()
{
//字符查找
char s[] = "wang sha sha";
char* p;//返回值是一个指针 用P接收
p =(char *)memchr(s, 'g', strlen(s));//标明返回的指针类型
if (p != NULL)//判断返回值是否为空
cout << "g被找到,是第"<<int(p)-int(s)+1<<"个" << endl;
else
cout << "没找到" << endl;
cout <<p<< endl;//此时P指向的是被查找字符g从此开始的地址
//若查找的字节中无所找的字符 则p指向未知报错
return 0;
}
数组查找例子:
#include<iostream>
#include<cstring>
using namespace std;
int main()
{
int s[] = { 1,2,3,4,5 };
int * p = (int*)memchr(s, 2, sizeof(s));//要定位的值,该值作为int传递查找的是数字直接写
if (p != NULL) cout << "找到了 " << p - s + 1 << endl;
else cout << "没找到" << endl;
return 0;
}
正常遍历查找,循环
#include<iostream>
using namespace std;
int main()
{
int s[] = { 1,2,3,4,5 };
int i;
for (i = 0; i < 5; i++)
{
if (s[i] == 2)
cout << "2找到了" << i + 1 << endl;
}
return 0;
}
2.strchr
定位字符串中第一个出现的字符,返回一个指针,指向字符串中第一个出现的字符。 也可以定位终止字符。
函数原型:const char * strchr ( const char * str, int character );
要定位的字符作为int提升传递,但为了比较,它在内部被转换回char。
返回值:指向字符串中第一个出现的字符的指针
举个例子:
#include<iostream>
#include<cstring>
using namespace std;
int main()
{
char s[] = "wang xin yue xiao sha sha";
char* p;
p = strchr(s, 'x');
cout << p << endl;//xin yue xiao sha sha
while (p != NULL)
{
cout << "找到这个字符 " << p-s+ 1 << endl;//第一次找到此字符 指向x开始的字符串
p = strchr(p + 1, 'x');//此时应跳过查找过的x继续查找
}
return 0;
}
不能是整型数组若是数组也可以定义为char类型
#include<iostream>
#include<cstring>
using namespace std;
int main()
{
char s[] = "12333456789";
char* p;
int i = 0;
p = strchr(s,'3');
while (p != NULL)
{
cout << '3' ;
i += 1;
p = strchr(p + 1, '3');
}
cout << '\n';
cout << i << endl;
return 0;
}
3.strcspn
找到字符串中符合条件的第一个字符,返回在第一个匹配项之前读取的字符数,如果找不到则返回字符串的长度。
函数原型:size_t strcspn ( const char * str1, const char * str2 );
#include <iostream>
#include<cstring>
using namespace std;
int main()
{
char s[] = "wang xin yue";
char b[] = "mxmy";
char c[] = "mmmm";
int i,j;
i = strcspn(s, b);//如果找到了返回在第一个匹配项之前读取的str1的字符数
j = strcspn(s, c);
cout << i << endl;
cout << j << endl;//如果找不到返回s的长度
cout << "第一个匹配的字符"<<s[i] <<"在这" << i + 1 << endl;
return 0;
}
4.strpbrk
定位字符串中的字符,返回一个指针,指向str1中第一个出现的属于str2的任何字符,如果没有匹配项,则返回一个空指针。 搜索不包括字符串的终止空字符
函数原型:const char * strpbrk ( const char * str1, const char * str2 );
#include <iostream>
using namespace std;
int main()
{
char s[] = "wang xin yue";
char b[] = "aeiou";
char* p;//接收返回指针
p = strpbrk(s, b);
cout << p << endl;
//ang xin yue指向s中第一个出现的属于b的任何字符的指针
cout << *p << endl;//a
while (p != NULL)
{
cout << "符合条件的字符" << *p << endl;
p = strpbrk(p + 1, b);
//找到后再继续搜索此字符之后的字符串符合条件的字符
}
return 0;
}
5.strrchr
定位字符串中最后一次出现所找字符的位置
函数原型:const char * strrchr ( const char * str, int character );
指向字符串中最后出现的字符的指针。 如果找不到该字符,该函数将返回一个空指针。
#include<iostream>
using namespace std;
int main()
{
char s[] = "wangxinyue";
char* p = strrchr(s,'n');
if (p != NULL)
{
//cout << p << endl; nyue指向字符串中最后出现的所找字符的指针
cout << "最后出现在" << p - s + 1 << endl;
}
else cout << "没有找到" << endl;
return 0;
}
6.strspn
从第一个字符开始,搜索字符串中属于另一个字符串的字符数,若第一个不符合条件,则返回0,若符合,则到第一个不符合的字符结束。
函数原型:size_t strspn ( const char * str1, const char * str2 );
#include<iostream>
using namespace std;
int main()
{
char s[] = "124wang xin 123 yue";
char c[] = "4wang";
char b[] = "123456wang";
int i;
int j;
i = strspn(s, b);//从第一个开始到第一个不属于的结束
j = strspn(s, c);//若第一个字符不属于需要的字符集则返回0
cout << "s中属于b的有" << i << "个" << endl;//3个
cout << "s中属于b的有" << j << "个" << endl;
return 0;
}
7.strstr
字符串中查找字符串
返回指向str1中第一个str2的指针,如果str2不是str1的一部分,则返回空指针。 匹配过程不包括终止的空字符,但是它在那里停止。
函数原型:const char * strstr ( const char * str1, const char * str2 );
#include<iostream>
#include<cstring>
using namespace std;
int main()
{
char s[] = "WANG wang as!";
char b[] = "wang";
char* p = strstr(s, b);
if (p != NULL)
{
memmove(p, "wwww", 4);
cout << p << endl;
}
else
cout << "没有找到" << endl;
return 0;
}
五.其他
1.memset
在字符串中的指定字节的数中设置指定值
函数原型:void * memset ( void * ptr, int value, size_t num );
#include<iostream>
#include<cstring>
using namespace std;
int main()
{
char s[] = "wang sha sha";
memset(s+1, '-', 3);//从第二个字符开始复制三个-
//要设置的以int形式存放不能是字符串
cout << s << endl;
return 0;
}