C++——认识STL及使用及实现第一个容器string

news2024/9/27 19:18:39

✨✨ 欢迎大家来到小伞的大讲堂✨✨

🎈🎈养成好习惯,先赞后看哦~🎈🎈

所属专栏:C++学习
小伞的主页:xiaosan_blog

1. 什么是STL

1.1 STL的版本

STL(standard template libaray-标准模板库):是C++标准库的重要组成部分,不仅是一个可复用的组件库,而且是一个包罗数据结构与算法的软件框架。

原始版本

Alexander Stepanov、Meng Lee 在惠普实验室完成的原始版本,本着开源精神,他们声明允许任何人任意运用、拷贝、修改、传播、商业使用这些代码,无需付费。唯一的条件就是也需要向原始版本一样做开源使用。 HP 版本--所有STL实现版本的始祖。

P. J. 版本

由P. J. Plauger开发,继承自HP版本,被Windows Visual C++采用,不能公开或修改,缺陷:可读性比较低,符号命名比较怪异。

RW版本

由Rouge Wage公司开发,继承自HP版本,被C+ + Builder 采用,不能公开或修改,可读性一般。

SGI版本

由Silicon Graphics Computer Systems,Inc公司开发,继承自HP版 本。被GCC(Linux)采用,可移植性好,可公开、修改甚至贩卖,从命名风格和编程 风格上看,阅读性非常高。我们后面学习STL要阅读部分源代码,主要参考的就是这个版本

1.2 STL的六大组件

2.使用第一个容器string

string - C++ Reference (cplusplus.com)

查看C++参考对string的解释,我们会发现string与字符串有关,

在使用string类时,必须包含#include头文件以及using namespace std

2.1 auto和范围for

在早期C/C++中auto的含义是:使用auto修饰的变量,是具有自动存储器的局部变量,后来这个不重要了。C++11中,标准委员会变废为宝赋予了auto全新的含义即:auto不再是一个存储类型指示符,而是作为一个新的类型指示符来指示编译器,auto声明的变量必须由编译器在编译时期推导而得。

用auto声明指针类型时,用auto和auto*没有任何区别,但用auto声明引用类型时则必须加&当在同一行声明多个变量时,这些变量必须是相同的类型,否则编译器将会报错,因为编译器实际只对第一个类型进行推导,然后用推导出来的类型定义其他变量。

auto不能作为函数的参数,可以做返回值,但是建议谨慎使用

auto不能直接用来声明数组

int func1()
{
	return 10;
} 

// 不能做参数
//void func2(auto a)
//{}

// 可以做返回值,但是建议谨慎使用
auto func3()
{
	return 3;
} 

int main()
{
	int a = 10;
	auto b = a;
	auto c = 'a';
	auto d = func1();

	// 编译报错:rror C3531: “e”: 类型包含“auto”的符号必须具有初始值设定项
	//auto e;

	//typeid().name可以打印变量类型
	cout << typeid(b).name() << endl;
	cout << typeid(c).name() << endl;
	cout << typeid(d).name() << endl;
	int x = 10;
	auto y = &x;
	auto* z = &x;
	auto& m = x;
	cout << typeid(x).name() << endl;
	cout << typeid(y).name() << endl;
	cout << typeid(z).name() << endl;
	auto aa = 1, bb = 2;

	// 编译报错:error C3538: 在声明符列表中,“auto”必须始终推导为同一类型
	//auto cc = 3, dd = 4.0;
	// 编译报错:error C3318: “auto []”: 数组不能具有其中包含“auto”的元素类型
	//auto array[] = { 4, 5, 6 };

	return 0;
}
#include<iostream>
#include <string>

using namespace std;

#include <map>
int main()
{
	map<string, string> dict = { { "apple", "ping guo" },{ "orange","cheng zi" }};
	auto it = dict.begin();
	while (it != dict.end())
	{
		cout << it->first << ":" << it->second << endl;
		++it;
	}
	return 0;
}

 auto适用大部分的容器,如:“字符串”“顺序表”......

2.2 范围for

对于一个有范围的集合而言,由程序员来说明循环的范围是多余的,有时候还会容易犯错误。因此C++11中引入了基于范围的for循环。for循环后的括号由冒号“ :”分为两部分:第一部分是范围内用于迭代的变量,第二部分则表示被迭代的范围,自动迭代,自动取数据,自动判断结束。

范围for可以作用到数组和容器对象上进行遍历

范围for的底层很简单,容器遍历实际就是替换为迭代器,这个从汇编层也可以看到。

#include<iostream>
#include<string>
using namespace std;

int main() {
	int arr[] = { 1,2,3,4,5,6,7,8,9 };
	// C++98的遍历
	//采用计算长度,利用for循环遍历
	for (int i = 0; i < sizeof(arr) / sizeof(arr[0]); ++i)
	{
		arr[i] *= 2;
	} 

	for (int i = 0; i < sizeof(arr) / sizeof(arr[0]); ++i)
	{
		cout << arr[i] << endl;
	}

	// C++11的遍历
	//auto会自己遍历
	for (auto& e : arr)
		e *= 2;
	for (auto e : arr)
		cout << e << " " << endl;

	string str("hello world");
	for (auto ch : str)
	{
		cout << ch << " ";
	} 

	cout << endl;

	return 0;
}

容器遍历实际就是替换为迭代器,这个从汇编层也可以看到,采用范围for会减少访问指针时的报错。

2.3 string类的常用接口说明(注意下面我只讲解最常用的接口)


int main() {
	string s1;//构造空的string类对象s1
	string s2("hello world");//构造的string类对象s1
	string s3(s2);//拷贝构造

	return 0;
}

2.3 string类对象的容量操作

函数名称功能说明

size(重点)返回字符串有效字符长度

length返回字符串有效字符长度

capacity返回空间总大小

empty(重点)检测字符串释放为空串,是返回true,否则返回false

clear(重点)清空有效字符

reserve(重点)reserve为字符串预留空间

resize(重点)将有效字符的个数调整成n个字符,多出的空间用字符c填充

#include<iostream>
#include<string>
using namespace std;

void test1(string& s) {
	//返回字符串有效字符(不包括'\0')
	cout << s.size()<< endl;
	cout << s.length()<< endl;
	//返回空间总大小
	cout << s.capacity() << endl;
	//检测字符串释放为空串,是返回true,否则返回false
	cout << s.empty() << endl;
	//清空有效字符
	s.clear();
	cout << s.empty() << endl;
	//为字符串预留空间
	s.reserve(40);
	//将有效字符的个数调整成n个字符,多出的空间用字符c填充
	s.resize(60);
}

void test2(string& s) {
	//string s2("hello world");
	//返回空间总大小:15
	cout << s.capacity() << endl;
	//预留空间<空间大小
	s.reserve(10);
	//返回空间大小:15
	cout << s.capacity() << endl;
	//预留空间>空间大小
	s.reserve(500);
	//返回空间大小:
	cout << s.capacity() << endl;
	s.reserve(20);
	//返回空间大小:15
	cout << s.capacity() << endl;
}

void test3() {
    string s;
	size_t sz = s.capacity();
	cout << "making s grow:\n";
	for (int i = 0; i < 100; ++i)
	{
        //从 15 31 47 70 105 157 235,依次增加空间,基本符合1.5倍空间开辟,后面会2倍开辟空间
		//而在gcc的环境下,空间为2倍开辟
		s.push_back('c');
		if (sz != s.capacity())
		{
			sz = s.capacity();
			cout << "capacity changed: " << sz << '\n';
		}
	}
}

void test4() {
	string s;
	// 测试reserve是否会改变string中有效元素个数
	s.reserve(100);
	cout << s.size() << endl;
	cout << s.capacity() << endl;

	// 测试reserve参数小于string的底层空间大小时,是否会将空间缩小
	s.reserve(50);
	cout << s.size() << endl;
	cout << s.capacity() << endl;
	//0 111 0 111
}


int main() {
	string s1;//构造空的string类对象s1
	string s2("hello world");//构造的string类对象s1
	string s3(s2);//拷贝构造
	//test1(s2);
	test2(s2);

	return 0;
}

reserve(为字符串预留空间):注意其小于有效字符大小时,不改变其空间大小

resize(将有效字符的个数调整成n个字符,多出的空间用字符c填充):注意其小于有效字符大小时,会删除其字符

2.4 string类对象的访问及遍历操作

函数名称功能说明

operator[](重点)返回pos位置的字符,const string类对象调用

begin+ endbegin获取一个字符的迭代器 + end获取最后一个字符下一个位

置的迭代器

rbegin + rend

rbegin:返回一个反向迭代器,该迭代器指向字符串的最后一个字符(即其反向开头

rend:返回一个反向迭代器,该迭代器指向字符串第一个字符之前的理论元素(被视为其反向端

范围forC++11支持更简洁的范围for的新遍历方式

operate[] :返回pos位置的字符,const string类对象调用

void test5() {
	string s1("hello world");
	const string s2("Hello world");
	cout << s1 << " " << s2 << endl;
	//支持下标的访问及更改(注意const对象不能更改)
	cout << s1[0] << " " << s2[0] << endl;

	s1[0] = 'H';
	cout << s1 << endl;

	// s2[0] = 'h';   代码编译失败,因为const类型对象不能修改
}

begin+ end:begin获取一个字符的迭代器 + end获取最后一个字符下一个位置的迭代器

void test6() {

	string s("hello world");
	// 3种遍历方式:
	// 需要注意的以下三种方式除了遍历string对象,还可以遍历是修改string中的字符,
	// 另外以下三种方式对于string而言,第一种使用最多
	
	// 1. for+operator[]
	for (size_t i = 0; i < s.size(); ++i)
		cout << s[i];
	cout << endl;
	// 2.迭代器:我们还可以自己实现begin和end迭代器以适配其他容器
	string::iterator it = s.begin();//it:获取s的第一个字符的迭代器
	while (it != s.end())//end获取最后一个字符迭代器
	{
		//相当于地址,此时需要解引用
		cout << *it ;
		++it;
	}
	cout << endl;

	// string::reverse_iterator rit = s.rbegin();
	// C++11之后,直接使用auto定义迭代器,让编译器推到迭代器的类型
	//反向迭代器
	auto rit = s.rbegin();
	while (rit != s.rend()) {
		cout << *rit ;
		rit++;
	}
	cout << endl;

	// 3.范围for,在编译层可以看到,其实是使用迭代器,但如果该改变begin与end的名,则不能使用,而iterator可以
	for (auto ch : s)
		cout << ch ;
}

hello world
hello world
dlrow olleh(因为rbegin为反向迭代器):
auto rit = s.rbegin();当rit++时,rit是往s第一个字符的方向;

hello world

2.5 string类对象的修改操作

函数名称功能说明

push_back在字符串后尾插字符c

append在字符串后追加一个字符串

operator+= (重点)在字符串后追加字符串str

c_str(重点)返回C格式字符串

find + npos(重点)从字符串pos位置开始往后找字符c,返回该字符在字符串中第一次出现的位置

rfind从字符串pos位置开始往前找字符c,返回该字符在字符串中最后一次出现的位置

substr在str中从pos位置开始截取n个字符,然后将其返回

void test7() {
	string str;
	str.push_back(' ');   // 在str后插入空格
	str.append("hello");  // 在str后追加一个字符"hello"
	str += 'w';           // 在str后追加一个字符'w'   
	str += "orld";          // 在str后追加一个字符串"orld"
	cout << str << endl;
	cout << str.c_str() << endl;   // 以C语言的方式打印字符串

	// 获取file的后缀
	string file("str.ing.cpp");
	size_t pos = file.rfind('.');//返回该字符出现的最后一次的位置
	string suffix(file.substr(pos, file.size() - pos));//在str中从pos位置开始,截取n个字符,然后将其返回
	cout << suffix << endl;

	// npos是string里面的一个静态成员变量
	// static const size_t npos = -1;

	// 取出url中的域名
	string url("http://www.cplusplus.com/reference/string/string/find/");
	cout << url << endl;
	size_t start = url.find("://");
	if (start == string::npos)
	{
		cout << "invalid url" << endl;
		return;
	}

	start += 3;//找到www.,删除前部分
	size_t finish = url.find('/', start);//查找第一次出现的位置
	string address = url.substr(start, finish - start);
	cout << address << endl;

	// 删除url的协议前缀
	pos = url.find("://");
	url.erase(0, pos + 3);//删除0到pos+3的位置
	cout << url << endl;
}

2.6 string类非成员函数

函数功能说明

operator+尽量少用,因为传值返回,导致深拷贝效率低

operator>> (重点)输入运算符重载

operator<< (重点)输出运算符重载

getline (重点)获取一行字符串

relational operators (重点)大小比较

getline(获取一行字符串):

之前在C语言中我们通常scanf("%[^\n]",&s):需要先定义字符串数组。fget()函数    

scanf("%[^\n]",&s);(这里是可以存放空格的);

char c[20];
fgets(c, sizeof(c), stdin);(可以存放空格)
puts(c);

而在C++中准备好了getline()函数,我们不需要提前准备好s的大小

string s;
getline(cin,s);
cout << s;


3.string容器的实现

3.1 string.h(实现接口)

对于调用频繁的函数,包在头文件中实现,效率更高,程序结构也更规范

#pragma once

#define _CRT_SECURE_NO_WARNINGS 1
#pragma once

#include<iostream>
#include<string>
#include<assert.h>
using namespace std;

namespace sui
{
	class string
	{
	public:
        //迭代器 普通类型与const类型
		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;
		}
        //构造函数,这里为全缺省函数""相当于初始化'\0';
		string(const char* str = "")
		{
			_size = strlen(str);
			_capacity = _size;
			//字符串中'\0'算一个字节
			_str = new char[_capacity + 1];
			strcpy(_str, str);
		}
        //析构函数
		~string()
		{
			if (_str) {
				free(_str);
				_str = nullptr;
				_size = _capacity = 0;
			}
		}

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

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

		size_t size() const
		{
			return _size;
		}

		size_t capacity() const
		{
			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);
		void push_back(char ch);
		void append(const char* str);
		string& operator+=(char ch);
		string& operator+=(const char* str);

		void insert(size_t pos, char ch);
		void insert(size_t pos, const char* str);
		void erase(size_t pos, size_t len = npos);

	private:
        //初始化成员
		char* _str = nullptr;
		size_t _size = 0;
		size_t _capacity = 0;
		static const size_t npos;
	};
}

3.2 string.cpp

void reserve(size_t n);

    void string::reserve(size_t n) {
        if (n > _capacity) {
            char* tmp = new char [n + 1];//多开辟一个字节存放'\0';

           //字符串拷贝
            strcpy(tmp, _str);
            delete[] _str;//注意[],因为new[],所以要delete[]与之匹配

            _str = tmp;
            _capacity = n;//_capacity不包含'\0';
        }
    }

void push_back(char ch);(插入字符)

void string::push_back(char ch) {

//插入之前,得判断是否剩余空间存放字符
    if (_size == _capacity) {

//三目操作符
        reserve(_capacity == 0 ? 4 : _capacity * 2);
    }
    _str[_size] = ch;
    ++_size;

//因为_str[_size] = ch;覆盖了原存在的'\0';
    _str[_size] = '\0';
}

void append(const char* str);

void string::append(const char* str) {
    size_t len = strlen(str);
    if (_size + len > _capacity)
    {
        // 大于2倍,需要多少开多少,小于2倍按2倍扩
        reserve(_size + len > 2 * _capacity ? _size + len : 2 * _capacity);

    }
    strcpy(_str + _size, str);//在_str + _size的位置后插入str;
    _size += len;
}

string& operator+=(char ch);

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

string& operator+=(const char* str);

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

void insert(size_t pos, char ch);

void string::insert(size_t pos, char ch) {
    assert(pos <= _size);
    if (_size == _capacity) {
        reserve(_capacity == 0 ? 4 : _capacity * 2);
    }
    //挪动数据(最后一个字符先移动,否则会覆盖数据)
    size_t end = _size + 1;
    while (end > pos)
    {
        _str[end] = _str[end - 1];
        --end;
    }

    _str[end] = ch;
    _size++;
}

void insert(size_t pos, const char* str);

void string::insert(size_t pos, const char* str) {

    assert(pos <= _size);

    size_t len = strlen(str);
    if (_size + len > _capacity)
    {
        // 大于2倍,需要多少开多少,小于2倍按2倍扩
        reserve(_size + len > 2 * _capacity ? _size + len : 2 * _capacity);
    }

    size_t end = _size + len;

   //找到目标位置的首个字符位置,移动,从前向后覆盖
    while (end > pos + len - 1)
    {
        _str[end] = _str[end - len];
        --end;
    }

   //覆盖目标位置

    for (size_t i = 0; i < len; i++) {
        _str[i + pos] = str[i];
    }

    _size += len;
}

void erase(size_t pos, size_t len = npos)默认设定为-1;

(注意:不要省略npos)

    void string::erase(size_t pos, size_t len ) {
        assert(pos <= _size);
        size_t end = pos;
        while (end < pos + len - 1) {
            _str[end] = _str[end + len];
            --end;
        }
        _size -= len;
    }

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

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

相关文章

垃圾回收级别分类识别系统源码分享

垃圾回收级别分类识别检测系统源码分享 [一条龙教学YOLOV8标注好的数据集一键训练_70全套改进创新点发刊_Web前端展示] 1.研究背景与意义 项目参考AAAI Association for the Advancement of Artificial Intelligence 项目来源AACV Association for the Advancement of Comp…

【线程】线程的同步---生产消费者模型

本文重点&#xff1a;理解条件变量和生产者消费者模型 同步是在保证数据安全的情况下&#xff0c;让我们的线程访问资源具有一定的顺序性 条件变量cond 当一个线程互斥地访问某个变量时&#xff0c;它可能发现在其它线程改变状态之前&#xff0c;它什么也做不了&#xff0c;…

电路 - 笔记2

1 555 芯片 2 类比 - pU*I 与 Fm*a 是不是可以与牛顿定律类比 - Fm*a 人的力量&#xff08;F&#xff09;有限。 当推大箱子&#xff08;m&#xff09;时&#xff0c;加速度&#xff08;a&#xff09;就不会很大 当推小箱子&#xff08;m&#xff09;时&#xff0c;加速度…

RTE 大会报名丨AI 时代新基建:云边端架构和 AI Infra ,RTE2024 技术专场第二弹!

所有 AI Infra 都在探寻规格和性能的最佳平衡&#xff0c;如何构建高可用的云边端协同架构&#xff1f; 语音 AI 实现 human-like 的最后一步是什么&#xff1f; AI 视频的爆炸增长&#xff0c;给新一代编解码技术提出了什么新挑战&#xff1f; 当大模型进化到实时多模态&am…

mysql批量修改表前缀

现有表前缀xh,批量修改为fax_需要怎么做 SELECTCONCAT(ALTER TABLE ,table_name, RENAME TO fax_,substring(table_name, 3),;) FROMinformation_schema. TABLES WHEREtable_name LIKE xh_%; 运行之后可以但是生成了一批修改表明的命令 此时批量复制执行就可实现批量修改表前…

架构设计读后有感——原则

成为架构时是程序员的梦想&#xff0c;并不意味着把编程做好就能够自然的成为一个架构师&#xff0c;他们之间有一个鸿沟->“不确定性” 不确定性&#xff1a;编程本质上说是不存在不确定性的&#xff0c;因为一个输入可以通过逻辑的运算得到确定的值&#xff0c;即使是机器…

电脑ip变了后导致原来的虚拟机静态ip失效问题

电脑ip变了后导致原来的虚拟机静态失效问题处理 静态IP设置的几个要点 查看本地网络的配置 VMware虚拟机网络设置 子网IP必须和本地ip在同一个网段下&#xff0c;本地的ip是192.168.1.10&#xff0c;那我子网ip就应该是192.168.1.xxx&#xff0c; 网关ip需要保持一致。 DHCP…

剧本杀分类管理

1用户界面 用户注册/登录模块与剧本杀填写模块&#xff1a;用户注册/登录成功后&#xff0c;将用户信息传递给剧本杀填写模块&#xff0c;以便用户进行剧本杀的填写。 图6-1登录注册 剧本杀填写模块与剧本杀分类管理模块&#xff1a;剧本杀填写完成后&#xff0c;将剧本杀信息…

Adaptive Object Detection with Dual Multi-Label Prediction

gradient reversal layer (GRL) 辅助信息 作者未提供代码

小孩真的需要手机上学吗?怎样远程了解他在学校用iPhone干什么?

互联网在教育、娱乐、社交等多个领域发挥着重要作用&#xff0c;成为孩子们获取知识、放松娱乐的重要渠道。孩子们首次接触互联网的年龄越来越小&#xff0c;有的甚至在幼儿园阶段就开始使用智能设备。 一些学校推行电子书包、网络作业等&#xff0c;虽然提高了效率&#xff0c…

【Golang】Go语言中如何面向对象?

✨✨ 欢迎大家来到景天科技苑✨✨ &#x1f388;&#x1f388; 养成好习惯&#xff0c;先赞后看哦~&#x1f388;&#x1f388; &#x1f3c6; 作者简介&#xff1a;景天科技苑 &#x1f3c6;《头衔》&#xff1a;大厂架构师&#xff0c;华为云开发者社区专家博主&#xff0c;…

Vue3:toRaw与markRaw

目录 一.toRaw 1.性质 2.作用 二.markRaw 1.性质 2.作用 三.toRaw的使用 四.markRaw的使用 五.代码示例 在Vue 3中&#xff0c;toRaw和markRaw是两个用于处理响应式对象的全局函数。 一.toRaw 1.性质 toRaw是一个全局函数&#xff0c;它接受一个由reactive或ref生成…

JS面试真题 part6

JS面试真题 part6 26、如何判断一个元素是否在可视区域中27、什么是单点登录&#xff1f;如何实现28、 如何实现上拉加载&#xff0c;下拉刷新29、说说你对正则表达式的理解&#xff1f;应用场景&#xff1f;30、说说你对函数式编程的理解&#xff1f;优缺点 26、如何判断一个元…

Vue74 路由的props配置

笔记 ​ 作用&#xff1a;让路由组件更方便的收到参数 {name:xiangqing,path:detail/:id,component:Detail,//第一种写法&#xff1a;props值为对象&#xff0c;该对象中所有的key-value的组合最终都会通过props传给Detail组件// props:{a:900}//第二种写法&#xff1a;props…

《动手学深度学习》笔记1.11——实战Kaggle比赛:预测房价+详细代码讲解

目录 0. 前言 原书正文 1. 下载和缓存数据集 1.1 download() 下载数据集 1.2 download_extract() 解压缩 2. Kaggle 简介 3. 访问和读取数据集 4. 数据预处理 5. 训练&#xff08;核心难点&#xff09; 5.1 get_net() 定义模型-线性回归 5.2 log_rmse() 对数均方根…

见合八方亮相重庆光纤传感大会(OFS China-2024)

2024年9月20日至22日&#xff0c;第十二届中国光纤传感大会&#xff08;OFS China-2024&#xff09;在重庆成功举办&#xff0c;该大会旨在展示光纤传感技术在多个领域的最新研究成果&#xff0c;推动该技术的产业化进程。 在本次大会上&#xff0c;天津见合八方光电科技有限公…

JDK1.8与JDK17相互切换

&#x1f4d6; 前言&#xff1a;在电脑已经安装jdk17后&#xff0c;发现有些项目不兼容&#xff0c;需要用到以前的jdk1.8&#xff0c;本文介绍简单切换的方法。 &#x1f50e; 甲骨文jdk1.8官网下载 下载完jdk1.8后&#xff0c;可以将其与jdk17放在同一目录层级下。 搜索栏直…

我眼中的Token2049 是一场加密大秀

今年Token2049&#xff0c;其实我也收到很多来自币圈朋友、项目方或交易所的邀请&#xff0c;都一一婉拒了。因为每年9月&#xff0c;都是我一年来最忙碌的日子。一方面进入金九银十的销售旺季&#xff0c;另外副业也需要谈一些团购业务。 我喜欢Web3&#xff0c;也曾是 #Bitg…

《操作系统 - 清华大学》1 -1:操作系统概述 —— 内容概述

文章目录 1. 内容摘要2. 实验内容 1. 内容摘要 在这里对学习内容做一个整体上的介绍&#xff0c;那在这里包括我们要学习的内容&#xff0c;实验的内容。操作系统课涉及到计算机系统当中的资源管理&#xff0c;所以我们围绕着操作系统的实现来介绍相关内容&#xff0c;那主要分…

Java之路--瓦解逻辑控制与方法使用已是瓮中捉鳖

嗨嗨大家&#xff01;今天我们来学习逻辑运算和方法的使用~ 目录 一 逻辑控制 1 分支结构 1.1 if语句 1.2 switch 语句 2 循环结构 2.1 while 循环 2.2 for 循环 2.3 do while 循环 2.4 break 2.5 continue 3. 输出输入 二、方法的使用 1 方法定义语法 2 实参和…