I need to make a windows form application in c# that provides the user with a textbox, and upon clicking a button it changes the letters in the first textbox to a replacement in the other one.
For example:
if I type "apple" in the first textbox and I have replaced "a" with "b" and "p" with "o" it should spell "baoole".
This process also has to work in reverse. I don't know how to accomplish this.
I tried using .Replace with every pair of letters in the alphabet ex: "a","b"; "c","d";, But it only replaced the first letters so if I typed "c" it would not change to "d". Once I tried to then replace "d","c"; it overlapped and my program wouldn't work. I then tried this:
if (richTextBox1.Text.Contains("a"))
{
richTextBox2.Text=richTextBox1.Text.Replace("a", "b");
}
if (richTextBox1.Text.Contains("b"))
{
richTextBox2.Text=richTextBox1.Text.Replace("b", "a");
}
But it only successfully replaced the first character. I am sorry if I missed anything obvious, I am learning c# and am eager to learn more. Thank you for your time and knowledge.
string x = richTextBox1.Text;
string result = "";
for (int i = 0; i < x.Length; i++)
{
char c = x[i];
if (c % 2 == 0)
{
c--;
}
else
{
c++;
}
result += c;
}
richTextBox2.Text=result;
If the text is "bad" this code will replace it with "abc" and will do the same in the reverse case, I think this is what you are looking for .
Every string is a character array.
So you need to make a loop over that character array (ie., string) and replace each and every character.
string richTextBoxString = richTextBox1.Text;
foreach(char ch in richTextBoxString )
{
if(ch=='a')
Convert.ToString(ch).Replace("a", "b");
//likewise for all characters you need to code
}
richTextBox1.Text=richTextBoxString ;
Any clarification please ask.
It appears you're just trying to make each character be the next character in the alphabet. If that is the case.. I would use a StringBuilder and iterate over each character. Something like this:
private string Encrypt(string text)
{
var content = new StringBuilder(text);
for (int i = 0; i < content.Length; i++) {
if (content[i] == 'z') {
content[i] = 'a';
continue;
}
if (content[i] == 'Z') {
content[i] = 'A';
continue;
}
content[i]++;
}
return content.ToString();
}
Basically, you can iterate over every character in the string and add 1 to it. If you encounter a Z or z.. then just round it out to A or a respectively and move on.
"Decryption" is the reverse of that:
private string Decrypt(string text) {
var content = new StringBuilder(text);
for (int i = 0; i < content.Length; i++) {
if (content[i] == 'a') {
content[i] = 'z';
continue;
}
if (content[i] == 'A') {
content[i] = 'Z';
continue;
}
content[i]--;
}
return content.ToString();
}
That is, if you encounter an A or a, change it to Z or z respectively. Using the above, you can call it like this:
richTextBox2.Text = Encrypt(richTextBox1.Text); // Encrypt it
richTextBox2.Text = Decrypt(richTextBox2.Text); // Decrypt it
Click here to see a live sample of it running
If I understand well what you would like to do:
You have "abba", and would like to do the following replacements { 'a' -> 'b', 'b' -> 'c' }.
If you would use consecutive replaces this would give "cccc", but you would like to get "bccb".
If this is the case, i do not know any out of the box solition in the .net library, but you should write your own class to do this.
I'd do it the following way:
The class gets a string (in the constructur), and splits it to a character array.
The class has a method to add transliteration pairs to its lisf of these steps.
The class has a method to do the transliteration.
This method creates a bitmap, to track which character has been replaced.
It scans the array and saves each transliteraated chracter to a target array.
It flags that position as 'done'.
When doing transliterations it skips the 'done' fields.
finally it fills the non-transliterated fields, and returns a string constructed from the result character array.
This architecture lets you make the translitation easily reversible.
As you stated you are learning C# (and I guess programming as well), thus I only wrote this guide to a possible implementation.
Try it:
var replacements = new Dictionary<char, string>();
replacements.Add('a', "b");
replacements.Add('b', "a");
var inputString = "abc";
var etalonString = "bac";
var resSB= new StringBuilder();
foreach(var letter in inputString)
{
if(replacements.ContainsKey(letter))
resSB.Append(replacements[letter]);
else
resSB.Append(letter);
}
var resString = resSB.ToString();
Related
Closed. This question needs to be more focused. It is not currently accepting answers.
Want to improve this question? Update the question so it focuses on one problem only by editing this post.
Closed 2 years ago.
Improve this question
It's a little confusing but if you look at the example below you get it!
I have a special "Console.Write" method that takes a string, for example "§cHello %mThere!" and when printing to the Console, this method ignores the §c and %m (it changes the color of the Console).
Now, I have another method to print text by aligning it, by breaking the string into an array of strings every nth char. That means, if I pass a string of 100 chars and a LineLength of 10, it will break my string into an array of 10 strings with 10 chars each, then my Write method will print each one in a new line.
The problem is, when I split the text every nth char, it count the '§' and 'c' chars, and when I print it (the method for printing will remove those two), so the output is off by two chars.
So... I need a method that:
Splits a string into an array of strings every nth character.
However, it must not count '§' and the following char, or '%' and the next char as characters in that math.
The output must have those extra chars in the string array.
Example:
string Text = "§cOnce upon a time there was a §R%mnice girl named Cinderella. She was very poor and her father passed way."
int LineLength = 6;
return string[] Output = {
"§conce u" //[o n c e space u], thats 6 chars ignoring the first two.
"pon a " //[p o n space a space], thats 6 chars.
"time t" // etc
//etc
}
If someone help me write this, thanks in advance!!!
If I understand what you're saying this seems about right.
public static string[] ConsoleChunk(string input, int length){
List<string> Output = new List<string>();
int k = 0;
string currentString = "";
for(int i = 0; i < input.Length; i++){
if(k == 6){
Output.Add(currentString);
currentString = input[i].ToString();
k = 1;
}
else if(input[i] == '§' || input[i] == '%'){
currentString += input[i];
currentString += input[++i];
}
else{
k++;
currentString += input[i];
}
}
Output.Add(currentString);
return Output.ToArray();
}
Input
string test = "§cOnce upon a time there was a §R%mnice girl named Cinderella. She was very poor and her father passed way.";
Output
§cOnce u
pon a
time t
here w
as a §R%mn
ice gi
rl nam
ed Cin
derell
a. She
was v
ery po
or and
her f
ather
passed
way.
Given
public static IEnumerable<string> FunkyChunk(string source, int size)
{
var index = 0;
while (index < source.Length)
{
var sb = new StringBuilder(size*2);
for (int count = 0; count<size && index < source.Length; index++)
{
sb.Append(source[index]);
if (source[index] != '§' && source[index] != '%')
count++;
}
yield return sb.ToString();
}
}
Note : This is O(n) and used StringBuilder for less allocations even though there would be more succinct solutions. Using a fixed buffer and another index would likely be better
Usage
var input = "012345§678901234567%890123%4567890123456§§789012§345678901234";
foreach (var result in FunkyChunk(input,10))
Console.WriteLine(result);
Output
012345§6789
01234567%89
0123%456789
0123456§§789
012§3456789
01234
Full Demo Here
This question already has answers here:
What is an IndexOutOfRangeException / ArgumentOutOfRangeException and how do I fix it?
(5 answers)
Closed 3 years ago.
So the task is that I have to code a program that lets the user enter text. After that, I have to filter the text for non-capital letters only and put them in a list. Every letter should only be in the list once. My code's problem is that when I enter a word like "even", the method selects out e and v but the method doesn't skip the second "e" and ends there.
for (int i = 0; i < text.Length; i++)
{
if (letters.Contains(text[i]) == false && (text[i] >= 'a' && text[i] <= 'z'))
{
letters.Add(text[i]);
Console.WriteLine($"{letters[i]}");
}
}
I get an index out of range error message.
It seems that the Exception is being caused by this line:
Console.WriteLine($"{letters[i]}");
can you replace it by
Console.WriteLine($"{text[i]}");
or you can use a foreach and another variable caller letter:
foreach (var letter in text)
{
if (letters.Contains(letter) == false && (letter >= 'a' && letter <= 'z'))
{
letters.Add(letter);
Console.WriteLine($"{letter}");
}
}
The cause for IndexOutOfRangeException lies in the following lines.
letters.Add(text[i]);
Console.WriteLine($"{letters[i]}");
When i= 3, you are attempting to process character 'n' (assuming your input is 'even'), which doesn't exist in the letters List. You then add it to letters List and print letters[3]. However, at this point, letters only have 2 items('e' and 'v') in it. This is the reason, IndexOutOfRangeException is raised.
What you could do to print the last element added to letters is
Console.WriteLine($"{letters.Last()}");
Or
Console.WriteLine($"{letters[letters.Count - 1]}");
Meanwhile, as juharr pointed out, even printing the text[i] would produce the same result as it is the same character.
Console.WriteLine($"{text[i]}");
Char class already has extensions that verifies the characters, you can use char.IsLetter(character) and char.IsLower(character) to get a lower case letters only.
here is an example of your code :
string input = "Even if I'm a string, I still like odd numbers like 1, 3, 5 ..etc.";
var text = input.ToCharArray();
List<char> letters = new List<char>();
for(int x =0; x < text.Length; x++)
{
if (char.IsLetter(text[x]) && char.IsLower(text[x]) && !letters.Contains(text[x]))
{
letters.Add(text[x]);
Console.WriteLine($"{text[x]}");
}
}
There are few things that could help you here:
HashSet
Char.IsLetter
Short example:
HashSet<char> characters = new HashSet<char>();
foreach (char c in text)
{
if (Char.IsLetter(c))
{
// This will add the character ONLY if it is not there
characters.Add(c);
}
}
Full console app. If you want to try it create a new console app and replace all the Programs.cs by this:
using System;
using System.Collections.Generic;
using System.Linq;
namespace ConsoleApp1
{
class Program
{
static void Main(string[] args)
{
string text = "evEn There";
// HashSet is like a list, but without duplicates
HashSet<char> characters = new HashSet<char>();
// First make all characters lower case
text = text.ToLower();
foreach (char c in text)
{
if (Char.IsLetter(c))
{
// This will add the character ONLY if it is not there, if not it returns false
bool couldBeInserted = characters.Add(c);
}
}
string allCharacters = new String(characters.ToArray());
//This will print: "evnthr"
Console.WriteLine(allCharacters);
}
}
}
You can do it easily with LINQ Where method and ToHashSet method for unique items in array:
var text = "Avene";
var letters = text.Where(ch => char.IsLower(ch)).ToHashSet();
// leters contain now 'e', 'v' and 'n'
To get rid out of that exception you just could do:
Console.WriteLine($"{text[i]}");
which would work just as you want it.
Having learned the basics/fundamentals of the C# programming language, I am now trying to tackle my first real-world problem: Write a program that, given a string, finds its longest sub-string that contains at least one upper-case letter but no digits (and then displays the length of this longest sub-string). This could be two qualifying conditions for an acceptable password, for example...
I have written the code below all by myself, which means there is probably performance issues, but that is for later consideration. I am stuck at the point where I have to make sure there is no digit in the sub-string. The comments in my code show my thinking while writing the program...
I thought first I should check to see if there is an upper-case letter in an extracted sub-string, and if there was, then I can store that qualifying sub-string in a list and then break out of the loop. But now I wonder how to check the no-digit condition at the same time in the same sub-string?
I am trying to keep it neat and simple (as I said I have only just started writing programs longer than a few lines!) so I thought doing a nested loop to check every character against !char.IsNumber(letter) might not be optimal. Or should I first check to see if there is no digit, then see if there is at least a capital character?
I feel confused how to achieve both restrictions, so I would appreciate some help in resolving this issue. I would also appreciate any observations or suggestions you might have. For example, is it OK to store my sub-strings in a list? Should I make a dictionary of some sort? Is my all-possible-sub-string extraction nested-loop optimal?
p.s. Some bits are still unfinished; for example I am still to implement the last step to find the longest sub-string and display to the user its length...
using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
namespace PasswordRestriction
{
class Program /// Write a program that, given a string, finds the longest substring that is a valid password and returns its length.
{
static void Main(string[] args)
{
// Ask the user for an alphanumeric string.
Console.WriteLine("Enter a string of alphanumeric values:");
// Receive the user input as string.
string password = Console.ReadLine();
// Print the length of the longest qualifying substring of the user string.
Console.WriteLine("Length of the longest qualifying substring:\n" + Solution(password).Length );
// Prevent the console window from closing.
Console.ReadLine();
}
/// The method that exracts the longest substring that is a valid password.
/// Note that a substring is a 'contiguous' segment of a string.
public static string Solution(string str)
{
// Only allow non-empty strings.
if ( String.IsNullOrEmpty(str) )
{
return "";
}
else
{
// Only allow letters and digits.
if ( str.All(char.IsLetterOrDigit) )
{
// A list for containing qualifying substrings.
List<string> passwordList = new List<string>();
// Generate all possible substrings. Note that
// string itself is not a substring of itself!
for (int i = 1; i < str.Length; i++)
{
for (int j = 0; j <= (str.Length-i); j++)
{
string subStr = str.Substring(j, i);
Console.WriteLine(subStr);
bool containsNum = false;
bool containsUpper = false;
// Convert the substrings to arrays of characters with ToCharArray.
// This method is called on a string and returns a new character array.
// You can manipulate this array in-place, which you cannot do with a string.
char[] subStrArray = subStr.ToCharArray();
// Go through every character in each substring.
// If there is at least one uppercase letter and
// no digits, put the qualifying substring in a list.
for (int k = 0; k < subStrArray.Length; k++)
{
char letter = subStrArray[k];
if ( char.IsNumber(letter) )
{
containsNum = true;
break;
}
if ( char.IsUpper(letter) )
{
containsUpper = true;
}
if ( containsUpper && (containsNum == false) && (k == subStrArray.Length - 1) )
{
Console.WriteLine("Found the above legit password!");
passwordList.Add(subStr);
}
}
}
}
//Find the longest stored string in the list.
//if (passwordList.Count != 0)
//{
string maxLength = passwordList[0];
foreach (string s in passwordList)
{
if (s.Length > maxLength.Length)
{
maxLength = s;
}
}
//}
// Return the qualifying substring.
return maxLength;
}
else
{
return "aaaaaaaaaa";
}
}
}
}
}
A good problem for Linq
contains no digits - Split on digits
at least one upper-case letter - Where + Any
longest (not shortest) OrderByDescending
longest (just one) - FirstOrDefault
Implementation
string source = ....
var result = source
.Split('0', '1', '2', '3', '4', '5', '6', '7', '8', '9')
.Where(line => line.Any(c => c >= 'A' && c <= 'Z')) // or char.IsUpper(c)
.OrderByDescending(line => line.Length)
.FirstOrDefault(); // null if there're no such substrings at all
As an alternative to the Linq answer, and if I understand you correctly, this is what I'd do, replacing the content of the str.All condition:
string qualifier;
string tempQualifier;
bool containsUpper = false;
for (int i = 0; i < str.Length(); i++) {
tempQualifier += str[i];
if (char.IsNumber(str[i])) {
if (containsUpper) {
if (tempQualifier.Length > qualifier.Length && tempQualifier.Length != str.Length) {
qualifier = tempQualifier;
}
containsUpper = false;
}
tempQualifier = "";
} else if (char.IsUpper(str[i])) {
containsUpper = true;
}
}
return qualifier;
This would go through the string, building up the substring until it comes across a number. If the substring contains an uppercase letter and is longer than any previous qualifier, it is stored as the new qualifier (also assuming that it isn't the length of the string provided). Apologies if I've made any mistakes (I'm not well versed in C#).
It's much longer than the Linq answer, but I thought it'd be handy for you to see the process broken down so you can understand it better.
Using C# I'm trying to find a specific word within a char array. Also, I don't want the same letter used more than once i.e. the word is 'hello' and I'm trying to find it within a random array of letters, so if the letter 'l' is used out of the random array of letters, I don't want it to be used again. There should be another 'l' within the array of letters to be used as the second 'l' in "hello". Just trying to be precise. A simple answer would be very helpful. Thank you.
Here is my attempt so far.
public static char [] Note = "hello".ToCharArray();
public static char [] Newspaper = "ahrenlxlpoz".ToCharArray();
static void main(string[] args)
{
Array.Sort(Note);
Array.Sort(Newspaper);
if(Newspaper.Contains<Note>)
{
Console.Write("It should display the letters of Note found within Newspaper");
}
}
I assume by "contains" you mean Newspaper has enough number of letters from each letter to make up Note. For example, you need at least two l's to make up the word "hello". If so, you need to basically count the number of each letter in both strings, and make sure the number of each letter in Note is less than or equal to the number of that letter in Newspaper.
var dictNote = Note.GroupBy(c => c).ToDictionary(g => g.Key, g => g.Count());
var dictNews = Newspaper.GroupBy(c => c).ToDictionary(g => g.Key, g => g.Count());
bool contains = dictNote.All(x =>
dictNews.ContainsKey(x.Key) && x.Value <= dictNews[x.Key]);
In fact, a string is a char array. And the most "classic" way to do this would be:
string Note = "hello";
char[] Newspaper = "ahrenlxlpoz".ToCharArray();
string res = "";
for (int i = 0; i < Note.Length; i++)
for (int j = 0; j < Newspaper.Length; j++)
if (Note[i] == Newspaper[j])
{
res += Newspaper[j];
Newspaper[j] = ' ';
break;
}
//This prints the remaining characters in Newspaper. I avoid repeating chars.
for (int i = 0; i < Newspaper.Length; i++ )
Console.Write(Newspaper[i]+"\n");
Console.Write("\n\n");
if (Note.Equals(res)) Console.Write("Word found");
else Console.Write("Word NOT found");
Console.Read();
At the end, res will be "hello". Print res in the console. I added the ' ' to avoid repeated characters as someone said in the answer up. So at the end it will compare the result with the word and will tell you if it found the word in the string. Try changing Newspaper to this: "ahrenlxlpaz" and it will tell you the word is NOT found :)
Try this:
public static char[] Note = "hello".ToCharArray();
public static char[] Newspaper = "ahrenlxlpoz".ToCharArray();
foreach (char c in Note) //check each character of Note
{
if (Newspaper.Contains(c))
{
Console.Write(c); //it will display hello
}
}
I need to get the letters as an array on passing two letters using C#
For ex.: When i pass "AE", i need to get the {A,B,C,D,E} as an array. and passing "FJ" should return {F,G,H,I,J}.
The Enumerable class can create a range, which makes the looping simple:
public static char[] CharactersBetween(char start, char end) {
return Enumerable.Range(start, end - start + 1).Select(c => (char)c).ToArray();
}
Note: A char value converts implicitly into int, so there is no conversion needed in that direction. You only have to convert the integers back to char.
Edit:
If you want to send in the alphabet to use (to handle language differences), you can use Substring to get a part of that string:
public static char[] CharactersBetween(char start, char end, string alphabet) {
int idx = alphabet.IndexOf(start);
return alphabet.Substring(idx, alphabet.IndexOf(end) - idx + 1).ToCharArray();
}
Do you mean something like
char[] CharactersBetween(char start, char end)
{
List<char> result = new List<char>();
for (char i = start; i <= end; i++)
{
result.Add(i);
}
return result.ToArray();
}
This should work out well
string startandend = "AG";
string result= "";
for( char i = startandend[0]; i <= startandend[1]; i++){
result += i;
}
result will now contain ABCDEFG.
You should probably add some logic to check if startandend actually have a Length of 2 and so on, but this should be a good starting block for you.
If you want the char[] instead of the string representation, simply call result.ToCharArray() at the end.
Use a loop with integer conversion
with
System.Convert.ToInt32(Char);
and
System.Convert.ToChar(Int32);
see http://msdn.microsoft.com/en-us/library/system.convert_methods.aspx
Pretty simple if you use a fixed alphabet,
public static string ALPHABET = "ABCDEFGHIJKLMNOPWRSTUVWXYZ";
public static List<char> GetLetters(string firstLast)
{
List<char> letters = new List<char>();
int start = ALPHABET.IndexOf(firstLast[0]);
int end = ALPHABET.IndexOf(firstLast[1]);
for (int i = start; i <= end; i++)
{
letters.Add(ALPHABET[i]);
}
return letters;
}
Obviously add in your checks for various things, but it does the basic job.
You're going to have to reference whichever alphabet you want to use. English is easy enough as the letters happen to correspond to code-point order, French treats Œ and Æ as letters in their own right sometimes, and not others. Danish and Norwegian place "Æ, Ø, Å" after Z and Swedish does the same with "Å, Ä, Ö". Irish uses "ABCDEFGHILMNOPRSTU" as the alphabet, but does also use J, K, Q, V, W, X, Y & Z in loan words.
And those are relatively easy cases. So there's no one-size-fits-all.
The easiest way to pass an alphabet is to have a string that contains it. So, e.g. the Danish alphabet would have the string "ABCDEFGHIJKLMNOPQRSTUVWXYZÆØÅ" while French could either include the ligatures or not as you wish (but do you need to deal with the possibility of receiving them while not using them?).
This done:
public static IEnumerable<char> AlphabetRange(string alphabet, string alphaRange)
{
if(alphaRange == null)
throw new ArgumentNullException();
if(alphaRange.Length < 2)
throw new ArgumentException();
int startIdx = alphabet.IndexOf(alphaRange[0]);
int endIdx = alphabet.IndexOf(alphaRange[1]) + 1;
if(startIdx == -1 || endIdx == 0)
throw new ArgumentException();
while(startIdx < endIdx)
yield return alphabet[startIdx++];
}