【C语言航路】第十一站:字符串、字符和内存函数(中)

简介: 【C语言航路】第十一站:字符串、字符和内存函数

4.strcmp

(1)strcmp库函数文档

1.这个函数有两个参数都是const char*类型的,因为我们不会进行修改,我们只会进行查看

2.这个函数的作用是比较两个字符串的大小,比较规则是:从第一个字符依次开始比较,一个字符一个字符比较,谁的ASCII码值大,谁就大。如果相等则比较后一个字符。

3.这个函数的返回值是int类型,如果str1大于str2,则返回一个大于0的数,如果相等则返回0,如果小于则返回小于0的一个数

4.在vs环境下:大于返回1,等于返回0,小于返回-1。但是在其他编译器上不一定成立

(2)strcmp的使用

#include<stdio.h>
#include<string.h>
int main()
{
  char arr1[] = "abcdef";
  char arr2[] = "abc";
  int ret = strcmp(arr1, arr2);
  printf("%d\n", ret);
  return 0;
}

(3)strcmp的模拟实现

#include<stdio.h>
#include<assert.h>
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;
  }
  //在一些编译器上是这样实现的
  //return *str1 - *str2;
}
int main()
{
  char arr1[] = "abcefg";
  char arr2[] = "abc";
  int ret = my_strcmp(arr1, arr2);
  printf("%d\n", ret);
  return 0;
}

注意事项(函数不安全的原因)

strcpy,strcat,strcmp这些函数都是不安全的函数,因为他们都是长度不受限制的函数,如果目标空间不是很大,则会出现问题。所以我们vs上使用这些函数需要使用开头的那个预处理指令

#define _CRT_SECURE_NO_WARNINGS 1

而为了让这些更安全,我们就有了strncpy,strncat,strncmp这些长度受限制的函数

5.strncpy

(1)strncpy库函数文档

这个函数有三个参数,char* destination,const char* source和size_t num,前两个参数的意思是目标空间的地址和源头的地址,num的意思是要拷贝几个字节

意思是拷贝前num个字节到destination中

返回类型是char*返回destination的地址

(2)strncpy的使用以及注意事项

1.拷贝num个字符从源字符串到目标空间。

2.如下图1所示,如果源字符串的长度小于num,则拷贝完源字符串之后,在目标的后边追加0,直到num个。

3.如下图2所示,我们在使用的时候要注意,不会将最后的\0给拷贝进来,需要拷贝几个字符就拷贝几个字符.

(3)strncpy的模拟实现

需要注意的事项是,由于拷贝受两个条件控制

如果num为0导致的结束的话,也就是拷贝了一部分,那么我们就不会补充\0

如果是由于源头字符串拷贝完了,但是num还没结束导致的结束,那么我们就要补充\0,要注意我们这个num是少减了一次1的,所以要前置--

第一个循环中,num和赋值的操作是不可以进行交换顺序的,这是因为&&的短路现象

#include<stdio.h>
#include<assert.h>
char* my_strncpy(char* dest, const char* src, size_t num)
{
  assert(dest && src);
  char* ret = dest;
  while (num && (*dest++ = *src++))
  {
    num--;
  }
  if (num)
  {
    while (--num)
    {
      *dest++ = '\0';
    }
  }
  return ret;
}
int main()
{
  char arr[] = "xxxxxxxxxxxxxxxxxxxxx";
  char* p = my_strncpy(arr, "hello", 10);
  printf("%s\n", p);
  return 0;
}

6.strncat

(1)strncat的库函数文档

这个的参数和返回类型与strncpy是一样的

不同的是函数的功能是追加source的前n的字符

这前n个字符追加后是需要补充一个\0的

(2)strncat的使用以及注意事项

1.对于这个函数,我们需要注意的就是追加之后后面会补充一个\0的

2.即便超出了source的范围,也只是补一个\0,不会补充多个\0

#include<stdio.h>
#include<string.h>
int main()
{
  char arr[] = "xxx\0xxxxxxxxxxxxxxx";
  char* p = strncat(arr, "hello", 3);
  return 0;
}

#include<stdio.h>
#include<string.h>
int main()
{
  char arr[] = "xxx\0xxxxxxxxxxxxxxx";
  char* p = strncat(arr, "hello", 10);
  return 0;
}

(3)strncat的模拟实现

#include<stdio.h>
#include<assert.h>
char* my_strncat(char* dest, const char* src, size_t num)
{
  assert(dest && src);
  char* ret = dest;
  while (*dest != '\0')
  {
    dest++;
  }
  while (num--)
  {
    if ((*dest++ = *src++) == '\0')
    {
      return ret;
    }
  }
  *dest = '\0';
  return ret;
}
int main()
{
  char arr[] = "xxx\0xxxxxxxxxxxxxxx";
  char* p = my_strncat(arr, "hello", 3);
  return 0;
}

7.strncmp

(1)strncmp的库函数文档

函数的功能是比较前n个字符的大小,返回一个值。

如果str1大,则返回大于0的数

如果str2大,则返回小于0的数

如果相等,则返回0

(2)strncmp的使用

比较到出现另个字符不一样或者一个字符串结束或者num个字符全部比较完

#include<stdio.h>
#include<string.h>
int main()
{
  char* p1 = "abcdef";
  char* p2 = "abcfda";
  int ret = strncmp(p1, p2, 3);
  printf("%d\n", ret);
  return 0;
}

#include<stdio.h>
#include<string.h>
int main()
{
  char* p1 = "abcdef";
  char* p2 = "abcfda";
  int ret = strncmp(p1, p2, 4);
  printf("%d\n", ret);
  return 0;
}

#include<stdio.h>
#include<string.h>
int main()
{
  char* p1 = "abdef";
  char* p2 = "abcfda";
  int ret = strncmp(p1, p2, 4);
  printf("%d\n", ret);
  return 0;
}

8.strstr

(1)strstr库函数文档

这个函数有两个参数,都是const char* 类型的

功能是子str1中查找是否存在str2字符串

返回一个const char* 类型的地址,如果存在,则返回在str1中第一次出现str2的地址,如果不存在,则返回NULL

(2)strstr的使用

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

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

(3)strstr的模拟实现

我们在这里采用的是暴力循环遍历的方法。当然也可以使用KMP算法,在此不做介绍了

#include<stdio.h>
#include<assert.h>
char* my_strstr(const char* str1, const char* str2)
{
  assert(str1 && str2);
  if (*str2 == '\0')
  {
    return (char*)str1;
  }
  const char* s1 = NULL;
  const char* s2 = NULL;
  const char* cp = str1;
  while (*cp)
  {
    s1 = cp;
    s2 = str2;
    while (*s1 != '\0' && *s2 != '\0' && *s1 == *s2)
    {
      s1++;
      s2++;
    }
    if (*s2 == '\0')
    {
      return cp;
    }
    cp++;
  }
  return NULL;
}
int main()
{
  char arr1[] = "abcdef";
  char arr2[] = "bcdef";
  char* ret = my_strstr(arr1, arr2);
  if (ret != NULL)
  {
    printf("%s\n", ret);
  }
  else
  {
    printf("找不到\n");
  }
  return 0;
}

9.strtok

(1)strtok的库函数文档

这个函数有两个参数,str是目标字符串。它是需要被修改的

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

函数的功能是,在str字符串中找到,delimiter这个集合中的任意一个字符,然后将最先出现的这个字符修改为\0,并且返回分割好的这个字符串的地址,并且内部有一个静态变量记录之前切割的位置

这个str可以是一个null,如果传的是空指针的话,那么就在后面的字符串中找到集合中的某个元素,并且修改为\0,然后返回这个字符串。

(2)strtok的使用以及注意事项

第二个参数sep是个字符串,定义了用作分隔符的字符集合

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

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

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

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

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

#include<stdio.h>
#include<string.h>
int main()
{
  char arr[] = "192.168.120.86#56789";
  char sep[] = ".#";
  char buf[30] = { 0 };
  strcpy(buf, arr);
  char* ret = NULL;
  for (ret = strtok(buf, sep); ret != NULL; ret = strtok(NULL, sep))
  {
    printf("%s\n",ret);
  }
  return 0;
}

10.strerror

(1)strerror的库函数文档

这个函数它会接受一个整型的数字,这个数字是一个错误码,然后返回一个字符串的地址,我们可以打印出这个字符串的地址,显示我们的错误信息

C语言在运行时,如果发生错误,就会将错误码存放到errno

这个变量中,而这个函数可以将错误码翻译成字符串

相关文章
|
1天前
|
搜索推荐 算法 C语言
使用C语言实现字符串排序
使用C语言实现字符串排序
|
2天前
|
存储 程序员 编译器
C语言:指针与内存
C语言:指针与内存
7 0
|
2天前
|
存储 编译器 C语言
C语言:函数
C语言:函数
10 0
|
2天前
|
机器学习/深度学习 C语言
C语言:函数递归
C语言:函数递归
|
2天前
|
存储 编译器 程序员
C语言:函数
C语言:函数
|
2天前
|
存储 C语言
C语言:字符函数和字符串函数
C语言:字符函数和字符串函数
|
26天前
|
Linux
|
1月前
|
监控 关系型数据库 MySQL
innodb_buffer_pool_instances 如何根据cpu和内存进行配置
`innodb_buffer_pool_instances` 是用于配置 InnoDB 缓冲池实例数的参数。每个实例都管理缓冲池的一部分,这有助于提高并发性能。通常,你可以根据系统的 CPU 和内存来调整这个参数,以获得更好的性能。 以下是一些建议和步骤,帮助你根据 CPU 和内存进行 `innodb_buffer_pool_instances` 的配置: 1. **了解系统资源:** 首先,了解系统的硬件资源,特别是内存和CPU。检查系统上可用的物理内存和 CPU 核心数量。 2. **考虑每个实例的大小:** 在配置 `innodb_buffer_pool_instances` 时,
|
1天前
|
弹性计算 大数据 测试技术
2024阿里云服务器租用价格表(CPU/内存/带宽/磁盘收费标准)
阿里云服务器分为轻量应用服务器和云服务器ECS,轻量适合个人开发者使用,搭建轻量级的网站、测试环境使用;专业级如大数据、科学计算、高并发网站等需要使用云服务器ECS。2024年阿里云服务器租用价格表出炉!云服务器ECS经济型e实例2核2G、3M固定带宽99元一年、ECS u1实例2核4G、5M固定带宽、80G ESSD Entry盘优惠价格199元一年,轻量应用服务器2核2G3M带宽轻量服务器一年61元、2核4G4M带宽轻量服务器一年165元12个月、2核4G服务器30元3个月,幻兽帕鲁4核16G和8核32G服务器配置,云服务器ECS可以选择经济型e实例、通用算力u1实例、ECS计算型c7、通
|
6天前
|
弹性计算 大数据 测试技术
2024年阿里云服务器租用价格表(CPU/内存/带宽/磁盘收费标准)
2024年阿里云服务器租用价格表更新,云服务器ECS经济型e实例2核2G、3M固定带宽99元一年、ECS u1实例2核4G、5M固定带宽、80G ESSD Entry盘优惠价格199元一年,轻量应用服务器2核2G3M带宽轻量服务器一年61元、2核4G4M带宽轻量服务器一年165元12个月、2核4G服务器30元3个月,幻兽帕鲁4核16G和8核32G服务器配置,云服务器ECS可以选择经济型e实例、通用算力u1实例、ECS计算型c7、通用型g7、c8i、g8i等企业级实例规格。阿里云百科分享阿里云服务器租用费用最新报价

相关产品

  • 云迁移中心