Program is not throwing ArgumentOutOfRange Exception - c#

I have a simple program that takes a number from the user and returns the number located at that position/index in an array. However, if the given number is not withing the index range, it throws an exception.
Here is my code:
int[] arr = { 1, 2, 3, 4, 5, 6 };
Console.WriteLine("input int");
int k = int.Parse(Console.ReadLine());
Console.WriteLine("before");
try
{
double n = 5 / k;
Console.WriteLine(n);
int l=arr[k];
Console.WriteLine(l);
}
catch (DivideByZeroException)
{
throw new ArgumentException("you cant divid by 0!");
}
catch (ArgumentOutOfRangeException)
{
throw new ArgumentException("please give a number between 0-5");
}
catch (Exception)
{
throw new ArgumentException("something went worng, please try again");
}
finally
{
Console.WriteLine("after");
Console.WriteLine("process compited!");
}
The problem however is, if the entered number is 7, which is not within the range, it shows ArgumentOutOfRangeException exception .
What should I do in case I want the Exception to be like "please give a number between 0-5"? (using try-catch method)

There is a difference between IndexOutOfRangeException and ArgumentOutOfRangeException.
You have to catch IndexOutOfRangeException instead.

Do not use exceptions to direct your application logic flow. Better check proactively if the index is not too big for your array. This index number is an input from outside so you are entitled to put any guards on it you see fit.
Other than that #Ciubotariu Florin is right.

Related

Program not catching IndexOutOfRangeException

I'm following an old YouTube guide for C# learning and I'm stuck on one of the challenges for error handling.
class Program
{
static Board myBoard = new Board(8);
public static Cell setCurrentCell()
{
int currentRow, currentColumn;
// get x and y coordinates from the user. return a cell location
Console.Write("Enter a current row number: ");
while (true)
{
try
{
currentRow = int.Parse(Console.ReadLine());
break;
}
catch (FormatException)
{
Console.Write("Input has to be a number, try again:");
}
catch (IndexOutOfRangeException)
{
Console.WriteLine("Input was out of range, try a number between 0 and 8.");
Console.Write("Please try again: ");
}
}
Console.Write("Enter the current column number: ");
while (true)
{
try
{
currentColumn = int.Parse(Console.ReadLine());
break;
}
catch (FormatException)
{
Console.Write("Input has to be a number, try again:");
}
catch (IndexOutOfRangeException)
{
Console.WriteLine("Input was out of range, try a number between 0 and 8.");
Console.Write("Please try again: ");
}
}
}
return myBoard.theGrid[currentRow, currentColumn];
}
}
I'm trying to catch an error if user enters a number out of bounds but the catch just skips over it and then throws the error anyways. what am I doing wrong here?
Following Int32.Parse method documentation – exception type IndexOutOfRangeException is not handled here.
If you want to check that value is less than Int32 min value or greater than Int32 max value, you should catch OverflowException.
IndexOutOfRangeException is throw by an attempt to access an indexable collection (arrays, List<T>, anything that implements IList<T>, etc.) using an invalid index - less than 0 or greater than or equal to the collection size.
Here's the first try block in your code:
try
{
currentRow = int.Parse(Console.ReadLine());
break;
}
Nothing in that block is attempting to index a collection, so we wouldn't expect IndexOutOfRangeException to be thrown. In fact there are only two things in there that can throw an exception at all (int.Parse and Console.ReadLine), neither of which can throw IndexOutOfRangeException under any circumstances.
There's only one line in your code that performs an indexing operation on a collection and that's the final return statement... which is not contained in a try...catch statement.
What you're trying to achieve is to range-check the entered values. There are a couple of ways to do this, but if you insist on using exceptions (which I wouldn't do, but you're learning I guess) then you can check the inputs by attempting to index the board's theGrid array after the parse in each try block like this:
try
{
currentRow = int.Parse(Console.ReadLine());
var test = myBoard.theGrid[currentRow, 0];
break;
}
And for currentColumn:
try
{
currentColumn = int.Parse(Console.ReadLine());
var test = myBoard.theGrid[0, currentColumn];
break;
}
If the entered value (currentRow or currentColumn) is out of bounds then this will throw the IndexOutOfRangeException as expected. (The 0 in the other index is guaranteed to not throw unless the row/column count is 0.)

Can you use a for loop to pop each value in a stack until there is only one left?

I have an array with six values in it {1, 2, 3, 4, 5, 6}.
I have been able to successfully push the values into a stack using a for loop. I am supposed to also write a for loop and pop each value from the stack until there is only one left. I can't find an example of it anywhere. Help, please?
int[] numbers = new int[] {1, 2, 3, 4, 5, 6};
Stack<int> myStack = new Stack<int>();
for (int i = 0; i <numbers.Length; i++)
{
mystack.Push(numbers[i]);
}
foreach(int item in myStack)
{
Console.Write(item + ", ");
}
This prints the pushed values in the array. We have been using the other properties such as Peek and Count with stack as well. I don't have an issue with those. I don't have an issue using Pop for a single value either.
Console.WriteLine("The value popped from the stack is: {0} ", myStack.Pop());
My issue is trying to use a for loop to pop each item from the stack one by one. My brain isn't translating this well at all. I have looked for examples. I have not been able to find one using a for loop.
A while loop may be better in this case. I would approach it like this:
while (myStack.Count > 1)
{
Console.WriteLine("The value popped from the stack is: {0} ", myStack.Pop());
}
// check stack count
while (myStack.Count > 1)
{
// console
Console.WriteLine($#"POP VALUE: {myStack.Pop()}");
}
for (int i = myStack.Count; i > 0; i--)
{
Console.WriteLine($"The value popped from the stack is: {myStack.Pop()}");
}
To use a for loop with a stack you want to use it in a descending manner, while initializing the loop variable to the count in the stack. If you use the stack length as the conditional it will check against the current count every time and stop prematurely
you can use the below code.
int count = myStack.Count;
for (int i = 1; i < count; i++)
{
Console.WriteLine("The value popped from the stack is: {0} ", myStack.Pop());
}
You can also use a while loop in place of for loop.

Kattis run time error solving Jumbo Javelin with C#

I am new to Kattis and trying solve the challenge Jumbo Javelin with C# but I get run time error even though I am exiting my program with 0.
Here is my code:
using System;
namespace JumboJavelin
{
class Program
{
static void Main(string[] args)
{
int l = int.Parse(Console.ReadLine());
int sum = 0;
int loss = 1;
for (int n = 0; n <= 100; n++)
{
sum += l;
if((n + 1) % 2 == 0 && !n.Equals(0))
{
sum -= ((n + 1) / 2)*loss;
}
try
{
l = int.Parse(Console.ReadLine());
}
catch (FormatException)
{
break;
}
}
Console.WriteLine(sum);
Environment.Exit(0);
}
}
}
Can someone please help me? I know my solution eventually outputs the wrong answer but right now I am trying to get rid of the run time error since it works perfectly fine on Visual Studio 2019.
All help is appreciated. Thanks
If you change the error your catch to Exception you will see that it is actually a wrong answer, so something goes wrong. You do exit your program with an exit code 0 at the bottom of your code, however, it throws an Exception somewhere else. Two things to consider:
First, the problem statement explains that as a first input, you get an integer N (this N indicates the amount of steel rods he has) and CAN BE between 1 and 100 (1 not inclusive hence, 1<N<=100). You now have a loop that always loops from 1 to 100. And the loop should loop from 1 up to and including whatever value N is. Try to see what you can do about that.
Second you read the input at the "tail" of the loop. This means that after the last cycle you do another read input. And that you do not read the first l. Try changing reading the input for l at the beginning of the loop. (and the first input you read in your Main, should not be for l (see point 1)).
See how far this gets you, is something is not clear please let me know.
As Kasper pointed out, n is dynamically provided on the first line; don't assume you have 100 lines to collect with for (int n = 0; n <= 100; n++).
There's no need to handle errors with the format; Kattis will always adhere to the format they specify. If something goes wrong parsing their input, there's no point trying to catch it; it's up to you to fix the misunderstanding. It's better to crash instead of catch so that you won't be fooled by Kattis telling you the failure was due to a wrong answer.
A simple approach is as follows:
Collect n from the first line of input; this is the preamble
Loop from 0 to n, collecting each line
Accumulate the values per line into a sum
Print sum - n + 1, the formula you can derive from their samples
using System;
class JumboJavelin
{
static void Main(string[] args)
{
int n = int.Parse(Console.ReadLine());
int sum = 0;
for (int i = 0; i < n; i++)
{
sum += int.Parse(Console.ReadLine());
}
Console.WriteLine(sum - n + 1);
}
}
You can use this pattern on other problems. You won't always aggregate one result after n lines of input though; sometimes the input is a single line or you have to print something per test case. Some problems require you to split and parse each line on a delimiter.
Regardless of the case, focus on gathering input cleanly as a separate step from solving the problem; only combine the two if you're confident you can do it without confusion or if your solution is exceeding the time limit and you're sure it's correct otherwise.

Checking the values in an array around a specific index

I have a 2 dimensional array and what I want to do is search for a specific value around that index(so I want to check array[x-1,y], array[x,y-1] and so on).
My problem is when it will check index which is out of range. Is there someway to check them (I don't want to a lot of IF's checking if x-1 or y-1 is in range of course). I haven't used try/catch a lot yet, and I'm not sure how that works either, but can I ignore the out of range Exception with that? Or is there a better solution for this problem?
If you can't have if you can pre-compute lists of indexes for each cell and iterate over them. I.e. have separate array of the same dimensions that contains lists of index pairs for iteration. Inner elements would have 8 pairs each, corner and border elements would have less (3 and 5 correspondingly).
Alternatively you can use ? : instead of if condition in case restriction is only on syntax and not on condition itself.
I suggest using an extension method for hiding the logic in it (weather with if's or with Math.Max and Math.Min):
public static partial class Array2DExtensions {
public static IEnumerable<T> Vicinity<T>(this T[,] data, int line, int col) {
if (null == data)
throw new ArgumentNullException("data");
//TODO: you may want to add range check here
for (int i = Math.Max(data.GetLowerBound(0), line - 1);
i <= Math.Min(data.GetUpperBound(0), line + 1);
++i)
for (int j = Math.Max(data.GetLowerBound(1), col - 1);
j <= Math.Min(data.GetUpperBound(1), col + 1);
++j)
yield return data[i, j];
}
}
And so you can put something like this:
int[,] sample = ...
...
// Are there any value less than 100 in vicinity of 5, 7 item?
bool found = sample
.Vicinity(5, 7)
.Any(item => item < 100);
You can calculate the safe lower and upper limits for both dimensions and then iterate over the matrix:
// Calculate x range to check
var xl = Math.Max(x-1, 0);
var xu = Math.Min(x+1, array.GetUpperBound(1));
// Calculate y range to check
var yl = Math.Max(y-1, 0);
var yu = Math.Min(y+1, array.GetUpperBound(0));
// Iterate using ranges
for (var j=yl; j <= yu; j++)
for (var i=xl; i <= xu; i++)
// Do the checking
// array[j, i]
I think you'll have to check for each index if it around the array edges.
with the necessary "if's"
if you want to use try and catch it will work,
but you'll have to surround each array access with it's own Try And Catch
(if all will be in same try, once exception was caught the following commands will be skipped)
like this:
try
{
array[x-1,y]
}
catch (ArgumentOutOfRangeException ex)
{
}
try
{
array[x,y-1]
}
catch (ArgumentOutOfRangeException ex)
{
}
etc..

C# Multiplying two variables of value int.MaxValue does not result in OverflowException

I've got an integer array that contains two values, each the maximum value of int32:
int[] factors = new int[] { 2147483647, 2147483647 };
I'm trying to get the product of these two numbers to create an OverflowException:
try
{
int product = factors[0] * factors [1];
}
catch(Exception ex)
{
}
Much to my surprise (and dismay), product actually returns a value of 1. Why is this, and how would I go about throwing an exception when the product of two integers exceeds int.MaxValue?
Because the default behavior of C# is not to check overflow with int.
However, you can force overflow checking by using checked keyword.
try
{
checked
{
int product = factors[0] * factors [1];
}
}
catch(Exception ex)
{
}
You will have to call BigMul of the math class(used to multiply large integers and avoid overflow),or else even without exception,by using the * operator will result in 1.
long product = Math.BigMul(factors[0], factors[1]);
to throw the exception you will have to place checked.
checked
{
int product = factors[0] * factors[1];
}
great tutorial about overflow by using the checked and unchecked
http://www.codeproject.com/Articles/7776/Arithmetic-Overflow-Checking-using-checked-uncheck
You need to enclose it in a checked block to throw an overflow exception. Replace int product = factors[0] * factors [1]; with this:
checked
{
int product = factors[0] * factors [1];
}
Without the checked block the result will be truncated since it exceeds int's maximum capacity.

Categories

Resources