C# Маршрутная заявка - повторный запрос перед продолжением - PullRequest
0 голосов
/ 05 августа 2020

Я пытался провести рефакторинг консольного приложения C#, которое спрашивает, куда пользователь хотел бы отправиться, записывает местоположение, повторяет вопрос, а затем либо запрашивает другое местоположение, либо печатает местоположения, указанные пользователем ( завершение программы).

Учитывая прокомментированные инструкции в коде, мне кажется, что все на месте. Однако в методе ContinuePlanning () он повторяется во второй раз, независимо от ответа пользователя, прежде чем продолжить работу в программе, и мне сложно понять, почему.

Насколько я могу судить, logi c делает смысл, но я знаю, что где-то в коде отсутствует простой шаг. Может ли кто-нибудь рассказать, почему это происходит?

Program.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
    }
}

Itinerary.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
    }
}

Заранее спасибо!

1 Ответ

0 голосов
/ 05 августа 2020

«Насколько я могу судить, лог c имеет смысл»

Вероятно потому, что вы читаете это так, как кто-то может сказать это в engli sh, но не как логическое выражение кода.

  • На английском sh мы бы сказали: "Если они не ответили" да ", или «нет», затем спросите их снова. »
  • В коде мы формулируем это по-другому: « Если ответ был не «да», и ответ не было «нет», затем спросите их еще раз »

Вот почему:

  • Условное логическое ИЛИ (||) вернет 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" или "no", только из этих операндов будет true, поэтому условие будет оцениваться как false. Если они введут любой другой ввод, то оба условия будут true, что мы и ищем.

Другая проблема заключается в том, что этот метод принимает аргумент bool, изменяет его на false, если пользователь вводит "no", а затем возвращает его. Проблема в том, что если переменная начинается с false, мы возвращаем false независимо от того, что вводит пользователь. Кроме того, этот метод не требует каких-либо аргументов от вызывающего. Вместо этого мы должны просто объявить переменную локально.

Мы также проверяем только один раз, вводят ли они "yes" или "no", но мы должны сделать это в al oop на всякий случай, если они действительно неуклюжие машинисты . :)

// 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;
}
...