Variable in switch, switch in loop, error in case 2 - c#

Welcome, I've a problem with small funcion in switch.
My problem is "Use of unassigned local variable 'matrix'"
Here is a code:
static void Main(string[] args)
{
char wyj = 'n';
do
{
Console.WriteLine("1. add numbers into matrix \n2. show matrix \n3. end");
int a;
Console.Write("\nYour choice: ");
a = int.Parse(Console.ReadLine());
switch (a)
{
case 1:
Console.WriteLine("You choose: 1");
int element;
Console.Write("\nsize of matrix: ");
int matrixsize;
matrixsize = Int32.Parse(Console.ReadLine());
int[,] matrix = new int[matrixsize, matrixsize];
for (int i = 0; i <= matrixsize - 1; i++)
{
for (int j = 0; j <= matrixsize - 1; j++)
{
Console.Write("element{0},{1} =", i + 1, j + 1);
element = int.Parse(Console.ReadLine());
matrix[i, j] = element;
}
}
break;
case 2:
Console.WriteLine("You choose 2");
foreach (int x in matrix)
Console.Write(x);
break;
case 3:
Console.WriteLine("End the program? y- yes, n- no");
wyj = char.Parse(Console.ReadLine());
break;
}
}
while (wyj != 'y');
Console.WriteLine("Koniec programu!");
Console.ReadKey();
}
What i need to do?
After Doc Brown answer, in case 2 nothing happens, the matrix is empty.
I think the loop is the problem?

You should not assume that the user first enters 1, then 2, but expect that this might happen the other way round.
the declaration int[,] matrix must be done before the switch statement, and you should set the variable to null there int[,] matrix=null;
the initialization matrix = new int[matrixsize, matrixsize] can stay where it is, but
in the case 2 block, you have to check if matrix was initialized if(matrix!=null) {/*...*/}

You've made an assumption that the compiler can't verify--that you will always generate the matrix be forming viewing it. The compiler knows that this doesn't have to be the case in a switch statement, so it prevents you from using a variable which may never have been set (or in this case, even declared). If you want to keep this code, declare the variable outside of the case and initialize it to a new matrix. Then check in case two if it is safe to display.

The matrix variable is local to the switch. The case 2 uses the variable from case 1, because case does not introduce a scope, but it is never initialized there, because the initializer is not executed when doing case 2.
Moving the variable out of the switch will silence the error if you provide initializer, but it will still be a new variable in each iteration, so when you fill it in in case 1, it will come out empty when doing case 2 in next iteration. You need to move the variable all the way out of the loop to have to values persist.
You still should not assume that user provides the inputs in correct order, so in the case 2 you have to check that the matrix was already filled in.

Related

Switch Event Being Skipped in Debug

I have a WPF application which has random chances of random events occurring. I have a switch statement like so which switches a random number:
(property)
static Random RandomObject { get; set; } = new Random();
...
RandomObject = new Random();
switch (RandomObject.Next())
{
case 1 when RandomObject.Next(1, 3) == 2:
// a
case 1 when RandomObject.Next(1, 13) == 2:
// b
break;
}
For some reason, in debug mode, the whole switch is being skipped completely. Could someone tell me what I'm doing wrong or how I could possibly make it so it does work?
EDIT: Okay can someone tell me how to fix this instead because I remember coming up with something similar that does what I want to do and it did work but the problem is my hard drive crashed so I lost all of my data
Would this be possible?
switch(RandomObject)
{
case 1 when RandomObject.Next(1,3) == 2:
//do stuff
break;
}
I will run tests to try to show you what's going wrong. Let's take this code, which is similar to your own:
int acount = 0, bcount = 0;
var r = new Random();
for(var i = 0; i < 1_000_000_000; ++i) // 1 billion iterations
{
switch (r.Next())
{
case 1 when r.Next(1, 3) == 2:
++acount;
break;
case 1 when r.Next(1, 13) == 2:
++bcount;
break;
}
}
Console.WriteLine($"a case hit {acount} times");
Console.WriteLine($"b case hit {bcount} times");
The output is:
a case hit 0 times
b case hit 0 times
Now, let's try shrinking up your range on your switch statement:
// ...
switch (r.Next(1, 20))
{
// ...
Your results are now:
a case hit 26313397 times
b case hit 2191910 times
So what we are trying to tell you in the comments is Random.Next() returns a value in the range of [0, 2147483647], which is near unlikely to ever return the value of 1, which is what your switch cases require to continue. By changing your range with much more reasonable values, your chances increase dramatically and is more than likely what you want.

Strange behavior with multithreading and random

Edit # Dublicate: I know that an unsafe use of Thread is not recomented. My question is about the why, and not about if random is thread-safe. Thanks to the answers, helped me understandig it better!
I wrote a "gimmick" program that is supposed to display random chars with random colors (For- and Background) in a Console-Window using Math.Random() and Multithreading. For more randomness I didn't made the program "thread safe". (Additional Information: I originally wanted the program to display an Space-Invader in the center, I achieved that with Thread-Safety, and I know, multithreading is supposed to be thread safe but this is not what this question is about)
The output looks like this:
The function of the program is like that: I have an Array in which all the Positions (X/Y) with colors and Char are stored. I have some Functions that change this array and I have some functions to display the array. I also got a function to return random chars and one to return random colors.
Now the point that I don't get: Sometimes everything works as described, but sometimes the program starts to display only !-Chars (exclamation mark) but keeps the random colors and positions:
Another time the program only shows the colors black and white but the chars keep being random:
And sometimes it happens, that the program only displays !-Chars and only black and white:
What I could say is the following:
My "Get a Random Char" function looks like that:
public static char GetChar()
{
return (char)randomChar.Next(33, 150);
}
!-Char is Ascii-Char 33. That means if the Program get stucked the Random-Char-Function only returns the lowest Random-Char (== 33 == !)
I got something similar for the colors. I give an random-number between 0 and 16 to a function to get back a Console-Color:
private ConsoleColor SetColor(char ColorIndex)
{
switch (ColorIndex)
{
case (char)1:
return ConsoleColor.Black;
case (char)2:
return ConsoleColor.Blue;
case (char)3:
return ConsoleColor.Cyan;
case (char)4:
return ConsoleColor.DarkBlue;
case (char)5:
return ConsoleColor.DarkCyan;
case (char)6:
return ConsoleColor.DarkGray;
case (char)7:
return ConsoleColor.DarkGreen;
case (char)8:
return ConsoleColor.DarkMagenta;
case (char)9:
return ConsoleColor.DarkRed;
case (char)10:
return ConsoleColor.DarkYellow;
case (char)11:
return ConsoleColor.Gray;
case (char)12:
return ConsoleColor.Green;
case (char)13:
return ConsoleColor.Magenta;
case (char)14:
return ConsoleColor.Red;
case (char)15:
return ConsoleColor.White;
case (char)16:
return ConsoleColor.Yellow;
default:
return ConsoleColor.Black;
}
}
//The call looks like that:
_Data[x, y, 1] = (char)random.Next(0, 16);
I know that random.Next(0, 16) will give a 15 as maximum number back, and 15 is the color white in the example. If I change 15 to red, the Program will display red instead of white, when the program gets stucked:
This means: When the program got stucked the Random-Char-Function always returns the lowest possible number (33) and the Random-Color-Function always returns the highest possible number (15).
The question: Why is this behaviour? Why is it just sometimes and not every time? And why it is every time after a different time of running? Why is one random function always returning max-number and the other one always the min-number?
My guess is, that his is because of the CPU predicting, but as I said, it's just a guess and I wonder how this works, and why it goes to different approaches (min/max).
Here are some of my Code, if needed I could post more Code:
//Program-Start after initialising some stuff:
public AnotherOne()
{
new Thread(DrawData).Start();
new Thread(DrawDataLR).Start();
new Thread(DrawDataRL).Start();
new Thread(DrawDataTD).Start();
new Thread(DrawDataDT).Start();
new Thread(ChangeData).Start();
ChangeData();
}
//Draw Data example for Left-Right:
private void DrawDataLR()
{
while (!_done)
{
DrawDataLeftRight();
Thread.Sleep(2);
}
}
private void DrawDataLeftRight()
{
for (int x = 0; x < _Width - 1; x++)
{
for (int y = 0; y < _Height - 1; y++)
{
Console.SetCursorPosition(x, y);
Console.BackgroundColor = SetColor(_Data[x, y, 1]);
Console.ForegroundColor = SetColor(_Data[x, y, 2]);
Console.WriteLine(_Data[x, y, 0]);
}
}
}
//Draw Data Function:
private void DrawData()
{
Random next = new Random();
int x = 1;
while (!_done)
{
x = next.Next(1, 5);
switch (x)
{
case 1:
DrawDataLeftRight();
break;
case 2:
DrawDataTopDown();
break;
case 3:
DrawDataRightLeft();
break;
case 4:
DrawDataDownTop();
break;
}
}
}
//Change Data Function with "stripes" as Example:
private void ChangeData()
{
int x = 100;
while (!_done)
{
FillRandomFeld();
Thread.Sleep(x);
ClearChar();
Thread.Sleep(x);
SetColor();
Thread.Sleep(x);
Stripes();
Thread.Sleep(x);
SetChar();
Thread.Sleep(x);
OtherStripes();
Thread.Sleep(x);
x = randomX.Next(0, 100);
}
}
private void Stripes()
{
char colr = (char)random.Next(0, 16);
for (int x = 0; x < _Width - 1; x += 4)
{
for (int y = 0; y < _Height - 1; y++)
{
if (_Data[x, y, 3] != (char)1)
{
_Data[x, y, 1] = colr;
_Data[x, y, 2] = colr;
}
}
}
}
Random.Next() ends up calling this code (from the reference source):
private int InternalSample() {
int retVal;
int locINext = inext;
int locINextp = inextp;
if (++locINext >=56) locINext=1;
if (++locINextp>= 56) locINextp = 1;
retVal = SeedArray[locINext]-SeedArray[locINextp];
if (retVal == MBIG) retVal--;
if (retVal<0) retVal+=MBIG;
SeedArray[locINext]=retVal;
inext = locINext;
inextp = locINextp;
return retVal;
}
Looking at this code, it is obvious that multithreaded access could do some very bad things. For example, if inext and inextp end up containing the same value, then SeedArray[locINext]-SeedArray[locINextp]; will always result in 0, and Random.Next() will always return 0.
I'm sure you can start to imagine lots of other ways that multithreaded access to this code could mess things up.
Conceptually, PRNGs internally have a large number of states, where each state corresponds to a possible output of the PRNG (although multiple states can have the same output), and they walk through each one of those states in a deterministic order. If you corrupt the internal state of the PRNG, it may start walking through a much smaller set of those states before looping back to the first one, so you get a small repeating set of "random" output numbers.
In another place in your code, you are creating a new Random instance each time the method is called. As mentioned in the linked answer, this will result in many Random instances which return the same set of random numbers.
Eric Lippert has an ongoing series of blog posts about improving the Random class: part 1 part 2 (and more to come).
Your multithreaded use of the Random object is corrupting its internal state.
You can reproduce the issue fairly easily using the following program. If you run it, after a while (or sometimes, immediately) it will start producing zeroes instead of random numbers. You may have to run it several times to see the effect. Also, it goes wrong more often for a RELEASE build rather than a DEBUG build (which is not unusual for multithreading problems!).
(Note: This was tested using .Net 4.7.2 on a 16 core processor. Results may vary for other systems.)
using System;
using System.Threading.Tasks;
namespace Demo
{
class Program
{
static void Main()
{
Console.WriteLine();
Random rng = new Random(12345);
Parallel.Invoke(
() => printRandomNumbers(rng),
() => printRandomNumbers(rng),
() => printRandomNumbers(rng));
Console.ReadLine();
}
static void printRandomNumbers(Random rng)
{
while (rng.Next() != 0)
{}
while (true)
{
Console.WriteLine(rng.Next());
}
}
}
}

How do I find the location of a particular string in a string array?

Yes, this is for school work however the question is a very small part of work and I feel as though it's almost negligible.
In short, I have used a string array to print a grid like this
Random rnd = new Random();
for (row = 0; row <= 5; row++)
{
for (column = 0; column <= 5; column++)
{
RandomNumber = rnd.Next(1, 13);
if (RandomNumber == 3)
luckDipBoard[row, column] = "You Win ";
else
luckDipBoard[row, column] = "You Lose ";
}
}
//Display board
for (row = 0; row <= 5; row++)
{
for (column = 0; column <= 5; column++)
{
Console.SetCursorPosition(column * 10, row * 2);
if (luckDipBoard[row, column] == "You Win ")
Console.ForegroundColor = ConsoleColor.Green;
else
Console.ForegroundColor = ConsoleColor.Red;
Console.Write(luckDipBoard[row, column]);
}
}
It prints the array grid and colours the variables accordingly. However, what I want to be able to do is for the user to be able to input a location, which I have written:
Console.WriteLine("Input a row");
rowChoice = int.Parse(Console.ReadLine());
Console.WriteLine("Input a column");
columnChoice = int.Parse(Console.ReadLine());
Console.Clear();
However, I have no idea how to turn these variables into a location in the array and search the array with these co-ordinates and find out what is inside of the location. So for example if the grid printed randomly and column 2 row 1 was "You Win ", and the user inputted column 2 row 1, it would simply add credits to a variable.
If somebody could point me in the right direction of:
Using the two input values as a location
Searching the array and returning the value inside of the location
int TextIndex = Array.FindIndex(luckDipBoard, m => m == "You Win ");
Errors: Severity Code Description Project File Line Suppression State Error CS0411 The type arguments for method 'Array.FindIndex(T[], Predicate)' cannot be inferred from the usage. Try specifying the type arguments explicitly.
The reason that Array.FindIndex doesn't work is that it only works with vectors (i.e string[]) - but you have a 2D array (i.e. string[,]). AFAIK, none of the regular array hunting methods work on multi-dimensional arrays, so you have two options:
do the hunt yourself by looping over the x/y dimensions manually
linearize your array and deal with the dimensionality manully (this would mean having a string[] instead, and computing the offsets via multiplication)
If you're fairly unfamiliar with it, the first approach (looping over x/y) is probably easier than the second (which would involve changing just about every line of code).

Variable doesn't recognize previous conversion?

I'm doing a console app for calculating BMI using arbitrary formulas for practice. The problem is with switch (index), Visual Studio keeps telling me that switch can't use double, even though I've already converted index to int. Simply using Convert.ToInt32(index) doesn't work either. What am I missing here?
bool loop = true;
int suly;
double magassag;
double index;
string valasz;
while (loop)
{
Console.WriteLine("Add meg a sulyodat");
suly = int.Parse(Console.ReadLine());
Console.WriteLine("Add meg a magassagodat");
magassag = double.Parse(Console.ReadLine());
magassag = magassag / 100;
index = suly / Math.Pow(magassag, 2);
index = Math.Round(index, 2);
Console.WriteLine(index + " a testtomeg indexed");
index = Convert.ToInt32(index);
switch (index)
{
case (0-5):
Console.WriteLine("asd1");
break;
case (6-10):
Console.WriteLine("asd");
break;
default:
Console.WriteLine("asd3");
break;
}
Console.WriteLine("Újra? igen/nem");
valasz = Console.ReadLine();
if (valasz == "igen")
loop = true;
else loop = false;
You can't use double in a switch. Index is still a double
index = Convert.ToInt32(index);
This converts the double value of index to an int. You then assign it to index (which is a double), which does an implicit conversion back to double.
int foo = Convert.ToInt32(index) would work
or even switch(Convert.ToInt32(index))
Just some notes:
1) You should declare your variables when you need them. For example suly exists in the scope of main, when it only need to be in the scope of the while loop.
2) Your loop variable is doing what the break keyword already does
3) Convert.ToInt32 already provides rounding (that's one of the things that makes it different from a cast ( (int)index ).
4) things like magassag = double.Parse(Console.ReadLine()); magassag = magassag / 100; could easily be done in one statment, and probably would be a bit clearer.
5) case (0-5) means case(-5), case (6-10) is -4. You want use if statements if( foo >= 0 || foo <= 5) or use switch statement fallthrough
It's always a good idea to just debug your program.
Visual Studio helps you a lot in these cases.
Set a breakpoint after your calculation on the index variable.
In the watches window you can check the type.
Anyway as a solution I agree with Praveen Paulose
switch(Convert.ToInt32(index))
The data type for index is double. That is why you get this error.
Try passing an int as shown below
switch(Convert.ToInt32(index))
The index is declared as double index;. Change that into int index;:
bool loop = true;
int suly;
double magassag;
int index; // not double
string valasz;
Otherwise the assignment will promote the int value produced by Convert.ToInt32() back into a double again, thus produce the error you see. The other solution is to throw out the index at all and just do the conversion where you need it:
switch( Convert.ToInt32(index))

How to Fill an array from user input C#?

What would be the best way to fill an array from user input?
Would a solution be showing a prompt message and then get the values from from the user?
string []answer = new string[10];
for(int i = 0;i<answer.length;i++)
{
answer[i]= Console.ReadLine();
}
Could you clarify the question a bit? Are you trying to get a fixed number of answers from the user? What data type do you expect -- text, integers, floating-point decimal numbers? That makes a big difference.
If you wanted, for instance, an array of integers, you could ask the user to enter them separated by spaces or commas, then use
string foo = Console.ReadLine();
string[] tokens = foo.Split(",");
List<int> nums = new List<int>();
int oneNum;
foreach(string s in tokens)
{
if(Int32.TryParse(s, out oneNum))
nums.Add(oneNum);
}
Of course, you don't necessarily have to go the extra step of converting to ints, but I thought it might help to show how you would.
It made a lot more sense to add this as an answer to arin's code than to keep doing it in comments...
1) Consider using decimal instead of double. It's more likely to give the answer the user expects. See http://pobox.com/~skeet/csharp/floatingpoint.html and http://pobox.com/~skeet/csharp/decimal.html for reasons why. Basically decimal works a lot closer to how humans think about numbers than double does. Double works more like how computers "naturally" think about numbers, which is why it's faster - but that's not relevant here.
2) For user input, it's usually worth using a method which doesn't throw an exception on bad input - e.g. decimal.TryParse and int.TryParse. These return a Boolean value to say whether or not the parse succeeded, and use an out parameter to give the result. If you haven't started learning about out parameters yet, it might be worth ignoring this point for the moment.
3) It's only a little point, but I think it's wise to have braces round all "for"/"if" (etc) bodies, so I'd change this:
for (int counter = 0; counter < 6; counter++)
Console.WriteLine("{0,5}{1,8}", counter, array[counter]);
to this:
for (int counter = 0; counter < 6; counter++)
{
Console.WriteLine("{0,5}{1,8}", counter, array[counter]);
}
It makes the block clearer, and means you don't accidentally write:
for (int counter = 0; counter < 6; counter++)
Console.WriteLine("{0,5}{1,8}", counter, array[counter]);
Console.WriteLine("----"); // This isn't part of the for loop!
4) Your switch statement doesn't have a default case - so if the user types anything other than "yes" or "no" it will just ignore them and quit. You might want to have something like:
bool keepGoing = true;
while (keepGoing)
{
switch (answer)
{
case "yes":
Console.WriteLine("===============================================");
Console.WriteLine("please enter the array index you wish to get the value of it");
int index = Convert.ToInt32(Console.ReadLine());
Console.WriteLine("===============================================");
Console.WriteLine("The Value of the selected index is:");
Console.WriteLine(array[index]);
keepGoing = false;
break;
case "no":
Console.WriteLine("===============================================");
Console.WriteLine("HAVE A NICE DAY SIR");
keepGoing = false;
break;
default:
Console.WriteLine("Sorry, I didn't understand that. Please enter yes or no");
break;
}
}
5) When you've started learning about LINQ, you might want to come back to this and replace your for loop which sums the input as just:
// Or decimal, of course, if you've made the earlier selected change
double sum = input.Sum();
Again, this is fairly advanced - don't worry about it for now!
C# does not have a message box that will gather input, but you can use the Visual Basic input box instead.
If you add a reference to "Microsoft Visual Basic .NET Runtime" and then insert:
using Microsoft.VisualBasic;
You can do the following:
List<string> responses = new List<string>();
string response = "";
while(!(response = Interaction.InputBox("Please enter your information",
"Window Title",
"Default Text",
xPosition,
yPosition)).equals(""))
{
responses.Add(response);
}
responses.ToArray();
Try:
array[i] = Convert.ToDouble(Console.Readline());
You might also want to use double.TryParse() to make sure that the user didn't enter bogus text and handle that somehow.
I've done it finaly check it and if there is a better way tell me guys
static void Main()
{
double[] array = new double[6];
Console.WriteLine("Please Sir Enter 6 Floating numbers");
for (int i = 0; i < 6; i++)
{
array[i] = Convert.ToDouble(Console.ReadLine());
}
double sum = 0;
foreach (double d in array)
{
sum += d;
}
double average = sum / 6;
Console.WriteLine("===============================================");
Console.WriteLine("The Values you've entered are");
Console.WriteLine("{0}{1,8}", "index", "value");
for (int counter = 0; counter < 6; counter++)
Console.WriteLine("{0,5}{1,8}", counter, array[counter]);
Console.WriteLine("===============================================");
Console.WriteLine("The average is ;");
Console.WriteLine(average);
Console.WriteLine("===============================================");
Console.WriteLine("would you like to search for a certain elemnt ? (enter yes or no)");
string answer = Console.ReadLine();
switch (answer)
{
case "yes":
Console.WriteLine("===============================================");
Console.WriteLine("please enter the array index you wish to get the value of it");
int index = Convert.ToInt32(Console.ReadLine());
Console.WriteLine("===============================================");
Console.WriteLine("The Value of the selected index is:");
Console.WriteLine(array[index]);
break;
case "no":
Console.WriteLine("===============================================");
Console.WriteLine("HAVE A NICE DAY SIR");
break;
}
}
Add the input values to a List and when you are done use List.ToArray() to get an array with the values.
of course....Console.ReadLine always return string....so you have to convert type string to double
array[i]=double.Parse(Console.ReadLine());
readline is for string..
just use read

Categories

Resources