C/C++ 开发常用代码块之一

日期处理

C++ 格式化当前时间

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
#include <iostream>
#include <time.h>

using namespace std;

// 格式化当前时间
// 默认格式是: 2020-06-07 23:46:53
string formatCurrentTime() {
time_t rawtime;
struct tm* info;
char buffer[80];

time(&rawtime);
info = localtime(&rawtime);
strftime(buffer, 80, "%Y-%m-%d %H:%M:%S", info);
string str(buffer);
return str;
}

// 格式化当前时间
// format: 格式字符串,例如 %Y-%m-%d %H:%M:%S
string formatCurrentTime(string format) {
time_t rawtime;
struct tm* info;
char buffer[80];

time(&rawtime);
info = localtime(&rawtime);
strftime(buffer, 80, format.c_str(), info);
string str(buffer);
return str;
}

int main() {
cout << formatCurrentTime() << endl;
cout << formatCurrentTime("%Y-%m-%d") << endl;
}

程序运行输出的结果如下:

1
2
2021-11-22 22:52:43
2021-11-22

C++ 计算两个日期之间的天数

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
#include <iostream>

using namespace std;

// 判断一个年份是否为闰年
bool isLeap(int year) {
return (year % 4 == 0 || year % 400 == 0) && (year % 100 != 0);
}

// 计算特定年份的天数
int daysOfYear(int year) {
return isLeap(year) ? 366 : 365;
}

// 根据给定的日期,计算它在该年的第几天
int dayInYear(int year, int month, int day) {
int DAY[12] = { 31, 28, 31, 30, 31, 30, 31, 31, 30, 31, 30, 31 };
if (isLeap(year)) {
DAY[1] = 29;
}
for (int i = 0; i < month - 1; ++i) {
day += DAY[i];
}
return day;
}

// 判断日期字符串是否合法,并分别取出日期中的年月日
// date: 日期字符串,格式是: 20211201
bool stringToDate(string date, int& year, int& month, int& day) {
year = atoi(date.substr(0, 4).c_str());
month = atoi(date.substr(4, 2).c_str());
day = atoi(date.substr(6, 2).c_str());
int DAY[12] = { 31, 28, 31, 30, 31, 30, 31, 31, 30, 31, 30, 31 };
if (isLeap(year)) {
DAY[1] = 29;
}
return year >= 0 && month <= 12 && month > 0 && day <= DAY[month - 1] && day > 0;
}

// 计算两个日期之间的天数
// date1: 日期字符串,格式是: 20211201
// date2: 日期字符串,格式是: 20211201
// 当返回值为 -1 时,说明日期的格式不正确
int daysBetween2Date(string date1, string date2) {
int year1, month1, day1;
int year2, month2, day2;
if (!stringToDate(date1, year1, month1, day1) || !stringToDate(date2, year2, month2, day2)) {
cout << "输入的日期格式不正确";
return -1;
}
if (year1 == year2 && month1 == month2) {
return day1 > day2 ? day1 - day2 : day2 - day1;
}
else if (year1 == year2) {
int d1, d2;
d1 = dayInYear(year1, month1, day1);
d2 = dayInYear(year2, month2, day2);
return d1 > d2 ? d1 - d2 : d2 - d1;
}
else {
// 确保year1年份比year2早
if (year1 > year2) {
swap(year1, year2);
swap(month1, month2);
swap(day1, day2);
}
// 计算第一个日期在该年还剩多少天
int d1, d2, d3;
if (isLeap(year1)) {
d1 = 366 - dayInYear(year1, month1, day1);
}
else {
d1 = 365 - dayInYear(year1, month1, day1);
}
// 计算第二日期在当年中的第几天
d2 = dayInYear(year2, month2, day2);
// 计算两个年份相隔的天数
d3 = 0;
for (int year = year1 + 1; year < year2; year++) {
if (isLeap(year))
d3 += 366;
else
d3 += 365;
}
return d1 + d2 + d3;
}
}

int main() {

int days = daysBetween2Date("20101111", "20111111");
cout << "相差 " << days << " 天" << endl;

int days2 = daysBetween2Date("20200202", "20200131");
cout << "相差 " << days2 << " 天" << endl;

int days3 = daysBetween2Date("20230712", "20050619");
cout << "相差 " << days3 << " 天" << endl;

return 0;
}

程序运行输出的结果如下:

1
2
3
相差 365 天
相差 2 天
相差 6597 天

加载动态库

C++ 加载动态库(.so)

下述示例代码,适用于 Linux 系统的 C++ 开发。

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
#include <stdio.h>
#include <dlfcn.h>
#include <stdlib.h>
#include <iostream>

using namespace std;

int main()
{
int a = 0;

// 加载动态库
void *handle = dlopen("./libadd_c.so", RTLD_LAZY);

if(!handle)
{
printf("open lib error\n");
cout<<dlerror()<<endl;
return -1;
}

// 定义函数指针类型
typedef int (*add_t)(int a, int b);

// 调用动态库
add_t add = (add_t) dlsym(handle, "add");
if(!add)
{
cout<<dlerror()<<endl;
dlclose(handle);
return -1;
}
a = add(3, 4);
printf("a = %d\n",a);

// 释放动态库
dlclose(handle);
return 0;
}

C/C++ 加载动态链接库(.dll)

下述示例代码,适用于 Windows 系统的 C++ 开发。值得一提的是,若是使用的是 C 语言,则只需将下面代码中的 #include <iostream> 替换为 #include <stdio.h>,同时删除掉 using namespace std; 即可。

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
#include <iostream>
#include <windows.h>

using namespace std;

int main() {

HINSTANCE hInstance;

// 加载动态链接库
hInstance = LoadLibrary("./socketclient.dll");
if (hInstance == NULL)
{
printf("LoadLibrary() 调用失败, ErrorCode: %d", GetLastError());
return -1;
}

// 定义函数类型指针
typedef int (*CltSocketInit)(void** handle);

// 调用动态链接库
CltSocketInit cltSocketInit = (CltSocketInit)GetProcAddress(hInstance, "cltSocketInit");
if (cltSocketInit != NULL)
{
void* handle = NULL;
int result = cltSocketInit(&handle);
printf("result = %d", result);
}

// 释放动态链接库
if (hInstance != NULL) {
FreeLibrary(hInstance);
}

return 0;
}

任务调度

C++ 定时器

基于 C++ 11 实现等价于 Javascript 的 setTimeout()setInterval() 函数。

  • timer.h
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
#include <iostream>
#include <thread>
#include <chrono>
#include <atomic>

using namespace std;

class Timer {

public:
typedef void(TimerFunction)();

public:
void setTimeout(TimerFunction, long delay);
void setInterval(TimerFunction, long interval);
void stop();

private:
atomic<bool> active{ true };

};

void Timer::setTimeout(TimerFunction function, long delay) {
active = true;
thread t([=]() {
if (!active.load()) return;
this_thread::sleep_for(chrono::milliseconds(delay));
if (!active.load()) return;
function();
});
t.detach();
}

void Timer::setInterval(TimerFunction function, long interval) {
active = true;
thread t([=]() {
while (active.load()) {
this_thread::sleep_for(chrono::milliseconds(interval));
if (!active.load()) return;
function();
}
});
t.detach();
}

void Timer::stop() {
active = false;
}
  • main.h
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
#include <conio.h>
#include <iostream>
#include "timer.h"

using namespace std;

void refreshConfig() {
cout << "execute refresh config ..." << endl;
}

int main() {
// 使用智能指针
unique_ptr<Timer> timer(new Timer());
Timer::TimerFunction* refreshFunc = refreshConfig;
timer->setInterval(refreshConfig, 3000);
timer->setTimeout(refreshConfig, 5000);
_getch();
return 0;
}

程序运行输出的结果如下:

1
2
3
4
5
execute refresh config ...
execute refresh config ...
execute refresh config ...
execute refresh config ...
execute refresh config ...