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

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

1.5 strncpy🎁

char * strncpy ( char * destination, const char * source, size_t num );

  • 拷贝num个字符从源字符串到目标空间。
  • 如果源字符串的长度小于num,则拷贝完源字符串之后,在目标的后边追加0,直到num

22441fa0356f4f4eaa2723308edf3c4d.png

整体区别其实就比strcpy多了一个参数(size_t num)限制。

这里要注意的是,如果需要拷贝的个数大于整体的源字符串的大小,那么拷贝的时候不够就用'\0'或者0来补充

int main()
{
  char arr1[] = "abcdef";
  char arr2[20] = "xxxxx";
  strncpy(arr2,arr1,20);
  printf("%s\n", arr2);
  return 0;
}


5191fc755f154fdf9eef0d7687dfb48c.png

因为arr1(源字符串)整体大小是6+1=7(它包含的'\0'), 所以补的时候只需要补三个'\0'就行了

个人认为:

只需要看要拷贝的那个个数是多少,然后把源字符串加上'\0'的总体个数相减就行

也就是10-(6+1)=3,所以要补的'\0'个数就是 3个


1.6 strncat💨

char * strncat ( char * destination, const char * source, size_t num );

f281763baca448c7a7efdd3654061b29.png


1.6.1strncat的正常调用

#include<stdio.h>
#include<string.h>
int main()
{
  char arr1[20] = "hello \0xxxxxxxxxxxx";
  char arr2[] = "abcdef";
  strncat(arr1, arr2, 10);
  printf("%s\n", arr1);
  return 0;
}


可以看到拷贝前的状况:

85134117c42c4a03ad84b81f1db1a023.png

拷贝之后:

这个函数的情况其实时,你让我追加几个就追加几个,追加完之后我就会在后面再补一个'\0',也不会多拷贝数据

279ecd75e19a4e328f6c12652c09f602.png

总结:追加的时候源字符串只有7个字符(6+1),这里已经包括’\0’了,那就停止了,并不会多拷贝’\0'


1.6.2模拟实现strncat💫

记住拷贝完字符串在后面补一个'\0'即可。

#include<stdio.h>
#include<assert.h>
int main() {
  char arr1[20] = "hello \0xxxxxxxxxxxx";
  char arr2[] = "abcdef";
  int n = 0;
  scanf("%d", &n);
  char* p = arr1;
  char* q = arr2;
  assert(arr1); 
  assert(arr2);
  while (*p)
  {
    p++;
  }
  while (n--) {
    *p = *q;
    p++;
    q++;
  }
  *p = '\0';
  printf("%s",arr1);
  printf("\n");
}


关于strncat模拟实现不多说了,毕竟下面的自己追加自己的情况才是重点

c94e5fa7568a49f588abf3d00c317ad2.png


模拟实现strncat,自己追加自己的情况💦

#include<stdio.h>
#include<assert.h>
int main() {
  char arr1[20] = "hello \0xxxxxxxxxxxx";
  int n = 0;
  scanf("%d", &n);
  char* p = arr1;
  char* q = arr1;
  assert(arr1); 
  while (*p)
  {
    p++;
  }
  while (n--) {
    *p = *q;
    p++;
    q++;
  }
  *p = '\0';
  printf("%s",arr1);
  printf("\n");
}

863b0fd42245453496003e2296dc25ba.png

图解:

37f1b10f195246908098b59d60a16d91.png

上面的第一个图是p指针和q指针初始化的位置

第二个图它们的最终位置


个人理解:

到n--成0的时候,假设拷贝三次,到第三个字符的时候,q指针最终还是会走一下

因为这是模拟实现库函数,是方便理解库函数的实现逻辑的

也就是q指针的最终位置,所以说库函数也是这样,strncat,是会把q指针的最终位置改成'\0'的


关于everything:

提示打开,everything的时候可以观察到以上库函数的代码实现,但这不是源代码,是参考代码

8450911bd18040a7be330ec778c2a98e.png

像这样把上面的.c文件直接拖拽过来即可。

3976c4331c9a4e34bcbc5829f60d14f1.png


1.7 strncmp

int strncmp( const char * str1, const char * str2, size_t num);

db1969df8daa44858b2dfb0217fae0d4.png

strncmp的正常操作

#include<stdio.h>
int main()
{
  char arr1[] = "abcdefadawdawfwa";
  char arr2[] = "abcq";
  int ret = strncmp(arr1, arr2, 8);
  printf("%d\n", ret);
  return 0;
}


d0db6d5d8a9a4826b497b0801d267bf4.png


个人理解:

如果n(要拷贝的个数)比str1或者str2其中一个要大,或者比两个都要大,那就找最短的字符串,比完就ok了


1.8 strstr

char * strstr ( const char *str1, const char * str2);

e7b6db10bcf546f1af00d573cd61b0df.png

#include<stdio.h>
int main()
{
  char arr1[] = "abcdefgh";
  char arr2[] = "de";
  char* p = strstr(arr1, arr2);
  if (p == NULL)
  {
    printf("找不到\n");
  }
  else
  {
    printf("%s\n", p);
  }
  return 0;
}

找到了:

60547a5a273f49d7956b897346102632.png

找不到:

f604867b6f0641729d472c9370fe0056.png


1.8.1strstr的模拟实现❗❗❗

前提准备:

str1和str2是用来记录初始位置的,而s1和s2是借助遍历字符串的

cp呢是匹配成功的时候返回匹配成功的字符串的指针。

总共就五个指针,只有三个是要用到的分别是s1,s2和cp。

#include<stdio.h>
char* my_strstr(const char* str1, const char* str2)
{
  char* s1 = NULL;
  char* s2 = NULL;
  char* cp = (char*)str1;//匹配成功的时候返回匹配成功的字符串的指针,跟下面的那个str2一样的情况
  while (*cp)
  {
    s1 = cp;
    s2 = (char*)str2;//编译器报警阿,把一个相对安全的指针交给一个不安全的指针,这个权限是放大了
    while (*s1 && *s2 && *s1 == *s2)
    {
      s1++;
      s2++;
    }
    if (*s2 == '\0')
    {
      return cp;
    }
    cp++;
  }
  return NULL;
}
int main()
{
  char arr1[] = "abcdebcdf";
  char arr2[] = "bcd";
  char* p = my_strstr(arr1, arr2);
  if (p == NULL)
  {
    printf("找不到\n");
  }
  else
  {
    printf("%s\n", p);
  }
  return 0;
}


执行:

016803017fd94ca39ab19f49b43378a8.png

图解:根据代码配合图理解即可。两图的指针指向情况均为它们的最终位置!

1.最基本的匹配情况:

9996c928d37a436abc450f9d9c1fcef7.png

2.上难度了

41acb266dd774a2294a5256f06c9d18a.png

一点小疑惑:❓

1.为什么不拿str1和str2走?

str1和str2是用来记住起始位置的,当两者走远的时候,想回到起始位置,就没有人知道起始位置在哪里了,就借助s1和s2来往后遍历字符即可

2.*s1存在的必要性,有必要吗?

14e9fed9eb3d4dbcb4ba15a489e3b57d.png

有必要:

比如说

aabcdefgh和bcd

s1肯定是比s2指向的字符串长对不对,但是如果你手动去干预,aabc\0defgh

while(*s1)这个条件就有存在的必要,加上*s1 只是咱们更加严格一点


3.这个while(*cp)循环又是干啥的?

如果匹配成功 就直接返回cp了

但是如果没有 就要从str1后面一位继续开始匹配

简单来说:

如果匹配成功了,这个只用走一遍

进入循环,出去循环

如果一次匹配失败

进入循环,再进入循环,再进入循环.........出去循环,直到匹配成功为止

接下来还有下半章的知识,欢迎各位大佬的指导和补充!

相关文章
|
编译器 C++
【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语言进阶字符函数和字符串函数(下)
38 0
|
C语言
C语言进阶字符函数和字符串函数(上)
C语言进阶字符函数和字符串函数(上)
69 0
|
算法 编译器 C语言
【C进阶】字符串函数
【C进阶】字符串函数
65 0
|
编译器 C语言
【C进阶】-- 字符串函数(1)(上)
【C进阶】-- 字符串函数(1)(上)