【C++】手撕string思路梳理

2023-12-16

目录

基本思路

代码实现

1.构建框架:

2.构建函数重载

3.迭代器:

4.遍历string

5.resetve 开空间,insert任意位置插入push_back,append,+=(按顺序依次实现)

6.erase删除,clear清除,resize缩容

7.流插入,流提取

全部代码


本文是对模拟string步骤进行梳理 若要详细讲解请跳转至: 【C++】string模拟-CSDN博客

string讲解: 【C++】String类-CSDN博客

基本思路

  1. 构建string类框架

    构造函数, 拷贝构造,析构 ,返回字符串的 C 风格表示,返回字符串长度,返回总容量

  2. 构建函数重载

    operator=,operator [], > == >= < <= !=

  3. 迭代器:

    begin() && end()

  4. 遍历string

  5. resetve 开空间,insert任意位置插入,push_back,append,+=,交换

  6. erase删除,clear清除,resize缩容

  7. 流插入,流提取

代码实现

1.构建框架:


   
class string
 {
 private:
   char *_str;
   size_t _size;
   size_t _capacity;
 public:
   string(const char *str = "")
       : _size(strlen(str))
   {
       _capacity = _size = 0 ? 3 : _size;
       _str = new char[_size + 1];
       strcpy(_str, str);
   }
 ​
   // 拷贝
   string(const string &s)
       : _size(s._size), _capacity(s._capacity)
   {
       _str = new char[_capacity + 1];
       strcpy(_str, s._str);
   }
 ​
   ~string()
   {
       delete[] _str;
       _str = nullptr;
       _capacity = _size = 0;
   }
   
   const char *c_str()
   {
       return _str;
   }
   //?
   size_t size() const // const?
   {
       return _size;
   }
   size_t capacity() const
   {
       return _capacity;
   }
 };

2.构建函数重载

 string &operator=(const string &s)
 {
     if (this != &s)
     {
         char *tmp = new char[s._capacity + 1];
         strcpy(tmp, s._str);
         delete[] _str;
         _str = tmp;
         _size = s._size;
         _capacity = s._capacity;
     }
     return *this;
 }
 ​
 char &operator[](size_t pos)
 {
     assert(pos < _size);
     return _str[pos];
 }
 ​
 const char &operator[](size_t pos) const
 {
     assert(pos < _size);
     return _str[pos];
 }
 ​
 bool operator<(string &s) const
 {
     return strcmp(_str, s._str) < 0;
 }
 bool operator==(string &s) const
 {
     return strcmp(_str, s._str) == 0;
 }
 bool operator<=(string &s) const
 {
     return *this < s || *this == s;
 }
 bool operator>(string &s) const
 {
     return !(*this <= s);
 }
 bool operator>=(string &s) const
 {
     return !(*this < s);
 }
 bool operator!=(string &s) const
 {
     return !(*this == s);
 }

3.迭代器:

 typedef char *iterator;
 typedef const char *const_iterator;
 ​
 iterator begin()
 {
     return _str;
 }
 iterator end()
 {
     return _str + _size;
 }

4.遍历string

 void Print(const string &s)
 {
     //方法1
     for (size_t i = 0; i < s.size(); i++)
     {
         cout << s[i] << " ";
     }
     cout << endl;
     
     //方法二:迭代器遍历
     const_iterator rit = s.begin();
     while (rit != s.end())
     {
         cout << *rit << " ";
         ++rit;
     }
 }

5.resetve 开空间,insert任意位置插入push_back,append,+=(按顺序依次实现)

 void reserve(size_t n)
 {
     if (n > _capacity)
     {
         char *tmp = new char[n + 1];
         strcpy(tmp, _str);
         delete[] _str;
         _str = tmp;
         _capacity = n;
     }
 }
 ​
 string &insert(size_t pos, char ch)
 {
     assert(pos <= _size);
     // 判断大小
     if (_size + 1 > _capacity)
     {
         reserve(2 * _capacity);
     }
     size_t end = _size + 1;
 ​
     while (end > pos)
     {
         _str[end] = _str[end + 1];
         end--;
     }
     _str[pos] = ch;
     ++_size;
     return *this;
 }
 ​
 string &insert(size_t pos, const char *str)
 {
     assert(pos <= _size);
     size_t len = strlen(str);
     if (_size + len > _capacity)
     {
         reserve(_size + len);
     }
     size_t end = _size + len;
     while (end > pos + len - 1)
     {
         _str[end - len] = _str[end];
         --end;
     }
     strncpy(_str + pos, str, end);
     _size += len;
 ​
     return *this;
 }
 ​
 void push_back(char ch)
 {
     insert(_size, ch);
 }
 ​
 void append(const char *str)
 {
     insert(_size, str);
 }
 ​
 string &operator+=(char ch)
 {
     push_back(ch);
     return *this;
 }
 ​
 string &operator+=(const char *str)
 {
     append(str);
     return *this;
 }
交换:

 void swap(string &s)
 {
     std::swap(_str, s._str);
     std::swap(_capacity, s._capacity);
     std::swap(_size, s._size);
 }

6.erase删除,clear清除,resize缩容

 string &erase(size_t pos, size_t len = npos)
 {
     assert(pos < _size);
     if (len == npos || len >= _size)
     {
         _str[pos] = '\0';
         _size = pos;
     }
     else
     {
         strcpy(_str + pos, _str + pos + len);
         _size -= len;
     }
     return *this;
 }
 ​
 void resize(size_t n, char ch = '\0')
 {
     if (n < _size)
     {
         _size = n;
         _str[_size] = '\0';
     }
     else if (n > _size)
     {
         if (n > _capacity)
         {
             reserve(n);
         }
         size_t i = _size;
         while (i < n)
         {
             _str[i] = ch;
             ++i;
         }
         _size = n;
         _size = '\0';
     }
 }
 ​
 void clear()
 {
     _str[0] = '\0';
     _size = 0;
 }

7.流插入,流提取

 ostream &operator<<(ostream &out, const string &s)
 {
     for (size_t i = 0; i < s.size(); ++i)
     {
         out << s[i];
     }
     return out;
 }
 ​
 istream &operator>>(istream &in, string &s)
 {
     s.clear();
     char ch = in.get();
     char buff[128];
     size_t i = 0;
 ​
     while (ch != ' ' && ch != '\n')
     {
         buff[i++] = ch;
         if (i == 127)
         {
             buff[127] = '\0';
             s += buff;
             i = 0;
         }
         ch = in.get();
     }
 ​
     if (i != 0)
     {
         buff[i] = ch;
         buff[i + 1] = '\0';
         s += buff;
     }
     return in;
 }

全部代码

string.h

 #include <iostream>
 #include <assert.h>
 using namespace std;
 ​
 namespace wzf
 {
     class string
     {
     private:
         char *_str;
         size_t _size;
         size_t _capacity;
 ​
         static size_t npos;
 ​
     public:
         typedef char *iterator;
         typedef const char *const_iterator;
 ​
         iterator begin()
         {
             return _str;
         }
         iterator end()
         {
             return _str + _size;
         }
 ​
         const_iterator begin() const
         {
             return _str;
         }
         const_iterator end() const
         {
             return _str + _size;
         }
 ​
         string(const char *str = "")
             : _size(strlen(str))
         {
             _capacity = _size = 0 ? 3 : _size;
             _str = new char[_size + 1];
             strcpy(_str, str);
         }
 ​
         // 拷贝
         string(const string &s)
             : _size(s._size), _capacity(s._capacity)
         {
             _str = new char[_capacity + 1];
             strcpy(_str, s._str);
         }
 ​
         ~string()
         {
             delete[] _str;
             _str = nullptr;
             _capacity = _size = 0;
         }
 ​
         string &operator=(const string &s)
         {
             if (this != &s)
             {
                 char *tmp = new char[s._capacity + 1];
                 strcpy(tmp, s._str);
                 delete[] _str;
                 _str = tmp;
                 _size = s._size;
                 _capacity = s._capacity;
             }
             return *this;
         }
 ​
         char &operator[](size_t pos)
         {
             assert(pos < _size);
             return _str[pos];
         }
 ​
         const char &operator[](size_t pos) const
         {
             assert(pos < _size);
             return _str[pos];
         }
 ​
         bool operator<(string &s) const
         {
             return strcmp(_str, s._str) < 0;
         }
         bool operator==(string &s) const
         {
             return strcmp(_str, s._str) == 0;
         }
         bool operator<=(string &s) const
         {
             return *this < s || *this == s;
         }
         bool operator>(string &s) const
         {
             return !(*this <= s);
         }
         bool operator>=(string &s) const
         {
             return !(*this < s);
         }
         bool operator!=(string &s) const
         {
             return !(*this == s);
         }
 ​
         void reserve(size_t n)
         {
             if (n > _capacity)
             {
                 char *tmp = new char[n + 1];
                 strcpy(tmp, _str);
                 delete[] _str;
                 _str = tmp;
                 _capacity = n;
             }
         }
 ​
         string &insert(size_t pos, char ch)
         {
             assert(pos <= _size);
             // 判断大小
             if (_size + 1 > _capacity)
             {
                 reserve(2 * _capacity);
             }
             size_t end = _size + 1;
 ​
             while (end > pos)
             {
                 _str[end] = _str[end + 1];
                 end--;
             }
             _str[pos] = ch;
             ++_size;
             return *this;
         }
 ​
         string &insert(size_t pos, const char *str)
         {
             assert(pos <= _size);
             size_t len = strlen(str);
             if (_size + len > _capacity)
             {
                 reserve(_size + len);
             }
             size_t end = _size + len;
             while (end > pos + len - 1)
             {
                 _str[end - len] = _str[end];
                 --end;
             }
             strncpy(_str + pos, str, end);
             _size += len;
 ​
             return *this;
         }
 ​
         void push_back(char ch)
         {
             insert(_size, ch);
         }
 ​
         void append(const char *str)
         {
             insert(_size, str);
         }
 ​
         string &operator+=(char ch)
         {
             push_back(ch);
             return *this;
         }
 ​
         string &operator+=(const char *str)
         {
             append(str);
             return *this;
         }
 ​
         string &erase(size_t pos, size_t len = npos)
         {
             assert(pos < _size);
             if (len == npos || len >= _size)
             {
                 _str[pos] = '\0';
                 _size = pos;
             }
             else
             {
                 strcpy(_str + pos, _str + pos + len);
                 _size -= len;
             }
             return *this;
         }
 ​
         void resize(size_t n, char ch = '\0')
         {
             if (n < _size)
             {
                 _size = n;
                 _str[_size] = '\0';
             }
             else if (n > _size)
             {
                 if (n > _capacity)
                 {
                     reserve(n);
                 }
                 size_t i = _size;
                 while (i < n)
                 {
                     _str[i] = ch;
                     ++i;
                 }
                 _size = n;
                 _size = '\0';
             }
         }
 ​
         void clear()
         {
             _str[0] = '\0';
             _size = 0;
         }
 ​
         const char *c_str()
         {
             return _str;
         }
         //?
         size_t size() const // const?
         {
             return _size;
         }
         size_t capacity() const
         {
             return _capacity;
         }
     };
     size_t string::npos = -1;
 ​
     ostream &operator<<(ostream &out, const string &s)
     {
         for (size_t i = 0; i < s.size(); ++i)
         {
             out << s[i];
         }
         return out;
     }
 ​
     istream &operator>>(istream &in, string &s)
     {
         s.clear();
         char ch = in.get();
         char buff[128];
         size_t i = 0;
 ​
         while (ch != ' ' && ch != '\n')
         {
             buff[i++] = ch;
             if (i == 127)
             {
                 buff[127] = '\0';
                 s += buff;
                 i = 0;
             }
             ch = in.get();
         }
 ​
         if (i != 0)
         {
             buff[i] = ch;
             buff[i + 1] = '\0';
             s += buff;
         }
         return in;
     }
 ​
     void TestString1()
     {
         string s1("Hello");
         cout << s1.c_str() << endl;
         string s2 = s1;
         string s3(s1);
         cout << s3.c_str() << endl;
         s1[0]++;
         cout << s1.c_str() << endl;
     }
     void TestString2()
     {
         string s1("Hello");
         cout << s1.c_str() << endl;
         string s2("NI");
         cout << (s1 > s2) << endl;
         cout << (s1 >= s2) << endl;
         cout << (s1 == s2) << endl;
         cout << (s1 != s2) << endl;
         cout << (s1 <= s2) << endl;
     }
     void TestString3()
     {
         string s1("Hello");
         cout << s1.c_str() << endl;
         s1 += '!';
         s1 += "2345";
         cout << s1.c_str() << endl;
     }
     void TestString4()
     {
         string s1("HelloWord");
         string s2("HelloWord");
         s1.erase(3, 1);
         cout << s1.c_str() << endl;
         s1.erase(3, 100);
         cout << s1.c_str() << endl;
         s2.resize(4);
         cout << s2.c_str() << endl;
         s2.resize(10, 'x');
         cout << s2.c_str() << endl;
     }
     void TestString5()
     {
         string s1("HelloWord");
         cout << s1 << endl;
         cin >> s1;
         string::iterator it = s1.begin();
         while (it != s1.end() - 1)
         {
             cout << *it << "";
             ++it;
         }
         cout << endl;
     }
 }

string.cpp

 #include "string.h"
 ​
 int main()
 {
     try // char* tmp = new char[s._capacity + 1];是否开辟异常
     {
         wzf::TestString5();
     }
     catch (const std::exception &e)
     {
         std::cerr << e.what() << '\n';
     }
 ​
     return 0;
 }
本文内容由网友自发贡献,版权归原作者所有,本站不承担相应法律责任。如您发现有涉嫌抄袭侵权的内容,请联系:hwhale#tublm.com(使用前将#替换为@)

【C++】手撕string思路梳理 的相关文章

  • 将所有 BigDecimal 运算设置为特定精度?

    我的Java程序以高精度计算为中心 需要精确到至少120位小数 因此 程序中所有非整数都将由 BigDecimal 表示 显然 我需要指定 BigDecimal 的舍入精度 以避免无限小数表达式等 目前 我发现必须在 BigDecimal
  • Java中如何动态添加charsequence[]中的数据?

    初始化的一种方法charsequence is charsequence item abc def 但我不想以这种方式初始化它 有人可以建议其他方式吗 比如我们初始化的方式string arrays 首先 修复变量声明 charsequen
  • Java泛型 - 实现像map这样的高阶函数

    我决定用 Java 编写一些常见的高阶函数 map filter reduce 等 这些函数通过泛型实现类型安全 但我在一个特定函数中遇到通配符匹配问题 为了完整起见 函子接口是这样的 The interface containing th
  • 如何调试使用maven构建的android应用程序

    我目前正在尝试从 Eclipse 调试我的设备上的 Android 应用程序 设备已添加 我可以在控制台和 Eclipse 中看到它 控制台 Windows adb devices List of devices attached 0019
  • 使用 TreeMap 和 Comparator 按值对 HashMap 进行排序

    我使用以下代码创建哈希图 然后使用树形图和比较器对哈希图中的值进行排序 然而 输出结果却出乎意料 所以任何关于我做错了什么的想法都会有帮助 Code public static void main String args System ou
  • 使用 Intellij 2017.2 /out 目录构建会重复 /build 目录中的文件

    更新到 Intellij 2017 2 后 构建我的项目会创建一个 out包含生成的源文件和资源文件的目录 这些文件与已包含的文件重复 build并导致duplicate class生成的类的编译器错误 关于 Gradle 或 Intell
  • 在 Java 8 中将对象追加到列表并返回结果?

    有没有一种方法可以将对象附加到列表并以功能性非命令方式在一行中返回结果 如果原始列表也不应该被改变 你会怎么做 Java 8 是允许的 我已经知道如何将两个列表连接到一行中 Source https stackoverflow com a
  • 为什么 hibernate 在一张表中保存两个 @OneToMany 列表?

    想象一下使用 Hibernate 和 JPA 的简化代码如下 Entity class C Id GeneratedValue public long id MappedSuperclass abstract class A Id Gene
  • IntelliJ Ultimate 在 Play 2.3 (Java) 项目测试中找不到路由

    虽然我的测试运行得很好 但 IntelliJ 抱怨它找不到路由对象 并且代码自动完成无法工作 我已经查看了所有文档 这应该可以工作 这是 IntelliJ 的报告内容 关于我的项目配置可能有什么问题有什么想法吗 这很可能与以下事实有关 ro
  • 向 JList 添加滚动条? [关闭]

    Closed 这个问题不符合堆栈溢出指南 help closed questions 目前不接受答案 如何将 JList 添加到 JScrollPane 把你的JList in a JScrollPane JScrollPane scrol
  • 如何显示/隐藏jsf组件

    在我的一个 JSF 应用程序中 顶部的标题部分包含 selectOneMenu 底部的内容部分显示过滤器组件 默认情况下 应用程序首先在顶部显示 selectOneMenu 数据 在底部显示相应的 Filter 信息 如果用户选择不同的se
  • 属性文件中的字符串主机名:Java

    这听起来可能是一个非常简单的问题 但我无法找到解决方法 我有一个 config properties 文件 其中包含两个键值 IP 地址和端口号 我读取此配置文件以提取字符串格式的键值 但是 当我尝试使用这些值时 我无法连接到从配置文件中检
  • Spring Boot 多部分文件始终为 null

    我正在使用 Spring Boot version 1 4 0 RC1 和 Spring Boot Stormpath 1 0 2 我正在尝试使用分段文件上传 但控制器中的 MultipartFile 始终为空 当我使用 RequestPa
  • 将 XML 从网站解析到 Android 设备

    我正在启动一个 Android 应用程序 它将解析来自网络的 XML 我创建了一些 Android 应用程序 但它们从未涉及解析 XML 我想知道是否有人对最佳方法有任何建议 这是一个例子 try URL url new URL your
  • iText7 将 SVG 添加到 PdfDocument 中以及可能出现的问题

    关于问题的答案 如何使用 iText7 将 SVG 添加到 PDF 这是一个链接点击这里 https stackoverflow com questions 50059456 how to add an svg to a pdf using
  • 如何在不同的班级中启动和停止计时器?

    我想测量从传入 HTTP 请求开始到应用程序到达某个点的时间 这两个时间点都位于不同的类中 我将如何启动和停止这些不同类别的计时器 我没有看到使用 MeterRegistry 中的 命名 计时器的方法 我该怎么办呢 您可以使用 AOP 如下
  • Java 中 .NET 的 Lambda 表达式

    我最近 再次 从 C 迁移到 Java 但我非常怀念 lambda 表达式和 C 的 IEnumerable Foreach 之类的东西 所以我正在寻找Java中的lambda表达式库 有比这更好的图书馆吗LambdaJ http code
  • 如何从 jenkins 的现有项目生成 .hpi 插件

    我正在尝试使用 jenkins 的性能插件 但最新版本存在一些问题 如链接中所述 https issues jenkins ci org browse JENKINS 27100 https issues jenkins ci org br
  • Java 应用程序启动,ProcessBuilder 一段时间后被阻止

    我正在开发一个 Java 桌面应用程序 我们称之为控制台 包含 3 个按钮 其中两个启动 Win32 应用程序 第三个应该启动一个可执行的 jar ProcessBuilder pb new ProcessBuilder java jar
  • 混合语言源目录布局

    我们正在运行一个使用多种不同语言的大型项目 Java Python PHP SQL 和 Perl 到目前为止 人们一直在自己的私有存储库中工作 但现在我们希望将整个项目合并到一个存储库中 现在的问题是 目录结构应该是什么样的 我们应该为每种

随机推荐

  • unittest 数据驱动DDT应用

    前言 一般进行接口测试时 每个接口的传参都不止一种情况 一般会考虑正向 逆向等多种组合 所以在测试一个接口时通常会编写多条case 而这些case除了传参不同外 其实并没什么区别 这个时候就可以利用ddt来管理测试数据 提高代码复用率 但要
  • Appium知多少

    Appium我想大家都不陌生 这是主流的移动自动化工具 但你对它真的了解么 为什么很多同学搭建环境时碰到各种问题也而不知该如何解决 appium为什么英语词典查不到中文含义 appium是一个合成词 分别取自 application 的前三
  • google Protobuf

    之前一直把第三方开源库protobuf编译 但是么用过没了解过 这次正好看到这篇文章 文章目录 前言 一 pandas是什么 二 使用步骤 1 引入库 2 读入数据 总结 前言 网易看到的protobuf的新闻 然后百度查到原文 记录一下
  • Jenkins部署python接口自动化测试

    一 点击新建Item 二 指定源码和分支 私钥位置 C Users Administrator ssh 文件下 三 构建脚本编写 四 构建后操作 指定输出的 allure 结果目录 总结 感谢每一个认真阅读我文章的人 作为一位过来人也是希望
  • arm平台编译so文件回顾

    提示 文章写完后 目录可以自动生成 如何生成可参考右边的帮助文档 文章目录 前言 一 几个点 二 回顾过程 1 上来就执行Makefile 2 编译第三方开源库 a文件 2 1 build sh脚本 2 2 Make
  • 聊聊Api接口优化的几个方法!

    我负责的系统到2021年初完成了功能上的建设 开始进入到推广阶段 随着推广的逐步深入 收到了很多好评的同时也收到了很多对性能的吐槽 刚刚收到吐槽的时候 我们的心情是这样的 当越来越多对性能的吐槽反馈到我们这里的时候 我们意识到 接口性能的问
  • 14:00面试,14:08就出来了,问的问题有点变态。。。。。。

    从小厂出来 没想到在另一家公司又寄了 到这家公司开始上班 加班是每天必不可少的 看在钱给的比较多的份上 就不太计较了 没想到5月一纸通知 所有人不准加班 加班费不仅没有了 薪资还要降40 这下搞的饭都吃不起了 还在有个朋友内推我去了一家互联
  • 性能测试工具 —— 掌握JMeter性能测试工具的入门要点!

    JMeter 是一款很优秀的开源性能测试工具 从性能工具的原理划分 Jmeter工具和其他性能工具在原理上完全一致 工具包含4个部分 1 负载发生器 通过多线程模拟并发 对目标产品产生负载 2 用户运行器 通常是一个脚本运行引擎 用户运行器
  • 报错处理集

    这个报错处理集的错误来源于编译arm平台的so文件产生的 但是后续可以补充成linux一个大的错误处理集 文章目录 前言 一 pandas是什么 二 使用步骤 1 引入库 2 读入数据 总结 前言 第一次整理的时间是2023年12月8日10
  • 测出Bug就完了?从4个方面教你Bug根因分析

    01 现状及场景 1 缺失bug根因分析环节 工作10年 虽然不是一线城市 也经历过几家公司 规模大的 规模小的都有 针对于测试行业很少有Bug根因环节 主流程基本上都是测试提交bug 开发修改 测试验证 发送报告 测试环节结束 往往有下面
  • 欧拉操作系统

    提示 文章写完后 目录可以自动生成 如何生成可参考右边的帮助文档 文章目录 前言 一 pandas是什么 二 使用步骤 1 引入库 2 读入数据 总结 前言 提示 这里可以添加本文要记录的大概内容 这个章节主要是介绍一下欧拉操作系统 欧拉系
  • STM32超声波——HC_SR04

    文章目录 一 超声波图片 二 时序图 三 超声波流程 四 单位换算 五 取余计算 六 换算距离 七 超声波代码 一 超声波图片 测量距离 2cm 400cm 二 时序图 1 以下时序图要先提供一个至少10us的脉冲触发信号 告诉单片机我准备
  • 商城免 费搭建之java鸿鹄云商 java电子商务商城 Spring Cloud+Spring Boot+mybatis+MQ+VR全景+b2b2c

    saas云平台 打造全行业全渠道全场景的saas产品 为经营场景提供一体化解决方案 门店经营区域化 网店经营一体化 本地化 全方位 一站式服务 为多门店提供统一运营解决方案 提供丰富多样的营销玩法覆盖所有经营场景 助力商家成功 系统稳定压倒
  • Jmeter+ant+jenkins接口自动化测试

    平台简介 一个完整的接口自动化测试平台需要支持接口的自动执行 自动生成测试报告 以及持续集成 Jmeter 支持接口的测试 Ant 支持自动构建 而 Jenkins 支持持续集成 所以三者组合在一起可以构成一个功能完善的接口自动化测试平台
  • Java版企业电子招标采购系统源码—鸿鹄电子招投标系统-企业战略布局下的采购寻源

    项目说明 随着公司的快速发展 企业人员和经营规模不断壮大 公司对内部招采管理的提升提出了更高的要求 在企业里建立一个公平 公开 公正的采购环境 最大限度控制采购成本至关重要 符合国家电子招投标法律法规及相关规范 以及审计监督要求 通过电子化
  • Java版企业电子招标采购系统源码Spring Cloud + Spring Boot +二次开发+ MybatisPlus + Redis tbms

    功能描述 1 门户管理 所有用户可在门户页面查看所有的公告信息及相关的通知信息 主要板块包含 招标公告 非招标公告 系统通知 政策法规 2 立项管理 企业用户可对需要采购的项目进行立项申请 并提交审批 查看所有的立项信息 主要功能包含 招标
  • Java版直播商城规划:电商源码、小程序、三级分销与免费搭建全攻略

    SAAS云平台 打造全行业全渠道全场景的SaaS产品 为店铺经营场景提供一体化解决方案 门店经营区域化 网店经营一体化 本地化 全方位 一站式服务 为多门店提供统一运营解决方案 提供丰富多样的营销玩法覆盖所有经营场景 助力商家成功 系统稳定
  • 如何使用Fiddler进行弱网测试

    测试APP web经常需要用到弱网测试 也就是在信号差 网络慢的情况下进行测试 我们自己平常在使用手机APP时 在地铁 电梯 车库等场景经常会遇到会话中断 超时等情况 这种就属于弱网 普通的弱网测试可以选择第三方工具对带宽 丢包 延时等模拟
  • 字节跳动面试挂在2面,复盘后,决定二战.....

    先说下我基本情况 本科不是计算机专业 现在是学通信 然后做图像处理 可能面试官看我不是科班出身没有问太多计算机相关的问题 因为第一次找工作 字节的游戏专场又是最早开始的 就投递了 投递的是游戏测试开发岗 字节是自己投的第一家公司 也是第一家
  • 【C++】手撕string思路梳理

    目录 基本思路 代码实现 1 构建框架 2 构建函数重载 3 迭代器 4 遍历string 5 resetve 开空间 insert任意位置插入push back append 按顺序依次实现 6 erase删除 clear清除 resiz