C#: Creating a string array from user input, then if it can't be parsed into int array, retrying the input
I've been trying to make a matrix console application in C# but I am struggling when it comes to checking viability of user input. Here's the code:
//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];
}
}
I doubt this is very efficient. I've tried using ArrayList instead because you can just remove the values in it, but it can't be split so I don't know how to make it work. What is a better way to do this?
Also tried conducting my own research, but didn't find any solution (maybe it's there and I am just stupid for not seeing it, I don't know).
How to delete an array in c#?
Convert 2D string array into 2D int array (Multidimensional Arrays)
C# arraylist user input
int.TryParse out into an object array (this seems pretty close but I don't see anything there to retry the input in case it can't be parsed).
So there you have it. I'm pretty dumb so if this question seems stupid it's because the one asking it is stupid.
c# arrays user-input tryparse
add a comment |
I've been trying to make a matrix console application in C# but I am struggling when it comes to checking viability of user input. Here's the code:
//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];
}
}
I doubt this is very efficient. I've tried using ArrayList instead because you can just remove the values in it, but it can't be split so I don't know how to make it work. What is a better way to do this?
Also tried conducting my own research, but didn't find any solution (maybe it's there and I am just stupid for not seeing it, I don't know).
How to delete an array in c#?
Convert 2D string array into 2D int array (Multidimensional Arrays)
C# arraylist user input
int.TryParse out into an object array (this seems pretty close but I don't see anything there to retry the input in case it can't be parsed).
So there you have it. I'm pretty dumb so if this question seems stupid it's because the one asking it is stupid.
c# arrays user-input tryparse
Try rewriting by putting the loop over the input. Only call ReadLine in one place. break out of loop if input correct.
– Garr Godfrey
Nov 24 '18 at 20:21
add a comment |
I've been trying to make a matrix console application in C# but I am struggling when it comes to checking viability of user input. Here's the code:
//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];
}
}
I doubt this is very efficient. I've tried using ArrayList instead because you can just remove the values in it, but it can't be split so I don't know how to make it work. What is a better way to do this?
Also tried conducting my own research, but didn't find any solution (maybe it's there and I am just stupid for not seeing it, I don't know).
How to delete an array in c#?
Convert 2D string array into 2D int array (Multidimensional Arrays)
C# arraylist user input
int.TryParse out into an object array (this seems pretty close but I don't see anything there to retry the input in case it can't be parsed).
So there you have it. I'm pretty dumb so if this question seems stupid it's because the one asking it is stupid.
c# arrays user-input tryparse
I've been trying to make a matrix console application in C# but I am struggling when it comes to checking viability of user input. Here's the code:
//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];
}
}
I doubt this is very efficient. I've tried using ArrayList instead because you can just remove the values in it, but it can't be split so I don't know how to make it work. What is a better way to do this?
Also tried conducting my own research, but didn't find any solution (maybe it's there and I am just stupid for not seeing it, I don't know).
How to delete an array in c#?
Convert 2D string array into 2D int array (Multidimensional Arrays)
C# arraylist user input
int.TryParse out into an object array (this seems pretty close but I don't see anything there to retry the input in case it can't be parsed).
So there you have it. I'm pretty dumb so if this question seems stupid it's because the one asking it is stupid.
c# arrays user-input tryparse
c# arrays user-input tryparse
edited Nov 24 '18 at 20:43
Fabio
20k22047
20k22047
asked Nov 24 '18 at 20:17
a morona moron
31
31
Try rewriting by putting the loop over the input. Only call ReadLine in one place. break out of loop if input correct.
– Garr Godfrey
Nov 24 '18 at 20:21
add a comment |
Try rewriting by putting the loop over the input. Only call ReadLine in one place. break out of loop if input correct.
– Garr Godfrey
Nov 24 '18 at 20:21
Try rewriting by putting the loop over the input. Only call ReadLine in one place. break out of loop if input correct.
– Garr Godfrey
Nov 24 '18 at 20:21
Try rewriting by putting the loop over the input. Only call ReadLine in one place. break out of loop if input correct.
– Garr Godfrey
Nov 24 '18 at 20:21
add a comment |
2 Answers
2
active
oldest
votes
First of all, make the user experience as good as possible. Inputing a matrix all at once can be error prone, make the user's life easier and take it step by step.
Second, make small methods that perform simple tasks; they are easier to reason about, easier to write, easier to debug and easier to modify if new requirements come along. Don't make methods do too much, it will only buy you headaches and more debugging hours than necessary. If you are learning, don't worry if it seems you are breaking down to seemingly absurdly simple tasks, you wont regret it. Always remember that the most complicated problems you can imagine are always solved solving smaller and easier ones.
So, the first thing you need is a method that prompts the user for a valid integer, so lets try that:
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;
}
See how that works? This method has one single goal in life; get the user to enter a valid integer. Never mind what the integer is for, it doesn't care, thats not its job, this method will keep asking the user until its goal in life is achieved.
Ok, whats next? When filling in a matrix we'll need to know:
- Number of rows
- Number of columns
- Values
Ok lets write some methods that fetch just that:
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);
}
And,
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}]");
}
}
}
Now you should come to realize why making small methods that do simple tasks is such a great idea. Because chances are really good you'll get to reuse them and once you know the method works correctly, it will work correctly everywhere.
Ok, we've got all we need, now its just a matter of putting it all together:
public static int[,] GetMatrixFromUser()
{
var size = GetMatrixSize();
return GetMatrixValues(size.Rows, size.Columns);
}
How easy does that read?
So, we're done! Really? Well... no. We have no value validation at all, and that can be a problem. What happens if someone decides to input a negative number of rows? Ok, no problem, lets make a method that makes sure a value is inside a valid range:
private static bool IsInRange(int value,
int lowerInclusiveBound,
int upperExclusiveBound,
string messageOnFailedValidation)
{
if (value >= lowerInclusiveBound &&
value < upperExclusiveBound)
return true;
Console.WriteLine(messageOnFailedValidation);
return false;
}
And now, becuase we've used small methods that do well defined tasks, adding the new requirement is easily done modifying our GetMatrixSize
method a little:
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);
}
Yeah, now we are done...
Almost! One last thing. Another good habit is making sure the truths you believe in are actually true. What are you believing to be true inside GetMatrixValues
? You believe that rows
and columns
will have valid values. But your belief is purely based on faith, you are not checking if this is true.
But wait... I already checked in GetMatrixSize
right? Yes, but what guarantee do you have that GetMatrixValues
won't be called from some other method later on? Reusability remember?
Here you can go two paths. You can throw an exception if the values are not valid or you can assert that the values are in fact valid. Because the method is private and having invalid values probably means a bug somewhere up the callstack, the better option here is to assert your truths:
private static int[,] GetMatrixValues(int rows, int columns)
{
Debug.Assert(rows > 0 && columns > 0);
var matrix = ...
}
Any other truths merely on faith? Who is making sure that upperExclusiveBound
and lowerInclusiveBound
in IsInRange
actually make sense? Is someone stopping you from making the following call: IsInRange(10, 100, -100, ...)
? A call like that is probably a bug somewhere else in your code, make your life easier by making these kind of bugs easier to spot. Again, assert your truths:
private static bool IsInRange(int value,
int lowerInclusiveBound,
int upperExclusiveBound,
string messageOnFailedValidation)
{
Debug.Assert(upperExclusiveBound > lowerInclusiveBound);
if ...
}
A good case could also be made on wether you should be checking that prompt
in GetIntegerFromUser
and messageOnFailedValidation
in IsInRange
are not empty or null strings, etc.
Yeah, now we are really done.
add a comment |
You do not need the while loop inside the for loop. just check each item for validity and break, if you encounter an invalid string, of course if all were valid (loop will go to the end) and i
will be equal to length of your array:
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);
Another way would be using 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);
add a comment |
Your Answer
StackExchange.ifUsing("editor", function () {
StackExchange.using("externalEditor", function () {
StackExchange.using("snippets", function () {
StackExchange.snippets.init();
});
});
}, "code-snippets");
StackExchange.ready(function() {
var channelOptions = {
tags: "".split(" "),
id: "1"
};
initTagRenderer("".split(" "), "".split(" "), channelOptions);
StackExchange.using("externalEditor", function() {
// Have to fire editor after snippets, if snippets enabled
if (StackExchange.settings.snippets.snippetsEnabled) {
StackExchange.using("snippets", function() {
createEditor();
});
}
else {
createEditor();
}
});
function createEditor() {
StackExchange.prepareEditor({
heartbeatType: 'answer',
autoActivateHeartbeat: false,
convertImagesToLinks: true,
noModals: true,
showLowRepImageUploadWarning: true,
reputationToPostImages: 10,
bindNavPrevention: true,
postfix: "",
imageUploader: {
brandingHtml: "Powered by u003ca class="icon-imgur-white" href="https://imgur.com/"u003eu003c/au003e",
contentPolicyHtml: "User contributions licensed under u003ca href="https://creativecommons.org/licenses/by-sa/3.0/"u003ecc by-sa 3.0 with attribution requiredu003c/au003e u003ca href="https://stackoverflow.com/legal/content-policy"u003e(content policy)u003c/au003e",
allowUrls: true
},
onDemand: true,
discardSelector: ".discard-answer"
,immediatelyShowMarkdownHelp:true
});
}
});
Sign up or log in
StackExchange.ready(function () {
StackExchange.helpers.onClickDraftSave('#login-link');
});
Sign up using Google
Sign up using Facebook
Sign up using Email and Password
Post as a guest
Required, but never shown
StackExchange.ready(
function () {
StackExchange.openid.initPostLogin('.new-post-login', 'https%3a%2f%2fstackoverflow.com%2fquestions%2f53461993%2fc-creating-a-string-array-from-user-input-then-if-it-cant-be-parsed-into-int%23new-answer', 'question_page');
}
);
Post as a guest
Required, but never shown
2 Answers
2
active
oldest
votes
2 Answers
2
active
oldest
votes
active
oldest
votes
active
oldest
votes
First of all, make the user experience as good as possible. Inputing a matrix all at once can be error prone, make the user's life easier and take it step by step.
Second, make small methods that perform simple tasks; they are easier to reason about, easier to write, easier to debug and easier to modify if new requirements come along. Don't make methods do too much, it will only buy you headaches and more debugging hours than necessary. If you are learning, don't worry if it seems you are breaking down to seemingly absurdly simple tasks, you wont regret it. Always remember that the most complicated problems you can imagine are always solved solving smaller and easier ones.
So, the first thing you need is a method that prompts the user for a valid integer, so lets try that:
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;
}
See how that works? This method has one single goal in life; get the user to enter a valid integer. Never mind what the integer is for, it doesn't care, thats not its job, this method will keep asking the user until its goal in life is achieved.
Ok, whats next? When filling in a matrix we'll need to know:
- Number of rows
- Number of columns
- Values
Ok lets write some methods that fetch just that:
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);
}
And,
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}]");
}
}
}
Now you should come to realize why making small methods that do simple tasks is such a great idea. Because chances are really good you'll get to reuse them and once you know the method works correctly, it will work correctly everywhere.
Ok, we've got all we need, now its just a matter of putting it all together:
public static int[,] GetMatrixFromUser()
{
var size = GetMatrixSize();
return GetMatrixValues(size.Rows, size.Columns);
}
How easy does that read?
So, we're done! Really? Well... no. We have no value validation at all, and that can be a problem. What happens if someone decides to input a negative number of rows? Ok, no problem, lets make a method that makes sure a value is inside a valid range:
private static bool IsInRange(int value,
int lowerInclusiveBound,
int upperExclusiveBound,
string messageOnFailedValidation)
{
if (value >= lowerInclusiveBound &&
value < upperExclusiveBound)
return true;
Console.WriteLine(messageOnFailedValidation);
return false;
}
And now, becuase we've used small methods that do well defined tasks, adding the new requirement is easily done modifying our GetMatrixSize
method a little:
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);
}
Yeah, now we are done...
Almost! One last thing. Another good habit is making sure the truths you believe in are actually true. What are you believing to be true inside GetMatrixValues
? You believe that rows
and columns
will have valid values. But your belief is purely based on faith, you are not checking if this is true.
But wait... I already checked in GetMatrixSize
right? Yes, but what guarantee do you have that GetMatrixValues
won't be called from some other method later on? Reusability remember?
Here you can go two paths. You can throw an exception if the values are not valid or you can assert that the values are in fact valid. Because the method is private and having invalid values probably means a bug somewhere up the callstack, the better option here is to assert your truths:
private static int[,] GetMatrixValues(int rows, int columns)
{
Debug.Assert(rows > 0 && columns > 0);
var matrix = ...
}
Any other truths merely on faith? Who is making sure that upperExclusiveBound
and lowerInclusiveBound
in IsInRange
actually make sense? Is someone stopping you from making the following call: IsInRange(10, 100, -100, ...)
? A call like that is probably a bug somewhere else in your code, make your life easier by making these kind of bugs easier to spot. Again, assert your truths:
private static bool IsInRange(int value,
int lowerInclusiveBound,
int upperExclusiveBound,
string messageOnFailedValidation)
{
Debug.Assert(upperExclusiveBound > lowerInclusiveBound);
if ...
}
A good case could also be made on wether you should be checking that prompt
in GetIntegerFromUser
and messageOnFailedValidation
in IsInRange
are not empty or null strings, etc.
Yeah, now we are really done.
add a comment |
First of all, make the user experience as good as possible. Inputing a matrix all at once can be error prone, make the user's life easier and take it step by step.
Second, make small methods that perform simple tasks; they are easier to reason about, easier to write, easier to debug and easier to modify if new requirements come along. Don't make methods do too much, it will only buy you headaches and more debugging hours than necessary. If you are learning, don't worry if it seems you are breaking down to seemingly absurdly simple tasks, you wont regret it. Always remember that the most complicated problems you can imagine are always solved solving smaller and easier ones.
So, the first thing you need is a method that prompts the user for a valid integer, so lets try that:
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;
}
See how that works? This method has one single goal in life; get the user to enter a valid integer. Never mind what the integer is for, it doesn't care, thats not its job, this method will keep asking the user until its goal in life is achieved.
Ok, whats next? When filling in a matrix we'll need to know:
- Number of rows
- Number of columns
- Values
Ok lets write some methods that fetch just that:
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);
}
And,
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}]");
}
}
}
Now you should come to realize why making small methods that do simple tasks is such a great idea. Because chances are really good you'll get to reuse them and once you know the method works correctly, it will work correctly everywhere.
Ok, we've got all we need, now its just a matter of putting it all together:
public static int[,] GetMatrixFromUser()
{
var size = GetMatrixSize();
return GetMatrixValues(size.Rows, size.Columns);
}
How easy does that read?
So, we're done! Really? Well... no. We have no value validation at all, and that can be a problem. What happens if someone decides to input a negative number of rows? Ok, no problem, lets make a method that makes sure a value is inside a valid range:
private static bool IsInRange(int value,
int lowerInclusiveBound,
int upperExclusiveBound,
string messageOnFailedValidation)
{
if (value >= lowerInclusiveBound &&
value < upperExclusiveBound)
return true;
Console.WriteLine(messageOnFailedValidation);
return false;
}
And now, becuase we've used small methods that do well defined tasks, adding the new requirement is easily done modifying our GetMatrixSize
method a little:
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);
}
Yeah, now we are done...
Almost! One last thing. Another good habit is making sure the truths you believe in are actually true. What are you believing to be true inside GetMatrixValues
? You believe that rows
and columns
will have valid values. But your belief is purely based on faith, you are not checking if this is true.
But wait... I already checked in GetMatrixSize
right? Yes, but what guarantee do you have that GetMatrixValues
won't be called from some other method later on? Reusability remember?
Here you can go two paths. You can throw an exception if the values are not valid or you can assert that the values are in fact valid. Because the method is private and having invalid values probably means a bug somewhere up the callstack, the better option here is to assert your truths:
private static int[,] GetMatrixValues(int rows, int columns)
{
Debug.Assert(rows > 0 && columns > 0);
var matrix = ...
}
Any other truths merely on faith? Who is making sure that upperExclusiveBound
and lowerInclusiveBound
in IsInRange
actually make sense? Is someone stopping you from making the following call: IsInRange(10, 100, -100, ...)
? A call like that is probably a bug somewhere else in your code, make your life easier by making these kind of bugs easier to spot. Again, assert your truths:
private static bool IsInRange(int value,
int lowerInclusiveBound,
int upperExclusiveBound,
string messageOnFailedValidation)
{
Debug.Assert(upperExclusiveBound > lowerInclusiveBound);
if ...
}
A good case could also be made on wether you should be checking that prompt
in GetIntegerFromUser
and messageOnFailedValidation
in IsInRange
are not empty or null strings, etc.
Yeah, now we are really done.
add a comment |
First of all, make the user experience as good as possible. Inputing a matrix all at once can be error prone, make the user's life easier and take it step by step.
Second, make small methods that perform simple tasks; they are easier to reason about, easier to write, easier to debug and easier to modify if new requirements come along. Don't make methods do too much, it will only buy you headaches and more debugging hours than necessary. If you are learning, don't worry if it seems you are breaking down to seemingly absurdly simple tasks, you wont regret it. Always remember that the most complicated problems you can imagine are always solved solving smaller and easier ones.
So, the first thing you need is a method that prompts the user for a valid integer, so lets try that:
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;
}
See how that works? This method has one single goal in life; get the user to enter a valid integer. Never mind what the integer is for, it doesn't care, thats not its job, this method will keep asking the user until its goal in life is achieved.
Ok, whats next? When filling in a matrix we'll need to know:
- Number of rows
- Number of columns
- Values
Ok lets write some methods that fetch just that:
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);
}
And,
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}]");
}
}
}
Now you should come to realize why making small methods that do simple tasks is such a great idea. Because chances are really good you'll get to reuse them and once you know the method works correctly, it will work correctly everywhere.
Ok, we've got all we need, now its just a matter of putting it all together:
public static int[,] GetMatrixFromUser()
{
var size = GetMatrixSize();
return GetMatrixValues(size.Rows, size.Columns);
}
How easy does that read?
So, we're done! Really? Well... no. We have no value validation at all, and that can be a problem. What happens if someone decides to input a negative number of rows? Ok, no problem, lets make a method that makes sure a value is inside a valid range:
private static bool IsInRange(int value,
int lowerInclusiveBound,
int upperExclusiveBound,
string messageOnFailedValidation)
{
if (value >= lowerInclusiveBound &&
value < upperExclusiveBound)
return true;
Console.WriteLine(messageOnFailedValidation);
return false;
}
And now, becuase we've used small methods that do well defined tasks, adding the new requirement is easily done modifying our GetMatrixSize
method a little:
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);
}
Yeah, now we are done...
Almost! One last thing. Another good habit is making sure the truths you believe in are actually true. What are you believing to be true inside GetMatrixValues
? You believe that rows
and columns
will have valid values. But your belief is purely based on faith, you are not checking if this is true.
But wait... I already checked in GetMatrixSize
right? Yes, but what guarantee do you have that GetMatrixValues
won't be called from some other method later on? Reusability remember?
Here you can go two paths. You can throw an exception if the values are not valid or you can assert that the values are in fact valid. Because the method is private and having invalid values probably means a bug somewhere up the callstack, the better option here is to assert your truths:
private static int[,] GetMatrixValues(int rows, int columns)
{
Debug.Assert(rows > 0 && columns > 0);
var matrix = ...
}
Any other truths merely on faith? Who is making sure that upperExclusiveBound
and lowerInclusiveBound
in IsInRange
actually make sense? Is someone stopping you from making the following call: IsInRange(10, 100, -100, ...)
? A call like that is probably a bug somewhere else in your code, make your life easier by making these kind of bugs easier to spot. Again, assert your truths:
private static bool IsInRange(int value,
int lowerInclusiveBound,
int upperExclusiveBound,
string messageOnFailedValidation)
{
Debug.Assert(upperExclusiveBound > lowerInclusiveBound);
if ...
}
A good case could also be made on wether you should be checking that prompt
in GetIntegerFromUser
and messageOnFailedValidation
in IsInRange
are not empty or null strings, etc.
Yeah, now we are really done.
First of all, make the user experience as good as possible. Inputing a matrix all at once can be error prone, make the user's life easier and take it step by step.
Second, make small methods that perform simple tasks; they are easier to reason about, easier to write, easier to debug and easier to modify if new requirements come along. Don't make methods do too much, it will only buy you headaches and more debugging hours than necessary. If you are learning, don't worry if it seems you are breaking down to seemingly absurdly simple tasks, you wont regret it. Always remember that the most complicated problems you can imagine are always solved solving smaller and easier ones.
So, the first thing you need is a method that prompts the user for a valid integer, so lets try that:
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;
}
See how that works? This method has one single goal in life; get the user to enter a valid integer. Never mind what the integer is for, it doesn't care, thats not its job, this method will keep asking the user until its goal in life is achieved.
Ok, whats next? When filling in a matrix we'll need to know:
- Number of rows
- Number of columns
- Values
Ok lets write some methods that fetch just that:
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);
}
And,
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}]");
}
}
}
Now you should come to realize why making small methods that do simple tasks is such a great idea. Because chances are really good you'll get to reuse them and once you know the method works correctly, it will work correctly everywhere.
Ok, we've got all we need, now its just a matter of putting it all together:
public static int[,] GetMatrixFromUser()
{
var size = GetMatrixSize();
return GetMatrixValues(size.Rows, size.Columns);
}
How easy does that read?
So, we're done! Really? Well... no. We have no value validation at all, and that can be a problem. What happens if someone decides to input a negative number of rows? Ok, no problem, lets make a method that makes sure a value is inside a valid range:
private static bool IsInRange(int value,
int lowerInclusiveBound,
int upperExclusiveBound,
string messageOnFailedValidation)
{
if (value >= lowerInclusiveBound &&
value < upperExclusiveBound)
return true;
Console.WriteLine(messageOnFailedValidation);
return false;
}
And now, becuase we've used small methods that do well defined tasks, adding the new requirement is easily done modifying our GetMatrixSize
method a little:
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);
}
Yeah, now we are done...
Almost! One last thing. Another good habit is making sure the truths you believe in are actually true. What are you believing to be true inside GetMatrixValues
? You believe that rows
and columns
will have valid values. But your belief is purely based on faith, you are not checking if this is true.
But wait... I already checked in GetMatrixSize
right? Yes, but what guarantee do you have that GetMatrixValues
won't be called from some other method later on? Reusability remember?
Here you can go two paths. You can throw an exception if the values are not valid or you can assert that the values are in fact valid. Because the method is private and having invalid values probably means a bug somewhere up the callstack, the better option here is to assert your truths:
private static int[,] GetMatrixValues(int rows, int columns)
{
Debug.Assert(rows > 0 && columns > 0);
var matrix = ...
}
Any other truths merely on faith? Who is making sure that upperExclusiveBound
and lowerInclusiveBound
in IsInRange
actually make sense? Is someone stopping you from making the following call: IsInRange(10, 100, -100, ...)
? A call like that is probably a bug somewhere else in your code, make your life easier by making these kind of bugs easier to spot. Again, assert your truths:
private static bool IsInRange(int value,
int lowerInclusiveBound,
int upperExclusiveBound,
string messageOnFailedValidation)
{
Debug.Assert(upperExclusiveBound > lowerInclusiveBound);
if ...
}
A good case could also be made on wether you should be checking that prompt
in GetIntegerFromUser
and messageOnFailedValidation
in IsInRange
are not empty or null strings, etc.
Yeah, now we are really done.
edited Nov 24 '18 at 22:28
answered Nov 24 '18 at 21:22
InBetweenInBetween
25.4k34068
25.4k34068
add a comment |
add a comment |
You do not need the while loop inside the for loop. just check each item for validity and break, if you encounter an invalid string, of course if all were valid (loop will go to the end) and i
will be equal to length of your array:
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);
Another way would be using 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);
add a comment |
You do not need the while loop inside the for loop. just check each item for validity and break, if you encounter an invalid string, of course if all were valid (loop will go to the end) and i
will be equal to length of your array:
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);
Another way would be using 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);
add a comment |
You do not need the while loop inside the for loop. just check each item for validity and break, if you encounter an invalid string, of course if all were valid (loop will go to the end) and i
will be equal to length of your array:
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);
Another way would be using 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);
You do not need the while loop inside the for loop. just check each item for validity and break, if you encounter an invalid string, of course if all were valid (loop will go to the end) and i
will be equal to length of your array:
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);
Another way would be using 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);
edited Nov 24 '18 at 21:09
answered Nov 24 '18 at 20:29
Ashkan Mobayen KhiabaniAshkan Mobayen Khiabani
20.7k1566116
20.7k1566116
add a comment |
add a comment |
Thanks for contributing an answer to Stack Overflow!
- Please be sure to answer the question. Provide details and share your research!
But avoid …
- Asking for help, clarification, or responding to other answers.
- Making statements based on opinion; back them up with references or personal experience.
To learn more, see our tips on writing great answers.
Sign up or log in
StackExchange.ready(function () {
StackExchange.helpers.onClickDraftSave('#login-link');
});
Sign up using Google
Sign up using Facebook
Sign up using Email and Password
Post as a guest
Required, but never shown
StackExchange.ready(
function () {
StackExchange.openid.initPostLogin('.new-post-login', 'https%3a%2f%2fstackoverflow.com%2fquestions%2f53461993%2fc-creating-a-string-array-from-user-input-then-if-it-cant-be-parsed-into-int%23new-answer', 'question_page');
}
);
Post as a guest
Required, but never shown
Sign up or log in
StackExchange.ready(function () {
StackExchange.helpers.onClickDraftSave('#login-link');
});
Sign up using Google
Sign up using Facebook
Sign up using Email and Password
Post as a guest
Required, but never shown
Sign up or log in
StackExchange.ready(function () {
StackExchange.helpers.onClickDraftSave('#login-link');
});
Sign up using Google
Sign up using Facebook
Sign up using Email and Password
Post as a guest
Required, but never shown
Sign up or log in
StackExchange.ready(function () {
StackExchange.helpers.onClickDraftSave('#login-link');
});
Sign up using Google
Sign up using Facebook
Sign up using Email and Password
Sign up using Google
Sign up using Facebook
Sign up using Email and Password
Post as a guest
Required, but never shown
Required, but never shown
Required, but never shown
Required, but never shown
Required, but never shown
Required, but never shown
Required, but never shown
Required, but never shown
Required, but never shown
Try rewriting by putting the loop over the input. Only call ReadLine in one place. break out of loop if input correct.
– Garr Godfrey
Nov 24 '18 at 20:21