Strange behaviour when threads using local var [duplicate] - c#

This question already has answers here:
creating new threads in a loop
(2 answers)
Closed 9 years ago.
I wrote a simple code
void go()
{
int i = 5;
ThreadPool.QueueUserWorkItem(delegate
{
for (int j = 1; j <= 1000; j++)
Console.Write(i);
});
for (int k = 1; k <= 1000; k++)
i = k;
Console.ReadLine();
}
What I got is : 100010001000100010001000....
I don't know why, I hope someone can explain it to me, thanks!

The loop that assigns k to i is run before the queued threads are being started.
So, at the time the queued threads are started, i has the value 1000 which is what you see.

Change the code to something like
void go()
{
int i = 5;
int i1 = i; //note this
ThreadPool.QueueUserWorkItem(delegate
{
for (int j = 1; j <= 1000; j++)
Console.Write(i1); //and note this
});
for (int k = 1; k <= 1000; k++)
i = k;
Console.ReadLine();
}
Resharper reports "Access to modified closure".

Related

How do I print # in a nested for loop [duplicate]

This question already has an answer here:
What is an "index out of range" exception, and how do I fix it? [duplicate]
(1 answer)
Closed 4 years ago.
for (int i = 0; i <= 6; i++)
{
string[] doors = new string[6];
doors[i] = "#";
for (int j = 1; j <=i; j++)
{
Console.Write(doors[j]);
}
Console.Writeline():
}
Hi guys. I need to print # one and then # twice, until i get to six times. It says System.index.out.of.range. How come?
You should try to extend your array, it's limited to 6 elements but you try to access 7 elements as you go through 0 to 6.
for (int i = 0; i <= 6; i++)
{
string[] doors = new string[7];
doors[i] = "#";
for (int j = 1; j <=i; j++)
{
Console.Write(doors[j]);
}
Console.Writeline():
}
If
I need to print # one and then # twice, until i get to six times.
You don't want any array - string[] doors = new string[6];, just loops:
for (int line = 1; line <= 6; ++line) {
for (int column = 1; column <= line; ++column) {
Console.Write('#');
}
Console.WriteLine();
}
If you have to work with array (i.e. array will be used somewhere else), get rid of magic numbers:
// Create and fill the array
string[] doors = new string[6];
for (int i = 0; i < doors.Length; i++)
doors[i] = "#";
// Printing out the array in the desired view
for (int i = 0; i < doors.Length; i++) {
for (int j = 0; j < i; j++) {
Console.Write(doors[j]);
}
Console.Writeline();
}
Please, notice that arrays are zero-based (array with 6 items has 0..5 indexes for them)
because it is out of range.
change it to this:
for (int i = 0; i <= 6; i++)
{
string[] doors = new string[6];
doors[i] = "#";
for (int j = 0; j <=i.length; j++)
{
Console.Write(doors[j]);
}
Console.Writeline():
}
No need to use 2 loops. Just repeat that character
for (int i = 0; i <= 6; i++)
{
Console.Write(new String("#",i));
Console.WriteLine():
}

C# : Find the largest palindromic number made from product of 3-digit numbers

I'm writing a program to find the largest palindromic number made from product of 3-digit numbers. Firstly,i Create a method which has ability to check if it is a palindromic number. Here is my code :
static int check(string input_number)
{
for (int i = 0; i < input_number.Length/2; i++)
if (input_number[i] != input_number[input_number.Length - i])
return 0;
return 1;
}
After that, it's my main code:
static void Main(string[] args)
{
int k = 0;
for (int i = 0; i < 999; i++)
for (int j = 0; j < 999; j++)
{
k = i * j;
if (check(k.ToString()) == 1)
Console.Write(k + " ");
}
}
But when it has a problem that the length of input_number is zero. So my code doesn't run right way. What can I do to solve the length of input_number?
You have a few bugs in your code:
1. 3-digit-numbers range from `100` to `999`, not from `0` to `998` as your loops currently do.
So your Main method should look like this:
static void Main(string[] args)
{
int k = 0;
for (int i = 100; i <= 999; i++)
for (int j = 100; j <= 999; j++)
{
k = i * j;
if (check(k.ToString()) == 1)
Console.Write(k + " ");
}
}
Now all pairs of three digit numbers are checked. But to improve performance you can let j start at i, because you already checked e.g. 213 * 416 and don't need to check 416 * 213 anymore:
for (int i = 100; i <= 999; i++)
for (int j = i; j <= 999; j++) // start at i
And since you want to find the largest, you may want to start at the other end:
for (int i = 999; i >= 100; i--)
for (int j = 999; j >= 100; j--)
But that still does not guarantee that the first result will be the largest. You need to collect the result and sort them. Here is my LINQ suggestion for your Main:
var results = from i in Enumerable.Range(100, 900)
from j in Enumerable.Range(i, 1000-i)
let k = i * j
where (check(k.ToString() == 1)
orderby k descending
select new {i, j, k};
var highestResult = results.FirstOrDefault();
if (highestResult == null)
Console.WriteLine("There are no palindromes!");
else
Console.WriteLine($"The highest palindrome is {highestResult.i} * {highestResult.j} = {highestResult.k}");
2. Your palindrome-check is broken
You compare the character at index i to input_number[input_number.Length - i], which will throw an IndexOutOfRangeException for i = 0. Strings are zero-based index, so index of the last character is Length-1. So change the line to
if (input_number[i] != input_number[input_number.Length - i - 1])
Finally, I suggest to make the check method of return type bool instead of int:
static bool check(string input_number)
{
for (int i = 0; i < input_number.Length/2; i++)
if (input_number[i] != input_number[input_number.Length - i - 1])
return false;
return true;
}
This seems more natural to me.
You can use method below. Because you are trying to find the largest number you start from 999 and head backwards, do multiplication and check if its palindrome.
private void FindProduct()
{
var numbers = new List<int>();
for (int i = 999; i > 99; i--)
{
for (int j = 999; j > 99; j--)
{
var product = i * j;
var productString = product.ToString();
var reversed = product.Reverse();
if (product == reversed)
{
numbers.Add(product);
}
}
}
Console.WriteLine(numbers.Max());
}

Infinite loop when iterating over a character array [closed]

Closed. This question is not reproducible or was caused by typos. It is not currently accepting answers.
This question was caused by a typo or a problem that can no longer be reproduced. While similar questions may be on-topic here, this one was resolved in a way less likely to help future readers.
Closed 6 years ago.
Improve this question
The following program is going in infinite loop when I am trying to access a multiple line input,do you have any idea why is it not working?
namespace AlternatingCharacters
{
class Program
{
static void Main(string[] args)
{
int N = Int32.Parse(Console.ReadLine());
string[] str = new string[N];
for (int i = 0; i < N ; i++)
{
str[i] = Console.ReadLine();
}
for (int i = 0; i < str.Length; i++)
{
int count = 0;
Char[] strArray = str[i].ToCharArray();
for (int j = 0; j < strArray.Length; j++)
{
if (strArray[i] == strArray[i + 1])
{
count++;
}
}
Console.WriteLine(count);
Console.ReadLine();
}
}
}
}
The problem is in this line:
for (int j = 0; i < strArray.Length; j++)
Your condition is checking on i, not on j, so i will always be 0 (start value) and will never change during the loop.
The right code is:
for (int j = 0; j < strArray.Length; j++)
After that it will fail on this line:
if (strArray[i] == strArray[i + 1])
At the end, it can't find 'the last index + 1' which you can prevent by subtracting one on the end, so this (also I think you need j here):
for (int j = 0; j < strArray.Length - 1; j++)
{
if (strArray[j] == strArray[j + 1])
{
count++;
}
}
The error comes from this piece of code:
for (int i = 0; i < str.Length; i++)
{
int count = 0;
Char[] strArray = str[i].ToCharArray();
for (int j = 0; i < strArray.Length; j++)
{
if (strArray[i] == strArray[i + 1])
{
count++;
}
}
Console.WriteLine(count);
Console.ReadLine();
}
First your loop-condition of the inner loop is whrong. While you increment j you check if i equals the number of elements in your array. More critical than this however is that you also use the whring array-elements. I guess you should use if (strArray[j] == strArray[j + 1]) instead of using i as index.
So all in all this should work:
for (int i = 0; i < str.Length; i++)
{
int count = 0;
Char[] strArray = str[i].ToCharArray();
for (int j = 0; j < strArray.Length; j++)
{
if (strArray[j] == strArray[j + 1])
{
count++;
}
}
Console.WriteLine(count);
Console.ReadLine();
}

Bubblesorting Need answers [duplicate]

This question already has answers here:
What is an IndexOutOfRangeException / ArgumentOutOfRangeException and how do I fix it?
(5 answers)
Closed 8 years ago.
I need some help with this code. I'm playing with this for a couple of hours and got nothing. So I'm asking for help from you guys.
The Array[b] was always returns out of bounds exception. I don't know why.
{
int[] Array = new int[6];
Array[0] = c;
Array[1] = d;
Array[2] = e;
Array[3] = f;
Array[4] = g;
int a = 0;
int b = 1;
int temp = 0;
for (int counter = 0; counter < Array.Length; counter++)
{
for (int counter2 = 0; counter2 < Array.Length; counter2++)
{
if (Array[a] > Array[b])
{
Console.WriteLine("{0} is Greater Than {1}, Swapping ({0},{1})", Array[a], Array[b]);
temp = Array[a];
Array[a] = Array[b];
Array[b] = temp;
Console.WriteLine("");
}
else
{
Console.WriteLine("{0} is Less Than {1}, Retain Value Position", Array[a], Array[b]);
Console.WriteLine("");
}
a += 1;
b += 1;
}
a = 0;
b = 0;
}
for (int counter = 0; counter < Array.Length; counter++)
{
Console.Write(Array[counter] + " ");
}
Console.WriteLine("Final Position");
return a;
}
Thanks, this is my code i hope any one of you can help me.
You are comparing one element to the next, so if you've arrived at the last element, there is no "next" element and you're out of bounds.
Change the inner loop to only go until Length - 1 to prevent this:
for (int counter = 0; counter < Array.Length; counter++)
{
for (int counter2 = 0; counter2 < Array.Length - 1; counter2++)
// ...
}
before incrementing b, check if you are in the last index of the array, because you start b at 1 instead of 0, so it will go out of bounds if you enter the block while looping over the last array index.

Threading modifying unintended variable [duplicate]

This question already has answers here:
Captured variable in a loop in C#
(10 answers)
Closed 9 years ago.
I'm fairly new to C# threading, so apologies in advance for this newbie error. The aim of the following code is to evaluate the fitness of a population that is stored in an array called members. The procedure members.calculateFitness() is a black box (i.e. I can't modify it to improve performance), so I'm trying to setup threads that call the black box simultaneously, and each thread will deal with 1/THREAD_COUNT population members (so if THREAD_COUNT=4, each thread will deal with 1/4 of the population).
In the first for loop I initialise each thread. In the second for loop, I start the thread.
public void ThreadedPrintPopFitness ()
{
int THREAD_COUNT = 1;
int membersPerThread = members.Length / THREAD_COUNT;
Thread[] fitnessCalculator = new Thread[THREAD_COUNT];
int[] threadResult = new int[THREAD_COUNT];
for (int i = 0; i < THREAD_COUNT; i++) {
int start = i * membersPerThread;
int stop = (i+1) * membersPerThread;
fitnessCalculator [i] = new Thread (() => getMaxFitness (members, start, stop, ref threadResult [i]));
}
for (int i = 0; i < THREAD_COUNT; i++) {
fitnessCalculator [i].Start ();
}
for (int i = 0; i < THREAD_COUNT; i++) {
fitnessCalculator [i].Join ();
}
int maxFitness = 0;
for (int i = 0; i < THREAD_COUNT; i++) {
if (maxFitness < threadResult [i])
maxFitness = threadResult [i];
}
Console.WriteLine ("(ThreadedCount) Fittest Population Member's Fitness: " + maxFitness);
}
private static void getMaxFitness (PopulationMember[] members, int start, int stop, ref int result)
{
int maxFitness = 0;
for (int i = start; i < stop && i < members.Length; i++) {
if (members [i].calculateFitness () > maxFitness) {
maxFitness = members [i].lastFitness;
}
}
result = maxFitness;
}
Stepping through the code shows that it gets into the second for loop, and then jumps back to the first for loop and declares an IndexOutOfBoundsException on the integer i. I can see that i = THREAD_COUNT (I've tried with different numbers for THREAD_COUNT).
I'm completely baffled, what am I doing wrong?
Thanks in advance!
Servy has it spot on, I even remember reading about this in John Skeet's book now. I had to make a copy of i within the for loop, this fixed it.
Thanks!
As written in the comments, i is captured, and when increased, the function refers to the new value.
What you should do is copy its value to a local variable:
for (int i = 0; i < THREAD_COUNT; i++) {
int start = i * membersPerThread;
int stop = (i+1) * membersPerThread;
int resultId = i;
fitnessCalculator [i] = new Thread (() => getMaxFitness (members, start, stop, ref threadResult [resultId]));
}

Categories