IT数码 购物 网址 头条 软件 日历 阅读 图书馆
TxT小说阅读器
↓语音阅读,小说下载,古典文学↓
图片批量下载器
↓批量下载图片,美女图库↓
图片自动播放器
↓图片自动播放器↓
一键清除垃圾
↓轻轻一点,清除系统垃圾↓
开发: C++知识库 Java知识库 JavaScript Python PHP知识库 人工智能 区块链 大数据 移动开发 嵌入式 开发工具 数据结构与算法 开发测试 游戏开发 网络协议 系统运维
教程: HTML教程 CSS教程 JavaScript教程 Go语言教程 JQuery教程 VUE教程 VUE3教程 Bootstrap教程 SQL数据库教程 C语言教程 C++教程 Java教程 Python教程 Python3教程 C#教程
数码: 电脑 笔记本 显卡 显示器 固态硬盘 硬盘 耳机 手机 iphone vivo oppo 小米 华为 单反 装机 图拉丁
 
   -> C++知识库 -> C++Primer中级,1-10 -> 正文阅读

[C++知识库]C++Primer中级,1-10

这是一篇听课笔记,这里是课程链接

# include <iostream>
# include <deque>

int main()
{
	using namespace std;
	deque<int> a;

	a.push_back(3);
	a.push_back(4);
	a.push_back(5);

	a.push_front(2);
	a.push_front(0);

	for (size_t ncount = 0; ncount < a.size(); ++ncount) // what is size_t??
	{
		cout << a[ncount] << endl;
	}

}
# include <iostream>
# include <deque>
# include <algorithm> // in order to use distance() function to get the index

int main()
{
	using namespace std;
	deque<int> a;

	a.push_back(3);
	a.push_back(4);
	a.push_back(5);

	a.push_front(2);
	a.push_front(0);

	for (size_t ncount = 0; ncount < a.size(); ++ncount) // what is size_t??
	{
		cout <<"a["<<ncount << "] = " << a[ncount] << endl;
	}

	cout << endl << endl;

	// delete some element , back or front
	a.pop_back();
	a.pop_front();

	deque<int>::iterator iElement;
	for (iElement = a.begin();
		iElement != a.end();
		++iElement)
	{
	// include <algorithm>, then we can use distance() function, 
	// we can obtain the index ,  because iterator does not have the index 
	size_t nOffset = distance(a.begin(), iElement);
	// a.begin() return an iterator pointing the initial place, 
	// iElement returns an iterator pointing the current place
	cout << "a[" << nOffset << "]=" << *iElement << endl;
	}
	
	cout << endl;
	return 0;

}
  • 向列表中插入数据
#include <iostream>
#include <list>

using namespace std;

void PrintListContents(const list<int>& listInput);

int main()
{
	list<int> a;
	list<int> b;

	std::list<int>::iterator iter;

	a.push_front(3);
	a.push_front(2);
	a.push_front(1);
	a.push_back(4);

	PrintListContents(a);
	cout << endl;

	// operation : insert values into list
	iter = a.begin();
	a.insert(iter, 10); // insert 10 in the front of list a
	PrintListContents(a);

	++iter;
	a.insert(iter, 2, 0);// insert two values 0 0 before the second element
	PrintListContents(a);

	// operation : insert the whole list b into list a 
	b.push_back(200);
	b.push_back(300);
	b.push_back(400);

	a.insert(a.begin(), b.begin(), b.end()); // insert b at the front of a
	PrintListContents(a);

	a.insert(a.end(), b.begin(), b.end()); // insert b at the end of a
	PrintListContents(a);

	a.insert(a.begin(), ++b.begin(), --b.end());
	PrintListContents(a);

	return 0;
}

void PrintListContents(const list<int>& listInput)
{
	cout << "{" ;
	std::list<int>::const_iterator iter;
	for(iter = listInput.begin(); iter!=listInput.end(); ++iter)
	{
		cout << *iter <<" ";
	}
	cout << "}" << endl;
}
  • 使用迭代器从列表中删除数据
#include <iostream>
#include <list>

using namespace std;

void PrintListContents(const list<int>& listInput);

int main()
{
	list<int> a;

	std::list<int>::iterator iter2;

	a.push_front(3);
	a.push_back(4);

	iter2 = a.insert(a.begin(), 2); // insert value 2 in the front of list a
	a.push_front(0);
	PrintListContents(a); // contains 2

	// delete the second part of this list
	a.erase(iter2, a.end());
	PrintListContents(a);


	/*
	// delete the first part of this list
	a.erase(a.begin(), iter2);
	PrintListContents(a);	
	// now, delete one value 2 from this list
	a.erase(iter2);
	PrintListContents(a); // not contains 2
	*/


	cout << endl;

	return 0;
}

void PrintListContents(const list<int>& listInput)
{
	cout << "{" ;
	std::list<int>::const_iterator iter;
	for(iter = listInput.begin(); iter!=listInput.end(); ++iter)
	{
		cout << *iter <<" ";
	}
	cout << "}" << endl;
}

  • 数组的反转与排序
#include <iostream>
#include <list>

using namespace std;

void PrintListContents(const list<int>& listInput);

int main()
{
	list<int> a;
	list<int> b;

	a.push_front(3);
	a.push_back(4);
	a.push_front(2);

	PrintListContents(a);
	a.reverse();
	PrintListContents(a);

	b.push_back(5);
	b.push_back(3);
	b.push_back(6);

	PrintListContents(b);
	b.sort();
	PrintListContents(b);

	cout << endl;

	return 0;
}

void PrintListContents(const list<int>& listInput)
{
	cout << "{" ;
	std::list<int>::const_iterator iter;
	for(iter = listInput.begin(); iter!=listInput.end(); ++iter)
	{
		cout << *iter <<" ";
	}
	cout << "}" << endl;
}
  • 堆栈
#include <iostream>
#include <stack>

using namespace std;

int main()
{
	stack<int> d;
	// stack<int, vector<int>> a;
	// stack<int, list<int>> b;
	// stack<int, deque<int>> c;

	d.push(20); // first put in 
	d.push(10);
	d.push(5); // last put in

	cout << d.top() << endl; // 5

	return 0;
}
  • 队列
#include <iostream>;
#include<queue>;
#include <list>;

using namespace std;

int main()
{
	queue<int, deque<int>> a;
	queue<int, list<int>> b;

	a.push(2);
	a.push(3);
	a.push(4);

	cout << "# : " << a.size() << endl;
	cout << "the element in the front is " << a.front() << endl;
	cout << "the element at the back is " << a.back() << endl;

	a.pop();
	cout << "after pop, " << endl;
	cout << "# : " << a.size() << endl;
	cout << "the element in the front is " << a.front() << endl;
}
  • 优先级队列
#include <iostream>;
#include <queue>;
#include <deque>;

using namespace std;

int main()
{
	priority_queue<int> pq; // default use vector, 最大优先级队列
	priority_queue<int, deque<int>, greater<int>> pq2; //  添加谓词,构建最小优先级队列

	pq.push(10);
	pq.push(5);
	pq.push(20);

	cout << "the most front element is " << pq.top() << endl;

	while (!pq.empty())
	{
		cout << " delete the element " << pq.top() << endl;
		pq.pop();
	}

	// 最小级优先队列
	pq2.push(30);
	pq2.push(10);
	pq2.push(15);

	cout << "the most front element is " << pq2.top() << endl;
	while (pq2.size() != 0)
	{
		cout << pq2.top() << endl;
		pq2.pop();
	}

	return 0;
}

C++ Primer中级

类的定义


# include <iostream>
#include <string>

using namespace std;

class Sales_item
{
public:
	Sales_item(const string &book, unsigned units, double amount)
		:isbn(book),units_sold(units),revenue(amount)
	{}

	double avg_price() const // do not modify the member data
	{
		if (units_sold)
			return revenue / units_sold;
		else
			return 0;
	}

	bool same_isbn(const Sales_item &rhs) const
	{
		return isbn == rhs.isbn;
	}

	void add(const Sales_item &rhs) // do not add const to limit this func to modify data 
	{
		units_sold += rhs.units_sold;
		revenue += rhs.revenue;
	}
	
private:
	string isbn; // book number
	unsigned units_sold; // how many books are sold
	double revenue; // total price
};

int main()
{
	Sales_item x(string("101-102"), 2, 40);
	Sales_item y(string("101-102"), 4, 60);

	cout << "x 's avg_price is " << x.avg_price() << endl;
	if (x.same_isbn(y))
		x.add(y);
	cout << "after adding y, " << "x 's avg_price is " << x.avg_price() << endl;

}

类的定义、内联函数

#include<iostream>
#include<string>

using namespace std;

class Screen {
public:

	typedef std::string::size_type index;

	Screen(index ht=0, index wd=0)
		:contents(ht*wd,'A'),cursor(0),height(ht),width(wd)
	{}

	Screen(index ht, index wd, const string& cons)
	{
		height = ht;
		width = wd;
		contents = cons;
		cursor = 0;
	}

	char get() const; // declaration of member function

	// 函数重载
	char get(index r, index c) const
	{
		index row = r * width;
		return contents[row + c];
	}

private:
	std::string contents;
	index cursor; // the current place of the cursor
	index height, width; // size of this screen objective
};

inline char Screen::get() const
{
	return contents[cursor];
}

int main() {
	Screen a(10, 100);
	cout << a.get() << endl;
	cout << a.get(2, 4) << endl;

	Screen b(3, 6, "hello world to be happy");
	cout << b.get() << endl;
	cout << b.get(1, 2) << endl;
}

this指针的使用

#include <iostream>
#include <string>

using namespace std;

class Screen
{
public:
	typedef std::string::size_type index;
	//"AAAAAAAAAAAAAAA"
	Screen( index ht=0, index wd=0,  const string cons= (3*5,"A")) //: cursor(0), height(ht), width(wd)
	{
		cursor = 0;
		height = ht;
		width = wd;
		contents = cons; // 这个地方有些疑问,为什么不能用 contents=(ht*wd,"A"),总是会报错,说什么string超出访问范围,很奇怪。
	}

	char get() const { return contents[cursor]; }
	char get(index r, index c) const { return contents[r * width + c]; }

	void set(char c) { contents[cursor] = c; }
	void set(index r,index c, const char ch) { contents[cursor+r*width+c] = ch; }

	// move the current cursor 
	Screen& move(index r, index c);

private:
	string contents;
	index cursor;
	index height, width;

};

Screen& Screen::move(index r, index c)
{
	cursor = r * width + c;
	return *this;
}

int main() 
{
	Screen myscreen(5, 3, "AAAAAAAAAAAAAAA");//
	cout << myscreen.get() << endl;


	cout << endl;
	myscreen.set(2, 3, 'E');
	cout << myscreen.get(2, 3) << endl;
	// 考虑能否将这两行内容,写成一行,chain的形式,即 myscreen.move(2,3).set('O')
	// 先移动到(2,3)的位置,然后在修改,于是需要修改move函数使它返回一个对象,该对象调用set函数
	// myscreen.move(2, 3);
	// myscreen.set('O');
	myscreen.move(2, 3).set('O');
	cout << myscreen.get(2,3) << endl;

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

using namespace std;

class Screen
{
public:
	typedef std::string::size_type index;
	//"AAAAAAAAAAAAAAA"
	Screen( index ht=0, index wd=0,  const string cons= (3*5,"A")) //: cursor(0), height(ht), width(wd)
	{
		cursor = 0;
		height = ht;
		width = wd;
		contents = cons;
	}

	char get() const { return contents[cursor]; }
	char get(index r, index c) const { return contents[r * width + c]; }

	Screen& set(char c) { contents[cursor] = c; return *this; }
	Screen& set(index r, index c, const char ch) { contents[cursor + r * width + c] = ch; return *this; }

	// move the current cursor 
	Screen& move(index r, index c);

	// display the contents
	const Screen& display(ostream &om) const //这是因为常函数,必须返回常变量,
	{
		cout << "const" << endl;
		do_display(om);
		return *this;
	}
	// 重载display函数,因为上面返回的常变量会不接受被修改函数set调用
	Screen& display(ostream& om) //不是常函数,也不会返回常对象,后面可以接set函数修改成员数据
	{
		cout << "no const" << endl;
		do_display(om);
		return *this;
	}


private:
	string contents;
	index cursor;
	index height, width;

	void do_display(std::ostream &om) const
	{
		om << contents;
	}
};

Screen& Screen::move(index r, index c)
{
	cursor = r * width + c;
	return *this;
}

int main() 
{
	Screen myscreen(5, 3, "AAAAAAAAAAAAAAA");//
	cout << myscreen.get() << endl;


	cout << endl;
	myscreen.set(2, 3, 'E');
	cout << myscreen.get(2, 3) << endl;
	// 考虑能否将这两行内容,写成一行,chain的形式,即 myscreen.move(2,3).set('O')
	// 先移动到(2,3)的位置,然后在修改,于是需要修改move函数使它返回一个对象,该对象调用set函数
	// myscreen.move(2, 3);
	// myscreen.set('O');

	myscreen.move(2, 3).set('O');
	cout << myscreen.get(2,3) << endl;

/*为了能让display函数返回一个对象类型的数据(这样就可以在display函数之后接着点调用其他成员函数了),接着修改display函数,值得注意的是

const Screen& do_display(std::ostream &os) const //const 函数的返回类型也必须是const

然而,选中的那部分又出现了新麻烦,即display成员函数返回了一个常对象,常对象不能修改数据,因此后面的set会报错

*/
	myscreen.move(4, 1).set('Q').move(4, 2).set('P').move(2,2 ).set('I').display(cout).set('E').display(cout);
	//cout << myscreen.get() << endl;

	//cout << endl;
	//myscreen.display(cout);
	//cout << endl;


	return 0;

构造函数

初始化列表的一些注意事项


cin初始化对象

#include <iostream>
#include <string>

using namespace std;

class Sales_items
{
public:
	Sales_items(const string &book):isbn(book),units_sold(0),revenue(0){}
	Sales_items():isbn(10,'A'),units_sold(0),revenue(10){}
	Sales_items(istream& is) 
	{ 
		cout << "Please input isbn, units, price";
		is >> *this; 
	}// by input to initialize the object
	// 这需要对>>做重载

	friend std::istream& operator>>(std::istream& in, Sales_items& s);

	void display(ostream& co)
	{
		do_display(co);
	}
private:
	string isbn;
	unsigned units_sold;
	double revenue;
	void do_display(ostream& co)
	{
		co<< isbn << units_sold << revenue << endl;
	}
};

inline std::istream& operator>>(istream& in, Sales_items& s)
{
	double price;
	in >> s.isbn >> s.units_sold >> price;
	if (in)
		s.revenue = s.units_sold * price;
	else
		s = Sales_items();
	return in;
}

int main() 
{
	Sales_items item1(cin);
	
	cout << "OK! We finished !" << endl;
	// display the detail of this object 
	item1.display(cout);

	return 0;
}

友元

// 三种友元:普通函数(非成员函数)、类、类的成员函数

#include <iostream>
#include <string>

using namespace std;

class Screen;

class Dog
{
public:
	void foo(Screen& s); // 这个地方会用到类Screen 的对象,所以需要在前面声明类Screen,否则会报错

};

class Screen
{
public:
	typedef std::string::size_type index;
	Screen(int ht = 0, int wd = 0) : contents(ht* wd, ' '), cursor(0), height(ht), width(wd) { cout << "Construted!"; }

	int area() const
	{
		return height * width;
	}

	// friend function
	friend int calArea(Screen& screen);

	// friend class
	friend class Window_Mgr;

	// friend some function of one class
	friend void Dog::foo(Screen & s);

private:
	std::string contents;
	index cursor;
	int height, width;
	
};

// 友元函数的定义
int calArea(Screen& screen)
{
	return screen.height * screen.width;
}

// 友元类的定义
class Window_Mgr
{
public:
	void relocate(int r, int c, Screen& s)
	{
		s.height += r;  // due to friend class, it can modify class Screen's private data
		s.width += c;
	}
};

void Dog::foo(Screen& s)
{
	cout << s.height << "," << s.width << endl;
}


int main() 
{
	
	Screen s(10,20);
	cout << endl;
	cout <<"Member function " << s.area() << endl;
	cout << "Friend function " << calArea(s) << endl;

	cout << "Window_Mgr come!" << endl;
	Window_Mgr w;
	w.relocate(5, 10, s);
	cout << "Member function " << s.area() << endl;
	cout << "Friend function " << calArea(s) << endl;

	// Dog
	Dog d;
	d.foo(s);

	return 0;
}

static 类成员

// *************static***************
#include<iostream>
#include<string>

using namespace std;

class Account
{
public:
	Account(string name, double money):
		owner(name), amount(money){}

	double getAmount() const
	{
		return this->amount;
	}

	// define functions to return and modify this static memeber
	static double rate()
	{
		return interestRate;
	}

	static void rate(double newRate) // modify interestRate
	{
		interestRate = newRate;
	}

private:
	string owner;
	double amount;
	static double interestRate; // all objects share this one
	static const int period = 30; //只有静态常整型才能在private中初始化 
};

double Account::interestRate = 0.015;

class newAccount
{
private:
	static double insterestRate; // we can define the same-name static members in different classes
};

int main()
{
	Account::rate(0.2); // we can use static function without  defination of any objects 
	Account a("Lily", 50);
	cout << a.rate() << endl; // return 0.015

	Account b("Bob", 60);
	b.rate(0.5); // now, we modify this static member on b
	cout << a.rate() << endl; // we can see these 2 objects sharing one variable
	// return 0.5

	return 0;
}
/*
全局变量的缺点,谁都可以用,这是我们不希望的,我们希望只能account的类的对象使用;



静态意味着只有一个,这个类下的所有对象共享这个静态私有成员数据,在类外初始化,设置成员函数查看、修改这个静态私有成员数据





静态的函数操作静态的数据成员,可以在开始时,通过类名调用静态成员函数,

静态成员(数据、函数)是类的成员,这个类的所有对象共有、所有对象的能看到的内容也是相等的,不能私人定制;

所以说,静态成员函数不能使用this指针


不同类的静态成员,即便是同名,也互不影响,作用域是类作用域,

类的静态成员可以是私有的,因此可以封装

这些都是全局变量做不到的(全局变量的作用域是全局作用域,所有类都可以看到并使用,不能私有,也不能封装。)
*/

复制构造函数和赋值函数

#include<iostream>
#include<string>
#include<vector>

using namespace std;

class Sales_item {
public:
	Sales_item():units_sold(0),revenue(0){} // default construct function
	Sales_item(const string &isbn_eg):isbn(isbn_eg),units_sold(0),revenue(0){}

	// 复制构造函数
	Sales_item(const Sales_item &orig)
		:isbn(orig.isbn),units_sold(orig.units_sold),revenue(orig.revenue)
	{
		cout << "copy construct function is used ." << endl;
	}

	// 赋值操作符
	Sales_item& operator=(const Sales_item& rhs)
	{
		cout << "operator= is used." << endl;
		isbn = rhs.isbn;
		units_sold = rhs.units_sold;
		revenue = rhs.revenue;
		return *this;
	}

private:
	string isbn;
	unsigned units_sold;
	double revenue;
};

int main()
{
	Sales_item a;
	Sales_item b("001");

	Sales_item c(b); // use copy construct function
	a = b;// use operator= function
/*
注:这里在函数重载operator=的定义中,输入输出都是引用,因此不需要调用复制构造函数;
如果输出不是引用,那么会调用一次复制构造函数。
如果输入不是引用,也会调用一次复制构造函数。
*/
	return 0;
}
#include<iostream>
#include<string>
#include<vector>

using namespace std;

class Sales_item {
public:
	Sales_item() :units_sold(0), revenue(0) 
	{
		cout << "default construct function is used." << endl;
	} // default construct function
	Sales_item(const string& isbn_eg) 
		:isbn(isbn_eg), units_sold(0), revenue(0) 
	{
		cout << "the 2nd construct function is used ." << endl;
	}

	// 复制构造函数
	Sales_item(const Sales_item& orig)
		:isbn(orig.isbn), units_sold(orig.units_sold), revenue(orig.revenue)
	{
		cout << "copy construct function is used ." << endl;
	}

	// 赋值操作符
	Sales_item& operator=(const Sales_item& rhs)
	{
		cout << "operator= is used." << endl;
		isbn = rhs.isbn;
		units_sold = rhs.units_sold;
		revenue = rhs.revenue;
		return *this;
	}


private:
	string isbn;
	unsigned units_sold;
	double revenue;
};

Sales_item foo(Sales_item item)  // copy -> operator= -> copy 
{
	Sales_item temp;
	temp = item;
	return temp;
}


int main()
{
	Sales_item a;
	Sales_item b("001");

	Sales_item c(b); // use copy construct function
	a = b;// use operator= function

	Sales_item item = string("003");
	cout << "use function foo(): " << endl;
	Sales_item ret;
	ret = foo(item);
/*
执行ret = foo(item)意味着要将实参拷贝到形参中(第一次调用复制构造函数),
然后函数中temp = item;调用operator=的重载,
然后在return temp;中第二次调用复制构造函数,将temp复制到一个看不见的对象中,
接着,执行ret = foo(item),赋值操作。

注:
如果在foo函数的定义中,参数、返回值为引用则不会调用复制构造函数;

*/
	return 0;

}

类成员有指针时的复制构造函数和赋值函数

#include<iostream>
#include<string>
#include<vector>

using namespace std;

class Sales_item {
public:
	Sales_item() :units_sold(0), revenue(0) 
	{
		cout << "default construct function is used." << endl;
	} // default construct function
	Sales_item(const string& isbn_eg) 
		:isbn(isbn_eg), units_sold(0), revenue(0) 
	{
		cout << "the 2nd construct function is used ." << endl;
	}

	// 复制构造函数
	Sales_item(const Sales_item& orig)
		:isbn(orig.isbn), units_sold(orig.units_sold), revenue(orig.revenue)
	{
		cout << "copy construct function is used ." << endl;
	}

	// 赋值操作符
	Sales_item& operator=(const Sales_item& rhs)
	{
		cout << "operator= is used." << endl;
		isbn = rhs.isbn;
		units_sold = rhs.units_sold;
		revenue = rhs.revenue;
		return *this;
	}


private:
	string isbn;
	unsigned units_sold;
	double revenue;
};

Sales_item foo(Sales_item item)  // copy -> operator= -> copy 
{
	Sales_item temp;
	temp = item;
	return temp;
}

class NoName
{
public:
	NoName():pstring(new std::string),i(0),d(0){}

	// 定义复制构造函数
	NoName(const NoName& other)
		:pstring(new std::string(*(other.pstring))),
		i(other.i),
		d(other.d)
	{}

	/*如果不自定义复制构造函数的话,C++会自行定义复制构造函数如下
	NoName(const NoName& other)
		:pstring(other.pstring),i(other.i),d(other.d){}
	注意到:这里直接将指针复制过去,而不是将指针所指向的内容复制过去
	
	自动的那个是浅拷贝,释放的时候会出问题,自己要写一个深拷贝
	赋值,把指针所指向的字符串赋值过去,而不是赋值指针
	(指针赋值 就是 x y同时指向字符串 释放掉一个的时候,另外一个也释放掉了)
	*/

	// 定义赋值函数
	NoName& operator=(const NoName& rhs)
	{
		pstring = new std::string;
		*pstring = *rhs.pstring;
		i = rhs.i;
		d = rhs.d;
	}

private:
	std::string* pstring; // pointer
	int i;
	double d;

};

int main()
{
	Sales_item a;
	Sales_item b("001");

	Sales_item c(b); // use copy construct function
	a = b;// use operator= function

	Sales_item item = string("003");
	cout << "use function foo(): " << endl;
	Sales_item ret;
	ret = foo(item);
	
	cout << endl;
	cout << "Vector :" << endl;
	vector<Sales_item> vec(5); // use the default function 5 times

	cout << endl;
	cout << "数组" << endl;
	Sales_item arr[] =
	{ string("001"),string("002"),string("003") };//这里会调用3遍第二个构造函数

	return 0;

}
  C++知识库 最新文章
【C++】友元、嵌套类、异常、RTTI、类型转换
通讯录的思路与实现(C语言)
C++PrimerPlus 第七章 函数-C++的编程模块(
Problem C: 算法9-9~9-12:平衡二叉树的基本
MSVC C++ UTF-8编程
C++进阶 多态原理
简单string类c++实现
我的年度总结
【C语言】以深厚地基筑伟岸高楼-基础篇(六
c语言常见错误合集
上一篇文章      下一篇文章      查看所有文章
加:2022-03-04 15:19:49  更:2022-03-04 15:21:04 
 
开发: C++知识库 Java知识库 JavaScript Python PHP知识库 人工智能 区块链 大数据 移动开发 嵌入式 开发工具 数据结构与算法 开发测试 游戏开发 网络协议 系统运维
教程: HTML教程 CSS教程 JavaScript教程 Go语言教程 JQuery教程 VUE教程 VUE3教程 Bootstrap教程 SQL数据库教程 C语言教程 C++教程 Java教程 Python教程 Python3教程 C#教程
数码: 电脑 笔记本 显卡 显示器 固态硬盘 硬盘 耳机 手机 iphone vivo oppo 小米 华为 单反 装机 图拉丁

360图书馆 购物 三丰科技 阅读网 日历 万年历 2024年11日历 -2024/11/24 5:48:37-

图片自动播放器
↓图片自动播放器↓
TxT小说阅读器
↓语音阅读,小说下载,古典文学↓
一键清除垃圾
↓轻轻一点,清除系统垃圾↓
图片批量下载器
↓批量下载图片,美女图库↓
  网站联系: qq:121756557 email:121756557@qq.com  IT数码