【c语言】模拟实现字符串函数(上)

简介: 【c语言】模拟实现字符串函数(上)

C语言中对 字符串 的处理很是频繁,C语言本身是没有字符串类型,但有字符类型,字符串通常放在 常量字符串 中或者 字符数组 中。


字符串常量:适用于那些不做修改的字符串函数,因为字符串常量是常量,常量是不允许被修改的,它存放在常量区。

q1.png



1.模拟实现strlen

1.1函数介绍

strlen:求字符串长度


注:字符串以 \0 作为字符串结束标志,strlen 函数返回的是 \0 之前的字符个数,不包含 \0


1.2函数的模拟实现

q2.png


我们既然要模拟实现 strlen 函数,就得模拟的像一点,我们可以通过查询找到 strlen 函数的形式,通过查找,我们可以发现函数的参数是一个字符指针类型,返回值是 size_t (无符号整型)


#include<stdio.h>
#include<assert.h>
size_t my_strlen(const char* str)
{
  assert(str != NULL);
  size_t ret = 0;
  while (*str++ != '\0')
  {
  ret++;
  }
  return ret;
}
int main()
{
  char arr[] = "abcdef";
  int ret = my_strlen(arr);
  printf("%d\n", ret);
  return 0;
}

分析:函数参数前面加上 const  是避免误改字符串,因为我们只需要计算它的长度不需要改变。返回值为 size_t 因为长度不可能为负数,所以设为 size_t 最合理。*str++ != '\0' 的运算:首先先对 str 解引用找到对应的字符然后与 \0 比较,如果不等于 \0 就 str++ 指向下一个字符,然后依次循环,直到 *str 等于 \0 然后跳出。


2.模拟实现strcpy

2.1函数介绍

strcpy:字符串拷贝函数,将一个字符串的内容拷贝到另一个字符串中


2.2函数模拟实现


q3.png

通过查询 strcpy 函数,我们可以发现 strcpy 函数有两个参数分别都是指针类型,第一个指针指向的是目标空间,第二个指针指向的是源字符串,我们要把源字符串拷贝到目标空间中,所以目标空间要足够大,能存储的下源字符串,并且可修改。


#include<stdio.h>
#include<assert.h>
char* my_strcpy(char* dest, const char* source)
{
  assert(dest != NULL);
  assert(source != NULL);
  char* ret = dest;
  while (*dest++ = *source++)
  {
  ;
  }
  return ret;
}
int main()
{
  char arr1[20] = { 0 };
  char arr2[] = "abc";
  my_strcpy(arr1, arr2);
  printf("%s\n", arr1);
  return 0;
}


分析:返回类型是 char*,我们用一个字符指针变量指向目标首地址,为了避免 dest 在后面指向的时候会改变指向的位置。把 *source 里面的字符 赋给 *dest ,然后在进行 while 判断,如果不为 \0 就后置++。


思考:在字符串拷贝的时候会把源字符串的 ‘\0’ 拷贝进去嘛?


q4.png


通过调试,我们可以知道拷贝时会把 ‘\0’ 拷贝进去。


3.模拟实现strcat

3.1函数介绍

strcat:字符串追加函数,将一个字符串追加到另一个字符串的后面


3.2函数模拟实现

w1.png


通过查询 strcat 函数,我们可以发现 strcat 函数有两个参数分别都是指针类型,第一个指针指向的是目标空间,第二个指针指向的是源字符串,我们要把源字符串追加到目标空间中,所以目标空间要足够大,能存储的下追加的源字符串,并且可修改。


#include<stdio.h>
#include<assert.h>
char* my_strcat(char* dest, const char* source)
{
  assert(dest != NULL);
  assert(source != NULL);
  char* ret = dest;
  while (*dest != '\0')
  {
  dest++;
  }
  while (*dest++ = *source++)
  {
  ;
  }
  return ret;
}
int main()
{
  char arr[20] = "abc";
  char brr[] = "def";
  my_strcat(arr, brr);
  printf("%s\n", arr);
  return 0;
}

分析:找到目标空间 '\0' 的位置,然后将源字符串的字符依次追加到目标空间里面,目标空间的 ‘\0’ 是会被替换掉的,直到源字符串赋值到 ‘\0’ 给目标空间就结束追加。


思考:字符串可以自己给自己追加嘛?

w2.png



结论:strcat 不可以自己给自己追加,因为一旦自己给自己追加就改变了 '\0',那么就一直追加下去,程序就会造成死循环。


4.模拟实现strcmp

4.1函数介绍

strcmp:字符串比较函数,是用来比较两个字符串大小的函数。


很多人会误以为字符串比较跟整型比较的方法一样,这是不正确的

w3.png



结论:上述代码充分证明了,字符串不能跟整型数据一样比较,那字符串与字符串怎么比较呢,字符串与字符串用 strcmp 函数来比较。


4.2函数模拟实现

w4.png


函数参数是两个指针,分别指向着两个需要比较的字符串,因为只需要比较不需要改变,所以前面加上了 const 。返回值为 int ,第一个字符串大于第二个字符串,则返回大于 0 的数字;第一个字符串等于第二个字符串,则返回0;第一个字符串小于第二个字符串,则返回小于0的数字。


#include<stdio.h>
#include<assert.h>
int my_strcmp(const char* str1, const char* str2)
{
  assert(str1 != NULL);
  assert(str2 != NULL);
  while (*str1 == *str2)
  {
  if (*str1 == '\0' && *str2 == '\0')
  {
    return 0;
  }
  str1++;
  str2++;
  }
  return *str1 - *str2;
}
int main()
{
  char arr[] = "abcdef";
  char brr[] = "abc";
  int ret = my_strcmp(arr, brr);
  if (ret > 0)
  {
  printf(">\n");
  }
  else if (ret == 0)
  {
  printf("==\n");
  }
  else
  {
  printf("<\n");
  }
  return 0;
}

分析:首先如果*str1 == *str2 ,就进入循环判断它们是否都为 '\0' ,如果是说明它们两个都结束了,且相等,那么就返回 0。否则就 str1++,str2++ 比较下一个字符是否相等,如果不相等就直接退出循环,返回 *str1 - *str2,如果返回的结果为负数,说明 *str1 小于 *str2,否则大于。

5.模拟实现strstr

5.1函数介绍

strstr:在一个字符串中找子串,例如 “abcdef”,找子串“def”,如果 “def” 在这个字符串中,则返回在这个字符串中找到子串的第一个字符的地址。


5.2函数的模拟实现

e1.png


函数参数分别是两个字符指针类型,分别指向了两个字符串,第二个字符串叫做子串,就在第一个字符串中找子串,如果找到则返回在第一个字符串中查找的子串的第一个字符的地址。


#include<stdio.h>
#include<assert.h>
char* my_strstr(const char* str1, const char* str2)
{
  assert(str1 && str2);
  char* s1 = str1;
  char* s2 = str2;
  char* p = str1;
  while (*p)
  {
  s1 = p;
  s2 = str2;
  while (*s1 == *s2 && *s1 != '\0' && *s2 != '\0')
  {
    s1++;
    s2++;
  }
  if (*s2 == '\0')
  {
    return p;
  }
  p++;
  }
  return NULL;
}
int main()
{
  char arr[] = "abcdefg";
  char brr[] = "def";
  char* ret = my_strstr(arr, brr);
  printf("%s\n", ret);
  return 0;
}

情况一:直接找到,然后对 s1 和 s2 解引用 比较,当 *s2 == '\0' 时,说明查找完毕,找到了。如果找不到,当 *p == ‘\0’ 退出循环,也就说明没有找到。


e2.png


情况二:找多次找到,第一次找到了 ' b'  ,*s1 和 *s2 都是 'b',当 s1++ 和 s2++,解引用然后它们里面的字符不相同了。然后 p 指向下一个字符,s1 = p ,s2 回到它第一个字符的位置,然后在找到与 s2 相同的字符然后在比较,直到 *s2 == '\0' 时,说明查找完毕,找到了。如果找不到,当 *p == ‘\0’ 退出循环,也就说明没有找到。


e3.png


6.了解strtok

6.1函数介绍

strtok:字符串分割函数


6.2函数使用

e4.png


delimiters 参数是个字符串,定义了用作分隔符的字符集合。

第一个参数指定一个字符串,它包含了0个或者多个由 delimiters 字符串中一个或者多个分隔符分割的标记。

strtok函数找到str中的下一个标记,并将其用 \0 结尾,返回一个指向这个标记的指针。(注: strtok函数会改变被操作的字符串,所以在使用strtok函数切分的字符串一般都是临时拷贝的内容 并且可修改。)

strtok函数的第一个参数不为 NULL ,函数将找到str中第一个标记,strtok函数将保存它在字符串 中的位置。

strtok函数的第一个参数为 NULL ,函数将在同一个字符串中被保存的位置开始,查找下一个标 记。

如果字符串中不存在更多的标记,则返回 NULL 指针。

#include <stdio.h>
#include <string.h>
int main()
{
  char *p = "I.LOVE@YOU";
  const char* sep = ".@";
  char arr[30];
  char *str = NULL;
  strcpy(arr, p);//将数据拷贝一份,处理arr数组的内容
  for (str = strtok(arr, sep); str != NULL; str = strtok(NULL, sep))
  {
  printf("%s\n", str);
  }
}

7.了解strerror

7.1函数介绍

strerror:返回错误码,所对应的错误信息。


7.2函数使用

#include <stdio.h>
#include <string.h>
#include <errno.h>//必须包含的头文件
int main()
{
  FILE * pFile;
  pFile = fopen("aaa.txt", "r");
  if (pFile == NULL)
  printf("Error opening file unexist.ent: %s\n", strerror(errno));
  //errno: Last error number
  return 0;
}

目前我没有创建 aaa.txt 文件,这个程序就会将错误码转换为错误信息打印出来。

e5.png



相关文章
|
1月前
|
C语言 C++
【C语言】解决不同场景字符串问题:巧妙运用字符串函数
【C语言】解决不同场景字符串问题:巧妙运用字符串函数
|
25天前
|
存储 C语言
【c语言】字符串函数和内存函数
本文介绍了C语言中常用的字符串函数和内存函数,包括`strlen`、`strcpy`、`strcat`、`strcmp`、`strstr`、`strncpy`、`strncat`、`strncmp`、`strtok`、`memcpy`、`memmove`和`memset`等函数的使用方法及模拟实现。文章详细讲解了每个函数的功能、参数、返回值,并提供了具体的代码示例,帮助读者更好地理解和掌握这些函数的应用。
21 0
|
1月前
|
存储 安全 编译器
深入C语言库:字符与字符串函数模拟实现
深入C语言库:字符与字符串函数模拟实现
|
1月前
|
C语言
C语言常见字符函数和字符串函数精讲
C语言常见字符函数和字符串函数精讲
|
1月前
|
C语言
【C语言】模拟实现深入了解:字符串函数
【C语言】模拟实现深入了解:字符串函数
|
3月前
|
安全 程序员 C语言
【C语言】字符串函数及其模拟实现
【C语言】字符串函数及其模拟实现
|
3月前
|
C语言
【C语言篇】字符和字符串以及内存函数详细介绍与模拟实现(下篇)
perror函数打印完参数部分的字符串后,再打印⼀个冒号和⼀个空格,再打印错误信息。
62 0
|
3月前
|
存储 安全 编译器
【C语言篇】字符和字符串以及内存函数的详细介绍与模拟实现(上篇)
当然可以用scanf和printf输入输出,这里在之前【C语言篇】scanf和printf万字超详细介绍(基本加拓展用法)已经讲过了,这里就不再赘述,主要介绍只针对字符的函数.
55 0
|
4月前
|
存储 缓存 C语言
【C语言】字符函数,字符串函数,内存函数
C语言中的字符串函数和内存函数
54 0
【C语言】字符函数,字符串函数,内存函数
|
5月前
|
C语言
【c语言】字符串函数的模拟实现(二)
【c语言】字符串函数的模拟实现(二)
25 1