C语言进阶学习日志:字符串和内存函数(一)(下)

简介: C语言进阶学习日志:字符串和内存函数(一)(下)

长度受限制的字符串函数


strncpy函数:

bb0e7c62fa3641c497c6415c99509fcd.png

第三个参数 size_t count 是要拷贝的元素个数

要注意的是当我们拷贝的元素个数大于我们被拷贝的字符串的长度时他会自动往不够的那片空间添加'\0'

#include <stdio.h>
int main()
{
  char string1[]="xxxxxxxxxxx";
  char string2[]="123";
  strncpy(string1,string2,5);
  这时string1就会变成123'\0'\0'xxxxxxxxx;
}

同时strncpy函数也更加安全一些 因为这样可以避免你拷进去的字符串过长 以至于目标的字符串不足以存储拷贝进来的字符串

#define _CRT_SECURE_NO_WARNINGS 1
#include <stdio.h>
#include <assert.h>
char* my_strncpy(char* rest, const char* tmp, unsigned int num)
{
  assert(rest && tmp);
  char* ret = rest;
  while (num)
  {
    if (*tmp == '\0')
    {
      *rest++ = *tmp;
      num--;
    }
    while (*tmp)
    {
      *rest++ = *tmp++;
      num--;
      if (!num) return ret;
    }
  }
  return ret;
}
int main()
{
  char rest[] = "xxxxxxxxxx";
  char tmp[] = "123";
  printf("%s",my_strncpy(rest, tmp, 5));//这里打印出来也就是123 前面已经给大家说过了
}

这个是库函数里的写法

char * __cdecl strncpy (
        char * dest,
        const char * source,
        size_t count
        )
{
        char *start = dest;
        while (count && (*dest++ = *source++) != '\0')    /* copy string */
                count--;
        if (count)                              /* pad out with zeroes */
                while (--count)
                        *dest++ = '\0';
        return(start);
}

strncat函数:

这个是往目标字符串追加 size_t num 的字符个数的字符串

212a888cddc24f97996e993c68f53d77.png

要注意的点除了前面说的 追加字符串要足够长 可变以外

这个函数还有一个要注意的点 在指定链接的字符个数后 如果我们原函数的长度大于字符串的长度 就好像这样 "hello" "world"这时如果链接的字符个数 num为3 那我们链接wor后

后面应该是什么样呢

#include <stdio.h>
int main()
{
  char string1[]="hello";
  char string2[]="world";
  strncpy(string1,string2,3);
  这样操作后string1的结果是什么内 留给大家思考一下
}

 提示 我们既然时链接两个字符串 那我们链接后肯定也是一个字符串 即使链接的元素个数中没有'\0' 大家想想字符串不可少的是什么 就知道答案了

#define _CRT_SECURE_NO_WARNINGS 1
#include <stdio.h>
#include <assert.h>
char* my_strncat(char* rest,const char* tmp,unsigned int num)
{
  assert(rest && tmp);
  char* ret = rest;
  while (*rest)
  {
    rest++;
  }
  while (*tmp)
  {
    *rest++ = *tmp++;
    num--;
    if (!num)break;
  }
  *rest = '\0';
  return ret;
}
int main()
{
  char string1[20] = "hello";
  char string2[] = "world";
  printf("%s",my_strncat(string1, string2, 4));
}

这个是库函数里的写法

char * __cdecl strncat (
        char * front,
        const char * back,
        size_t count
        )
{
        char *start = front;
        while (*front++)
                ;
        front--;
        while (count--)
                if ((*front++ = *back++) == 0)
                        return(start);
        *front = '\0';
        return(start);
}

strncmp函数:

还是一样的道理 这个也是指定了比较的元素的个数

0d669af8f81448889974108d4c1605ab.png

#define _CRT_SECURE_NO_WARNINGS 1
#include <stdio.h>
#include <assert.h>
int my_strncmp(const char* rest, const char* tmp, unsigned int num)
{
  assert(rest && tmp);
  while (*rest == *tmp)
  {
    num--;
    if (!num ||(* rest == '\0'))break;
    rest++;
    tmp++;
  }
  return *rest - *tmp;
}
int main()
{
  char string1[] = "abczefg";
  char string2[] = "abcqqq";
  printf("%d",my_strncmp(string1, string2, 4));
}

这个是库函数的里的写法

int __cdecl strncmp
(
    const char *first,
    const char *last,
    size_t      count
)
{
    size_t x = 0;
    if (!count)
    {
        return 0;
    }
    /*
     * This explicit guard needed to deal correctly with boundary
     * cases: strings shorter than 4 bytes and strings longer than
     * UINT_MAX-4 bytes .
     */
    if( count >= 4 )
    {
        /* unroll by four */
        for (; x < count-4; x+=4)
        {
            first+=4;
            last +=4;
            if (*(first-4) == 0 || *(first-4) != *(last-4))
            {
                return(*(unsigned char *)(first-4) - *(unsigned char *)(last-4));
            }
            if (*(first-3) == 0 || *(first-3) != *(last-3))
            {
                return(*(unsigned char *)(first-3) - *(unsigned char *)(last-3));
            }
            if (*(first-2) == 0 || *(first-2) != *(last-2))
            {
                return(*(unsigned char *)(first-2) - *(unsigned char *)(last-2));
            }
            if (*(first-1) == 0 || *(first-1) != *(last-1))
            {
                return(*(unsigned char *)(first-1) - *(unsigned char *)(last-1));
            }
        }
    }
    /* residual loop */
    for (; x < count; x++)
    {
        if (*first == 0 || *first != *last)
        {
            return(*(unsigned char *)first - *(unsigned char *)last);
        }
        first+=1;
        last+=1;
    }
    return 0;
}

strstr函数:

这是一个在字符串中寻找目标字符串的函数 如果找到则返回被寻找字符串首元素在目标字符串的地址

52687bca27f24bb49d11090bbf459d0e.png

#include <stdio.h>
int main()
{
  char string1[]="abbcqwer";
  char string2[]="bbc"
  printf("%s",strstr(string1,string2));
  打印出来的就是 bbcqwer
}

 我们来理一下模拟这个函数的思路  首先 我们是要在目标字符串寻找 肯定需要几个指针来帮我们判断是不是我们要寻找的字符串

bfcde9ac55b5442ea7f814c1432cfe3d.png

#include <stdio.h>
#include <assert.h>
char* my_strstr(const char* tmp, const char* ret)
{
  assert(tmp && ret);
  const char* suter = tmp;//被寻找字符串的枚举地址
  const char* cstr = tmp;//被寻找字符串的起始地址
  const char* sup = ret;
  if (*ret == '\0')
  {
    return tmp;
  }
  while (*cstr)
  {
    suter = cstr;
    sup = ret;
    while (*suter&&*suter == *sup)//当是这种"afbbc" "bbc" 最后'\0'和'\0'相同会一直循环随 
                                         会跳出但结果就会出问题
    {                              //所以suter和sup指向不能为'\0'
      suter++;
      sup++;
    }                       //上面那种循环我的if语句sup要放前面 我是找到了的而且两个都 
                                 是'\0'要把bbc打印出来才行
    if (*sup == '\0')      //像是这种"afbbcfgh" "bbc" 这时发现不相等我的sup会指向'\0'就 
                                  可以结束了
    {
      return (char*)cstr;
    }
    if (*suter == '\0')//"afbbbc" "bbcd"这种就是我往后寻找suter已经到'\0'了就可以结束了
    {                   //虽然没有也行 但是就要等到cstr到'\0'才停止 这样就可以早点结束
      return NULL;
    }
    cstr++;
  }
  return NULL;
}
int main()
{
  char arr1[] = "afbbbcdfgh";
  char arr2[] = "bbc";
  printf("%s",my_strstr(arr1, arr2));
}

我们把那个我所说的s1s2的赋值放在循环的前面 只要不相等我们跳出循环就会来到开始的位置 s1s2自然就恢复开始的位置了


strtok函数:

725df4d71e9443c5bf9982b022b95d70.png

这个函数的第二个参数我们这里简称 s2 是一个字符串 里面存储的是多个分隔符的集合

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

strtok函数找到s1中的下一个标记 并将其'\0'结尾  返回一个指向该标记的指针

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

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

不存在更多标记则返回NULL

#include <stdio.h>
int main()
{
   const char* p="@.";
   char arr[] = "luck++@8023.sg";
   char buf[] = { 0 };
   strcpy(arr,buf);  //因为我们的这个函数会改变原本字符串的内容
                       所以要先拷贝一份
   char* str=strtok(arr,p);//luck++
   printf("%s",str);
   str=strtok(arr,p);//8023
   printf("%s",str);
   str=strtok(arr,p);//sg
   printf("%s",str);
   //strtok 这里返回NULL
}

但是这种写法是不可取的 这样才是正确的用法

const char* p="@.";
char *arr="luck++@8023.sg";
for(char* str=strtok(arr,p);str!=NULL;str=strtok(NULL,p))
{
   printf("%s\n",str);
}

strerror函数:

这是一个错误信息的解释 报告函数 返回错误信息字符串的首地址

c语言中:

错误码-错误信息

   0     -“No error”

2c71dd48c0f94e07a24d6182ccee2550.png

其中errno一般与strerror配合着使用

当库函数使用的时候,发生错误会把errno这个全局的错误变量设置为本次执行库函数产生的错误码

errno是c语言提供的一个全局变量,可以直接使用,放在errno.h文件中


字符分类函数:

3b9ea676fa7a45afb03409647300f839.png


字符转换函数:

int tolower(int c);将字符转换成小写

int toupper(int c); 将字符转换成大写

到这里字符相关的函数就 弄完了 祝大家都能收到自己心仪的大厂的offer!!!!

相关实践学习
日志服务之使用Nginx模式采集日志
本文介绍如何通过日志服务控制台创建Nginx模式的Logtail配置快速采集Nginx日志并进行多维度分析。
目录
相关文章
|
2天前
|
C语言
pta浙大版《C语言程序设计(第3版)》 习题6-4 使用函数输出指定范围内的Fibonacci数 (20分)
pta浙大版《C语言程序设计(第3版)》 习题6-4 使用函数输出指定范围内的Fibonacci数 (20分)
|
2天前
|
C语言
pta 浙大版《C语言程序设计(第3版)》题目集 习题6-6 使用函数输出一个整数的逆序数 (20分)
pta 浙大版《C语言程序设计(第3版)》题目集 习题6-6 使用函数输出一个整数的逆序数 (20分)
|
2天前
|
C语言
(浙大版《C语言程序设计(第3版)》 习题6-5 使用函数验证哥德巴赫猜想 (20分)
(浙大版《C语言程序设计(第3版)》 习题6-5 使用函数验证哥德巴赫猜想 (20分)
|
4天前
|
安全 C语言
【C语言】strcpy与strncpy函数的使用和模拟实现
【C语言】strcpy与strncpy函数的使用和模拟实现
5 0
|
4天前
|
C语言
【C语言】字符分类函数与字符转换函数
【C语言】字符分类函数与字符转换函数
9 1
|
28天前
|
Java
使用Java代码打印log日志
使用Java代码打印log日志
89 1
|
1月前
|
Linux Shell
Linux手动清理Linux脚本日志定时清理日志和log文件执行表达式
Linux手动清理Linux脚本日志定时清理日志和log文件执行表达式
81 1
|
2月前
|
SQL 关系型数据库 MySQL
MySQL数据库,可以使用二进制日志(binary log)进行时间点恢复
对于MySQL数据库,可以使用二进制日志(binary log)进行时间点恢复。二进制日志是MySQL中记录所有数据库更改操作的日志文件。要进行时间点恢复,您需要执行以下步骤: 1. 确保MySQL配置文件中启用了二进制日志功能。在配置文件(通常是my.cnf或my.ini)中找到以下行,并确保没有被注释掉: Copy code log_bin = /path/to/binary/log/file 2. 在需要进行恢复的时间点之前创建一个数据库备份。这将作为恢复的基准。 3. 找到您要恢复到的时间点的二进制日志文件和位置。可以通过执行以下命令来查看当前的二进制日志文件和位
102 1
|
2月前
|
监控 Shell Linux
【Shell 命令集合 系统管理 】Linux 自动轮转(log rotation)日志文件 logrotate命令 使用指南
【Shell 命令集合 系统管理 】Linux 自动轮转(log rotation)日志文件 logrotate命令 使用指南
51 0
|
2月前
|
存储 数据库
ALTER MATERIALIZED VIEW LOG :语句来更改现有物化视图日志的存储特征或类型。
`ALTER MATERIALIZED VIEW LOG` 语句用于修改已有的物化视图日志的存储属性或类型。配合示例中的动画图像(由于格式限制无法显示),该语句帮助优化数据库的性能和管理。
46 0