【面试题分享】重现 string.h 库常用的函数

文章目录

  • 【面试题分享】重现 string.h 库常用的函数
  • 一、字符串复制
    • 1. strcpy(复制字符串直到遇到 null 终止符)
    • 2. strncpy(复制固定长度的字符串)
  • 二、字符串连接
    • 1. strcat(将一个字符串连接到另一个字符串的末尾)
    • 2. strncat(将指定长度的字符串连接到另一个字符串的末尾)
  • 三、字符串比较
    • 1. strcmp(比较两个字符串的内容)
    • 2. strncmp(比较指定长度的两个字符串的内容)
  • 四、字符串搜索
    • 1. strchr(在字符串中查找第一个出现的字符)
    • 2. strrchr(在字符串中查找最后一个出现的字符)
    • 3. strstr(在字符串中查找子字符串)
  • 五、字符串长度计算
    • 1. strlen(计算字符串的长度)
    • 2. strnlen(在指定数量范围内计算字符串的最大长度)
  • 六、内存操作
    • 1. memcpy(复制内存块的内容)
    • 2. memset(用指定字符填充内存块)
  • 附录
    • 1. 英文惯用缩写
    • 2. size_t
    • 3. 很多字符串函数明明不需要返回值,但为什么还是有返回值?

在这里插入图片描述

【面试题分享】重现 string.h 库常用的函数

在嵌入式软件开发的面试中,编程题往往是考察候选人基本功和实际动手能力的重要环节。而在众多面试题目中,重现标准库中的常用函数,如 string.h 库中的那些函数,既能展示候选人的编程技巧,也能反映其对基础概念的掌握程度。程序实现字符串操作相关的常见函数,是面试中比较常见的笔试题。本文也将重点介绍如何实现 string.h 库中的常用函数,主要包括字符串复制连接比较搜索长度计算内存操作。通过这些实例,不仅帮助读者更好地备战面试,也能加深对标准库函数内部实现的理解。

[!CAUTION]

本文并不解释 string.h 里所有的函数,只介绍一些较为常见或面试常考的函数

一、字符串复制

1. strcpy(复制字符串直到遇到 null 终止符)

strcpy,即 string copy(字符串复制)的缩写,是把从 src 地址开始且含有 NULL 结束符的字符串复制到以 dest 开始的地址空间,函数原型声明如下:

char *strcpy(char *dest, const char *src);

如果要自己实现一个与之功能相同的函数,可以如下编码:

char *myStrcpy(char *dest, const char *src)
{if (NULL == dest || NULL == src)return dest;char *temp = dest;do {*temp = *src;temp++;} while (*src++);return dest;
}

上述代码中,首先要判断 srcdest 是不是空指针;其次用临时指针 temp 代替 dest 指针做边遍历,这样返回值时可以直接用 dest 指针。

[!NOTE]

为什么要用 do......while,而不是 while呢?

根据 strcpy 函数的功能,当复制完所有字符串后,还会再复制一个 '\0'(空字符)。如果使用 while 循环,一旦判断到 src 指针已经指到空字符,就会立刻结束遍历,并不会把空字符复制到目标地址。所以使用 do......while 可以先复制再判断,确保空字符被复制。

面试中能现场写出上述的代码就算完成了,当然也可以使用下面的简化版本:

char *myStrcpy(char *dest, const char *src)
{if (NULL == dest || NULL == src)return dest;char *temp = dest;while (*temp++ = *src++);return dest;
}

while (*temp++ = *src++); 这一句,使用了指针操作来遍历和复制字符。其中,*dest++ = *src++ 语句做了以下操作:

  • *src 获取源字符串当前字符。
  • *dest 存储该字符到目标字符串当前字符位置。
  • 然后两个指针分别自增,指向下一个字符位置。

[!NOTE]

为什么这里又用了 while 了呢?

因为当 src 指向空字符时,会先复制给 dest,然后 while 再判断 *dest 的值是否为空字符。

2. strncpy(复制固定长度的字符串)

strncpy 函数(string copy with n)也是复制字符串的函数,只是多了一个指定长度,把 src 所指向的字符串中以 src 地址开始的前 n 个字节复制到 dest 所指的数组中,并返回被复制后的 dest。函数原型声明如下:

char *strncpy(char *dest, const char *src, size_t n)

实现一个与之功能相同的函数,可以如下编码:

char *myStrncpy(char *dest, const char *src, size_t n)
{if (NULL == dest || NULL == src || 0 == n)return dest;char *temp = dest;while (n && (*temp++ = *src++))n--;while (n--)*temp++ = '\0';return dest;
}

代码前半部分与 strcpy 相同,后半部分的第一个 while 循环,判断 *src 是否为空字符、以及拷贝的字符数量是否指定的字符数之内。第二个 while 循环执行的前提是第一个 while 循环提前结束(即 src 中的字符数小于 n),第二个 while 循环用于填充目标字符串的剩余部分为空字符。

 [!NOTE]*为什么第一个 `while` 不写成 `while (n-- && (*temp++ = *src++))`,这样不是更简洁吗?*有一种情况我们要考虑到,那就是当 `src` 指向的字符串数量大于 n 时,如果使用 `while (n-- && (*temp++ = *src++))` 这种写法,假设 n 此时为 1,`while` 先判断 n 的值,发现不为零,于是继续执行 `(*temp = *src)`,然后再执行 `n--`、`temp++`、`src++`,之后 n 的值就已经为 0 了。这时循环开始下一轮,又判断了一次 n 的值,发现为零,结束 `while` 循环,再执行 `n--`。这时就会出现,n 的值变成了 -1,第二个 `while` 循环判断的是 n 的值不为零,就会进入循环,并执行 `n--`,n 再减一就会变成 -2,如此减下去,n 只会变成更小的负数,最后导致 `temp` 越界,造成内存踩踏。

二、字符串连接

1. strcat(将一个字符串连接到另一个字符串的末尾)

strcat 是 string concatenation 的缩写。这个函数用于将一个字符串连接到另一个字符串的末尾。具体来说,strcat 函数将源字符串的内容复制到目标字符串的末尾,并自动添加一个 null 终止符来结束新的组合字符串。函数原型声明如下:

char *strcat(char *dest, const char *src);

实现一个与之功能相同的函数,可以如下编码:

char *myStrcat(char *dest, const char *src)
{if (NULL == dest || NULL == src)return dest;char *temp = dest;while (*temp)temp++;while (*temp++ = *src++);return dest;
}

第一个 while 循环的作用是为了将 temp 指针移动到目标字符串的末尾(即空字符的位置),之后就是将源字符串的内容逐字符复制到目标字符串的末尾。由于大部分代码的功能与字符串复制的一样,这里就不过多赘述。

2. strncat(将指定长度的字符串连接到另一个字符串的末尾)

strncat 是 “string concatenate with n” 的缩写,全称是 “string concatenate with length limit”。这个函数用于将源字符串的指定长度的字符追加到目标字符串的末尾,并自动添加一个 null 终止符来结束新的组合字符串。函数原型声明如下:

char *strncat(char *dest, const char *src, size_t n);

实现一个与之功能相同的函数,可以如下编码:

char *myStrncat(char *dest, const char *src, size_t n)
{if (NULL == dest || NULL == src || 0 == n)return dest;char *temp = dest;while (*temp)temp++;while (n && (*temp++ = *src++))n--;while (n--)*temp++ = '\0';return dest;
}

代码具体描述与前面的 myStrncpymyStrcat 相同,这里不展开说明。

三、字符串比较

1. strcmp(比较两个字符串的内容)

strcmp 是 “string compare” 的缩写。 这个函数用于比较两个字符串的字典顺序。它根据两个字符串的字符逐一比较,直到找到不同的字符或遇到终止的 null 字符。函数原型声明如下:

int strcmp(const char *str1, const char *str2);

strcmp 的返回值是整数类型,有三种情况,分别是 -101,以上三种情况均是在比较到不同字符时,将两个字符直接做差得到的结果,具体情况如下:

  • 如果 str1str2 之前,则返回值为 -1。
  • 如果 str1 等于 str2,则返回值为 0。
  • 如果 str1str2 之后,则返回值为 1。

实现一个与之功能相同的函数,可以如下编码:

int myStrcmp(const char *str1, const char *str2)
{if (str1 == str2)return 0;while (*str1 && (*str1 == *str2)) {str1++;str2++;}return ((*str1 - *str2) ? ((*str1 - *str2) > 0 ? 1 : -1) : 0);
}

上述代码中,先判断两个地址是否相同,如果是一样,那字符串也是一样的,直接返回 0 即可。while 循环中,除了判断 str1 当前所指的字符是否为空字符之外,还要判断 str1str2 各自所指的字符是否相同,同时满足两个条件,两个指针各自递增偏移。

最后返回时,用三目运算符内嵌另一个三目运算符做一个差值判断,先判断是否为 0,如果是则返回 0,否则再判断是正数还是负数,正数返回 1,负数返回 -1。

[!NOTE]

如果两个参数中有一个传参传入了 NULL,会导致段错误,为什么这个代码没有体现出解决方法?

strcmp 也是如此,只要参数中有且只有一个参数是 NULL,就会出现段错误。传入两个 NULL 则返回 0,因此,我只是保留了原本 strcmp 该有功能写了这个 myStrcmp

2. strncmp(比较指定长度的两个字符串的内容)

strncmpstrcmp 基础上,加上了需要比较的长度,该函数用于比较两个字符串的前 n 个字符的字典顺序。它根据两个字符串的字符逐一比较,直到找到不同的字符、比较了指定的 n 个字符或遇到空字符。函数原型声明如下:

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

实现一个与之功能相同的函数,可以如下编码:

int myStrncmp(const char *str1, const char *str2, size_t n)
{if (str1 == str2)return 0;while (n && (*str1 && (*str1 == *str2))) {str1++;str2++;n--;}return ((*str1 - *str2) ? ((*str1 - *str2) > 0 ? 1 : -1) : 0);
}

四、字符串搜索

1. strchr(在字符串中查找第一个出现的字符)

strchr 是 “string character” 的缩写,全称是 “string character search”。这个函数用于在字符串中查找第一个出现的指定字符,并返回一个指向该字符的指针。函数原型声明如下:

char *strchr(const char *str, int c);

在被搜索的字符串 str 中,查找 c 指定的字符,虽传入的类型为 int ,但实际比较时会被转换为 char。如果在字符串 str 中找到 c ,则返回一个指向字符串中第一个出现的字符 c 的指针;如果没有没有找到,则返回 NULL

实现一个与之功能相同的函数,可以如下编码:

char *myStrchr(const char *str, int c)
{while (*str && (*str != (char)c))str++;if (*str == (char)c)return (char *)str;return NULL;
}

上述代码中,while 循环除了判断 *str,同时还判断 *str 是否与 (char)c 是否匹配,所以退出循环就存在两个情况:一是 str 已经遍历结束,如果 c 是空字符(c 有可能是 '\0'),则返回 str 当前所指的地址,否则返回 NULL;二是在 str 遍历结束之前,找到了与 c 匹配的字符,返回 str 当前所指的地址。

[!NOTE]

为什么返回 str 要强转类型为 char *,直接返回不行吗?

函数的返回类型是 char *,而 strconst char * 类型,直接返回并没有什么问题,只是在编译时会警告类型不匹配,所以这里强转只是为了消除警告。

2. strrchr(在字符串中查找最后一个出现的字符)

strrchr 是 “string reverse character” 的缩写,全称是 “string reverse character search”。该函数用于在字符串中查找最后一次出现的指定字符,并返回一个指向该字符的指针。函数原型声明如下:

char *strrchr(const char *str, int c);

strchr 函数类似,如果在字符串 str 中找到 c ,则返回一个指向字符串中最后一个出现的字符 c 的指针;如果没有没有找到,则返回 NULL

实现一个与之功能相同的函数,可以如下编码:

char *myStrrchr(const char *str, int c)
{const char *last = NULL;while (*str) {if (*str == (char)c) {last = str;}str++;}if (*str == (char)c)return (char *)str;return (char *)last;
}

上述代码依然使用了 while 循环遍历的方法,在遍历的过程中查找相匹配的字符,找到字符后保存最新的地址到 last 指针并继续查找,一旦再次找到指定字符立刻更新 last 指针,直到字符串全部遍历结束。

3. strstr(在字符串中查找子字符串)

strstr 是 “string substring” 的缩写,全称是 “string substring search”。这个函数用于在字符串中查找第一次出现的子字符串,并返回一个指向该子字符串起始位置的指针。函数原型声明如下:

char *strstr(const char *haystack, const char *needle);

其中,haystack 是要搜索的主字符串,needle 是要查找的子字符串。如果 needlehaystack 的子字符串,则返回一个指向主字符串中第一次出现的子字符串的指针,否则返回 NULL

char *myStrstr(const char *haystack, const char *needle)
{if (!*needle)return (char *)haystack;while (*haystack) {if (*haystack == *needle) {char *h = (char *)haystack;char *n = (char *)needle;while (*h && *n && (*h == *n)) {h++;n++;}if (!*n)return (char *)haystack;haystack++;} else {haystack++;}}return NULL;
}

可以看出,strstr 函数的代码要远比前面提到的所有函数都要复杂,所以以下是代码的剖析:

  1. 空字符串检查:首先检查 needle 是否为空字符串(原 strstr 函数也是如此),如果是,直接返回 haystack 的指针。
  2. 逐字符比较
    • 外层 while (*haystack) 循环遍历 haystack 字符串。
    • 当出现第一个匹配的字符后,进入内层 while (*h && *n && *h == *n) 循环逐字符比较 haystackneedle,直到字符不匹配或到达 needle 末尾。
  3. 匹配检查:如果 needle 的所有字符都匹配,即 !*n,返回 haystack 当前的位置。
  4. 继续搜索:如果当前字符不匹配,haystack 移动到下一个字符继续搜索。
  5. 未找到返回 NULL:如果遍历完 haystack 仍未找到 needle,返回 NULL

五、字符串长度计算

1. strlen(计算字符串的长度)

strlen 是 “string length” 的缩写,该函数用于计算字符串的长度,即字符串中字符的数量(不包括终止空字符)。函数原型声明如下:

size_t strlen(const char *str);

实现一个与之功能相同的函数,可以如下编码:

size_t myStrlen(const char *str)
{const char *temp = str;while (*temp)temp++;return temp - str;
}

代码非常简短,这里就不过多讲解了。

2. strnlen(在指定数量范围内计算字符串的最大长度)

strnlen 是 “string length with n” 的缩写,全称是 “string length with length limit”。该函数用于计算字符串的长度,但最多检查指定的最大字符数。函数原型声明如下:

size_t strnlen(const char *str, size_t maxlen);

实现一个与之功能相同的函数,可以如下编码:

size_t myStrnlen(const char *str, size_t maxlen)
{const char *temp = str;size_t num = 0;while (num < maxlen && *temp) {temp++;num++;}return num;
}

六、内存操作

1. memcpy(复制内存块的内容)

memcpy 是 “memory copy” 的缩写,该函数用于从源地址复制指定数量的字节到目标地址。函数原型声明如下:

void *memcpy(void *dest, const void *src, size_t n);

dest 是指向目标内存块的指针,src 是指向源内存块的指针,n 是要复制的字节数。最后是返回目标内存块 dest 的指针。

实现一个与之功能相同的函数,可以如下编码:

void *myMemcpy(void *dest, const void *src, size_t n)
{unsigned char *d = (unsigned char *)dest;const unsigned char *s = (const unsigned char *)src;while (n--)*d++ = *s++;return dest;
}

这里要注意的就是类型问题,由于是内存复制,因此要强转为 unsigned char 类型。

2. memset(用指定字符填充内存块)

memset 是 “memory set” 的缩写,该函数用于将指定值填充到内存块中,通常用于初始化或重置内存。通常也管这个函数叫 “填充” 函数,函数原型声明如下:

void *memset(void *str, int c, size_t n);

str 是指向要填充的内存块的指针。c 是要设置的值,传递为 int 类型,填充的时候会转换为 unsigned char 类型。n 是要填充的字节数。最后是返回指向内存块 str 的指针。

实现一个与之功能相同的函数,可以如下编码:

 void *myMemset(void *str, int c, size_t n){unsigned char *s = (unsigned char *)str;while (n--)*s++ = (unsigned char)c;return str;}

附录

1. 英文惯用缩写

在函数的参数列表中有两个高频出现的参数——srcdest,其中 src源操作数,是 source 的缩写,dest目标操作数,是 destination 的缩写。

2. size_t

size_t 是一种用于表示对象大小或数组索引的无符号整数类型。在 C 和 C++ 标准库中,对于 size_t 的定义有所不同。在不同的编译器和平台上,size_t 可能通过一些中间文件间接定义,但主要头文件通常是 stddef.h(C)和 cstddef(C++)。

在 C 语言中,stddef.h 可能包含以下内容:

#ifndef _STDDEF_H
#define _STDDEF_Htypedef unsigned long size_t;#endif // _STDDEF_H

在 C++ 中,cstddef 可能包含以下内容:

#ifndef _CSTDDEF_
#define _CSTDDEF_#include <stddef.h>namespace std {using ::size_t;
}#endif // _CSTDDEF_ 

3. 很多字符串函数明明不需要返回值,但为什么还是有返回值?

字符串函数返回值的设计有以下几个实用的理由,返回值的设计提供了一些附加的好处,使函数的使用更加灵活和方便。以下以 strcpy 函数为例进行说明。

  1. 链式调用strcpy 返回目标字符串的指针,这使得链式调用成为可能。链式调用允许多个字符串操作函数连续使用,从而简化代码。

    char dest[100];
    strcpy(dest, "Hello, ");
    strcat(dest, "world!");// 使用链式调用
    strcat(strcpy(dest, "Hello, "), "world!");
    
  2. 更好的函数组合:返回目标字符串的指针使得 strcpy 可以与其他需要字符串指针作为输入的函数更好地组合在一起。例如,许多字符串处理函数(如 strlen)需要一个字符串指针作为参数。

    char dest[100];
    size_t len = strlen(strcpy(dest, "Hello, world!"));
    
  3. 代码一致性和便利性:在 C 标准库中,许多字符串操作函数都返回与输入相关的指针。例如,strcatstrtok 都返回指向结果字符串的指针。strcpy 也遵循这个设计模式,使得整个库的设计更一致和直观。

  4. 调试和错误处理:尽管 strcpy 本身没有提供错误处理机制,但在某些情况下,返回值可以在调试时提供便利。例如,在检查链式调用的中间结果时,可以打印返回值来验证复制操作是否成功。

    char dest[100];
    printf("Copied string: %s\n", strcpy(dest, "Hello, world!"));
    
  5. 兼容历史习惯:许多早期的 C 函数,包括 strcpy,都是遵循 UNIX 函数设计习惯的。这种习惯通常会返回一个指向结果的指针。遵循这种习惯,使得库函数更容易被广泛接受和使用。

本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如若转载,请注明出处:http://www.mzph.cn/diannao/31673.shtml

如若内容造成侵权/违法违规/事实不符,请联系多彩编程网进行投诉反馈email:809451989@qq.com,一经查实,立即删除!

相关文章

Java中setLineWrap(true)和setWrapStyleWord(true)优化TextArea

在 Java Swing 开发中&#xff0c;JTextArea 是一个多行的文本区域组件&#xff0c;常用于显示和编辑大量文本。当处理长文本时&#xff0c;默认行为是不换行并且出现水平滚动条&#xff0c;这通常会降低用户体验。幸运的是&#xff0c;JTextArea 提供了两个非常有用的方法&…

为何你的App安装转化率不高?试试Xinstall的页面唤起功能吧!

在当今互联网快速发展的时代&#xff0c;App已经成为我们生活中不可或缺的一部分。然而&#xff0c;随着市场竞争的加剧&#xff0c;App推广和运营面临着诸多挑战。其中&#xff0c;安装页面唤起不顺畅、用户体验不佳等问题&#xff0c;成为了许多开发者和运营者头疼的难题。为…

C++【继承】

继承的概念 继承(inheritance)机制是面向对象程序设计使代码可以复用的最重要的手段&#xff0c;它允许程序员在保 持原有类特性的基础上进行扩展&#xff0c;增加功能&#xff0c;这样产生新的类&#xff0c;称派生类。继承呈现了面向对象 程序设计的层次结构&#xff0c;体现…

网上预约就医取号系统

摘 要 近年来&#xff0c;随着信息技术的发展和普及&#xff0c;我国医疗信息产业快速发展&#xff0c;各大医院陆续推出自己的信息系统来实现医疗服务的现代化转型。不可否认&#xff0c;对一些大型三级医院来说&#xff0c;其信息服务质量还是广泛被大众所认可的。这就更需要…

u盘在电脑上读不出来?这些方法或许能帮到你!

U盘作为一种便捷的存储设备&#xff0c;广泛应用于数据传输和备份。然而&#xff0c;在使用过程中&#xff0c;用户可能会遇到U盘在电脑上读不出来的问题。这种情况可能由多种原因引起&#xff0c;包括硬件故障、驱动问题、文件系统损坏等。本文将详细介绍解决u盘在电脑上读不出…

小红书点赞评论收藏【更新版本】

小红书作为社交媒体的一个亮点&#xff0c;其点赞、评论和收藏的功能形成了一种特有的交流机制。点赞简直就是一枚迷你奖章&#xff0c;为创作者带去信心与动力。一次点赞&#xff0c;表达的是你心中无言的喜好和认可&#xff1b;它如明亮的灯塔&#xff0c;在汪洋大海中为创作…

人工智能对决:ChatGLM与ChatGPT,探索发展历程

图: a robot is writing code on a horse, By 禅与计算机程序设计艺术 目录 ChatGLM:

项目实践---Windows11中安装Zookeeper3.5.5/Hadoop2.7.2/Hive2.3.7

1.背景 项目第一版本使用大数据组件核心版本均为2.x&#xff0c;需要在个人电脑搭建相关大数据环境&#xff0c;这次提供Hadoop2.7.2 Hive2.3.7版本的环境搭建。 2.相关安装包下载 链接&#xff1a;https://pan.baidu.com/s/1tkYr1UpqMKKVJHY5cfvVSw?pwddcxd 提取码&…

摊牌了,我不装了~各种Amazon Bedrock小样儿、试用装,今天免费!

探索世界顶级的大模型、智能体、文生图、对话机器人……新手&#xff1f;还是专家&#xff1f;加入我们&#xff0c;解锁精彩内容&#xff1a; l 初体验&#xff1a;在 Amazon Bedrock Playground 直接调用强大的大模型&#xff0c;点亮生成式AI技能树。 l 文生图&#xff1a…

Pyqt QCustomPlot 简介、安装与实用代码示例(二)

目录 前言实用代码示例彩色图演示散点像素图演示实时数据演示多轴演示对数轴演示 结语 所有文章除特别声明外&#xff0c;均采用 CC BY-NC-SA 4.0 许可协议。转载请注明来自 nixgnauhcuy’s blog&#xff01; 如需转载&#xff0c;请标明出处&#xff01; 完整代码我已经上传到…

【C++进阶学习】第三弹——菱形继承和虚拟继承——菱形继承的二义性和数据冗余问题

继承&#xff08;上&#xff09;&#xff1a;【C进阶学习】第一弹——继承&#xff08;上&#xff09;——探索代码复用的乐趣-CSDN博客 继承&#xff08;下&#xff09;&#xff1a;【C进阶学习】第二弹——继承&#xff08;下&#xff09;——挖掘继承深处的奥秘-CSDN博客 …

教育培训系统(FastAdmin+ThinkPHP+Unipp)

引领学习新风尚 &#x1f4da; 引言&#xff1a;教育新篇章 随着科技的不断发展&#xff0c;教育形式也在不断创新与变革。教育培训系统作为这一变革的重要载体&#xff0c;正逐渐改变着我们的学习方式。今天&#xff0c;就让我们一起探索教育培训系统的魅力&#xff0c;看看它…

雷池社区版自动SSL

正常安装雷池&#xff0c;并配置站点&#xff0c;暂时不配置ssl 不使用雷池自带的证书申请。 安装&#xff08;acme.sh&#xff09;&#xff0c;使用域名验证方式生成证书 先安装git yum install git 或者 apt-get install git 安装完成后使用 git clone https://gitee.com/n…

【代码仓库提交大文件,用Git LFS!】

开始前 Git LFS&#xff1a;请注意&#xff0c;你的远程仓库需要支持Git LFS。GitHub、GitLab和Bitbucket都支持Git LFS&#xff0c;但可能需要额外的配置或开启特定的支持选项。 介绍 Git LFS (Large File Storage) 是一个 Git 扩展&#xff0c;用于处理和存储大文件。通常…

DVWA 靶场 Authorisation Bypass 通关解析

前言 DVWA代表Damn Vulnerable Web Application&#xff0c;是一个用于学习和练习Web应用程序漏洞的开源漏洞应用程序。它被设计成一个易于安装和配置的漏洞应用程序&#xff0c;旨在帮助安全专业人员和爱好者了解和熟悉不同类型的Web应用程序漏洞。 DVWA提供了一系列的漏洞场…

在寻找电子名片在线制作免费生成?5个软件帮助你快速制作电子名片

在寻找电子名片在线制作免费生成&#xff1f;5个软件帮助你快速制作电子名片 当你需要快速制作电子名片时&#xff0c;有几款免费在线工具可以帮助你实现这个目标。这些工具提供了丰富的设计模板和元素&#xff0c;让你可以轻松地创建个性化、专业水平的电子名片。 1.一键logo…

个人知识库(python/AI/机器学习/数据分析/神经网络/机器视觉/共享文档)

个人工作学习中总结的知识技巧,欢迎大家阅读学习,地址:语雀阅读地址 后期也会把资源在csdn上公布出来,方便同行借鉴.

神经网络学习5-非线性激活

非线性激活&#xff0c;即 这是最常用的 inplaceTrue 原位操作 改变变量本身的值&#xff0c;就是是否输入时若原本有值&#xff0c;是否更换 该函数就是表示&#xff1a;输入小于零时输出0&#xff0c;大于零时保持不变 代码如下&#xff1a; import torch from torch imp…

Databend 开源周报第 149 期

Databend 是一款现代云数仓。专为弹性和高效设计&#xff0c;为您的大规模分析需求保驾护航。自由且开源。即刻体验云服务&#xff1a;https://app.databend.cn 。 Whats On In Databend 探索 Databend 本周新进展&#xff0c;遇到更贴近你心意的 Databend 。 支持递归公共表…

(项目实战)RocketMQ5.0延迟消息在聚合支付系统中的应用

1 基于业务场景掌握RocketMQ5.0 本篇文章主要结合聚合支付系统中的业务场景来落地RocketMQ中间件的应用&#xff0c;聚合支付系统主要在支付系统超时订单和商户支付结果异步通知场景中会使用到RocketMQ消息中间件。本文使用到了RocketMQ中的延迟消息知识点&#xff0c;RocketM…