【c++】string模拟实现

string类的接口

namespace zjw
{class string{public:typedef char* iterator;typedef   const char* const_iterator;private:char* _str;int _size;int _capacity;};

这里的迭代器直接使用原生指针来封装。
_str为指向string数组的首地址的指针。
_size为string数组的大小。
_capacity为string数组的容量

基本函数

实现 函数返回string的首地址;
实现 函数返回string的尾地址;
实现 函数返回string的大小;
实现 函数返回string的容量;

	iterator begin(){return _str;}iterator end(){return _str+_size;}size_t size(){return _size;}size_t capacity(){return _capacity;}

如果一个string类不能被修改的话,就无法调用非const的成员函数
在这里插入图片描述

	const_iterator begin() const{return _str;}const_iterator end() const{return _str + _size;}

默认构造以及析构函数

	string(const char* str = ""):_size(strlen(str)){_capacity = _size;_str = new char[_capacity + 1];strcpy(_str, str);}~string(){ delete[]_str;_str = nullptr;_size = _capacity = 0;}

这里有一个问题,就是默认构造传的缺省参数可以是nullptr 吗??
答案是不行的,因为strlen要将str解引用找’\0’,如果传nullptr的话,对空指针解引用就会出错。
这里也不可以传单字符‘\0’,因为这里的str是const char* 类型,而’\0’是char 类型


运算符重载下标访问函数

	char& operator[](size_t pos){assert(pos<_size);return _str[pos];}const char& operator[](size_t pos) const{assert(pos < _size);return _str[pos];}

下标为_size的地方存的是’\0’,所以不用访问,pos<_size,为了让const迭代器不修改对于下标的值,修改上面得到下面,对上面进行函数重载

reserve函数

	void reserve(size_t n){if (n > _capacity){char* tmp = new char[n + 1];strcpy(tmp, _str);delete[]_str;_str = tmp;_capacity = n;}}

在这里插入图片描述
注意:这里多开一个是为了存’\0’;

push_back()函数

	void push_back(char ch){if (_capacity == _size){reserve(_capacity == 0 ? 4 : _capacity * 2);}_str[_size] = ch;_size++;_str[_size] = '\0';}

原来下标是_size的地方是‘\0’,然后之间在_size的地方放入ch,_size++,染后在补一个’\0’;要插入数据的一半都要扩容

append函数

	void append(const char* str){size_t len = strlen(str);if (_size + len > _capacity){reserve(_size + len);}strcpy(_str + _size, str);_size += len;//_str[_size] = '\0';}

尾插一个字符串,如果string的大小+要插入的字符串大小>_capacity,就扩容到_size + len,刚好,strcpy会从str开始直到遇到‘\0’一个字节一个字节拷贝到_str + _size(原字符串’\0’的地方),这里会把str字符串后面的‘\0’也拷贝过来。

运算符重载+=字符以及+=字符串

	string& operator+=(char ch){push_back(ch);return *this;}string& operator+=(const char* str){append(str);return *this;}

在这里传引用返回是因为_str指向的空间是在堆上开的,出函数不会被销毁,所以可以传引用返回

insert函数(插入字符)

void insert(size_t pos, char ch){assert(pos<=_size);if (_capacity == _size){reserve(_capacity == 0 ? 4 : _capacity * 2);}size_t end = _size;while (end >=pos){_str[end+1] = _str[end];end--;}_str[pos] = ch;_size++;}

上面这个写法可以吗??
是不可以的
在这里插入图片描述
怎么修改呢??

	void insert(size_t pos, char ch){assert(pos<=_size);if (_capacity == _size){reserve(_capacity == 0 ? 4 : _capacity * 2);}size_t end = _size+1;while (end >pos){_str[end] = _str[end-1];end--;}_str[pos] = ch;_size++;}

这样就可以了,我们从’\0’的下一个位置开始end,此时end结束的条件是=0,所以不会陷入循环,这里和顺序表的insert很像,可以参考顺序表那里。


earse函数

	void earse(size_t pos, size_t len = npos){assert(pos < _size);if (len == npos || pos > _size-len){_str[pos] = '\0';_size = pos;}else{strcpy(_str + pos, _str + pos + len);_size -= len;}}

删除从pos位置开始的len个字符长度的字符,如果len大于剩下的字符,就全删了,这里给的缺省值为npos=-1,可以认为是很大的数,绝对超过了pos后面的字符数,我们要在string里面声明一个npos,在类外面定义初始化。
在这里插入图片描述

如果len==npos或者len+pos>_size,就始要将pos开始后面的字符串全删除,我们直接在pos位置放’\0’即可,
_size=pos;
如果没有超过字符串
在这里插入图片描述


insert(插入字符串)

void insert(size_t pos, const char* str){size_t len = strlen(str);if (_size + len > _capacity){reserve(_size + len);}size_t end = _size + len;while (end > pos + len - 1){_str[end] = _str[end - len];end--;}strncpy(_str + pos, str, len);_size += len;}

![在这里插入图片描述](https://img-blog.csdnimg.cn/direct/9d88ba8502954c0dbd884890654c612a.png

void test6(){string str;str.push_back('a');str.push_back('a');str.push_back('b');str.insert(2, "hello");cout << str.c_str();}

swap

	void swap(string& str){std::swap(_str, str._str);std::swap(_size, str._size);std::swap(_capacity, str._capacity);}
	void test12(){   string str1;string str2;str1 += "hello";str2+="nihao";cout << "str1:"<<str1 << endl;cout << "str2:"<<str2 << endl;str1.swap(str2);cout << "str1:" << str1 << endl;cout << "str2:" << str2 << endl;}

在这里插入图片描述


这里我们自己实现的swap是类成员函数,但是#include< algorithm >这个头文件库里面也有一个swap,swap全局也有一个非成员函数swap

在这里插入图片描述

我们可以发现算法库中的swap需要完成三次的拷贝,以及一次析构(临时变量c的析构),而string里面定义一个全局的swap,就是为了防止调用算法库里面的swap,因为会先在全局找,然后会在展开的库里找,而全局的swap实现只需要调用类里面的swap即可

	void swap(string& x, string& y){x.swap(y);cout << "没使用库里的" << endl;}
	void test13(){string str1;string str2;str1 += "hello";str2 += "nihao";cout << "str1:" << str1 << endl;cout << "str2:" << str2 << endl;swap(str1, str2);//检测是调用库里的,还是全局的cout << "str1:" << str1 << endl;cout << "str2:" << str2 << endl;}

在这里插入图片描述

赋值以及拷贝构造

	string(const string& s){string tmp(s._str);swap(tmp);}string& operator=(string tmp){swap(tmp);return *this;}

根据调试发现
在这里插入图片描述

老版本赋值

		string& operator=(const string& s){char* tmp = new char[s._capacity + 1];strcpy(tmp, s._str);delete[] _str;_str = tmp;_size = s._size;_capacity = s._capacity;return *this;}

find函数(查找字符)

	size_t find(char ch, size_t pos = 0){for (int i = pos; i < _size; i++){if (_str[i] == ch)return i;}return npos;}

从pos位置开始查找,如果pos使用缺省,则从第一个位置开始查找,从pos位置开始遍历,如果找到返回下标,如果找不到返回npos

	void test7(){string str;str.push_back('a');str.push_back('a');str.push_back('b');str.insert(2, "hello");cout << endl;int ret = str.find('b', 0);cout << ret;}

在这里插入图片描述


find函数(查找子串)

		size_t find(const char* sub, size_t pos = 0) const{assert(pos < _size);//下标为_size的是‘\0’const char* ptr = strstr(_str + pos, sub);if (ptr != nullptr)//找到了,但是strstr返回的是找到子串的起始地址-字符串起始地址就是子串相对起始位置的长度{return ptr - _str;}else{return npos;}}
	void test8(){string str;str += "beijing huanyingni zhangjiawang";int ret = str.find("zhangjiawang");cout << ret;}

在这里插入图片描述


substr函数

string substr(size_t pos = 0, size_t len = npos) const{string substr;if (pos > _size - len){for (int i = pos; i <= _size; i++){substr += _str[i];}}else{for (int i = pos; i < pos + len; i++){substr += _str[i];}substr += '\0';}return substr;}

从pos位置开始取,取len个长度,分两种情况,如果从pos开始还没取到len长,就结束,就取到结尾,遍历pos到_size,string substr 保存遍历的值.
第二种,遍历pos到pos+len,string substr 保存遍历的值.最后记得加‘\0’;
在这里插入图片描述

运算符重载比较函数

	bool operator==(const string& s1, const string& s2){return strcmp(s1.c_str(), s2.c_str())==0;}bool operator>(const string& s1, const string& s2){return strcmp(s1.c_str(), s2.c_str());}bool operator<(const string& s1, const string& s2){return  !(s1 > s2 && s1 == s2);}bool operator<=(const string& s1, const string& s2){return  !(s1 > s2);}bool operator>=(const string& s1, const string& s2){return  !(s1 < s2);}bool operator!=(const string& s1, const string& s2){return  !(s1 == s2);}

注意这里为什么要搞成全局的呢??

	void test10(){string str1;string str2;str1 += "abc";str2 += "aba";cout << (str1 == str2) << endl;cout << ("aba" == str2) << endl;//2cout << (str2== "aba") << endl;}

因为第二种的话不满足类成员做左操作数,全局的话就可以,而第三个是会搞一个类型转换.

	void test10(){string str1;string str2;str1 += "abc";str2 += "aba";cout << (str1 == str2) << endl;cout << ("aba" == str2) << endl;cout << (str2== "aba") << endl;cout << (str1>str2) << endl;cout << (str1 >=str2) << endl;cout << (str1<str2) << endl;cout << (str1 <=str2) << endl;cout << (str1!=str2) << endl;}

在这里插入图片描述


运算符重载流插入

	ostream& operator<<(ostream& out, const string& s){for (auto e : s)//遍历一个一个输出{out << e;}return out;}

有返回值是为了可以连续流插入

运算符重载流提取

版本一:

	istream& operator>>(istream& in, string& s){char ch;in >> ch;//读取字符到chwhile (ch != ' ' && ch != '\n')//读到‘ ’或‘\n’结束输入{s += ch;//将ch加进去in >> ch;//循环读取}return in;}

这样写会有一个问题,就是cin和scanf一样默认‘\n’和‘ ’是分割符不会进行读取,所以ch不会是空格或换行,所以陷入死循环.
在这里插入图片描述
版本2:
c语言中可以用getchar来读取,而c++中存在get就可以读空格

istream& operator>>(istream& in, string& s){char ch;in.get(ch);while (ch != ' ' && ch != '\n'){s += ch;in.get(ch);}return in;}
	void test11(){string str1;string str2;cin >> str1;//>>str2;//>>str2;cout << str1;//cout << str1.capacity();}

在这里插入图片描述


版本3
由于我们在s+=ch,会出现频繁扩容,影响效率,我们应该怎么解决呢??
我们可以提前开好空间,但是不知道应该开多大.假如说我们开128个

	istream& operator>>(istream& in, string& s){char ch;in.get(ch);s.reserve(128);while (ch != ' ' && ch != '\n'){s += ch;in.get(ch);}return in;}
	void test11(){string str1;string str2;cin >> str1;//>>str2;//>>str2;//cout << str1;cout << str1.capacity();}

在这里插入图片描述
两个数据开128就会有极大的浪费,多一点还好
在这里插入图片描述
版本4

	istream& operator>>(istream& in, string& s){s.clear();//可能我们s里面之前有数据,但是流提取是要覆盖的char ch;ch = in.get();char buff[128];int 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] = '\0';s += buff;}return in;}

这里感觉可以类比冯诺依曼体系,buff就相当于内存,先将输入的值放在内存buff里面,等到装满了,在一次性给s,减少搬运次数.避免了一次空间开的很大,而数据只有几个
在这里插入图片描述

在这里插入图片描述

在这里插入图片描述

clear

	void clear(){_size = 0;_str[0] = '\0';}

c_str

将const string* 转化为const char*

	const char* c_str() const{return _str;}

cout不能直接处理自定义类型string,但是可以使用c_str将string转成常量字符串,内置类型就可以直接打印


源码

.h

#pragma once
#define _CRT_SECURE_NO_WARNINGS
using namespace std;
#include<assert.h>
#include<iostream>
#include<algorithm>
namespace zjw
{class string{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;_str = new char[_capacity + 1];strcpy(_str, str);}~string(){delete[]_str;_str = nullptr;_size = _capacity = 0;}size_t size(){return _size;}size_t capacity(){return _capacity;}char& operator[](size_t pos){assert(pos < _size);return _str[pos];}const char& operator[](size_t pos) const{assert(pos < _size);return _str[pos];}void reserve(size_t n){if (n > _capacity){char* tmp = new char[n + 1];strcpy(tmp, _str);delete[]_str;_str = tmp;_capacity = n;}}void push_back(char ch){if (_capacity == _size){reserve(_capacity == 0 ? 4 : _capacity * 2);}_str[_size] = ch;_size++;_str[_size] = '\0';}void append(const char* str){size_t len = strlen(str);if (_size + len > _capacity){reserve(_size + len);}strcpy(_str + _size, str);_size += len;//_str[_size] = '\0';}string& operator+=(char ch){push_back(ch);return *this;}string& operator+=(const char* str){append(str);return *this;}void insert(size_t pos, char ch){assert(pos <= _size);if (_capacity == _size){reserve(_capacity == 0 ? 4 : _capacity * 2);}size_t end = _size + 1;while (end > pos){_str[end] = _str[end - 1];end--;}_str[pos] = ch;_size++;}const char* c_str() const{return _str;}void earse(size_t pos, size_t len = npos){assert(pos < _size);if (len == npos || pos > _size - len){_str[pos] = '\0';_size = pos;}else{strcpy(_str + pos, _str + pos + len);_size -= len;}}bool empty(){return _size == 0;}void resize(size_t n, char ch = '\0'){if (n <= _size){_str[n] = '\0';_size = n;}else{reserve(n);for (size_t i = _size; i < n; i++){_str[i] = ch;}_size = n;}}void insert(size_t pos, const char* str){size_t len = strlen(str);if (_size + len > _capacity){reserve(_size + len);}size_t end = _size + len;while (end > pos + len - 1){_str[end] = _str[end - len];end--;}strncpy(_str + pos, str, len);_size += len;}size_t find(char ch, size_t pos = 0){for (int i = pos; i < _size; i++){if (_str[i] == ch)return i;}return npos;}size_t find(const char* sub, size_t pos = 0) const{assert(pos < _size);const char* ptr = strstr(_str + pos, sub);if (ptr != nullptr){return ptr - _str;}else{return npos;}}string substr(size_t pos = 0, size_t len = npos) const{string substr;if (pos > _size - len){for (int i = pos; i <= _size; i++){substr += _str[i];}}else{for (int i = pos; i < pos + len; i++){substr += _str[i];}substr += '\0';}return substr;}void swap(string& str){std::swap(_str, str._str);std::swap(_size, str._size);std::swap(_capacity, str._capacity);}string(const string& s){string tmp(s._str);swap(tmp);}string& operator=(string tmp){swap(tmp);return *this;}string& operator=(const string& s){char* tmp = new char[s._capacity + 1];strcpy(tmp, s._str);delete[] _str;_str = tmp;_size = s._size;_capacity = s._capacity;return *this;}void clear(){_size = 0;_str[0] = '\0';}friend istream& operator>>(istream& in, string& s);public:static const int  npos;private:char* _str;int _size;int _capacity;};const int string::npos = -1;void swap(string& x, string& y){x.swap(y);cout << "没使用库里的" << endl;}istream& operator>>(istream& in, string& s){s.clear();char ch;ch = in.get();char buff[128];int 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] = '\0';s += buff;}return in;}//istream& operator>>(istream& in, string& s)//{//	//	char ch;//	//	in.get(ch);//	//	s.reserve(128);//	while (ch != ' ' && ch != '\n')//	{//	//	//		s += ch;//		in.get(ch);//	}//	//		//		//	//	return in;//}bool operator==(const string& s1, const string& s2){return strcmp(s1.c_str(), s2.c_str())==0;}bool operator>(const string& s1, const string& s2){return strcmp(s1.c_str(), s2.c_str());}bool operator<(const string& s1, const string& s2){return  !(s1 > s2 && s1 == s2);}bool operator<=(const string& s1, const string& s2){return  !(s1 > s2);}bool operator>=(const string& s1, const string& s2){return  !(s1 < s2);}bool operator!=(const string& s1, const string& s2){return  !(s1 == s2);}ostream& operator<<(ostream& out, const string& s){for (auto e : s){out << e;}return out;}//istream& operator>>(istream& in, string& s)//{//	s.clear();//	char ch;//	//	ch = in.get();//	//in >> ch;//	s.reserve(128);//	while (ch != ' ' && ch != '\n')//	{//		//		s += ch;//		ch = in.get();//		//in >> ch;//	}//	return in;//////////}void test1(){string str;str += 'a';str += 'b';str += "beijing";string::iterator it = str.begin();while (it != str.end()){cout << *it << " ";it++;}}void test2(){string str;str.push_back('a');str.push_back('a');str.push_back('b');str.push_back('a');str.push_back('a');string::iterator it = str.begin();while (it != str.end()){cout << *it << " ";it++;}cout << str[2];}void test3(){string str;str.append("stringbj");for (auto& e : str){cout << e << " ";}}void print_string(const string it){string::const_iterator res = it.begin();while (res != it.end()){cout << *res << " ";++res;}}void test4(){string str;str += "abc";str.append("stringbj");string::iterator it = str.begin();while (it != str.end()){cout << *it << " ";it++;}//str.insert(0, 'g');for (auto& e : str){cout << e << " ";}cout << endl;// str.earse(1,string::npos);*//* for (auto e : str){cout << e << " ";}*/// print_string(str);}void test5(){string str;str.push_back('a');str.push_back('a');str.push_back('b');str.resize(10);/* string::iterator it = str.begin();while (it != str.end()){cout << *it << " ";it++;}*/cout << str.c_str();}void test6(){string str;str.push_back('a');str.push_back('a');str.push_back('b');str.insert(2, "hello");cout << str.c_str();}void test7(){string str;str.push_back('a');str.push_back('a');str.push_back('b');str.insert(2, "hello");cout << endl;int ret = str.find('b', 0);cout << ret;}void test8(){string str;str += "beijing huanyingni zhangjiawang";int ret = str.find("zhangjiawang");cout << ret;}void test9(){string str;str += "beijing huanyingni zhangjiawang";string op = str.substr(0, 10);cout << op.c_str();}void test10(){string str1;string str2;str1 += "abc";str2 += "aba";cout << (str1 == str2) << endl;cout << ("aba" == str2) << endl;cout << (str2== "aba") << endl;cout << (str1>str2) << endl;cout << (str1 >=str2) << endl;cout << (str1<str2) << endl;cout << (str1 <=str2) << endl;cout << (str1!=str2) << endl;}void test11(){string str1;string str2;cin >> str1;//>>str2;//>>str2;//cout << str1;cout << str1.capacity();}void test12(){   string str1;string str2;str1 += "hello";str2+="nihao";cout << "str1:"<<str1 << endl;cout << "str2:"<<str2 << endl;str1.swap(str2);cout << "str1:" << str1 << endl;cout << "str2:" << str2 << endl;}void test13(){string str1;string str2;str1 += "hello";str2 += "nihao";cout << "str1:" << str1 << endl;cout << "str2:" << str2 << endl;swap(str1, str2);cout << "str1:" << str1 << endl;cout << "str2:" << str2 << endl;}void test14(){string str2;str2 += "nihao";string str1(str2);}}

.cpp

#include"标头.h"int main()
{zjw::test11();
}

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

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

相关文章

Python实例☞组织结构案例

实例一&#xff1a; ❶要求☞ 使用while循环模拟用户登录 ❷程序代码☞ i1 while i<4: nameinput("请输入您的姓名&#xff1a;") passwardinput("请输入你的密码&#xff1a;") if name"鯨殤" and passward"88888": print(&quo…

代码随想录刷题day18|找树左下角的值路径总和中序后序构造二叉树

文章目录 day18学习内容一、找树左下角的值1.1、思路1.2、错误写法1.2.1、为什么这么写是错的&#xff1f; 1.3、正确写法 二、路径总和2.1、思路2.2、正确写法12.2.1、这种写法回溯思想体现在哪里&#xff1f; 2.3、正确写法22.3.1、这种写法回溯思想体现在哪里&#xff1f; 2…

面向切面编程(AOP)介绍(横切关注点、通知(增强)、连接切入点、切面)

1. 面向切面编程思想AOP AOP&#xff1a;Aspect Oriented Programming面向切面编程 AOP可以说是OOP&#xff08;Object Oriented Programming&#xff0c;面向对象编程&#xff09;的补充和完善。OOP引入封装、继承、多态等概念来建立一种对象层次结构&#xff0c;用于模拟公…

【理解指针(二)】

文章目录 一、指针的运算&#xff08;1&#xff09;指针加整数&#xff08;2&#xff09;指针减指针&#xff08;指针关系运算&#xff09; 二、野指针&#xff08;1&#xff09;野指针的成因&#xff08;1.1&#xff09;指针未初始化&#xff08;1.2&#xff09;指针的越界访问…

idea2023版使用废弃类没有删除线处理方法

idea2023版使用废弃类没有删除线处理方法 新版Idea使用废弃类时,默认是黄色警告处理方法1. 打开file -> setting2. 编辑(Editor) -> 检查(Inspections) -> 搜索Deprecated API usage 新版Idea使用废弃类时,默认是黄色警告 处理方法 1. 打开file -> setting 2. 编…

微服务---Eureka注册中心

目录 一、服务中的提供者与消费者 二、Eureka工作流程 三、搭建Eureka服务 四、服务拉取 五、总结 1.搭建EurekaServer 2.服务注册 3.服务发现 一、服务中的提供者与消费者 服务提供者&#xff1a;一次业务中&#xff0c;被其他微服务调用的服务。即提供接口给其他微服务。…

<Linux> 初识线程

目录 前言&#xff1a; 一、什么是线程 &#xff08;一&#xff09;基本概念 &#xff08;二&#xff09;线程理解 &#xff08;三&#xff09;线程与进程的关系 &#xff08;四&#xff09;简单实用线程 &#xff08;五&#xff09;重谈虚拟地址空间 1. 页表的大小 2…

编码器-解码器模型(Encoder-Decoder)

注意&#xff1a;本文引用自专业人工智能社区Venus AI 更多AI知识请参考原站 &#xff08;[www.aideeplearning.cn]&#xff09; 编码器-解码器模型简介 Encoder-Decoder算法是一种深度学习模型结构&#xff0c;广泛应用于自然语言处理&#xff08;NLP&#xff09;、图像处理…

数组:初始化,访问某一个,遍历

文章目录 静态初始化数组数组的访问&#xff1a;遍历数组案例 动态初始化数组总结案例 静态初始化数组 定义数组的时候直接给数组赋值。 简化格式&#xff1a; int[] ages {12,52,96}; 完整格式&#xff1a; int[] ages new int[]{12,16,26};数组变量名中存储的是数组在内存…

数据结构奇妙旅程之二叉平衡树

꒰˃͈꒵˂͈꒱ write in front ꒰˃͈꒵˂͈꒱ ʕ̯•͡˔•̯᷅ʔ大家好&#xff0c;我是xiaoxie.希望你看完之后,有不足之处请多多谅解&#xff0c;让我们一起共同进步૮₍❀ᴗ͈ . ᴗ͈ აxiaoxieʕ̯•͡˔•̯᷅ʔ—CSDN博客 本文由xiaoxieʕ̯•͡˔•̯᷅ʔ 原创 CSDN …

Dubbo-记录

1.概念 Apache Dubbo 是一款 RPC 服务开发框架&#xff0c;用于解决微服务架构下的服务治理与通信问题&#xff0c;官方提供了 Java、Golang 等多语言 SDK 实现。使用 Dubbo 开发的微服务原生具备相互之间的远程地址发现与通信能力&#xff0c; 利用 Dubbo 提供的丰富服务治理…

Linux最小系统安装无法查看IP地址

1&#xff0c;出现原因 服务器重启完成之后&#xff0c;我们可以通过linux的指令 ip addr 来查询Linux系统的IP地址&#xff0c;具体信息如下: 从图中我们可以看到&#xff0c;并没有获取到linux系统的IP地址&#xff0c;这是为什么呢&#xff1f;这是由于启动服务器时未加载网…