基本数据类型
- 基本内置类型
- 定义变量
- `type field = value;`
- `type field(value);`
- `type field{value};`
- `type field = {value};`
- 数学常量及函数
- 静态类型转换 `static_cast`
- 格式化字符串
- `std::stringstream`
- `std::string`
- 引入三方库 `fmt/core.h`
- 字符运算
- `auto` 关键字
- 枚举类型
- 数据类型定义别名
- 判断是否为NaN
- 三向比较运算符(太空飞船运算符)
- 多维数组
- 避免幻数
- 运行期间为数组分配内存空间
- 数组的替代品
- `std::array`
- `std::vector`
基本内置类型
#include <iostream>
using namespace std;
int main() {
cout << "数据类型" << "\t\t" << "所占字节" << "\t" << "最小值" << "\t\t\t" << "最大值" << endl;
cout << "bool(布尔型)" << "\t\t" << sizeof(bool) << "\t\t" << numeric_limits<bool>::min() << "\t\t\t" << numeric_limits<bool>::max() << endl;
cout << "char(字符型)" << "\t\t" << sizeof(char) << "\t\t" << numeric_limits<char>::min() << "\t\t\t" << numeric_limits<char>::max() << endl;
cout << "unsigned char" << "\t\t" << sizeof(unsigned char) << "\t" << numeric_limits<unsigned char>::min() << "\t" << numeric_limits<unsigned char>::max() << endl;
cout << "signed char" << "\t\t" << sizeof(signed char) << "\t\t" << numeric_limits<signed char>::min() << "\t\t\t" << numeric_limits<signed char>::max() << endl;
cout << "int(整型)" << "\t\t" << sizeof(int) << "\t\t" << numeric_limits<int>::min() << "\t\t" << numeric_limits<int>::max() << endl;
cout << "unsigned int" << "\t\t" << sizeof(unsigned int) << "\t\t" << numeric_limits<unsigned int>::min() << "\t\t\t" << numeric_limits<unsigned int>::min() << endl;
cout << "signed int" << "\t\t" << sizeof(signed int) << "\t\t" << numeric_limits<signed int>::min() << "\t\t" << numeric_limits<signed int>::max() << endl;
cout << "short int" << "\t\t" << sizeof(short int) << "\t\t" << numeric_limits<short int>::min() << "\t\t\t" << numeric_limits<short int>::max() << endl;
cout << "unsigned short int" << "\t" << sizeof(unsigned short int) << "\t\t" << numeric_limits<unsigned short int>::min() << "\t\t\t" << numeric_limits<unsigned short int>::max() << endl;
cout << "signed short int" << "\t" << sizeof(signed short int) << "\t\t" << numeric_limits<signed short int>::min() << "\t\t\t" << numeric_limits<signed short int>::max() << endl;
cout << "long int" << "\t\t" << sizeof(long int) << "\t\t" << numeric_limits<long int>::min() << "\t" << numeric_limits<long int>::max() << endl;
cout << "unsigned long int" << "\t" << sizeof(unsigned long int) << "\t\t" << numeric_limits<unsigned long int>::min() << "\t\t\t" << numeric_limits<unsigned long int>::max() << endl;
cout << "signed long int" << "\t\t" << sizeof(signed long int) << "\t\t" << numeric_limits<signed long int>::min() << "\t" << numeric_limits<signed long int>::max() << endl;
cout << "float(浮点型)" << "\t\t" << sizeof(float) << "\t\t" << numeric_limits<float>::min() << "\t\t" << numeric_limits<float>::max() << endl;
cout << "double(双浮点型)" << "\t" << sizeof(double) << "\t\t" << numeric_limits<double>::min() << "\t\t" << numeric_limits<double>::max() << endl;
cout << "long double" << "\t\t" << sizeof(long double) << "\t\t" << numeric_limits<long double>::min() << "\t\t" << numeric_limits<long double>::max() << endl;
cout << "wchar_t(宽字符型)" << "\t" << sizeof(wchar_t) << "\t\t" << numeric_limits<wchar_t>::min() << "\t\t" << numeric_limits<wchar_t>::max() << endl;
return 0;
}
定义变量
type field = value;
这是最常见的初始化语法,使用等号来将value赋值给field。这种方式允许发生隐式类型转换,并且不会进行列表初始化检查。
#include <iostream>
using namespace std;
int main() {
int a = 1;
int b = 1.5;
cout << a << endl; // 1
cout << b << endl; // 1
return 0;
}
type field(value);
这种初始化方式使用括号进行初始化。它类似于使用等号进行初始化,允许发生隐式类型转换,不进行列表初始化检查。
#include <iostream>
using namespace std;
int main() {
int a(1);
int b(1.56);
cout << a << endl; // 1
cout << b << endl; // 1
return 0;
}
type field{value};
这种初始化方式使用花括号,被称为列表初始化。它提供了更严格的类型检查,并且不允许发生窄化转换(narrowing conversion)。如果存在可能发生精度损失或信息丢失的情况,编译器会产生错误。
#include <iostream>
using namespace std;
int main() {
int a{1}; // int a{1.5}; error
cout << a << endl; // 1
return 0;
}
type field = {value};
这种初始化方式也使用等号和花括号,被称为统一初始化。它类似于列表初始化,提供了更严格的类型检查,并且不允许窄化转换。与type field{value}; 的区别在于,等号和花括号之间可以有空格。
#include <iostream>
using namespace std;
int main() {
int a = {1}; // int a = {1.5}; error
cout << a << endl; // 1
return 0;
}
数学常量及函数
#include <iostream>
#include <numbers>
using namespace std;
int main() {
cout << "自然对数的底\t\t\t" << numbers::e << endl;
cout << "圆周率\t\t\t\t" << numbers::pi << endl;
cout << "2的平方根\t\t\t" << numbers::sqrt2 << endl;
cout << "黄金比例常量\t\t\t" << numbers::phi << endl;
cout << "绝对值\t\t\t\t" << abs(-1.23) << endl;
cout << "大于或等于参数的最小整数\t" << ceil(-1.23) << endl;
cout << "小于或等于参数的最大整数\t" << floor(-1.23) << endl;
cout << "计算e^参数\t\t\t" << exp(1) << endl;
cout << "计算底为e的参数的自然对数\t" << log(exp(1)) << endl;
cout << "计算底为10的参数的自然对数\t" << log10(100) << endl;
cout << "幂\t\t\t\t" << pow(2, 10) << endl;
cout << "平方根\t\t\t\t" << sqrt(9) << endl;
cout << "四舍五入\t\t\t" << round(-12.54) << endl;
return 0;
}
静态类型转换 static_cast
强制转换为另一种数据类型的值,转换过程中不进行任何运行时类型检查,因此可能导致运行时错误,通常用于比较类型相似的对象之间的转换,如int转float
#include <iostream>
using namespace std;
int main() {
float a = 1.23;
int b = static_cast<int>(a);
cout << a << " 类型:" << typeid(a).name() << endl; // 1.23 类型:f
cout << b << " 类型:" << typeid(b).name() << endl; // 1 类型:i
return 0;
}
格式化字符串
std::stringstream
#include <iostream>
#include <sstream>
using namespace std;
int main() {
int age = 18;
char name[] = "Lee";
stringstream msg;
msg << "Hello, " << name << "!!! " << age << "!!!";
cout << msg.str() << endl; // Hello, Lee!!! 18!!!
return 0;
}
std::string
#include <iostream>
using namespace std;
int main() {
int age = 18;
string name = "Lee";
string msg = "Hello, " + name + "!!! " + to_string(age) + "!!!";
cout << msg << endl; // Hello, Lee!!! 18!!!
return 0;
}
引入三方库 fmt/core.h
下载
https://github.com/fmtlib/fmt.git
引入 c-app/CMakeLists.txt
cmake_minimum_required(VERSION 3.25)
project(c_app)
set(CMAKE_CXX_STANDARD 20)
add_executable(c_app ../main.cpp)
# 添加fmt库目录
add_subdirectory(../libs/fmt-10.0.0)
# 链接fmt库
target_link_libraries(c_app fmt::fmt)
运行
#include <iostream>
#include "libs/fmt-10.0.0/include/fmt/core.h"
using namespace std;
int main() {
char name[] = "Lee";
double height = 1.8123456;
int age = 18;
string msg = fmt::format("Hello, {}! Height: {:.2f}! Age: {}!", name, height, age);
cout << msg << endl; // Hello, Lee! Height: 1.81! Age: 18!
return 0;
}
字符运算
#include <iostream>
#include "libs/fmt-10.0.0/include/fmt/core.h"
using namespace std;
int main() {
char word = 'A';
string msg = fmt::format("字符: {} \n表示字符的整数代码: {} \n整数转字符: {}", word, word + 1, static_cast<char>(word + 2));
/**
* 字符: A
* 表示字符的整数代码: 66
* 整数转字符: C
*/
cout << msg << endl;
return 0;
}
auto
关键字
用于自动推断变量类型
#include <iostream>
#include "libs/fmt-10.0.0/include/fmt/core.h"
using namespace std;
int main() {
auto a = 1;
auto b = {2};
auto c{3};
/**
* a: i
* b: St16initializer_listIiE
* c: i
*/
cout << fmt::format("a: {}\nb: {}\nc: {}", typeid(a).name(), typeid(b).name(), typeid(c).name()) << endl;
return 0;
}
枚举类型
#include <iostream>
#include "libs/fmt-10.0.0/include/fmt/core.h"
using namespace std;
/**
* 枚举类型Color
*/
enum class Color {
red, green = 3, blue
} color;
/**
* 枚举类型Mode
*/
enum class Mode : char {
create = 'C',
del = 'D',
edit = 'U',
search = 'Q'
};
int main() {
cout << static_cast<int>(color) << endl; // 0
color = Color::red;
cout << static_cast<int>(color) << endl; // 0
color = Color::green;
cout << static_cast<int>(color) << endl; // 3
color = Color::blue;
cout << static_cast<int>(color) << endl; // 4
Color c1 = Color::red;
Color c2 = Color::green;
Color c3 = Color::blue;
cout << fmt::format("c1: {}, c2: {}, c3: {}", static_cast<int>(c1), static_cast<int>(c2), static_cast<int>(c3)) << endl; // c1: 0, c2: 3, c3: 4
Mode mode{Mode::edit};
cout << fmt::format("mode: {}, {}", static_cast<char>(mode), static_cast<int>(mode)) << endl; // mode: U, 85
return 0;
}
数据类型定义别名
#include <iostream>
#include "libs/fmt-10.0.0/include/fmt/core.h"
// 别名方式1
using str1 = std::string;
// 别名方式2
typedef char str2;
int main() {
str1 say = "Hello";
str2 name[] = "Lee";
std::cout << fmt::format("{}, {}!!!", say, name) << std::endl; // Hello, Lee!!!
return 0;
}
判断是否为NaN
#include <iostream>
#include "libs/fmt-10.0.0/include/fmt/core.h"
#include <numbers>
using namespace std;
int main() {
double pi = numbers::pi;
double num = sqrt(-1);
cout << fmt::format("pi: {}, num: {}", pi, num) << endl; // pi: 3.141592653589793, num: nan
cout << fmt::format("pi: {}, num: {}", isnan(pi), isnan(num)) << endl; // pi: false, num: true
return 0;
}
三向比较运算符(太空飞船运算符)
a <=> b
返回枚举类型equal(等于)
equivalent(等于)
greater(大于)
less(小于)
unordered(NaN相等)
比较类型 | less | greater | equal | equivalent | unordered | 用于 |
---|---|---|---|---|---|---|
strong_ordering | YES | YES | YES | YES | NO | 整数和指针 |
partial_ordering | YES | YES | NO | YES | YES | 浮点数 |
weak_ordering | YES | YES | NO | YES | NO | 仅用于用户自定义的运算符 |
#include <iostream>
#include "libs/fmt-10.0.0/include/fmt/core.h"
using namespace std;
int main() {
double a = numeric_limits<double>::quiet_NaN(); // nan
double b = numeric_limits<double>::quiet_NaN(); // nan
partial_ordering c{a <=> b};
if (c == strong_ordering::equal) {
cout << "a = b" << endl;
} else if (c == strong_ordering::equivalent) {
cout << "两个值在强序比较中是等价的" << endl;
} else if (c == strong_ordering::greater) {
cout << "a > b" << endl;
} else if (c == strong_ordering::less) {
cout << "a < b" << endl;
}
if (c == partial_ordering::unordered) {
cout << fmt::format("a: {}, b: {}", isnan(a), isnan(b)) << endl; // a: true, b: true
}
if (is_eq(c)) {
cout << "a = b" << endl;
}
if (is_gt(c)) {
cout << "a > b" << endl;
}
if (is_gteq(c)) {
cout << "a >= b" << endl;
}
if (is_lt(c)) {
cout << "a < b" << endl;
}
if (is_lteq(c)) {
cout << "a <= b" << endl;
}
return 0;
}
多维数组
#include <iostream>
#include "libs/fmt-10.0.0/include/fmt/core.h"
using namespace std;
int main() {
int list[3][3] = {
{1, 2, 3},
{4, 5, 6},
{7, 8, 9}
};
for (int i = 0; i < size(list); ++i) {
for (int j = 0; j < size(list[i]); ++j) {
cout << fmt::format("{} ", list[i][j]); // 1 2 3 4 5 6 7 8 9
}
}
for (auto &a: list) {
for (int b: a) {
cout << fmt::format("{} ", b); // 1 2 3 4 5 6 7 8 9
}
}
return 0;
}
避免幻数
幻数是指在代码中直接使用一些未经解释的常数值,这样的代码可读性较差,且不易于维护和理解,示例如下:
#include <iostream>
#include "libs/fmt-10.0.0/include/fmt/core.h"
using namespace std;
int main() {
int list[3]{1, 2, 3};
for (int i = 0; i < size(list) + 5; ++i) {
/**
* 结果:
* 1 2 3 1 -1445723955 -250088645 0 0
* 1 2 3 1 1461452947 457358528 0 0
* 1 2 3 1 805896392 1713566091 0 0
*/
cout << fmt::format("{} ", list[i]);
}
return 0;
}
运行期间为数组分配内存空间
可变的数组长度
#include <iostream>
#include "libs/fmt-10.0.0/include/fmt/core.h"
using namespace std;
int main() {
int count;
cin >> count; // 8
int list[count];
for (int i = 0; i < count; ++i) {
list[i] = i + 1;
}
for (int num: list) {
cout << fmt::format("{} ", num); // 1 2 3 4 5 6 7 8
}
return 0;
}
数组的替代品
std::array
#include <iostream>
#include "libs/fmt-10.0.0/include/fmt/core.h"
using namespace std;
int main() {
/* ========= list1 =========*/
array<int, 5> list1 = {1, 2, 3, 4, 5};
for (int d: list1) {
cout << d; // 1 2 3 4 5
}
/* ========= list2 =========*/
auto list2 = array{1, 2, 3, 4, 5}; // 根据值推断模版参数
cout << list2.size(); // 5
cout << list2.at(3); // 4
cout << list2[2]; // 3
list2.fill(3);
for (double d: list2) {
cout << d; // 3 3 3 3 3
}
return 0;
}
比较
相等
:比较每个元素均相等
不等
:只要存在不等即不等
大于
:第一个元素进行比较然后返回对应判断
小于
:第一个元素进行比较然后返回对应判断
#include <iostream>
#include "libs/fmt-10.0.0/include/fmt/core.h"
using namespace std;
int main() {
array<int, 5> l = {1, 2, 3, 4, 5};
array<int, 5> a = {1, 2, 3, 4, 5}; // l == a
array<int, 5> b = {5, 4, 3, 2, 1}; // l < b
array<int, 5> c = {3, 2, 1, 5, 4}; // l < c
array<int, 5> d = {6, 6, 6, 6, 6}; // l < d
array<int, 5> e = {0, 0, 1, 0, 0}; // l > e
return 0;
}
std::vector
#include <iostream>
#include "libs/fmt-10.0.0/include/fmt/core.h"
using namespace std;
int main() {
/* ====== list1 ====== */
vector<int> list1 = {1, 2, 3, 4, 5};
// push一个元素
list1.push_back(6);
// 数组长度
cout << list1.size() << endl; // 6
for (int num: list1) {
cout << num; // 1 2 3 4 5 6
}
// 删除最后一个元素
list1.pop_back();
for (int num: list1) {
cout << num; // 1 2 3 4 5
}
/* ====== list2 ====== */
vector list2(1, 6); // 1 到 6
for (int num: list2) {
cout << num; // 1 2 3 4 5 6
}
list2.assign(3, 1); // 3 个 1
for (int num: list2) {
cout << num; // 1 1 1
}
list2.assign({6, 2, 3, 4, 5});
for (int num: list2) {
cout << num; // 6 2 3 4 5
}
/* ====== list3 ====== */
vector<int> list3{7, 6, 2, 3, 3, 6, 3, 8};
erase(list3, 3);
for (int num: list3) {
cout << num; // 7 6 2 6 8
}
list3.empty(); // 清空但保留长度
cout << list3.size(); // 5
list3.clear(); // 清空
cout << list3.size(); // 0
return 0;
}