日常小程序测试大全
一、map中key为结构体
1、概要说明
(1) 当结构体作为map的key或者set中,需要重载 < 运算符
(2)stl中map和set的声明,二者比较像,底层都是用红黑树实现的
2、测试程序
#include "csdn_demo.h"
#include <map>
using namespace std;
struct Mapkey
{
int age;
string name;
/*自定义排序方式 -- 从小到大*/
bool operator < (const Mapkey& other) const
{
if (age != other.age)
{
return (age < other.age);
}
else
{
return (name < other.name);
}
}
};
int main()
{
/*=========================正常测试===========================*/
Mapkey mapkey1;
mapkey1.age = 18;
mapkey1.name = "ybhy1";
Mapkey mapkey2;
mapkey2.age = 18;
mapkey2.name = "ybhy2";
Mapkey mapkey3;
mapkey3.age = 20;
mapkey3.name = "ybhy3";
map<Mapkey, int > stMap;
/*=========================非常测试===========================*/
stMap.insert(pair<Mapkey, int >(mapkey1, 1));
stMap.insert(pair<Mapkey, int >(mapkey2, 2));
stMap.insert(pair<Mapkey, int >(mapkey3, 3));
Mapkey mapkey4;
mapkey4.age = 10;
mapkey4.name = "ybhy10";
stMap.insert(pair<Mapkey, int >(mapkey4, 4));
Mapkey mapkey5;
mapkey5.age = 8;
mapkey5.name = "ybhy10";
stMap.insert(pair<Mapkey, int >(mapkey5, 5));
/*输出*/
for (auto iter = stMap.begin(); iter != stMap.end(); iter++)
{
cout << "iter first age == " << iter->first.age << " iter first name == " << iter->first.name << " iter second == "<<iter->second << endl;
}
cout << "Hello CMake." << endl;
return 0;
}
3、 运行结果
iter first age == 8 iter first name == ybhy10 iter second == 5
iter first age == 10 iter first name == ybhy10 iter second == 4
iter first age == 18 iter first name == ybhy1 iter second == 1
iter first age == 18 iter first name == ybhy2 iter second == 2
iter first age == 20 iter first name == ybhy3 iter second == 3
二、C/C++中,*和++的优先级
1、概要说明
如下图所示:两者的++代表不同的含义,(1)中的++运算符,(2)中的++有关指针;
2、测试程序
int main()
{
int testArr[5] = { 1,2,3,4,5 };
int* cursor = &testArr[1];
printf("cursor1 = %x\n", cursor);/*输出 testArr[1] 地址*/
printf("*cursor++ = %d\n", (*cursor++));/*输出 2*/
printf("cursor2 = %x\n", cursor);/*输出 testArr[1] + 1 地址*/
printf("cursor2 = %x\n", *cursor);/*输出 3*/
return 0
}
3、测试结果
cursor1 = ff2ff63c
*cursor++ = 2
cursor2 = ff2ff640
cursor2 = 3
三、C++小括号重载的意义是什么?
1、链接
2、摘录、总结
常见的用法有三种、一种是Callable、一种是索引、一种是正常类赋值操作
(1)正常类赋值操作
a:测试程序
#include <iostream>
using namespace std;
class Clastype
{
public:
int a;
public:
Clastype(int a)
{
cout << "Hello Clastype a == " << a << endl;
this->a = a;
}
bool operator ()(int b)
{
cout << "Hello Clastype b == " << b << endl;
this->a = b;
return true;
}
};
int main()
{
Clastype a(1);
cout << " int a === " << a.a << endl;
Clastype(2);
cout << " int a === " << Clastype(2).a << endl;
Clastype t = Clastype(3);
cout << " int a === " << t.a << endl;
t(4);
cout << " int a === " << t.a << endl;
Clastype* b = new Clastype(5);
cout << " int a === " << (*b).a << endl;
(*b)(6);
cout << " int a === " << (*b).a << endl;
return 0;
}
b:运行结果
Hello Clastype a == 1
int a === 1
Hello Clastype a == 2
Hello Clastype a == 2
int a === 2
Hello Clastype a == 3
int a === 3
Hello Clastype b == 4
int a === 4
Hello Clastype a == 5
int a === 5
Hello Clastype b == 6
int a === 6
(2)Callable
a:相关介绍
(1)Callable,也就是可调用对象。他包含了函数指针、重载operator()的对象、以及可隐式转化为前两者的对象。重载operator()的对象,也称为Functor。中文翻译为函子。
(2)Functor的用法,详情如下程序
b:测试程序
#include "csdn_demo.h"
#include <map>
using namespace std;
/*=======================================第一种用法======================================*/
/*仿写一个std::for_each函数 - 在函数f类型定义了一个Callable参数*/
template<typename T,typename Func>
void self_for_each(T* begin, T* end, const Func f)
{
while (begin != end)
{
f(*begin++);
}
}
/*实现一个函数,将这个函数作为Func第三个参数*/
template<typename T>
void self_print(const T x)
{
cout << "value == " << x << endl;
}
/*=======================================第一种用法======================================*/
/*=======================================第二种用法======================================*/
template<typename T>
struct Self_Printf
{
void operator()(const T x)const
{
cout << "struct === " << x << endl;
}
};
/*=======================================第二种用法======================================*/
/*调用*/
int main()
{
int a[5] = { 1,2,3,4,5 };
/*=======================================第一种用法 调用======================================*/
self_for_each(a,a+5, self_print<int>);
cout << "================" << endl;
/*=======================================第二种用法 调用======================================*/
self_for_each(a, a + 5, Self_Printf<int>());
cout << "================" << endl;
/*=======================================第三种用法 调用======================================*/
self_for_each(a, a + 5, [](auto& x) {cout << "lambda == " << x << endl; });
return 0;
}
c:测试结果
value == 1
value == 2
value == 3
value == 4
value == 5
================
struct === 1
struct === 2
struct === 3
struct === 4
struct === 5
================
lambda == 1
lambda == 2
lambda == 3
lambda == 4
lambda == 5
(3)索引
a:相关介绍
类似于python一样:x[5,5]
b:测试程序
#include "csdn_demo.h"
#include <map>
#include <iostream>
using namespace std;
template<typename T,size_t ROWS, size_t COLS>
struct Self_index
{
T data[ROWS][COLS];
T operator()(int x,int y)const
{
cout << "1111111111111111" << endl;
return data[x][y];
}
T& operator()(int x, int y)
{
cout << "222222222222" << endl;
return data[x][y];
}
template <class...Args>
auto get(Args&&... args)const
{
return this->operator()(std::forward<Args>(args)...);
}
};
/*调用*/
int main()
{
Self_index<int, 10, 5> index;
index(5, 5) = 10;
cout << index.get(5, 5) << endl;
return 0;
}
c:测试结果
222222222222
1111111111111111
10
四、find_if函数关于浮点数==比较
1、概要说明
find_if函数在判断两个浮点书相等的时候会遇到问题,在日常程序中,比较两个浮点数相等,原理上不能用==直接比较。需要自己手动实现比较函数。
2、测试程序
using namespace std;
#include <vector>
#include <iostream>
#include <fstream>
#include <iterator>
#include <functional>
/*结构体版本*/
struct compare : binary_function<float, float, bool>
{
bool operator()(float val, float b) const
{
if (fabs(val - b) < 1e-6)
return true;
else
return false;
}
};
/*类版本*/
template <typename T>
class find_test
{
public:
find_test(T& value)
{
this->value = value;
}
bool operator()(T& t)
{
if (fabs(t - value) < 1e-6)
return true;
else
return false;
}
private:
T value;
};
/*就是从begin开始 ,到end为止,返回第一个让 func这个函数返回true的iterator*/
void lambda_test01()
{
float a = 44.48999786;
vector <float> vec;
vec.push_back(44.48999786);
vec.push_back(44.46999741);
vec.push_back(44.45999908);
vec.push_back(44.43999863);
vec.push_back(44.41999817);
auto num = find_if(vec.begin(), vec.end(), find_test<float>(a));
cout << "类 == " << *num << endl;
}
/*就是从begin开始 ,到end为止,返回第一个让 func这个函数返回true的iterator*/
void lambda_test()
{
vector <float> vec;
vec.push_back(44.48999786);
vec.push_back(44.46999741);
vec.push_back(44.45999908);
vec.push_back(44.43999863);
vec.push_back(44.41999817);
auto num = find_if(vec.begin(), vec.end(), bind2nd(compare(), 44.48999786));
cout << "结构体 == " << *num << endl;
}
/*调用*/
int main()
{
lambda_test01();
cout << "============================" << endl;
lambda_test();
return 0;
}
3、测试结果
类 == 44.49
============================
结构体 == 44.49
五、判断数据是否为 Nan 或者 INF
1、概要说明
返回NaN的运算有如下三种:
(1)至少有一个参数是NaN的运算
(2)不定式
下列除法运算:0/0、∞/∞、∞/−∞、−∞/∞、−∞/−∞
下列乘法运算:0×∞、0×−∞
下列加法运算:∞ + (−∞)、(−∞) + ∞
下列减法运算:∞ - ∞、(−∞) - (−∞)
(3)产生复数结果的实数运算。例如:
对负数进行开偶次方的运算
对负数进行对数运算
对正弦或余弦到达域以外的数进行反正弦或反余弦运算 [1]
2、测试程序
#include <iostream>
#include <math.h>
using namespace std;
int main02(int argc, char* argv[])
{
//nan
cout << "nan: " << sqrt(-1) << endl;
//cout << "nan: " << log(-1.0) << endl;
//cout << "nan: " << 0.0 / 0.0 << endl;
//cout << "nan: " << 0.0 * sqrt(-1) << endl;
cout << "nan: " << sqrt(-1) / sqrt(-1) << endl;
cout << "nan: " << sqrt(-1) - sqrt(-1) << endl;
cout << "nan: " << isnan(sqrt(-1) - sqrt(-1)) << endl;
cout << "nan: " << isnormal(sqrt(-1) - sqrt(-1)) << endl;
//inf
//cout << "inf: " << 1 / 0.0 << endl;
//cout << "-inf: " << -1 / 0.0 << endl;
//cout << "inf: " << 0.0 + 1 / 0.0 << endl;
cout << "-inf: " << log(0) << endl;
//cout << "isfinite: 0" << isfinite(0.0 / 0.0) << endl;
//cout << "isfinite: 0" << isfinite(1 / 0.0) << endl;
cout << "isfinite: 1" << isfinite(1.1) << endl;
//cout << "isnormal: 0" << isnormal(0.0 / 0.0) << endl;
//cout << "isnormal: 0" << isnormal(1 / 0.0) << endl;
cout << "isnormal: 1" << isnormal(1.1) << endl;
//cout << "isnan: 1" << isnan(0.0 / 0.0) << endl;
//cout << "isnan: 0" << isnan(1 / 0.0) << endl;
cout << "isnan: 0" << isnan(1.1) << endl;
//cout << "isinf: 0" << isinf(0.0 / 0.0) << endl;
//cout << "isinf: 1" << isinf(1 / 0.0) << endl;
cout << "isinf: 0" << isinf(1.1) << endl;
int num = 0;
float rate = 1 / num;
/*判断该浮点数 是否为一个数(非inf或nan),是返回1,其它返回0;*/
if (isnormal(rate) == 0)
{
cout << "rate 是Nan值 或者 INF值" << endl;
}
return 0;
}
3、测试结果
nan: -nan(ind)
nan: -nan(ind)
nan: -nan(ind)
nan: 1
nan: 0
-inf: -inf
isfinite: 11
isnormal: 11
isnan: 00
isinf: 00
六、Lambda计算平均数
1、概要说明
正常的计算平均数:先求和再求平均数。目前通过lambda的方式来进行计算
2、测试程序
template<class E,class T>
E mean(T& container)
{
auto sum = std::accumulate(container.begin(), container.end(), 0.0/*initial value*/,
[](float total, float cur)
{
cout << "total == " << total << " cur == " << cur << endl;
return total + cur;
}//end of lambda
);//end of accumulate
return static_cast<float>(sum) / (container.size() * 1.0); //to find the mean
}//end of mean
int main()
{
std::vector<float> a{ 1.2, 2.4, 3.8, 4.4, 5.2, 6.6, 7.8, 8.9, 9.1, 10.2, 15.12, 14.34 };
float mean_temp = mean<float , vector<float>>(a);
cout << mean_temp << endl;
return 0;
}
3、测试结果
total == 0 cur == 1.2
total == 1.2 cur == 2.4
total == 3.6 cur == 3.8
total == 7.4 cur == 4.4
total == 11.8 cur == 5.2
total == 17 cur == 6.6
total == 23.6 cur == 7.8
total == 31.4 cur == 8.9
total == 40.3 cur == 9.1
total == 49.4 cur == 10.2
total == 59.6 cur == 15.12
total == 74.72 cur == 14.34
7.42167
七、自动创建文件夹(跨平台)
1、概要说明
C++版本直接自动生成目录
2、测试程序
/*-----------------------完成目录创建---------------------*/
#pragma once
#include <iostream>
#include <iostream>
#include <algorithm>
#include <math.h>
#include <time.h>
#include <string.h>
#include <string>
#include <list>
#include <map>
#include <queue>
#include <vector>
#include <stack>
using namespace std;
#ifdef _WIN32
#include <direct.h>
#include <io.h>
#include <windows.h>
#elif __linux__
#include <unistd.h>//for mkdir rmdir
#include <sys/stat.h>//for access
#include <dirent.h> //for DIR remove
#endif
#ifdef _WIN32
#define ACCESS _access
#define MKDIR(a) _mkdir((a))
#define RMDIR(a) _rmdir((a))
#elif __linux__
#define ACCESS access
#define MKDIR(a) mkdir((a),0755)
#define RMDIR(a) rmdir((a))
#endif
class Util
{
public:
static int JudgeFileExiste(const char* FileName)
{
int flag = ACCESS(FileName, 0);
return flag;
}
static bool RadarMkDir(const char* strPath1)
{
int i = 0;
string strPath = strPath1;
int nDirLen = strPath.length();
if (nDirLen <= 0)
return false;
char* pDirTemp = new char[nDirLen + 4];
strPath.copy(pDirTemp, nDirLen + 1, 0);
pDirTemp[nDirLen] = '\0';
if (pDirTemp[nDirLen - 1] != '\\' && pDirTemp[nDirLen - 1] != '/')
{
pDirTemp[nDirLen] = '/';
pDirTemp[nDirLen + 1] = '\0';
nDirLen++;
}
for (i = 0; i < nDirLen; i++)
{
if (pDirTemp[i] == '\\' || pDirTemp[i] == '/')
{
pDirTemp[i] = '\0';
int statu;
statu = ACCESS(pDirTemp, 0);
cout << "statu == " << statu << endl;
if (statu != 0)
{
statu = MKDIR(pDirTemp);
if (statu != 0)
{
return false;
}
}
pDirTemp[i] = '/';
}
}
delete[] pDirTemp;
return true;
}
/*操作说明:
path 文件所在目录路径,
maker 文件后缀,无需加通配符(至于windows下为什么要加我需要再次研究代码)
files 输出 */
static void GetFiles(string path, string maker, vector<string>& files)
{
#ifdef _WIN32
string S_maker = "/*" + maker; /*加上通配符*/
//文件句柄
intptr_t hFile = 0;
//文件信息
struct _finddata_t fileinfo;
string p;
if ((hFile = _findfirst(p.assign(path).append(S_maker).c_str(), &fileinfo)) != -1)
{
do
{
//如果是目录,迭代之
//如果不是,加入列表
if ((fileinfo.attrib & _A_SUBDIR))
{
if (strcmp(fileinfo.name, ".") != 0 && strcmp(fileinfo.name, "..") != 0)
GetFiles(p.assign(path).append("/").append(fileinfo.name), S_maker, files);
}
else
{
files.push_back(p.assign(path).append("/").append(fileinfo.name));
}
} while (_findnext(hFile, &fileinfo) == 0);
_findclose(hFile);
}
#endif
#ifdef __linux__
string directory = path;
string m_ext = maker;
DIR* dir = opendir(path.c_str());
if (dir == NULL)
{
printf("[ERROR] %s is not a directory or not exist!", path.c_str());
return;
}
// dirent会存储文件的各种属性
struct dirent* d_ent = NULL;
// 一行一行的读目录下的东西,这个东西的属性放到dirent的变量中
string p;
while ((d_ent = readdir(dir)) != NULL)
{
// 忽略 "." 和 ".."
if (strcmp(d_ent->d_name, ".") == 0 || strcmp(d_ent->d_name, "..") == 0) ///current dir OR parrent dir
{
continue;
}
else
{
// d_type可以看到当前的东西的类型,DT_DIR代表当前都到的是目录,在usr/include/dirent.h中定义的
if (d_ent->d_type != DT_DIR)
{
string d_name(d_ent->d_name);
if (strcmp(d_name.c_str() + d_name.length() - m_ext.length(), m_ext.c_str()) == 0)
{
files.push_back(p.assign(path).append("/").append(d_ent->d_name));
}
}
}
}
sort(files.begin(), files.end());
closedir(dir);
dir = NULL;
#endif
}
};
/*-------------------------------函数调用---------------------------*/
int main()
{
string data_all_path = "D:\\Desktop\\att";
Util::RadarMkDir(data_all_path .c_str());
return 0;
}
3、测试结果
会直接生成该目录,如果目录存在,则跳过;
八、vector删除函数
1、概要说明
记录一下删除一组数据中的指定值
2、测试程序
/*方法一*/
int main()
{
std::vector<float> value{ 1.2, -1280,2.4, 3.8, 4.4, 5.2, -1280,6.6, 7.8, 8.9,-1280, 9.1, 10.2,-1280, 15.12, 14.34 };
cout << "删除之前:" << value.size() << endl;
for (float a : value)
{
cout << "value == " << a << endl;
}
value.erase(remove(value.begin(), value.end(), -1280), value.end()); //value是要删除的值
cout << "删除之后:" << value.size() << endl;
for (float a : value)
{
cout << "value == " << a << endl;
}
return 0;
}
/*方法二*/
int main()
{
std::vector<float> value{ 1.2, -1280,2.4, 3.8, 4.4, 5.2, -1280,6.6, 7.8, 8.9,-1280, 9.1, 10.2,-1280, 15.12, 14.34 };
cout << "删除之前:" << value.size() << endl;
for (int a : value)
{
cout << "value == " << a << endl;
}
auto temp_iter = value.begin();
cout << "" << endl;
for (int i = 0; i < value.size(); i++)
{
if (value[i] == -1280)
{
value.erase(temp_iter + i);
}
}
cout << "删除之后:" << value.size() << endl;
for (float a : value)
{
cout << "value == " << a << endl;
}
return 0;
}
/*方法三*/
int main()
{
std::vector<float> value{ 1.2, -1280,2.4, 3.8, 4.4, 5.2, -1280,6.6, 7.8, 8.9,-1280, 9.1, 10.2,-1280, 15.12, 14.34 };
for (int a : value)
{
cout << "value == " << a << endl;
}
for (auto iter = value.begin(); iter != value.end();)
{
if (*iter == -1280)
{
iter = value.erase(iter);
}
else
{
iter++;
}
}
cout << " " << endl;
for (int a : value)
{
cout << "value == " << a << endl;
}
return 0;
}
3、测试结果
删除前
value == 1.2
value == -1280
value == 2.4
value == 3.8
value == 4.4
value == 5.2
value == -1280
value == 6.6
value == 7.8
value == 8.9
value == -1280
value == 9.1
value == 10.2
value == -1280
value == 15.12
value == 14.34
删除后
value == 1.2
value == 2.4
value == 3.8
value == 4.4
value == 5.2
value == 6.6
value == 7.8
value == 8.9
value == 9.1
value == 10.2
value == 15.12
value == 14.34
九、C/C++中定义全局变量时避免重复定义
1、概要说明
在日常工作中,可能会需要多个文件共同使用一个变量,并通过不同文件对该变量进行修改,但是不同文件包含相同头文件,会报错:变量类型重定义,使用extern 关键字完成这个操作;
解决方案:只要在定义时尽量在.cpp下进行,而不要在.h中定义,利用extern关键字进行申明即可,其他文件要使用这些变量只要引入相对应头文件即可。而且不会引起重复定义的错误
2、测试程序
1、在.cpp中进行定义
/*mian_shi.cpp*/
#include "mian_shi.h"
using namespace std;
int a;
int main()
{
func();
a = 10;
func();
return 0;
}
2、在.h中使用extern声明
/*mian_shi.h*/
#pragma once
#include <iostream>
#include "a.h"
extern int a;
3、使用另一个.h、.cpp来使用变量 a
/*a.h*/
/*在该.h中引入mian_shi.h */
#pragma once
#include "mian_shi.h"
void func();
4、使用另一个.cpp完成变量 a的使用及修改
/*a.cpp*/
#include "a.h"
void func()
{
cout << " 来自外部的 a 变量 == " << a << endl;
a = 100;
cout << "经由函数:" << __func__ << " 修改后 a 变量 == " << a << endl;
}
3、运行结果
来自外部的 a 变量 == 0
经由函数:func 修改后 a 变量 == 100
来自外部的 a 变量 == 10
经由函数:func 修改后 a 变量 == 100
十、Qt安装成功后,报:This application failed to start because no Qt platform plugin could be initialized问题
方法一:(亲测有效)
在用户变量中添加如下内容:
变量名:QT_QPA_PLATFORM_PLUGIN_PATH
变量值:%QTDIR%\plugins\platforms
方法二:
将Qt目录下plugin文件夹中的platforms文件夹直接复制到项目.exe的运行目录下
方法三:
如果仍报错,可以尝试下列方法:
在Qt安装文件夹,相应版本的bin目录中找到libEGL.dll,将该动态链接库直接复制到运行项目文件夹中即可正常运行。