Eigen学习笔记1
固定大小的矩阵和向量
/** 参考链接:http://eigen.tuxfamily.org/dox-2.0/TutorialCore.html#TutorialCoreGettingStarted
*/#include <iostream>
#include <Eigen/Core>using namespace Eigen;
using namespace std; // import most common Eigen types
int main(int, char *[])
{Matrix3f m3; //3x3单精度矩阵m3 << 1, 2, 3, 4, 5, 6, 7, 8, 9;Matrix4f m4 = Matrix4f::Identity(); //4x4单位矩阵(单精度)Vector4i v4(1, 2, 3, 4); // 长度为4的整型向量// 输出结果std::cout << "m3\n" << m3 << "\nm4:\n"<< m4 << "\nv4:\n" << v4 << std::endl;
}
- 1
- 2
- 3
- 4
- 5
- 6
- 7
- 8
- 9
- 10
- 11
- 12
- 13
- 14
- 15
- 16
- 17
- 18
- 19
- 20
- 21
- 22
- Matrix表示矩阵,Vector表示向量,数字表示维度,最后的f和i分别表示单精度和整型数据类型。
- 固定大小表示编译时,行数和列数是固定的。这时,Eigen不会分配动态内存。这对于比较小的尺寸比较适合,比如16x16。
动态大小的矩阵和向量
/** 参考链接:http://eigen.tuxfamily.org/dox-2.0/TutorialCore.html#TutorialCoreGettingStarted
*/#include <iostream>
#include <Eigen/Core>using namespace Eigen;
using namespace std; int main(int, char *[])
{// 动态矩阵for (int size=1; size<=4; ++size){MatrixXi m(size,size+1); // 一个整型的大小为 (size)x(size+1) 的矩阵for (int j=0; j<m.cols(); ++j) // 遍历列for (int i=0; i<m.rows(); ++i) // 遍历行m(i,j) = i+j*m.rows(); // 使用圆括号m(i,j)访问矩阵的元素std::cout << m << "\n\n"; //打印矩阵}// 动态向量VectorXf v(4); // 定义一个4维单精度向量// 使用圆括号()或方括号[]访问向量元素v[0] = 1; v[1] = 2; v(2) = 3; v(3) = 4;std::cout << "\nv:\n" << v << std::endl;
}
- 1
- 2
- 3
- 4
- 5
- 6
- 7
- 8
- 9
- 10
- 11
- 12
- 13
- 14
- 15
- 16
- 17
- 18
- 19
- 20
- 21
- 22
- 23
- 24
- 25
- 26
- 27
- 28
- 小结:X表示动态大小。
#include <Eigen/Eigen>
将包含所有的Eigen函数。#include <Eigen/Dense>
包含所有普通矩阵函数,不包括稀疏矩阵函数。它们会增加编译时间。
矩阵和向量类型
- Eigen中的所有密集矩阵和向量都是通过Matrix类来表示的。Matrix通过一系列的模板参数来生成具体的类别。
Matrix<Scalar, RowsAtCompileTime, ColsAtCompileTime>
中,Scalar表示数据类型,RowsAtCompileTime和ColsAtCompileTime分别表示编译时的行数和列数。Vector3d
定义为Matrix<double, 3, 1>
- 对于动态大小的类型,在编译时不指定行数和列数,使用Eigen::Dynamic。比如,
VectorXd
定义为Matrix<double, Dynamic, 1>
。
访问元素
- Eigen支持以下的读/写元素语法:
matrix(i,j);
vector(i)
vector[i]
vector.x() // first coefficient
vector.y() // second coefficient
vector.z() // third coefficient
vector.w() // fourth coefficient
- 1
- 2
- 3
- 4
- 5
- 6
- 7
- 矩阵只能通过圆括号()访问;
- 向量可以通过圆括号()和方括号[]访问。
- 上述的元素访问方法都通过断言检查范围,代价比较大。
- 通过定义EIGEN_NO_DEBUG 或 NDEBUG,取消断言。
- 通过使用
coeff()
和coeffRef()
,来取消检查。比如,MatrixBase::coeff(int,int) const, MatrixBase::coeffRef(int,int)等。
创建和初始化矩阵和向量
通过预定义矩阵初始化
创建固定大小的矩阵和向量
/** 参考链接:http://eigen.tuxfamily.org/dox-2.0/TutorialCore.html#TutorialCoreGettingStarted
*/#include <iostream>
#include <Eigen/Core>using namespace Eigen;
using namespace std; int main(int, char *[])
{float value = 3.0;Matrix3f x; // 创建一个3x3的单精度矩阵x = Matrix3f::Zero(); //全零矩阵cout << x << endl << endl;x = Matrix3f::Ones(); //全一矩阵cout << x << endl << endl;x = Matrix3f::Constant(value); //全value矩阵cout << x << endl << endl;x = Matrix3f::Identity(); //单位矩阵cout << x << endl << endl;x = Matrix3f::Random(); // 随机矩阵cout << x << endl << endl;x.setZero();cout << x << endl << endl;x.setOnes();cout << x << endl << endl;x.setIdentity();cout << x << endl << endl;x.setConstant(value);cout << x << endl << endl;x.setRandom();cout << x << endl << endl;
}
- 1
- 2
- 3
- 4
- 5
- 6
- 7
- 8
- 9
- 10
- 11
- 12
- 13
- 14
- 15
- 16
- 17
- 18
- 19
- 20
- 21
- 22
- 23
- 24
- 25
- 26
- 27
- 28
- 29
- 30
- 31
- 32
- 33
- 34
- 35
创建动态大小的矩阵
/** 参考链接:http://eigen.tuxfamily.org/dox-2.0/TutorialCore.html#TutorialCoreGettingStarted
*/#include <iostream>
#include <Eigen/Core>using namespace Eigen;
using namespace std; int main(int, char *[])
{float value = 3.0f;int rows = 3;int cols = 4;MatrixXf x;x = MatrixXf::Zero(rows, cols);cout << x << endl << endl;x = MatrixXf::Ones(rows, cols);cout << x << endl << endl;x = MatrixXf::Constant(rows, cols, value);cout << x << endl << endl;x = MatrixXf::Identity(rows, cols);cout << x << endl << endl;x = MatrixXf::Random(rows, cols);cout << x << endl << endl;x.setZero(rows, cols);cout << x << endl << endl;x.setOnes(rows, cols);cout << x << endl << endl;x.setConstant(rows, cols, value);cout << x << endl << endl;x.setIdentity(rows, cols);cout << x << endl << endl;x.setRandom(rows, cols);cout << x << endl << endl;return 0;
}
- 1
- 2
- 3
- 4
- 5
- 6
- 7
- 8
- 9
- 10
- 11
- 12
- 13
- 14
- 15
- 16
- 17
- 18
- 19
- 20
- 21
- 22
- 23
- 24
- 25
- 26
- 27
- 28
- 29
- 30
- 31
- 32
- 33
- 34
- 35
- 36
- 37
- 38
创建动态大小的向量
/** 参考链接:http://eigen.tuxfamily.org/dox-2.0/TutorialCore.html#TutorialCoreGettingStarted
*/#include <iostream>
#include <Eigen/Core>using namespace Eigen;
using namespace std; int main(int, char *[])
{int size = 3;float value = 3.0f;VectorXf x; // 定义动态向量x = VectorXf::Zero(size); //全0向量cout << x << endl << endl;x = VectorXf::Ones(size); //全1向量cout << x << endl << endl;x = VectorXf::Constant(size, value);//全value向量cout << x << endl << endl;//x = VectorXf::Identity(size);//报错x = VectorXf::Random(size);cout << x << endl << endl;x.setZero(size);cout << x << endl << endl;x.setOnes(size);cout << x << endl << endl;x.setConstant(size, value);cout << x << endl << endl;//x.setIdentity(size);x.setRandom(size);cout << x << endl << endl;return 0;
}
- 1
- 2
- 3
- 4
- 5
- 6
- 7
- 8
- 9
- 10
- 11
- 12
- 13
- 14
- 15
- 16
- 17
- 18
- 19
- 20
- 21
- 22
- 23
- 24
- 25
- 26
- 27
- 28
- 29
- 30
- 31
- 32
- 33
- 34
- 35
创建固定大小的基向量
/** 参考链接:http://eigen.tuxfamily.org/dox-2.0/TutorialCore.html#TutorialCoreGettingStarted
*/#include <iostream>
#include <Eigen/Core>using namespace Eigen;
using namespace std; int main(int, char *[])
{Vector3f x;x = Vector3f::UnitX(); // 1 0 0cout << x << endl << endl;x = Vector3f::UnitY(); // 0 1 0cout << x << endl << endl;x = Vector3f::UnitZ(); // 0 0 1cout << x << endl << endl;return 0;
}
- 1
- 2
- 3
- 4
- 5
- 6
- 7
- 8
- 9
- 10
- 11
- 12
- 13
- 14
- 15
- 16
- 17
- 18
- 19
- 20
- 21
- 22
创建动态大小的基向量
/** 参考链接:http://eigen.tuxfamily.org/dox-2.0/TutorialCore.html#TutorialCoreGettingStarted
*/#include <iostream>
#include <Eigen/Core>using namespace Eigen;
using namespace std; int main(int, char *[])
{VectorXf x;x = VectorXf::Unit(4,1);cout << x << endl << endl;x = Vector4f(0,1,0,0);cout << x << endl << endl;x = Vector4f::UnitY();cout << x << endl << endl;return 0;
}
- 1
- 2
- 3
- 4
- 5
- 6
- 7
- 8
- 9
- 10
- 11
- 12
- 13
- 14
- 15
- 16
- 17
- 18
- 19
- 20
- 21
- 22
例子
/** 参考链接:http://eigen.tuxfamily.org/dox-2.0/TutorialCore.html#TutorialCoreGettingStarted
*/#include <iostream>
#include <Eigen/Core>using namespace Eigen;
using namespace std; int main(int, char *[])
{cout << MatrixXf::Constant(2, 3, sqrt(2)) << endl; // 2x3的单精度矩阵RowVector3i v; //3维行向量v.setConstant(6);cout << "v = " << v << endl;return 0;
}
- 1
- 2
- 3
- 4
- 5
- 6
- 7
- 8
- 9
- 10
- 11
- 12
- 13
- 14
- 15
- 16
- 17
- 18
- 19
- 20
通过Cast的方式初始化
相同尺寸的矩阵兼容
- 元素类型通过
MatrixBase::cast()
自动转换。
/** 参考链接:http://eigen.tuxfamily.org/dox-2.0/TutorialCore.html#TutorialCoreGettingStarted
*/#include <iostream>
#include <Eigen/Core>
#include <Eigen/Eigen>using namespace Eigen;
using namespace std; int main(int, char *[])
{Vector3d md(1,2,3);Vector3f mf = md.cast<float>();cout << "md = " << md << endl;cout << "mf = " << mf << endl;return 0;
}
- 1
- 2
- 3
- 4
- 5
- 6
- 7
- 8
- 9
- 10
- 11
- 12
- 13
- 14
- 15
- 16
- 17
- 18
- 19
相同类型的矩阵兼容
/** 参考链接:http://eigen.tuxfamily.org/dox-2.0/TutorialCore.html#TutorialCoreGettingStarted
*/#include <iostream>
#include <Eigen/Core>using namespace Eigen;
using namespace std; int main(int, char *[])
{MatrixXf res(10,10);Matrix3f a, b;a = Matrix3f::Identity();b = Matrix3f::Constant(3);res = a+b; // OK: res is resized to size 3x3cout << a << endl << endl;cout << b << endl << endl;cout << res << endl << endl;return 0;
}
- 1
- 2
- 3
- 4
- 5
- 6
- 7
- 8
- 9
- 10
- 11
- 12
- 13
- 14
- 15
- 16
- 17
- 18
- 19
- 20
- 21
- 22
- 23
通过Map方式初始化
/** 参考链接:http://eigen.tuxfamily.org/dox-2.0/TutorialCore.html#TutorialCoreGettingStarted
*/#include <iostream>
#include <vector>
#include <Eigen/Core>using namespace Eigen;
using namespace std; int main(int, char *[])
{std::vector<float> stlarray(10);VectorXf::Map(&stlarray[0], stlarray.size()).squaredNorm();return 0;
}
- 1
- 2
- 3
- 4
- 5
- 6
- 7
- 8
- 9
- 10
- 11
- 12
- 13
- 14
- 15
- 16
- 17
- 18
- 下面的代码没有完全调通
/** 参考链接:http://eigen.tuxfamily.org/dox-2.0/TutorialCore.html#TutorialCoreGettingStarted
*/#include <iostream>
#include <vector>
#include <Eigen/Core>using namespace Eigen;
using namespace std; int main(int, char *[])
{const int rows = 3;const int cols = 4;float array[rows*cols];Map<MatrixXf> m(array,rows,cols);Matrix3f othermatrix1 = Matrix3f::Identity();//单位矩阵MatrixXf othermatrix2(3,4);othermatrix2 = MatrixXf::Constant(3,4,5);//3x4的常量矩阵,值都为5m = othermatrix1 * othermatrix2;//m.eigenvalues();std::vector<float> stlarray(10);VectorXf::Map(&stlarray[0], stlarray.size()).squaredNorm();cout << m << endl;return 0;
}
- 1
- 2
- 3
- 4
- 5
- 6
- 7
- 8
- 9
- 10
- 11
- 12
- 13
- 14
- 15
- 16
- 17
- 18
- 19
- 20
- 21
- 22
- 23
- 24
- 25
- 26
- 27
通过逗号初始化
/** 参考链接:http://eigen.tuxfamily.org/dox-2.0/TutorialCore.html#TutorialCoreGettingStarted
*/#include <iostream>
#include <vector>
#include <Eigen/Core>using namespace Eigen;
using namespace std; int main(int, char *[])
{Matrix3f m;m << 1, 2, 3,4, 5, 6,7, 8, 9;cout << m << endl;return 0;
}
- 1
- 2
- 3
- 4
- 5
- 6
- 7
- 8
- 9
- 10
- 11
- 12
- 13
- 14
- 15
- 16
- 17
- 18
- 19
- 20
- 使用逗号和子矩阵,初始化矩阵。
/** 参考链接:http://eigen.tuxfamily.org/dox-2.0/TutorialCore.html#TutorialCoreGettingStarted
*/#include <iostream>
#include <vector>
#include <Eigen/Core>using namespace Eigen;
using namespace std; int main(int, char *[])
{int rows=5, cols=5;MatrixXf m(rows,cols);m << (Matrix3f() << 1, 2, 3, 4, 5, 6, 7, 8, 9).finished(),//左上角3x3MatrixXf::Zero(3,cols-3), //右上角3x2MatrixXf::Zero(rows-3,3), //左下角2x3MatrixXf::Identity(rows-3,cols-3); //右下角2x2cout << m << endl;return 0;
}
- 1
- 2
- 3
- 4
- 5
- 6
- 7
- 8
- 9
- 10
- 11
- 12
- 13
- 14
- 15
- 16
- 17
- 18
- 19
- 20
- 21
- 22
- 23
.finished()
用于当临时矩阵初始化完成时,获取实际的矩阵对象。尽管看起来很复杂,但实际上编译时已经优化。
算术操作
传统的数学运算
- 矩阵/向量乘法:
col2 = mat1 * col1; //矩阵x列向量
row2 = row1 * mat1; // 行向量x矩阵
row1 *= mat1;
mat3 = mat1 * mat2;
mat3 *= mat1;
- 1
- 2
- 3
- 4
- 5
- 矩阵/向量加法/减法:
mat3 = mat1 + mat2;
mat3 += mat1;
mat3 = mat1 - mat2;
mat3 -= mat1;
- 1
- 2
- 3
- 4
- 标量加法/减法:
mat3 = mat1 * s1;
mat3 = s1 * mat1;
mat3 *= s1;
mat3 = mat1 / s1;
mat3 /= s1;
- 1
- 2
- 3
- 4
- 5
逐元素的操作
逐元素的操作,请查阅
.cwise()
。逐元素乘法
mat3 = mat1.cwise() * mat2;
- 1
- 加/减标量
//需要Array模块 #include <Eigen/Array>
mat3 = mat1.cwise() + scalar;
mat3.cwise() += scalar;
mat3.cwise() -= scalar;
- 1
- 2
- 3
- 4
- 逐元素除法
//需要Array模块 #include <Eigen/Array>
mat3 = mat1.cwise() / mat2;
- 1
- 2
- 逐元素取倒数
//需要Array模块 #include <Eigen/Array>
mat3 = mat1.cwise().inverse();
- 1
- 2
- 逐元素比较运算
//需要Array模块 #include <Eigen/Array>
mat3 = mat1.cwise() < mat2;
mat3 = mat1.cwise() <= mat2;
mat3 = mat1.cwise() > mat2;
//等
- 1
- 2
- 3
- 4
- 5
- 三角余弦
- sin(), cos()等。
//需要Array模块 #include <Eigen/Array>
mat3 = mat1.cwise().sin();
// 等
- 1
- 2
- 3
- 指数
- pow(), square(), cube(), sqrt(), exp(), log()等。
//需要Array模块 #include <Eigen/Array>
mat3 = mat1.cwise().square();
mat3 = mat1.cwise().pow(5);
mat3 = mat1.cwise().log();
//等
- 1
- 2
- 3
- 4
- 5
- 最小值,最大值,绝对值
mat3 = mat1.cwise().min(mat2);
mat3 = mat1.cwise().max(mat2);
mat3 = mat1.cwise().abs();
mat3 = mat1.cwise().abs2();
- 1
- 2
- 3
- 4
各种乘法运算
- 矩阵乘法:
m1*m2
- 逐元素乘法:
mat1.cwise()*mat2
- 点积:
scalar = vec1.dot(vec2);
- 外积:
mat = vec1 * vec2.transpose();
- 交叉积:
#include <Eigen/Geometry> vec3 = vec1.cross(vec2);
- 矩阵乘法:
逐元素操作示例:
/** 参考链接:http://eigen.tuxfamily.org/dox-2.0/TutorialCore.html#TutorialCoreGettingStarted
*/#include <iostream>
#include <vector>
#include <Eigen/Eigen>using namespace Eigen;
using namespace std; int main(int, char *[])
{Matrix3f x, y;x << 5,3,1,2,-7,8,9,-4,6;y << 5,3,1,2,-7,8,9,4,7;cout << x << endl << endl;cout << x.cwiseAbs() << endl << endl;//绝对值cout << x.cwiseAbs2() << endl << endl; //平方cout << x.cwiseEqual(y) << endl << endl; //是否相等cout << x.cwiseMax(y) << endl << endl; //逐元素最大值cout << x.cwiseMin(y) << endl << endl;cout << x.cwiseInverse() << endl << endl; //倒数cout << x.cwiseNotEqual(y) << endl << endl; //不相等cout << x.cwiseProduct(y) << endl << endl; //逐元素乘法cout << x.cwiseQuotient(y) << endl << endl; //除法cout << x.cwiseSqrt() << endl << endl; //return 0;
}
- 1
- 2
- 3
- 4
- 5
- 6
- 7
- 8
- 9
- 10
- 11
- 12
- 13
- 14
- 15
- 16
- 17
- 18
- 19
- 20
- 21
- 22
- 23
- 24
- 25
- 26
- 27
- 28
- 29
Reductions
- Eigen提供了一些reduction方法: minCoeff() , maxCoeff() , sum() , trace() , norm() , squaredNorm() , all() , 和 any()。
- 上述这些方法都可以逐列或逐行的执行。如下所示:
/** 参考链接:http://eigen.tuxfamily.org/dox-2.0/TutorialCore.html#TutorialCoreGettingStarted
*/#include <iostream>
#include <vector>
#include <Eigen/Core>using namespace Eigen;
using namespace std; int main(int, char *[])
{Matrix3f x;x << 5,3,1,2,7,8,9,4,6;cout << x.minCoeff() << endl;cout << x.colwise().minCoeff() << endl;cout << x.rowwise().minCoeff() << endl;return 0;
}
- 1
- 2
- 3
- 4
- 5
- 6
- 7
- 8
- 9
- 10
- 11
- 12
- 13
- 14
- 15
- 16
- 17
- 18
- 19
- 20
- 21
- maxCoeff()和minCoeff()函数可以通过设置可选参数,返回最大/小值的位置:maxCoeff(int* i, int* j) , minCoeff(int* i, int* j) 。
- all() 和 any()在使用逐元素操作时,非常有用。
Eigen学习笔记1相关推荐
- Eigen学习笔记13:固定大小的可矢量化Eigen对象
对于固定大小的可矢量化Eigen对象的解释! Executive Summary 如果Eigen对象具有固定大小并且该大小是16个字节的倍数,则称为"固定大小向量化". 示例包括: ...
- 【Eigen学习笔记】-- Umeyama
Umeyama算法 前言 一.Umeyama目标 二.Umeyama原理介绍 三.Umeyama使用方法 前言 一.Umeyama目标 在研究pcl中的icp算法时,看到在求解对应点关系矩阵时,用的是 ...
- Eigen 学习笔记
1. 初始化 //外部指针初始化 double _mu0[12]={...}; double _sigma_inv[9] = ...; kernels[0].mu = Vector3d(_mu0); ...
- 视觉SLAM十四讲学习笔记-第三讲-相似、仿射、射影变换和eigen程序、可视化演示
专栏系列文章如下: 视觉SLAM十四讲学习笔记-第一讲_goldqiu的博客-CSDN博客 视觉SLAM十四讲学习笔记-第二讲-初识SLAM_goldqiu的博客-CSDN博客 视觉SLAM十四讲学习 ...
- 视觉SLAM十四讲学习笔记-第三讲-旋转矩阵和Eigen库
专栏系列文章如下: 视觉SLAM十四讲学习笔记-第一讲_goldqiu的博客-CSDN博客 视觉SLAM十四讲学习笔记-第二讲-初识SLAM_goldqiu的博客-CSDN博客 视觉SLAM十四讲学习 ...
- Eigen库学习笔记(四)Eigen用于三维张量
Eigen库学习笔记(四)Eigen用于三维张量 1.示例: 2.3维张量 3.固定大小矩阵TensorFixedSize 4.常用函数API 5.矩阵乘法与广播机制 Tensor的矩阵乘法操作 Te ...
- Eigen库学习笔记(五)张量计算
Eigen库学习笔记(五)张量计算 1.规约操作 2.最值与索引 3.按索引取值 Array of indices 4.类似 where的功能,生成mask 5.reshape 改变形状元素个数不变 ...
- Eigen库学习笔记(十三)Eigen实现softmax
Eigen库学习笔记(十三)Eigen实现softmax 1.pytorch中的softmax 2.Eigen实现softmax 1.pytorch中的softmax 示例: import torch ...
- SVO学习笔记(二)
SVO学习笔记(二) 这篇文章 稀疏图像对齐 地图点投影(地图与当前帧间的关系) reprojectMap reprojectPoint reprojectCell 特征点对齐中的非线性优化 结尾 这 ...
- 【Jetson Nano学习笔记】2. ORB-SLAM3及ZED 2i驱动安装
目录 ZED 2i驱动安装 安装驱动 自测 ROS测试 zed2i.launch rostopic list rosnode list display_zed2i.launch zed_rtabmap ...
最新文章
- 阿里AI labs发布两大天猫精灵新品,将与平头哥共同定制智能语音芯片
- 一文回顾深度学习发展史上最重要经典模型
- MVC通过ViewBag动态生成Html输出到View
- 2017-2018-1 20155209 实验三 实时系统
- 微软确认5月2日召开新品发布会 8天后就是Build 2017大会
- 推荐两本移动开发挺火的书
- python js 性能_Python Json使用,Json库性能测试
- php post请求超时,php用curl提交post数据,本地测试服务器OK,线上超时,需要如何排除问题?...
- 适合初学者的大数据学习路线
- 傅里叶变换1 ~ 离散时间傅里叶变换(DTFT)
- 技术至简-8:调制解调到底是什么样的数学运算?---从时域和频域两个角度看调制解调的本质
- scipy短时傅里叶分析STFT
- 成功解决Collecting package metadata (current_repodata.json): failedCondaHTTPError: HTTP 000 CONNECTION
- CentOS从零搭建SRS直播服务器
- pdo.需要mysql版本_php PDO mysql
- 做移动网站还是移动应用程序?
- spark的UI界面及调优
- virtualbox安装时发生致命错误的解决方法
- xcode报错:multiple commands produce Code Signing “No account for team” failed to register bundle
- 1.2基本IO口控制
热门文章
- 管理感悟:掌握写文档的技能
- 如何查看cudnn当前版本_当前版本的花木兰,如何成为边路战神?
- 华为怎么授权位置服务器,华为手机设置位置服务器
- linux中如何实时同步时间,linux实现时间同步有哪几种方法
- c++ 11 新特性讲解大全
- matlab导弹追踪问题垂直逃逸,综合程序设计 导弹追踪问题 (matlab)
- 如何用python写程序设置当前打印机为默认打印机,从Python打印到标准打印机?
- 常见报错_【办公】文档打印常见报错,怎么办?
- CentOS7连接无线网络
- Category为什么会覆盖原来类中的方法?