strcpy函数
char* strcpy(char* dst, const char* src)
{
if ((dst == NULL) || (src == NULL))
return NULL;//如果有空指针存在,返回空指针
char* ret = dst; //【1】设置返回值,返回接收数组的地址
while ((*dst++ = *src++) != '\0'); //【2】通过地址使得接收数组收到原数组的元素
return ret;//【3】
}
(1)const 修饰:源字符串参数用const修饰,防止修改源字符串;
(2)空指针检查:源指针和目的指针都有可能会出现空指针的情况,所以应该对其进行检查;
(3)为什么要设置ret 指针以及返回ret指针的位置[3],由于目的指针dst已经在进行移动了,所以用辅助指针ret表明首指针;
(4)以上所示[2]处,为简单的字符串的复制过程,正好表明strcpy函数遇到'\0'将会停止;
复现实例
char* my_strcpy(char* dest, char* scr)//传首元素地址,返回值为接收数组的地址
{
assert(dest != NULL);//引用头文件<assert.h>
assert(scr != NULL);//保证传递的不是空指针
char* ret = dest; //设置返回值
while (*scr != '\0')//当解引用地址后得到的不是‘\0’时执行while循环
{
*dest++ = *scr++;//解引用scr数组的首元素地址,取得首元素,存放到dest数组的首元素地址
}
*dest = *scr;//scr读取到‘\0’的地址,将\0存放到dest对应位置
return ret;
}
int main()
{
char arr1[] = "abcdefg";
char arr2[] = "get";
my_strcpy(arr1, arr2);
printf("%s\n", arr1);
return 0;
}
字符串函数通常使用字符串末尾的\0进行操作。
strcat函数
int main()
{
char arr1[] = "abcdefg";
char arr2[] = "get";
strcat(arr1, arr2);
printf("%s\n", arr1);
return 0;
}
会产生报错,将源数组arr2追加到目的地数组arr1时,会造成arr1数组的溢出。只需设置arr1数组大小即可解决。
复现实例
char* my_strcat(char* dest, char* scr)
{
assert(dest != NULL);
assert(scr != NULL);
char* ret = dest;
while (*dest != '\0')
{
*dest++;
}
while (*scr != '\0')
{
*dest++ = *scr++;
}
*dest = *scr;
return ret;
}
int main()
{
char arr1[] = "abcdefg";
char arr2[] = "get";
my_strcat(arr1, arr2);
printf("%s\n", arr1);
return 0;
}
函数执行前arr1
函数执行后arr1
strcmp函数
strcmp() 函数用于对两个字符串进行比较(区分大小写),比较的ASCII值,而非长度。
语法/原型:
int strcmp(const char* stri1,const char* str2);
参数 str1 和 str2 是参与比较的两个字符串。
strcmp() 会根据 ASCII 编码依次比较 str1 和 str2 的每一个字符,直到出现不到的字符,或者到达字符串末尾(遇见\0)。
返回值:
如果返回值 < 0,则表示 str1 小于 str2。
如果返回值 > 0,则表示 str2 小于 str1。
如果返回值 = 0,则表示 str1 等于 str2。
注意,C语言标准并没有具体规定 strcmp() 函数的返回值是多少,大多数编译器选择了以下两种方案:返回两个字符串的差值,即找到两个字符串中首个不相等的字符,然后返回这两个字符的差值; 返回 -1、0 或者 +1;
实例
int main()
{
const char* p1 = "abcde";
const char* p2 = "abcdef";
int ret = strcmp(p1, p2);
printf("%d\n", ret);
return 0;
}
结果为-1
int main()
{
const char* p1 = "abcde";
const char* p2 = "aacde";
int ret = strcmp(p1, p2);
printf("%d\n", ret);
return 0;
}
结果为1
复现实例
int my_strcmp(const char* str1, const char* str2)
{
assert(str1 && str2);
while (*str1 == *str2)
{
if (*str1 == '\0')
{
return 0;
}
str1++;
str2++;
}
if (*str1 > *str2)
return 1;
else
return -1;
}
int main()
{
const char* p1 = "abcde";
const char* p2 = "aacde";
int ret = my_strcmp(p1, p2);
printf("%d\n", ret);
return 0;
}
注意const char*接收的为用常量修饰的字符数组,即字符内容无法修改。
strncpy函数
逐个字符赋值
int main()
{
char arr1[10] = "abcdef";
char arr2[] = "ooo";
strncpy(arr1, arr2, 2);
printf("%s\n", arr1);
return 0;
}
oocdef
为了防止dest数组溢出,可以将scr数组元素按地址逐个赋值给dest数组,此例中仅复制前两个元素,scr数组内显然有4个元素。当更改n值为4时
ooo
内存使用情况
可见,此函数再超出源数组大小时,会对超出的部分补充“\0".
strncat函数
int main()
{
char arr1[10] = "abcdef";
char arr2[] = "ooo";
strncat(arr1, arr2, 2);
printf("%s\n", arr1);
return 0;
}
abcdefoo
与strncpy类似,逐字符追加。
复现实例
char* my_strncat(char* str1, const char* str2, int size) {
int n = strlen(str1);
int i = 0;
while (*(str1++ + n + i) = *(str2++ + i)) {
if (i == size) {
*(str1 + n + i) = 0;
break;
}
}
return str1;
}
int main() {
char str1[12] = "abcde";
char str2[] = "fghijk";
printf("str1为:\n%s\n", str1);
printf("str2为:\n%s\n", str2);
my_strncat(str1, str2, 6);
printf("str1连接str2后为:\n%s\n", str1);
system("pause");
return 0;
}
char* my_strncat(char* str1, const char* str2, int size)
{
int n = strlen(str1);
int i = 0;
while (*(str1++ + n + i) = *(str2++ + i))
{
if (i == size)
{
*(str1 + n + i) = 0;
break;
}
}
return str1;
}
此函数较简单,此处略过。
strncmp函数
int my_strncmp ( const char* str1, const char* str2, size_t num )
{
assert(str1 && str2);
if(!num)return 0;
while(--num && *str1 && (*str1 == *str2))
{
str1++;
str2++;
}
return *str1 - *str2;
}