找到
22
篇与
刘纪彤
相关的结果
- 第 3 页
-
Joe再续前缘版对接LBS展示IP属地(本站同款) 为深度贯彻落实中央网信办《互联网用户账号信息管理规定》,开放查询IP操作,特将办法如下: 本文来源: https://blog.yanqingshan.com/130.html 上次偶然逛 CSDN 看到腾讯的 LBS 服务支持 IP 定位,而且还支持 IPv6 地址定位,这个是其他 LBS 供应商所不支持的 (百度地图、高德地图),所有腾讯 LBS 服务还算良心。我们一步一步对接主题吧,今天先来申请应用 AK。 注册账号 打开腾讯位置服务官网,点击登录,直接使用 QQ 登录或微信登录即可,如果单独注册需要输入手机号之类,麻烦的事情,但是使用 QQ 登录 / 微信登录后也需要校验一下手机号,但是个人信息不用填写太多。 腾讯位置服务官网 使用 QQ 登录 / 微信登录后会提示注册或绑定账号,这个时候我们直接选择注册账户即可。 绑定新用户 你看这样简单吧,输入手机号和邮箱就 OK, 不用填写过多信息,下次可以直接使用 QQ 或者微信登录即可。 注册账户 创建应用 这时候我们选择 WebService API 服务即可,选择后有三种方案,域名白名单、授权 IP、签名校验,一般我们会部署在服务器上,所以可以选择授权 IP,这样方便一些;域名白名单和签名校验限制有些多,且我们这次对接主题也是以授权 IP 为主。 保存后我们就能拿到一个 Key,这里我们简称 AK,下面开始对接 Joe 主题展示博友访客 IP 属地信息。 注意AK要给其分配调用次数 添加主题调用方法 2022.05.25:为了个人隐私,以下代码已去除城市和区县信息,仅显示国家和省 核心方法代码位置:Joe/core/function.php 在末尾添加以下代码 /* 腾讯Lbs IP定位服务 */ function curl_tencentlbs_ip($ip) { //应用Key也就是上面所说的AK,修改成自己的Key即可 $key = '5E4BZ-NYCKQ-2C25A-2E4PB-7CXJH-AMBKN'; $url = 'https://apis.map.qq.com/ws/location/v1/ip?ip='.$ip.'&key='.$key; $ch = curl_init(); curl_setopt($ch, CURLOPT_URL, $url); curl_setopt($ch, CURLOPT_BINARYTRANSFER, 1); curl_setopt($ch, CURLOPT_RETURNTRANSFER, 1); curl_setopt($ch, CURLOPT_AUTOREFERER, 1); curl_setopt($ch, CURLOPT_FOLLOWLOCATION, 1); curl_setopt($ch, CURLOPT_HTTPGET, true); curl_setopt($ch, CURLOPT_REFERER, $url); curl_setopt($ch, CURLOPT_SSL_VERIFYPEER, false); curl_setopt($ch, CURLOPT_SSL_VERIFYHOST, false); curl_setopt($ch, CURLOPT_USERAGENT, 'Mozilla/5.0 (Windows NT 6.1; Win64; x64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/71.0.3578.98 Safari/537.36'); $content = curl_exec($ch); curl_close($ch); if($content) { $json = json_decode($content,true); if($json['status'] == 0 ) { $resjson = $json['result']['ad_info']; if($resjson['province']=='北京市'||$resjson['province']=='天津市'||$resjson['province']=='上海市'||$resjson['province']=='重庆市') { echo $resjson['nation'].$resjson['city']; } echo $resjson['nation'].$resjson['province'].$resjson['city'].$resjson['district']; } } else echo '未知IP地址'; echo ''; }上面调用接口后,处理以下国内的直辖市,这样就不会显示成北京市北京市了。 修改主题评论相关代码 评论代码位置:/comment.php 需要修改的位置大概在末尾最后一个方法,位置 112 行。 也可以在需要显示评论信息的位置插入下方嵌入点代码即可,我是把 IP 信息放在 agent 旁边了,这样不是特别显眼。 <?php echo curl_tencentlbs_ip($comments->ip); ?> 以下示例代码从 96 行到尾部 <?php function threadedComments($comments, $options) { ?> <li class="comment-list__item"> <div class="comment-list__item-contain" id="<?php $comments->theId(); ?>"> <div class="term"> <img width="48" height="48" class="avatar lazyload" src="<?php joe\getAvatarLazyload() ?>" data-src="<?php joe\getAvatarByMail($comments->mail); ?>" alt="头像" /> <div class="content"> <div class="user"> <span class="author"><?php $comments->author(); ?></span> <?php if ($comments->authorId === $comments->ownerId) : ?> <i class="owner">作者</i> <?php endif; ?> <?php if ($comments->status === "waiting") : ?> <em class="waiting">(评论审核中...)</em> <?php endif; ?> <div class="agent"> <?php joe\curl_tencentlbs_ip($comments->ip); ?> · <?php joe\getAgentOS($comments->agent); ?> · <?php joe\getAgentBrowser($comments->agent); ?></div> </div> <div class="substance"> <?php joe\getParentReply($comments->parent) ?> <?php echo _parseCommentReply($comments->content); ?> </div> <div class="handle"> <time class="date" datetime="<?php $comments->date('Y-m-d'); ?>"><?php $comments->date('Y-m-d'); ?></time> <span class="reply joe_comment__reply" data-id="<?php $comments->theId(); ?>" data-coid="<?php $comments->coid(); ?>"> <i class="icon fa fa-pencil" aria-hidden="true"></i>回复 </span> </div> </div> </div> </div> <?php if ($comments->children) : ?> <div class="comment-list__item-children"> <?php $comments->threadedComments($options); ?> </div> <?php endif; ?> </li> <?php } ?>代码经过二次改造,适配Joe再续前缘版 其他博客主题,应该也可以适用。
-
运算符重载 运算符重载 运算符重载的概念 运算符重载是指允许用户自定义类型的对象使用内置的运算符,或者允许用户自定义的运算符作用于内置类型的对象。运算符重载是通过函数重载来实现的。 不能重载的运算符: .和.*运算符 ::运算符 ?:运算符 sizeof运算符 typeid运算符 运算符重载的基本语法 运算符重载的基本语法如下: 返回类型 operator 运算符(参数列表) { //函数体 }加法运算符重载 //运算符重载-1 #include<iostream> using namespace std; class example { public: int a; int b; example(int x,int y):a(x),b(y) { cout<<"初始化赋值操作"<<endl; } example operator+ (example x) { cout<<"重载操作"<<endl; example temp(a+x.a,b+x.b); return temp; } }; int main() { example e1(1,2),e2(3,4); e1=e1+e1+e2+e2; example e3 = e1+e2; cout<<"e3的值"; cout<<e3.a<<","<<e3.b<<endl; cout<<"e1的值"; cout<<e1.a<<","<<e1.b<<endl; return 0; }运行结果: 初始化赋值操作 初始化赋值操作 重载操作 初始化赋值操作 重载操作 初始化赋值操作 重载操作 初始化赋值操作 重载操作 初始化赋值操作 e3的值11,16 e1的值8,12不但可以成员函数实现 + 号运算符重载,也可以通过全局函数实现 + 号运算符重载。 //运算符重载-2 #include<iostream> using namespace std; class example { public: int a; int b; example(int x,int y):a(x),b(y) { cout<<"初始化赋值操作"<<endl; } }; example operator+ (example x,example y) { cout<<"重载操作"<<endl; example temp(x.a+y.a,x.b+y.b); return temp; } int main() { example e1(1,2),e2(3,4); e1=e1+e1+e2+e2; example e3 = e1+e2; cout<<"e3的值"; cout<<e3.a<<","<<e3.b<<endl; cout<<"e1的值"; cout<<e1.a<<","<<e1.b<<endl; return 0; }初始化赋值操作 初始化赋值操作 重载操作 初始化赋值操作 重载操作 初始化赋值操作 重载操作 初始化赋值操作 重载操作 初始化赋值操作 e3的值11,16 e1的值8,12左移(<<)运算符重载 //运算符重载-3 #include<iostream> using namespace std; class example { public: int a; int b; example(int x,int y):a(x),b(y) { cout<<"初始化赋值操作"<<endl; } //如果需要访问私有成员,需要将重载运算符函数声明为友元函数 friend ostream& operator<< (ostream &out,example x); }; ostream& operator<< (ostream &out,example x) { cout<<"重载<<运算符"<<endl; out<<x.a<<","<<x.b<<endl; return out; } int main() { example e1(1,2),e2(3,4); cout<<e1<<e2; return 0; }输出结果: 初始化赋值操作 初始化赋值操作 重载<<运算符 1,2 重载<<运算符 3,4自增运算符重载 //运算符重载-4(前置++) #include<iostream> using namespace std; class example { public: int a; int b; example(int x,int y):a(x),b(y) { cout<<"初始化赋值操作"<<endl; } example operator++ () { cout<<"重载++运算符"<<endl; a++; b++; return *this; } }; ostream& operator<<(ostream& out, example ex1) { out << ex1.a<<ex1.b; return out; } int main() { example e1(1,2),e2(3,4); ++e1; ++e2; cout<<e1<<","<<e2; return 0; }输出结果: 初始化赋值操作 初始化赋值操作 重载++运算符 重载++运算符 23,45//运算符重载-5(后置++) #include<iostream> using namespace std; class example { public: int a; int b; example(int x,int y):a(x),b(y) { cout<<"初始化赋值操作"<<endl; } example operator++ (int) { cout<<"重载++运算符"<<endl; example temp(a,b); a++; b++; return temp; } }; ostream& operator<<(ostream& out, example ex1) { out << ex1.a<<ex1.b; return out; } int main() { example e1(1,2),e2(3,4); e1++; e2++; cout<<e1<<e2<<endl; cout<<e1++<<endl; cout<<e1; return 0; }输出结果: 初始化赋值操作 初始化赋值操作 重载++运算符 初始化赋值操作 重载++运算符 初始化赋值操作 2345 重载++运算符 初始化赋值操作 23 34所以说:前置递增返回引用,后置递增返回值。 赋值运算符重载 //运算符重载-6 #include<iostream> using namespace std; class example { public: int a; int b; example(int x,int y):a(x),b(y) { cout<<"初始化赋值操作"<<endl; } example operator= (example x) { cout<<"重载赋值运算符"<<endl; a=x.a; b=x.b; return *this; } }; ostream& operator<<(ostream& out, example ex1) { out << ex1.a<<ex1.b; return out; } int main() { example e1(1,2),e2(3,4); e1=e2; cout<<e1<<e2<<endl; return 0; }输出结果: 初始化赋值操作 初始化赋值操作 重载赋值运算符 3434关系运算符重载 //运算符重载-7 #include<iostream> using namespace std; class example { public: int a; int b; example(int x,int y):a(x),b(y) { cout<<"初始化赋值操作"<<endl; } bool operator== (example x) { cout<<"重载==运算符"<<endl; if(a==x.a&&b==x.b) return true; else return false; } bool operator!= (example x) { cout<<"重载!=运算符"<<endl; if(a!=x.a||b!=x.b) return true; else return false; } bool operator> (example x) { cout<<"重载>运算符"<<endl; if(a>x.a&&b>x.b) return true; else return false; } bool operator< (example x) { cout<<"重载<运算符"<<endl; if(a<x.a&&b<x.b) return true; else return false; } }; ostream& operator<<(ostream& out, example ex1) { out << ex1.a<<ex1.b; return out; } int main() { example e1(1,2),e2(3,4); if(e1==e2) cout<<"e1==e2"<<endl; else cout<<"e1!=e2"<<endl; if(e1!=e2) cout<<"e1!=e2"<<endl; else cout<<"e1==e2"<<endl; if(e1>e2) cout<<"e1>e2"<<endl; else cout<<"e1<=e2"<<endl; if(e1<e2) cout<<"e1<e2"<<endl; else cout<<"e1>=e2"<<endl; return 0; }输出结果: 初始化赋值操作 初始化赋值操作 重载==运算符 e1!=e2 重载!=运算符 e1!=e2 重载>运算符 e1<=e2 重载<运算符 e1<e2函数调用运算符重载 //运算符重载-8 #include<iostream> using namespace std; class example { public: int a; int b; example(int x,int y):a(x),b(y) { cout<<"初始化赋值操作"<<endl; } example operator() (example x) { cout<<"重载()运算符"<<endl; a=x.a; b=x.b; return *this; } }; ostream& operator<<(ostream& out, example ex1) { out << ex1.a<<ex1.b; return out; } int main() { example e1(1,2),e2(3,4); e1(e2); cout<<e1<<","<<e2<<endl; return 0; }输出结果: 初始化赋值操作 初始化赋值操作 重载()运算符 34,34其他运算符略 重载运算符的注意事项 重载运算符不能改变运算符的优先级和结合性 重载运算符不能创建新的运算符 重载运算符不能改变运算符的操作数个数 重载运算符不能改变运算符的操作数类型 重载运算符不能改变运算符的操作数的含义 重载运算符的应用 重载运算符可以使得类的对象像内置类型一样使用,如:cin、cout、+、-、、/、==、!=、>、<、++、--、=、()、[]、&、|、~、!、<<、>>、+=、-=、=、/=、<<=、>>=、&=、^=、|=、,、->、->*、new、delete、new[]、delete[]等;
-
引用 引用 语法结构数据类型 &别名=原名 注意事项: 引用必须在定义的时候必须要初始化。 引用在初始化后不允许更改引用。 引用做函数参数,进行引用传递:其和按地址传递是一样的。因为引用传递可以看作给变量取别名的过程。 引用也是可以作为返回值存在的,但是返回局部变量的引用会因为局部变量存在于战区内导致被系统释放掉。但是函数是可以作左值出现的 例如: //返回静态变量引用 int& test02() { static int a = 20; return a; } //如果函数做左值,那么必须返回引用 int& ref2 = test02(); cout << "ref2 = " << ref2 << endl; cout << "ref2 = " << ref2 << endl; test02() = 1000; cout << "ref2 = " << ref2 << endl; cout << "ref2 = " << ref2 << endl;本质:引用的本质在c++内部实现是一个指针常量. 常量引用 作用:常量引用主要用来修饰形参,防止误操作 在函数形参列表中,可以加==const修饰形参==,防止形参改变实参 示例: //引用使用的场景,通常用来修饰形参 void showValue(const int& v) { //v += 10; cout << v << endl; } int main() { //int& ref = 10; 引用本身需要一个合法的内存空间,因此这行错误 //加入const就可以了,编译器优化代码,int temp = 10; const int& ref = temp; const int& ref = 10; //ref = 100; //加入const后不可以修改变 cout << ref << endl; //函数中利用常量引用防止误操作修改实参 int a = 10; showValue(a); system("pause"); return 0; }
-
文件 文件 C++可以将进行文件操作。C++使用文件的时候需要包含#include<fstream>这个库。 文件类型分为两种,一种是二进制文件,一种是文本文件。他们分别对应两大种存储方式。一个我们可以通过类似于记事本方式打开,一个一般情况之下我们看不太懂。 文本文件 包含头文件 #include<fstream> 创建流对象 ofstream ofs; 打开文件 ofs.open("文件路径",打开方式); 写数据 ofs << "写入的数据"; 关闭文件 ofs.close(); 文件打开方式: 打开方式解释ios::in为读文件而打开文件ios::out为写文件而打开文件ios::ate初始位置:文件尾ios::app追加方式写文件ios::trunc如果文件存在先删除,再创建ios::binary二进制方式注意: 文件打开方式可以配合使用,利用|操作符 例如:用二进制方式写文件 ios::binary | ios:: out for example: //文件-1(文本文件写入) #include<iostream> #include<fstream> using namespace std; int main() { ofstream ofs1; ofs1.open("1.txt",ios::out); ofs1<<"我是你的爸爸"<<endl; ofs1<<"66666"<<endl; ofs1.close(); }读文件其实类似,只需要把输出流fstream改为输入流ifstream就可以了,头文件不变。看代码 //文件-2(文本文件读取) #include<iostream> #include<fstream> using namespace std; int main() { ifstream ifs1; ifs1.open("1.txt",ios::in); if (!ifs1.is_open()) { cout << "文件打开失败" << endl; return 0; } //第一种方式 //char buf[1024] = { 0 }; //while (ifs >> buf) //{ // cout << buf << endl; //} //第二种 //char buf[1024] = { 0 }; //while (ifs1.getline(buf,sizeof(buf))) //{ // cout << buf << endl; //} //第三种 //string buf; //while (getline(ifs1, buf)) //{ // cout << buf << endl; //} char c; while ((c = ifs1.get()) != EOF)//EOF:end of file { cout << c; } ifs1.close(); }二进制文件 二进制文件的读取和写入,可以用以下两个函数原型: 写入:ostream& write(const char * buffer,int len);参数解释:字符指针buffer指向内存中一段存储空间。len是读写的字节数 读取:istream& read(char *buffer,int len);参数解释:字符指针buffer指向内存中一段存储空间。len是读写的字节数 同时加上|操作符,ios::binary以二进制打开就可以了 for example
-
内存分区 内存分区 C++内存分区模型 C++的程序在执行过程中,大体会划分为四个区域,也就是:代码区,全局区,堆区,栈区。 在程序进行了编译之后C++的编译器会在编译之后,生成一个.exe的可执行文件,这个可执行文件在被执行之前,会有两个区域。 代码区: 存放 CPU 执行的机器指令 代码区是共享的,共享的目的是对于频繁被执行的程序,只需要在内存中有一份代码即可 代码区是只读的,使其只读的原因是防止程序意外地修改了它的指令 全局区: 全局变量和静态变量存放在此. 全局区还包含了常量区, 字符串常量和其他常量也存放在此. ==该区域的数据在程序结束后由操作系统释放==. 可以利用下面这行代码理解一下: //全局变量 int g_a = 10; int g_b = 10; //全局常量 const int c_g_a = 10; const int c_g_b = 10; int main() { //局部变量 int a = 10; int b = 10; //打印地址 cout << "局部变量a地址为: " << (int)&a << endl; cout << "局部变量b地址为: " << (int)&b << endl; cout << "全局变量g_a地址为: " << (int)&g_a << endl; cout << "全局变量g_b地址为: " << (int)&g_b << endl; //静态变量 static int s_a = 10; static int s_b = 10; cout << "静态变量s_a地址为: " << (int)&s_a << endl; cout << "静态变量s_b地址为: " << (int)&s_b << endl; cout << "字符串常量地址为: " << (int)&"hello world" << endl; cout << "字符串常量地址为: " << (int)&"hello world1" << endl; cout << "全局常量c_g_a地址为: " << (int)&c_g_a << endl; cout << "全局常量c_g_b地址为: " << (int)&c_g_b << endl; const int c_l_a = 10; const int c_l_b = 10; cout << "局部常量c_l_a地址为: " << (int)&c_l_a << endl; cout << "局部常量c_l_b地址为: " << (int)&c_l_b << endl; system("pause"); return 0; }局部变量是不会存放在全局区中,全局区中又会包含常量,全局常量和字符串常量。无论如何局部的常量或者变量都不会存放在全局区中。 当然在程序执行后,又会有两个区域。 栈区: 由编译器自动分配释放, 存放函数的参数值,局部变量等 注意事项:不要返回局部变量的地址,栈区开辟的数据由编译器自动释放 堆区: 由程序员分配释放,若程序员不释放,程序结束时由操作系统回收 在C++中主要利用new在堆区开辟内存 new操作符 基本语法:new 数据类型 new返回的是该数据对性的类型的指针。堆区的数据由代码的编写者管理开辟,管理释放,释放需要用到delete。 释放数组的时候要加一个[] 举例: new int a[10];//堆区创建一个数组 new int a(10);//堆区创建一个整型值为10 delete p;//释放 delete[] p;//释放数组