【面试题分享】重现 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_H

typedef 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.mfbz.cn/a/730523.html

如若内容造成侵权/违法违规/事实不符,请联系我们进行投诉反馈qq邮箱809451989@qq.com,一经查实,立即删除!

相关文章

【2024最新华为OD-C/D卷试题汇总】[支持在线评测] 5G基站光纤连接问题(200分) - 三语言AC题解(Python/Java/Cpp)

&#x1f36d; 大家好这里是清隆学长 &#xff0c;一枚热爱算法的程序员 ✨ 本系列打算持续跟新华为OD-C/D卷的三语言AC题解 &#x1f4bb; ACM银牌&#x1f948;| 多次AK大厂笔试 &#xff5c; 编程一对一辅导 &#x1f44f; 感谢大家的订阅➕ 和 喜欢&#x1f497; &#x1f…

光大证券-放量恰是入市时:成交量择时初探

核心算法 1. 在熊市中&#xff0c;各成交量时序排名出现的频次基本随排名变小而单调增大&#xff1b;在牛市中&#xff0c;各成交量时序排名出现的频次基本随排名变小而单调减少&#xff1b;而在震荡市中&#xff0c;各成交量时序排名出现的频次两头大&#xff0c;中间小&…

天津这场智博会,成了智能时代的风向标

毫无疑问&#xff0c;这是一场智能产业的盛宴。 2024年6月20日至23日&#xff0c;国家会展中心&#xff08;天津&#xff09;迎来了一场智能科技领域的盛会——世界智能产业博览会&#xff1a;这场以“智行天下、能动未来”为主题的博览会&#xff0c;汇聚了全球49个国家和地区…

域内攻击手法——域内用户枚举和密码喷洒

一、域内用户枚举 1、域内用户枚举原理 域内用户枚举可以在无域内有效凭据的情况下&#xff0c;枚举出域内存在的用户名&#xff0c;并对其进行密码喷洒攻击&#xff0c;以此获得域内的有效凭据&#xff0c;在 Kerberos 协议认证的 AS-REQ 阶段&#xff0c;客户端向 AS 发送的…

MySQL之优化服务器设置(一)

优化服务器设置 配置MySQL的IO行为 有一些配置影响着MySQL怎样同步数据到磁盘以及如何做恢复操作。这些操作对性能的影响非常大&#xff0c;因为都涉及到昂贵的IO操作。它们也表现了性能和数据安全之间的权衡。通常&#xff0c;保证数据立刻并且一致地写到磁盘是很昂贵的。如…

【文心智能体大赛】迎接属于你的休闲娱乐导师!

迎接属于你的休闲娱乐导师&#xff01; 前言创建智能体发布智能体最后结语 前言 文心智能体平台AgentBuilder 是百度推出的基于文心大模型的智能体&#xff08;Agent&#xff09;平台&#xff0c;支持广大开发者根据自身行业领域、应用场景&#xff0c;选取不同类型的开发方式&…

AI全栈之logo生成:执文,描摹,妙哉~

前言 前几日体验了国产的AI-Agents产品coze 它是一种能够自主执行任务、与环境进行交互并根据所获取的信息做出决策和采取行动的软件程序 并且可以自己去创建属于自己的AIBot&#xff0c;还是很有意思的&#xff0c;大家可以去体验体验 在体验过程中&#xff0c;我发现在创…

肾虚学习实验第T1周:实现mnist手写数字识别

>- **&#x1f368; 本文为[&#x1f517;365天深度学习训练营](https://mp.weixin.qq.com/s/0dvHCaOoFnW8SCp3JpzKxg) 中的学习记录博客** >- **&#x1f356; 原作者&#xff1a;[K同学啊](https://mtyjkh.blog.csdn.net/)** 目录 一、前言 作为一名研究牲&#xff0…

数据库复习——模式分解

模式分解这边主要包括无损分解和保持函数依赖的分解两种形式&#xff0c;简单整理一下。 无损分解 把一个 R R R 分成 ρ { R 1 , R 2 , ⋯ , R k } \rho \{R_1,R_2,\cdots,R_k\} ρ{R1​,R2​,⋯,Rk​}&#xff0c;然后通过自然连接 R 1 ⋈ R 2 ⋈ ⋯ ⋈ R k R_1\bowtie R…

可视化数据科学平台在信贷领域应用系列七:自动机器学习(下篇)

在当今金融科技迅速发展的时代&#xff0c;自动机器学习&#xff08;AutoML&#xff09;逐步成为了信贷风控领域的重要工具。随着大数据和人工智能技术的进步以及信贷风险环境的快速变化&#xff0c;传统人工建模模式的时效性已经难以应对复杂多变的挑战。自动机器学习框架将数…

AI创作音乐引发的深思

在最近一个月中&#xff0c;音乐大模型的迅速崛起让素人生产音乐的门槛降到了最低。这一变革引发了关于AI能否彻底颠覆音乐行业的广泛讨论。在初期的兴奋过后&#xff0c;人们开始更加理性地审视AI在音乐领域的应用&#xff0c;从版权归属、原创性、创作质量、道德层面以及法律…

【linux】dup文件描述符复制函数和管道详解

目录 一、文件描述符复制 1、dup函数&#xff08;复制文件描述符&#xff09; ​编辑 2、dup2函数&#xff08;复制文件描述符&#xff09; ​编辑 二、无名管道pipe 1、概述 2、无名管道的创建 3、无名管道读写的特点 4、无名管道ps -A | grep bash实现 三、有名管道FI…

没有超头、最低价的视频号618战况如何?有何趋势变化?| 视频号618观察

转眼618大促已接近尾声&#xff0c;今年的你有剁手哪些好物吗&#xff1f;对618的整体感觉又是如何呢&#xff1f; 这是12年来&#xff0c;第一个电商平台没有预售付定金的618&#xff0c;当然或许此后的双11、每一次大促也将逐渐回归传统&#xff0c;回归本质。 而对于视频号来…

普通变频器位置闭环控制(S7-1200PLC工艺对象模拟量轴)

1、S7-1200PLC控制V90总线伺服通过工艺对象实现定位控制 S7-1200PLC和V90总线伺服通过工艺对象实现定位控制(标准报文3应用)_1200报文3控制v90-CSDN博客文章浏览阅读182次。V90伺服驱动器调试软件SINAMICS V-ASSISTANT Commissioning tool下载地址如下:西门子官网选型|资料CS…

linux下的进程通讯

一. 实验内容 1&#xff0e;编写一个程序&#xff0c;实现在两个进程之间运用管道进行通讯。程序中创建一个子进程&#xff0c;然后父、子进程各自独立运行。父进程不断地在标准输入设备上读入小写字母&#xff0c;写入管道。子进程不断地从管道中读取字符&#xff0c;转换为大…

Qt坐标系统

目录 概述 渲染 逻辑表示 锯齿绘制 坐标转换 模拟时钟示例 Window-Viewport转换 概述 坐标系统由QPainter类控制。与QPaintDevice和QPaintEngine类一起&#xff0c;QPainter构成了Qt绘画系统的基础。QPainter用于执行绘制操作&#xff0c;QPaintDevice是一个二维空间的抽…

10地!2024年一级造价师报名通知发布!

各位考生注意&#xff0c;西藏、四川、江西、新疆&#xff0c;辽宁、江苏、云南、新疆兵团、海南10个地区已经发布了关于2024年度一级造价工程师职业资格考试报名工作的通知&#xff1a; 浙江 辽宁 江苏 云南 报名时间&#xff1a;6月28日9:00—7月8日17:00&#xff1b; 缴费时…

基于Python+Django+MySQL+HTML的创新创业平台

DjangoMySQLHTML 基于PythonDjangoMySQLHTML的创新创业平台 用户管理 系统监控 角色管理 资源管理 参数设置 角色管理 简介 学生创新创业平台是一个功能丰富的在线教育或协作系统&#xff0c;支持中文语言环境。它提供用户管理、系统监控、多角色权限控制、资源管理、参…

手写方法实现字符串例如:“123“与整型例如:123相互转化(面试必会)

目录 二、字符串类型转化为整型 1. 初始化变量 2.定义字符串索引值 3.思考如何将字符1转化为数字1 4. 转化思路 5.考虑字符串转化负数例&#xff1a;-123456 6.完整代码 四、最后 一、前言 在c语言和c中&#xff0c;有许许多多的数据类型相互转化的方法&#xff0c;这里…

算法篇-排序

快排 算法思想&#xff1a;每次找一个基数&#xff0c;然后对数组左右遍历&#xff0c;将小于基数的数据放到左边&#xff0c;大于基数的数放到右边&#xff0c;然后将基数左边&#xff0c;右边进行迭代再排序。 public static void quickSort(int[] nums, int left, int ri…