What's wrong with my C# For Loop and If statement? - c#

int LetterCount = 0;
string strText = "Debugging";
string letter;
for (int i = 0; i <strText.Length; i++)
{
letter = strText.Substring(0, 9);
if(letter == "g")
{
LetterCount++;
textBox1.Text = "g appears " + LetterCount + " times";
}
}
So, I'm doing this tutorial thing, and I've been stuck on this exercise for like 4 hours. And I can't figure out what's wrong with my For Loop.
The point of the exercise is to make my program thing tell me how many g's are in the word debugging. But you probably figured that out. Anyway, I'm not even sure that I have the right code for telling me that, because I think that I need to change the second part of the For Loop (the i < ) part.
But my problem is that it isn't registering the "if letter == "g" " at all. Because according to my locals window it says that letter=Debugging, which would make me think that g should be registering on my program 24 times, I think (because str.length is 9 letters long?) But it's registering as 0 no matter what I do.

You are extracting a string of 9 characters. It will never be equal to "g" (which only has one). Here's how I'd do it.
int count = 0;
foreach (char c in strText)
{
if (c == 'g')
count++;
}
Using the for loop:
for (int i = 0; i < strText.Length; i++)
{
if (strText[i] == 'g')
count++;
}

Take a look at the documentation for string.Substring(x, y).
Basically:
letter = strText.Substring(0, 9);
Isn't giving you a letter. Each time through it's giving you all 9 characters of the string strText. You might want to consider using the variable i for one of the values you pass to Substring.
(I've deliberately not given you the entire answer as you seem to want to understand, so, if the pointers I've given don't get you there, let me know and I'll expand my answer =)

Try this:
for (int i = 0; i <strText.Length; i++)
{
if(strText[i] == 'g')
{
LetterCount++;
}
}
textBox1.Text = "g appears " + LetterCount + " times";
The issue is that you are looking at the entire string when you compare to "g". By specifying an index you are telling it to look at a specific character in the string. Also, I removed your substring because it did not appear to be doing anything.

You're not using i at all in your for loop.
Do you mean
letter = strText.Substring(i, 1);
?

Well, you are taking substring that is long 9 charachters and comparing it to "g". It won't be equal.
You should try:
letter = strText.Substring(i,1);

Because String.Substring(int, int) takes two arguments: the offset and amount to take.
In your case, letter = strText.Substring(0, 9); will simply assign letter's value to "Debugging". If you want to check each letter individually, you need to write letter = strText.Substring(i, 1).

You're probably looking for something like this:
int LetterCount = 0;
string strText = "Debugging";
string letter;
for (int i = 0; i <strText.Length; i++)
{
letter = strText.Substring(i, 1);
if(letter == "g")
{
LetterCount++;
textBox1.Text = "g appears " + LetterCount + " times";
}
}

letter = strText.Substring(0, 9);
at this point, 'letter' has the value "Debugging" since you're taking the entire string.
Try letter = strText[i] so you isolate the single letter.

What #Rob said.
Try something like this:
int gCount = 0;
string s = "Debugging";
for ( int i = 0; i <strText.Length; i++)
{
if ( s[i] == 'g' ) ++gCount ;
}
textBox1.Text = "g appears " + gCount+ " times";

namespace runtime
{
public partial class Form1 : Form
{
public Form1()
{
InitializeComponent();
}
private void button1_Click(object sender, EventArgs e)
{
int lettercount = 0;
string strText = "Debugging";
string letter;
for (int i = 0; i < strText.Length; i++)
{
letter = strText.Substring(i,1);
if (letter == "g")
{
lettercount++;
}
}
textBox1.Text = "g appear " + lettercount + " times";
}
}
}

Related

Why is this function crashing my program?

I'm new in programming and this is my first project and I'm using C#. Basically I tryed to do a function that insert one more single quote in string that already have a single quote, but this is crashing my program and I don't know why.
The function:
private string CheckSingleQuote(string txt)
{
for (int i = 0; i < txt.Length; i++)
if (txt[i] == '\'')
txt = txt.Insert(i, "'");
return txt;
}
When I click in a specific button, this function is called ten times to set the value of the strings.
You can do String.Replace("'", "''") or if you want to use the for:
private string CheckSingleQuote(string txt)
{
for (int i = 0; i < txt.Length; i++)
if (txt[i] == '\'')
txt = txt.Insert(i++, "'");
return txt;
}
As mjwills said in the comment the i++ is to skip the ' character that you just inserted.

Elements in array (when reproduced from a dictionary value) are reversed

My goal is to make a math expression interpreter with c#, for example if you type "A=3", it'll save the A as a dictionary key and 3 as its value, this program has more features so if you type "B=3" and then "A=B+3" and then "Show(A)", it must display "6" as the answer.
Everything is right until I type something like "A=10" "B=10" "C=A+B" and finally "Show(C)", because Variables' value are 2-digit (or more) numbers in this case, when producing the final result, numbers are saved in the string like "01+01" instead of "10+10" (because A and B values are 10 so A+B should be 10+10), so it's kinda reversed.
I tried to reverse the string and then evaluate the answer but that didn't work as well, simply it gives me "1+1" for some reason!
Notes:
expression evaluation is done by "return Convert.ToInt32(new DataTable().Compute(result, null));"
because strings are immutable in c#, when every expression like "A+B" or "3+5" comes in the method, I create a new empty string like (string result = " ";) and then with the help of "result = ValidExpression[i] + result.Remove(counter, 0);", I change the variables with values (note = if all the elements of input are numbers, answer is right) like "A" with "23" and put them in the new string and then evaluate the final string. But as I said, it saves the 23 as 32 so the answer will be wrong.
This is my code and the bug is probably in the LongProcessing method.
Thanks for your helps.
using System;
using System.Collections.Generic;
using System.Linq;
using System.Globalization;
using System.Data;
namespace ConsoleApp2
{
class Program
{
static void Main(string[] args)
{
Console.WriteLine("Welcome To The Program\nCorrect Syntax:");
Console.WriteLine("A=10\nB=15\nC=A+B\nD=13/4-2+A-C+B\nShow(D)");
Console.WriteLine("\nEnter your input:");
Expression E = new Expression();
string expression = "start";
while (expression != "exit")
{
expression = Console.ReadLine();
// for show command
if (expression.Contains("Show") == true)
try { E.Show(expression[5]); }
catch (Exception e)
{
Console.WriteLine("input is not correct, Can not show anything. please try again");
}
if (E.Validation(expression) == false)
Console.WriteLine("input is not correct, please try again");
else
E.Processing(expression);
}
Console.ReadKey();
}
}
class Expression
{
public Dictionary<Char, String> Variables = new Dictionary<Char, String>();
public Expression()
{ }
public Boolean Validation(string expression)
{
// true if c is a letter or a decimal digit; otherwise, false && true if c is a decimal digit; otherwise, false.
if (!Char.IsLetterOrDigit(expression[0]) || Char.IsDigit(expression[0]))
return false;
else
return true;
}
public void Processing(String ValidExpression)
{
// Update Dictionary with new values per key
if (Variables.ContainsKey(ValidExpression[0]))
Variables.Remove(ValidExpression[0]);
string temp = " ";
if (ValidExpression.Length > 2 && !ValidExpression.Contains("Show") && !ValidExpression.Contains("exit"))
{
// removing the variable name and "=" from the string
for (int i = 2; i < ValidExpression.Length; i++)
temp = ValidExpression[i] + temp.Remove(i, 0);
Variables.Add(ValidExpression[0], LongProcessing(temp).ToString());
}
}
// something is wrong in this method
public int LongProcessing(String ValidExpression)
{
string temp;
int counter = 0;
string result = " ";
for (int i = 0; i < ValidExpression.Length; i++)
{
//changing variables (letters) with values
if (Char.IsLetter(ValidExpression[i]))
{
if (Variables.ContainsKey(ValidExpression[i]))
{
Variables.TryGetValue(ValidExpression[i], out temp);
for (int j = 0; j < temp.Length; j++)
{
result = temp[j] + result.Remove(counter, 0);
counter++;
}
}
}
else
{
result = ValidExpression[i] + result.Remove(counter, 0);
counter++;
}
}
// checks if all of the string elements are numbers
if (ValidExpression.All(char.IsDigit))
return Convert.ToInt32(ValidExpression);
else
{
return Convert.ToInt32(new DataTable().Compute(result, null));
}
}
public void Show(Char ValidExpression)
{
Console.WriteLine(Variables[ValidExpression]);
}
}
}
This is broken:
for (int i = 2; i < ValidExpression.Length; i++)
temp = ValidExpression[i] + temp.Remove(i, 0);
temp.Remove(i, 0) is a non op, you might as well just write temp
So let's plot the loop:
Assume ValidExpression is "A=10"
Temp starts out as " "
First iteration, temp is "1 "
Second iteration, temp is "01 "
Any operation that works left to right through a string, character by character, pulling a character out and sticking it on the start of a growing string, will reverse the string
Perhaps you meant to not have a loop and instead do temp = ValidExpression.Substring(2) ?
Here are some suggestions:
Start by looking at the value of "temp" in "Processing". To assist in your debugging, add a "Console.WriteLine" statement.
public void Processing(String ValidExpression)
{
// Update Dictionary with new values per key
if (Variables.ContainsKey(ValidExpression[0]))
Variables.Remove(ValidExpression[0]);
string temp = " ";
if (ValidExpression.Length > 2 && !ValidExpression.Contains("Show") && !ValidExpression.Contains("exit"))
{
// removing the variable name and "=" from the string
for (int i = 2; i < ValidExpression.Length; i++)
{
temp = ValidExpression[i] + temp.Remove(i, 0);
Console.WriteLine(" temp: " + temp); //added for debugging
}
Variables.Add(ValidExpression[0], LongProcessing(temp).ToString());
}
}
A couple of other things:
The user is never informed how to exit.
There is a class named "Expression" and a string variable named
"expression". This is likely to cause confusion.
You may also want to look at this post: how to convert a string to a mathematical expression programmatically

C#: Increment only the last number of a String

I have strings that look like this:
1.23.4.34
12.4.67
127.3.2.21.3
1.1.1.9
This is supposed to be a collection of numbers, separated by '.' symbols, similar to an ip address. I need to increment only the last digit/digits.
Expected Output:
1.23.4.35
12.4.68
127.3.2.21.4
1.1.1.10
Basically, increment whatever the number that is after the last '.' symbol.
I tried this:
char last = numberString[numberString.Length - 1];
int number = Convert.ToInt32(last);
number = number + 1;
If I go with the above code, I just need to replace the characters after the last '.' symbol with the new number. How do I get this done, good folks? :)
It seems to me that one method would be to:
split the string on . to get an array of components.
turn the final component into an integer.
increment that integer.
turn it back into a string.
recombine the components with . characters.
See, for example, the following program:
using System;
namespace ConsoleApplication1 {
class Program {
static void Main(string[] args) {
String original = "1.23.4.34";
String[] components = original.Split('.');
int value = Int32.Parse(components[components.Length - 1]) + 1;
components[components.Length - 1] = value.ToString();
String newstring = String.Join(".",components);
Console.WriteLine(newstring);
}
}
}
which outputs the "next highest" value of:
1.23.4.35
You can use string.LastIndexOf().
string input = "127.3.2.21.4";
int lastIndex = input.LastIndexOf('.');
string lastNumber = input.Substring(lastIndex + 1);
string increment = (int.Parse(lastNumber) + 1).ToString();
string result = string.Concat(input.Substring(0, lastIndex + 1), increment);
You need to extract more than just the last character. What if the last character is a 9 and then you add 1 to it? Then you need to correctly add one to the preceding character as well. For example, the string 5.29 should be processed to become 5.30 and not simply 5.210 or 5.20.
So I suggest you split the string into its number sections. Parse the last section into an integer. Increment it and then create the string again. I leave it as an exercise for the poster to actually write the few lines of code. Good practice!
Something like this:
var ip = "1.23.4.34";
var last = int.Parse(ip.Split(".".ToCharArray(),
StringSplitOptions.RemoveEmptyEntries).Last());
last = last + 1;
ip = string.Format("{0}.{1}",ip.Remove(ip.LastIndexOf(".")) , last);
If you are dealing with IP, there will be some extra code in case of .034, which should be 035 instead of 35. But that logic is not that complicated.
It's simple as this, use Split() and Join() String methods
String test = "1.23.4.34"; // test string
String[] splits = test.Split('.'); // split by .
splits[splits.Length - 1] = (int.Parse(splits[splits.Length - 1])+1).ToString(); // Increment last integer (Note : Assume all are integers)
String answ = String.Join(".",splits); // Use string join to make the string from string array. uses . separator
Console.WriteLine(answ); // Answer : 1.23.4.35
Using a bit of Linq
int[] int_arr = numberString.Split('.').Select(num => Convert.ToInt32(num)).ToArray();
int_arr[int_arr.Length - 1]++;
numberString = "";
for(int i = 0; i < int_arr.Length; i++) {
if( i == int_arr.Length - 1) {
numberString += int_arr[i].ToString();
}
else {
numberString += (int_arr[i].ToString() + ".");
}
}
Note: on phone so can't test.
My Solution is:
private static string calcNextCode(string value, int index)
{
if (value is null) return "1";
if (value.Length == index + 1) return value + "1";
int lastNum;
int myIndex = value.Length - ++index;
char myValue = value[myIndex];
if (int.TryParse(myValue.ToString(), NumberStyles.Integer, null, out lastNum))
{
var aStringBuilder = new StringBuilder(value);
if (lastNum == 9)
{
lastNum = 0;
aStringBuilder.Remove(myIndex, 1);
aStringBuilder.Insert(myIndex, lastNum);
return calcNextCode(aStringBuilder.ToString(), index++);
}
else
{
lastNum++;
}
aStringBuilder.Remove(myIndex, 1);
aStringBuilder.Insert(myIndex, lastNum);
return aStringBuilder.ToString();
}
return calcNextCode(value, index++);
}

Remove string from a char array

I am making a hangman in C# by my own and so far i am doing good. The game works but the letters organize depending on the users input and i want to erase the " _ " from the character everytime the word is found and is on the text.
This is how it looks on the game :
As you can see , the "_" only disapears for the first letter but not for the others and if the users put the correct answer correctly but radomly some words stick together in many cases and do not stay on their places. This my code for the game:
string word;
char letter_inserted;
int correctanswer, incorrectanswer;
int counter = 0;
correctanswer = 5;
Console.WriteLine("welcome to the game of hangman");
Console.Write("First player please introduce the secret word: ");
word = Console.ReadLine();
Char[] sentenceChar = word.ToCharArray();
Console.WriteLine("Second player you can already play.");
foreach( char letter in senteceChar)
{
Console.Write(" _ ");
}
Console.WriteLine("\n");
Console.WriteLine("{0} correcct answers are allowed. \n",correctanswers); //lives
Char[] correctletter = new Char[5];
for (int i = 1; i > 0; i++)
{
Console.Write("\n\nWhat letter you want to play : ");
letter_inserted = Convert.ToChar(Console.ReadLine());
for (int j = 0; j < sentenceChar.Length; j++)
{
if (sentenceChar[j] != letter_inserted)
{
incorrectanswer = correctanswer - 1; //lives
Console.Write(correctletter[j] + " _ ");
}
if (sentenceChar[j] == letter_inserted)
{
correctletter[j] += sentnceChar[j]; //inserting the correct word
Console.Write(correctletter[j]);
}
}
}
Console.ReadKey();
}
I would use a different approach for this. Create two arrays, one for the solution:
var solution = new char[] {'H', 'A', 'N', 'G', 'M', 'A', 'N'};
And one for the current hint. At the beginning, you'd initialize this to:
var hint = new char[] {'_', '_', '_', '_', '_', '_', '_'};
When a letter is guessed, you can loop through solution and each time solution[i] is equal to the guessed letter, replace the corrosponding index in hint:
for(int i = 0; i < solution.Length; i++)
{
if(solution[i] == guess)
hint[i] = guess;
}
At the end of this loop, just re-write hint onto the screen, which will always contain the current hint.
A few things you'll want to do:
Have a Boolean within your loop to track if solution contained any instances of the letter. If not, at the end of the loop you'd subtract a life. You can also do this very easily using solution.Contains(guess) as well.
Perhaps create a List<char> to track already attempted guesses. If this list already contains the entered letter, you can display "You already guessed that!", otherwise add the guess to the list.
This answer is meant as a hint to get you going in the right direction, rather than a complete solution. However, feel free to ask if any part of it is unclear.
I will start with your first sentence - I am making a hangman in C# by my own and so far i am doing good. In fact as you can see in the comments there are a lot of things that you would want to consider before going to this exact problem but since you ask how to deal with the extra _ I'll jump to that.
And a method :
public static void printWord(char[] correctletters)
{
for (int j = 0; j < correctletters.Length; j++)
{
Console.Write(correctletters[j]);
}
}
And then rewrite your code like this:
namespace Hangman
{
class Program
{
static void Main(string[] args)
{
string word;
char letter_inserterd;
int correctanswer = 5;
int counter = 0;
Console.WriteLine("welcome to the game of hangman");
Console.Write("First player enter the secret word: ");
word = Console.ReadLine();
Char[] sentenceChar = word.ToCharArray();
Console.WriteLine("Second player you can already play.");
foreach( char letter in sentenceChar)
{
Console.Write(" _ ");
}
Console.WriteLine("\n");
Console.WriteLine("{0} correct answers are allowed. \n",correctanswer); //lives
Char[] correctletter = new Char[sentenceChar.Length];
for (int i = 0; i <sentenceChar.Length; i++)
{
correctletter[i] = '_';
}
while (correctanswer > 0)
{
Console.Write("\n\nWhat letter you want to play : ");
letter_inserted = Convert.ToChar(Console.ReadLine());
bool ContainsWord = false;
for (int j = 0; j < sentenceChar.Length; j++)
{
if (sentnceChar[j] == letter_inserted)
{
correctletter[j] = letter_inserted; //inserting the correct word
ContainsWord = true;
}
}
if (!ContainsWord)
{
correctanswer -= 1;
}
printWord(correctletter);
}
Console.ReadKey();
}
public static void printWord(char[] correctletter)
{
for (int j = 0; j < correctletter.Length; j++)
{
Console.Write(correctletter[j]);
}
}
}
}
P.S if you want to make it a little more clear in printWord method change the Console.Write line like this: Console.Write(letracorrecta[j] + " ");

Send Keys special characters (){}+^ c#

Okay so I'm making an auto typer and I want the user to be able to enter the keys {}()^+ and have the application out put. I know that you need to format the symbols like SendKeys.Send({^}); but I cant get this to work. Heres what I have so far for my Timer Tick. Also, I have global int blockCount, which tells the program to move on to the next character in the blockText string.
It returns "Group delimiters are not balanced."
private void timer3_Tick(object sender, EventArgs e)
{
string blockText = richTextBox1.Text;
int blockLength = richTextBox1.TextLength;
btrand = RandomNumber(75, 200); //I have a method to make a rand num
timer3.Interval = btrand;
char[] specialChars = { '{', '}', '(', ')', '+','^' };
foreach (char letter in blockText)
{
for (int i = 0; i < specialChars.Length; i++)
{
if (letter == specialChars[i])
{
SendKeys.Send("{" + specialChars[i] + "}");
blockText.Remove(blockText.IndexOf(specialChars[i].ToString()));
}
else
{
SendKeys.Send(letter.ToString());
}
}
}
blockCount++;
if (blockCount >= blockLength)
{
blockCount = 0;
}
}
Ok, quick analysis, so forgive me if I miss something.
You're doing a foreach using blockText as your collection, and manipulating it if a special char is found. This can be messy; I would think on another way to implement this.
You're looping through all special chars, and for each interaction that you can't identify a match you're sending the current letter. That means you're re-sending all non-special characters for the number of elements in the specialChars array minus one. I don't think that's what you've intended to do.
I would suggest an implementation like this:
foreach (char letter in blockText)
{
bool _specialCharFound = false;
for (int i = 0; i < specialChars.Length; i++)
{
if (letter == specialChars[i])
{
_specialCharFound = true;
break;
}
}
if (_specialCharFound)
SendKeys.Send("{" + letter.ToString() + "}");
else
SendKeys.Send(letter.ToString());
}
There are more optimized ways to implement, but I would choose this one out of clarity of purpose and similarity to your original code.

Categories

Resources