I need to delete all english letters in a string.
I wrote the following code:
StringBuilder str = new StringBuilder();
foreach(var letter in test)
{
if(letter >= 'a' && letter <= 'z')
continue;
str.Append(letter); }
What is the fastest way?
use Regex replace method, and give it [a-z]|[A-Z]
Try this:
var str = test.Where(item => item < 'A' || item > 'z' || (item > 'Z' && item < 'a'));
Use this method to do such execution....
public static string RemoveSpecialCharacters(string str)
{
StringBuilder sb = new StringBuilder();
foreach (char c in str)
{
if ((c >= 'A' && c <= 'Z') || (c >= 'a' && c <= 'z'))
continue;
else
sb.Append(c);
}
return sb.ToString();
}
Related
I actually tried to make a StringToASCII function from scratch in c#.
I get the input from _myString and this is the code :
public void convertToASCII() {
//A-Z --> 65-90
//a-z --> 97-122
//0-9 --> 48-57
//Space --> 32
int[] returnString = new int[_myString.Length];
int iTableau = 0;
char iAZ = 'A';
char iaz = 'a';
char i09 = '0';
char iSpace = ' ';
for(int i = 0; i < _myString.Length; i++)
{
if(_myString[i] >= 65 && _myString[i] <= 90 || _myString[i] >= 97 && _myString[i] <= 122 || _myString[i] >= 48 && _myString[i] <= 57 || _myString[i] == 32)
{
while(iAZ < 90 || iaz < 122 || iaz < 122 || i09 < 57 || _myString[i] == 32)
{
if(_myString[i] == iAZ && iAZ >= 'A' && iAZ <= 'Z')
{
returnString[iTableau] = iAZ;
iTableau++;
iAZ--;
}
else
{
iAZ++;
}
if(_myString[i] == iaz && iaz >= 'a' && iaz <= 'z')
{
returnString[iTableau] = iaz;
iTableau++;
iaz--;
}
else
{
iaz++;
}
if(_myString[i] == i09 && i09 >= '0' && i09 <= '9')
{
returnString[iTableau] = i09;
iTableau++;
i09--;
}
else
{
i09++;
}
if(_myString[i] == iSpace)
{
returnString[iTableau] = iSpace;
iTableau++;
}
}
}
}
_myString = "";
for (int i = 0; i < returnString.Length; i++)
{
_myString += returnString[i];
}
}
I also tried this kind of function which it works, but i would like to make one who checks only chars from A-Z and a-z and 0-9 and space.
Same thing as the first function, i take the input from a global string variable called "_myString".
public void convertToASCII()
{
string asciiChar;
string returnString = "";
foreach (char c in _myString)
{
asciiChar= ((int)(c)).ToString();
returnString += " " + asciiChar;
}
_myString = returnString;
}
This is actually relatively simple:
public string StringToLettersOrNumbersOrSpace(string input)
{
var sb = new StringBuilder();
for (int i = 0; i < input.Length; i++)
{
if (Char.IsLetterOrDigit(input[i]) || input[i] == ' ')
{
sb.Append(input[i]);
}
}
return sb.ToString();
}
First, you'll want to use StringBuilder instead of continuously appending to a string variable. Strings in C# are immutable, meaning that they can't be changed after they've been created, so doing something like string s1 = "aaa"; s1 += "bbb"; will actually create an entirely new string instead of just adding to the original. StringBuilder, on the other hand, is mutable, so you don't need to worry about reallocating a bunch of strings every time you want to concatenate strings (which gets progressively slower and slower as the string gets bigger).
Second, you can use Char.IsLetterOrDigit instead of using comparisons. The method takes a char as input and returns true if the character is a letter (uppercase or lowercase) or a number. This maps directly to your desired range a-z, A-Z, and 0-9. Since you also care about spaces, though, you will have to manually check for that.
I'm new to programming and C# and i'm trying to make Atbash Cipher in C#.
So I'm stuck at this problem: the cipher ran good, but they don't put spacing, or special characters (that not need to encode) in the result. I tried to make it but it got repeated.
So is there a way to let it skip the non-alphabet characters and put it on result ?
Here is my code
using System;
namespace AtbashCipher
{
class Program
{
static void Main()
{
Console.WriteLine("Atbash cipher v1.0");
Console.WriteLine();
Console.Write("Enter messages: ");
string userInput = Console.ReadLine();
Console.WriteLine();
string Alphabet = "abcdefghijklmnopqrstuvwxyz";
string AlphabetUpper = "ABCDEFGHIJKLMNOPQRSTUVWXYZ";
string result = "";
Boolean SpecialChar = false;
foreach (char c in userInput)
{
for (int i = 0; i < Alphabet.Length; i++)
{
if (c == Alphabet[i])
{
result += Alphabet[Alphabet.Length - 1 - i];
}
if (c == AlphabetUpper[i])
{
result += AlphabetUpper[AlphabetUpper.Length - 1 - i];
}
}
}
//Print result for user
Console.WriteLine("Encoded messages: " + result);
Console.WriteLine();
Console.Write("Press any key to exit.");
Console.ReadKey();
}
}
}
I had the same task recently and here is my approach:
private string GetAtbash(string s)
{
var charArray = s.ToCharArray();
for (int i = 0; i < charArray.Length; i++)
{
char c = charArray[i];
if (c >= 'a' && c <= 'z')
{
charArray[i] = (char) (96 + (123 - c));
}
if (c >= 'A' && c <= 'Z')
{
charArray[i] = (char) (64 + (91 - c));
}
}
return new String(charArray);
}
You forgot to append the character if it's not between a-z or A-Z. You can check if (c >= 'a' && c <= 'z') || (c >= 'A' && c <= 'Z') and simply append c to result if that's not the case.
I am only able to encrypt, but i do not how to decrypt. Someone please help. Do I have to declare a bool variable?
Or is that any other better way to do it?
string UserInput = "";
int shift;
Shift OBSHIFT = new Shift();
Console.Write("\nType a string to encrypt:");
UserInput = Console.ReadLine();
Console.Write("How many chars would you like to shift?: ");
shift = int.Parse(Console.ReadLine());
Console.WriteLine("\nApplying Caesar cipher ... ");
Console.Write("Your encrypted string is: ");
Console.WriteLine(OBSHIFT.Cshift(UserInput, shift));
Console.Read();
}
}
class Shift
{
public string Cshift(string str, int shift )
{
string UserOutput = "";
char[] A = null;
A = str.ToCharArray();
int temp;
for (int i = 0; i < str.Length; i++)
{
char c = A[i];
if ((c >= 'A' && c <= 'Z') || (c >= 'a' && c <= 'z'))
{
temp = (int)(A[i] + shift);
if ((c >= 'A' && c <= 'Z' && temp > 'Z') || (c >= 'a' && c <= 'z' && temp > 'z'))
temp = temp - 26;
else
temp = (int)(A[i] + (shift));
}
else
temp = c;
UserOutput += (char)temp;
}
return UserOutput;
}
}
}
}
Talking about Caesar cipher, you can simply negate the shift and get the original string.
I.e., cshift(cshift(string, x), -x) == string.
Using your Shift class:
int sh = 17;
string original = "abcdefgh";
string encrypted = shift.Cshift(original, sh);
string decrypted = shift.Cshift(shifted, -sh);
Console.WriteLine(decrypted == original); // true
For convenience, you can create a method Decrypt, which will do this:
class Shift
{
public string Encrypt(string originalString, int shift)
{
string userOutput = "";
char[] a = originalString.ToCharArray();
for (int i = 0; i < originalString.Length; i++)
{
char c = a[i];
int temp;
if ((c >= 'A' && c <= 'Z') || (c >= 'a' && c <= 'z'))
{
temp = (int)(a[i] + shift);
if ((c >= 'A' && c <= 'Z' && temp > 'Z') || (c >= 'a' && c <= 'z' && temp > 'z'))
temp = temp - 26;
else
temp = (int)(a[i] + (shift));
}
else
temp = c;
userOutput += (char)temp;
}
return userOutput;
}
public string Decrypt(string cipherString, int shift)
{
return Encrypt(cipherString, -shift);
}
}
Note that I have also done some little code improvements like:
combined declaration and assignment of A
moved temp into the inner scope
gave the proper names to the local variables (lower-case)
Please excuse the rubbish title, I don't know how to word it properly. I am wondering how I can use this code:
int cnt = 0;
foreach (char c in test) {
if (c == '&') cnt++;
}
from this question and instead of adding 1 to the count for 'just' &, add 1 to the count for & or # or %?
You can directly count using .Count and with using Linq
var cnt = test.Count(c => c == '&' || c == '#' || c == '%');
It's easy, just add more conditions:
int cnt = 0;
foreach (char c in test) {
if (c == '&' || c == '#' || c == '%') cnt++;
}
You could use Regex:
cnt = Regex.Matches(test, "[&#%]").Count
string pattern = "&#%";
int cnt = 0;
foreach (char c in test)
{
if (pattern.IndexOf(c) != -1) cnt++;
}
I've written this function...
internal static IEnumerable<KeyValuePair<char?, string>> SplitUnescaped(this string input, char[] separators)
{
int index = 0;
var state = new Stack<char>();
for (int i = 0; i < input.Length; ++i)
{
char c = input[i];
char s = state.Count > 0 ? state.Peek() : default(char);
if (state.Count > 0 && (s == '\\' || (s == '[' && c == ']') || ((s == '"' || s == '\'') && c == s)))
state.Pop();
else if (c == '\\' || c == '[' || c == '"' || c == '\'')
state.Push(c);
if (state.Count == 0 && separators.Contains(c))
{
yield return new KeyValuePair<char?, string>(c, input.Substring(index, i - index));
index = i + 1;
}
}
yield return new KeyValuePair<char?, string>(null, input.Substring(index));
}
Which splits a string on the given separators, as long as they aren't escaped, in quotes, or in brackets. Seems to work pretty well, but there's one problem with it.
There characters I want to split on include a space:
{ '>', '+', '~', ' ' };
So, given the string
a > b
I want it to split on > and ignore the spaces, but given
a b
I do want it to split on the space.
How can I fix the function?
You could continue to split based on and > and then remove the strings which are empty.
I think this does it...
internal static IEnumerable<KeyValuePair<char?, string>> SplitUnescaped(this string input, char[] separators)
{
int startIndex = 0;
var state = new Stack<char>();
input = input.Trim(separators);
for (int i = 0; i < input.Length; ++i)
{
char c = input[i];
char s = state.Count > 0 ? state.Peek() : default(char);
if (state.Count > 0 && (s == '\\' || (s == '[' && c == ']') || ((s == '"' || s == '\'') && c == s)))
state.Pop();
else if (c == '\\' || c == '[' || c == '"' || c == '\'')
state.Push(c);
else if (state.Count == 0 && separators.Contains(c))
{
int endIndex = i;
while (input[i] == ' ' && separators.Contains(input[i + 1])) { ++i; }
yield return new KeyValuePair<char?, string>(input[i], input.Substring(startIndex, endIndex - startIndex));
while (input[++i] == ' ') { }
startIndex = i;
}
}
yield return new KeyValuePair<char?, string>(null, input.Substring(startIndex));
}
I was trying to push the space onto the stack too before, and then doing some checks against that...but I think this is easier.