I am trying to create a program by the name of "Count Vowels" that accepts a phrase from a user and outputs the number of vowels within that phrase.
I used a while statement with a nested if statement that runs through all the vowels, and counts the vowels, so that it can be displayed. When ever I run the program it is not going through my while statement and checking the vowels as intended. Instead it just keeps adding one to my count variable after each iteration.
I am new to C# and tried to understand the issue logically, but am having trouble trying to get my program to execute. If someone could please help me understand what I'm doing wrong I would greatly appreciate it. Below is the code that I am using.
using System;
using static System.Console;
class CountVowels
{
static void Main()
{
string phrase;
int count=0;
int i=0;
Console.WriteLine("please enter a phrase of your choice");
phrase=Console.ReadLine();
while(i < phrase.Length)
{
if(phrase[i]=='a' ||
phrase[i]=='A' ||
phrase[i]=='e' ||
phrase[i]=='E' ||
phrase[i]=='i' ||
phrase[i]=='I' ||
phrase[i]=='o' ||
phrase[i]=='O' ||
phrase[i]=='u' ||
phrase[i]=='U')
{
count++;
}
{
i++;
}
Console.WriteLine("The number of vowels in your phrase is {0}",count);
Console.ReadLine();
}
}
}
A while loop is overkill for this but I am assuming you have a requirement for this? How about a little refactor to clean it up? You will need LINQ for this example.
using System.Linq;
string phrase;
int count=0;
int i=0;
Console.WriteLine("please enter a phrase of your choice");
phrase=Console.ReadLine();
while(i < phrase.Length)
{
string[] vowels = {"a", "e", "i", "o", "u"};
var characterValue = phrase[i].ToString().ToLower();
if(vowels.Contains(characterValue))
{
count++;
}
i++;
}
Console.WriteLine("The number of vowels in your phrase is {0}",count);
Console.ReadLine();
Or mush shorter still using LINQ but no loop:
using System.Linq;
Console.WriteLine("please enter a phrase of your choice");
var phrase=Console.ReadLine();
var count = phrase.Count(x => "aeiou".Contains(char.ToLower(x)));
Console.WriteLine("The number of vowels in your phrase is {0}",count);
Console.ReadLine();
Fixing your problem
var phrase = "asd";
var vowels = "aeiou";
int i = 0, count = 0;
while (i < phrase.Length)
{
if (vowels.Contains(char.ToLower(phrase[i])))
count++;
i++;
}
for loop
for (int i = 0; i < phrase.Length; i++)
if (vowels.Contains(char.ToLower(phrase[i])))
count++;
foreach
foreach (var c in phrase)
if (vowels.Contains(char.ToLower(c)))
count++;
foreach C#9 pattern matching
foreach (var c in phrase.ToLower())
if (c is 'a' or 'e' or 'o' or 'u')
count++;
Linq 1
count = phrase.Count(c => vowels.Contains(char.ToLower(c)));
Linq 2
count = phrase.ToLower().Count(c => vowels.Contains(c));
Regex
var count = Regex.Matches(phrase, "[aeiou]",RegexOptions.IgnoreCase).Count;
Efficient with a hashset
var hash = new HashSet<char>("aeiou".ToCharArray());
var count = phrase.ToLower().Count(x => hash.Contains(x));
Note this is not really an answer, it was more showing option.
Related
I do not understand why this code prints the contents of the array twice.
static void Main(string[] args)
{
Int64 userlength;
Int64 userlengthcounter;
String unencrypted;
char current;
start:
Console.WriteLine("Please enter how many characters the string you want encrypyted to be:");
userlength = Convert.ToInt64(Console.ReadLine());
Console.WriteLine("Please enter the string you want to be encrypted:");
unencrypted = Console.ReadLine();
int[] first = new int[userlength];
int[] second = new int[userlength];
if (userlength != unencrypted.Length)
{
Console.WriteLine("The string you entered was not the same length as the number of characters you specified");
goto start;
}
for (int i = 0; i < userlength; i++)
{
Console.WriteLine(unencrypted[i]);
current = unencrypted[i];
first[i] = current;
}
foreach (char item in first)
{
Console.WriteLine(item.ToString());
}
Console.ReadLine();
}
For example entering abcd would return abcdabcd and i don't understand why. Any help would be appreciated thanks.
It's because you have two loops, first you print each character in unencrypted in the for loop and store the chars in first array.
Then you loop over the array and print the chars again with foreach.
Additional Note: Using goto is almost always a bad idea because it makes your code hard to follow and unreadable. Because you have to manually track where the code jumps.
You can do the same thing with a do-while loop instead.
do {
Console.WriteLine("Please enter how many characters the string you want encrypyted to be:");
userlength = Convert.ToInt64(Console.ReadLine());
Console.WriteLine("Please enter the string you want to be encrypted:");
unencrypted = Console.ReadLine();
int[] first = new int[userlength];
int[] second = new int[userlength];
if (userlength != unencrypted.Length)
{
Console.WriteLine("The string you entered was not the same length as the number of characters you specified");
}
} while(userlength != unencrypted.Length);
you specifically build "first" then you print it in foreach, basically displaying the same content twice:
for (int i = 0; i < userlength; i++)
{
Console.WriteLine(unencrypted[i]);
current = unencrypted[i];
first[i] = current;
}
foreach (char item in first)
{
Console.WriteLine(item.ToString());
}
I need some help with a C# program that i am creating. So in this scenario i am inputting duplicate values into the program. For Example, a,b,b,c,c.
The exercise is that if there are any duplicated letters inputted (no numbers) i should get an error stating "Duplicate Value. Please Try Again!" and will not accept the duplicate value, and should show the values as a,b,c,d,e.
class Program
{
static void Main(string[] args)
{
char[] arr = new char[5];
//User input
Console.WriteLine("Please Enter 5 Letters only: ");
for (int i = 0; i < arr.Length; i++)
{
arr[i] = Convert.ToChar(Console.ReadLine());
}
//display
for(int i = 0; i<arr.Length; i++)
{
Console.WriteLine("You have entered the following inputs: ");
Console.WriteLine(arrArray[i]);
}
}
}
Choose right data structure at beginning, use HashSet instead of array since the operations are mainly looking up & inserting.
Using a hashtable (Generic Dictionary) is an efficient way to determine if an entered character has already been encountered.
Also, the Char.IsLetter method in the .NET framework is a great way to check for bad data.
static void Main(string[] args) {
Dictionary<char, bool> charsEntered = new Dictionary<char, bool>();
Console.WriteLine("Please enter 5 characters, each on a separate line.");
while (charsEntered.Count() < 5) {
Console.WriteLine("Enter a character:");
char[] resultChars = Console.ReadLine().ToCharArray();
if(resultChars.Length != 1 || !Char.IsLetter(resultChars[0])) {
Console.WriteLine("Bad Entry. Try again.");
} else {
char charEntered = resultChars[0];
if (charsEntered.ContainsKey(charEntered))
Console.WriteLine("Character already encountered. Try again.");
else
charsEntered[charEntered] = true;
}
}
Console.WriteLine("The following inputs were entered:");
Console.WriteLine(String.Join(", ", charsEntered.Keys));
Console.ReadLine();
}
Use Any linq expression to validate duplicates. char.TryParse will validates input and returns true when succeeded.
public static void Main()
{
char[] arr = new char[5];
//User input
Console.WriteLine("Please Enter 5 Letters only: ");
for (int i = 0; i < arr.Length; i++)
{
char input;
if(char.TryParse(Console.ReadLine(), out input) && !arr.Any(c=>c == input))
{
arr[i] = input;
}
else
{
Console.WriteLine( "Error : Either invalid input or a duplicate entry.");
i--;
}
}
Console.WriteLine("You have entered the following inputs: ");
//display
for(int i = 0; i<arr.Length; i++)
{
Console.WriteLine(arr[i]);
}
}
Working Code
Elaborating on Shelvin's answer of using HashSet
HashSet<char> chars = new HashSet<char>();
//User input
Console.WriteLine("Please Enter 5 Letters only: ");
for (int i = 0; i < 5; )
{
char c = Convert.ToChar(Console.ReadLine());
if(!("abcdefghijklmnopqrstuvwxyz".Contains(c.ToString().ToLower())))
{
Console.WriteLine("Please enter an alphabet");
continue;
}
else if (!chars.Contains(c))
{
chars.Add(c);
i++;
}
else
{
Console.WriteLine("Duplicate value please try again");
continue;
}
}
//display
Console.WriteLine("You have entered the following inputs: ");
foreach(char c in chars)
Console.WriteLine(c.ToString());
Console.Read();
Keep it simple, and although a HashSet is nice semantically, it's not needed for 5 elements (it's actually slower than a List in that case). Worse, it requires a parallel structure to track the characters (assuming you care about order).
Clearly none of these considerations matter for such a small example but it's good to learn them up front and don't always jump to big-O notation when actually measured performance and memory consumption should be your guide for most practical applications.
Instead you can simply do:-
List<char> chars = new List<char>(5);
while (chars.Count < 5)
{
char c = Console.ReadKey().KeyChar;
if (!char.IsLetter(c)) continue;
if (chars.Contains(char)) continue;
chars.Add(char);
}
Plus whatever error messages you want to add.
I wanted to count all of the "A's" in a paritcular string.
using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using System.Threading.Tasks;
using System.IO;
namespace TESTING
{
class Testing
{
static void Main(string[] args)
{
//ask user for the filename
string userInput = fetchFileName("Enter the textfile you want to view: ");
//test if the filename writes anything to console
string fileContents = File.ReadAllText(userInput);
string theFileContents = analyseFile(fileContents);
// Console.WriteLine(theFileContents);
Console.ReadLine();
}
private static string analyseFile(string fileContents)
{
string str = fileContents;
if (str.Contains("A"))
{
Console.WriteLine("YES");
}
else
{
Console.WriteLine("NO");
}
return str;
}
private static string fetchFileName(string askFileName)
{
Console.WriteLine(askFileName);
string userAnswer = Console.ReadLine();
return userAnswer;
}
}
}
Take a look at LINQ. It allows to perform whole range of operations on any kind of collection. And a string is a collection of chars. Below an example how LINQ can make your life easier:
string text = "A sdfsf a A sdfsf AAS sdfA";
int res = text.Count(letter => letter == 'A');
What happens here is that you take text and provide a predicat saying that you want to take any variable letter from the string such that the letter is equal to char A. Then you want to count them.
One of the easiest ways is to iterate over all characters in your file and check if the letter is equal to the letter you want.
When you realize that a string is nothing more then an array of characters, you can do something like this:
public int LetterCount(string filename, char letter)
{
int cnt = 0;
string source = File.ReadAllText(filename);
//Check every character in your string; if it matches increase the counter by 1
foreach (char c in source)
{
if(c == letter)
{
cnt++;
}
}
return cnt;
}
And use it like this:
int A_count = LetterCount(#"C:\test.txt", 'A');
Please note, that this code does not check, if the file actually exists. If you put in a wrong path, you end up with a FileNotFoundException.
Foreach is just another type of loop. This could just as easily be done with a for-loop. The trick is to split the string up in individual characters that you can later compare.
I'm sure you will figure out how to implement this if I just set you on the right path:
string test = "My name is Isak";
char[] arrayOfChars = test.ToCharArray();
int count = 0;
for (int i = 0; i < arrayOfChars.Length; i++)
{
if (arrayOfChars[i] == 'a' || arrayOfChars[i] == 'A')
{
count++;
}
}
try simple as
string test = "ABBCDABNDEAA";
int Count = test.Count(x => x == 'A');
Using LINQ, this can by really simple:
string myString = "ababsgsdfsaaaAA22bbaa";
var count = myString.ToLower().Count(c => c == 'a');
Console.Write(count);
Here we take the string and convert it to all lower case so that A and a will be counted together. Then we use the simple LINQ method Count() to count the number of a characters there are.
You could use linq
string text = "The quick brown fox jumps over the lazy dog";
var count = text.ToLower().Where(x => x == 'a').Count();
Console.WriteLine(count);
But if you cannot use any advanced techniques you could do it like this:
string text = "The quick brown fox jumps over the lazy dog";
int counter = 0;
for (int i = 0; i < text.Count(); i++)
{
if (text[i] == 'a' || text[i] == 'A')
{
counter++;
}
}
Console.WriteLine(counter);
You can do this:
string stringValue = "Addsadsd AAf,,werAA";
int qtdChar = stringValue.Count(x => x == 'A');
int qtdCharInsensitive = stringValue.Count(x => x == 'A' || x=='a');
If you do not want to use a foreach you could erase all the letter A's and compare the length difference.
A bit like this :
private static string analyseFile(string fileContents)
{
var strippedString = fileContents.Replace("A","");
var count = fileContents.Length - strippedString.Length;
return count.ToString();
}
Hej, does anyone know how i can make my method for guessing letters remember
the guesses before? Currently it turns all the "right" guesses into the last right letter guessed :(
public void myGuess(char letter)
{
string wordToGuess = label4.Text;
string wordToShow = label5.Text;
for (int i = 0; i < wordToGuess.Length; i++)
{
if (wordToGuess[i] == letter || wordToGuess[i] == wordToShow[i])
wordToShow = wordToShow.Remove(i, 1).Insert(i, Char.ToString(letter));
}
label5.Text = wordToShow;
if (wordToGuess == wordToShow)
this.Close();
Form Win = new Win();
Win.Show();
}
Have a global list of char and add to it after every guess
List<char> guesses = new List<char>();
Then in your method just add to it
guesses.Add(letter);
and then you can check using this
if (guesses.Contains(letter))
{
//DoSomething
}
The problem is with your loop.
Your test checks if the character equals either the guessed letter or the letter at the same position in the already guessed words.
If the test succeeds you then effectively replace the value with the guessed letter.
You need to either remove the second part of the test:
if (wordToGuess[i] == letter)
wordToShow = wordToShow.Remove(i, 1).Insert(i, Char.ToString(letter));
or change the replacement
if (wordToGuess[i] == letter || wordToGuess[i] == wordToShow[i])
wordToShow = wordToShow.Remove(i, 1).Insert(i, Char.ToString(wordToShow[i]));
Also instead of removing/inserting if you change the wordToShow to a char array first you can then just directly change it's value and convert back to a string when finished, this makes the code a little easier to read. It may also be better performance than all the insert/removes.
var newWord = wordToShow.ToCharArray();
for (var i = 0; i<wordToGuess.Length; i++) {
if (wordToGuess[i] == letter) {
newWord[i] = letter;
}
}
wordToGuess = new string(newWord);
I'm trying to figure out how to display the repeated letter in a string. For example if the entered string was "red house" it would show that the letter "e" was repeated, then it would be displayed in the label I created. This is a basic program, Here is what I've written thus far. Any help is appreciated.
private void button1_Click(object sender, EventArgs e)
{
string enteredWord = textBox1.Text;
char letter;
for (int index = 0; index < enteredWord.Length; index++)
{
letter = enteredWord[index];
if (letter == enteredWord[index])
{
label1.Text = (letter.ToString());
}
else
{ return;
}
You could also use Linq for that:
var query = from l in enteredWord
group l by l into g
where g.Count() > 1
select new { letter = g.Key, count = g.Count() };
foreach (var item in query)
{
label1.Text += item.letter + " ";
}
This should do what you're looking for:
public static Dictionary<char, int> Count(string input)
{
Dictionary<char, int> d = new Dictionary<char, int>();
foreach (char c in input)
{
if (d.Keys.Contains(c))
d[c]++;
else
d.Add(c, 1);
}
return d;
}
static void Main(string[] args)
{
Dictionary<char, int> d = Count("Red House");
foreach (char c in d.Keys)
{
Console.WriteLine("{0}: {1}", c, d[c]);
}
Console.ReadKey();
}
Could build a HashSet and check each letter. I'm sure there's a more efficient way, but this should work: (untested)
string enteredWord = textBox1.Text;
HashSet<char> letters = new HashSet<char>();
foreach(char c in enteredWord)
{
if (letters.Contains(c))
label1.Text += c.ToString();
else
letters.Add(c);
}
EDIT: I suppose this will print out duplicates of the letters if they appear 3 or more times, but you get the idea.
I would suggest using a List and add the value if you have not encountered it, and update the textbox if you have already encountered it. For a future FYI, you could use a Dictionary if you need to know the exact counts, also.
List<char> charactersThatHaveOccurred = new List<char>();
string enteredWord = textBox1.Text;
foreach(var character in enteredWord)
{
if(charactersThatHaveOccurred.Contains(character ))
label1.Text += character ;
else
charactersThatHaveOccurred.Add(character );
}
The first thing that comes to mind is:
List<char> repeats = enteredWord.Where(c1 => enteredWord.Count(c2 => c1 == c2) > 1).Distinct().ToList();
That will return a List<char> of all the repeated characters. You can grab the first one, or whatever you want.
It may not be optimal in terms of speed, but it's simple.
See other answers for better ways to solve this problem, but I'm trying to see what you were trying to do. (Note, the code below is very inefficient, using a HashSet of already seen characters would be my solution at it.)
Perhaps you're missing an inner for loop? Currently you assign something (enteredword[index]) to letter, and then immediately compare them. So you're comparing each letter to itself.
something like
for (int index = 0; index < enteredWord.Length; index++)
{
letter = enteredWord[index];
for (int index2 = 0; index < enteredWord.Length; index++)
{
if (index != index2 && letter == enteredWord[index2])
{
label1.Text = (letter.ToString());
return;
}
}
}
string s = "red house";
foreach (char c in s)
{
if (s.IndexOf(c) != s.LastIndexOf(c))
{
label1.Text += c.ToString();
}
s.Replace(c.ToString(), string.Empty);
}