You can not select more than 25 topics
Topics must start with a letter or number, can include dashes ('-') and can be up to 35 characters long.
338 lines
13 KiB
338 lines
13 KiB
import java.util.Scanner;
|
|
import java.io.File;
|
|
import java.io.FileNotFoundException;
|
|
|
|
/**
|
|
* 温度转换器示例程序(Java)
|
|
* 支持摄氏度(C)与华氏度(F)之间互转
|
|
* 增强版本:支持命令行参数和文件批量转换
|
|
*/
|
|
public class TemperatureConverter {
|
|
|
|
/**
|
|
* 将摄氏度转换为华氏度。
|
|
*
|
|
* 换算公式:F = C × 9/5 + 32
|
|
*
|
|
* @param c 摄氏温度(浮点数)
|
|
* @return 对应的华氏温度(浮点数)
|
|
*/
|
|
public static double celsiusToFahrenheit(double c) {
|
|
return c * 9.0 / 5.0 + 32.0;
|
|
}
|
|
|
|
/**
|
|
* 将华氏度转换为摄氏度。
|
|
*
|
|
* 换算公式:C = (F - 32) × 5/9
|
|
*
|
|
* @param f 华氏温度(浮点数)
|
|
* @return 对应的摄氏温度(浮点数)
|
|
*/
|
|
public static double fahrenheitToCelsius(double f) {
|
|
return (f - 32.0) * 5.0 / 9.0;
|
|
}
|
|
|
|
/**
|
|
* 从粘连格式中提取数值和单位。
|
|
* 例如:100f → ["100", "F"],36.6c → ["36.6", "C"],100 f → ["100", "F"]
|
|
* 支持单位前的空格。
|
|
*
|
|
* @param input 粘连格式的输入
|
|
* @return 包含数值和单位的数组,如果无法提取则返回 null
|
|
*/
|
|
public static String[] extractAdjacent(String input) {
|
|
String trimmed = input.trim();
|
|
// 使用正则表达式匹配粘连格式,允许单位前有空格
|
|
// 格式:数字(可选小数) + 可选空格 + C或F
|
|
java.util.regex.Pattern pattern = java.util.regex.Pattern.compile("^(\\d+(?:\\.\\d+)?)\\s*([CcFf])$");
|
|
java.util.regex.Matcher matcher = pattern.matcher(trimmed);
|
|
|
|
if (matcher.matches()) {
|
|
String value = matcher.group(1);
|
|
String unit = matcher.group(2).toUpperCase();
|
|
return new String[]{value, unit};
|
|
}
|
|
return null;
|
|
}
|
|
|
|
/**
|
|
* 分析并提供错误诊断和建议。
|
|
* 在交互模式中使用此方法进行智能纠正。
|
|
*
|
|
* @param input 用户输入
|
|
* @param isInteractiveMode 是否为交互模式
|
|
* @return 如果输入有效返回true,否则返回false并打印诊断信息
|
|
*/
|
|
public static boolean analyzeAndSuggestFix(String input, boolean isInteractiveMode) {
|
|
input = input.trim();
|
|
|
|
// 1. 检查粘连单位模式(如 100f)
|
|
String[] adjacent = extractAdjacent(input);
|
|
if (adjacent != null) {
|
|
// 判断是否真正是粘连格式(数值和单位直接相连,无空格)
|
|
boolean isDirectlyAdjacent = input.matches("^\\d+(?:\\.\\d+)?[CcFf]$");
|
|
if (isDirectlyAdjacent && isInteractiveMode) {
|
|
System.out.println("✓ 已自动纠正输入:'" + input + "' → '" + adjacent[0] + " " + adjacent[1] + "'");
|
|
}
|
|
// 进行转换
|
|
return convertWithValidatedInput(Double.parseDouble(adjacent[0]), adjacent[1]);
|
|
}
|
|
|
|
// 2. 分割输入
|
|
String[] parts = input.split("\\s+");
|
|
|
|
// 3. 检查缺少单位模式(如 100)
|
|
if (parts.length == 1) {
|
|
try {
|
|
Double.parseDouble(parts[0]);
|
|
// 能解析为数字,但缺少单位
|
|
if (isInteractiveMode) {
|
|
System.out.println("⚠️ 缺少温度单位!");
|
|
System.out.println(" 请指定 C(摄氏度)或 F(华氏度)");
|
|
System.out.println(" 示例:" + parts[0] + " C 或 " + parts[0] + " F");
|
|
}
|
|
return false;
|
|
} catch (NumberFormatException e) {
|
|
// 既不是数字也不是正确格式
|
|
if (isInteractiveMode) {
|
|
System.out.println("❌ 温度值不是有效的数字:'" + parts[0] + "'");
|
|
System.out.println(" 请输入数值(如 36.6, 100 等)");
|
|
System.out.println(" 示例:36.6 C");
|
|
}
|
|
return false;
|
|
}
|
|
}
|
|
|
|
// 4. 验证数值有效性
|
|
try {
|
|
double value = Double.parseDouble(parts[0]);
|
|
String unit = parts[1].toUpperCase();
|
|
|
|
// 5. 验证单位有效性
|
|
if (!unit.startsWith("C") && !unit.startsWith("F")) {
|
|
if (isInteractiveMode) {
|
|
System.out.println("❌ 不支持的温度单位:'" + unit + "'");
|
|
System.out.println(" 支持的单位:C(摄氏度)或 F(华氏度)");
|
|
System.out.println(" 示例:" + parts[0] + " C 或 " + parts[0] + " F");
|
|
}
|
|
return false;
|
|
}
|
|
|
|
// 转换成功
|
|
return convertWithValidatedInput(value, unit);
|
|
|
|
} catch (NumberFormatException e) {
|
|
if (isInteractiveMode) {
|
|
System.out.println("❌ 温度值不是有效的数字:'" + parts[0] + "'");
|
|
System.out.println(" 请输入数值(如 36.6, 100 等)");
|
|
System.out.println(" 示例:36.6 C");
|
|
}
|
|
return false;
|
|
}
|
|
}
|
|
|
|
/**
|
|
* 使用验证过的数值和单位进行转换。
|
|
* 这是真正的转换逻辑,不包含错误处理。
|
|
*
|
|
* @param value 温度值
|
|
* @param unit 单位(C 或 F)
|
|
* @return 始终返回 true(如果调用说明数据有效)
|
|
*/
|
|
public static boolean convertWithValidatedInput(double value, String unit) {
|
|
if (unit.startsWith("C")) {
|
|
double f = celsiusToFahrenheit(value);
|
|
System.out.printf("%.2f °C = %.2f °F%n", value, f);
|
|
} else if (unit.startsWith("F")) {
|
|
double c = fahrenheitToCelsius(value);
|
|
System.out.printf("%.2f °F = %.2f °C%n", value, c);
|
|
}
|
|
return true;
|
|
}
|
|
|
|
/**
|
|
* 处理单个温度转换(命令行/文件模式用,宽松验证)。
|
|
*
|
|
* @param input 温度输入字符串,格式:"数值 单位",例如 "36.6 C"
|
|
* @return 转换成功返回true,失败返回false
|
|
*/
|
|
public static boolean convertSingleTemperature(String input) {
|
|
input = input.trim();
|
|
|
|
// 检查输入是否为空
|
|
if (input.isEmpty()) {
|
|
return false;
|
|
}
|
|
|
|
// 检查粘连单位并自动分离
|
|
String[] adjacent = extractAdjacent(input);
|
|
if (adjacent != null) {
|
|
try {
|
|
return convertWithValidatedInput(Double.parseDouble(adjacent[0]), adjacent[1]);
|
|
} catch (NumberFormatException e) {
|
|
return false;
|
|
}
|
|
}
|
|
|
|
// 按空白字符分割输入字符串
|
|
String[] parts = input.split("\\s+");
|
|
|
|
try {
|
|
double value = Double.parseDouble(parts[0]);
|
|
// 如果没有单位,在命令行/文件模式中仍然尝试转换(宽松模式)
|
|
// 但在交互模式中会被 analyzeAndSuggestFix 拒绝
|
|
String unit = (parts.length > 1) ? parts[1].toUpperCase() : "C";
|
|
|
|
if (unit.startsWith("C")) {
|
|
double f = celsiusToFahrenheit(value);
|
|
System.out.printf("%.2f °C = %.2f °F%n", value, f);
|
|
} else if (unit.startsWith("F")) {
|
|
double c = fahrenheitToCelsius(value);
|
|
System.out.printf("%.2f °F = %.2f °C%n", value, c);
|
|
} else {
|
|
return false;
|
|
}
|
|
return true;
|
|
|
|
} catch (NumberFormatException e) {
|
|
return false;
|
|
} catch (Exception e) {
|
|
return false;
|
|
}
|
|
}
|
|
|
|
/**
|
|
* 从文件中批量读取温度数据并进行转换。
|
|
* 文件中每一行包含一个温度及其单位。
|
|
*
|
|
* @param filename 文件路径
|
|
*/
|
|
public static void convertFromFile(String filename) {
|
|
File file = new File(filename);
|
|
|
|
if (!file.exists()) {
|
|
System.out.println("文件不存在:" + filename);
|
|
return;
|
|
}
|
|
|
|
try {
|
|
Scanner fileScanner = new Scanner(file);
|
|
int lineNum = 0;
|
|
int successCount = 0;
|
|
|
|
System.out.println("从文件读取温度数据:" + filename);
|
|
System.out.println("========================================");
|
|
|
|
while (fileScanner.hasNextLine()) {
|
|
lineNum++;
|
|
String line = fileScanner.nextLine();
|
|
|
|
// 跳过空行和注释行(以#开头)
|
|
if (line.trim().isEmpty() || line.trim().startsWith("#")) {
|
|
continue;
|
|
}
|
|
|
|
System.out.print("第 " + lineNum + " 行:");
|
|
if (convertSingleTemperature(line)) {
|
|
successCount++;
|
|
}
|
|
}
|
|
|
|
System.out.println("========================================");
|
|
System.out.println("处理完成:共处理 " + lineNum + " 行,成功转换 " + successCount + " 条。");
|
|
|
|
fileScanner.close();
|
|
|
|
} catch (FileNotFoundException e) {
|
|
System.out.println("无法打开文件:" + filename);
|
|
}
|
|
}
|
|
|
|
/**
|
|
* 交互式模式:提示用户输入温度进行转换,使用智能诊断。
|
|
*/
|
|
public static void interactiveMode() {
|
|
Scanner scanner = new Scanner(System.in);
|
|
|
|
System.out.println("========================================");
|
|
System.out.println("温度转换器 - 交互式模式");
|
|
System.out.println("========================================");
|
|
System.out.println("请输入要转换的温度与单位(例如 36.6 C 或 97 F)");
|
|
System.out.println("输入 'quit' 或 'exit' 退出程序");
|
|
System.out.println("========================================");
|
|
|
|
while (true) {
|
|
System.out.print("> ");
|
|
String input = scanner.nextLine();
|
|
|
|
if (input.equalsIgnoreCase("quit") || input.equalsIgnoreCase("exit")) {
|
|
System.out.println("程序退出。");
|
|
break;
|
|
}
|
|
|
|
// 在交互模式中使用智能诊断
|
|
if (!analyzeAndSuggestFix(input, true)) {
|
|
// 诊断方法已经打印了具体的错误信息
|
|
}
|
|
}
|
|
|
|
scanner.close();
|
|
}
|
|
|
|
/**
|
|
* 显示使用说明。
|
|
*/
|
|
public static void showUsage() {
|
|
System.out.println("温度转换器 - 使用说明");
|
|
System.out.println("========================================");
|
|
System.out.println("用法1(命令行参数模式):");
|
|
System.out.println(" java TemperatureConverter_PytoJava <温度> <单位>");
|
|
System.out.println(" 例如:java TemperatureConverter_PytoJava 36.6 C");
|
|
System.out.println();
|
|
System.out.println("用法2(批量转换模式):");
|
|
System.out.println(" java TemperatureConverter_PytoJava <文件路径>");
|
|
System.out.println(" 例如:java TemperatureConverter_PytoJava temperatures.txt");
|
|
System.out.println(" 文件格式:每行一条温度数据,格式为 '温度 单位'");
|
|
System.out.println();
|
|
System.out.println("用法3(交互式模式):");
|
|
System.out.println(" java TemperatureConverter_PytoJava");
|
|
System.out.println(" 然后按提示输入温度数据");
|
|
System.out.println("========================================");
|
|
}
|
|
|
|
/**
|
|
* 程序入口主方法。
|
|
* 支持三种模式:
|
|
* 1. 命令行参数模式:java TemperatureConverter_PytoJava 36.6 C
|
|
* 2. 文件批量转换:java TemperatureConverter_PytoJava temperatures.txt
|
|
* 3. 交互式模式:java TemperatureConverter_PytoJava
|
|
*
|
|
* @param args 命令行参数
|
|
*/
|
|
public static void main(String[] args) {
|
|
if (args.length == 0) {
|
|
// 交互式模式
|
|
interactiveMode();
|
|
} else if (args.length == 1) {
|
|
// 检查是否为文件路径(包含.txt或其他扩展名,或者是一个存在的文件)
|
|
File file = new File(args[0]);
|
|
if (file.exists() && file.isFile()) {
|
|
// 文件批量转换模式
|
|
convertFromFile(args[0]);
|
|
} else if (args[0].equalsIgnoreCase("-h") || args[0].equalsIgnoreCase("--help")) {
|
|
// 显示帮助信息
|
|
showUsage();
|
|
} else {
|
|
// 可能是单个温度但缺少单位,默认使用摄氏度
|
|
System.out.println("处理输入:" + args[0]);
|
|
convertSingleTemperature(args[0]);
|
|
}
|
|
} else if (args.length == 2) {
|
|
// 命令行参数模式:温度和单位
|
|
convertSingleTemperature(args[0] + " " + args[1]);
|
|
} else {
|
|
showUsage();
|
|
}
|
|
}
|
|
}
|
|
|