I've been working on this issue for awhile and I've been stuck so I hope someone can push me in the right direction. I have a c# console application that will take in a string and verify that it contains only 0-9, a-z, A-Z, and -.
My issue that I'm having is that I need to convert any letters in the phone number to their respective number. So if I input 1800-Flowers, it will output as 1800-3569377. I have my methods defined:
I'm not looking for the solutions here (this is homework), but I'm looking for a push in the right direction. Do I need to convert the string to a char array to break up each individual character, and then use that in the convert method to switch any letter into a number?
There are certainly a lot of solutions here. Since you're already using Regex, you could approach it in a basic way:
num = Regex.Replace(num, #"[abcABC]", "2");
num = Regex.Replace(num, #"[defDEF]", "3");
//....
or you could create a Dictionary<string,char> and run through each char and convert it to the mapped character. Something like :
var dict = new Dictionary<string, char>();
dict.Add("abcABC",'2');
//...
foreach(char c in num.Where(char.IsLetter))
{
var digit = dict.First(d => d.Key.Contains(c)).Value;
num = num.Replace(c, digit);
}
Like you said, the LINQ here is splitting the string to a char array, and looping through ones that are letters
Since this is for school, i'm sure you can't go crazy with more advanced topics. Lets keep it simple with a switch/case.
You can map the letters to their corresponding number first, just use a switch/case to find the correct number depending on the letter.
For example:
String phoneNumber = "1800ab";
for(int x=0; x < phoneNumber.Length; x++)
{
if(Char.IsLetter(phoneNumber[x]))
{
switch(phoneNumber[x].ToString().ToLower())
{
case "a":
case "b":
case "c":
//This is number 2!
break;
}
}
}
String already implements IEnumerable<char> - so no need to "break up" there.
Mapping of something to something (like letter code to matching number) is generally done with map (associative array) types (in C#/.Net it is Dictionary) that provide mapping one value ("key") to corresponding "value" - consider using that.
string letter1 = AskuserforInput("first letter");
string number1 = SwitchMethod(letter1);
string letter2 = AskuserforInput("second letter");
string number2 = SwitchMethod(letter2);
string letter3 = AskuserforInput("third letter");
string number3 = SwitchMethod(letter3);
string letter4 = AskuserforInput("fouth letter");
string number4 = SwitchMethod(letter4);
string letter5 = AskuserforInput("fifth letter");
string number5 = SwitchMethod(letter5);
string letter6 = AskuserforInput("sixth letter");
string number6 = SwitchMethod(letter6);
string letter7 = AskuserforInput("seventh letter");
string number7 = SwitchMethod(letter7);
string letter8 = AskuserforInput("eigth letter");
string number8 = SwitchMethod(letter8);
string letter9 = AskuserforInput("ninth letter");
string number9 = SwitchMethod(letter9);
string letter10 = AskuserforInput("tenth letter");
string number10 = SwitchMethod(letter10);
//declaring strings
Console.WriteLine("This is the original letter phone digits");
Console.WriteLine("({0}{1}{2})) {3}{4}{5} - {6}{7}{8}{9} ", letter1,letter2, letter3, letter4, letter5, letter6, letter7, letter8, letter9, letter10);//continue this
Console.WriteLine("The actual numbers" );
Console.WriteLine("({0}{1}{2})) {3}{4}{5} - {6}{7}{8}{9} ", number1, number2, number3, number4, number5, number6, number7, number8, number9, number10);//continue this
Console.Read();
#region End Program
//wait for program to acknowledge results
Console.BackgroundColor = ConsoleColor.White;
Console.ForegroundColor = ConsoleColor.Red;
Console.WriteLine("\n\nPlease hit ENTER to end program. . .");
Console.Read();
#endregion
Console.Read();
//also pulled this back up from a previous program
}
public static string SwitchMethod(string x)
{
string y = "*";
switch (x)
{
case "0":
y = "0";
break;
case "1":
y = "1";
break;
case "A":
case "a":
case "B":
case "b":
case "C":
case "c":
case "2":
y = "2";
break;
case "D":
case "d":
case "E":
case "e":
case "F":
case "f":
case "3":
y = "3";
break;
case "G":
case "g":
case "H":
case "h":
case "I":
case "i":
case "4":
y = "4";
break;
case "J":
case "j":
case "K":
case "k":
case "L":
case "l":
case "5":
y = "5";
break;
case "M":
case "m":
case "N":
case "n":
case "O":
case "o":
case "6":
y = "6";
break;
case "P":
case "p":
case "Q":
case "q":
case "R":
case "r":
case "S":
case "s":
case "7":
y = "7";
break;
case "T":
case "t":
case "U":
case "u":
case "V":
case "v":
case "8":
y = "8";
break;
case "W":
case "w":
case "X":
case "x":
case "Y":
case "y":
case "Z":
case "z":
case "9":
y ="9";
break;
default:
Console.WriteLine("knucklehead, not a letter");
Console.WriteLine("an '*' will show up");
break;
//used cases, next will use to.lower
//Lynch helped
}
return y;
}
public static string AskuserforInput(string x)
{
Console.WriteLine("\nPlease type {0}", x);
String input = Console.ReadLine();
return input;
}
I'm sure someone can think of a better way, but you could loop through each digit and pass it to this function:
int Asc(char ch)
{
//Return the character value of the given character
return (int)Encoding.ASCII.GetBytes(ch)[0];
}
Then just assign a number based on which ASCII character is returned.
Related
public class ChineseZodiac
{
public static void Main(String[] args)
{
Console.Write("Enter a year: ");
var year = Convert.ToInt64(Console.ReadLine());
switch (year % 12)
{
case 0:
Console.WriteLine("monkey");
break;
case 1:
Console.WriteLine("rooster");
break;
case 2:
Console.WriteLine("dog");
break;
case 3:
Console.WriteLine("pig");
break;
case 4:
Console.WriteLine("rat");
break;
case 5:
Console.WriteLine("ox");
break;
case 6:
Console.WriteLine("tiger");
break;
case 7:
Console.WriteLine("rabbit");
break;
case 8:
Console.WriteLine("dragon");
break;
case 9:
Console.WriteLine("snake");
break;
case 10:
Console.WriteLine("horse");
break;
case 11:
Console.WriteLine("sheep");
break;
}
}
}
I'm trying to get the formula in the switch statement block to output a zodiac sign based on the user's input. I'm also supposed to have the switch statement converted to a switch expression with the same results. I was able to run it without any errors in VS Code as a switch statement but I'm confused about the difference between a switch statement and a switch expression.
Switch expressions return a value, so you couldn't do exactly what you're doing now (since the action is happening within the switch), but you could use it to return the string and then display it:
var yearMod12 = year % 12;
var yearOf = yearMod12 switch
{
0 => "monkey",
1 => "rooster",
...
};
Console.WriteLine(yearOf);
An enum or Dictionary<int, string> would be a good choice for this type of mapping as well.
I suggest extracting model (animals) into a collection; try keeping data and actions separatedly:
public class ChineseZodiac {
// Model (data): Zodiac animals
private static readonly IReadOnly<string> s_Animals = new string[] {
"monkey", "rooster", "dog",
"pig", "rat", "ox",
"tiger", "rabbit", "dragon",
"snake", "horse", "sheep",
};
// An action which is based on the model
public static void Main(String[] args) {
Console.Write("Enter a year: ");
Console.WriteLine(s_Animals[int.Parse(Console.ReadLine()) % s_Animals.Count]);
}
}
I am trying to make the enclosed subroutine more performant using NET framework 4.6.1 although I will eventually port it to net core 2.2 .
It may run up to 250,000 times when parsing a file.
Using Visual Studio Performance Analyzer I see this routine seems to have a fairly high relative cost in the whole parsing process.
The code is part of a parsing program whose input is a binary file that contains some very old record formats that contain over-signed numbers.
Over-signed Numbers (background)
Instead of a minus sign and in order to save space the last digit is made a letter if the number is negative. Its a very old standard dating back to when computers had limited memory and fixed width records were required for performance.
When parsing I need to convert the last letter back to a number and make the number negative
Some examples of input and output of the routine
00056K = -562
00032N = -325
Current Code (slow)
private int ConvertOverSign(string overSignedString)
{
switch(overSignedString.Substring(overSignedString.Length -1,1))
{
case " ":
return 0;
case "J":
return -Convert.ToInt32(overSignedString.Substring(0,overSignedString.Length -1) + "1");
case "K":
return -Convert.ToInt32(overSignedString.Substring(0,overSignedString.Length -1) + "2");
case "L":
return -Convert.ToInt32(overSignedString.Substring(0,overSignedString.Length -1) + "3");
case "M":
return -Convert.ToInt32(overSignedString.Substring(0,overSignedString.Length -1) + "4");
case "N":
return -Convert.ToInt32(overSignedString.Substring(0,overSignedString.Length -1) + "5");
case "O":
return -Convert.ToInt32(overSignedString.Substring(0,overSignedString.Length -1) + "6");
case "P":
return -Convert.ToInt32(overSignedString.Substring(0,overSignedString.Length -1) + "7");
case "Q":
return -Convert.ToInt32(overSignedString.Substring(0,overSignedString.Length -1) + "8");
case "R":
return -Convert.ToInt32(overSignedString.Substring(0,overSignedString.Length -1) + "9");
case "!":
return -Convert.ToInt32(overSignedString.Substring(0,overSignedString.Length -1) + "0");
default:
return Convert.ToInt32(overSignedString);
}
}
Not sure the below solution is fully equivalent to yours, but at least should give you a hint on how to make a very fast string-to-number parser.
private int ConvertOverSign(string overSignedString)
{
if (overSignedString == " ") return 0;
int value = 0;
for (int i = 0; i < overSignedString.Length; i++)
{
char ch = overSignedString[i];
switch (ch)
{
case '0':
case '1':
case '2':
case '3':
case '4':
case '5':
case '6':
case '7':
case '8':
case '9':
value = value * 10 + (ch - 0x30);
break;
case '!':
value *= 10;
return -value;
case 'J':
case 'K':
case 'L':
case 'M':
case 'N':
case 'O':
case 'P':
case 'Q':
case 'R':
value = value * 10 + (ch - 'I');
return -value;
}
}
return value;
}
Bear in mind that string manipulations (e.g. Substring) are typically heavy if you need performance.
Switch over the indexed character. Substring is actually alocating a new string and that is slow:
switch (overSignedString[Length - 1])
{
case ' ':
return 0;
case "J":
return ...
You might want to read this to see if its worth parsing the string inside each case avoiding Convert. There are faster ways.
Your method is slow because it generates a lot of string garbage.
You could improve it by comparing characters instead of strings, and perform multiplication of the resulting integer instead of appending strings and using a lookup instead of a switch:
private Dictionary<char, int> _additions = new Dictionary<char, int>
{
{ '!', 0 },
{ 'J', 1 },
{ 'K', 2 },
{ 'L', 3 },
{ 'M', 4 },
{ 'N', 5 },
{ 'O', 6 },
{ 'P', 7 },
{ 'Q', 8 },
{ 'R', 9 },
};
private int ConvertOverSign(string overSignedString)
{
var lastChar = overSignedString[overSignedString.Length -1];
if (lastChar == ' ')
{
return 0;
}
if (!_additions.TryGetValue(lastChar, out int addition))
{
return Convert.ToInt32(overSignedString);
}
var result = (Convert.ToInt32(overSignedString.Substring(0, overSignedString.Length - 1)) * -10) - addition;
return result;
}
I want to create a program that takes in a string and output just the numbers, hopefully using regex to save effort, here is the following code i have
public void main{
string str = "abc-123.44def";
string output = "";
bool setA = false;
StringBuilder stb = new StringBuilder();
for(int i=0; i<str.Length; i++){
switch(str[i]){
case 'b':
setA = foo();
break;
case 'c':
foo2();
break;
case '\d':
case '-':
case '.':
if(setA){
stb.Append(str[i]);
}
break;
default:
break;
}
}
output = stb.toString();
}
public void foo(){
return true;
}
Problem is, the editor gives me a error saying
Unrecognized Escape Sequence
on the '\d' part. Ive seen online sample codes where such usage is allowed so im not sure why my editor is not accepting this. Can someone explain to me what the problem is and how to solve it?
EDIT: It seems like my sample was alittle misleading. I cannot just take out the numbers from the strings by itself since other characters in the string calls different functions and the number characters i want to take out depends on some of them. I updated the code to correct the misinformation.
You can use the Char.IsDigit() to check if a char is a digit (as I mentioned in my first comment):
string str = "abc-123.44def";
string output = "";
bool setA = false;
StringBuilder stb = new StringBuilder();
for(int i=0; i<str.Length; i++){
switch(str[i]){
case 'b':
setA = foo();
break;
case 'c':
foo2();
break;
// case '\d': REMOVE IT
case '-':
case '.':
if(setA){
stb.Append(str[i]);
}
break;
default:
if (Char.IsDigit(str[i])) stb.Append(str[i]); // Add this
break;
}
}
output = stb.ToString();
}
Result:
Is this what you are looking for ?
Regex r = new Regex(#"\d+");
string s = "abc-123.44def";
var matches = r.Matches(s);
List<string> numbersOnly = new List<string>();
foreach (Match match in matches)
numbersOnly.Add(match.Value);
foreach (var number in numbersOnly)
Console.WriteLine(number);
//output:
//123
//44
Hey I´am trying to add two numbers together via switch case.
I have 3 inputs, number 1 and number 2. The 3rd input is the method which I´d like to calculate number 1 and 2 with(e.g +, -, *, /, etc...)
Now the problem is how do I create something like "this" ? I´ve tried this way, but it does not work...
Is it possible to make switch case like this : case %: ???
Thanks
string firstNumber;
string secondNumber;
string method;
//get numbers
Console.WriteLine ("Get first number");
firstNumber = Console.ReadLine ();
Console.WriteLine ("get 2nd number");
secondNumber = Console.ReadLine ();
Console.WriteLine ("the method to calculate with");
Console.WriteLine (" 1:\"*\"");
Console.WriteLine (" 2:\"/\"");
Console.WriteLine (" 3:\"+\"");
Console.WriteLine (" 4:\"-\"");
method = Console.ReadLine ();
//convert
int methodNew = Convert.ToInt32 (method);
int firstNumberNew = Convert.ToInt32 (firstNumber);
int secondNumberNew = Convert.ToInt32 (secondNumber);
switch (methodNew) {
case 1:
firstNumberNew *= secondNumberNew;
break;
default:
Console.WriteLine ("check the methods.");
break;
}
Console.WriteLine (methodNew);
Of course, you can read in a char and do a switch-case
for it:
int c = Console.Read(); // read from console
switch(c) {
case '/':
// work
break;
case '%':
// work
break;
case '*':
// work
break;
case '+':
// work
break;
}
First get the operator then use switch like this:
char method = Console.ReadKey().KeyChar;
double result = 0.0;
switch (method)
{
case '+':
result = firstNumberNew + secondNumberNew;
break;
case '-':
result = firstNumberNew - secondNumberNew;
break;
case '/':
result = firstNumberNew / secondNumberNew;
break;
case '%':
result = firstNumberNew % secondNumberNew;
break;
default:
Console.WriteLine("Invalid value, try again");
break;
}
Console.WriteLine(result);
It would be better if you change the type of firstNumberNew and secondNumberNew to double.Alşo you can use a while loop to force user to enter a valid character.
I have strings in a XML file that ment to be doubles (or float) such as:
<VIPair>
<voltage>+100mV</voltage>
<current>+1.05pA</current>
</VIPair>
<VIPair>
<voltage>+5.00mV</voltage>
<current>+0.0035nA</current>
</VIPair>
The first pair will be "0.1" Volt and "0.00000000000105" Ampere.
The second pair would be "0.005" Volt and "0.000000000035" Ampere.
How can I convert them to double of float in C#?
Thanks.
P.S: I already can read them from xml file and at the moment I retrive them as string.
Try with this:
// Read string (if you do not want to use xml)
string test = "<voltage>+100mV</voltage>";
string measure = test.Substring(test.IndexOf('>')+1);
measure = measure.Substring(0, measure.IndexOf('<')-1);
// Extract measure unit
string um = measure.Substring(measure.Length - 1);
measure = measure.Substring(0, measure.Length - 1);
// Get value
double val = Double.Parse(measure);
// Convert value according to measure unit
switch (um)
{
case "G": val *= 1E9; break;
case "M": val *= 1E6; break;
case "k": val *= 1E3; break;
case "m": val /= 1E3; break;
case "u": val /= 1E6; break;
case "n": val /= 1E9; break;
case "p": val /= 1E12; break;
}
Hi here is another version of what Marco has written.
string str = "1pV";
double factor;
double value;
switch (str[str.Length-2])
{
case 'M': factor = 1E6; break;
case 'm': factor = 1E-3; break;
case 'n': factor = 1E-9; break;
case 'p': factor = 1E-12; break;
default:
factor = 1; break;
}
value = double.Parse(str.Substring(0,str.Length-2)) * factor;
Assuming that the html text is already available to you. I have tried to do the same thing with one substring, switch case with characters instead of strings(This is a bit faster to comparing strings) and a double.parse. Hope someone comes up with a better version than this.
Remove the suffix string mV and nA using string.Substring or string.Remove() method and use double.TryParse() method to parse string to double.
If your values always have 2 chars on the end you could simple remove these and parse the number.
var newstring = fullstring.Substring(0, fullstring.Length - 2);
var number = double.Parse(newstring);