I have a string which comprise lots of letters. I have used the following code to convert it to numbers, but the new string t still gives me imperfect result.
For example:
tung2003 -> -1-1-1-12003
What I expected: 1161171101032003 (116 is the ASCII code of t, 117 is the ASCII code of u
string t=null;
foreach (char c in Properties.Settings.Default.password)
{
int ascii = (int)Char.GetNumericValue(c);
int counter=0;
counter = ascii;
t = t + Convert.ToString(counter);
}
The problem is the - character. I want my new string only comprises numbers.
It looks like you do not want the ASCII values of the numbers based on your expected output. In that case you can just do something like this:
string input = "tung2003";
string output = string.Empty;
foreach(char c in input)
{
if(char.IsNumber(c))
{
output += c;
}
else
{
output += ((byte)c).ToString();
}
}
//output is now: 1161171101032003
Fiddle here
Also added as a Linq expression for a short hand solution.
// Method 1 Linq
string output = string.Concat(("tung2003".ToCharArray()
.Select(s=> char.IsDigit(s) ? s.ToString() : ((int)s).ToString())));
// Method 2
string input = "tung2003";
string output = string.Empty;
foreach (char c in input)
{
if (Char.IsDigit(c)) output += c.ToString();
else output += ((int)c).ToString();
}
Extrapolating your output it looks like you want two different things. You want to tally each ascii character as long as it is a letter and extract the numeric values to append. The following provides three options, the first is to tally the ascii values from letters and the other two are ways to extract only digits. Because your code example uses a Password I am assuming you are trying to do some sort of custom hashing and if that is the case you should use a Hash implementation from the Cryptography namespace or some other package.
using System;
using System.Linq;
using System.Text.RegularExpressions;
namespace ConsoleApp5
{
class Program
{
static void Main(string[] args)
{
var combined = OnlyLettersToAscii("tung2003") + OnlyNumbers("tung2003");
Console.WriteLine($"Input: tung2003 Output: {OnlyNumbers("tung2003")}");
Console.WriteLine($"Input: tung2003 Output Regex: {OnlyNumbersWithRegex("tung2003")}");
Console.ReadKey();
}
private static string OnlyLettersToAscii(string originalString)
{
if (string.IsNullOrWhiteSpace(originalString)) return originalString;
return string.Join(string.Empty, originalString.ToArray()
.Where(w => char.IsLetter(w))
.Select(s => ((int)s).ToString()));
}
private static string OnlyNumbers(string originalString)
{
if (string.IsNullOrWhiteSpace(originalString)) return originalString;
return new string(originalString.Where(w => char.IsDigit(w)).ToArray());
}
public static string OnlyNumbersWithRegex(string originalString)
{
return Regex.Replace(originalString, #"[^\d]", string.Empty);
}
}
}
string t = "";
foreach (char c in Properties.Settings.Default.password)
{
if (IsNumber(x)) t += System.Convert.ToInt32(c).ToString();
else
{
t += c.ToString();
}
}
Moreover, if you just want to get rid off '-' the use this code: t =String.Replace(t, '-');
Related
This question already has answers here:
How do I create a terminable while loop in console application?
(7 answers)
Closed 3 years ago.
I started a C# course now and there is an assignment where I have to create a "palindrome detector" program. Point is that user inputs some word or sentence, then I have to remove chars like ,.;:!? and space from it. I have done that with two different methods, because char method can not remove space so I wrote another method for it.
After "cleaning" operation program reversing input what user gave, and comparing original user input and reversed user input to each other. It they are same it prints "It is palindrome", if they are different it prints "It is not palindrome". That is working fine, BUT THE PROBLEM IS I have to put them in for loop. It have to ask input again and again, until user give empty.
This would be very easy, but somehow I can not do it.
Here is my code:
using System;
namespace Palindromi
{
class Program
{
static void Main()
{
Console.WriteLine("Hei! Tervetuloa palindromin tunnistusohjelmaan. Tämä tunnistaa, onko syöttämäsi sana sama toisinpäin!");
Console.Write("Anna teksti (tyhjä lopettaa): ");
string userinput = Console.ReadLine(); //userinput is user's input, this is what you have to modify. remove some chars and reverse it.
if (userinput == "")
{
Console.ReadLine();//when i have loop this have to be "break". This meant to break for loop when i have it.
}
char[] removechars = { '.', ':', ';', ',', '!', '?' };//this is the list of "have to be removed" chars
string userinput_without_chars = userinput.Trim(removechars); //this method remove chars which are listed
string userinput_without_chars_space = userinput_without_chars.Replace( " ", ""); //replace space with empty
string reverse_string, reversed;
reverse_string = userinput_without_chars_space;
reversed = "";
int len;
len = userinput_without_chars_space.Length - 1;
while (len >= 0)
{
reversed = reversed + reverse_string[len];
len--;
}
Console.WriteLine("Sana käännettynä on {0}", reversed); //tells user input reversed
if (userinput_without_chars_space == reversed)//check is the userinput same than reversed user input
{
Console.Write("On palindromi.");//it is palindrome
}
else
{
Console.Write("Ei ole palindromi.");//it is not palindrome
}
}
}
}
You could potentially do something along these lines:
var running = true;
while(running)
{
var input = Console.ReadLine().ToLower();
var phrase = input.Sanitize(new List<string>() {".", ",", "?", "!", "'", "&", "%", "$", " "});
if(phrase.IsPalindrome())
Console.Writeline("Input was palindrome.");
}
public static string Sanitize(this string input, IList<string> punctuation) =>
String.Join(String.Empty, input.Where(character => punctuation.Contains(character) == false));
public static bool IsPalindrome(this string sentence)
{
for (int l = 0, r = sentence.Length - 1; l < r; l++, r--)
if (sentence[l] != sentence[r])
return false;
return true;
}
public static void Close(string input)
{
// Some logic to see if the application should stop.
}
You could create another method that looks for commands, or keystrokes, then sets the boolean to run as false. Which would break the infinite loop. You could also do an abrupt close with Environment.Exit.
The very simplest approach is replace your Console.ReadLine() where you want to break to return.
Alternatively, you could wrap the logic in another while loop.
while (userinput != "")
{
// Remove chars
// rest of your logic
/* IMPORTANT */
userinput = Console.Readline();
}
To remove the symbols from the input, you can use the Regex.Replace method. In this case, you can be sure, that the specified symbols will be correctly removed from the input string. Note, that you can handle the whitespaces along with other characters you mentioned, like in the code snippet below:
var CharactersToRemove { get; set; } = " ,.;:!?";
var processedInput = Regex.Replace(input.ToLower(), $"[{CharactersToRemove}]", string.Empty);
Note, that here I used input.ToLower() to convert the input to a lowercase string. This will make the palindrome tests case-insensitive. Should you need case-sensitive palindrome tests, just remove the .ToLower() part.
There is no need to reverse the input string to check if it is a palindrome. You can check this within one for loop as follows:
bool CheckForBeingaAPalindrome(string input)
{
var frontIndex = 0;
var tailIndex = input.Length - 1;
for (; frontIndex < tailIndex;)
{
if (input[frontIndex] != input[tailIndex])
return false;
++frontIndex;
--tailIndex;
}
return true;
}
Note, that in this case you only iterate over the elements of the input string once. This approach will give you al least 4 times better performance than the one you used.
Below, you can find a complete minimal working solution to your problem.
using System.Text.RegularExpressions;
using static System.Console;
namespace Assignment
{
public static class PalindromeFinder
{
public static string CharactersToRemove { get; set; } = " ,.;:!?";
public static bool IsPalindrome(string input)
{
var processedInput = RemoveUnnecessaryCharacters(input);
return CheckForBeingAPalindrome(processedInput);
}
private static string RemoveUnnecessaryCharacters(string input)
{
return Regex.Replace(input.ToLower(), $"[{CharactersToRemove}]", string.Empty);
}
private static bool CheckForBeingAPalindrome(string input)
{
var frontIndex = 0;
var tailIndex = input.Length - 1;
for (; frontIndex < tailIndex;)
{
if (input[frontIndex] != input[tailIndex])
return false;
++frontIndex;
--tailIndex;
}
return true;
}
}
public class Program
{
private static void Main(string[] args)
{
ContinuouslyCheckUserInputForBeingAPalindrome();
}
private static void ContinuouslyCheckUserInputForBeingAPalindrome()
{
while (FetchUserInputFromConsole() is string input
&& !string.IsNullOrWhiteSpace(input))
{
var isPalindrome = PalindromeFinder.IsPalindrome(input);
var modifier = isPalindrome ? "a" : "not a";
WriteLine($"It is {modifier} palindrome");
}
}
private static string FetchUserInputFromConsole()
{
Write("Enter a string: ");
return ReadLine();
}
}
}
I have an string that can be 2 to N chars long. I also have 4 ocode (each 2 chars long).
Is there a way to so something like:
var tmpArray = inputStr.Split(char1, char2, char3, char4).ToArray();
Say that the opcodes are A,B,C,D or 8 and I have this string AB123456789C123412341234B123 the array would be like this:
A
B
123456789
C
123412341234
B
123
This is all you need.
string toSplit = "AB123456789C123412341234B123";
string pattern = #"([ABCD])";
IEnumerable<string> substrings = Regex.Split(toSplit, pattern).Where(i => !String.IsNullOrWhiteSpace(i));
Test here: http://www.beansoftware.com/Test-Net-Regular-Expressions/Split-String.aspx
All you have to do is declare a character class [...] involving all your characters you want to split on, then you encompass that in (...) parens to keep the delimiters.
Try this,
private char[] alphabets = {'A','B','C', 'D','E','F','G','H','I','J','K','L','M','N','O','P','Q','R','S','T','U','V','W','X','Y','Z'};
var input = "AB123456789C123412341234B123";
var result = input.SplitAndKeep(alphabets).ToList();
public static class Extensions
{
public static IEnumerable<string> SplitAndKeep(this string s, char[] delims)
{
int start = 0, index;
while ((index = s.IndexOfAny(delims, start)) != -1)
{
if (index - start > 0)
yield return s.Substring(start, index - start);
yield return s.Substring(index, 1);
start = index + 1;
}
if (start < s.Length)
{
yield return s.Substring(start);
}
}
}
Use Regex.Split
var str = "AB123456789C123412341234B123";
Regex r = new Regex(#"([A-Z])|(\d*)");
var parts = r.Split(str).Where(x=> !string.IsNullOrWhiteSpace(x)).ToArray();
if you want just A,B,C and D, use this
Regex r = new Regex(#"([A-D])|(\d*)");
I find that Regex lookahead/lookbehind fits this scenario. The pattern basically says to split when a single letter is found behind or ahead of the current position. Then use Linq to not return any empty spaces as part of the result, which in this sample case the empty element would be the first element.
Lookahead/Lookbehind Reference
using System;
using System.Linq;
using System.Text.RegularExpressions;
public class Program
{
public static void Main()
{
string data = "AB123456789C123412341234B123";
var pieces = Regex.Split(data, "(?<=[a-zA-Z])|(?=[a-zA-Z])").Where(p => !String.IsNullOrEmpty(p));
foreach (string p in pieces)
Console.WriteLine(p);
}
}
Results:
A
B
123456789
C
123412341234
B
123
Fiddle Demo
Try first splitting on A only. Then split each result on B only. Then split each result on C only etc...
Splitting on A gives you:
B123456789C123412341234B123
which you know starts with A
Splitting on B gives you:
123456789C123412341234,
123
each of which you know starts with B and so on.
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();
}
I have string which I split to see if any of the split value is string. If so I want to return true else false.
string words = "1 2 c 5";
Easy approach, I can follow by converting into int array and then compare value side by side.
int[] iar = words.Split(' ').Select(s => int.TryParse(s, out n) ? n : 0).ToArray();
Can any one recommend better approach?
You can simply check without using Split:
var result = words.Any(c => !char.IsWhiteSpace(c)
&& !char.IsDigit(c));
Or using Split:
var result = words.Split()
.Any(w => w.Any(c => !char.IsDigit(c)));
The point is you can use char.IsDigit to check instead of using int.Parse or int.TryParse.
You could do this with a simple little method:
public static bool CheckForNum(string[] wordsArr)
{
int i = 0;
foreach (string s in wordsArr)
{
if (Int32.TryParse(s, out i))
{
return true;
}
}
return false;
}
Using:
bool result = CheckForNum(words.Split(' '));
Console.Write(result);
Why not use a regular expression? If a string has words and numbers in it, it must have letters and number characters. I don't entirely understand the logic in your question, so you may need to adjust the logic here.
using System;
using System.Text.RegularExpressions;
...
string words = "1 2 c 5";
Match numberMatch = Regex.Match(words, #"[0-9]", RegexOptions.IgnoreCase);
Match letterMatch = Regex.Match(words, #"[a-zA-Z]", RegexOptions.IgnoreCase);
// Here we check the Match instance.
if (numberMatch.Success && letterMatch.Success)
{
// there are letters and numbers
}
I have a URL formatter in my application but the problem is that the customer wants to be able to enter special characters like:
: | / - “ ‘ & * # #
I have a string:
string myCrazyString = ":|/-\“‘&*##";
I have a function where another string is being passed:
public void CleanMyString(string myStr)
{
}
How can I compare the string being passed "myStr" to "myCrazyString" and if "myStr has any of the characters in myCrazyString to remove it?
So if I pass to my function:
"this ' is a" cra#zy: me|ssage/ an-d I& want#to clea*n it"
It should return:
"this is a crazy message and I want to clean it"
How can I do this in my CleanMyString function?
Use Regular Expression for that Like:
pattern = #"(:|\||\/|\-|\\|\“|\‘|\&|\*|\#|\#)";
System.Text.RegularExpressions.Regex.Replace(inputString, pattern, string.Empty);
split each string you want to remove by |
To remove the special characters like the | itself use \, so \| this will handle the | as normal character.
Test:
inputString = #"H\I t&he|r#e!";
//output is: HI there!
solution without regular expressions, just for availability purposes:
static string clear(string input)
{
string charsToBeCleared = ":|/-\“‘&*##";
string output = "";
foreach (char c in input)
{
if (charsToBeCleared.IndexOf(c) < 0)
{
output += c;
}
}
return output;
}
You can use Regex as others mentioned, or code like this:
char[] myCrazyChars = "\"\':|/-\\“‘&*##".ToCharArray();
string myCrazyString = "this ' is a\" cra#zy: me|ssage/ an-d I& want#to clea*n it";
string[] splittedCrazyString = myCrazyString.Split(myCrazyChars);
string notCrazyStringAtAll = string.Join("", splittedCrazyString);
Try using a Regular Expression.
Here's a fairly straight-forward way to do it. Split the string based on all of the characters in your "crazy string and then join them back together without the bad characters.
string myCrazyString = #":|/-\“‘&*##";
string str = #"this ' is a"" cra#zy: me|ssage/ an-d I& want#to clea*n it";
string[] arr = str.Split(myCrazyString.ToCharArray(), StringSplitOptions.None);
str = string.Join(string.Empty, arr);
Another possible solution:
namespace RemoveChars
{
class Program
{
static string str = #"this ' is a\“ cra#zy: me|ssage/ an-d I& want#to clea*n it";
static void Main(string[] args)
{
CleanMyString(str);
}
public static void CleanMyString(string myStr)
{
string myCrazyString = #":|/-\“‘&*##";
var result = "";
foreach (char c in myStr)
{
var t = true; // t will remain true if c is not a crazy char
foreach (char ch in myCrazyString)
if (c == ch)
{
t = false;
break;
}
if (t)
result += c;
}
}
}
}
You could try an if statement and if a character is present then mention the craziness
if (myCrazyString.Contains("#"))
{
Console.WriteLine("This string is out of controL!");
}
Regex is also a good idea(Maybe better)
Try this :
1.Define a StringBuilder
2.Iterate through the characters of the string to be cleaned.
3.Put everything required in the StringBuilder and ignore other special charactersby simply putting if conditions.
4.Rerurn StringBuilder.
Or
Try using Regular Expression.