Do loops and while loops - c#

When I type in the word "Andrea" the program crashes. I am guessing, but I think it's because I am inside the loop and it doesn't know when to stop. If I am correct can you tell me how to get out of the loop. when I put a break in it tells me there is no loop to end.
private void button1_Click(object sender, EventArgs e)
{
do Commission.Text = (Convert.ToDouble(textBox2.Text) / 10).ToString();
while (textBox1.Text == "Andrea");
break;
do Commission.Text = (Convert.ToDouble(textBox2.Text) / 10).ToString();
while (textBox1.Text == "Brittany");
do Commission.Text = (Convert.ToDouble(textBox2.Text) / 10).ToString();
while (textBox1.Text == "Eric");
break;
MessageBox.Show("The spelling of the name is incorrect", "Bad Spelling");

You have textBox1.Text == "Andrea" and textBox1.Text == "Brittany" as your loop conditions, but you don't seem to be changing that value anywhere in the code. Therefore, you have an infinite loop which will result in your program crashing.
I'm not certain what your program is meant to be doing, but your options to break out of a loop are:
Use a break; statement to exit the loop.
Change your loop condition to something which can eventually result in false.
Change the textBox.Text property somewhere in the loop body.
Alternatively, you could use an if statement to check the condition once, and execute some code if that condition is true.
Edit:
I have done this with if statements but now i am looking to try doing the same thing with loops
no purpose just trying to learn how to program
In response to the above comments, I'll tell you how to replace an if statement with a loop. Just do it like so:
// Check the condition before executing the code.
while (textBox1.Text == "Andrea") {
// Execute the conditional code.
Commission.Text = (Convert.ToDouble(textBox2.Text) / 10).ToString();
// We actually only want to execute this code once like an if statement,
// not while the condition is true, so break out of the loop.
break;
}
In your original post, you are using a do while loop rather than a while loop. You should keep in mind that the do while executes once for certain, regardless of whether its condition is true. It only checks the condition to see whether it should run additional times. The while loop, on the other hand, checks the condition before executing at all, which means you can substitute an if statement with it.
You should keep in mind that this is a bad practice. If you want to execute code depending on a certain condition, use an if statement. If you want to execute code repeatedly a certain number of times or while some condition is true, then use a loop.

At a glance, it looks like you have an infinite loop. As soon as you type in "Andrea" in textBox1 and click button1, it will perpetually update Commission.Text, not interrupting the thread to process any additional input.
The bigger question is, what the heck is this program supposed to be doing? And why is it doing it in a loop?

I suspect that by while you actually mean if. Otherwise, do you get an error message or exception when the application crashes? Can you wrap this function in a try/catch to see what the exception is?
Edit To clarify, try this method body:
private void button1_Click(object sender, EventArgs e)
{
try
{
if(textBox1.Text == "Andrea")
{
Commission.Text = (Convert.ToDouble(textBox2.Text) / 10).ToString();
}
else if(textBox1.Text == "Brittany")
{
Commission.Text = (Convert.ToDouble(textBox2.Text) / 10).ToString();
}
else
{
MessageBox.Show("The spelling of the name is incorrect", "Bad Spelling");
}
}
catch(Exception ex)
{
MessageBox.Show(ex.ToString(), "Bad Spelling");
}
}
}
}

Adding to what FacticiusVir said earlier, you can also do this in a switch statement (and since we're calculating the same commissions for each person, they can be combined:
private void button1_Click(object sender, EventArgs e)
{
switch(textBox1.Text)
{
case "Andrea":
case "Brittany":
Commission.Text = (Convert.ToDouble(textBox2.Text) / 10).ToString();
break;
default:
MessageBox.Show("The spelling of the name is incorrect", "Bad Spelling");
}
}
If you want to do different commissions per person you need to split it (in the below Brittany is getting a different commission value now):
private void button1_Click(object sender, EventArgs e)
{
switch(textBox1.Text)
{
case "Andrea":
Commission.Text = (Convert.ToDouble(textBox2.Text) / 10).ToString();
break;
case "Brittany":
Commission.Text = (Convert.ToDouble(textBox2.Text) / 15).ToString();
break;
default:
MessageBox.Show("The spelling of the name is incorrect", "Bad Spelling");
}
}

The do { x } while (y) construct runs x once, and then proceeds to run x continuously as long as y is true.
You're not having any success because you seem to be structuring it like this:
do
{
// This will just run over and over...
}
while (condition); // ...because this is always true.
break; // This isn't even in the loop!
In other words, the point where you're trying to add your break (based on a comment you left on another answer) is outside the loop, which is why your code is running indefinitely.
Now, it sounds like you're really just trying to use a do/while to emulate an if statement, presumably as a challenge to yourself. If that is the case, do yourself a favor and give up on that idea.
You cannot use a do/while loop to emulate an if condition, because do will always run at least once. The only way you could ensure that it runs exactly once under a specific condition (i.e., what if does) would be by embedding an if statement inside the do loop, which would defeat the purpose of the exercise.
That said, you can emulate an if with a while:
while (condition)
{
// Execute code once.
break; // Then just quit.
}

Looking at this one piece:
do Commission.Text = (Convert.ToDouble(textBox2.Text) / 10).ToString();
while (textBox1.Text == "Andrea");
...what do you expect to happen if textBox1.Text == "Andrea"?
What the program is doing is checking your comparison test, then if it's true, it does what is inside of the do / while block, then it checks the comparison test, then if it's true, it does what is inside of the do / while block, then it checks the comparison test, then if it's true, it does what is inside of the do / while block, then...
Get the point?
You use do / while loops if the condition is going to change inside the loop (or you explicitly break out of it).
What you want instead is to change it to something like
if( textBox1.Text == "Andrea" )
Commission.Text = (Convert.ToDouble(textBox2.Text) / 10).ToString();

Just a guess, but as FacticiusVir says, you probably want to use conditionals instead of loops:
private void button1_Click(object sender, EventArgs e)
{
if (textBox1.Text == "Andrea" || textBox1.Text == "Brittany")
{
Commission.Text = (Convert.ToDouble(textBox2.Text) / 10).ToString();
}
else
{
MessageBox.Show("The spelling of the name is incorrect", "Bad Spelling");
}
}

Related

Pin code application that increments number of attempts

I have been trying to finish this small application for counting the number of attempts if you fail to write the correct pin code.
This is my code so far, and I am not understanding why my code isn't working and it keeps on incrementing non stop.
private void btn_login_Click(object sender, EventArgs e)
{
int attempts = 0;
int pin_number;
do
{
pin_number = int.Parse(txt_pin.Text);
MessageBox.Show("Hi There");
if (pin_number != 1326)
{
attempts++;
MessageBox.Show($"pin code is incorrect you have {attempts} of 3 attempts left");
txt_pin.Text = "";
txt_pin.Focus();
}
} while (pin_number == 1326 && attempts < 3);
}
Every time you click the button is an "attempt", correct? Well, what's the first thing you do every time you click the button...
int attempts = 0;
So every attempt is the first attempt. Except when the user gets it right. Then what you have is an infinite loop because the pin_number is correct and attempts is never incremented.
First, get rid of the loop entirely. There's no need to repeatedly check the same input. Once it's checked, it's checked. Second, track the number of attempts outside the scope of each attempt, such as at the class level. Third, check the number of attempts. Perhaps something like this:
private int attempts = 0;
private void btn_login_Click(object sender, EventArgs e)
{
int pin_number;
pin_number = int.Parse(txt_pin.Text);
MessageBox.Show("Hi There");
if (attempts < 3 && pin_number != 1326)
{
attempts++;
MessageBox.Show($"pin code is incorrect you have {attempts} of 3 attempts left");
txt_pin.Text = "";
txt_pin.Focus();
}
}
Now it's at least checking the pin as expected. Though at this point you have some logic to reconsider for your program. Off the top of my head...
It never notifies the user if they got the pin right. Perhaps something else should happen?
After the number of attempts is exhausted, there's no warning to indicate this. It looks exactly as it does if the pin is correct.
The text implies that the number of attempts is counting down, but it's actually counting up.
Perhaps something like this might get you started:
private int attempts = 3;
private void btn_login_Click(object sender, EventArgs e)
{
int pin_number;
pin_number = int.Parse(txt_pin.Text);
MessageBox.Show("Hi There");
if (attempts <= 0)
{
MessageBox.Show($"No more attempts left");
}
else if (pin_number != 1326)
{
attempts--;
MessageBox.Show($"Pin code is incorrect you have {attempts} attempts left");
txt_pin.Text = "";
txt_pin.Focus();
}
}
Examine each statement in the logic. For your own logic, particularly around if blocks and loops and whatnot, perhaps even grab a piece of paper and draw out the different code paths and write down in each path what should happen there. Every detail is important, such as when to show a message or when to modify a value. There's a lot of polish that can be added to this code, and I imagine it's an academic exercise so I'll leave that to you.
Right now you have a loop inside your button click handler. You probably don't want that since you want to enable the user to enter a new pin code and click the Login button again.
But that also means that you need to store the number of attempts outside the click handler, since it needs to be saved from one click to the next.
So if you change your code to something like this, I think you'll get the functionality you're after
private int attempts = 0;
private void btn_login_Click(object sender, EventArgs e)
{
int pin_number;
pin_number = int.Parse(txt_pin.Text);
MessageBox.Show("Hi There");
if (pin_number != 1326)
{
attempts++;
MessageBox.Show($"pin code is incorrect you have {3-attempts} of 3 attempts left");
txt_pin.Text = "";
txt_pin.Focus();
}
if (attempts >= 3)
{
btn_login.Enabled = false;
}
}

How to solve a IndexOutOfRange made by the user?

I'm still new to programming, so every time i get an exeption i try to rewrite code so it is avoided. However in this case i see no way to work around it.
I have a textbox that the user uses to imput commands. The string(imput) is then split after the first space.
private void tbxMainImput_KeyDown(object sender, KeyEventArgs e)
{
if (e.KeyCode == Keys.Enter)
{
string commandText = tbxMainImput.Text.ToLower();
string[] commandTextSplitted = commandText.Split(new char[] { ' ' }, 2, StringSplitOptions.RemoveEmptyEntries);
ReadTextboxImput(commandTextSplitted);
tbxMainImput.ResetText();
e.SuppressKeyPress = true; //anoying beep is removed :)
}
}
this splitted string commandTextSplitted is being used by a switch method ReadTextboxImput
private void ReadTextboxImput(string[] imput)
{
switch (imput[0])
{
//some other cases
case "attack":
StartCombat(imput[1]); //trows exeption if user only types one word
break;
}
}
If a player only types one word, imput[1] doesnt exist, and an IndexOutOfRange exeption is cast(as it should). However the exeption seems unavoidable. the player can type one word and press enter...
so ive been trying some things to check for the exeption and then break out of the code but it doesnt seem to work. The msdn website isn't realy beginners friendly, and all i found on stackoverflow where people asking to find where the error came from. witch i know.
So far i have tried:
case "attack":
if (imput[1] == null) //(imput[1] == system.IndexOutOfRange) doesnt make sense but i had to try
{
rtbOutput.AppendText("Yes yes. Attack nothing...");
break;
}
StartCombat(imput[1]);
break;
i made a method that uses try and catch that worked, but it just detected the error, i wasn't able to do anything with it(like return a false, or something)
Any help would be apreciated.
you can check if the array length is > 1 instead of imput[1] == null
if (imput.Length > 1){
rtbOutput.AppendText("Yes yes. Attack nothing...");
break;
}
StartCombat(imput[1]);
break;

Is it possible to escape out of a `if...elseif...else` statement like `break` does to a loop and `return` does for methods?

In my program, I have a method that has code that is used always when it is run. However, in the same method, I have if statements that branches off the code based on a state machine. Let's just (for simplicity) say that it's made of two values.
using System;
using System.Console;
int stateA = 1;
int stateB = 1;
void Main () {
while (true) {
Method();
}
}
void Method () {
Console.WriteLine("This will always be printed no matter what happens.");
if (stateA == 1 && stateB == 1)
{
Console.WriteLine("State 1");
stateB = 2;
// goto endofifstatement;
}
elseif (stateA == 1 && stateB == 2)
{
Console.WriteLine("State 2");
stateA = 2;
// goto endofifstatement;
}
else {
Console.WriteLine("Resetting States...")
stateA = 1;
stateB = 2;
// goto endofifstatement;
}
// endofifstatement:
Console.WriteLine("This will always also be printed no matter what happens.");
Console.WriteLine("");
}
Now. The problem with this code right now, is that all three parts of the if...elseif...else block will run in every loop iteration.
Of course, there are several ways I could fix this:
Separate (encapsulate) the if...elseif....else statement into its own method and use return to break out.
Swap the contents and expressions for the if and elseif block, but that'd only work in this case. What happens if we have a few hundred cases?
Use goto, but nobody really uses that anymore. (Commented in the snippet above)
Use multiple switch...case or IF statements, nested inside each other.
Question:
Is it possible to escape out of a if...elseif...else statement like break does to a loop and return does for methods?
So for the example above, the output should be:
This will always be printed no matter what happens.
State 1
This will always also be printed no matter what happens.
This will always be printed no matter what happens.
State 2
This will always also be printed no matter what happens
This will always be printed no matter what happens.
Resetting States...
This will always also be printed no matter what happens
And repeat, as opposed to:
This will always be printed no matter what happens.
State 1
State 2
Resetting States...
This will always also be printed no matter what happens
This will always be printed no matter what happens.
State 1
State 2
Resetting States...
This will always also be printed no matter what happens
Aaand repeat. Plus, if we extend this to have more than two variables and possible values, it should be able to hold up, even at the expanse of CPU speed, since we're just essentially breaking out of a block.
Yes, goto statement cause problems because you have to hunt for the line you want to execute next. In addition, it can cause unexpected behaviors in particularly complex code.
You have a number of options available to you. My preference would be to rewrite your logic so it is easier to read (Option 1), but I'll demonstrate the ones I see.
Option 1: Rewrite
void Method() {
Console.WriteLine("This will always be printed no matter what happens.");
if (stateA == 1) {
if (stateB == 1) {
Console.WriteLine("State 1");
stateB = 2;
}
else {
Console.WriteLine("State 2");
stateA = 2;
}
}
else {
Console.WriteLine("Resetting States...")
stateA = 1;
stateB = 2;
}
Console.WriteLine("This will always also be printed no matter what happens.");
Console.WriteLine("");
}
Option 2: Separate method
void UpdateState() {
if (stateA == 1 && stateB == 1) {
Console.WriteLine("State 1");
stateB = 2;
return;
}
elseif (stateA == 1 && stateB == 2) {
Console.WriteLine("State 2");
stateA = 2;
return;
}
else {
Console.WriteLine("Resetting States...")
stateA = 1;
stateB = 2;
return;
}
}
void Method() {
Console.WriteLine("This will always be printed no matter what happens.");
UpdateState();
Console.WriteLine("This will always also be printed no matter what happens.");
Console.WriteLine("");
}
Option 3: try/finally
void Method() {
Console.WriteLine("This will always be printed no matter what happens.");
try {
if (stateA == 1 && stateB == 1) {
Console.WriteLine("State 1");
stateB = 2;
return;
}
elseif (stateA == 1 && stateB == 2) {
Console.WriteLine("State 2");
stateA = 2;
return;
}
else {
Console.WriteLine("Resetting States...")
stateA = 1;
stateB = 2;
return;
}
}
finally {
Console.WriteLine("This will always also be printed no matter what happens.");
Console.WriteLine("");
}
}
Option 4: Encapsulation/Polymorphism
There are a number of design patterns that would apply here. In particular, Strategy and State come to mind.
From what I understand, you are trying to write a cleaner code when the elseif ladder grows very long. If that the case and NOT cpu performance then you have a few options:
State pattern
Have interface ASuitableNameState with method getNextState which return type of ASuitableNameState. Now you can have concrete implementations like class StateAOneBOne : ASuitableNameState and class StateAZeroBOne : ASuitableNameState.
In StateAOneBOne you override the method getNextState . There you return new StateAOneBTwo();
This way your if-else ladder vanishes. Your main can be rewritten as:
using System;
using System.Console;
ASuitableNameState currentState = new StateAOneBOne();
void Main () {
while (true) {
Method();
}
}
void Method () {
consolw.writeLine("A and B are");
console.writeLine(currentState.getA + currentState.getB);
currentState = currentState.getNextState();
}
The downside is, you have to create as many classes as there are stateA and stateB combinations. If the total combinations are witin (say) twenty, then this approach is feasible, otherwise not.

Something is wrong with my code

I am making a music maker program in C# (visual studio).
Here is my code:
int accCount = 0;
enum accidental { flat, sharp, none }
accidental thisAcc = accidental.none;
if (keyComboBox.SelectedItem.ToString().Length < 8)
{
MessageBox.Show("Please select a key!");
}
else switch (keyComboBox.SelectedItem.ToString())
{
case "C major - A minor":
accCount = 0; thisAcc = accidental.none;
break;
case "G major - E minor":
accCount = 1; thisAcc = accidental.sharp;
break;
...etc..
}
and so on...This all is included in postButton_click(postButton_Click(object sender, EventArgs e)
But when I click the button, an exception is shown (An unhandled exception of type 'System.StackOverflowException' occurred in Program.exe)And if I select "break", this line is selected:
object key(int count, accidental ac) (here is the cursor){
return key(0, accidental.none);
}
Does anyone know what is wrong?Sorry if this question is not specific enough, just tell me.
Well yes, look at this code (reformatted from your question for readability):
object key(int count, accidental ac)
{
return key(0, accidental.none);
}
That will just invoke the same method... which will invoke the same method... which will invoke the same method etc, until it runs out of stack space.
It's not clear what you intended to return from this method, but you need to stop recursing in this infinite way.
A stackoverflow means that you have some unbound recursion in your application. In English this essentially means you're calling a method again and again.
Can you see how you're calling your method key within itself?

Comparing to previous string gets me stuck in a loop

Ok, so I have a program that checks a twitch url for whenever someone new follows the channel by comparing a certain string is different from a "temp" string that I use for reference. But instead of only outputting a message every time the string is different it gets stuck in a loop of outputting the latest follower and then second latest follower then latest follower again etc.
What am I missing? Also, is there a better way of checking if a certain string is updated?
private void DonationListen()
{
try
{
followers = this.donationClient.DownloadString("https://api.twitch.tv/kraken/channels/" + channel.Trim() + "/follows");
donationTimer.Interval = 10000;
donationTimer.Elapsed += new ElapsedEventHandler(CheckUpdates);
donationTimer.Start();
}
catch (Exception e)
{
Console.WriteLine(e.ToString());
}
}
private void CheckUpdates(object source, ElapsedEventArgs e)
{
donationTimer.Stop();
int startIndex = followers.IndexOf("display_name\":") + 15;
int endIndex = followers.IndexOf(",\"logo", startIndex);
prevFollower = followers.Substring(startIndex, (endIndex - 1) - startIndex);
if (firstRun == true)
{
temp = prevFollower;
}
else if (prevFollower != temp)
{
//New follower detected
temp = prevFollower;
if (updateFollower != null)
{
updateFollower(prevFollower);
}
}
else
{
//Follower is the same as before
}
firstRun = false;
DonationListen();
}
I'm thinking it might have something to do with the downloadstring trying to get a new string from the url but failing since it's currently being updated and therefore the CheckUpdates doesn't have correct information or something?
Without a good code example, it is difficult to know for sure what the problem is. So we are left inspecting the code you did show us.
Based on that, it appears to me as though your "loop" is being caused by repeatedly subscribing to the same event.
In your DonationListen() method, you have this statement:
donationTimer.Elapsed += new ElapsedEventHandler(CheckUpdates);
In the CheckUpdates() method (i.e. the handler you are subscribing), you have this statement (as the very last statement):
DonationListen();
In other words, every time the timer's Elapsed event is raised, you add another event handler instance to the event. For every handler you add, the CheckUpdates() method will be called.
Again, without a good code example, it is difficult to know for sure what the best fix would be. But given the code that is here, it appears to me that you could just remove that last statement from the CheckUpdates() method, as the DonationListen() method does not appear to do anything that needs doing again.

Categories