c# - C# 行程申请 - 在继续之前重复查询
问题描述
我一直在尝试重构一个 C# 控制台应用程序,该应用程序询问用户想去哪里旅行、记录位置、重复问题,然后询问另一个位置或打印用户指定的位置(结束程序)。
鉴于代码中的注释说明,我似乎已经准备好了一切。但是,在 ContinuePlanning() 方法中,无论用户响应如何,它都会在继续程序之前重复第二次,我无法弄清楚原因。
据我所知,逻辑是有道理的,但我知道我在代码的某个地方遗漏了一个简单的步骤。谁能提供一些关于为什么会发生这种情况的见解?
程序.cs
using System;
using System.Collections.Generic;
// Synopsis: Everyone loves a great vacation! This application helps you keep track of all the wonderful places on your bucket list.
namespace TravelPlanner
{
class Program
{
static void Main(string[] args)
{
// Display header
Console.WriteLine("");
Console.WriteLine("========================================");
Console.WriteLine(" TRAVEL PLANNER ");
Console.WriteLine("========================================");
Console.WriteLine("");
Console.WriteLine("Helping you keep track of the places you will travel. \r\n");
/*
3. PLAN ITINERARY
-------------------------
[ After completing steps #1 and #2, lets take the optimization even further...
Reviewing what you've accomplished, you will notice that each step now contains a single line
of code. We've compartmentalized each action into a method, excellent refactoring!
The while loop below contains these two actions. Looping over those actions is how we plan the
itinerary. So lets migrate the loop and the nested actions into the middle of the Plan() method.
The only thing left now is the creation of the list. Add one line that sets the value of
"locations" to the calling of that method. Planning the itinerary has now be accomplished with
one line within Main()!
The Main() method has become an outline of the application... after displaying the header, we Plan(),
then display what we've planned, and finally display a footer.
Uh, oh... don't forget the syntax problem!
] */
// Create List
List<string> locations = new List<string>();
// Repeat until all locations are added
bool planning = true;
while (planning)
{
/*
1. GET LOCATION
-------------------------
[ Migrate the following, except for the last line, into the Itinerary class' (Itinerary.cs)
GetLocation() method. Then change the last line so "location," within locations.Add()
calls that GetLocation() method. Refer to the lesson on static classes/methods to see
how you can call methods from other classes.
Also, make sure to fix the validation's logic errors!
] */
locations.Add(Itinerary.GetLocation());
/*
2. CONTINUE PLANNING
-------------------------
[ Migrate all of the following into the ContinuePlanning() method. Replace this with a
single line that sets the value of the "planning" variable to the returned value.
This validation also contains a logic error!
] */
planning = Itinerary.ContinuePlanning(planning);
}
/*
4. DISPLAY ITINERARY
-------------------------
[ The Itinerary class has allowed us to organize the code, containing all the methods (processes)
related to the planning of the itinerary: Plan(), GetLocation(), and ContinuePlanning().
Since the following code is used to display the itinerary, it should be there too.
Migrate the following into the Display() method. Then replace with a call to that method.
Of course you'll need an argument for the "locations" list to display.
Carefully read the output to spot a syntax error... we want to practice string interpolation!
] */
Itinerary.Display(locations);
// -------------------------
// Display footer
Console.WriteLine("");
Console.WriteLine("========================================");
Console.WriteLine("Safe travels on your future trips!");
Console.WriteLine("");
Console.ReadKey();
}
// End class
}
}
行程.cs
using System;
using System.Collections.Generic;
// Synopsis: Collection of methods used in the planning and displaying of travel itinerary locations.
namespace TravelPlanner
{
public class Itinerary
{
// Plan itinerary
public static List<string> Plan()
{
// Create list for locations
List<string> locations = new List<string>();
return locations;
}
// Request location from user
public static string GetLocation()
{
// Initial request
Console.WriteLine("");
Console.WriteLine("--------------------");
Console.Write("Where would you like to travel? ");
string location = Console.ReadLine();
// Validate user input
while (String.IsNullOrWhiteSpace(location))
{
// Reminder not to leave blank
Console.WriteLine("Please do not leave this blank! \r\n");
// Ask again where they would like to go
Console.Write("Where would you like to travel? ");
// String for user input
string newlocation = Console.ReadLine();
}
return location;
}
// Question - another location?
public static bool ContinuePlanning(bool planning)
{
// Another location?
Console.Write("Another location? (yes/no) ");
string response = Console.ReadLine();
// Validate user input
if (response.ToLower() != "yes" || response.ToLower() != "no")
{
// Error message
Console.WriteLine("Please only enter yes or no.");
// Re-ask question
Console.Write("Another location? (yes/no) ");
response = Console.ReadLine();
}
// Continue planning?
if (response.ToLower() == "no")
{
planning = false;
}
return planning;
}
// Display itinerary locations
public static void Display(List<string> locations)
{
//Output the number of locations the user will visit
Console.WriteLine("");
Console.WriteLine("--------------------");
Console.WriteLine($" You will take {locations.Count} trip(s).");
//Output each location the user will visit
for (int i = 0; i < locations.Count; i++)
{
Console.WriteLine($" You will visit {locations[i]}.");
}
}
// End class
}
}
提前致谢!
解决方案
“据我所知,逻辑是有道理的”
这可能是因为您正在阅读它,因为有人可能会用英语说它,而不是作为逻辑代码语句。
- 在英语中,我们会说,“如果他们没有回答“是”或“否”,那么再问他们一次。
- 在代码中,我们用不同的方式表达它:“如果答案不是“是”并且答案不是“否”,那么再问他们一次”
原因如下:
- 如果任一操作数是,则条件逻辑 OR 运算符(
||
) 将返回(并且评估将在第一个结果处停止):true
true
true
false || false == false
false || true == true
true || false == true
true || true == true
- 这与条件逻辑 AND 运算符(
&&
) 不同,后者true
仅在两个操作数都为真时才返回。false && false == false
false && true == false
true && false == false
true && true == true
现在让我们看看你的if
情况ContinuePlanning
:
if (response.ToLower() != "yes" || response.ToLower() != "no")
现在,如果有人进入"yes"
,第一部分是false
,第二部分是true
,所以条件将评估为true
。同样,如果他们输入"no"
(或任何其他输入),第一部分是true
,因此条件将评估为true
相反,我们要测试第一部分和第二部分是否为真,所以我们应该使用&&
运算符:
if (response.ToLower() != "yes" && response.ToLower() != "no")
现在如果他们输入"yes"
or "no"
,那么只有那些操作数是true
,所以条件将评估为false
。如果他们输入任何其他输入,那么两个条件都是true
,这就是我们正在寻找的。
另一个问题是这个方法接受一个参数,如果用户输入了bool
,修改它,然后返回它。这样做的问题是,如果变量开始是,那么无论用户输入什么我们都会返回。此外,此方法不需要来自调用者的任何参数。我们应该只在本地声明变量。false
"no"
false
false
如果他们输入"yes"
or "no"
,我们也只检查一次,但我们应该循环执行,以防他们真的是笨拙的打字员。:)
// Question - another location?
public static bool ContinuePlanning()
{
// Start out assuming we will contiune planning
bool continuePlanning = true;
// Another location?
Console.Write("Another location? (yes/no) ");
// Get the user reponse and make it lower case
string response = Console.ReadLine().ToLower();
// Validate user input
while (response != "yes" && response != "no")
{
// Error message
Console.WriteLine("Please only enter yes or no.");
// Re-ask question
Console.Write("Another location? (yes/no) ");
response = Console.ReadLine();
}
// If the user doesn't want to continue, set our variable
if (response == "no") continuePlanning = false;
return continuePlanning;
}
推荐阅读
- javascript - 将数据 url 转换为可用于发送到后端 Web api 并存储在数据库中的格式
- r - 当它感觉到R中的某个单词时如何开始一个新行?
- pandas - 使用 pandas 读取列名上有标点符号的 csv
- javascript - console.log(array[0]) 在 promise 中未定义
- python - BeautifulSoup中股票的刮变价格
- opengl - Opengl & glsl (vec4 * vec4) 冗余
- javascript - ES6 推特文本导入
- linux - 重命名后文件在 Ubuntu 18.04 上消失了
- dataframe - 将 pyspark 列值向左移动 1
- dependencies - https://codesandbox.io 如何实现对本地版本的依赖