OOP-实验3

news/2025/11/22 11:54:06/文章来源:https://www.cnblogs.com/dingxy-home/p/19240377

实验任务1

源代码 button.hpp,window.hpp,task1.cpp

点击查看代码 button.hpp
#pragma once#include <iostream>
#include <string>class Button
{
public:Button(const std::string &label_);const std::string &get_label() const;void click();private:std::string label;
};Button::Button(const std::string &label_) : label{label_}
{
}inline const std::string &Button::get_label() const
{return label;
}inline void Button::click()
{std::cout << "Button '" << label << "' clicked\n";
}
点击查看代码 window.hpp
#pragma once#include <iostream>
#include <vector>
#include <algorithm>
#include "button.hpp"// 窗口类
class Window
{
public:Window(const std::string &title_);void display() const;void close();void add_button(const std::string &label);void click_button(const std::string &label);private:bool has_button(const std::string &label) const;private:std::string title;std::vector<Button> buttons;
};Window::Window(const std::string &title_) : title{title_}
{buttons.push_back(Button("close"));
}inline void Window::display() const
{std::string s(40, '*');std::cout << s << std::endl;std::cout << "window : " << title << std::endl;int cnt = 0;for (const auto &button : buttons)std::cout << ++cnt << ". " << button.get_label() << std::endl;std::cout << s << std::endl;
}inline void Window::close()
{std::cout << "close window '" << title << "'" << std::endl;click_button("close");
}inline bool Window::has_button(const std::string &label) const
{for (const auto &button : buttons)if (button.get_label() == label)return true;return false;
}inline void Window::add_button(const std::string &label)
{if (has_button(label))std::cout << "button " << label << " already exists!\n";elsebuttons.push_back(Button(label));
}inline void Window::click_button(const std::string &label)
{for (auto &button : buttons)if (button.get_label() == label){button.click();return;}std::cout << "no button: " << label << std::endl;
}
点击查看代码 task1.cpp
#include "window.hpp"
#include <iostream>void test()
{Window w("Demo");w.add_button("add");w.add_button("remove");w.add_button("modify");w.add_button("add");w.display();w.close();
}int main()
{std::cout << "用组合类模拟简单GUI:\n";test();
}

运行测试截图

image

  • 问题1:这个范例中,WindowButton是组合关系吗?

  • 回答:是的,ButtonWindow组成的一部分。

  • 问题2:bool has_button(const std::string &label) const;被设计为私有。思考并回答:

  • (1)若将其改为公有接口,有何优点或风险?

  • 回答:优点是在类外也可以复用接口;风险是接口完全暴露在外部,容易造成数据泄露。

  • (2)设计类时,如何判断一个成员函数应为public还是private?(可从“用户是否需要”、“是否仅为内部实现
    细节”、“是否易破坏对象状态”等角度分析。)

  • 回答:其一,看是否需要对外部提供规范化接口,若需要则应把成员函数设计为public;其二,看是否是内部实现环节的一部分,若是则应把成员函数设计为private;其三,除为外部提供的修改接口外,其余涉及修改操作的成员函数应考虑为private。

  • 问题3:Button的接口const std::string& get_label() const;返回const std::string&。对比以下两种接口设计在性能和安全性方面的差异并精炼陈述。
    接口1:const std::string& get_label() const;
    接口2:const std::string get_label() const;

  • 回答:接口1返回const std::string&,提供的是Button成员label的本体,加以const约束,由于不涉及拷贝操作,性能更优,但label直接暴露在类外,安全性较差;接口2返回const std::string,提供的是Button成员label的副本,因此类外的操作仅针对副本,而不涉及label自己,安全性更高,但涉及到拷贝操作,性能有所损耗。

  • 问题4:把代码中所有xx.push_back(Button(xxx))改成xx.emplace_back(xxx),观察程序是否正常运行;查阅资料,回答两种写法的差别。

  • 回答:程序能够正常运行。push_back的参数是对象,将对象拷贝存到容器内;emplace_back的参数是构造对象的参数列表,通过参数列表创建对象存到容器内。

实验任务2

源代码 task2.cpp

点击查看代码 task2.cpp
#include <iostream>
#include <vector>void test1();
void test2();
void output1(const std::vector<int> &v);
void output2(const std::vector<int> &v);
void output3(const std::vector<std::vector<int>> &v);int main()
{std::cout << "深复制验证1: 标准库vector<int>\n";test1();std::cout << "\n深复制验证2: 标准库vector<int>嵌套使用\n";test2();
}void test1()
{std::vector<int> v1(5, 42);const std::vector<int> v2(v1);std::cout << "**********拷贝构造后**********\n";std::cout << "v1: ";output1(v1);std::cout << "v2: ";output1(v2);v1.at(0) = -1;std::cout << "**********修改v1[0]后**********\n";std::cout << "v1: ";output1(v1);std::cout << "v2: ";output1(v2);
}void test2()
{std::vector<std::vector<int>> v1{{1, 2, 3}, {4, 5, 6, 7}};const std::vector<std::vector<int>> v2(v1);std::cout << "**********拷贝构造后**********\n";std::cout << "v1: ";output3(v1);std::cout << "v2: ";output3(v2);v1.at(0).push_back(-1);std::cout << "**********修改v1[0]后**********\n";std::cout << "v1: \n";output3(v1);std::cout << "v2: \n";output3(v2);
}// 使用xx.at()+循环输出vector<int>数据项
void output1(const std::vector<int> &v)
{if (v.size() == 0){std::cout << '\n';return;}std::cout << v.at(0);for (auto i = 1; i < v.size(); ++i)std::cout << ", " << v.at(i);std::cout << '\n';
}// 使用迭代器+循环输出vector<int>数据项
void output2(const std::vector<int> &v)
{if (v.size() == 0){std::cout << '\n';return;}auto it = v.begin();std::cout << *it;for (it = v.begin() + 1; it != v.end(); ++it)std::cout << ", " << *it;std::cout << '\n';
}// 使用auto for分行输出vector<vector<int>>数据项
void output3(const std::vector<std::vector<int>> &v)
{if (v.size() == 0){std::cout << '\n';return;}for (auto &i : v)output2(i);
}

运行测试截图

image

  • 问题1:测试模块1中这两行代码分别完成了什么构造?v1v2各包含多少个值为42的数据项?

image

  • 回答:第1行代码完成带参构造,第2行代码完成拷贝构造。v1v2均包含5个值为42的数据项。

  • 问题2:测试模块2中这两行代码执行后,v1.size()v2.size()v1[0].size()分别是多少?

image

  • 回答:v1.size()v2.size()v1[0].size()分别是2、2、3。

  • 问题3:测试模块1中,把v1.at(0) = -1;写成v1[0] = -1;能否实现同等效果?两种用法有何区别?

  • 回答:能实现同等效果。前者是成员函数,具有索引越界的判断功能,安全性较高,但是性能低于后者;后者实现的本质是指针偏移,不具有索引越界的判断功能,性能较高,但安全性低于前者。

  • 问题4:测试模块2中执行v1.at(0).push_back(-1);

  • (1)用以下两行代码,能否输出-1?为什么?

image

  • 回答:能输出-1,因为rv1.at(0)的引用,在上一行代码中,v1.at(0)尾插-1值,r.at(r.size()-1)就是访问尾值-1.

  • (2)r定义成用const &类型接收返回值,在内存使用上有何优势?有何限制?

  • 回答:优势是避免拷贝操作,且保护v1.at(0)里的数据安全;限制是r仅能访问v1.at(0)里的元素,而不能进行修改操作。

  • 问题5:观察程序运行结果,反向分析、推断:

  • (1) 标准库模板类vector的复制构造函数实现的是深复制还是浅复制?

  • 回答:深复制。

  • (2)vector<T>::at()接口思考:当vvector<int>时,v.at(0)返回值类型是什么?当vconst vector<int>时,v.at(0)返回值类型又是什么?据此推断at()是否必须提供带const修饰的重载版本?

  • 回答:当vvector<int>时,v.at(0)返回值类型是int&;当vconst vector<int>时,v.at(0)返回值类型是const int&。因此,at()提供带const修饰的重载版本是有必要的。

实验任务3

源代码 vectorInt.hpp,task3.cpp

点击查看代码 vectorInt.hpp
#pragma once#include <iostream>// 动态int数组对象类
class vectorInt
{
public:vectorInt();vectorInt(int n_);vectorInt(int n_, int value);vectorInt(const vectorInt &vi);~vectorInt();int size() const;int &at(int index);const int &at(int index) const;vectorInt &assign(const vectorInt &vi);int *begin();int *end();const int *begin() const;const int *end() const;private:int n;// 当前数据项个数int *ptr; // 数据区
};vectorInt::vectorInt() : n{0}, ptr{nullptr} {}vectorInt::vectorInt(int n_) : n{n_}, ptr{new int[n_]} {}vectorInt::vectorInt(int n_, int value) : n{n_}, ptr{new int[n_]}
{for (auto i = 0; i < n; ++i)ptr[i] = value;
}vectorInt::vectorInt(const vectorInt &vi) : n{vi.n}, ptr{new int[n]}
{for (auto i = 0; i < n; ++i)ptr[i] = vi.ptr[i];
}vectorInt::~vectorInt()
{delete[] ptr;
}int vectorInt::size() const
{return n;
}const int &vectorInt::at(int index) const
{if (index < 0 || index >= n){std::cerr << "IndexError: index out of range\n";std::exit(1);}return ptr[index];
}int &vectorInt::at(int index)
{if (index < 0 || index >= n){std::cerr << "IndexError: index out of range\n";std::exit(1);}return ptr[index];
}vectorInt &vectorInt::assign(const vectorInt &vi)
{if (this == &vi)return *this;int *ptr_tmp;ptr_tmp = new int[vi.n];for (int i = 0; i < vi.n; ++i)ptr_tmp[i] = vi.ptr[i];delete[] ptr;n = vi.n;ptr = ptr_tmp;return *this;
}int *vectorInt::begin()
{return ptr;
}int *vectorInt::end()
{return ptr + n;
}const int *vectorInt::begin() const
{return ptr;
}const int *vectorInt::end() const
{return ptr + n;
}
点击查看代码 task3.cpp
#include "vectorInt.hpp"
#include <iostream>void test1();
void test2();
void output1(const vectorInt &vi);
void output2(const vectorInt &vi);int main()
{std::cout << "测试1: \n";test1();std::cout << "\n测试2: \n";test2();
}void test1()
{int n;std::cout << "Enter n: ";std::cin >> n;vectorInt x1(n);for (auto i = 0; i < n; ++i)x1.at(i) = (i + 1) * 10;std::cout << "x1: ";output1(x1);vectorInt x2(n, 42);vectorInt x3(x2);x2.at(0) = -1;std::cout << "x2: ";output1(x2);std::cout << "x3: ";output1(x3);
}void test2()
{const vectorInt x(5, 42);vectorInt y;y.assign(x);std::cout << "x: ";output2(x);std::cout << "y: ";output2(y);
}// 使用xx.at()+循环输出vectorInt对象数据项
void output1(const vectorInt &vi)
{if (vi.size() == 0){std::cout << '\n';return;}std::cout << vi.at(0);for (auto i = 1; i < vi.size(); ++i)std::cout << ", " << vi.at(i);std::cout << '\n';
}// 使用迭代器+循环输出vectorInt对象数据项
void output2(const vectorInt &vi)
{if (vi.size() == 0){std::cout << '\n';return;}auto it = vi.begin();std::cout << *it;for (it = vi.begin() + 1; it != vi.end(); ++it)std::cout << ", " << *it;std::cout << '\n';
}

运行测试截图

image

  • 问题1:当前验证性代码中,vectorInt接口assign实现是安全版本。如果把assign实现改成版本2,逐条指出版本2存在的安全隐患和缺陷。(提示:对比两个版本,找出差异化代码,加以分析)
// 版本2
vectorInt &vectorInt::assign(const vectorInt &vi)
{delete[] ptr;n = vi.n;ptr = new int[n];for (int i = 0; i < n; ++i)ptr[i] = vi.ptr[i];return *this;
}
  • 回答:一是未判断this == &vi,存在冗余操作的风险;二是直接将ptr指向尚未赋值完成的空间,安全性较弱。

  • 问题2:当前验证性代码中,重载接口at内部代码完全相同。若把非const版本改成如下实现,可消除重复并遵循“最小化接口”原则(未来如需更新接口,只更新const接口,另一个会同步)。

int &vectorInt::at(int index)
{return const_cast<int &>(static_cast<const vectorInt *>(this)->at(index));
}
  • (1)static_cast<const vectorInt*>(this)的作用是什么?转换前后this的类型分别是什么?转换目的?

  • 回答:static_cast<const vectorInt*>(this)vectorInt指针this转为const vectorInt指针,为了给this加上const约束。

  • (2)const_cast<int&>的作用是什么?转换前后的返回类型分别是什么?转换目的?

  • 回答:const_cast<int&>const vectorInt指针转为int&类型,为了与返回值匹配。

  • 问题3:vectorInt类封装了begin()end()的const/非const接口。

  • (1)以下代码片段,分析编译器如何选择重载版本,并总结这两种重载分别适配什么使用场景。

vectorInt v1(5);
const vectorInt v2(5);
auto it1 = v1.begin(); // 调用哪个版本?
auto it2 = v2.begin(); // 调用哪个版本?
  • 回答:根据const/非const匹配对应const/非const接口。const版本适用于仅访问对象数据的场景,非const版本适用于涉及对象修改的场景。

  • (2)拓展思考(选答*):标准库迭代器本质上是指针的封装。vectorInt直接返回原始指针作为迭代器,这种设计让你对迭代器有什么新的理解?

  • 回答:这说明迭代器也可以使用指针的操作。

  • 问题4:以下两个构造函数及assign接口实现,都包含内存块的赋值和复制操作。使用算法库<algorithm>改成如下写法是否可以?回答这3行更新代码的功能。

vectorInt::vectorInt(int n_, int value) : n{n_}, ptr{new int[n_]}
{std::fill_n(ptr, n, value); // 更新
}
vectorInt::vectorInt(const vectorInt &vi) : n{vi.n}, ptr{new int[n]}
{std::copy_n(vi.ptr, vi.n, ptr); // 更新
}
vectorInt &vectorInt::assign(const vectorInt &vi)
{if (this == &vi)return *this;int *ptr_tmp;ptr_tmp = new int[vi.n];std::copy_n(vi.ptr, vi.n, ptr_tmp); // 更新delete[] ptr;n = vi.n;ptr = ptr_tmp;return *this;
}
  • 回答:可以。第一个函数实现大小为n,值均为valuevectorInt对象初始化;第二个函数实现拷贝构造函数的操作;第三个函数实现已有对象的拷贝操作。

实验任务4

源代码 matrix.hpp,task4.cpp

点击查看代码 matrix.hpp
#pragma once#include <iostream>
#include <algorithm>
#include <cstdlib>// 类Matrix声明
class Matrix
{
public:Matrix(int rows_, int cols_, double value = 0); // 构造rows_*cols_矩阵对象, 初值valueMatrix(int rows_, double value = 0);            // 构造rows_*rows_方阵对象, 初值valueMatrix(const Matrix &x);                        // 深复制~Matrix();void set(const double *pvalue, int size); // 按行复制pvalue指向的数据,要求size=rows*cols,否则报错退出void clear();                             // 矩阵对象数据项置0const double &at(int i, int j) const; // 返回矩阵对象索引(i,j)对应的数据项const引用(越界则报错后退出)double &at(int i, int j);             // 返回矩阵对象索引(i,j)对应的数据项引用(越界则报错后退出)int rows() const; // 返回矩阵对象行数int cols() const; // 返回矩阵对象列数void print() const; // 按行打印数据private:int n_rows;  // 矩阵对象内元素行数int n_cols;  // 矩阵对象内元素列数double *ptr; // 数据区
};// 构造rows_*cols_矩阵对象, 初值value
Matrix::Matrix(int rows_, int cols_, double value): n_rows(rows_), n_cols(cols_)
{ptr = new double[n_rows * n_cols];std::fill(ptr, ptr + n_rows * n_cols, value);
}// 构造rows_*rows_方阵对象, 初值value
Matrix::Matrix(int rows_, double value): n_rows(rows_), n_cols(rows_)
{ptr = new double[n_rows * n_cols];std::fill(ptr, ptr + n_rows * n_cols, value);
}// 深复制
Matrix::Matrix(const Matrix &x): n_rows(x.n_rows), n_cols(x.n_cols)
{ptr = new double[n_rows * n_cols];std::copy(x.ptr, x.ptr + n_rows * n_cols, ptr);
}// 析构函数
Matrix::~Matrix()
{delete[] ptr;
}// 按行复制pvalue指向的数据,要求size=rows*cols,否则报错退出
void Matrix::set(const double *pvalue, int size)
{if (size != n_rows * n_cols){std::cerr << "Error: Size mismatch in set method." << std::endl;std::exit(EXIT_FAILURE);}std::copy(pvalue, pvalue + size, ptr);
}// 矩阵对象数据项置0
void Matrix::clear()
{std::fill(ptr, ptr + n_rows * n_cols, 0);
}// 返回矩阵对象索引(i,j)对应的数据项const引用(越界则报错后退出)
const double &Matrix::at(int i, int j) const
{if (i < 0 || i >= n_rows || j < 0 || j >= n_cols){std::cerr << "IndexError: Index out of range." << std::endl;std::exit(EXIT_FAILURE);}return ptr[i * n_cols + j];
}// 返回矩阵对象索引(i,j)对应的数据项引用(越界则报错后退出)
double &Matrix::at(int i, int j)
{if (i < 0 || i >= n_rows || j < 0 || j >= n_cols){std::cerr << "IndexError: Index out of range." << std::endl;std::exit(EXIT_FAILURE);}return ptr[i * n_cols + j];
}// 返回矩阵对象行数
int Matrix::rows() const
{return n_rows;
}// 返回矩阵对象列数
int Matrix::cols() const
{return n_cols;
}// 按行打印数据
void Matrix::print() const
{for (int i = 0; i < n_rows; i++){for (int j = 0; j < n_cols; j++){std::cout << at(i, j) << ", ";}std::cout << std::endl;}
}
点击查看代码 task4.cpp
#include <iostream>
#include <cstdlib>
#include "matrix.hpp"void test1();
void test2();
void output(const Matrix &m, int row_index);int main()
{std::cout << "测试1: \n";test1();std::cout << "\n测试2: \n";test2();
}void test1()
{double x[1000] = {1, 2, 3, 4, 5, 6, 7, 8, 9, 10};int n, m;std::cout << "Enter n and m: ";std::cin >> n >> m;Matrix m1(n, m);  // 创建矩阵对象m1, 大小n×mm1.set(x, n * m); // 用一维数组x的值按行为矩阵m1赋值Matrix m2(m, n);  // 创建矩阵对象m2, 大小m×nm2.set(x, m * n); // 用一维数组x的值按行为矩阵m1赋值Matrix m3(n);     // 创建一个n×n方阵对象m3.set(x, n * n); // 用一维数组x的值按行为矩阵m3赋值std::cout << "矩阵对象m1: \n";m1.print();std::cout << "矩阵对象m2: \n";m2.print();std::cout << "矩阵对象m3: \n";m3.print();
}void test2()
{Matrix m1(2, 3, -1);const Matrix m2(m1);std::cout << "矩阵对象m1: \n";m1.print();std::cout << "矩阵对象m2: \n";m2.print();m1.clear();m1.at(0, 0) = 1;std::cout << "m1更新后: \n";std::cout << "矩阵对象m1第0行 ";output(m1, 0);std::cout << "矩阵对象m2第0行: ";output(m2, 0);
}// 输出矩阵对象row_index行所有元素
void output(const Matrix &m, int row_index)
{if (row_index < 0 || row_index >= m.rows()){std::cerr << "IndexError: row index out of range\n";exit(1);}std::cout << m.at(row_index, 0);for (int j = 1; j < m.cols(); ++j)std::cout << ", " << m.at(row_index, j);std::cout << '\n';
}

运行测试截图

img

实验任务5

源代码 contact.hpp,contactBook.hpp,task5.cpp

点击查看代码 contact.hpp
#pragma once#include <iostream>
#include <string>// 联系人类
class Contact
{
public:Contact(const std::string &name_, const std::string &phone_);const std::string &get_name() const;const std::string &get_phone() const;void display() const;private:std::string name;  // 必填项std::string phone; // 必填项
};Contact::Contact(const std::string &name_, const std::string &phone_) : name{name_}, phone{phone_} {}const std::string &Contact::get_name() const
{return name;
}const std::string &Contact::get_phone() const
{return phone;
}void Contact::display() const
{std::cout << name << ", " << phone;
}
点击查看代码 contactBook.hpp
#pragma once#include <iostream>
#include <string>
#include <vector>
#include <algorithm>
#include "contact.hpp"// 通讯录类
class ContactBook
{
public:void add(const std::string &name, const std::string &phone); // 添加联系人void remove(const std::string &name);                        // 移除联系人void find(const std::string &name) const;                    // 查找联系人void display() const;                                        // 显示所有联系人size_t size() const;private:int index(const std::string &name) const; // 返回联系人在contacts内索引,如不存在,返回-1void sort();                              // 按姓名字典序升序排序通讯录private:std::vector<Contact> contacts;
};void ContactBook::add(const std::string &name, const std::string &phone)
{if (index(name) == -1){contacts.push_back(Contact(name, phone));std::cout << name << " add successfully.\n";sort();return;}std::cout << name << " already exists. fail to add!\n";
}void ContactBook::remove(const std::string &name)
{int i = index(name);if (i == -1){std::cout << name << " not found, fail to remove!\n";return;}contacts.erase(contacts.begin() + i);std::cout << name << " remove successfully.\n";
}void ContactBook::find(const std::string &name) const
{int i = index(name);if (i == -1){std::cout << name << " not found!\n";return;}contacts[i].display();std::cout << '\n';
}void ContactBook::display() const
{for (auto &c : contacts){c.display();std::cout << '\n';}
}size_t ContactBook::size() const
{return contacts.size();
}// 待补足1:int index(const std::string &name) const;实现
// 返回联系人在contacts内索引; 如不存在,返回-1
int ContactBook::index(const std::string &name) const
{for (size_t i = 0; i < contacts.size(); ++i){if (contacts[i].get_name() == name){return static_cast<int>(i);}}return -1;
}// 待补足2:void ContactBook::sort();实现
// 按姓名字典序升序排序通讯录
void ContactBook::sort()
{std::sort(contacts.begin(), contacts.end(), [](const Contact &a, const Contact &b){ return a.get_name() < b.get_name(); });
}
点击查看代码 task5.cpp
#include "contactBook.hpp"void test()
{ContactBook contactbook;std::cout << "1. add contacts\n";contactbook.add("Bob", "18199357253");contactbook.add("Alice", "17300886371");contactbook.add("Linda", "18184538072");contactbook.add("Alice", "17300886371");std::cout << "\n2. display contacts\n";std::cout << "There are " << contactbook.size() << " contacts.\n";contactbook.display();std::cout << "\n3. find contacts\n";contactbook.find("Bob");contactbook.find("David");std::cout << "\n4. remove contact\n";contactbook.remove("Bob");contactbook.remove("David");
}int main()
{test();
}

运行测试截图

img

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

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

相关文章

2025年优秀的火山岩滤料行业内知名厂家排行榜

2025年优秀的火山岩滤料行业内知名厂家排行榜行业背景与市场趋势火山岩滤料作为一种高效环保过滤材料,近年来在水处理、人工湿地建设和工业过滤等领域应用日益广泛。根据中国环保产业协会2024年发布的《中国水处理材料…

2025年知名的热镀锌钢零售品牌竞争力口碑排行榜

2025年知名的热镀锌钢零售品牌竞争力口碑排行榜 行业背景与市场趋势 热镀锌钢因其优异的耐腐蚀性、高强度及长寿命,广泛应用于建筑、交通、机械制造、家居等领域。随着国内基建投资的持续增长以及绿色建筑材料的推广…

NCHU_单部电梯调度程序的题后分析与总结

1.前言: 这三次题目集围绕电梯调度系统的设计与实现,清晰地展现了面向对象编程思想和软件设计原则的迭代深化过程。题目集5(第一次)的核心任务是实现一个基础的单类电梯系统。它主要考察了面向对象编程的基础概念,…

2025年换热器盘管批发厂家权威推荐:U型弯管/筒体半圆管/不锈钢盘管源头供应商精选

面对市场众多选择,这份基于客观数据与行业调研的榜单有望为您的采购决策提供有力参考。 在工业生产与商业供热、制冷领域中,换热器盘管作为关键设备,其性能优劣直接影响到整个系统的能效与运行成本。据QYResearch最…

2025年比较好的水泥基防火涂料最新TOP品牌厂家排行

2025年水泥基防火涂料最新TOP品牌厂家排行行业背景与市场趋势随着建筑安全标准的不断提高和防火意识的增强,水泥基防火涂料市场在2025年迎来了新一轮增长。根据中国建筑材料联合会最新数据,2025年全球水泥基防火涂料…

xss-lab全通关

xss漏洞的基础靶场xss-labs Less-1 首先是代码审计,可以看到是利用name参数进行GET传参,$str没有进行任何的过滤,只要触发了alert函数也就是弹窗了就会自动跳转下一关 <!DOCTYPE html><!--STATUS OK-->&…

2025年比较好的净化器光触媒厂家最新权威推荐排行榜

2025年比较好的净化器光触媒厂家最新权威推荐排行榜行业背景与市场趋势随着环境污染问题日益严重和公众健康意识不断提升,空气净化器市场近年来呈现爆发式增长。据市场研究机构Statista数据显示,2024年全球空气净化器…

2025年质量好的螺旋风管加工厂家最新推荐权威榜

2025年质量好的螺旋风管加工厂家最新推荐权威榜行业背景与市场趋势随着我国建筑行业持续发展和工业制造水平不断提升,螺旋风管作为通风系统的重要组成部分,市场需求呈现稳定增长态势。据中国通风设备行业协会最新数据…

2025年评价高的插补y车铣复合最新TOP厂家排名

2025年评价高的插补y车铣复合最新TOP厂家排名行业背景与市场趋势随着制造业向智能化、精密化方向快速发展,车铣复合机床作为高端数控机床的重要分支,正迎来前所未有的市场机遇。根据中国机床工具工业协会最新数据,2…

2025年可靠的耐磨尼龙改性颗粒厂家最新实力排行

2025年可靠的耐磨尼龙改性颗粒厂家最新实力排行行业背景与市场趋势随着全球制造业的持续升级和新兴产业的快速发展,耐磨尼龙改性颗粒作为工程塑料领域的重要材料,市场需求呈现稳定增长态势。据中国塑料加工工业协会最…

2025年小型自动切片机制造商权威推荐榜单:切片机/冷凝结晶切片机/徕卡切片机源头制造商精选

在生命科学与材料研究高速发展的今天,三家各具特色的小型自动切片机制造商正以专业能力赢得市场认可。 小型自动切片机作为实验室精密设备的重要组成部分,因其操作便捷、精度高、占地面积小等特点,在生物医学、材料…

2025年热门的地磅厂家最新权威推荐排行榜

2025年热门的地磅厂家最新权威推荐排行榜行业背景与市场趋势随着工业4.0和智能制造的深入推进,称重设备作为工业生产、物流运输和商业贸易中不可或缺的基础设施,正迎来新一轮技术升级和市场扩容。据《2024-2029年中国…

2025年镀锌波纹排水管厂家权威推荐榜单:排水管/镀锌排水管/波纹排水管源头厂家精选

在市政工程、公路排水和水利建设等领域,镀锌波纹排水管因其耐腐蚀、强度高和安装便捷的特点,已成为基础设施建设的关键材料。行业数据显示,2025年中国镀锌波纹钢管市场规模预计达到185亿元,年产量突破350万吨,在市…

2025年知名的鼓风式冷却塔厂家推荐及选购参考榜

2025年知名的鼓风式冷却塔厂家推荐及选购参考榜行业背景与市场趋势随着全球工业化进程加速和节能减排政策日趋严格,鼓风式冷却塔作为工业循环水冷却系统的核心设备,市场需求持续增长。据中国制冷空调工业协会(CRAA)…

251122预感到今天要上硬仗

16进8,应该今天要上男双,拼吧

2025年比较好的厚壁不锈钢焊管TOP实力厂家推荐榜

2025年比较好的厚壁不锈钢焊管TOP实力厂家推荐榜行业背景与市场趋势不锈钢焊管作为工业领域的重要基础材料,近年来随着我国制造业升级和基础设施建设加速,市场需求持续增长。据中国特钢企业协会不锈钢分会统计,2023…

Android Studio 使用教程 - 教程

pre { white-space: pre !important; word-wrap: normal !important; overflow-x: auto !important; display: block !important; font-family: "Consolas", "Monaco", "Courier New", …

【神秘题解】NOIP 前复健

题意 有 \(n\) 名同学从左到右排成一排,第 \(i\) 名同学的身高为 \(h_i\)。现在张老师想改变排队的顺序,他能进行任意多次(包括 0 次)如下操作:如果两名同学相邻,并且他们的身高之差不超过 \(D\),那么老师就能交…

2025年质量好的液压水渠成型机厂家实力及用户口碑排行榜

2025年质量好的液压水渠成型机厂家实力及用户口碑排行榜行业背景与市场趋势随着我国农业现代化进程的加速推进和水利基础设施建设的持续投入,液压水渠成型机作为农田水利建设的关键设备,市场需求呈现稳定增长态势。根…

2025年金属腐蚀检测制造企业权威榜单:金属腐蚀实验/金属腐蚀测试/晶间腐蚀检测标杆企业精选

在工业制造、能源化工、航空航天等领域,金属材料的腐蚀问题直接影响设备寿命与生产安全。根据行业统计,全球每年因金属腐蚀造成的经济损失约占各国GDP的3%-5%,而有效的腐蚀检测可帮助企业降低30%以上的维护成本。为…