常用的C++小代码段

目录:

  1. win10上在程序中调用.exe文件,并获取返回值
  2. 任意给出一个路径(非根目录),找到上一层目录
  3. 使用C++标准库中的thread类编写多线程程序
  4. 在结构体中定义函数
  5. C++复制文件
  6. C++如何判断某一个目录是否存在?创建文件夹?删除文件夹?
  7. C++调用OpenCV对视频文件进行解帧以及将图片压缩为视频文件
  8. linux下的程序计时操作

1、win10上在c++中调用.exe文件,并获取返回值

这里只比较其中的两种方式:WinExec和system。它们的区别是:
  • WinExec()有两个参数,第一个参数是要执行的cmd,第二个参数可以设置窗口如何显示。但是要注意的是WinExec()是不同步的进程调用,一经调用立刻就会返回一个值(这个值用来表示是否调用成功),如果调用成功则返回值大于31,调用失败则返回值小于31。
  • system()只有一个参数,就是要执行的cmd命令。system()是同步调用进程的方式,调用的进程不结束,就不会返回。

可以用下面的程序测试一下,运行结果有明显的不同:

#include <iostream>
#include <thread>

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 <iostream>
#include <thread>
#include <Windows.h>

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()的运行结果:可以很清楚的看到两者的区别。
WinExec()的执行结果
system()的执行结果

2、查找任意一个路径(非根目录)的上一层目录---进行字符串反向查找"\\"并截取字符串即可

std::string find_last_dir(std::string path) {
	std::string::size_type pos;
	pos = path.rfind("\\");
	return path.substr(0, pos);
}

3、使用c++标准库中的thread类来编写多线程程序

使用thread来编写多线程程序时非常方便的。

  • 首先要导入头文件#include 并且声明使用std名字空间using namespace std;。然后要注意的是线程需要有一个“开始”的地方,就是线程入口的函数,也可以直接称为线程函数。当线程函数返回时,线程也就随之终止了。

  • 启动线程的两个方法:join()或者detach()

如果选用join()方法时,主线程(可以认为main函数也是一个线程)会阻塞住,直接该子线程退出为止,然后主线程继续顺序执行。
如果选择detach()方式:执行的线程从线程对象中被独立独立运行,主线程丧失对子线程的控制权。(可能main已经执行结束了,但是子线程还没有结束)这就引出了两个需要注意的问题:
主线程结束之后,子线程可能还在执行(因而可以作为守护线程)
主线程结束伴随着资源销毁,所以需要保证子线程没有引用这些资源。
下面是一个很简单的多线程线程的例子:

#include <iostream>
#include <thread>
#include <string>

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<mutex>。

代码修改如下:

#include <iostream>
#include <thread>
#include <string>
#include <mutex>

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;
}

运行结果如下:
在这里插入图片描述

4、在结构体中定义函数

c++中是允许在结构体中定义函数的,它的用法和类的用法很像,不过与类有一个区别在于**struct中定义的函数和变量都是默认为public类型的,但是class中默认的是private类型**。

下面同样给出一个简单例子:

#include <iostream>
#include <string>

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;
}

5、C++复制文件

这里直接使用简单粗暴的方式,先用ifstream、ofstream打开文件(以w模式打开文件,如果文件不存在的话会自动创建文件),然后一边读一边写实现复制操作。

函数定义如下:

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、论文学习的一个分享平台。只推干货,宁缺毋滥。
在这里插入图片描述

6、C++如何判断某一个目录是否存在?创建文件夹?删除文件夹?

在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

7、C++调用OpenCV对视频文件进行解帧以及将图片压缩为视频文件

#include <opencv2\opencv.hpp>
#include <iostream>
#include <vector>

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();
}

8、linux下的计时操作

可用于测量程序的执行时间。也是经常要用到的。通过gettimeofday()实现,可精确到微秒级别。 需要使用到结构struct timeval,定义如下:
struct timeval {
	time_t tv_sec; //秒
	long tv_usec; //微秒
};

gettimeofday()返回自1970-01-01 00:00:00到现在经历的秒数。

#include <sys/time.h>
#include <iostream>
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;
}

运行结果:
在这里插入图片描述

发布了47 篇原创文章 · 获赞 23 · 访问量 8万+

猜你喜欢

转载自blog.csdn.net/llfjcmx/article/details/102831251