笑 · 二十年

笑 ·  二十年

土坑里头打滚
瞭高山上怒号
长风之中奔跑
知否天几许高

注:生于黄土高原的我,早已习惯自由的在山间奔走。能接近天空的跑道也别有一番风味。

——————————脩于公元贰零壹玖年六月二日晨

 

【mysql技巧】linux安装mysql后重置密码 ,快速解决 ERROR 1045 (28000)

一般情况下linux下mysql安装完成后会自动生成一个密码,我们可以使用cat命令在/var/log/msqld.log下查看,但是,有一次却发现这个密码神奇的不可用,所以我们得想个办法来跳过验证了:

0.环境说明:

①mysql 5.7.25

②centos 7.4

③拥有root权限,忘记mysql root密码或者无法登陆的情况

1.跳过mysql密码验证:

whereis my

 

找到my目录后编辑my.cnf 在[mysqld]后面任意一行添加“skip-grant-tables”

vi /etc/my.cnf
skip-grant-tables 

2.重启mysql

service mysqld restart
mysql

现在mysql可以直接登录了

3.修改mysql密码:

UPDATE mysql.user SET authentication_string = PASSWORD('Root123A'), password_expired = 'N' WHERE User = 'root' AND Host = 'localhost';
flush privileges;
quit;

这样就将mysql root用户的默认密码修改成了Root123A

如果是5.7以前的用户可以尝试使用:

update msyql.user set password=password("Root123A") where user="root";
flush privileges;
quit;

4.然后编辑my.cnf 在[mysqld]去掉刚刚添加的“skip-grant-tables”,重启mysql

sevice mysqld restart

centos 7.4 VMWare 虚机固定IP设定

在使用VM安装LINUX虚拟机后,为了方便使用,常需要使用一些SSH工具登录,这里用固定IP就会方便很多:

0.环境说明:

①本机配置win10X64 8GBRAM

②VM 14.0.0

③虚机系统 CENTOS 7.4 X64

1.在编辑→虚拟网络编辑器中选中 Vmnat8 ,点击底部的更改设置(需要管理员权限),填写子网IP,点击DHCP配置,配置起始和结束IP地址:

2.在网络中心,选择更改适配器设置,找到vmnat8对应的适配器:

右键点击属性,双击internat协议4,按照VM的配置更改,并配置网关、和DNS服务:

3.下面在虚拟机内的操作:

①修改配置文件ifcfg

cd /etc/sysconfig/network-scripts/
ls
vi ifcfg-ens33

②按照如下配置ifcfg文件:

BOOTPROTO=static      #开机协议,有dhcp及static;
ONBOOT=yes        #设置为开机启动;
DNS1 = 8.8.8.8
DNS2=114.114.114.114   
IPADDR=192.168.5.20    #你想要设置的固定IP,在第一部的起始地址和结束地址间选一个; 
NETMASK=255.255.255.0   #子网掩码,保持一
GATEWAY=192.168.5.16   #网关,与2配置的网关保持一致

③重启网络服务,并查看当前IP,你发现已经改成了所需的静态IP地址:

service network restart
ifconfig

这时我们就可以使用Xshell、SecureCRT等SSH工具轻松的访问虚拟机了

【mysql技巧】如何在存储过程(produce)中使用数组

在工作中难免会遇到需要使用一个数组的时候,但是mysql却没有数组这种类型,所以我们需要想个办法来处理它。下面是一个简单的演示:

CREATE procedure proc_update_use_arr(myID BIGINT(10))
BEGIN
	DECLARE arr VARCHAR(100);
        DECLARE arr_flag INT;
        DECLARE index_a INT;
	DECLARE num INT;

	SET arr  = '1,2,3,4,5'; 
	SET arr_flag = 1;
	SET index_a = 1 ;
	WHILE arr_flag <= 5 DO
		SET num = substring_index(substring_index(arr,',',index_a),',',-1);
		SET index_a = index_a + 1 ;
		SET arr_flag = arr_flag + 1;
		INSERT INTO b(id,num) VALUES(arr_flag,num);
	END WHILE;
    COMMIT;
END$$

上面的功能就是把一个数组arr中的五个数字分五条记录插入,其中我们使用一个长varchar类型 arr来保存数组,再使用分隔字符串的方法substring_index来分解字符串为数字。

天空洒雨会长风

天空洒雨会长风

微雨是露空迷眼
直指剑河莫知倦
未见长空多疑路
何须再会梦长风

注:早起雨淅沥,看着渐小的天色还是忍不住要出去跑一下,小雨打面,但是对于经常在风雨里的跑者又算得什么呢?花花绿绿的红绿灯就像魔都的霓虹,让我分不清方向,规划的路径早已没有用了。就让我沿着剑河路跑到底,不知道是否能离天空更近一点?忘记了跑的疲惫,雨水淋湿全身,湿了双眼,离目的地长风公园越来越远。拖着一身的湿衣服迷失了方向,我们下次再见。

——————————脩于公元二零一九年五月二十六日

【python你不知道的知识】如何实现python中的字符(注意不是字符串)

工程中遇到了C++读python字符的场景,但是因为python没有字符的概念,只有常量字符串,几乎试过了所有的方法,单个字符,或者是ascii码都不行。最后终于找到一种可行的方案,那就是使用python中的byte。

关于两者的异同,想要追根究底的同学可以看下这篇文章:https://www.cnblogs.com/chownjy/p/6625299.html

如果比较急,不想浪费时间,那么直接开看使用方法吧:

char = bytes('s',encoding='utf-8')

这样我们就实现了byte型的字符’s’,便可以将其当做C++等语言的char型进行字符的传递了。

【mysql技巧】mysql中查询一个字段属于什么表什么数据库

知道一个字段,却不知道它所在的表和数据库可用这个方法:

select table_schema,table_name from information_schema.columns where 
column_name = '字段名'

 

亦冥亦魔

吾乃修魔
无情无泪
跟风作对
与天挣命
下得九幽
上可三清
怒断黄泉
笑斩万邪
踏破苍天
卧劈神佛

癫瑕代替了我那不流在南山路上,也不留在雷锋塔下的泪。希望我永远都是你心内的阳光!

风中冥

 

风中冥

老僧呆闺中
心游百里槐
闲庭坐风里
盘膝九曲愁

注:虽每日与天地挣命,但也期有两三闲时,可以悠然南山下。

——————————脩于公元二零一九年三月二十五日

C++ 11 C++14 C++17新功能

一、C++11的新功能:

1.使用nullptr代表空指针:

主要是为了解决C++中NULL带来的二义性问题(因为NULL的值实际是0)

2.自动类型推断关键字auto和decltype()得到类型

①使用auto进行自动类型推导:

使用auto进行类型的自动推导可以大大简化编程工作;auto是在编译期执行,所以不会影响程序运行速度;由于C++编译的特性是从右向左推断类型,所以不会影响编译速度。

//auto的使用示例
//auto tmp; // 错误,auto是通过初始化表达式进行类型推导,如果没有初始化表达式,就无法确定tmp的类型  
auto tmp = 1;//等价于int tmp = 1;  
auto tmp = 1.0; //等价于 double tmp = 1.0;
auto tmp = "Hello World";  //等价于 char *tmp = "Hello World";
auto tmp  = 'A';  //等价于 char tmp  = 'A';
auto func = less<int>();  
vector<int> arr;  
auto it = arr.begin();  //等价于vector<int>::iterator it   = arr.begin(); 
auto p = new foo(); // 对自定义类型进行类型推导

另外auto可以应用于模版:

//auto应用于模版
        //1.不使用auto
	template <class Student, class Teacher>
	void levelUp(const Teacher& th)
	{
		Student * addSalary = th.levelPlus();
		// do somthing with addSalary
	}

	//2.使用auto
	template <class Teacher>
	void levelUp(const Teacher& th)
	{
		auto * addSalary = th.levelPlus();
		// do somthing with addSalary
	}

②使用decltype()得到类型:

//使用decltype()得到变量类型
int x = 3;  
decltype(x) y = x; 

template <class Teacher>
void levelUp(const Teacher& th)->decltype(th.levelPlus();)
{
	auto * addSalary = th.levelPlus();
	// do somthing with addSalary
}

3.使用默认构造函数和删除(default:A()=default; A()=delete;)

为了避免手动编写空默认构造函数,C++11引入了显示默认构造函数的概念,从而仅仅需在类的定义中编写空默认构造函数而不须要在实现文件里提供事实上现,相同的,C++还支持显式删除构造函数的概念。

//默认构造函数和删除
启用默认构造函数A()=default;
删除默认构造函数A()=delete;

4.匿名函数lambda表达式

lambda表达式类似Javascript中的闭包,它可以用于创建并定义匿名的函数对象,以简化编程工作。

Lambda语法:[函数对象参数](操作符重载函数参数)->返回值类型{函数体}

//lambda表达式
vector<int> arr{5, 4, 3, 2, 1};  
int a = 2, b = 1;  


for_each(arr.begin(), arr.end(), [b](int &x){cout<<(x + b)<<endl;});
//b就是指函数可以得到在Lambda表达式外的全局变量
for_each(arr.begin(), arr.end(), [=](int &x){x *= (a + b);});    
 //在[]中传入=的话,即是可以取得所有的外部变量
for_each(arr.begin(), arr.end(), [=](int &x)->int{return x * (a + b);});

//①[]内的参数指的是Lambda表达式可以取得的全局变量
//②()内的参数是每次调用函数时传入的参数
//③->后接的是Lambda表达式返回值的类型

5.智能指针:

shared_ptr、unique_ptr、weak_ptr、auto_ptr,主要为了解决内存泄露问题

详见:https://x.wolfmark.org/x-select_2018-09-10_481.html

(中第23②)

6.右值引用T&&与移动构造函数:

a.函数参数为什么要使用常量引用:

因为函数在参数传递(实参—>形参)的时候会有两种形式:值传递和引用传递。若使用值传递,在遇到大的对象作为参数时会耗费大量时间与内存空间。采用引用就不会有这个拷贝过程。所以使用引用。而我们一般又希望作为参数的引用不要改变原来的对象的内容,所以采用常量引用(const &)。

 b.拷贝构造函数为什么使用常量引用:

拷贝构造函数,首先是一个函数,其次它的任务就是借用一个本类型的对象,拷贝创建一个新的对象。
所以有如下的过程:实参—>形参—>新创建的对象
其中,形参—>新创建的对象,是拷贝构造函数这个函数所赋予的功能(新创建的对象要和作为参数的对象内容相同但是拥有独立的内存空间)。
类的构造函数是没有返回值的,所以实参—>形参之后,还是需要一个形参—>拷贝初始化新对象的过程。

 c.移动构造函数为什么使用右值引用:

首先还是为了不拷贝大对象,所以使用引用。

但是由于引用对象是右值(如字面值或者临时对象),因为这类值本身就是用于临时存储,所以窃取其值不影响程序正确性。

所以这样我们如果确实需要一个单独的传入的参数也不需要拷贝了,就直接将这个传入的参数“据为己有”即可。

总结:移动构造函数就是实参—>形参,形参—>新创建的对象,这两个过程的拷贝都省了。

//(1)声明一个右值引用
int&& i = 42;
或者
class X
{
private:
int* data;
public:X():data(new int[1000000]){}~X(){delete [] data;}
X(const X& other):data(new int[1000000]){std::copy(other.data,other.data+1000000,data);}
//拷贝构造函数
X(X&& other):data(other.data){other.data=nullptr;}};
//移动构造函数

//(2)使用在拷贝构造函数
X x1;
X x2 = std::move(x1);
X x3 = static_cast<X&&>(x2);

//(3)使用在函数模板
//填入左值,推断为左值引用;填入右值,推断为普通无修饰类型。
foo(42);foo(3.14159);foo(std::string());
//填入右值,推断为普通无修饰类型情况
int i=42;foo(i);
//填入左值,推断为左值引用情况

7.初始化列表(更加优雅的初始化方法):

//初始化列表(更加优雅的初始化方法)

//引入C++11之前,只有数组能使用初始化列表,
//其他容器想要使用初始化列表,只能用以下方法:
int arr[3] = {1, 2, 3}  
vector<int> arr(arr, arr + 3); 

//C++11中,我们可以使用以下语法来进行替换:
int arr[3]{1, 2, 3};  
vector<int> arr{1, 2, 3};  
map<int, string>{{1, "a"}, {2, "b"}};  
string str{"Hello World"};

8.加长参数模板:

//加长参数模板

//在C语言中printf可以传入多个参数,在C++11中,
//可以用加长参数模板实现更简洁的Print

template<typename head, typename... tail>  
void Print(Head head, typename... tail) {  
    cout<< head <<endl;  
    Print(tail...);  
}

9.元组tuple:

//C++中的pair可以使用make_pair构造,构造一个包含两种不同类型的数据的容器
auto p = make_pair(1, "C++ 11"); 

//C++11中引入了变长参数模板(参见8),所以发明了新的数据类型:tuple
//tuple是一个N元组,可以传入1个, 2个甚至多个不同类型的数据
auto t1 = make_tuple(1, 2.0, "C++ 11");  
auto t2 = make_tuple(1, 2.0, "C++ 11", {1, 0, 2}); 

10.序列for循环:

//C++中for循环可以使用类似java的简化的for循环,
//可以用于遍历数组,容器,string以及由begin和end函数定义的序列
map<string, int> m{{"a", 1}, {"b", 2}, {"c", 3}};  
for (auto p : m){  
    cout<<p.first<<" : "<<p.second<<endl;  
}

c++11部分参考了文章:https://www.cnblogs.com/guxuanqing/p/6707824.html

二、C++14加入的新功能:

1.Lambda函数在C++11的基础上更加方便:

//C++11要求Lambda参数使用具体的类型声明
auto lambda = [](int x, int y) {return x + y;};

//C++14的泛型Lambda使编写如下语句成为可能:
auto lambda = [](auto x, auto y) {return x + y;};

//新标准中的std::move函数可用于捕获Lambda表达式中的变量,
//这是通过移动对象而非复制或引用对象实现的:
std::unique_ptr ptr(new int(10));
auto lambda = [value = std::move(ptr)] {return *value;};

2.constexpr

在C++11中,使用constexpr声明的函数可以在编译时执行,生成一个值,用在需要常量表达式的地方,比如作为初始化模板的整形参数。C++11的constexpr函数只能包含一个表达式,C++14放松了这些限制,支持诸如if 和switch等条件语句,支持循环,其中包括基于区间(range)的for 循环。

3.类型推导:

C++11仅支持Lambda函数的类型推导,C++14对其加以扩展,支持所有函数的返回类型推导:
auto DeducedReturnTypeFunction();
因为C++14是强类型语言,有些限制需要考虑:

①如果一个函数的实现中有多个返回语句,这些语句一定要推导出同样的类型。

②返回类型推导可以用在前向声明中,但是在使用它们之前,翻译单元中必须能够得到函数定义。

③返回类型推导可以用在递归函数中,但是递归调用必须以至少一个返回语句作为先导,以便编译器推导出返回类型。

C++14带来的另一个类型推导方面的改进是decltype(auto)语法,它支持使用与auto同样的机制计算给定表达式的类型。auto和 decltype在C++11中就已经出现了,但是它们在推导类型时使用了不同的机制,这可能会产生不同的结果。
C++14中的其他改变包括可以声明变量模板,支持使用0b或0B前缀来声明二进制字面常量。InfoQ已经介绍过C++14中可能破坏C++11程序的其他小型修改。
主流C++编译器对新语言特性的支持正在有条不紊地开发:Clang“完全实现了当前草案的所有内容”;GCC和Visual Studio也对C++14的新特性提供了一些支持。

三、C++17加入的新功能:

1.使 static_assert 的文本信息可选

2.删除 trigraphs

3.在模板参数中允许使用 typename(作为替代类)

4.来自 braced-init-list 的新规则用于自动推导

5.嵌套命名空间的定义,例如:使用 namespace X::Y { … } 代替 namespace X { namespace Y { … }}

6.允许命名空间和枚举器的属性

7.新的标准属性:[[fallthrough]], [[maybe_unused]] 和 [[nodiscard]]

8.UTF-8 字符文字

9.对所有非类型模板参数进行常量评估

10.Fold 表达式,用于可变的模板

11.A compile-time static if with the form if constexpr(expression)

12.结构化的绑定声明,现在允许 auto [a, b] = getTwoReturnValues();

13.if 和 switch 语句中的初始化器

14.在某些情况下,确保通过编译器进行 copy elision(Guaranteed copy elision by compilers in some cases)

15. 一些用于对齐内存分配的扩展

16.构造函数的模板推导,允许使用 std::pair(5.0, false) 代替std::pair<double,bool>(5.0, false)

17.内联变量,允许在头文件中定义变量

18.__has_include,允许由预处理程序指令检查头文件的可用性

19.__cplusplus 的值更改为 201703L