【C进阶】-- 字符串函数(1)(中)

简介: 【C进阶】-- 字符串函数(1)(中)

4.目标空间不能被修改

#include<stdio.h>
#include<string.h>
int main()
{
  char* p = "abcdefghi";
  char arr2[] = "hehe\n";
  strcpy(p, arr2);//这也是一样错的示范 - 目标空间必须可以修改
  printf("%s\n", p);
   return 0;
}


aabdd9896f174a108b3cbf94fac5bbf4.png


1.2.1学会strcpy模拟实现:💎

 strcpy的模拟实现:函数返回类型是char*,把源头的数据拷贝到目标空间之后,整个目标空间发生变化,把目标空间的地址返回来。要感知函数的变化,返回目标空间的地址是比较合适的。

278ec57813ec4271bf8f307515c05cd0.png

对于ret来说,返回的时候。arr2数组是一段连续的空间,所以返回首元素地址,后面就紧跟的是后序元素

#include<stdio.h>
#include<string.h>
char* my_strcpy(char* dest, const char* src)//加上const对源头的数据进行保护
{
  char* ret = dest;
  assert(dest && src);
  while (*dest++ = *src++)
  {
    ;
  }
  return ret;//数组是一段连续的空间,所以返回首元素地址,后面就紧跟的是后序元素
}
int main()
{
  char arr1[] = "hehe";
  char arr2[20] = { 0 };
  my_strcpy(arr2, arr1);
  printf("%s\n",arr2);
  return 0;
}

合2为1写法🏈

char* my_strcpy(char* dest, const char* src)

{

   char* ret = dest;

   assert(dest && src);

   while (*dest++ = *src++)

   {

       ;

   }

   return ret;

}

int main()

{

   char arr1[] = "hehe";

   char arr2[20] = { 0 };

   printf("%s\n", my_strcpy(arr2, arr1));//合2为1

   return 0;

}  


1.3 strcat

char * strcat( char * destination, const char * source);

a212f7d8e2774d2392069835140ca9e5.png

注意:拷贝(strcpy)的意思是覆盖掉,与追加不一样, strcat也就是追加的时候第一个字符是把'\0'给覆盖掉,之后在拷贝完后加上一个‘\0’即可。

#include<stdio.h>
int main()
{
  char arr1[20] = "hello \0xxxxxxxxxxx";
  char arr2[] = "world";
  strcat(arr1, arr2);//会以\0为起始位置拷贝
  printf("%s\n", arr1);
}
  • 源字符串必须以 '\0' 结束。
  • 目标空间必须有足够的大,能容纳下源字符串的内容。
  • 目标空间必须可修改。

7d25befd1e8349709fb4d75dc55a2e0a.png


1.3.1模拟实现strcat🏐

模拟实现的图解:

30f1879825d640a8817a9b6a01e4f8d1.png

#include<assert.h>
#include<stdio.h>
char* my_strcat(char* dest, const char* src)
{
  assert(dest && src);
  char* ret = dest;
//找目标空间的'\0'
  while (*dest != '\0')
  {
    dest++;
  }
  //拷贝
  while (*dest++ = *src++)
  {
    ;
  }
  return ret;
}
int main()
{
  char arr1[20] = "hello ";
  char arr2[] = "world";
  //追加
  my_strcat(arr1, arr2);
  printf("%s\n", arr1);
   return 0; 
}

4974aa2c378c4e44b34ccb6d7c55893e.png

返回值问题?

4f21879c48dd48bdadd2974d3da06185.png

注意问题:

只是它的返回值这里没有使用到而已,库函数是有返回值的,因为有些场景下 ,我们需要用到字符串的首地址

可以理解为:我可以不用,但是应该有, 因为这是关于这个strcat的模拟实现,是对于它的库函数的一种理解,所以说它的库函数也可能会这样使用。


1.3.2strcat自己对自己追加🎈

会陷入死循环, 这种情况是不能用strcat的,要用的是strncat!

#include<stdio.h>

#include<assert.h>

char* my_strcat(char* dest, const char* src)

{

   assert(dest && src);

   char* ret = dest;

   while (*dest != '\0')

   {

       dest++;

   }

   //拷贝

   while (*dest++ = *src++)

   {

       ;

   }

   return ret;

}

int main()

{

   char arr1[20] = "bit";

   my_strcat(arr1, arr1);

   printf("%s", arr1);


  return 0;

}

图解:

c390118fbf55427eb7d5c9fc6bac55b1.png

注意const char*src:

不会通过src来改变里面空间的数据,但是把src指向的内容放进dest指向的空间里面去了

因为dest指针没有受到限制,是不能通过src来改变这块空间的数据,并不意味着这块空间不能被改变,数组内容还是可以被改变的.

src本身是改变了,是因为src的指向在发生变化,这块空间,是通过dest去改变的

b771ed8cad0040889abf93f8735c8c14.png


1.4 strcmp

 这里比较的是2个字符串的内容的时候,不能使用 == ,应该使用strcmp;

char* p = "abcdef";//因为"abcdef"把这个表达式首字符'a'的地址给了p指针,所以这个表达式的值是'a'的地址


//这里下面比的其实是"abcdef"的'a'的地址和"bbcdef"的'b'的地址是否相等,并没有比较内容


   if ("abcdef" == "bbcdef")//这里比较的是两个字符串首字符的地址,而不是字符串内容

   {


   }


前提

:首先说明这个函数strcmp实现两个字符串的比较的时候是跟长度不存在对应的关系,并不是谁长谁就大!

int strcmp ( const char * str1, const char * str2 );

4bf0260d245e4d13b2060fd47374604a.png

举例:

"abcdef"

"bbq"

这两个字符串,上面长,下面短,对应位置的字符比较,根据ascll码值,a是小于b,所以

bbq大于abcdef

总结:

当对应位置的字符比较时,,如果相等就跳过一个字符比较,当它们不相等时,ascll码值的大整个字符串就大,与长度无关

再举例:

"abcdef"

"abbbbbbbbb"

因为'c'的ascll码值大于'b',所以"abcdef"大


标准规定:

  1. 第一个字符串大于第二个字符串,则返回大于0的数字
  2. 第一个字符串等于第二个字符串,则返回0
  3. 第一个字符串小于第二个字符串,则返回小于0的数字


正常代码操作:

#include<stdio.h>
#include<string.h>
int main()
{
  //跟长度没关系. 
  char arr1[] = "abcdef";
  char arr2[] = "bbq";
  int ret = strcmp(arr1, arr2);
  printf("%d\n", ret);
  return 0;
}

d9178e92e85f4a17b9c0004040b10482.png

arr1<arr2,所以返回-1;


1.4.1strmpy的模拟实现📌

#include<stdio.h>
int my_strcmp(const char* str1, const char* str2)
{
  while (*str1 == *str2)
  {
    if(*str1=='\0')
          return 0;
    str1++;
    str2++;
     }
  if (*str1 > *str2)
    return 1;
  else
    return -1;
}
int main()
{
  char arr1[] = "abzqb";
  char arr2[] = "abq";
  int ret = my_strcmp(arr1, arr2);
  printf("%d\n", ret);
  return 0;
}


写成(const char* str1, const char* str2)的原因:

str1和str2不会去修改原字符串的内容,只是比较它们的大小,所以只要能拿到这个字符串内容就可以了。


函数实现部分也可以写成:👓

#include<stdio.h>

int my_strcmp(const char* str1, const char* str2)

{

   while (*str1 == *str2)

   {

       if(*str1==*str2)

       str1++;

       str2++;

    }

   return *str1 - *str2;//ascllm码值相减


}


主函数部分也可以写成:👓

int main()

{

   char arr1[] = "abzqw";

   char arr2[] = "abq";


//这里不能写成 if (strcmp(arr1, arr2) == 1),vs这个环境底下大于返回1,其它的平台有可能返回其它大于0的数字,所以不能这样写


               ⬇⬇⬇


//要写成这样

   if (strcmp(arr1, arr2) > 0)

       printf(">\n");

   else if (strcmp(arr1, arr2) == 0)

       printf("=\n");

   if (strcmp(arr1, arr2) <0)

       printf("<\n");

   return 0;

}


整体来说:

strcpy,strcat,strcmp这三种函数,是长度不受限制的字符串函数,以及scanf这些函数在vs等高版本系列的编译器看来都是不安全的,原因是:arr2太小放不下,程序崩溃

#include<stdio.h>
int main()
{
  char arr1[] = "abcdef";
  char arr2[5] = { 0 };
  strcpy(arr2, arr1);
  printf("%s\n", arr2);
  return 0;
}


262d25176a4241adbb102a6e63675c7b.png

所以为了解决这种不安全,引入了一系列的长度受限制的字符串函数strncpy,strncat,strncmp;

相关文章
【C进阶】-- 字符串函数(1)(下)
【C进阶】-- 字符串函数(1)(下)
|
算法 C++
C基础知识(字符串函数)
C基础知识(字符串函数)
47 0
|
1月前
|
C语言
C语言常见字符函数和字符串函数精讲
C语言常见字符函数和字符串函数精讲
|
5月前
|
存储 编译器 C语言
C primer plus 学习笔记 第11章 字符串和字符串函数
C primer plus 学习笔记 第11章 字符串和字符串函数
|
6月前
|
Go C语言
【C语言】字符+字符串函数精讲
【C语言】字符+字符串函数精讲
|
6月前
|
C语言 存储 编解码
C语言(进阶)—字符函数和字符串函数
C语言(进阶)—字符函数和字符串函数
|
C语言
C语言进阶字符函数和字符串函数(上)
C语言进阶字符函数和字符串函数(上)
69 0
|
C语言
C语言进阶字符函数和字符串函数(下)
C语言进阶字符函数和字符串函数(下)
38 0
|
算法 编译器 C语言
【C进阶】字符串函数
【C进阶】字符串函数
65 0
|
编译器 C语言
【C进阶】-- 字符串函数(1)(上)
【C进阶】-- 字符串函数(1)(上)