换一种参数自适应方法，因为所有模态都被标为温度，要确保可运行：import os
import json
import pandas as pd
import numpy as np
import matplotlib.pyplot as plt
from PyEMD import EMD
from sklearn.ensemble import IsolationForest
from scipy.signal import savgol_filter
from scipy.fft import fft, fftfreq
from sklearn.model_selection import ParameterGrid
from sklearn.metrics import mean_squared_error
import warnings

# 忽略不必要的警告
warnings.filterwarnings("ignore")

# 解决中文显示问题
plt.rcParams['font.sans-serif'] = ['SimHei']  # 使用黑体显示中文
plt.rcParams['axes.unicode_minus'] = False    # 解决负号显示问题

# 参数文件路径
PARAM_FILE = 'best_params.json'

def calculate_dominant_frequency(imf, sampling_rate):
    """
    计算IMF的主频率
    :param imf: 一维信号
    :param sampling_rate: 采样率（Hz）
    :return: 主频率（Hz）
    """
    N = len(imf)
    yf = fft(imf)
    xf = fftfreq(N, d=1/sampling_rate)
    
    # 只考虑正频率部分
    positive_freqs = xf[:N//2]
    positive_yf = np.abs(yf[:N//2])
    
    if len(positive_yf) == 0:
        return 0.0
    
    # 找到主频率
    idx = np.argmax(positive_yf)
    dominant_freq = positive_freqs[idx]
    return dominant_freq

def emd_spectral_decomposition(signal, time_seconds, frequency_threshold=0.1):
    """
    使用EMD分解并通过频谱分析自动去除低频IMF
    :param signal: 一维信号
    :param time_seconds: 时间序列，单位为秒
    :param frequency_threshold: 频率阈值，低于该值的IMF将被去除
    :return: 去除低频IMF后的信号, 低频IMF编号列表, 所有IMF
    """
    emd = EMD()
    IMFs = emd.emd(S=signal, T=time_seconds)
    num_IMFs = IMFs.shape[0]
    print(f"分解得到的IMF数量: {num_IMFs}")
    
    # 估计采样率
    time_deltas = np.diff(time_seconds)
    avg_time_delta = np.mean(time_deltas)
    if avg_time_delta == 0:
        raise ValueError("时间序列的平均时间间隔为0，无法计算采样率。")
    sampling_rate = 1 / avg_time_delta
    print(f"估计采样率: {sampling_rate:.4f} Hz")
    
    # 计算每个IMF的主频率并选择低频IMF
    low_freq_IMF_indices = []
    for i, imf in enumerate(IMFs):
        dom_freq = calculate_dominant_frequency(imf, sampling_rate)
        print(f"IMF {i+1}: 主频率 = {dom_freq:.4f} Hz")
        if dom_freq < frequency_threshold:
            low_freq_IMF_indices.append(i)
    
    print(f"需要去除的低频IMF编号: {low_freq_IMF_indices}")
    
    # 去除低频IMF
    if low_freq_IMF_indices:
        removed_signal = np.sum(IMFs[low_freq_IMF_indices, :], axis=0)
        cleaned_signal = signal - removed_signal
    else:
        cleaned_signal = signal
    
    return cleaned_signal, low_freq_IMF_indices, IMFs

def moving_average_forecast(series, window_size):
    """移动平均预测"""
    forecast = []
    for t in range(len(series) - window_size + 1):
        forecast.append(series[t:t + window_size].mean())
    return np.array(forecast)

def plot_imfs(time, IMFs, low_freq_indices):
    """
    绘制所有IMF，并标注低频IMF
    :param time: 时间序列
    :param IMFs: 所有IMF
    :param low_freq_indices: 低频IMF的索引列表
    """
    num_IMFs = IMFs.shape[0]
    plt.figure(figsize=(12, 3*num_IMFs))
    
    for i in range(num_IMFs):
        plt.subplot(num_IMFs, 1, i + 1)
        plt.plot(time, IMFs[i], label=f'IMF {i+1}', color='b' if i not in low_freq_indices else 'r')
        if i in low_freq_indices:
            plt.legend(loc='upper right')
            plt.title(f'IMF {i+1} (低频, 温度影响)')
        else:
            plt.legend(loc='upper right')
            plt.title(f'IMF {i+1}')
        plt.xlabel('时间')
        plt.ylabel('挠度')
    
    plt.tight_layout()
    plt.show()

def save_best_params(params):
    """保存最佳参数到JSON文件"""
    with open(PARAM_FILE, 'w', encoding='utf-8') as f:
        json.dump(params, f, ensure_ascii=False, indent=4)
    print(f"最佳参数已保存到 {PARAM_FILE}。")

def load_best_params():
    """从JSON文件加载最佳参数"""
    if not os.path.exists(PARAM_FILE):
        print(f"参数文件 {PARAM_FILE} 不存在。")
        return None
    with open(PARAM_FILE, 'r', encoding='utf-8') as f:
        params = json.load(f)
    print(f"已加载最佳参数: {params}")
    return params

def main_automated_process(file_path, mode, param_grid=None):
    """
    主自动化处理流程
    :param file_path: Excel文件路径
    :param mode: 1 - 自适应选择参数, 2 - 使用上次的参数
    :param param_grid: 参数网格，用于优化（仅模式1时使用）
    :return: 处理后的DataFrame, 最佳参数组合
    """
    # 默认参数网格
    if param_grid is None:
        param_grid = {
            'contamination': [0.01, 0.02, 0.05],
            'frequency_threshold': [0.05, 0.1, 0.2],
            'window_size_forecast': [12, 24, 36]
        }
    
    # 读取数据
    try:
        df = pd.read_excel(file_path)
    except Exception as e:
        print(f"读取Excel文件时出错: {e}")
        return None, None
    
    print("Excel文件读取成功。")
    print(f"数据总行数: {len(df)}")
    print(f"列名: {df.columns.tolist()}")
    
    # 检查列名是否包含 '时间' 和 '挠度'
    required_columns = ['时间', '挠度']
    for col in required_columns:
        if col not in df.columns:
            print(f"Excel文件中缺少 '{col}' 列，请检查列名。")
            return None, None
    
    # 将“时间”列转换为datetime格式
    try:
        df['时间'] = pd.to_datetime(df['时间'])
    except Exception as e:
        print(f"转换 '时间' 列为 datetime 格式时出错: {e}")
        return None, None
    
    # 使用 Savitzky-Golay 滤波器进行平滑
    window_size = 11
    poly_order = 3
    if window_size % 2 == 0:
        window_size += 1
        print(f"window_size为偶数，已调整为 {window_size}")
    
    try:
        df['平滑挠度'] = savgol_filter(df['挠度'], window_size, poly_order)
    except Exception as e:
        print(f"Savgol 滤波器应用时出错: {e}")
        return None, None
    
    # 参数优化或加载最佳参数
    if mode == '1':
        # 模式1: 自适应选择参数
        best_rmse = np.inf
        best_params = {}
        best_cleaned_signal = None
        best_removed_IMFs = None
        best_IMFs = None
        best_low_freq_IMF_indices = []
        
        # 网格搜索
        grid = ParameterGrid(param_grid)
        print(f"共有 {len(grid)} 组参数组合进行测试。")
        
        for params in grid:
            contamination = params['contamination']
            frequency_threshold = params['frequency_threshold']
            window_size_forecast = params['window_size_forecast']
            
            # 使用孤立森林检测异常值
            iso_forest = IsolationForest(contamination=contamination, random_state=42)
            try:
                anomalies = iso_forest.fit_predict(df[['平滑挠度']])
            except Exception as e:
                print(f"孤立森林异常检测时出错: {e}")
                continue
            
            num_anomalies = (anomalies == -1).sum()
            # 仅保留参数组合检测到的异常值数量在合理范围内
            if num_anomalies > len(df) * 0.2:
                # 若异常值过多，跳过该参数组合
                print(f"参数组合 {params} 检测到过多异常值 ({num_anomalies} 个)，跳过。")
                continue
            
            df['挠度_去除异常'] = df['平滑挠度']
            df.loc[anomalies == -1, '挠度_去除异常'] = np.nan
            
            # 获取去除异常后的数据
            cleaned_data = df[['时间', '挠度_去除异常']].dropna()
            
            if len(cleaned_data) < window_size_forecast:
                # 数据不足以进行预测，跳过
                print(f"参数组合 {params} 数据不足以进行预测，跳过。")
                continue
            
            # 将时间列转换为秒数
            try:
                time_seconds = (cleaned_data['时间'] - cleaned_data['时间'].iloc[0]).dt.total_seconds().values
            except Exception as e:
                print(f"转换时间列为秒数时出错: {e}")
                continue
            
            # EMD分解并去除低频IMF
            try:
                cleaned_signal, removed_IMFs, IMFs = emd_spectral_decomposition(
                    signal=cleaned_data['挠度_去除异常'].values,
                    time_seconds=time_seconds,
                    frequency_threshold=frequency_threshold
                )
            except Exception as e:
                print(f"EMD分解过程中出错: {e}")
                continue
            
            # 移动平均预测
            try:
                forecast = moving_average_forecast(cleaned_signal, window_size_forecast)
                if len(forecast) == 0:
                    # 预测结果为空，跳过
                    print(f"参数组合 {params} 生成的预测数据为空，跳过。")
                    continue
                actual = cleaned_signal[window_size_forecast -1 :]
                predicted = forecast
                # 检查是否有NaN值
                if np.isnan(actual).any() or np.isnan(predicted).any():
                    print(f"参数组合 {params} 的实际或预测数据包含NaN，跳过。")
                    continue
                rmse = np.sqrt(mean_squared_error(actual, predicted))
            except Exception as e:
                print(f"移动平均预测过程中出错: {e}")
                continue
            
            print(f"参数组合 {params} 的RMSE: {rmse:.4f}")
            
            if rmse < best_rmse:
                best_rmse = rmse
                best_params = params
                best_cleaned_signal = cleaned_signal
                best_removed_IMFs = removed_IMFs
                best_IMFs = IMFs
                # 重新计算低频IMF编号
                best_low_freq_IMF_indices = [i for i, freq in enumerate(
                    [calculate_dominant_frequency(imf, 1 / np.mean(np.diff(time_seconds))) for imf in IMFs]
                ) if freq < frequency_threshold]
        
        # 检查是否找到最佳参数
        if not best_params:
            print("未找到合适的参数组合，请调整参数网格。")
            return df, None
        
        print(f"\n最佳参数组合: {best_params}, 对应的RMSE: {best_rmse:.4f}")
        
        # 保存最佳参数
        save_best_params(best_params)
        
        # 使用最佳参数重新检测异常值
        contamination = best_params['contamination']
        frequency_threshold = best_params['frequency_threshold']
        window_size_forecast = best_params['window_size_forecast']
        
        iso_forest = IsolationForest(contamination=contamination, random_state=42)
        try:
            anomalies = iso_forest.fit_predict(df[['平滑挠度']])
        except Exception as e:
            print(f"孤立森林异常检测时出错: {e}")
            return df, best_params
        
        df['挠度_去除异常'] = df['平滑挠度']
        df.loc[anomalies == -1, '挠度_去除异常'] = np.nan
        
        # 获取去除异常后的数据
        cleaned_data = df[['时间', '挠度_去除异常']].dropna()
        
        # 将时间列转换为秒数
        try:
            time_seconds = (cleaned_data['时间'] - cleaned_data['时间'].iloc[0]).dt.total_seconds().values
        except Exception as e:
            print(f"转换时间列为秒数时出错: {e}")
            return df, best_params
        
        # EMD分解并去除低频IMF
        try:
            cleaned_signal, removed_IMFs, IMFs = emd_spectral_decomposition(
                signal=cleaned_data['挠度_去除异常'].values,
                time_seconds=time_seconds,
                frequency_threshold=frequency_threshold
            )
        except Exception as e:
            print(f"EMD分解过程中出错: {e}")
            return df, best_params
        
        # 绘制所有IMF并标注低频IMF
        plot_imfs(cleaned_data['时间'], IMFs, best_low_freq_IMF_indices)
        
        # 添加去除温致挠度后的信号到DataFrame
        df.loc[cleaned_data.index, '去除温致挠度'] = cleaned_signal
        
        # 移动平均预测
        try:
            forecast = moving_average_forecast(cleaned_signal, window_size_forecast)
            # 对于最终预测结果，直接与实际数据对齐
            forecast_series = np.concatenate([cleaned_signal[:len(cleaned_signal) - len(forecast)], forecast])
            df.loc[cleaned_data.index, '预测'] = forecast_series
        except Exception as e:
            print(f"移动平均预测过程中出错: {e}")
            return df, best_params
        
        # 绘制最终结果
        try:
            plt.figure(figsize=(14, 8))
            
            # 原始信号 vs 去除低频IMF后的信号
            plt.subplot(2, 1, 1)
            plt.plot(cleaned_data['时间'], cleaned_data['挠度_去除异常'], label='原始信号', color='b', alpha=0.5)
            plt.plot(cleaned_data['时间'], cleaned_signal, label='去除低频IMF后的信号', color='g')
            plt.legend(loc='upper right')
            plt.title('原始信号 vs 去除低频IMF后的信号')
            plt.xlabel('时间')
            plt.ylabel('挠度')
            
            # 信号及预测
            plt.subplot(2, 1, 2)
            plt.plot(cleaned_data['时间'], cleaned_signal, label='去除低频IMF后的信号', color='g')
            plt.plot(cleaned_data['时间'], forecast_series, label='移动平均预测', color='r')
            plt.legend(loc='upper right')
            plt.title('去除低频IMF后的信号及其预测')
            plt.xlabel('时间')
            plt.ylabel('挠度')
            
            plt.tight_layout()
            plt.show()
        except Exception as e:
            print(f"可视化过程中出错: {e}")
        
        return df, best_params
    
    def load_and_process_with_best_params(file_path, best_params):
        """
        使用加载的最佳参数进行处理
        :param file_path: Excel文件路径
        :param best_params: 最佳参数字典
        :return: 处理后的DataFrame
        """
        contamination = best_params['contamination']
        frequency_threshold = best_params['frequency_threshold']
        window_size_forecast = best_params['window_size_forecast']
        
        # 读取数据
        try:
            df = pd.read_excel(file_path)
        except Exception as e:
            print(f"读取Excel文件时出错: {e}")
            return None
        
        print("Excel文件读取成功。")
        print(f"数据总行数: {len(df)}")
        print(f"列名: {df.columns.tolist()}")
        
        # 检查列名是否包含 '时间' 和 '挠度'
        required_columns = ['时间', '挠度']
        for col in required_columns:
            if col not in df.columns:
                print(f"Excel文件中缺少 '{col}' 列，请检查列名。")
                return None
        
        # 将“时间”列转换为datetime格式
        try:
            df['时间'] = pd.to_datetime(df['时间'])
        except Exception as e:
            print(f"转换 '时间' 列为 datetime 格式时出错: {e}")
            return None
        
        # 使用 Savitzky-Golay 滤波器进行平滑
        window_size = 11
        poly_order = 3
        if window_size % 2 == 0:
            window_size += 1
            print(f"window_size为偶数，已调整为 {window_size}")
        
        try:
            df['平滑挠度'] = savgol_filter(df['挠度'], window_size, poly_order)
        except Exception as e:
            print(f"Savgol 滤波器应用时出错: {e}")
            return None
        
        # 使用最佳参数进行异常值检测
        iso_forest = IsolationForest(contamination=contamination, random_state=42)
        try:
            anomalies = iso_forest.fit_predict(df[['平滑挠度']])
        except Exception as e:
            print(f"孤立森林异常检测时出错: {e}")
            return None
        
        df['挠度_去除异常'] = df['平滑挠度']
        df.loc[anomalies == -1, '挠度_去除异常'] = np.nan
        
        # 获取去除异常后的数据
        cleaned_data = df[['时间', '挠度_去除异常']].dropna()
        
        if len(cleaned_data) < window_size_forecast:
            print("清洗后数据不足以进行预测。")
            return df
        
        # 将时间列转换为秒数
        try:
            time_seconds = (cleaned_data['时间'] - cleaned_data['时间'].iloc[0]).dt.total_seconds().values
        except Exception as e:
            print(f"转换时间列为秒数时出错: {e}")
            return None
        
        # EMD分解并去除低频IMF
        try:
            cleaned_signal, removed_IMFs, IMFs = emd_spectral_decomposition(
                signal=cleaned_data['挠度_去除异常'].values,
                time_seconds=time_seconds,
                frequency_threshold=frequency_threshold
            )
        except Exception as e:
            print(f"EMD分解过程中出错: {e}")
            return None
        
        # 绘制所有IMF并标注低频IMF
        best_low_freq_IMF_indices = [i for i, freq in enumerate(
            [calculate_dominant_frequency(imf, 1 / np.mean(np.diff(time_seconds))) for imf in IMFs]
        ) if freq < frequency_threshold]
        plot_imfs(cleaned_data['时间'], IMFs, best_low_freq_IMF_indices)
        
        # 添加去除温致挠度后的信号到DataFrame
        df.loc[cleaned_data.index, '去除温致挠度'] = cleaned_signal
        
        # 移动平均预测
        try:
            forecast = moving_average_forecast(cleaned_signal, window_size_forecast)
            # 对于最终预测结果，直接与实际数据对齐
            forecast_series = np.concatenate([cleaned_signal[:len(cleaned_signal) - len(forecast)], forecast])
            df.loc[cleaned_data.index, '预测'] = forecast_series
        except Exception as e:
            print(f"移动平均预测过程中出错: {e}")
            return df
        
        # 绘制最终结果
        try:
            plt.figure(figsize=(14, 8))
            
            # 原始信号 vs 去除低频IMF后的信号
            plt.subplot(2, 1, 1)
            plt.plot(cleaned_data['时间'], cleaned_data['挠度_去除异常'], label='原始信号', color='b', alpha=0.5)
            plt.plot(cleaned_data['时间'], cleaned_signal, label='去除低频IMF后的信号', color='g')
            plt.legend(loc='upper right')
            plt.title('原始信号 vs 去除低频IMF后的信号')
            plt.xlabel('时间')
            plt.ylabel('挠度')
            
            # 信号及预测
            plt.subplot(2, 1, 2)
            plt.plot(cleaned_data['时间'], cleaned_signal, label='去除低频IMF后的信号', color='g')
            plt.plot(cleaned_data['时间'], forecast_series, label='移动平均预测', color='r')
            plt.legend(loc='upper right')
            plt.title('去除低频IMF后的信号及其预测')
            plt.xlabel('时间')
            plt.ylabel('挠度')
            
            plt.tight_layout()
            plt.show()
        except Exception as e:
            print(f"可视化过程中出错: {e}")
        
        return df, best_params

    def load_and_process_with_best_params(file_path, best_params):
        """
        使用加载的最佳参数进行处理
        :param file_path: Excel文件路径
        :param best_params: 最佳参数字典
        :return: 处理后的DataFrame
        """
        contamination = best_params['contamination']
        frequency_threshold = best_params['frequency_threshold']
        window_size_forecast = best_params['window_size_forecast']
        
        # 读取数据
        try:
            df = pd.read_excel(file_path)
        except Exception as e:
            print(f"读取Excel文件时出错: {e}")
            return None
        
        print("Excel文件读取成功。")
        print(f"数据总行数: {len(df)}")
        print(f"列名: {df.columns.tolist()}")
        
        # 检查列名是否包含 '时间' 和 '挠度'
        required_columns = ['时间', '挠度']
        for col in required_columns:
            if col not in df.columns:
                print(f"Excel文件中缺少 '{col}' 列，请检查列名。")
                return None
        
        # 将“时间”列转换为datetime格式
        try:
            df['时间'] = pd.to_datetime(df['时间'])
        except Exception as e:
            print(f"转换 '时间' 列为 datetime 格式时出错: {e}")
            return None
        
        # 使用 Savitzky-Golay 滤波器进行平滑
        window_size = 11
        poly_order = 3
        if window_size % 2 == 0:
            window_size += 1
            print(f"window_size为偶数，已调整为 {window_size}")
        
        try:
            df['平滑挠度'] = savgol_filter(df['挠度'], window_size, poly_order)
        except Exception as e:
            print(f"Savgol 滤波器应用时出错: {e}")
            return None
        
        # 使用最佳参数进行异常值检测
        iso_forest = IsolationForest(contamination=contamination, random_state=42)
        try:
            anomalies = iso_forest.fit_predict(df[['平滑挠度']])
        except Exception as e:
            print(f"孤立森林异常检测时出错: {e}")
            return None
        
        df['挠度_去除异常'] = df['平滑挠度']
        df.loc[anomalies == -1, '挠度_去除异常'] = np.nan
        
        # 获取去除异常后的数据
        cleaned_data = df[['时间', '挠度_去除异常']].dropna()
        
        if len(cleaned_data) < window_size_forecast:
            print("清洗后数据不足以进行预测。")
            return df
        
        # 将时间列转换为秒数
        try:
            time_seconds = (cleaned_data['时间'] - cleaned_data['时间'].iloc[0]).dt.total_seconds().values
        except Exception as e:
            print(f"转换时间列为秒数时出错: {e}")
            return None
        
        # EMD分解并去除低频IMF
        try:
            cleaned_signal, removed_IMFs, IMFs = emd_spectral_decomposition(
                signal=cleaned_data['挠度_去除异常'].values,
                time_seconds=time_seconds,
                frequency_threshold=frequency_threshold
            )
        except Exception as e:
            print(f"EMD分解过程中出错: {e}")
            return None
        
        # 绘制所有IMF并标注低频IMF
        best_low_freq_IMF_indices = [i for i, freq in enumerate(
            [calculate_dominant_frequency(imf, 1 / np.mean(np.diff(time_seconds))) for imf in IMFs]
        ) if freq < frequency_threshold]
        plot_imfs(cleaned_data['时间'], IMFs, best_low_freq_IMF_indices)
        
        # 添加去除温致挠度后的信号到DataFrame
        df.loc[cleaned_data.index, '去除温致挠度'] = cleaned_signal
        
        # 移动平均预测
        try:
            forecast = moving_average_forecast(cleaned_signal, window_size_forecast)
            # 对于最终预测结果，直接与实际数据对齐
            forecast_series = np.concatenate([cleaned_signal[:len(cleaned_signal) - len(forecast)], forecast])
            df.loc[cleaned_data.index, '预测'] = forecast_series
        except Exception as e:
            print(f"移动平均预测过程中出错: {e}")
            return df
        
        # 绘制最终结果
        try:
            plt.figure(figsize=(14, 8))
            
            # 原始信号 vs 去除低频IMF后的信号
            plt.subplot(2, 1, 1)
            plt.plot(cleaned_data['时间'], cleaned_data['挠度_去除异常'], label='原始信号', color='b', alpha=0.5)
            plt.plot(cleaned_data['时间'], cleaned_signal, label='去除低频IMF后的信号', color='g')
            plt.legend(loc='upper right')
            plt.title('原始信号 vs 去除低频IMF后的信号')
            plt.xlabel('时间')
            plt.ylabel('挠度')
            
            # 信号及预测
            plt.subplot(2, 1, 2)
            plt.plot(cleaned_data['时间'], cleaned_signal, label='去除低频IMF后的信号', color='g')
            plt.plot(cleaned_data['时间'], forecast_series, label='移动平均预测', color='r')
            plt.legend(loc='upper right')
            plt.title('去除低频IMF后的信号及其预测')
            plt.xlabel('时间')
            plt.ylabel('挠度')
            
            plt.tight_layout()
            plt.show()
        except Exception as e:
            print(f"可视化过程中出错: {e}")
        
        return df, best_params

    def display_menu():
        """显示菜单选项"""
        print("\n请选择操作模式:")
        print("1. 自适应选择参数 (自动参数优化)")
        print("2. 使用上次的参数")
        print("3. 退出")
        choice = input("请输入选项 (1/2/3): ").strip()
        return choice

    def main():
        file_path = './挠度数据910.xlsx'  # 替换为实际文件路径
        
        while True:
            choice = display_menu()
            
            if choice == '1':
                print("\n您选择了自适应选择参数 (自动参数优化)。")
                df_result, optimal_params = main_automated_process(
                    file_path=file_path,
                    mode='1',
                    param_grid={
                        'contamination': [0.01, 0.02, 0.05],           # 异常值比例
                        'frequency_threshold': [0.05, 0.1, 0.2],      # 频率阈值
                        'window_size_forecast': [12, 24, 36]         # 移动平均窗口大小
                    }
                )
                if optimal_params:
                    print("\n自动化处理完成。")
                    print(f"最佳参数组合: {optimal_params}")
            elif choice == '2':
                print("\n您选择了使用上次的参数。")
                best_params = load_best_params()
                if best_params is None:
                    print("未找到上次的参数，请先进行自适应选择参数 (选项1)。")
                    continue
                df_result, _ = load_and_process_with_best_params(file_path, best_params)
                if df_result is not None:
                    print("\n使用上次的参数处理完成。")
            elif choice == '3':
                print("退出程序。")
                break
            else:
                print("无效的选项，请重新选择。")

    if __name__ == "__main__":
        main()