C#控制台任务工期计算错误修复与goto语句替换实现
问题修复及代码优化方案
一、计算逻辑错误原因
原代码的结束日期计算存在两个核心问题:
- 仅对最终计算出的日期做周末判断,没有跳过计算周期内的所有周六周日,当日历跨度超过1周后,自然日和工作日的差值会越来越大,导致结果错误
- 日期累加时多加了1天:开始日期当天已经算作第1个工作日,比如所需工作日为1时,结束日期就是开始日期,无需额外加1
二、代码结构优化思路
将不同功能的逻辑拆分为独立方法,用while循环替代所有goto语句,每个方法仅负责单一功能,后续新增参数或规则时只需要修改对应方法即可:
- 通用整数输入校验方法:负责所有整数类型的输入校验,可自定义校验规则
- 开始日期输入校验方法:专门负责日期格式校验和周末判断
- 工作日结束日期计算方法:独立实现跨周末的工作日计算逻辑
- 主方法:仅负责流程调度和重启判断
三、修复后的完整代码
public static class Program { static void Main(string[] args) { while (true) { // 获取合法的任务总工时 int totalTaskHours = GetValidIntInput( "Enter Total Time for the Task in Hours : ", "You have entered invalid value for total hours of task. Please enter a positive integer", input => input > 0); // 获取合法的每日工作时长 int dailyWorkHours = GetValidIntInput( "\nEnter No of working hours per day: ", "Please enter an integer between 1 and 9 for working hours per day", input => input is > 0 and <= 9); // 获取合法的开始日期 DateTime startDate = GetValidStartDate( "\nEnter the start date of the task (e.g.mm/dd/yyyy) : ", "You have entered an incorrect value for start date. Please enter a correct value", "Cannot start work on {0} because it is a {1}"); // 计算所需工作日 int requiredWorkDays = (int)Math.Ceiling((double)totalTaskHours / dailyWorkHours); Console.WriteLine($"\nTask will take {requiredWorkDays} working days"); // 计算结束日期 DateTime endDate = CalculateWorkEndDate(startDate, requiredWorkDays); Console.WriteLine($"The ending date will be {endDate:MM/dd/yyyy}"); // 程序重启判断 Console.WriteLine("\n\nProgram complete ... press Y to restart or any other key to exit.\n"); if (Console.ReadKey(true).Key != ConsoleKey.Y) { break; } Console.Clear(); } } /// <summary> /// 获取符合规则的整数输入 /// </summary> /// <param name="prompt">输入提示语</param> /// <param name="errorMsg">校验失败提示语</param> /// <param name="validateRule">自定义校验规则</param> /// <returns>合法的整数输入</returns> private static int GetValidIntInput(string prompt, string errorMsg, Func<int, bool> validateRule) { int inputValue; while (true) { Console.WriteLine(prompt); if (int.TryParse(Console.ReadLine(), out inputValue) && validateRule(inputValue)) { Console.WriteLine($"Input value is : {inputValue}"); return inputValue; } Console.WriteLine(errorMsg); } } /// <summary> /// 获取符合规则的任务开始日期 /// </summary> /// <param name="prompt">输入提示语</param> /// <param name="formatErrorMsg">格式错误提示语</param> /// <param name="weekendErrorMsg">周末日期提示语</param> /// <returns>合法的开始日期</returns> private static DateTime GetValidStartDate(string prompt, string formatErrorMsg, string weekendErrorMsg) { DateTime inputDate; while (true) { Console.WriteLine(prompt); if (!DateTime.TryParse(Console.ReadLine(), out inputDate)) { Console.WriteLine(formatErrorMsg); continue; } if (inputDate.DayOfWeek is DayOfWeek.Saturday or DayOfWeek.Sunday) { Console.WriteLine(string.Format(weekendErrorMsg, inputDate.ToString("MM/dd/yyyy"), inputDate.DayOfWeek)); continue; } Console.WriteLine($"Start Date is : {inputDate:MM/dd/yyyy}"); return inputDate; } } /// <summary> /// 计算任务结束日期,自动跳过周六周日 /// </summary> /// <param name="startDate">任务开始日期(必须为工作日)</param> /// <param name="requiredWorkDays">所需工作日总数</param> /// <returns>任务结束日期(工作日)</returns> private static DateTime CalculateWorkEndDate(DateTime startDate, int requiredWorkDays) { DateTime currentDate = startDate; int completedDays = 1; // 开始日期当天算第一个工作日 while (completedDays < requiredWorkDays) { currentDate = currentDate.AddDays(1); // 跳过周末 if (currentDate.DayOfWeek is not DayOfWeek.Saturday and not DayOfWeek.Sunday) { completedDays++; } } return currentDate; } }
四、测试验证
针对你提到的测试用例:总工时130、每日工作时长4、开始日期08/02/2021,计算得所需工作日为33天,运行上述代码得到的结束日期为09/15/2021,结果正确。
内容的提问来源于stack exchange,提问作者rissa
相关产品推荐
相关产品推荐

