# 2. 数据类型 DataType
# 1. 数字
# 1.1. 定义
整型
整型 长度 short 至少 16 位 int 至少与 short 一样 long 至少 32 位 long long 至少 64 位 unsigned 无符号整数 const 静态变量 // 获取当前系统变量长度 #include <iostream> #include <climits> using namespace std; int main() { short n_short = SHRT_MAX; int n_int = INT_MAX; long n_long = LONG_MAX; long long n_ll = LONG_LONG_MAX; cout << "Short is " << sizeof(n_short) << " bytes. " << "Range in [" << SHRT_MIN << ", " << SHRT_MAX << "]" << endl; cout << "Int is " << sizeof(n_int) << " bytes. " << "Range in [" << INT_MIN << ", " << INT_MAX << "]" << endl; cout << "Long is " << sizeof(n_long) << " bytes. " << "Range in [" << LONG_MIN << ", " << LONG_MAX << "]" << endl; cout << "Long Long is " << sizeof(n_long) << " bytes. " << "Range in [" << LONG_LONG_MIN << ", " << LONG_LONG_MAX << "]" << endl; return 0; } // 输出 Short is 2 bytes. Range in [-32768, 32767] Int is 4 bytes. Range in [-2147483648, 2147483647] Long is 4 bytes. Range in [-2147483648, 2147483647] Long Long is 4 bytes. Range in [-9223372036854775808, 9223372036854775807]
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24浮点数
浮点 位数 float 至少 32 位 double 至少 64 位 long double 80, 96 或 128 位
# 1.2. 计算
整数相除
int a = 5; int b = 4; int c = a / b; // 1 double d = ((double)a / b); // 1.25 float e = ((float)a / b); // 1.25
1
2
3
4
5浮点相除
#include "math.h" float a = 3.2; float b = 17.2; // 浮点取整 int c = b / a; // 5 // 浮点取余 float d = fmod(b, a); // 1.2 // 浮点相除 float e = b / a; // 5.375
1
2
3
4
5
6
7
8
9
10取整
#include "math.h" // 向下取整 floor(10.3) // 10 floor(10.7) // 10 floor(-2.6) // -3 // 向上取整 ceil(10.3) // 11 ceil(-2.6) // -2 // 四舍五入 round(10.3) // 10 round(10.7) // 11
1
2
3
4
5
6
7
8
9
10
11
12求绝对值
#include "math.h" // 整型 int abs(int i); // 复数 double cabs(struct complex znum); // 浮点/双精度浮点 double fabs(double x); // 长整型 long labs(long n);
1
2
3
4
5
6
7
8
9
10三元操作符 ?:
// 条件表达式 ? 表达式 1 : 表达式 2; // 满足条件时执行执行表达式 1,不满足时执行表达式 2; int x = 1; x = x > 0 ? x + 1 : x - 1; // 2
1
2
3
4
5
# 1.3. 位操作&逻辑运算
# 1.4. 枚举 ENUM
语法
enum <类型名> {<枚举常量表>};
1示例
enum week { sun=10, // 不设的话默认 0 mon, tue }; int main(int argc, char const *argv[]) { printf("%d\n", sun); // 10 printf("%d\n", mon); // 11 printf("%d\n", tue); // 12 return 0; }
1
2
3
4
5
6
7
8
9
10
11
12
13
14
# 1.5. 随机数
随机整数
#include <random> #include <iostream> int main() { std::random_device rd; // 获取随机种子 std::mt19937 gen(rd()); // 使用随机种子初始化随机数引擎 std::uniform_int_distribution<> dis(1, 100); // 定义随机数分布范围 // 生成并打印 10 个随机数 for(int n = 0; n < 10; ++n) { std::cout << dis(gen) << ' '; } std::cout << std::endl; return 0; }
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16随机小数
#include <iostream> #include <random> int main() { // 获取一个随机设备来用作随机数生成器的种子 std::random_device rd; // 使用随机设备作为种子初始化一个随机数引擎 std::mt19937 gen(rd()); // 定义一个在 [0.0, 1.0) 范围内均匀分布的随机数分布 std::uniform_real_distribution<> dis(0.0, 1.0); // 生成并打印一个随机小数 double random_float = dis(gen); std::cout << "Random float: " << random_float << std::endl; // 如果你需要生成多个随机小数,可以放在循环中 for(int i = 0; i < 5; ++i) { random_float = dis(gen); std::cout << "Random float: " << random_float << std::endl; } return 0; }
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
# 2. 数组
# 2.1. 数组定义
// 创建数组
int num[] = {1, 2, 3};
int num[3] = {1, 2, 3};
float temperature[10];
sizeof(num)/sizeof(num[0]); // 数组长度
// 字符串数组
char *str_list[] = {"abc", "def"};
cout << str_list[0] << endl; // abc
1
2
3
4
5
6
7
8
9
10
11
2
3
4
5
6
7
8
9
10
11
# 2.2. 改查
改
// 修改元素 num[0] = 10;
1
2查
// 单个查询 cout << num[0] << endl; // 遍历 for (int i : num) { cout << i << endl; } // 查询数组中的最大最小值 #include <algorithm> int max = *max_element(num, num + sizeof(num)/sizeof(num[0])); // 最大值 int max_p = max_element(num, num + sizeof(num)/sizeof(num[0])) - num; // 最大值所在位置
1
2
3
4
5
6
7
8
9
10
11
12
# 2.3. 计算
生成数组的全部排列组合形式
#include <algorithm> #include <iostream> using namespace std; int main() { int arr[] = {1, 2, 3}; int n = sizeof(arr) / sizeof(arr[0]); // sort(arr, arr+n); cout << "所有排列组合:\n"; do { for (int i = 0; i < n; i++) cout << arr[i] << " "; cout << endl; } while (next_permutation(arr, arr + n)); return 0; }
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
# 3. 静态数组 Array
array(c++11):与数组一样,array 对象的长度也是固定的,也是用栈(静态内存分配),而不是自由存储区,因此其效率与数组相同,但更方便,更安全。
创建 array:
array<typeName, number> name = {};
#include <array> using namespace std; array<int, 5> num_list{}; // 或 array<int, 5> num_list = {0, 1, 2, 3, 4}; // 遍历 for (int i:num_list) { cout << i << endl; }
1
2
3
4
5
6
7
8
9
10
11
12
# 4. 字符串 Char & String
# 4.1. 创建字符串
Char
char c1[] = "abc"; char c2[4] = "abc"; // 结尾有'\0', 所以占 4 字节 char *c3 = "abc";
1
2
3String
// 头文件 #include <string> using namespace std; string s1 = "what is your name" string s2 = "is"
1
2
3
4
5
6
# 4.2. 访问
访问
// 访问 cout << s1[1] << endl; // char 类型
1
2遍历
# 4.3. 增
插入
s1.insert(int num, string s) // 在 num 位置插入 s
1追加
s1.append(string s) // 追加字符串 s1.append(int n, char c) // 追加 n 个 c 字符 // strcat(不推荐,有内存泄露风险) char a[10] = "abc"; char b[5] = "fbs"; strcat(a, b); // a = "abcfbs" // strncat(推荐) char *strncat(char *dest, const char *src, size_t n); strncat(a, b, sizeof(a)); // sprintf(不推荐,有内存泄露风险) sprintf(a, "%s%s", a, b); // snprintf(推荐) snprintf(a, sizeof(a), "%s%s", a, b);
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15拼接
int i = 5; string s = "station: " + to_string(i);
1
2拷贝
strcpy(c1, c2); // (不推荐,有内存泄露风险) strncpy(c1, c2, sizeof(c1)); // 安全模式 strncpy(c1, c2+3, 5); // 截取 c2 第 3 个字符后的 5 个字符到 c1 中 #include <string.h> strcpy(s1, s2) // 把 s2 拷贝到 s1 中
1
2
3
4
5
# 4.4. 删
清空
memset(a, 0, sizeof(a))
1删除
s1.erase(int a, int b) // 删除 a 之后的 b 个字符
1
# 4.5. 改
替换
s1.replace(int num1, int num2, string s) // 用 s 替换 num1 后面的 num2-1 个字符 s1.replace(int num1, int num2, string s, int num3, int num4) // 用 s 的第 num3 后面的 num4-1 个字符替换 num1 后面的 num2-1 个字符
1
2截取
strncpy(c1, c2 + 3, 5); // 截取 c2 第 3 个字符后的 5 个字符到 c1 中 s2 = s1.substr(int a, int b) // 起始位 a,长度 b s2 = s1.substr(int a) // 截取第 a 个之后的字符串
1
2
3大小写转换
// char char c1[64], C1[64]; C1 = strupr(c1); // 转大写 win c1 = strlwr(C1); // 转小写 win for (char *ptr = c1; *c1; ptr++) { *ptr = toupper(*ptr); // 转大写 linux *ptr = tolower(*ptr); // 转小写 linux } // string transform(str.begin(), str.end(), str.begin(), (int (*)(int))tolower); // 转小写 transform(str.begin(), str.end(), str.begin(), (int (*)(int))toupper); // 转大写 // 或 transform(str.begin(), str.end(), str.begin(), ::tolower); // 转小写 transform(str.begin(), str.end(), str.begin(), ::toupper); // 转大写
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
# 4.6. 查
字符查询
// 查找 s1.find(s2); // 返回起始位置或-1,大小写敏感 if (s1.find(s2) == string::npos){ // string::npos 常用作没有匹配到内容的判定结果 cout << "Can't find " << s2 << endl; } s1.rfind(s2); // 从后往前查找,其他同上 s1.find_first_of(s2); // 查找 s2 第一次出现的位置 s1.find_last_of(s2); // 查找 s2 最后一次出现的位置 s1.find_first_not_of(s2); // 在 s1 中查找第一个不再 s2 中的字符 s1.find_last_not_of(s2); // 与上面相似 p = strchr(s1, s2); // 查找 s2 在 s1 中第一次出现的位置
1
2
3
4
5
6
7
8
9
10
11
12
13长度查询
strlen(c1); // char s1.length(); // string
1
2判断字符串为空
// char if (strlen(c1) == 0) // 或 if (c1[0] == '\0') // String if (s1.empty()) // 或 if (s1 == "")
1
2
3
4
5
6
7
8
9
# 4.7. 其他操作
比较
// 比较 s1.compare(s2); // 大于:1;小于:-1;等于:0 strcmp(s1, s2); // 同上 strcmp(c1, c2); // 同上 // 比较两个字符串的前 n 个字符 strncmp(c1, c2, n);
1
2
3
4
5
6
7分割 split 参考🔗 (opens new window)
/* c++11 以前没有通用的字符串分割程序 */ // 字符串分割函数:要分割的字符串 s_in, 分割结果 s_out, 分隔符 delimiter void split(const string &s_in, vector<string> &s_out, const string &delimiter = " ") { s_out.clear(); string s = s_in; // 创建一个可修改的副本 // 去除 s 中的所有空格 if (delimiter != " ") { s.erase(std::remove_if(s.begin(), s.end(), ::isspace), s.end()); } string::size_type lastPos = s.find_first_not_of(delimiter, 0); string::size_type pos = s.find_first_of(delimiter, lastPos); while (string::npos != pos || string::npos != lastPos) { s_out.push_back(s.substr(lastPos, pos - lastPos)); lastPos = s.find_first_not_of(delimiter, pos); pos = s.find_first_of(delimiter, lastPos); } }
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22格式化读取 sscanf
char c[64] = "2022-02-28 16:47:00"; int year, month, day, hour, minute, second; sscanf(c, "%d-%d-%d %d:%d:%d", &year, &month, &day, &hour, &minute, &second);
1
2
3
4
# 5. 日期时间
# 5.1. 时间格式
time_t: 本质为长整型 (long)
#include <time.h> // 或 ctime time_t now = time(0); // 获取系统当前时间,0 或 NULL
1
2tm 格式
tm 结构
struct tm { int tm_sec; // 秒,正常范围从 0 到 59,但允许至 61 int tm_min; // 分,范围从 0 到 59 int tm_hour; // 小时,范围从 0 到 23 int tm_mday; // 一月中的第几天,范围从 1 到 31 int tm_mon; // 月,范围从 0 到 11 int tm_year; // 自 1900 年起的年数 int tm_wday; // 一周中的第几天,范围从 0 到 6,从星期日算起 int tm_yday; // 一年中的第几天,范围从 0 到 365,从 1 月 1 日算起 int tm_isdst; // 夏令时 }
1
2
3
4
5
6
7
8
9
10
11tm 参数传递
#include <time.h> void use_tm(struct tm *now_tm){ // code here } int main(){ tm *now_tm; time_t now = time(0); now_tm = localtime(&now); use_tm(now_tm); }
1
2
3
4
5
6
7
8
9
10
11
12
# 5.2. 时间转换
time_t <-> tm
/* time_t -> tm */ time_t t = time(0); tm *tm1 = localtime(&t); // 不能连续使用 // 连续使用需要用 localtime_s(Win) 或 localtime_r(Linux) tm tm1; localtime_s(&tm1, &t); // Win localtime_r(&t, &tm1); // Linux
1
2
3
4
5
6
7
8/* tm -> time_t */ time_t t = mktime(&tm1); // 不能连续使用
1
2string 转 time_t
#include <string> #include <ctime> // string 转 time_t time_t str_to_time(const string &str) { char *c = (char *)str.data(); // string 转 char* tm tm1; int year, month, day, hour, minute, second; sscanf(c, "%d-%d-%d %d:%d:%d", &year, &month, &day, &hour, &minute, &second); tm1.tm_year = year - 1900; // 年份,从 1900 年开始 tm1.tm_mon = month - 1; // 月份,范围 0-11 tm1.tm_mday = day; tm1.tm_hour = hour; tm1.tm_min = minute; tm1.tm_sec = second; tm1.tm_isdst = 0; time_t t = mktime(&tm1); return t; }
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19time_t 转 string
// time_t 转 string string time2string(const time_t t) { tm ltm; localtime_r(&t, <m); // linux char c[256]; snprintf(c, sizeof(c), "%04d-%02d-%02d %02d:%02d:%02d", ltm.tm_year + 1900, ltm.tm_mon + 1, ltm.tm_mday, ltm.tm_hour, ltm.tm_min, ltm.tm_sec); string str = c; return str; }
1
2
3
4
5
6
7
8
9
10time_t 转 Char
// 推荐使用 strftime, 注意不要漏掉& char t_char[64]; strftime(t_char, sizeof(t_char), "%Y-%02m-%02d %02H:%02M:%02S", localtime(&time(0))); // 使用 localtime_r tm t_tm; localtime_r(&time(0), &t_tm); strftime(t_char, sizeof(t_char), "%Y-%02m-%02d %02H:%02M:%02S", &t_tm); // time_t 转 char char *Time2Char(time_t t) { static char t_char[64]; // static 必须 tm t_tm; localtime_r(&t, &t_tm); snprintf(t_char, sizeof(t_char), "%04d-%02d-%02d %02d:%02d:%02d", t_tm.tm_year + 1900, t_tm.tm_mon + 1, t_tm.tm_mday, t_tm.tm_hour, t_tm.tm_min, t_tm.tm_sec); return t_char; }
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19日期格式化
strftime
, 参考链接🔗 (opens new window)#include <ctime> time_t now = time(0); char tm_str[32]; // 字符串,复制最大字符数,format, 指向 tm 结构的指针 strftime(tm_str, 32, "%Y-%m-%d %H:%M:%S", localtime(&now));
1
2
3
4
5
6
7符号 说明 示例 %a 缩写的星期几名称 Sun %A 完整的星期几名称 Sunday %b 缩写的月份名称 Mar %B 完整的月份名称 March %c 日期和时间表示法 Sun Aug 19 02:56:02 2012 %d 一月中的第几天(01-31) 19 %H 24 小时格式的小时(00-23) 14 %I 12 小时格式的小时(01-12) 05 %j 一年中的第几天(001-366) 231 %m 十进制数表示的月份(01-12) 08 %M 分(00-59) 55 %p AM 或 PM 名称 PM %S 秒(00-61) 02 %U 一年中的第几周以第一个星期日作为第一周的第一天(00-53) 33 %w 十进制数表示的星期几,星期日表示为 0(0-6) 4 %W 一年中的第几周以第一个星期一作为第一周的第一天(00-53) 34 %x 日期表示法 08/19/12 %X 时间表示法 02:50:06 %y 年份,最后两个数字(00-99) 01 %Y 年份 2012 %Z 时区的名称或缩写 CDT %% 一个 % 符号 %
# 5.3. 时间使用
延时
// Linux sleep(5); // 延时 5 秒 usleep(5); // 延时 5 微秒
1
2
3
# 6. 类型转换
# 6.1. 数字 -> 字符串
to_string(i)
(c++11)sprintf
char c[256]; float pi = 3.14; sprintf(c, "Pi = %f", pi); // 格式化字符串
1
2
3常用
# 6.2. 字符串 -> 数字
stoi
和stof
(c++11)// c++ 11 以上限定 int i = stoi(str); float f = stof(str);
1
2
3c++11 以下
// c++11 以下 string s1 = "123"; char *c1 = "123.45"; int i = atoi(s1.c_str()); float j = atof(c1); long k = atol(c1);
1
2
3
4
5
6
# 6.3. char <-> string
// char -> string
char *c1 = "abc";
string str1 = c1;
// string ->char
char *c1 = str1.c_str();
// string -> char*
char *c1 = (char*)str1.data();
1
2
3
4
5
6
7
2
3
4
5
6
7
# 6.4. ASCII 码转换
字符 <-> int
string s = (char) (n + 64); int n = (int)('a')
1
2
# 7. json
# 7.1. json.h 库
- 头文件
json/json.h
- 动态库
-ljson
# 7.2. json 构建
c++ 构建 json
Json::Value jsonObject; jsonObject["name"] = name; jsonObject["value"] = value; Json::StyledWriter writer; string json_str = writer.write(jsonObject);
1
2
3
4
5
6string 转 json
#include "json/json.h" using namespace json; int main() { string json_str = R"({"name": "John", "age": 30, "city": "New York"})"; Value j = parse(json_str); // string 转 json string name = j["name"].asString(); int age = j["age"].asInt(); string city = j["city"].asString(); cout << "name: " << name << endl; cout << "age: " << age << endl; cout << "city: " << city << endl; return 0; } // 输出 // name: John // age: 30 // city: New York
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
# 7.3. json 解析
c++ 解析 json
#include "json/json.h" using namespace json; int main() { string json_str = R"({"name": "John", "age": 30, "city": "New York"})"; Value j; Reader reader; bool parsingSuccessful = reader.parse(json_str, j); if (!parsingSuccessful) { cout << "Failed to parse JSON" << endl; return 1; } string name = j["name"].asString(); int age = j["age"].asInt(); string city = j["city"].asString(); cout << "name: " << name << endl; cout << "age: " << age << endl; cout << "city: " << city << endl; return 0; } // 输出 // name: John // age: 30 // city: New York
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
# 7.4. json 遍历
遍历所有键值对
Json::Value root; if (!reader.parse(json_str, root)) { printr("Json parse error: %s", reader.getFormattedErrorMessages().c_str()); return; } for (Json::ValueConstIterator it = root.begin(); it != root.end(); ++it) { const std::string key = it.key().asString(); const Json::Value& value = *it; json_map[key] = value.asString(); printf(" key = %s, value = %s\n", key.c_str(), value.asString().c_str()); }
1
2
3
4
5
6
7
8
9
10
11
12
13
14
# 7.5. Json 转换
string 转 json 转 map
// 递归函数 void Json2Map(const Json::Value& root, map<string, string>& json_map) { for (Json::ValueConstIterator it = root.begin(); it != root.end(); ++it) { string key = it.key().asString(); const Json::Value& value = *it; switch (value.type()) { case Json::ValueType::objectValue: // 针对嵌套结构 Json2Map(&value, json_map); break; case Json::ValueType::stringValue: // 针对字符串 json_map[key] = value.asString(); printf(" key = %s, value = %s\n", key.c_str(), value.asString().c_str()); break; case Json::ValueType::intValue: // 整型 json_map[key] = to_string(value.asInt()); printf(" key = %s, value = %d\n", key.c_str(), value.asInt()); break; case Json::ValueType::realValue: // 浮点型 json_map[key] = to_string(value.asDouble()); printf(" key = %s, value = %f\n", key.c_str(), value.asDouble()); break; case Json::ValueType::arrayValue: { string temp_str; for (int i = 0; i < value.size(); i++) { temp_str += value[i].asString(); temp_str += ","; } if (!temp_str.empty()) { temp_str = temp_str.substr(0, temp_str.size() - 1); } json_map.insert(pair<string, string>(key, temp_str)); printf(" key = %s, value = %s\n", key.c_str(), temp_str.c_str()); break; } default: cout << "Value has an unknown or unsupported type. value = " << value << endl; break; } } } // 字符串 json 转 map void JsonStr2Map(const string& json_str, map<string, string>& json_map) { json_map.clear(); if (json_str.empty()) return; printy("\nreadStrJson: json_str = %s", json_str.c_str()); Json::Reader reader; Json::Value root; if (!reader.parse(json_str, root)) { printr(" Json parse error: %s", reader.getFormattedErrorMessages().c_str()); return; } // cout << root.toStyledString() << endl; Json2Map(root, json_map); }
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
# 8. 修饰符
# 8.1. extern
声明 extern 关键字的全局变量和函数可以使得它们能够跨文件被访问
extern "C": 在 C++中使用 C 语言
extern "C" { #include "cExample.h" //C++中使用 C 的函数和变量 }
1
2
3
4
# 8.2. const
# 8.3. static
← 1. C++ 环境配置 3. 数据结构 →