Don't understand why this loop doesn't iterate - c#

Not sure what I am doing wrong here. I am new to C# and am trying to convert VB.Net code from an online tutorial. I can't get this For loop to iterate:
if (Screens.Count > 0)
{
for (int i = Screens.Count - 1; i == 0; --i)
{
if (Screens[i].GrabFocus==true)
{
Screens[i].Focused = true;
DebugScreen.FocusScreen = "Focused Screen: " + Screens[i].Name;
break;
}
}
}
There are 2 screens in the list. The second screen (Screens[1]) has GrabFocus set to true. During debugging, execution jumps from line 3 (for ...) right to the last closing brace. The nested "If" statement never executes. Also, I think the break statement is wrong because I am actually trying to end the "For" loop.

You haven't written correctly your for loop. You should replace it with the following:
for (int i = Screens.Count - 1; i >=0; --i)
You start from the value Screens.Count - 1 and you decrease by 1 the i in each step, until i becomes equal to zero. Then you stop.
Generally speaking, the correct syntax is the following:
for (initializer; condition; iterator)
body
The initializer section sets the initial conditions. The statements in this section run only once, before you enter the loop. The section can contain only one of the following two options.
The condition section contains a boolean expression that’s evaluated to determine whether the loop should exit or should run again.
The iterator section defines what happens after each iteration of the body of the loop. The iterator section contains zero or more of the following statement expressions, separated by commas
The body of the loop consists of a statement, an empty statement, or a block of statements, which you create by enclosing zero or more statements in braces.
For more information about this, please have a look here.
What's the problem in your case?
The second bullet. The condition, i==0 is false by the begin. Hence the loop will not be executed at all.

i == 0 should be i >= 0
i.e.
for (int i = Screens.Count - 1; i >= 0; --i)

i == 0 should be replaced with i >= 0
for (int i = Screens.Count - 1; i >=0; --i)

Your for loop is not correct. Here's is the code
if (Screens.Count > 0)
{
for (int i = Screens.Count - 1; i >= 0; --i)
{
if (Screens[i].GrabFocus==true)
{
Screens[i].Focused = true;
DebugScreen.FocusScreen = "Focused Screen: " + Screens[i].Name;
break;
}
}
}

Related

What is the appropriate way to append string to the end of the current line?

I'm working through a practice problem for one of my classes and I'm having a bit of trouble with part of the prompt.
We need to:
Write code to go through number -20 - 20 (but skip 5-15 inclusively)
If the number is negative, the line should start with an "*"
If the number is divisible by 2, add "#" to the end of the current line
If the number is divisible by 3, add "!" to the front of the line
If the previous line has both "!" and "#", then add "wow" to the end of the current line (Hint: use bool)
With the code I've written so far, I've managed to complete the first two tasks on the list, but I run into trouble starting with the third task. In my code I'm using
if (num%2==0)
{
Console.WriteLine(num+"#");
}
but all it's doing is outputting another number with "#" instead of putting "#" on the current line. How do I make it so "#" is appended to the end of the current line?
Here's my code for reference:
static void Main(string[] args)
{
int num = -20;
while (num <= 20)
{
if (num < 5 || num > 15)
{
if (num < 0)
{
Console.WriteLine("*" + num);
}
if (num%2==0)
{
Console.WriteLine(num+"#");
}
else
{
Console.WriteLine(num);
}
}
num++;
}
}
Since we are only working with the first 3 points in this question (try the other 2 yourself), I will only address those.
The main problem with the code is that it will always write the number more than once if more than one rule applies to it. There's 2 ways to tackle this. Also note I cleaned up the code a bit and I'll explain why later since it's secondary.
Fix
Method 1 : Incremental Writing
This method uses incremental writing to apply rules and then write a new line at the end before going to the next iteration.
// More succinct than a while loop for this particular scenario
for (int num = -20; num <=20; num++)
{
//Skip while avoiding nested if
if (num >= 5 && num <= 15)
continue;
//Since it needs to start with * in this case we prioritize it
if (num < 0)
Console.Write("*");
Console.Write(num);
// Since this would need to be appended at the end if it's true
if (num % 2 == 0)
Console.Write("#");
Console.Write(Environment.NewLine);
}
Method 2: Store the line then print before next iteration
In this case you would build the line that you want to print and then use one Console.WriteLine statement to write it while avoiding duplication. The writing would need to be done before moving to the next iteration.
You can use string concatenation instead of StringBuilder which would generally be more costly but in this case performance doesn't really matter (string are really small and amount of concatenation is minimal). However this would be a typical use case for a StringBuilder.
Also, since we know we know that we will always print out num when we aren't skipping then we can start off with num. But we could also do it like Method 1 where we add it in the middle. I'll illustrate both ways.
StringBuilder constructor with number
// More succinct than a while loop for this particular scenario
for (int num = -20; num <= 20; num++)
{
//Skip while avoiding nested if
if (num >= 5 && num <= 15)
continue;
// Create and update your string in a string builder, apply rules thereafter
// (this constructor usage means we don't need to add the number later)
var line = new StringBuilder(num.ToString());
//Since it needs to start with * in this case we prioritize it
if (num < 0)
line.Insert(0, "*");
// No need to add the number, already present
// Since this would need to be appended at the end if it's true
if (num % 2 == 0)
line.Append("#");
Console.WriteLine(line.ToString());
}
StringBuilder constructor without number
// More succinct than a while loop for this particular scenario
for (int num = -20; num <= 20; num++)
{
//Skip while avoiding nested if
if (num >= 5 && num <= 15)
continue;
// Create and update your string in a string builder, apply rules thereafter
// (this constructor usage means we must add the number later)
var line = new StringBuilder();
//Since it needs to start with * in this case we prioritize it
if (num < 0)
line.Append("*"); // NOTICE: This is now Append instead of Insert since line is empty
// Since we didn't add the number before
line.Append(num);
// Since this would need to be appended at the end if it's true
if (num % 2 == 0)
line.Append("#");
Console.WriteLine(line.ToString());
}
Additional Changes
for loop is better suited for this situation since you have an int with a clear start, end and an incrementor supported by the structure.
Avoid unnecessary nesting of conditions, common newbie mistake. If you have a condition to skip in certain cases, simply check and skip and otherwise the rest of the code will apply. This could otherwise lead to really annoying duplication and condition checks that are unnecessary (most of the time).
use string.concat but first save the string into variable and reach the end and finally do the concatenation

How is the code interpreted if no curly braces follow a while loop?

I am new to programming, and can not understand how the following code is interpreted by the compiler. As you can notice in the code, the while loop does not have curly braces around the code that comes right after it. Can somebody please explain to me, step by step, how this loop works:
int num = 0;
while(++num < 6)
Console.WriteLine(++num);
Console.WriteLine(num++);
Console.WriteLine(++num);
A while loop without braces is the same as a while loop with braces surrounding the line immediately below it:
int num = 0;
while(++num < 6)
{
Console.WriteLine(++num);
}
Console.WriteLine(num++);
Console.WriteLine(++num);
First iteration:
while(1 < 6) // num is 1
{
Console.WriteLine(2); // num is 2
}
Second iteration:
while(3 < 6) // num is 3
{
Console.WriteLine(4); // num is 4
}
Third iteration:
while(5 < 6) // num is 5
{
Console.WriteLine(6); // num is 6
}
On the fourth iteration, num becomes 7 and then gets checked by < 6, which evaluates to false. The while loop exits and the two lines below gets executed.
// num is 7
Console.WriteLine(7); // num is 8
Console.WriteLine(9); // num is 9
So it prints 2, 4, 6, 7, 9
Since ommitting curly braces can quickly lead to unexpected behavior or hard to read code, it is good practice to always write them, even if not needed. Consider the following code (I have left out the indentation on purpose):
int i, j;
for (i=0;i<10;i++)
for (j=0;j<10;j++)
if (j > i)
continue;
foo(i, j);
Nobody will be able to read that, and even if you add the spaces, it's very error prone. Also, if you later need to add another line to the if () condition, you'll very likely forget to also add braces. (The example is very poor: foo(i,j) will only be called once and the loop will do nothing!)
Also beware of the following slightly modfied code from your question:
int num = 0;
while(++num < 6); // Careful: a semicolon ends the statement
Console.WriteLine(++num);
This will run the loop six times before even calling Console.WriteLine once, because the semicolon ends the statement.

How can i make the FOR to loop backward ? Getting some errors

for (int i = uids.Count; i > 0; i--)
{
counting += 1;
if (counting == 30)
break;
string currentUidOnServer = uids[i - 1];
if (!seenUids.Contains(currentUidOnServer))
{
OpenPop.Mime.Message unseenMessage = client.GetMessage(i + 1);
newMessages.Add(unseenMessage);
seenUids.Add(currentUidOnServer);
allMessages.Add(unseenMessage);
int nProgress = (uids.Count - i + 1) * 100 / uids.Count;
backgroundWorker1.ReportProgress(nProgress, client.GetMessageCount().ToString() + "/" + i);
}
}
The variable uids contain 7038 items.
I want to report to the backgroundworker progresschanged event.
And it does reporting but it did backward started from 7038 and 100%
And i want it to report from 0% to 100% so i changed the FOR to
for (int i = uids.Count; i > 0; i--)
It was
for (int i = 0; i < uids.Count; i++)
The first error out of index exception was on the line
string currentUidOnServer = uids[i - 1];
So i changed it to [i - 1]
Now i'm getting exception on the line
OpenPop.Mime.Message unseenMessage = client.GetMessage(i + 1);
Since 7038 + 1 not exist.
So i messed it all.
How this two lines i have/had the exceptions should be ?
This is the typical way to do this:
for (int i = uids.Count - 1; i >= 0; i--)
Then, use uids[i] and maybe client.GetMessage(i), however I have no idea, what "client" is in your code
Arrays in C# (and all the other C-like languages) are zero-indexed, which means that the first item in the array is at position 0. Attempting to access an array index that is less than 0 or greater than or equal to the number of elements in the array will result in an error as you have seen.
The first form of your loop:
for (int i = uids.Count; i > 0; i--)
...produces a sequence of numbers (on your 7038-item array) from 7038 down to 1. Since 7038 is an invalid array index (1 past the end of the array) and the sequence doesn't include 0, the array access expressions in the loop all use i -1 to shift the entire sequence down by 1.
To properly reverse the for without changing any other code you need to produce a sequence from 1 up to 7038, like this:
for (int i = 1; i <= uids.Count; i++)
This is the direct opposite form of your original.
Personally I would prefer that the loop variable be the array index most of the time, and my first instinct when I see a > 0 condition in a for statement is that someone forgot to put the = in.
You could just reverse your array with Array.reverse() and then iterate over it using i++ as per your original approach
Oops I thought this was JavaScript question lol, o well the approach I said can conceptually be applied to any language, just need to find the array reverse for your language
If I understood correctly, originally i went from 0 to uids.Count - 1. If you can get back to that situation, then your formula for nProgress should be
int nProgress = (i + 1) * 100 / uids.Count;

C# When using foreach on a list of arrays, the foreach only iterates 5 times even though the list has length 86

I'm writing a chess engine in C#, and I'm trying to debug move generation. I've been using breakpoints so far to check variables, but I need a better way to debug. Despite the fact that a breakpoint shows that this list has a length of 86, the loop only runs 5 times. The only thing I can think of is that the arrays in the list have a length of 5, but I have no idea what would be causing this.
foreach (int[] debugBoard in futures)
{
for (int i = 0; i < 5; i++)
{
Debug.Write(debugBoard[i].ToString().PadLeft(3, ' '));
}
Debug.Write("\n");
int[,] debugOutBoard = new int[8, 8];
Array.Copy(chessBoard.Pieces(), debugOutBoard, 64);
if (debugBoard[0] < 0 || debugBoard[1] < 0 || debugBoard[2] < 0 || debugBoard[3] < 0 || debugBoard[0] > 7 || debugBoard[1] > 7 || debugBoard[2] > 7 || debugBoard[3] > 7)
break;
debugOutBoard[debugBoard[2], debugBoard[3]] = debugOutBoard[debugBoard[0], debugBoard[1]];
debugOutBoard[debugBoard[0], debugBoard[1]] = 0;
int rowLength = debugOutBoard.GetLength(0);
int colLength = debugOutBoard.GetLength(1);
for (int i = 0; i < rowLength; i++)
{
for (int j = 0; j < colLength; j++)
{
Debug.Write(debugOutBoard[i, j].ToString().PadLeft(3, ' '));
}
Debug.Write(Environment.NewLine + Environment.NewLine);
}
}
Also, I tried using a concurrentbag to store moves in (I was going to multithread the move processing later on) but as soon as the foreach loop touched the concurrent bag, all the memory values of the bag changed to one value. I've been stuck on this roadblock for days, and I really need help.
Your if statement breaks out of the for loop when its condition is met, I presume this happens for the first time on the 5th/6th iteration.
What I meant to do is iterate to the next element. What command would I use to do that? –
You need to use continue instead of break
If 'futures' contains 86 items the only way it could stop iterating is if an exception occurs. Visual studio (In default settings) should break when this occurs unless you handle the exception somewhere.
Wrap the whole thing in a try{} catch{} and set a breakpoint in catch and see if it hits.

Searching a random Array for a specific value

Hi I have been told to "Write code that determines if a value, say “5”, is contained in the array from task 7(a random array) by going backwards through the array starting at the end and comparing the search value with the values in the array. After the search, if the value is found print “The value has been found” otherwise print “The value has not been found”."
I understand the creation of the random array but I am stuck on how to work backwards through it and locate the specific value.
Here is the code so far
class Program
{
static void Main(string[] args)
{
int[] myArray = new int[10];
Random rand = new Random();
for (int i = 0; i < myArray.Length; i++)
{
myArray[i] = rand.Next(19);
}
}
}
}
Use the loop starting from largest to smallest index.
bool found = false;
for (int i = myArray.Length - 1; i >=0 ; i--)
if(myArray[i] == 5)
found = true;
if(found)
{
}
else
{
}
To go backward just use a for loop with the iterator to i--.
for (int i = myArray.Length - 1; i >= 0; i---)
{
if(// Check if myArray[i] equals the value to find)
{
// If it is the case, you can get out from the for loop with break
break;
}
}
The for loop is splitted in 4 parts:
for (initializer; condition; iterator)
body
The initializer is executed before the first iteration in the loop (here you want to start at the last index in the array : myArray.Length - 1)
The condition is evaluated for each iteration, if this condition is true then it goes to 3 (you want to stay in the for loop while i >= 0) otherwise it quit the for loop
The body is executed for each iteration that satisfy the condition
The iterator is executed (here as you want to go backward you want to decrease i)
Then it go back to 2

Categories