可以用下面的程序测试一下,运行结果有明显的不同:
#include
#include
int main()
{
for(int i=0; i<10; i++)
{
std::this_thread::sleep_for(std::chrono::milliseconds(1000));
std::cout << "i = " << i << std::endl;
}
return 0;
}
下面的程序调用上面的程序经过编译-连接后生成的.exe文件:
#include
#include
#include
int main() {
std::string command = "E:\\code\\cpp_learn\\while_10\\x64\\while_10.exe";
//int result = WinExec(command.data(), SW_SHOW);
int result = system(command.data());
std::cout << "result = " << result << std::endl;
return 0;
}
下面依次是使用WinExec()、system()的运行结果:可以很清楚的看到两者的区别。
std::string find_last_dir(std::string path) {
std::string::size_type pos;
pos = path.rfind("\\");
return path.substr(0, pos);
}
使用thread来编写多线程程序时非常方便的。
首先要导入头文件#include 并且声明使用std名字空间using namespace std;。然后要注意的是线程需要有一个“开始”的地方,就是线程入口的函数,也可以直接称为线程函数。当线程函数返回时,线程也就随之终止了。
启动线程的两个方法:join()或者detach()
如果选用join()方法时,主线程(可以认为main函数也是一个线程)会阻塞住,直接该子线程退出为止,然后主线程继续顺序执行。
如果选择detach()方式:执行的线程从线程对象中被独立独立运行,主线程丧失对子线程的控制权。(可能main已经执行结束了,但是子线程还没有结束)这就引出了两个需要注意的问题:
主线程结束之后,子线程可能还在执行(因而可以作为守护线程)
主线程结束伴随着资源销毁,所以需要保证子线程没有引用这些资源。
下面是一个很简单的多线程线程的例子:
#include
#include
#include
void thread_func(std::string tName) {
for (int i = 0; i < 10; i++) {
std::cout << "线程" << tName << "执行了 " << i << " 次" << std::endl;
std::this_thread::sleep_for(std::chrono::milliseconds(100));
}
}
int main() {
std::thread t1(thread_func, "A");
std::thread t2(thread_func, "B");
t1.join();
t2.join();
std::cout << "main结束" << std::endl;
}
下面是运行结果:
从运行结果中可以看到:两个线程都结束了之后,main函数继续向下执行,输出“main结束”。但是现在出现问题了:
std::cout << "线程" << tName << "执行了 " << i << " 次" << std::endl;
比如说线程A执行这条语句,但是还没有执行完,就被B“抢”过去执行了。
要解决这个问题,可以对其进行加锁—信号量机制。
c++11提供了std::mutex类,在头文件mutex中声明,因此要首#include
代码修改如下:
#include
#include
#include
#include
std::mutex tLock;
void thread_func(std::string tName) {
for (int i = 0; i < 10; i++) {
tLock.lock();
std::cout << "线程" << tName << "执行了 " << i << " 次" << std::endl;
tLock.unlock();
std::this_thread::sleep_for(std::chrono::milliseconds(100));
}
}
int main() {
std::thread t1(thread_func, "A");
std::thread t2(thread_func, "B");
t1.join();
t2.join();
std::cout << "main结束" << std::endl;
}
下面同样给出一个简单例子:
#include
#include
using namespace std;
typedef struct Person {
string name;
string sex;
int age;
Person(string _name, string _sex, int _age) {
name = _name;
sex = _sex;
age = _age;
}
string to_string() {
string str;
str = "name: " + name + "\nsex: " + sex + "\nage: " + std::to_string(age);
return str;
}
};
int main() {
Person a("Robert", "man", 25);
cout << a.to_string() << endl;
return 0;
}
函数定义如下:
inline void copy_file(string old_file_name, string new_file_name) {
ifstream in(old_file_name, std::ios::in);
ofstream out(new_file_name, std::ios::out);
if (!(in.is_open() && out.is_open())) {
cout << "Error!" << endl;
}
string line;
while (getline(in, line))
{
out << line << endl;
}
in.close();
out.close();
}
上面的小代码段都很小,平时可以用来做一些简单、重复的处理,类似于脚本。需要的时候拿过来用就好了。
公众号中还有很多有趣的东西哦,是一个SLAM、ML/DL、论文学习的一个分享平台。只推干货,宁缺毋滥。
在C++标准库中没有直接对目录操作的函数(反正我没找到),因此在需要操作文件夹的时候使用系统平台函数比较方便。同时系统函数在windows平台和Linux平台上有一定的区别。
判断文件和文件夹是否存在以及是否具有访问权限:
windows:
函数: int access(const char* _Filename, int AccessMode)
头文件: io.h
Linux:
int access(const char* _Filename, int AccessMode)]
头文件:unistd.h
功能:确定文件和文件夹是否存在或者是否具有访问权限,有指定访问权限则返回0,否则返回-1。
AccessMode参数:
00表示只判断是否存在
02表示文件是否可执行
04表示文件是否可写
06表示文件是否可读
创建文件夹:
windows:
函数:int mkdir(const char* _Path)
头文件:direct.h
Linux:
函数:int mkdir(const char* pathname, mode_t mode)
头文件:sys/types.h, sys/stat.h
功能:创建文件夹,返回0为创建成功,否则返回-1
删除文件夹:
windows:
函数: int rmdir(const char* _Path)
头文件:direct.h
linux:
函数:int rmdir(const char* _Path)
头文件:sys/types.h, sys/stat.h
功能: 删除文件夹,成功返回0,否则-1
#include
#include
#include
class Video2Image
{
private:
const std::string conWindowName;
std::string video_full_name;
std::string image_dir;
public:
Video2Image(std::string video_full_name_, std::string image_dir_, std::string current_image_);
void toImage();
void toVideo();
};
Video2Image::Video2Image(std::string video_full_name_, std::string image_dir_, std::string current_image_)
:conWindowName(current_image_)
{
video_full_name = video_full_name_;
image_dir = image_dir_;
}
void Video2Image::toImage()
{
cv::VideoCapture cap;
cap.open(video_full_name);
if (cap.isOpened())
{
cv::Mat frame;
char img_full_name[256];
cv::namedWindow(conWindowName, CV_WINDOW_NORMAL);
for (int i = 0; cap.read(frame); ++i)
{
cv::imshow(conWindowName, frame);
cv::waitKey(1);
sprintf(img_full_name, "%s\\%04d.jpg", image_dir.c_str(), i);
cv::imwrite(img_full_name, frame);
}
cv::destroyWindow(conWindowName);
}
else
{
std::cout << "Open " << video_full_name << " failed..." << std::endl;
}
}
void Video2Image::toVideo()
{
std::vector<cv::String> img_names;
cv::glob(image_dir, img_names);
int counts = image_dir.size();
//打开视频文件
cv::VideoWriter vw;
std::cout << video_full_name << std::endl;
vw.open(
video_full_name,
CV_FOURCC('M', 'J', 'P', 'G'),
25,
cv::imread(img_names[0]).size(),
true
);
char img_full_name[256];
for (int i = 0; i < img_names.size(); i++)
{
sprintf(img_full_name, "%s\\%04d.jpg", i);
vw.write(cv::imread(img_full_name));
cv::waitKey(1);
}
rw.release();
}
struct timeval {
time_t tv_sec; //秒
long tv_usec; //微秒
};
gettimeofday()返回自1970-01-01 00:00:00到现在经历的秒数。
#include
#include
using namespace std;
int main()
{
struct timeval start, end;
gettimeofday(&start, NULL);
for(int i=0; i<100; ++i)
{
cout << "i = " << i << endl;
}
gettimeofday(&end, NULL);
//毫秒级别
double cost_time = (end.tv_sec - start.tv_sec) * 1000.0 + (end.tv_usec - start.tv_usec) / 1000.0;
cout << "for循环耗时:" << cost_time << "毫秒." << endl;
//微秒
double cost_time_1 = (end.tv_sec - start.tv_sec) * 1000000.0 + (end.tv_usec - start.tv_usec);
cout << "for循环耗时:" << cost_time_1 << "微秒." << endl;
return 0;
}