我是靠谱客的博主 背后草丛,这篇文章主要介绍C++ 11手写状态机,现在分享给大家,希望可以做个参考。

本文有电话的几种模式,通过一个trigger进行转换。在各种模式之间切换状态。
手写状态机。
程序代码结构如下,
手写状态机代码结构
test/CMakeLists.txt

复制代码
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
cmake_minimum_required(VERSION 2.6) if(APPLE) message(STATUS "This is Apple, do nothing.") set(CMAKE_MACOSX_RPATH 1) set(CMAKE_PREFIX_PATH /Users/aabjfzhu/software/vcpkg/ports/cppwork/vcpkg_installed/x64-osx/share ) elseif(UNIX) message(STATUS "This is linux, set CMAKE_PREFIX_PATH.") set(CMAKE_PREFIX_PATH /vcpkg/ports/cppwork/vcpkg_installed/x64-linux/share) endif(APPLE) project(handmake_state_machine) set(CMAKE_CXX_STANDARD 20) set(CMAKE_CXX_FLAGS "${CMAKE_CXX_FLAGS} -Wno-narrowing") add_definitions(-g) find_package(ZLIB) find_package(OpenCV REQUIRED ) find_package(Arrow CONFIG REQUIRED) find_package(unofficial-brotli REQUIRED) find_package(unofficial-utf8proc CONFIG REQUIRED) find_package(Thrift CONFIG REQUIRED) find_package(glog REQUIRED) find_package(OpenSSL REQUIRED) find_package(Boost REQUIRED COMPONENTS system filesystem serialization program_options thread ) find_package(DataFrame REQUIRED) if(APPLE) MESSAGE(STATUS "This is APPLE, set INCLUDE_DIRS") set(INCLUDE_DIRS ${Boost_INCLUDE_DIRS} /usr/local/include /usr/local/iODBC/include /opt/snowflake/snowflakeodbc/include/ ${CMAKE_CURRENT_SOURCE_DIR}/../include/ ${CMAKE_CURRENT_SOURCE_DIR}/../../../include) elseif(UNIX) MESSAGE(STATUS "This is linux, set INCLUDE_DIRS") set(INCLUDE_DIRS ${Boost_INCLUDE_DIRS} /usr/local/include ${CMAKE_CURRENT_SOURCE_DIR}/../include/ ${CMAKE_CURRENT_SOURCE_DIR}/../../../include/) endif(APPLE) if(APPLE) MESSAGE(STATUS "This is APPLE, set LINK_DIRS") set(LINK_DIRS /usr/local/lib /usr/local/iODBC/lib /opt/snowflake/snowflakeodbc/lib/universal) elseif(UNIX) MESSAGE(STATUS "This is linux, set LINK_DIRS") set(LINK_DIRS ${Boost_INCLUDE_DIRS} /usr/local/lib /vcpkg/ports/cppwork/vcpkg_installed/x64-linux/lib) endif(APPLE) if(APPLE) MESSAGE(STATUS "This is APPLE, set ODBC_LIBS") set(ODBC_LIBS iodbc iodbcinst) elseif(UNIX) MESSAGE(STATUS "This is linux, set LINK_DIRS") set(ODBC_LIBS odbc odbcinst ltdl) endif(APPLE) include_directories(${INCLUDE_DIRS}) LINK_DIRECTORIES(${LINK_DIRS}) file( GLOB test_file_list ${CMAKE_CURRENT_SOURCE_DIR}/*.cpp) file( GLOB APP_SOURCES ${CMAKE_CURRENT_SOURCE_DIR}/../impl/*.cpp ${CMAKE_CURRENT_SOURCE_DIR}/../include/*.h ${CMAKE_CURRENT_SOURCE_DIR}/../include/*.cpp ${CMAKE_CURRENT_SOURCE_DIR}/../../../include/arr_/impl/*.cpp ${CMAKE_CURRENT_SOURCE_DIR}/../../../include/http/impl/*.cpp ${CMAKE_CURRENT_SOURCE_DIR}/../../../include/yaml/impl/*.cpp ${CMAKE_CURRENT_SOURCE_DIR}/../../../include/df/impl/*.cpp ${CMAKE_CURRENT_SOURCE_DIR}/../../../include/death_handler/impl/*.cpp) add_library(${PROJECT_NAME}_lib SHARED ${APP_SOURCES} ${test_file}) target_link_libraries(${PROJECT_NAME}_lib ${Boost_LIBRARIES} ZLIB::ZLIB glog::glog DataFrame::DataFrame ${OpenCV_LIBS}) target_link_libraries(${PROJECT_NAME}_lib OpenSSL::SSL OpenSSL::Crypto libgtest.a pystring libyaml-cpp.a libgmock.a ${ODBC_LIBS} libnanodbc.a pthread dl backtrace libzstd.a libbz2.a libsnappy.a re2::re2 parquet lz4 unofficial::brotli::brotlidec-static unofficial::brotli::brotlienc-static unofficial::brotli::brotlicommon-static utf8proc thrift::thrift arrow arrow_dataset) foreach( test_file ${test_file_list} ) file(RELATIVE_PATH filename ${CMAKE_CURRENT_SOURCE_DIR} ${test_file}) string(REPLACE ".cpp" "" file ${filename}) add_executable(${file} ${test_file}) target_link_libraries(${file} ${PROJECT_NAME}_lib) endforeach( test_file ${test_file_list})

test/handmake_state_machine_test.cpp

复制代码
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
#include "handmake_state_machine.hpp" #include <glog/logging.h> #include <gtest/gtest.h> #include <fstream> #include <memory> #include <algorithm> #include "death_handler/death_handler.h" int main(int argc, char** argv) { FLAGS_log_dir = "./"; FLAGS_alsologtostderr = true; // 日志级别 INFO, WARNING, ERROR, FATAL 的值分别为0、1、2、3 FLAGS_minloglevel = 0; Debug::DeathHandler dh; google::InitGoogleLogging("./logs.log"); testing::InitGoogleTest(&argc, argv); int ret = RUN_ALL_TESTS(); return ret; } GTEST_TEST(HMakeMSMTests, HMakeMSM) { StateMachine sm; while(sm.next_state()); std::cout << "We are done using the phonen"; }

include/handmake_state_machine.hpp

复制代码
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
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
#ifndef _FREDRIC_HANDMAKE_STATE_MACHINE_HPP_ #define _FREDRIC_HANDMAKE_STATE_MACHINE_HPP_ #include <iostream> #include <string> #include <map> #include <vector> enum class State { off_hook, // 已拿起电话 connecting, // 正在连接 connected, // 已连接 on_hold, // 暂停 on_hook // 挂机电话, 退出状态 }; inline std::ostream& operator<< (std::ostream& os, State const& s) { switch(s) { case State::off_hook: os << "off the hook"; break; case State::connecting: os << "connecting"; break; case State::connected: os << "connected"; break; case State::on_hold: os << "on hold"; break; case State::on_hook: os << "on the hook"; break; } return os; } enum class Trigger { call_dialed, hung_up, call_connected, placed_on_hold, taken_off_hold, left_message, stop_using_phone }; inline std::ostream& operator<<(std::ostream& os, Trigger const& t) { switch(t) { case Trigger::call_dialed: os << "call dialed"; break; case Trigger::hung_up: os << "hung up"; break; case Trigger::call_connected: os << "call connected"; break; case Trigger::placed_on_hold: os << "placed on hold"; break; case Trigger::taken_off_hold: os << "taken off hold"; break; case Trigger::left_message: os << "left message"; break; case Trigger::stop_using_phone: os << "putting phone on hook"; break; default: break; } return os; } struct StateMachine { std::map<State, std::vector<std::pair<Trigger, State>>> rules; State currentState{ State::off_hook }, exitState{ State::on_hook }; StateMachine() { rules[State::off_hook] = { {Trigger::call_dialed, State::connecting}, {Trigger::stop_using_phone, State::on_hook} }; rules[State::connecting] = { {Trigger::hung_up, State::off_hook}, {Trigger::call_connected, State::connected} }; rules[State::connected] = { {Trigger::left_message, State::off_hook}, {Trigger::hung_up, State::off_hook}, {Trigger::placed_on_hold, State::on_hold} }; rules[State::on_hold] = { {Trigger::taken_off_hold, State::connected}, {Trigger::hung_up, State::off_hook} }; } bool next_state() { std::cout << "The phone is currently " << currentState << std::endl; select_trigger: std::cout << "Select a trigger:n"; int i = 0; for(auto item: rules[currentState]) { std::cout << i++ << ". " << item.first << "n"; } int input; std::cin >> input; if(input < 0 || (input+1) > rules[currentState].size()) { std::cout << "Incorrect option. Please try again.n"; goto select_trigger; } currentState = rules[currentState][input].second; return (currentState != exitState); } }; #endif

程序输出如下,
在这里插入图片描述

最后

以上就是背后草丛最近收集整理的关于C++ 11手写状态机的全部内容,更多相关C++内容请搜索靠谱客的其他文章。

本图文内容来源于网友提供,作为学习参考使用,或来自网络收集整理,版权属于原作者所有。
点赞(65)

评论列表共有 0 条评论

立即
投稿
返回
顶部