https://blog.csdn.net/MOU_IT/article/details/88975116#3、strcat()函数
1、strcpy():复制字符串
2、strncpy():复制n个字符串
3、strcat():连接字符串
4、strncat():连接n个字符串
5、strcmp():字符串比大小
6、strlen():字符串长度
7、strset():字符串重置
9、memset():内存重置
10、memcpy():内存复制(不安全)
11、memmove():内存复制(安全)
12、strstr()、strchr():查找后一个字符出现的地址
注意:当src串长度>dest串长度时,程序仍会将整个src串复制到dest区域,可是dest数组已发生溢出。因此会导致dest栈空间溢出以致产生崩溃异常。当达到最大尺寸时,它只是停止复制字符。
-
char* myStrcpy(char* pre, const char* next)
-
{
-
if (pre ==
nullptr || next ==
nullptr)
//空指针直接返回
-
{
-
return
nullptr;
-
}
-
if (pre == next)
// 两者相等也无需拷贝了
-
return pre;
-
-
while ((*pre++ = *next++) !=
'\0');
// 依次赋值给主字符数组
-
return pre;
-
}
上面程序实现了strcpy的程序,实现很简单依次赋值给朱字符数组即可,当遇到next指向字符串结束字符’\0’后,完成赋值并且停止赋值。这样新赋值的’\0’就成了字符数组表示的字符串结尾符,哪怕主字符串pre比next长也会戛然而止。字符串判断不管字符数组存了啥,它只认到’\0’前的数是它的主体核心部分。strcpy没有检查长度会溢出,推荐使用strncpy。
说明:如果n > dest串长度,dest栈空间溢出。否则:
1)src串长度<=dest串长度,(这里的串长度包含串尾NULL字符)
如果n=(0, src串长度),src的前n个字符复制到dest中。但是由于没有NULL字符,所以直接访问dest串会发生栈溢出的异常情况。
如果n = src串长度,与strcpy一致。
如果n = dest串长度,[0,src串长度]处存放src字串,(src串长度, dest串长度]处存放NULL。
2)src串长度>dest串长度
如果n =dest串长度,则dest串没有NULL字符,会导致输出会有乱码。
-
char *strncpy(char *strDest , const char *strSrc , int n)
-
{
-
assert((strDest !=
NULL) && (strSrc !=
NULL));
-
char *address = strDest;
-
while(n-- >
0)
-
*strDest++ = *strSrc++;
-
return address;
-
}
strcat函数常见的错误就是数组越界,即两个字符串连接后,长度超过第一个字符串数组定义的长度,导致越界。
-
char* myStrcat(char* pre, const char* next)
-
{
-
if (pre ==
nullptr || next ==
nullptr)
// 如果有一个为空指针,直接返回pre
-
return pre;
-
char* tmp_ptr = pre +
strlen(pre);
//strlen计算字符数,需要包含都文件string.h,当然也可以自己实现
-
while ( (*tmp_ptr++ = *next++) !=
'\0');
// 依次接着赋值
-
return pre;
-
}
由于strcat也容易造成缓冲区溢出,因此推荐使用strncat.
strncat把src所指向的字符的前n个字符添加到dest结尾处(覆盖原dest结尾处的'\0'),并添加新的'\0'。src和dest所指内存区域不可以重叠,并且dest必须有足够的空间来容纳src的前n个字符串,返回指向dest的指针。
-
char *strncat(char *dest,const char *str,int n)
-
{
-
assert((dest!=
NULL)&&(str!=
NULL));
-
char *cp=dest;
-
while(*cp!=
'\0') ++cp;
-
-
while(n&&(*cp++=*str++)!=
'\0')
-
{
-
--n;
-
}
-
return dest;
-
}
-
由于这四个函数都可能造成缓冲区溢出,在VS2015中已经禁用这几个函数。
strcmp函数是C/C++中基本的函数,它对两个字符串进行比较,然后返回比较结果,函数形式为:int strcmp(const char* str1, const char* str2)。其中str1和str2可以是字符串常量或者字符串变量,返回值为整形。返回结果如下规定:
① str1小于str2,返回负值或者-1(VC返回-1);
② str1等于str2,返回0;
③ str1大于str2,返回正值或者1(VC返回1);
strcmp函数实际上是对字符的ASCII码进行比较,实现原理如下:首先比较两个串的第一个字符,若不相等,则停止比较并得出两个ASCII码大小比较的结果;如果相等就接着 比较第二个字符然后第三个字符等等。无论两个字符串是什么样,strcmp函数最多比较到其中一个字符串遇到结束符'/0'为止,就能得出结果。代码实现如下(参考):
-
int strcmp(const char* str1, const char* str2)
-
{
-
int ret =
0;
-
while(!(ret=*(
unsigned
char*)str1-*(
unsigned
char*)str2) && *str1){
-
str1++;
-
str2++
-
}
-
if (ret <
0){
-
return
-1;
-
}
-
else
if(ret >
0){
-
return
1;
-
}
-
return
0;
-
}
strlen()用于计算字符数组长度,到字符串结束符’\0’即停止。如:
-
char nzArr[] =
"abcdef";
-
int nLen =
strlen(nzArr);
//结果为6,并不是100,和分配数组内存大小无关,不包含'/0'
-
int nLen =
sizeof(nzArr);
//结果为7,包括'/0'
strset()用于设定字符数组全为某一字符,如果存在‘\0’结束符,遇结束符停止赋值。
-
char nzArr[
100]=
"abcd";
-
strset(nzArr,
'g');
//nzArr结果为“gggg”,如果未初始化,则100个空间都为'g'
memset()与strset()类似,赋值字符数组指定字符,但可以指定个数。
-
char nzArr[
100]=
"abcd";
-
memset(nzArr,
'g',
sizeof(nzArr));
//nzArr中全为g,该函数是空间操作,不遇'\0'停止,输出g后会出现乱码
memcpy()由src指向地址为起始地址的连续n个字节的数据复制到以destin指向地址为起始地址的空间内。
函数实现:
-
void* memcpy(void* dest, const void* src, size_t n)
-
{
-
char* d = (
char*) dest;
-
const
char* s = (
const
char*) src;
-
while(n-–)
-
*d++ = *s++;
-
return dest;
-
}
strcpy和memcpy主要有以下3方面的区别。
-
#include
-
#include
-
int main(){
-
char*s=
"Golden Global View";
-
chard[
20];
-
clrscr();
-
memcpy(d,s,
strlen(s));
-
d[
strlen(s)]=
'\0';
//因为从d[0]开始复制,总长度为strlen(s),d[strlen(s)]置为结束符
-
printf(
"%s",d);
-
getchar();
-
return0;
-
}
-
输出结果:GoldenGlobal View
memcpy与memmove的目的都是将N个字节的源内存地址的内容拷贝到目标内存地址中。但当源内存和目标内存存在重叠时,memcpy会出现错误,而memmove能正确地实施拷贝,但这也增加了一点点开销。memmove的处理措施:
函数实现:
-
void* memmove(void* dest, const void* src, size_t n)
-
{
-
char* d = (
char*) dest;
-
const
char* s = (
const
char*) src;
-
-
if (s>d)
-
{
-
// start at beginning of s
-
while (n--)
-
*d++ = *s++;
-
}
-
else
if (s
-
{
-
// start at end of s
-
d = d+n
-1;
-
s = s+n
-1;
-
-
while (n--)
-
*d-- = *s--;
-
}
-
return dest;
-
}
12、strstr()、strchr():查找后一个字符出现的地址
strstr()和strchr()都是查找第二个参数第一次出现在第一个字符数组的位置,前者是查找字符数组,而后者是字符。但是注意返回,返回的是参数出现的地址,需要赋给char*指针来存储,而不是一个索引。
-
char nzArr[
10] =
"ababcde",nzBuf[
10]=
"abc";
-
char* nzCount = (
char*)
malloc(
sizeof(
char)*
10);
-
char* nzCount1 = (
char*)
malloc(
sizeof(
char)*
10);
//结果分配空间
-
memset(nzCount,
0,
sizeof(nzCount));
//赋初值
-
memset(nzCount1,
0,
sizeof(nzCount1));
//防止未匹配到指定字符或字符数组,而成为野指针
-
nzCount =
strstr(nzArr,nzBuf);
//返回为'abcde'
-
nzCount1 =
strstr(nzArr,
'c');
//返回为'cc'
参考:https://blog.csdn.net/FX677588/article/details/76702319
https://blog.csdn.net/lanzhihui_10086/article/details/39828901
https://blog.csdn.net/wgenek/article/details/7257435
https://blog.csdn.net/fx677588/article/details/53102634
https://www.cnblogs.com/kekec/archive/2011/07/22/2114107.html