簡體   English   中英

C#:根據用戶輸入創建字符串數組,然后,如果無法將其解析為int數組,請重試輸入

[英]C#: Creating a string array from user input, then if it can't be parsed into int array, retrying the input

我一直在嘗試使用C#制作矩陣控制台應用程序,但是在檢查用戶輸入的可行性時,我一直很努力。 這是代碼:

//INPUT OF VALUES INTO MATRIX A BY ROWS
int ValuesCounter = 2; //index for new arrays created on fail.
string[] valuesValuesCounter = Console.ReadLine().Split(' '); //read user input into string array
int[] valuescheckValuesCounter = new int[valuesValuesCounter.Length]; //test array to check if user input can be parsed into int
for (int i = 0; i <= valuesValuesCounter.Length; i++) // loop for checking parseability of individual array items
{
    while(!int.TryParse(valuesValuesCounter[i], out valuescheckValuesCounter[i])) //same
    {
        /*if it can't be parsed, create new array and try again*/
        ValuesCounter += 2;
        Console.WriteLine("Wrong values! Please try again!");
        valuesValuesCounter = Console.ReadLine().Split(' ');
        valuescheckValuesCounter = new int[valuesValuesCounter.Length];
    }
}

我懷疑這是非常有效的。 我嘗試使用ArrayList代替,因為您只能刪除其中的值,但是無法拆分,因此我不知道如何使其工作。 有什么更好的方法可以做到這一點?
還嘗試進行自己的研究,但沒有找到任何解決方案(也許它在那里,我只是因為沒有看到它而愚蠢,我不知道)。

如何在C#中刪除數組?
將2D字符串數組轉換為2D int數組(多維數組)
C#arraylist用戶輸入
int.TryParse解析為一個對象數組 (這看起來很接近,但是我看不到有任何東西可以重試輸入以防無法解析)。

所以你有它。 我很傻,所以如果這個問題看起來很愚蠢,那是因為問這個問題的那個愚蠢的人。

首先,使用戶體驗盡可能好。 一次輸入矩陣容易出錯,使用戶的生活更加輕松並逐步進行。

第二,制作執行簡單任務的小型方法。 如果出現新的要求,它們就更容易推理,更容易編寫,更容易調試和更容易修改。 不要讓方法做太多事情,它只會給您帶來頭痛,並且會花費不必要的調試時間。 如果您正在學習,請不要擔心似乎正在分解為看似荒謬的簡單任務,您不會后悔。 永遠記住,您能想象到的最復雜的問題總是可以解決較小更簡單的問題。

因此,您需要的第一件事是一種提示用戶輸入有效整數的方法,因此讓我們嘗試一下:

private static int GetIntegerFromUser(string prompt)
{
    int value;
    Console.Write($"{prompt}: ");

    while (!int.TryParse(Console.ReadLine(), out value))
    {
        Console.WriteLine("That is not a valid value. Please try again.");
        Console.Write($"{prompt}: ");
    }

    return value;
}

看看如何運作? 這種方法在生活中有一個目標。 讓用戶輸入有效的整數。 不必介意整數是什么,它不在乎,那不是它的工作,這種方法將不斷詢問用戶,直到實現其生活目標為止。

好的,接下來是什么? 填寫矩陣時,我們需要知道:

  1. 行數
  2. 列數
  3. 價值觀

好吧,讓我們寫一些方法來獲取:

private static (int Rows, int Columns) GetMatrixSize()
{
    var rows = GetIntegerFromUser("Please enter number of rows");
    var columns = GetIntegerFromUser("Please enter number of columns");
    return (rows, columns);
}

和,

private static int[,] GetMatrixValues(int rows, int columns)
{
    var matrix = new int[rows, columns];

    for (var row = 0; row < rows; row++)
    {
        for (var column = 0; column < columns; column++)
        {
            matrix[row, column] =
               GetIntegerFromUser($"Enter matrix value [{row}, {column}]");
        }
    }
}

現在您應該意識到為什么制作執行簡單任務的小型方法是一個好主意的原因。 因為機會真的很好,所以您將可以重用它們,一旦您知道該方法正確運行,它便會在任何地方正確運行。

好的,我們已經有了所有需要的東西,現在只需將它們放在一起即可:

public static int[,] GetMatrixFromUser()
{
    var size = GetMatrixSize();
    return GetMatrixValues(size.Rows, size.Columns);
}

讀起來有多容易?

至此,我們完成了! 真? 好吧 我們根本沒有價值驗證,這可能是一個問題。 如果有人決定輸入負數行會怎樣? 好的,沒問題,讓我們建立一個確保值在有效范圍內的方法:

private static bool IsInRange(int value, 
                              int lowerInclusiveBound,
                              int upperExclusiveBound,
                              string messageOnFailedValidation)
{
    if (value >= lowerInclusiveBound &&
        value < upperExclusiveBound)
        return true;

    Console.WriteLine(messageOnFailedValidation);
    return false;
}

現在,由於我們使用了可以很好地完成定義任務的小型方法,因此添加新要求很容易就可以對GetMatrixSize方法進行一些修改:

private static (int Rows, int Columns) GetMatrixSize()
{
    int rows, columns;

    do
    {
        rows = GetIntegerFromUser("Please enter number of rows");
        columns = GetIntegerFromUser("Please enter number of columns");
    } while (!IsInRange(rows,
                        1,
                        int.MaxValue,
                        "Number of rows must be equal or greater than one.") |
             !IsInRange(columns,
                        1,
                        int.MaxValue,
                        "Number of columns must be equal or greater than one."));

    return (rows, columns);
}

是的,現在我們完成了...

幾乎! 最后一件事。 另一個好習慣是確保您所相信的事實是真實的。 您認為GetMatrixValues內部的GetMatrixValues什么? 您認為rowscolumns將具有有效值。 但是您的信念純粹基於信念,您沒有檢查這是否是真的。

但是等等...我已經簽入GetMatrixSize嗎? 是的,但是您如何保證GetMatrixValues不會再通過其他方法調用GetMatrixValues 可重用性還記得嗎?

在這里,您可以走兩條路。 如果值無效或可以斷言這些值實際上有效,則可以引發異常。 由於該方法是私有的,並且具有無效值,可能意味着在調用堆棧中的某個地方存在錯誤,因此,更好的選擇是聲明您的真相:

private static int[,] GetMatrixValues(int rows, int columns)
{
    Debug.Assert(rows > 0 && columns > 0);
    var matrix = ...
}

還有其他關於信仰的真理嗎? 誰是確保upperExclusiveBoundlowerInclusiveBoundIsInRange實際意義? 是否有人阻止您撥打以下電話: IsInRange(10, 100, -100, ...) 這樣的調用可能是代碼中其他地方的錯誤,通過使這類錯誤更容易發現,可以使您的生活更輕松。 再次聲明您的事實:

private static bool IsInRange(int value, 
                              int lowerInclusiveBound,
                              int upperExclusiveBound,
                              string messageOnFailedValidation)
{  
    Debug.Assert(upperExclusiveBound > lowerInclusiveBound);

    if ...
}  

一個很好的例子也可以由上無論您應檢查promptGetIntegerFromUsermessageOnFailedValidationIsInRange不為空或空字符串,等等。

是的,現在我們真的完成了。

您不需要for循環內的while循環。 只需檢查每個項目的有效性和中斷,如果遇到無效的字符串,當然,如果所有的字符串都是有效的(循環將結束),並且i等於數組的長度:

bool success = false;
do
{
     int i = 0;
     string[] valuesValuesCounter = Console.ReadLine().Split(' ');
     int[] valuescheckValuesCounter = new int[valuesValuesCounter.Length];
     for (int i = 0; i <= valuesValuesCounter.Length; i++)
        if(!int.TryParse(valuesValuesCounter[i], out valuescheckValuesCounter[i]) break;
     success = i == valuesValuesCounter.Length;
}while(!success);

另一種方法是使用Linq:

do
{
    int i = 0;
    string[] valuesValuesCounter = Console.ReadLine().Split(' ');
    int[] valuescheckValuesCounter = new int[valuesValuesCounter.Length];
    success = valuesValuesCounter.All(x => int.TryParse(x, out valuescheckValuesCounter[i++]);
}while(!success);

暫無
暫無

聲明:本站的技術帖子網頁,遵循CC BY-SA 4.0協議,如果您需要轉載,請注明本站網址或者原文地址。任何問題請咨詢:yoyou2525@163.com.

 
粵ICP備18138465號  © 2020-2024 STACKOOM.COM