第2章:数据类型与变量

🎯 学习目标

完成本章学习后,您将能够:

  • ✅ 理解C/C++基本数据类型的分类和特点
  • ✅ 掌握变量的声明、初始化和作用域规则
  • ✅ 理解常量的定义和使用场景
  • ✅ 掌握类型转换的原理和方法
  • ✅ 学会选择合适的变量命名
  • ✅ 理解内存中数据的存储方式

📋 本章知识结构

数据类型与变量
├── 基本数据类型
│   ├── 整型家族(int, short, long, long long)
│   ├── 浮点型家族(float, double, long double)
│   ├── 字符型(char, wchar_t, char16_t, char32_t)
│   └── 布尔型(bool)
├── 变量基础
│   ├── 变量声明与定义
│   ├── 变量初始化
│   ├── 变量作用域
│   └── 变量生命周期
├── 常量与字面量
│   ├── 字面量常量
│   ├── const常量
│   ├── #define宏常量
│   └── constexpr常量
├── 类型转换
│   ├── 隐式类型转换
│   ├── 显式类型转换
│   └── 类型转换规则
└── 内存模型
    ├── 内存大小
    ├── 内存对齐
    └── 字节序

2.1 基本数据类型详解

2.1.1 整型家族

#include <iostream>
#include <climits>  // 整型限制常量
#include <cstdint>  // 固定宽度整型

int main() {
    // 基本整型
    int age = 25;                    // 通常32位
    short temperature = -10;         // 通常16位  
    long population = 1400000000L;   // 通常32位或64位
    long long big_number = 9000000000000000000LL; // 至少64位
    
    // 无符号整型
    unsigned int positive_value = 42U;
    unsigned short port = 8080U;
    unsigned long memory_size = 4294967295UL;
    unsigned long long huge_number = 18446744073709551615ULL;
    
    // 固定宽度整型(C++11)
    int8_t tiny = 127;      // 8位有符号
    uint16_t small = 65535; // 16位无符号
    int32_t medium = 2147483647; // 32位有符号
    uint64_t large = 18446744073709551615ULL; // 64位无符号
    
    return 0;
}

整型大小对照表

类型 典型大小 范围(有符号) 范围(无符号)
char 8位 -128 到 127 0 到 255
short 16位 -32,768 到 32,767 0 到 65,535
int 32位 -2,147,483,648 到 2,147,483,647 0 到 4,294,967,295
long 32/64位 平台相关 平台相关
long long 64位 -9,223,372,036,854,775,808 到 9,223,372,036,854,775,807 0 到 18,446,744,073,709,551,615

2.1.2 浮点型家族

#include <iostream>
#include <cfloat>  // 浮点限制常量
#include <cmath>   // 数学函数

int main() {
    // 单精度浮点
    float pi_float = 3.14159f;      // 通常32位,6-7位有效数字
    float e_float = 2.71828f;
    
    // 双精度浮点
    double pi_double = 3.141592653589793;  // 通常64位,15-16位有效数字
    double e_double = 2.718281828459045;
    
    // 扩展精度浮点
    long double pi_long_double = 3.141592653589793238L; // 通常80位或更多
    
    // 科学计数法
    float avogadro = 6.022e23f;     // 阿伏伽德罗常数
    double electron_mass = 9.109e-31; // 电子质量
    
    // 特殊值
    float infinity = std::numeric_limits<float>::infinity();
    double nan_value = std::numeric_limits<double>::quiet_NaN();
    
    return 0;
}

浮点型精度对照表

类型 典型大小 有效数字 范围
float 32位 6-7位 ~3.4e-38 到 ~3.4e+38
double 64位 15-16位 ~1.7e-308 到 ~1.7e+308
long double 80/128位 18-19位 平台相关

2.1.3 字符型

#include <iostream>
#include <cwchar>   // 宽字符支持

int main() {
    // 基本字符型
    char letter = 'A';           // ASCII字符
    char digit = '5';           // 字符数字
    char special = '@';         // 特殊字符
    char newline = '\n';         // 转义字符
    
    // 字符编码
    char ascii_char = 65;        // ASCII码65对应'A'
    unsigned char extended = 200; // 扩展ASCII
    
    // 宽字符(C++11)
    wchar_t wide_char = L'中';     // 宽字符
    char16_t utf16_char = u'你';   // UTF-16字符
    char32_t utf32_char = U'好';   // UTF-32字符
    
    // 字符串字面量
    const char* str = "Hello";
    const wchar_t* wstr = L"世界";
    const char16_t* u16str = u"UTF-16字符串";
    const char32_t* u32str = U"UTF-32字符串";
    
    // 原始字符串(C++11)
    const char* path = R"(C:\Program Files\MyApp\)";  // 无需转义
    const char* regex = R"(\d{3}-\d{3}-\d{4})";      // 正则表达式
    
    return 0;
}

2.1.4 布尔型

#include <iostream>

int main() {
    // 布尔类型
    bool is_student = true;
    bool has_passed = false;
    bool is_valid = 1;   // true
    bool is_empty = 0;   // false
    
    // 布尔表达式
    bool result = (5 > 3);        // true
    bool equal = (10 == 10);      // true
    bool not_equal = (5 != 3);    // true
    
    // 逻辑运算
    bool logical_and = true && false;  // false
    bool logical_or = true || false;   // true
    bool logical_not = !true;          // false
    
    // 隐式转换
    bool from_int = 42;     // true(非零)
    bool from_zero = 0;     // false
    bool from_float = 3.14; // true(非零)
    
    return 0;
}

2.2 变量基础

2.2.1 变量声明与定义

#include <iostream>

// 声明(declaration)- 告诉编译器变量的存在
extern int global_var;     // 声明全局变量
extern const int max_size; // 声明常量

// 定义(definition)- 为变量分配存储空间
int global_var = 42;      // 定义并初始化全局变量
const int max_size = 100;  // 定义常量

int main() {
    // 基本变量定义
    int count;                    // 未初始化(危险!)
    int total = 0;               // 定义并初始化
    double price{19.99};         // 统一初始化(C++11)
    int quantity{10};            // 统一初始化
    
    // 多个变量同时定义
    int x, y, z;                  // 三个未初始化的整型变量
    int a = 1, b = 2, c = 3;     // 三个初始化了的整型变量
    
    // auto类型推导(C++11)
    auto number = 42;           // int类型
    auto rate = 3.14;           // double类型
    auto text = "Hello";        // const char*类型
    
    return 0;
}

2.2.2 变量作用域

#include <iostream>

int global_var = 100;  // 全局变量

void function_scope() {
    int local_var = 200;  // 局部变量
    
    {  // 块作用域
        int block_var = 300;
        std::cout << "块内可见: " << block_var << std::endl;
        std::cout << "局部变量: " << local_var << std::endl;
        std::cout << "全局变量: " << global_var << std::endl;
    }
    
    // std::cout << block_var << std::endl;  // 错误:块变量不可见
}

int main() {
    // 全局作用域
    std::cout << "全局变量: " << global_var << std::endl;
    
    // 函数作用域
    function_scope();
    
    // 局部作用域
    int main_var = 400;
    
    // 块作用域
    for (int i = 0; i < 3; i++) {  // i只在循环内可见
        std::cout << "循环变量: " << i << std::endl;
    }
    
    // if语句块作用域
    if (true) {
        int if_var = 500;  // 只在if块内可见
        std::cout << "if变量: " << if_var << std::endl;
    }
    
    return 0;
}

2.2.3 变量生命周期

#include <iostream>

class VariableDemo {
private:
    int member_var;  // 成员变量,生命周期与对象相同
    
public:
    VariableDemo() : member_var(0) {
        std::cout << "成员变量创建: " << member_var << std::endl;
    }
    
    ~VariableDemo() {
        std::cout << "成员变量销毁: " << member_var << std::endl;
    }
    
    void demonstrateLifetime() {
        // 自动变量(栈变量)
        int auto_var = 100;  // 函数调用时创建,返回时销毁
        
        // 静态局部变量
        static int static_var = 200;  // 程序整个运行期间存在
        static_var++;
        
        std::cout << "自动变量: " << auto_var << std::endl;
        std::cout << "静态变量: " << static_var << std::endl;
    }
};

// 全局变量
int global_static = 300;  // 程序整个运行期间存在

int main() {
    std::cout << "=== 变量生命周期演示 ===" << std::endl;
    
    {  // 创建新的作用域
        VariableDemo demo;
        demo.demonstrateLifetime();
        demo.demonstrateLifetime();  // 静态变量会保持上次的值
    }  // demo对象在这里销毁
    
    // 动态分配变量(堆变量)
    int* dynamic_var = new int(400);  // 手动管理生命周期
    std::cout << "动态变量: " << *dynamic_var << std::endl;
    
    delete dynamic_var;  // 必须手动释放
    
    return 0;
}

2.3 常量与字面量

2.3.1 字面量常量

#include <iostream>

int main() {
    // 整数字面量
    int decimal = 42;        // 十进制
    int octal = 052;         // 八进制(以0开头)
    int hex = 0x2A;          // 十六进制(以0x开头)
    int binary = 0b101010;   // 二进制(C++14,以0b开头)
    
    // 浮点字面量
    double pi = 3.14159;     // 默认double
    float e = 2.71828f;      // float(以f结尾)
    long double big = 1.23L; // long double(以L结尾)
    
    // 科学计数法
    double big_num = 1.23e10;   // 1.23 × 10¹⁰
    double small_num = 1.23e-10; // 1.23 × 10⁻¹⁰
    
    // 字符字面量
    char letter = 'A';
    char newline = '\n';
    char tab = '\t';
    char unicode = u8'A';  // UTF-8字符(C++20)
    
    // 字符串字面量
    const char* str = "Hello, World!";
    const wchar_t* wstr = L"宽字符串";
    const char16_t* u16str = u"UTF-16字符串";
    const char32_t* u32str = U"UTF-32字符串";
    const char* raw_str = R"(原始字符串,无需转义)";
    
    // 布尔字面量
    bool is_true = true;
    bool is_false = false;
    
    // 空指针字面量(C++11)
    int* null_ptr = nullptr;
    
    return 0;
}

2.3.2 const常量

#include <iostream>

int main() {
    // 基本const变量
    const int max_size = 100;           // 编译时常量
    const double pi = 3.14159265359;    // 编译时常量
    const std::string app_name = "MyApp"; // 编译时常量
    
    // 运行时const变量
    int user_input;
    std::cin >> user_input;
    const int user_const = user_input;  // 运行时确定
    
    // const与指针
    int value = 42;
    const int* ptr1 = &value;      // 指向常量的指针(不能修改值)
    int* const ptr2 = &value;      // 常量指针(不能修改地址)
    const int* const ptr3 = &value; // 指向常量的常量指针
    
    // const与函数参数
    void printValue(const int& val);      // 引用参数,保证不被修改
    void processArray(const int arr[], int size); // 数组参数,保证不被修改
    
    // const与成员函数
    class MyClass {
    private:
        int data;
        mutable int access_count;  // 即使在const函数中也可修改
        
    public:
        int getData() const {      // const成员函数
            access_count++;        // 可以修改mutable成员
            return data;           // 不能修改非mutable成员
        }
    };
    
    return 0;
}

2.3.3 #define宏常量

#include <iostream>

// 宏常量定义
#define PI 3.14159265359
#define MAX_SIZE 100
#define APP_NAME "MyApplication"
#define VERSION_MAJOR 1
#define VERSION_MINOR 0
#define VERSION_STRING "1.0.0"

// 带参数的宏
#define SQUARE(x) ((x) * (x))
#define MAX(a, b) ((a) > (b) ? (a) : (b))
#define ABS(x) ((x) >= 0 ? (x) : -(x))

// 条件编译宏
#ifdef DEBUG
    #define LOG(msg) std::cout << "[DEBUG] " << msg << std::endl
#else
    #define LOG(msg)
#endif

// 字符串化宏
#define STRINGIFY(x) #x
#define TO_STRING(x) STRINGIFY(x)

int main() {
    // 使用宏常量
    std::cout << "PI = " << PI << std::endl;
    std::cout << "Max size = " << MAX_SIZE << std::endl;
    std::cout << "App name = " << APP_NAME << std::endl;
    
    // 使用宏函数
    int a = 5, b = 3;
    std::cout << "SQUARE(" << a << ") = " << SQUARE(a) << std::endl;
    std::cout << "MAX(" << a << ", " << b << ") = " << MAX(a, b) << std::endl;
    std::cout << "ABS(-42) = " << ABS(-42) << std::endl;
    
    // 使用调试宏
    LOG("程序开始执行");
    LOG("计算完成");
    
    // 字符串化
    std::cout << "Line number: " << TO_STRING(__LINE__) << std::endl;
    
    return 0;
}

2.3.4 constexpr常量(C++11)

#include <iostream>

// constexpr函数
constexpr int factorial(int n) {
    return n <= 1 ? 1 : n * factorial(n - 1);
}

// constexpr变量
constexpr int array_size = 10;
constexpr double gravity = 9.8;
constexpr int compile_time_value = factorial(5); // 120

class Circle {
private:
    double radius;
    
public:
    constexpr Circle(double r) : radius(r) {}
    
    constexpr double area() const {
        return 3.14159 * radius * radius;
    }
    
    constexpr double circumference() const {
        return 2 * 3.14159 * radius;
    }
};

int main() {
    // constexpr变量
    constexpr int max_items = 100;
    constexpr double pi = 3.14159265359;
    
    // 编译时计算
    constexpr int fact_5 = factorial(5);
    constexpr int fact_10 = factorial(10);
    
    std::cout << "5! = " << fact_5 << std::endl;
    std::cout << "10! = " << fact_10 << std::endl;
    
    // constexpr对象
    constexpr Circle unit_circle(1.0);
    constexpr double unit_area = unit_circle.area();
    constexpr double unit_circumference = unit_circle.circumference();
    
    std::cout << "单位圆面积: " << unit_area << std::endl;
    std::cout << "单位圆周长: " << unit_circumference << std::endl;
    
    // 编译时数组大小
    int numbers[array_size];  // array_size是编译时常量
    
    return 0;
}

2.4 类型转换

2.4.1 隐式类型转换

#include <iostream>

int main() {
    // 整型提升
    char ch = 'A';
    int i = ch;      // char自动提升为int
    std::cout << "char 'A' as int: " << i << std::endl;
    
    // 算术转换
    int a = 10;
    double b = 3.14;
    double result = a + b;  // int转换为double
    std::cout << "int + double = " << result << std::endl;
    
    // 赋值转换
    double pi = 3.14159;
    int approx_pi = pi;       // 截断小数部分
    std::cout << "double to int: " << approx_pi << std::endl;
    
    // 布尔转换
    int non_zero = 42;
    bool is_true = non_zero;  // 非零转换为true
    int zero = 0;
    bool is_false = zero;     // 零转换为false
    
    // 指针转换
    int* ptr = nullptr;       // nullptr可以转换为任何指针类型
    bool ptr_exists = ptr;    // 指针可以转换为bool
    
    return 0;
}

2.4.2 显式类型转换

#include <iostream>

int main() {
    // C风格转换(不推荐)
    double pi = 3.14159;
    int c_style = (int)pi;  // 截断小数部分
    
    // C++风格转换(推荐)
    
    // static_cast:基本类型转换
    double value = 42.7;
    int static_casted = static_cast<int>(value);  // 截断小数
    std::cout << "static_cast: " << static_casted << std::endl;
    
    // const_cast:去除const属性
    const int const_value = 100;
    int* non_const_ptr = const_cast<int*>(&const_value);
    // *non_const_ptr = 200;  // 未定义行为,不要这样做!
    
    // reinterpret_cast:重新解释位模式
    int int_value = 42;
    double* double_ptr = reinterpret_cast<double*>(&int_value);
    // 危险:int和double的内存布局不同
    
    // dynamic_cast:运行时类型检查(需要多态)
    // 将在面向对象章节详细讲解
    
    return 0;
}

2.4.3 类型转换最佳实践

#include <iostream>
#include <type_traits>  // 类型特征

template<typename T, typename U>
auto safe_divide(T numerator, U denominator) 
    -> decltype(numerator / denominator) {
    
    using result_type = decltype(numerator / denominator);
    
    if (denominator == 0) {
        throw std::runtime_error("除零错误");
    }
    
    return static_cast<result_type>(numerator) / 
           static_cast<result_type>(denominator);
}

// 安全的数值转换
template<typename Target, typename Source>
bool safe_narrow_cast(Target& target, Source source) {
    target = static_cast<Target>(source);
    
    // 检查是否发生精度损失
    if (static_cast<Source>(target) != source) {
        return false;  // 转换失败
    }
    
    // 检查符号变化
    if (std::is_signed<Source>::value != std::is_signed<Target>::value) {
        if ((source < 0) != (target < 0)) {
            return false;  // 符号变化
        }
    }
    
    return true;  // 转换成功
}

int main() {
    // 安全转换示例
    double large_double = 1e10;
    int small_int;
    
    if (safe_narrow_cast(small_int, large_double)) {
        std::cout << "转换成功: " << small_int << std::endl;
    } else {
        std::cout << "转换失败:数值超出范围" << std::endl;
    }
    
    // 安全除法
    try {
        auto result = safe_divide(10, 3);
        std::cout << "10 / 3 = " << result << std::endl;
        
        auto result2 = safe_divide(10.0, 0.0);
    } catch (const std::exception& e) {
        std::cout << "错误: " << e.what() << std::endl;
    }
    
    return 0;
}

2.5 内存模型与大小

2.5.1 内存大小和对齐

#include <iostream>
#include <cstddef>  // sizeof运算符

int main() {
    // 基本类型大小
    std::cout << "=== 基本类型大小 ===" << std::endl;
    std::cout << "char: " << sizeof(char) << " 字节" << std::endl;
    std::cout << "short: " << sizeof(short) << " 字节" << std::endl;
    std::cout << "int: " << sizeof(int) << " 字节" << std::endl;
    std::cout << "long: " << sizeof(long) << " 字节" << std::endl;
    std::cout << "long long: " << sizeof(long long) << " 字节" << std::endl;
    std::cout << "float: " << sizeof(float) << " 字节" << std::endl;
    std::cout << "double: " << sizeof(double) << " 字节" << std::endl;
    std::cout << "long double: " << sizeof(long double) << " 字节" << std::endl;
    std::cout << "bool: " << sizeof(bool) << " 字节" << std::endl;
    
    // 指针大小(与平台相关)
    std::cout << "\n=== 指针大小 ===" << std::endl;
    std::cout << "int*: " << sizeof(int*) << " 字节" << std::endl;
    std::cout << "double*: " << sizeof(double*) << " 字节" << std::endl;
    std::cout << "char*: " << sizeof(char*) << " 字节" << std::endl;
    
    // 数组大小
    std::cout << "\n=== 数组大小 ===" << std::endl;
    int arr[10];
    std::cout << "int[10]: " << sizeof(arr) << " 字节" << std::endl;
    std::cout << "元素个数: " << sizeof(arr) / sizeof(arr[0]) << std::endl;
    
    return 0;
}

2.5.2 字节序检测

#include <iostream>
#include <cstdint>

// 检测字节序
enum class ByteOrder {
    LITTLE_ENDIAN,
    BIG_ENDIAN,
    UNKNOWN
};

ByteOrder getSystemByteOrder() {
    union {
        uint32_t integer;
        uint8_t bytes[4];
    } test = {0x01020304};
    
    if (test.bytes[0] == 0x04) {
        return ByteOrder::LITTLE_ENDIAN;
    } else if (test.bytes[0] == 0x01) {
        return ByteOrder::BIG_ENDIAN;
    } else {
        return ByteOrder::UNKNOWN;
    }
}

// 字节序转换函数
template<typename T>
T swapEndian(T value) {
    union {
        T value;
        uint8_t bytes[sizeof(T)];
    } src, dst;
    
    src.value = value;
    
    for (size_t i = 0; i < sizeof(T); i++) {
        dst.bytes[i] = src.bytes[sizeof(T) - 1 - i];
    }
    
    return dst.value;
}

int main() {
    // 检测系统字节序
    ByteOrder order = getSystemByteOrder();
    
    std::cout << "系统字节序: ";
    switch (order) {
        case ByteOrder::LITTLE_ENDIAN:
            std::cout << "小端序" << std::endl;
            break;
        case ByteOrder::BIG_ENDIAN:
            std::cout << "大端序" << std::endl;
            break;
        default:
            std::cout << "未知" << std::endl;
    }
    
    // 演示字节序转换
    uint32_t original = 0x01020304;
    uint32_t swapped = swapEndian(original);
    
    std::cout << "\n原始值: 0x" << std::hex << original << std::endl;
    std::cout << "转换后: 0x" << std::hex << swapped << std::endl;
    
    return 0;
}

2.6 完整示例:科学计算器

/**
 * @file scientific_calculator.cpp
 * @brief 科学计算器 - 数据类型与变量综合应用
 */

#include <iostream>
#include <cmath>
#include <limits>
#include <iomanip>

// 物理常量
constexpr double PI = 3.14159265358979323846;
constexpr double E = 2.71828182845904523536;
constexpr double AVOGADRO = 6.02214076e23;
constexpr double ELECTRON_MASS = 9.10938356e-31;

// 枚举:计算模式
enum class CalculationMode {
    BASIC,
    SCIENTIFIC,
    PROGRAMMER
};

// 枚举:数据类型选择
enum class DataType {
    INTEGER,
    FLOAT,
    DOUBLE,
    SCIENTIFIC
};

// 科学计算器类
class ScientificCalculator {
private:
    CalculationMode mode_;
    DataType current_type_;
    int precision_;
    
public:
    ScientificCalculator() : mode_(CalculationMode::SCIENTIFIC), 
                              current_type_(DataType::DOUBLE), 
                              precision_(6) {}
    
    // 设置计算模式
    void setMode(CalculationMode mode) {
        mode_ = mode;
    }
    
    // 设置数据类型
    void setDataType(DataType type) {
        current_type_ = type;
    }
    
    // 设置精度
    void setPrecision(int precision) {
        precision_ = precision;
    }
    
    // 基本运算
    template<typename T>
    T add(T a, T b) {
        return a + b;
    }
    
    template<typename T>
    T subtract(T a, T b) {
        return a - b;
    }
    
    template<typename T>
    T multiply(T a, T b) {
        return a * b;
    }
    
    template<typename T>
    T divide(T a, T b) {
        if (b == 0) {
            throw std::runtime_error("除零错误");
        }
        return a / b;
    }
    
    // 科学运算
    double power(double base, double exponent) {
        return std::pow(base, exponent);
    }
    
    double squareRoot(double value) {
        if (value < 0) {
            throw std::runtime_error("负数不能开平方");
        }
        return std::sqrt(value);
    }
    
    double naturalLog(double value) {
        if (value <= 0) {
            throw std::runtime_error("对数参数必须为正");
        }
        return std::log(value);
    }
    
    double sine(double angle_rad) {
        return std::sin(angle_rad);
    }
    
    double cosine(double angle_rad) {
        return std::cos(angle_rad);
    }
    
    double tangent(double angle_rad) {
        return std::tan(angle_rad);
    }
    
    // 显示计算结果
    template<typename T>
    void displayResult(const std::string& operation, T result) {
        std::cout << operation << " = ";
        
        switch (current_type_) {
            case DataType::SCIENTIFIC:
                std::cout << std::scientific << std::setprecision(precision_);
                break;
            case DataType::FLOAT:
            case DataType::DOUBLE:
                std::cout << std::fixed << std::setprecision(precision_);
                break;
            default:
                break;
        }
        
        std::cout << result << std::endl;
    }
    
    // 显示常量信息
    void displayConstants() {
        std::cout << "\n=== 数学和物理常量 ===" << std::endl;
        std::cout << "π (PI): " << std::setprecision(15) << PI << std::endl;
        std::cout << "e (自然对数底): " << std::setprecision(15) << E << std::endl;
        std::cout << "阿伏伽德罗常数: " << std::scientific << AVOGADRO << std::endl;
        std::cout << "电子质量: " << std::scientific << ELECTRON_MASS << " kg" << std::endl;
    }
    
    // 数据类型信息
    void displayTypeInfo() {
        std::cout << "\n=== 数据类型信息 ===" << std::endl;
        std::cout << "char: " << sizeof(char) << " 字节" << std::endl;
        std::cout << "short: " << sizeof(short) << " 字节" << std::endl;
        std::cout << "int: " << sizeof(int) << " 字节" << std::endl;
        std::cout << "long: " << sizeof(long) << " 字节" << std::endl;
        std::cout << "long long: " << sizeof(long long) << " 字节" << std::endl;
        std::cout << "float: " << sizeof(float) << " 字节" << std::endl;
        std::cout << "double: " << sizeof(double) << " 字节" << std::endl;
        std::cout << "long double: " << sizeof(long double) << " 字节" << std::endl;
    }
};

// 辅助函数
void displayMenu() {
    std::cout << "\n=== 科学计算器 ===" << std::endl;
    std::cout << "1. 基本运算 (+, -, *, /)" << std::endl;
    std::cout << "2. 科学运算 (幂, 平方根, 对数)" << std::endl;
    std::cout << "3. 三角函数 (sin, cos, tan)" << std::endl;
    std::cout << "4. 显示常量信息" << std::endl;
    std::cout << "5. 显示数据类型信息" << std::endl;
    std::cout << "0. 退出" << std::endl;
    std::cout << "选择操作: ";
}

double getNumber(const std::string& prompt) {
    double value;
    while (true) {
        std::cout << prompt;
        if (std::cin >> value) {
            return value;
        }
        std::cout << "输入无效,请输入数字!" << std::endl;
        std::cin.clear();
        std::cin.ignore(std::numeric_limits<std::streamsize>::max(), '\n');
    }
}

int main() {
    ScientificCalculator calc;
    int choice;
    
    std::cout << "欢迎使用科学计算器!" << std::endl;
    
    while (true) {
        displayMenu();
        std::cin >> choice;
        
        try {
            switch (choice) {
                case 1: {  // 基本运算
                    double a = getNumber("请输入第一个数字: ");
                    double b = getNumber("请输入第二个数字: ");
                    
                    calc.displayResult("加法", calc.add(a, b));
                    calc.displayResult("减法", calc.subtract(a, b));
                    calc.displayResult("乘法", calc.multiply(a, b));
                    calc.displayResult("除法", calc.divide(a, b));
                    break;
                }
                
                case 2: {  // 科学运算
                    double base = getNumber("请输入底数: ");
                    double exp = getNumber("请输入指数: ");
                    double value = getNumber("请输入数值: ");
                    
                    calc.displayResult("幂运算", calc.power(base, exp));
                    calc.displayResult("平方根", calc.squareRoot(value));
                    calc.displayResult("自然对数", calc.naturalLog(value));
                    break;
                }
                
                case 3: {  // 三角函数
                    double angle_deg = getNumber("请输入角度(度): ");
                    double angle_rad = angle_deg * PI / 180.0;
                    
                    calc.displayResult("正弦", calc.sine(angle_rad));
                    calc.displayResult("余弦", calc.cosine(angle_rad));
                    calc.displayResult("正切", calc.tangent(angle_rad));
                    break;
                }
                
                case 4:  // 显示常量
                    calc.displayConstants();
                    break;
                    
                case 5:  // 显示类型信息
                    calc.displayTypeInfo();
                    break;
                    
                case 0:  // 退出
                    std::cout << "感谢使用科学计算器!" << std::endl;
                    return 0;
                    
                default:
                    std::cout << "无效选择!" << std::endl;
            }
        } catch (const std::exception& e) {
            std::cout << "错误: " << e.what() << std::endl;
        }
    }
    
    return 0;
}

📝 练习题

基础练习

  1. 数据类型大小:编写程序显示你系统上各种数据类型的大小
  2. 温度转换:编写华氏度到摄氏度的转换程序,使用合适的变量类型
  3. 圆的计算:给定半径,计算圆的面积和周长,使用const常量存储π

进阶练习

  1. 类型安全转换:实现一个安全的数值转换函数,能够检测溢出和精度损失
  2. 内存对齐:编写程序显示结构体的内存对齐情况
  3. 字节序转换:实现一个网络字节序和主机字节序的转换函数

综合练习

  1. 单位转换器:创建一个完整的单位转换程序,支持长度、重量、温度等
  2. 科学计算器:扩展本章的科学计算器,添加更多数学函数和统计功能
  3. 数据验证器:编写一个程序验证用户输入的各种数据类型

📚 参考资料

🔗 相关章节


版本记录:

  • v1.0: 2025年 - 基础阶段第2章文档创建
  • 更新记录:定期检查并更新内容

本章代码示例:参见 code_examples/ 目录

Logo

Agent 垂直技术社区,欢迎活跃、内容共建。

更多推荐