C语言——字符串函数

简介: 对字符串函数知识进行分享


🔴前言

  • 我们知道,在C语言中对字符和字符串的处理很是频繁,但是C语言本身是没有字符串类型的(不像其他语言直接String即可解决),在C语言中字符串通常放在常量字符串中或者字符数组中。
  • 字符串常量适用于那些对它不做修改的字符串函数。

我们这次主要介绍的就是一些字符串函数。

  • 关于学习一些陌生的函数:我们可以通过cplusplus.com进行了解学习,知道参数所代表的含义以及实现的功能是上面,这可以让我们事半功倍!对于英文不理解的话,我们可以翻译成自己熟悉的中文啦。💗
  • 一定要自己多动手去实现代码哦,也不要一口气吃成胖子💖

🟠求字符串长度——strlen()

关于**strlen()**我们需要知道几个点:

size_t strlen ( const char * str );//返回无符号整型
  1. 字符串已经 ‘\0’ 作为结束标志,strlen函数返回的是在字符串中 ‘\0’ 前面出现的字符个数(不包 含 ‘\0’ )。
  2. 参数指向的字符串必须要以 ‘\0’ 结束。
  3. 注意函数的返回值为size_t,是无符号的( 易错 )
  4. 学会strlen函数的模拟实现

对于第3点我们怎么去理解❓我们可以来举个例子:

#include <stdio.h>
#include <string.h>
int main()
{
  //返回无符号整型
  if (strlen("abc") - strlen("abcdef") > 0)
  {
    printf(">\n");
  }
  else
  {
    printf("<\n");
  }
  return 0;
}

输出结果是什么

是:>

因为strlen()返回无符号整型,虽然3-6<0,但是对于无符号的数来说,怎么可能有负数呢?所以结果肯定是>号

我们可以来测试运行一下结果:

本篇博客主要的内容就是函数的模拟实现

下面我们介绍strlen()的三种模拟实现方法👇:

1.计数器方法

直接定义一个变量去统计字符串的长度:

#include <stdio.h>
#include <string.h>
#include <assert.h>
//计数器方法
size_t my_strlen(const char*str)
{
  int count = 0;
  assert(str);
  while (*str != '\0')
  {
    count++;
    str++;
  }
  return count;
}
int main()
{
  char arr[] = "abcdef";
  size_t n = my_strlen(arr);
  printf("%u\n", n);
  return 0;
}

同时,我们需要严谨一些,注意一些细节📝:

  1. 第一个就是const修饰,我们只需要去访问,不需要进行修改操作
  2. 第二个就是assert断言,如果传过来的是空的呢?这就是assert的用处了
  3. 第三个就是返回值size_t无符号

2.指针-指针方法

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

指针减去指针就是元素的个数,所以我们记录刚开始的地址,由最后一个指针地址减去刚开始记录的指针地址就可以得到长度了!

3.递归

找出递归条件可以完美模拟实现strlen()。下面进行代码实现:

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

测试运行:


🟡长度不受限制的字符串函数

strcpy

对于strcpy(),我们要知道几个点:

char* strcpy(char * destination, const char * source );
  1. Copies the C string pointed by source into the array pointed by destination, including the terminating null character (and stopping at that point). 简单理解就是字符串的拷贝,不过拷贝要注意下面几个点:
  2. 源字符串必须以 ‘\0’ 结束。
  3. 会将源字符串中的 ‘\0’ 拷贝到目标空间。
  4. 目标空间必须足够大,以确保能存放源字符串。
  5. 目标空间必须可变。 学会模拟实现。

我觉得这个函数最重要的一点是:第一个参数是目的地字符串,第二个参数是源来的字符串。第二个参数是不可改变的,可以用const来修饰。这点比较重要。

下面我们来对其进行模拟实现:

//模拟实现
#include <stdio.h>
char* my_strcpy(char* dest, const char* src)
{
  assert(dest);
    assert(src);
  char* ret = dest;
  while (*src)
  {
    *dest++ = *src++;
  }
  *dest = *src;
  return ret;
}
int main()
{
  char arr1[] = "abcdef";
  char arr2[20] = { 0 };
  my_strcpy(arr2, arr1);
  printf("%s\n", arr2);
  return 0;
}

对于这次的模拟实现我们可以进行优化,使之看起来更加简化

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

测试运行结果:

strcat

char * strcat ( char * destination, const char * source );
  1. Appends a copy of the source string to the destination string. The terminating null character in destination is overwritten by the first character of source, and a null-character is included at the end of the new string formed by the concatenation of both in destination. 简单理解,就是字符串的追加。
  2. 源字符串必须以 ‘\0’ 结束。
  3. 目标空间必须有足够的大,能容纳下源字符串的内容。
  4. 目标空间必须可修改。 字符串自己给自己追加,如何?

有了上面的知识点之后,对于strcat我们是很好理解的,下面我们先来进行模拟实现:

#include <stdio.h>
//字符串追加
//字符串追加
char* my_strcat(char* dest, const char* src)
{
  assert(dest && src);
  int ret = dest;
  while (*dest != '\0')
  {
    dest++;
  }
  while (*dest++ = *src++)
  {
    ;
  }
  return ret;
}
int main()
{
  char arr1[20] = "hello ";
  strcat(arr1, "world");
  //my_strcat(arr1, "world");
  //自己给自己追加?
  //my_strcat(arr1, arr1);//这是错误的,破坏了本身自己。\0不见了
  printf("%s\n", arr1);
  return 0;
}

测试运行:

这里有人会问了:自己给自己追加呢?想想看,这是错误的做法,因为你会发现,追加自己的过程中本身自己发生了变化,'\0’被覆盖了,根本无法实现。无论是我们自己模拟实现的或者库函数自己的,都没法自己追加自己。

strcmp

int strcmp ( const char * str1, const char * str2 );
  1. This function starts comparing the first character of each string. If they are equal to each other, it continues with the following pairs until the characters differ or until a terminating null-character is reached. 简单来说,就是进行字符串的比较。
  2. 标准规定: 第一个字符串大于第二个字符串,则返回大于0的数字
  3. 第一个字符串等于第二个字符串,则返回0
  4. 第一个字符串小于第二个字符串,则返回小于0的数字
  5. 那么如何判断两个字符串?比较的是对应的ASCII码值

先来简单理解一下库函数把:

#include <stdio.h>
int main()
{
  int ret = strcmp("abbb", "abq");
  printf("%d", ret);
  return 0;
}

将会得到:

因为第三位b小于q的ASCII码值,自然返回-1。这就是strcmp的基本原理。

不过这里我们要对其进行模拟实现,怎么模拟实现呢❓

#include <stdio.h>
int my_strcmp(const char* s1, const char* s2)
{
  while (*s1 == *s2)
  {
    if (*s1 == '\0')
    {
      return 0;
    }
    s1++;
    s2++;
  }
  if (*s1 > *s2)
  {
    return 1;
  }
  else 
  {
    return -1;
  }
}
int main()
{
  char* p = "abcdef";
  char* q = "abbb";
  int ret = my_strcmp(p, q);
  if (ret>0)
  {
    printf("p>q");
  }
  else if(ret <0)
  {
    printf("p<q");
  }
  else
  {
    printf("p=q");
  }
  return 0;
}

测试运行结果:

这样就完了吗?并没有,我们可以对模拟实现的代码进行优化简洁一些:

//优化模拟实现
#include <stdio.h>
#include <assert.h>
int my_strcmp(const char* s1, const char* s2)
{
  assert(s1 && s2);
  while (*s1 == *s2)
  {
    if (*s1 == '\0')
    {
      return 0;
    }
    s1++;
    s2++;
  }
  return *s1 - *s2;
}
int main()
{
  char* p = "abcdef";
  char* q = "abbb";
  int ret = my_strcmp(p, q);
  if (ret>0)
  {
    printf("p>q");
  }
  else if(ret <0)
  {
    printf("p<q");
  }
  else
  {
    printf("p=q");
  }
  return 0;
}

注意到:

并没有具体要求<0的数是多少,或者说>0的数是多少,我们直接去相减即可。

测试运行一下代码:

自己认为看得懂就会了,实际操作起来是跟自己的想法是不一样的,希望大家能够多动手去实践一下!🌹



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