I have an array of names concatenated with an _ ex: string[] samples = ["Test_test","Test2_blah", "Test3_"].
At some point in my code I want to try and validate the value after the _ to check if it's empty or null, and if it is, remove it from the array like so :
string[] splitSample= samples[2].Split(new char[] { '_' }, 2);
if(!string.IsNullOrWhiteSpace(splitSample[1]))
The problem i'm running into is that splitSample[1] is "", when i check the length of the string it's 1, not 0 but in Visual Studio 2017 it shows empty quotes. Is there a way to actually see the value that's invisible or what's actually going on?
EDIT:
Here's a pic of the immediate window when i check the array value
Depending on how they get rendered, some Unicode characters can be invisible (i.e., "") when represented (e.g., "\u200C", "\u2063", and check this answer for more).
Now, your string has a length (>0), and you'd like to know what it actually represents. There are many ways to achieve this, one of them is to convert your string to hex. Here's an example using the Unicode character mentioned above:
static void Main(string[] args)
{
string invisibleChar = "\u200C";
string[] samples = { "Test_test", "Test2_blah", "Test3_" + invisibleChar };
string[] splitSample = samples[2].Split(new char[] { '_' }, 2);
// Prints "Test3_" (or "Test3_?" if you use Console.Write).
Debug.Print(samples[2]);
Debug.Print(splitSample.Length.ToString()); // 2
if (!string.IsNullOrWhiteSpace(splitSample[1]))
{
Debug.Print(splitSample[1].Length.ToString()); // 1
// Prints "" (or "?" in Console).
Debug.Print(splitSample[1]);
var hex = string.Join("", splitSample[1].Select(c => ((int)c).ToString("X2")));
// Prints "200C"
Debug.Print(hex);
}
Console.ReadLine();
}
Note that because you're using !string.IsNullOrWhiteSpace, you could be missing other Unicode characters (e.g., "\u00A0") because they're considered a white space. So, you should ask yourself whether you want to also check for these or not.
Hope that helps.
Related
I'm making a console adventure game for practice and I need to display a text when my character close to an object (at adjacent position). This string must be displayed until the character close to the object, but if it step further the text need to gone.
I tried this:
if (field[ver, hor + 1] == '█')
{
notice_detection = "DETECTION: '█' (right)";
Console.SetCursorPosition(37, 0);
Console.Write(notice_detection);
}
else
{
if (notice_detection != null)
{
notice_detection = " ";
Console.SetCursorPosition(37, 0);
Console.Write(notice_detection);
}
}
It's working but not too elegant. I'm sure a better solution exist.
My first try was to put 'notice_detection.Remove(0)' into else, but its didn't remove the already displayed string (by the way, why it's happened?).
Thanks!
The .Remove() method on strings returns a new string containing the remaining characters that are not removed starting from the given index. Calling it with 0 means that it removes everything from index 0 and returns the remaining, an empty string. If you write an empty string to the console, that looks like it does not did anything.
You can also replace your whitespacing hard coded string with a dynamic sized one filled with whitespaces like this:
var clearChars = new string(' ', notice_detection.Length);
Console.SetCursorPosition(37, 0);
Console.Write(clearChars);
Convert.ToString((input.Split(' ').Length + 1), 2).PadLeft(8, '0')
could anybody explain this line for me
It takes an input string (input), splits it on the space character (input.Split(' ')) (presumably to get the number of "words"), adds 1 to the .Length of the resulting array (not sure why), converts that number to a binary string (Convert.ToString(int, 2) will convert the int to a base-2 number and return it as a string), then pads the left side of the string with the 0 character until it's 8 characters long (.PadLeft(8, '0')).
My guess is that this might be used in some kind of encoding/decoding algorithm(?).
Here it is in action:
var inputStrings = new List<string>
{
"one",
"two words",
"this is three",
"this one is four",
"and this one has five"
};
foreach(var input in inputStrings)
{
var result = Convert.ToString((input.Split(' ').Length + 1), 2).PadLeft(8, '0');
Console.WriteLine($"{input.PadRight(22, ' ')} = {result}");
}
Console.Write("\nDone!\nPress any key to exit...");
Console.ReadKey();
Output
Split it up:
var stringItems = input.Split(' ');
Split the input string on spaces
int itemCount = stringItems.Length + 1;
However many items are in the collection, add one to that
var str = Convert.ToString(itemCount, 2);
Call some overload of Convert.ToString that takes two ints as parameters (I have no idea what this is). Consult Documentation as we have no idea what this overload does
It turns out that it:
Converts the value of a 32-bit signed integer to its equivalent string representation in a specified base
So we have a string from a 32 bit integer in base 2.
str.PadLeft(8, '0')
Make sure the string has 8 characters total, all 0's except the one's that existed already.
Looks like we created a pretty binary number. Though I have no idea what the meaning of it is without context.
Ok guys so I've got this issue that is driving me nuts, lets say that I've got a string like this "aaa,bbb,ccc,ddd,eee,fff,ggg" (with out the double quotes) and all that I want to get is a sub-string from it, something like "ddd,eee,fff,ggg".
I also have to say that there's a lot of information and not all the strings look the same so i kind off need something generic.
thank you!
One way using split with a limit;
string str = "aaa,bbb,ccc,ddd,eee,fff,ggg";
int skip = 3;
string result = str.Split(new[] { ',' }, skip + 1)[skip];
// = "ddd,eee,fff,ggg"
I would use stringToSplit.Split(',')
Update:
var startComma = 3;
var value = string.Join(",", stringToSplit.Split(',').Where((token, index) => index > startComma));
Not really sure if all things between the commas are 3 length. If they are I would use choice 2. If they are all different, choice 1. A third choice would be choice 2 but implement .IndexOf(",") several times.
Two choices:
string yourString="aaa,bbb,ccc,ddd,eee,fff,ggg";
string[] partsOfString=yourString.Split(','); //Gives you an array were partsOfString[0] is "aaa" and partsOfString[1] is "bbb"
string trimmed=partsOfString[3]+","+partsOfString[4]+","+partsOfString[5]+","+partsOfSting[6];
OR
//Prints "ddd,eee,fff,ggg"
string trimmed=yourString.Substring(12,14) //Gets the 12th character of your string and goes 14 more characters.
So I'm writing some code and using RegistryKey.GetValue and I can't seem to get it to return the proper string array. I would use RegSaveKeyEx except I need to change the location of where the keys are being saved to in the reg file I'm creating.
The MultiString I'm querying has two lines in it, : and a blank line. Regedit gives hex(7):3a,00,00,00,00,00 for the reg file export of said value. This is correct. 3a would be :, then a null, two nulls for the blank line and finally two more nulls to signify the end of the value. My code is giving hex(7):3a,00,00,00, which would be a : and the double-null EOL characters on a MultiString. When imported back into the registry hex(7):3a,00,00,00 is only a :, the blank line is missing.
If I import hex(7):3a,00,00,00,00,00 then view the value in regedit, I see : and a blank line. This is correct and this is what I want my code to do.
When I query this value with RegistryKey.GetValue in C# 4.0 I get the a string[] with just one element, the :.
For other MultiString values I get an array containing an element for every line, as I would expect.
RegistryKey.GetValue doesn't return anything for the blank line. It doesn't return a null, a blank string in the array, nothing.
On everything except blank lines it returns exactly the same result as regedit export. What needs to be changed to have it return an array that includes the blank line?
Here's my code if that's helpful:
private static string RegMultiStringExtraction(RegistryKey UsersSubKey, string Key)
{
string[] InputStrs = (string[])UsersSubKey.GetValue(Key, Environment.NewLine, RegistryValueOptions.DoNotExpandEnvironmentNames);
StringBuilder sb = new StringBuilder();
foreach (string str in InputStrs)
{
char[] Values = str.ToCharArray();
foreach (char letter in Values)
{
int ValueInt = Convert.ToInt32(letter);
sb.Append(ValueInt.ToString("x"));
sb.Append(",00,");
if (Values.Length == 0)
{
if (sb.Length == 0)
{
sb.Append("00,");
}
else if (sb.Length > 1)
{
sb.Append(",00,");
}
}
}
sb.Append("00,00,");
}
string Value = ('"' + Key.ToString() + #"""=" + "hex(7):" + sb.ToString().TrimEnd(','));
return Value;
}
Double null-terminated strings cannot contain empty lines. An attempt to include empty lines means including two consecutive nulls, and that is interpreted as termination rather than an empty line. Raymond Chen discussed this quirk much more eloquently that I can.
Perhaps you can save to REG_SZ and use Environment.NewLine as a delimiter.
I have a string when a telephone number is inputted - there is a mask so it always looks like "(123) 456-7890" - I'd like to take the formatting out before saving it to the DB.
How can I do that?
One possibility using linq is:
string justDigits = new string(s.Where(c => char.IsDigit(c)).ToArray());
Adding the cleaner/shorter version thanks to craigmoliver
string justDigits = new string(s.Where(char.IsDigit).ToArray())
You can use a regular expression to remove all non-digit characters:
string phoneNumber = "(123) 456-7890";
phoneNumber = Regex.Replace(phoneNumber, #"[^\d]", "");
Then further on - depending on your requirements - you can either store the number as a string or as an integer. To convert the number to an integer type you will have the following options:
// throws if phoneNumber is null or cannot be parsed
long number = Int64.Parse(phoneNumber, NumberStyles.Integer, CultureInfo.InvariantCulture);
// same as Int64.Parse, but returns 0 if phoneNumber is null
number = Convert.ToInt64(phoneNumber);
// does not throw, but returns true on success
if (Int64.TryParse(phoneNumber, NumberStyles.Integer,
CultureInfo.InvariantCulture, out number))
{
// parse was successful
}
Since nobody did a for loop.
long GetPhoneNumber(string PhoneNumberText)
{
// Returns 0 on error
StringBuilder TempPhoneNumber = new StringBuilder(PhoneNumberText.Length);
for (int i=0;i<PhoneNumberText.Length;i++)
{
if (!char.IsDigit(PhoneNumberText[i]))
continue;
TempPhoneNumber.Append(PhoneNumberText[i]);
}
PhoneNumberText = TempPhoneNumber.ToString();
if (PhoneNumberText.Length == 0)
return 0;// No point trying to parse nothing
long PhoneNumber = 0;
if(!long.TryParse(PhoneNumberText,out PhoneNumber))
return 0; // Failed to parse string
return PhoneNumber;
}
used like this:
long phoneNumber = GetPhoneNumber("(123) 456-7890");
Update
As pr commented many countries do have zero's in the begining of the number, if you need to support that, then you have to return a string not a long. To change my code to do that do the following:
1) Change function return type from long to string.
2) Make the function return null instead of 0 on error
3) On successfull parse make it return PhoneNumberText
You can make it work for that number with the addition of a simple regex replacement, but I'd look out for higher initial digits. For example, (876) 543-2019 will overflow an integer variable.
string digits = Regex.Replace(formatted, #"\D", String.Empty, RegexOptions.Compiled);
Aside from all of the other correct answers, storing phone numbers as integers or otherwise stripping out formatting might be a bad idea.
Here are a couple considerations:
Users may provide international phone numbers that don't fit your expectations. See these examples So the usual groupings for standard US numbers wouldn't fit.
Users may NEED to provide an extension, eg (555) 555-5555 ext#343 The # key is actually on the dialer/phone, but can't be encoded in an integer. Users may also need to supply the * key.
Some devices allow you to insert pauses (usually with the character P), which may be necessary for extensions or menu systems, or dialing into certain phone systems (eg, overseas). These also can't be encoded as integers.
[EDIT]
It might be a good idea to store both an integer version and a string version in the database. Also, when storing strings, you could reduce all punctuation to whitespace using one of the methods noted above. A regular expression for this might be:
// (222) 222-2222 ext# 333 -> 222 222 2222 # 333
phoneString = Regex.Replace(phoneString, #"[^\d#*P]", " ");
// (222) 222-2222 ext# 333 -> 2222222222333 (information lost)
phoneNumber = Regex.Replace(phoneString, #"[^\d]", "");
// you could try to avoid losing "ext" strings as in (222) 222-2222 ext.333 thus:
phoneString = Regex.Replace(phoneString, #"ex\w+", "#");
phoneString = Regex.Replace(phoneString, #"[^\d#*P]", " ");
Try this:
string s = "(123) 456-7890";
UInt64 i = UInt64.Parse(
s.Replace("(","")
.Replace(")","")
.Replace(" ","")
.Replace("-",""));
You should be safe with this since the input is masked.
You could use a regular expression or you could loop over each character and use char.IsNumber function.
You would be better off using regular expressions. An int by definition is just a number, but you desire the formatting characters to make it a phone number, which is a string.
There are numerous posts about phone number validation, see A comprehensive regex for phone number validation for starters.
As many answers already mention, you need to strip out the non-digit characters first before trying to parse the number. You can do this using a regular expression.
Regex.Replace("(123) 456-7890", #"\D", String.Empty) // "1234567890"
However, note that the largest positive value int can hold is 2,147,483,647 so any number with an area code greater than 214 would cause an overflow. You're better off using long in this situation.
Leading zeros won't be a problem for North American numbers, as area codes cannot start with a zero or a one.
Alternative using Linq:
string phoneNumber = "(403) 259-7898";
var phoneStr = new string(phoneNumber.Where(i=> i >= 48 && i <= 57).ToArray());
This is basically a special case of C#: Removing common invalid characters from a string: improve this algorithm. Where your formatng incl. White space are treated as "bad characters"
'you can use module / inside sub main form VB.net
Public Function ClearFormat(ByVal Strinput As String) As String
Dim hasil As String
Dim Hrf As Char
For i = 0 To Strinput.Length - 1
Hrf = Strinput.Substring(i, 1)
If IsNumeric(Hrf) Then
hasil &= Hrf
End If
Next
Return Strinput
End Function
'you can call this function like this
' Phone= ClearFormat(Phone)
public static string DigitsOnly(this string phoneNumber)
{
return new string(
new[]
{
// phoneNumber[0], (
phoneNumber[1], // 6
phoneNumber[2], // 1
phoneNumber[3], // 7
// phoneNumber[4], )
// phoneNumber[5],
phoneNumber[6], // 8
phoneNumber[7], // 6
phoneNumber[8], // 7
// phoneNumber[9], -
phoneNumber[10], // 5
phoneNumber[11], // 3
phoneNumber[12], // 0
phoneNumber[13] // 9
});
}