Out of range index in if condition [duplicate] - c#

This question already has answers here:
What is an IndexOutOfRangeException / ArgumentOutOfRangeException and how do I fix it?
(5 answers)
Closed 3 years ago.
I have a sentence, and I want to check for duplication letters in order to add a 'x' as a separator between them, however I debugged and kept getting an exception in here:
for (int i = 0; i < res.Length; i++)
{
t += res[i];
if (res[i] == res[i + 1]) //Index out of range exception here
{
t += 'x';
}
}
what goes wrong in here?

The cause of misbehavior is in the if:
if (res[i] == res[i + 1])
when i == res.Length - 1 (for loop last iteration) you have
if (res[res.Length - 1] == res[res.Length])
and res[res.Length] throws OutOfRangeException since valid range is [0..res.Length - 1] (please, note - 1).
Your code corrected:
for (int i = 0; i < res.Length; i++)
{
Nplaintext += res[i];
// we don't want to check (and insert 'x') for the last symbol
if (i < res.Length - 1 && res[i] == res[i + 1])
{
Nplaintext += 'x';
}
}
Often we work with string with a help of regular expressions (let .Net loop over the string for you):
using System.Text.RegularExpressions;
...
string source = "ABBBACCADBCAADA";
// Any symbol followed by itself should be replaced with the symbol and 'x'
string result = Regex.Replace(source, #"(.)(?=\1)", "$1x");
Console.Write(result);
Outcome:
ABxBxBACxCADBCAxADA

i+1 us causing this.
in the last iteration, i+1 refers to a location which is not inside that array.
Better change the condition in for loop as below:
for (int i = 0; i < res.Length - 1; i++)
{
t += res[i];
if (res[i] == res[i + 1]) //Index out of range exception here
{
t += 'x';
}
}
t += res[res.Length -1 ];
Hope this helps.

Sure you get this exception. In the case i=res.Length -1 (what is exactly the last position) you ask for res[Length] with the i +1 but because of starting with 0 the element you are asking for does not exist.
try something like
if(i+i < res.Length)
before you ask for that element
or even better start counting with i=1 and use
if (res[i] == res[i - 1])
{
Nplaintext += 'q';
}

Related

System out of range in for loop

System is giving me out of range exception when p = 255. My understanding is that with "OR" operator, later part of if statement should come into affect. However, it is not. Please advise on how to fix it.
for (int p = 0; p < 256; p++)
{
if (buffer[p] == buffer[p + 1] || buffer[p] == buffer[p - 1])
{
//Code
}
}
In the first iteration p = 0;
With p = 0; the right side of the conditional expression is trying to access buffer[-1], which throws the Exception.
You should start the iteration with index 1 and end it one item before the last item in the buffer. Try something like this:
for (int p = 1; p < buffer.Length - 1; p++)
{
if (buffer[p] == buffer[p + 1] || buffer[p] == buffer[p - 1])
{
//Code
}
}
You have out of range error. It means that index p is out of buffer range,
which is
// buffer has Length items, starting from 0
[0 .. buffer.Length - 1]
Now, let's have a look at index usage: you have
if (buffer[p] == buffer[p + 1] || buffer[p] == buffer[p - 1])
and you address
buffer[p] where p can be in 0..buffer.Length - 1 range
buffer[p + 1] where p can be in -1..buffer.Length - 2 range
buffer[p - 1] where p can be in 1..buffer.Length range
combining all 3 ranges for index p together we get p in 1..buffer.Length - 2 range or
for (int p = 1; p < buffer.Length - 1; p++)
if (buffer[p] == buffer[p + 1] || buffer[p] == buffer[p - 1]) {
...
}
Note edge cases (first and last buffer items):
when p == 1 we have
(buffer[1] == buffer[2] || buffer[1] == buffer[0])
^
first item
when p == buffer.Length - 2
(buffer[buffer.Length - 2] == buffer[buffer.Length - 1] || buffer[buffer.Length - 2] == buffer[buffer.Length - 3])
^
last item
that's why no item is lost
You're comparing an item x to either the item before it or the item after it. Then you move along one, and you potentially make the same compare you just did, so you're wasting a lot of CPU:
var a= new []{1,2,3,4}
if(2 == 1 or 2 == 3)
...
if(3 == 2 or 3 == 4). //3==2 was already done above like 2==3
Just compare current with next, moving along by 1 each time, stopping 1 short of the end of the loop
If you want to duplicate messaging, print twice
for(int x=0; x<array.Length-1; x++){
if(array[x] == array[x+1]){
Console.WriteLine($"index {x} is same as {x+1}");
Console.WriteLine($"index {x+1} is same as {x}");
}
}
My understanding is that with "OR" operator, later part of if statement should come into affect.
Later part of statement comes into effect if first part of statement returns false. First part of statement is always done. your first part of statement is guaranteed to crash if the array is length 256
C# isn't some sort of AI that thinks "ooh, if I do the left part of the OR then I'll get a crash, so I'll just do the right part", it just does as you told it according to its "do left, then if false, do right" rules, which might mean you try access an array index that doesn't exist
Worth pointing out that if the first two bytes in your buffer are not the same (left part of OR returns false) then you'll get another crash, this time because C# is trying to evaluate the right side of the OR, and you make it do buffer[-1]

Printing even numbers with commas except the last in C# not working

I have been trying to fix this issue for some days now but can't find the error. It seems as simple as an if statement for the code to print commas for all but the last number. It worked for me putting random numbers but when i put the specific numbers (24,7,35,2,27,7,89)it prints the comma at the end.
Print even numbers with commas
This is my code, but i tried multiple other ways.
using System.Collections.Generic;
using System.Text;
using System.Transactions;
namespace ArrayExercises
{
class TaskFour
{
public static void FindEvenNumbers()
{
int[] input = new int[7];
int count = 1;
string comma = ",";
Console.WriteLine("[== Please Enter 7 numbers ==]");
Console.WriteLine();
for (int i = 0; i < input.Length; i++)
{
Console.WriteLine($"Enter number {count}:");
input[i] = int.Parse(Console.ReadLine());
count++;
}
Console.WriteLine("The even numbers in this array are: ");
for (int i = 0; i < input.Length; i++)
{
if (input[i] % 2 == 0)
{
if (i < input.Length)
{
Console.Write(input[i] + comma);
}
else
{
Console.Write(input[i]);
}
}
}
}
}
}
Thanks in advance :)
You can use below code without introducing any extra space using for loop.
for (int i = 0; i < input.Length; i++)
{
if (input[i] % 2 == 0)
{
if (i != 0) Console.Write(comma);
Console.Write(input[i]);
}
}
Or use the inbuilt string.Join function.
Console.WriteLine(string.Join(',', input.Where(i => i % 2 == 0)));
This answer assumes that the above is homework/tutorial, there are more efficient means that what I am posting here
The problem is this segment:
if (i < input.Length)
{
Console.Write(input[i] + comma);
}
The problem is that you are always outputting a comma, regardless of what is to follow. I think that the easiest approach would be to add the comma before hand, meaning, while you are going through the second loop, if you have already printed a number before, you pre-pend a comma and print the number you have, if you did not print any numbers before (that is, you are about to print the first number) then you do not prepend the comma.
i will always be less than the length the input due to the loop's condition.
Instead of implementing this yourself, you could let string.join do the heavy lifting for you:
string result = string.Join(comma, input.Where(i => i % 2 == 0));
Console.WriteLine(result);
Your else condition will never execute. If you are rookie in C# then I would suggest get all even numbers first and store it in the list. Iterate over again to print with comma and just skip the last comma.
//Your existing source code
List<int> evenNumber = new List<int>();
for (int i = 0; i < input.Length; i++)
{
if (input[i] % 2 == 0)
{
evenNumber.Add(input[i]);
}
}
for(int i = 0; i < evenNumber.Length; i++)
{
//Print just number if it is last, otherwise print number with comma
if(i == evenNumber.Length - 1)
Console.Write(evenNumber[i]);
else
Console.Write(evenNumber[i]+comma);
}
If you know string.Join() then use linq to get list of even numbers and print list of even numbers with ',' as a delimiter
var evenNumbers = input.Where(x => x % 2 ==0); //Filter all even numbers
Console.WriteLine(string.Join(",", evenNumbers); //Print using string.Join
Yet another version:
string result = "";
for (int i = 0; i < input.Length; i++)
{
if (input[i] % 2 == 0)
{
result += $",{input[i]}";
}
}
Console.WriteLine( result.Length > 0 ? result.Substring(1).ToString() : "");

how continue, the jump statement affects for loop in c# [closed]

Closed. This question needs details or clarity. It is not currently accepting answers.
Want to improve this question? Add details and clarify the problem by editing this post.
Closed 5 years ago.
Improve this question
i am reading C-Sharp 7.0 in a Nutshell - Joseph Albahari,
in jump statements section, there is a code like
for (int i = 0; i < 10; i++)
{
if ((i % 2) == 0) // If i is even,
continue; // continue with next iteration
Console.Write (i + " ");
}
Output is : 1 3 5 7 9
but when i comment the continue jump statement like below
for (int i = 0; i < 10; i++)
{
if ((i % 2) == 0) // If i is even,
//continue; // continue with next iteration
Console.Write (i + " ");
}
Output is : 0 2 4 6 8
can someone explain how continue statement affects flow of loop ?
Without the curly brackets, C# will compile the next statement to be executed when the condition of the if is true. A comment is not a statement. This is one of the main reasons it's best to always include curly brackets, even with a single statement.
continue tells the program to jump to the start of the loop and retest the condition. In this case the Console.Write calls will be skipped.
There is also break which ends the loop completely and does not retest the condition.
Your fundamental confusion I think has to do with the fact that commenting out a statement removes the statement entirely. It does not make a "do nothing" statement that is then the body of the if.
However, I think there is also a confusion expressed about what continue does. A good way to understand this is to reduce it to something simpler.
Suppose you have
for (int i = 0; i < 10; i++)
{
if ((i % 2) == 0)
continue;
Console.Write (i + " ");
}
Let's reduce this to a simpler program, in the sense that for is complicated and while is less complicated. Your program fragment is the same as:
{
int i = 0;
while (i < 10)
{
if ((i % 2) == 0)
goto DoTheLoopIncrement;
Console.Write (i + " ");
DoTheLoopIncrement:
++i;
}
}
Which is the same as:
{
int i = 0;
DoTheLoopTest:
if (i < 10)
goto DoTheLoopBody;
else
goto DoneTheLoop;
DoTheLoopBody:
{
if ((i % 2) == 0)
goto DoTheLoopIncrement;
Console.Write (i + " ");
DoTheLoopIncrement:
++i;
goto DoTheLoopTest;
}
}
DoneTheLoop:
...
Notice how much longer and harder to read the "goto" version is. That's why we use while and for. But you must understand that this is precisely what while and for and continue are doing in order to make sense of their control flows. They are just a pleasant way of writing a goto.
Now: do you understand what break means? Break is just a pleasant way to write goto DoneTheLoop.
Poor formatting:
for (int i = 0; i < 10; i++)
{
if ((i % 2) == 0) // If i is even,
continue; // continue with next iteration
Console.Write (i + " ");
}
Better formatting:
// Output is : 1 3 5 7 9
for (int i = 0; i < 10; i++)
{
if ((i % 2) == 0) // If i is even,
continue; // continue with next iteration
Console.Write (i + " ");
}
Without "continue":
// Output is : 0 2 4 6 8
for (int i = 0; i < 10; i++)
{
if ((i % 2) == 0) // If i is even,
// continue; // continue with next iteration
Console.Write (i + " ");
}
Best formatting:
// Output is : 1 3 5 7 9
for (int i = 0; i < 10; i++)
{
// If i is even,
if ((i % 2) == 0)
{
// continue with next iteration
continue;
}
Console.Write (i + " ");
}
Continue will ignore all the statements that follow inside the loop and continue with the next iteration.

Exiting loop without break/return/if

If you have a for loop:
for(i=0;i<10;i++){}
Now, when i==5, how can I exit the for loop completely without using break, return, or if?
The best I could come up with was this:
for (int i = 0; i < 10; i++)
{
i = (i == 5) ? 10 : i;
Trace.WriteLine("i = " + i.ToString());
}
...which will cause the loop to run six times (i=0..5) and display this..
i = 0
i = 1
i = 2
i = 3
i = 4
i = 10
The alternative way to "exit the loop" (in a particularly nasty fashion) would be to do this...
for (int i = 0; i < 10; i++)
{
int a = 3 / ((i == 5) ? 0 : 1);
Trace.WriteLine("i = " + i.ToString());
}
..which crashes out, errr, successfully exits the loop without using the break, return or if commands.
i = 0
i = 1
i = 2
i = 3
i = 4
A first chance exception of type 'System.DivideByZeroException' occurred in MikesProgram.dll
language is C# .it was an interview question actually..curious
Do I get the job ?
I would need to check your health & dental plans, and I have to leave early on Thursdays to collect my daughters from school.
;-)
for (int n = 0; n < 10; n++)
{
n += (n / 5) * 5;
}
well here's another way if you want to break the processing exactly when i = 5 without using break, return, or if
for (int lowsetLimit = 0, highestLimit = 10, i = lowsetLimit; i < highestLimit; i++)
{
//normal code which process before i gets eqaul to 5 goes here...
i = (i < 5) ? i : highestLimit; //and here is the pivot point.
}
for(i=0;i<10;i++){
(i==5) ? goto Outer : //do something;
}
Outer:
//do something
The question says that loop should end when i=5, It says nothing about start, So this should be valid (ternary operator solution is better, but if we are not allowed to use any conditional operator)
for (int i = 0; i < 10; i++)
{
i=i-4;
Console.WriteLine("i = " + i.ToString());
i=i+4;
}
this Starts at -4 and ends at 5.
The real answer of course would be the following:
for (i=0; i!=5; i++)
{
// do something
}
But let's make it a bit more generic: stop if (expression) becomes true.
The second argument of the for loop is a boolean expression which determines whether to continue the loop with the next element or not.
So if you want to stop looping because of any condition:
for (i=0; !(expression) && i<10; i++)
{
// do something
}
This works using while and goto:
for (int i = 0; i < 10; i++)
{
while (i < 5)
{
Console.Write(i + " ");
goto OutsideWhile;
}
OutsideWhile:
continue;
}
// 0 1 2 3 4

C# & VS error: "make sure that the maximum index on a list is less than the list size"

I faced the error mentioned in the title when doing my homework, and simply can't find a way to remove it. Here is the method that I have this problem with:
public static double LaskeMiidi(double[] luvut)
{
double ka = Keskiarvo(luvut);
double miidi = luvut[0];
for (int i = 0; i < luvut.Length; i++)
{
if (luvut[i] - ka < luvut[i + 1] - ka) // The line error points to!
{
miidi = luvut[i];
}
else
{
miidi = luvut[i + 1];
}
}
return miidi;
}
So basically the problem is that when I say luvut[i + 1], at some point this index might become more than the length of the array is. I just can't figure out any ways to solve this problem, since I'm only a beginner with programming.
Yes, this is the problem:
for (int i = 0; i < luvut.Length; i++)
{
if (luvut[i] - ka < luvut[i + 1] - ka)
When i is luvut.Length - 1, then i + 1 will be luvut.Length - and therefore an invalid index. (For an array of length x, the valid indexes are 0 to x - 1 inclusive.) You probably want to end one iteration earlier:
for (int i = 0; i < luvut.Length - 1; i++)
That way i + 1 will still be a valid index in the array - both in the if condition and in the body of the else clause.
End your loop earlier:
for (int i = 0; i < luvut.Length - 1; i++)
This stops the loop ever getting to the point where an index would be invalid.
When i = luvut.Length -1, luvut[i + 1] will give an error as it is beyond the array bounds.
You need either:
for (int i = 0; i < luvut.Length - 1; i++)
Or else handle the luvut[i + 1] issue in another way in another If block.
Notice that when you define an array, range of items are between 0 and array.length-1. so you should write:
for (int i = 0; i < luvut.Length-1; i++)

Categories

Resources