strcpy()、strlen()、memcpy()、memmove()、memset()的实现
strcpy(), 字符串拷贝.
char *strcpy(char *strDest, const char *strSrc)
{
assert((strDest!=NULL) && (strSrc !=NULL));
char *address = strDest;
while( (*strDest++ = * strSrc++) != '\0')
NULL ;
return address ;
}
strlen,
#include <iostream>
using namespace std;
void itoaTest(int num,char str[] )
{
int sign = num,i = 0,j = 0;
char temp[11];
if(sign<0)//判断是否是一个负数
{
num = -num;
};
do
{
temp[i] = num%10+'0';
num/=10;
i++;
}while(num>0);
if(sign<0)
{
temp[i++] = '-';//对于负数,要加以负号
}
temp[i] = '\0';
i--;
while(i>=0)//反向操作
{
str[j] = temp[i];
j++;
i--;
}
str[j] = '\0';
}
2. //字符串转换成整数atoi函数的实现
int atoiTest(char s[])
{
int i = 0,sum = 0,sign; //输入的数前面可能还有空格或制表符应加判断
while(' '==s[i]||'\t'==s[i])
{
i++;
}
sign = ('-'==s[i])?-1:1;
if('-'==s[i]||'+'==s[i])
{
i++;
}
while(s[i]!='\0')
{
sum = s[i]-'0'+sum*10;
i++;
}
return sign*sum;
}
3.//字符串拷贝函数
#include "stdafx.h"
#include <assert.h>
#include <string.h>
#include <iostream>
using namespace std;
char *srcpy(char *dest,const char *source)
{
assert((dest!=NULL)&&(source!=NULL));
char *address = dest;
while(*source!='\0')
{
*dest++=*source++;
}
*dest = '\0';
return address;
}
4.//判断输入的是否是一个回文字符串
#include "stdafx.h"
#include <string.h>
#include <iostream>
using namespace std;
//方法一:借助数组
bool isPalindrome(char *input)
{
char s[100];
strcpy(s,input);
int length = strlen(input);
int begin = 0,end = length-1;
while(begin<end)
{
if(s[begin]==s[end])
{
begin++;
end--;
}
else
{
break;
}
}
if(begin<end)
{
return false;
}
else
{
return true;
}
}
//方法二:使用指针
bool isPalindrome2(char *input)
{
if(input==NULL)
return false;
char *begin = input;
char *end = begin+strlen(input)-1;
while(begin<end)
{
if(*begin++!=*end--)
return false;
}
return true;
}
int main(int argc, char* argv[])
{
char *s ="1234554321";
if(isPalindrome(s))
{
cout<<"True"<<endl;
}
else
{
cout<<"Fasle"<<endl;
}
if(isPalindrome2(s))
{
cout<<"True"<<endl;
}
else
{
cout<<"Fasle"<<endl;
}
cin.get();
return 0;
}
5.//不使用库函数,编写函数int strcmp(char *source, char *dest),若相等返回0,否则返回-1
int strcmp(char *source, char *dest)
{
assert(source != NULL && dest != NULL);
while(*source++==*dest++)
{
if(*source=='\0'&&*dest=='\0')
return 0;
}
return -1;
}
ret = strcmp("aa", "aa"); //0
ret = _stricmp("aa", "AA"); //0
ret = strcmp("aa", "aad"); //-1
strcmp(s1,s2)与_stricmp(s1,s2)
相同点:处理的都是C格式的字串,如果比较C++格式的string类型字串时,可以使用string.c_str()来转换成C格式的字串再进行比较。
不同点:1)前者区分大小写,后者不区分大小写
2)前者返回-1,0,1,后者返回字串实际差值,即整形数:负数,零,正数
二:strcpy_s&&strcpy的比较
如下所示:
char szBuf[2] = {0};
strcpy_s(szBuf, 2, "12131"); //注意第二个参数是申清空间的大小
strcpy(szBuf, "12131");
上述代码,明显有缓冲区溢出的问题。 使用strcpy_s函数则会抛出一个异常。而使用strcpy函数的结果
则未定,因为它错误地改变了程序中其他部分的内存的数据,可能不会抛出异常但导致程序数据错误,
也可能由于非法内存访问抛出异常。使用新的增强安全的CRT函数有什么好处呢?简单地说,新的函数
加强了对参数合法性的检查以及缓冲区边界的检查,如果发现错误,会返回errno或抛出异常。
老版本的这些CRT函数则没有那么严格的检查与校验,如果错误地传输了参数或者缓冲区溢出,
那么错误并不能被立刻发现,对于定位程序错误也带来更大困难。
//--------------------strcpy,strcpy_s------------------------------------------
//原型:extern char *strcpy(char *dest,char *src);
//功能:把src所指由NULL结束的字符串复制到dest所指的数组中。
//说明:src和dest所指内存区域不可以重叠且dest必须有足够的空间来容纳src的字符串,返回指向dest的指针。
//strcpy用法:
// 若源长<目标长 --->OK。
//将源串COPY至目标串(包括结尾符),其它字节保持不变,
//若源长>目标长 --->溢出报错。
//将源串COPY至目标串(包括结尾符),但目标串太短,下标越界而溢出,不正常的字串显然会在导致运行时异常,
//使用原则总结:使用时保证源长<目标长
//strcpy_s用法:
//若源长<目标长 sizeof([min, max])--->OK,但自定义拷贝的字串长度超过目标长度时,会因下标越界而导致运行异常
//若源长>目标长 sizeof任何一方都会发生运行异常,
//(有可能是编译器在copy前会先检查两者长度,
//如果源串较长便会发生告警而退出,因此后续使用sizeof(strlen(strDest)=0)语句已无效)
//使用原则总结: 1,使用时保证:源长<目标长,2,长度不能超出szDest长度,建议使用sizeof(szDest)
#include <iostream>
#include <string>
using namespace std;
#define STRCPY_TEST 0
#define LEN_STR 15
void main()
{
char szDest[10];
char szSrc_shorter[] = "1234";
char szSrc_longer[] ="123456789012";
cout<<"char szDest[10];"<<endl;
cout<<"char szSrc_shorter[] = \"1234\";"<<endl;
cout<<"char szSrc_longer[] = \"123456789012345\";"<<endl;
#if (0 == STRCPY_TEST)
cout<<"\n[OK] strcpy(szDest, szSrc_shorter);\nstrDest[1~15] = ";
strcpy(szDest, szSrc_shorter);
for(int i = 0; i < LEN_STR; i++)
{
cout<<szDest[i]<<", ";
}
cout<<endl<<"szDest = "<<szDest<<endl;
strcpy(szDest, szSrc_longer);
cout<<"\n[NG] strcpy(szDest, szSrc_longer);\nstrDest[1~15] = ";
for(int i = 0; i < LEN_STR; i++)
{
cout<<szDest[i]<<", ";
}
cout<<endl<<"szDest = "<<szDest<<endl;
#else
cout<<"\n[OK] strcpy_s(szDest, sizeof(szSrc_shorter), szSrc_shorter);\nstrDest[1~15] = ";
strcpy_s(szDest, sizeof(szSrc_shorter), szSrc_shorter);
for(int i = 0; i < LEN_STR; i++)
{
cout<<szDest[i]<<", ";
}
cout<<endl<<"szDest = "<<szDest<<endl;
cout<<"[OK] strcpy_s(szDest, sizeof(szDest), szSrc_shorter);\nstrDest[1~15] = ";
strcpy_s(szDest, sizeof(szDest), szSrc_shorter);
for(int i = 0; i < LEN_STR; i++)
{
cout<<szDest[i]<<", ";
}
cout<<endl<<"szDest = "<<szDest<<endl;
cout<<"[NG] strcpy_s(szDest, sizeof(szSrc_longer), szSrc_longer);\nstrDest[1~15] = ";
strcpy_s(szDest, sizeof(szSrc_longer), szSrc_longer);
for(int i = 0; i < LEN_STR; i++)
{
cout<<szDest[i]<<", ";
}
cout<<endl<<"szDest = "<<szDest<<endl;
cout<<"\n[NG] strcpy_s(szDest, sizeof(szDest), szSrc_longer);\nstrDest[1~15] = ";
strcpy_s(szDest, sizeof(szDest), szSrc_longer);
szDest[sizeof(szDest) - 1] = 0;
for(int i = 0; i < LEN_STR; i++)
{
cout<<szDest[i]<<", ";
}
cout<<endl<<"szDest = "<<szDest<<endl;
#endif
}
输出:(NG部分的输出已无意义,可以不看)
(1)STRCPY_TEST==0
char szDest[10];
char szSrc_shorter[] = "1234";
char szSrc_longer[] = "123456789012345";
[OK] strcpy(szDest, szSrc_shorter);
strDest[1~15] = 1, 2, 3, 4, , ? ? ? ? ? ? ? ? ? ?
szDest = 1234
[NG] strcpy(szDest, szSrc_longer);
strDest[1~15] = 1, 2, 3, 4, 5, 6, 7, 8, 9, 0, 1, 2, , ? ?
(2)STR_CPY_TEST<>0
char szDest[10];
char szSrc_shorter[] = "1234";
char szSrc_longer[] = "123456789012345";
[OK] strcpy_s(szDest, sizeof(szSrc_shorter), szSrc_shorter);
strDest[1~15] = 1, 2, 3, 4, , ? ? ? ? ? ? ? ? ? ?
szDest = 1234
[OK] strcpy_s(szDest, sizeof(szDest), szSrc_shorter);
strDest[1~15] = 1, 2, 3, 4, , ? ? ? ? ? ? ? ? ? ?
szDest = 1234
[NG] strcpy_s(szDest, sizeof(szSrc_longer), szSrc_longer);
strDest[1~15] = 1, 2, 3, 4, 5, 6, 7, 8, 9, 0, 1, 2, , ? ?
szDest = 123456789012
[NG] strcpy_s(szDest, sizeof(szDest), szSrc_longer);
strDest[1~15] = 请按任意键继续. . .
//-------------------------------memcpy-------------------------------------
// 原型:extern void *memcpy(void *dest, void *src, unsigned int count);
// 原理:由src所指内存区域复制count个字节到dest所指内存区域。
// 说明:src和dest所指内存区域不能重叠,函数返回指向dest的指针。
//strncpy() 是处理的字符串(遇零结束),
//memcpy() 是处理一个缓冲区(void*类型的),
//以字串类型的memcpy用法为例:
//源长<目标长时,第3个参数使用任何一方的size,效果都一样
//源长>目标长时,第3个参数用sizeof(strSrc),会造成下标越界,而使目标串溢出,从而导致运行异常
// 第3个参数用sizeof(strDest), 末尾字符(\0)没有被COPY,输出字串会有乱码,
// 但不会运行异常,如果不考虑完整性,可以使用strDest[sizeof(strDest)-1]=0截取前半部
//使用原则总结:1)保证源长<目标长;2)第3个参数推荐使用sizeof(strDest) 另外如果字串是指针要考虑一下sizeof的副作用
#include <iostream>
#include <string>
using namespace std;
void main()
{
char szSrc_shorter[] = "Good";
char szSrc_longer[] = "Have a Good Day!";
char szDest[10];
cout<<"char szSrc_shorter[] = \"Good\";"<<endl;
cout<<"char szSrc_longer[] = \"Have a Good Day!\";"<<endl;
cout<<"char szDest[10];"<<endl<<endl;
memcpy(szDest, szSrc_shorter, sizeof(szSrc_shorter));//<=>
//memcpy(szDest, szSrc_shorter, sizeof(szDest));
cout<<"[OK] memcpy(szDest, szSrc_shorter, sizeof(szSrc_shorter));";
cout<<"<=>\n[OK] memcpy(szDest, szSrc_shorter, sizeof(szDest));\nszDest[0~20] = \n";
for (int i = 0; i < 20; i++)
cout<<szDest[i]<<", ";
cout<<endl<<"szDest = "<<szDest<<endl;
memcpy(szDest, szSrc_longer, sizeof(szDest));
cout<<"\n[OK] memcpy(szDest, szSrc_longer, sizeof(szDest));\nszDest[sizeof(szDest) - 1] = 0; \nszDest[0~20] = \n";
szDest[sizeof(szDest) - 1] = 0;
for (int i = 0; i < 20; i++)
cout<<szDest[i]<<", ";
cout<<endl<<"szDest = "<<szDest<<endl;
memcpy(szDest, szSrc_longer, sizeof(szSrc_longer));
cout<<"\n[NG] memcpy(szDest, szSrc_longer, sizeof(szSrc_longer));\nszDest[sizeof(szDest) - 1] = 0; \nszDest[0~20] = \n";
szDest[sizeof(szDest) - 1] = 0;
for (int i = 0; i < 20; i++)
cout<<szDest[i]<<", ";
cout<<endl<<"szDest = "<<szDest<<endl;
}
输出:(NG部分的输出没有意义,可以不看):
char szSrc_shorter[] = "Good";
char szSrc_longer[] = "Have a Good Day!";
char szDest[10];
[OK] memcpy(szDest, szSrc_shorter, sizeof(szSrc_shorter));<=>
[OK] memcpy(szDest, szSrc_shorter, sizeof(szDest));
szDest[0~20] =
G, o, o, d, , ?.....?(15个?)
szDest = Good
[OK] memcpy(szDest, szSrc_longer, sizeof(szDest));
szDest[sizeof(szDest) - 1] = 0;
szDest[0~20] =
H, a, v, e, , a, , G, o, , ? ...?(10个?)
szDest = Have a Go
[NG] memcpy(szDest, szSrc_longer, sizeof(szSrc_longer));
szDest[sizeof(szDest) - 1] = 0;
szDest[0~20] =
H, a, v, e, , a, , G, o, , d, , D, a, y, !, , ? ? ?
szDest = Have a Go