c# - How to convert from int to short? - c#

Doing an exercise where the output is different from the input.
For example if I input the number "6" into the console the output will be 54. What is the reason behind the output and how could I get the same numer as input?
{
int intVal;
short ShortVal;
intVal = Console.Read();
ShortVal = (short)intVal;
Console.WriteLine("{0}", ShortVal);
}
}

The answer is in the documentation for Console.Read:
Returns [...] The next character from the input stream, or negative one (-1) if there are currently no more characters to be read.
It is written a bit sloppily, because technically it returns the Unicode character code of the character.[1]
If you type in the character 6, what is the ordinal Unicode character value for this character? It's 54 (hex 0x0036; think of ASCII codes, but the encoding not being ASCII but rather Unicode). And that's precisely what you are seeing/getting here.
If you want to get the numeric value of the digit the character is representing (which is not the same as the numerical Unicode character code), take a look at the Unicode character codes for the characters 0...9. They occupy the character code range from 0x0030 (for the '0' character) to 0x0039 (for the 9 character). It shouldn't be hard to notice that you could simply subtract the Unicode character code of the 0 character to get the value of the digit these characters represent:
intVal = Console.Read();
if (intVal < '0' || intVal > '9')
{
Console.WriteLine("Not a numerical digit.");
}
else
{
var digitValue = intVal - '0';
Console.WriteLine("{0}", digitValue);
}
Now, this hopefully helps furthering understanding of character codes. However, the example code i have given here could be written differently, as the char type has a convenient method which provides the digit value of characters which represent digits (or represent numerical values, like roman numerals for example):
intVal = Console.Read();
if (intVal <= -1)
{
Console.WriteLine("No character entered");
}
else
{
var digitValue = char.GetNumericValue((char) intVal);
if (digitValue < 0)
{
Console.WriteLine("Not a numerical digit.");
}
else
{
Console.WriteLine("{0}", digitValue);
}
}
[1] If the method were to return a character, its return type would be char and not int. Although, the char type can be converted/cast to a numeric value such as int or short and back to get a characters Unicode character value and vice versa, so this distinction of characters vs. Unicode character code values seldomly matters in practical situations. However, here it may be useful to make this distinction to get a better understanding of what you observed.

Related

Convert convert int to alphabetical value

i would like to convert int's between 1-26 to the corresponding alphabetical char letter
i saw somewhere i could use char outPut = (char)currentValue; or Convert.ToChar(currentValue however both do not seem to work. i am testing this by having the program print the char to the console. both attempts have resulted in a empty character being printed
i am making a program that takes in a char letter, converts it to an int to do some maths to it and then converts the final int back to a char letter and prints the char to the console
char outPut = (char)currentValue;
would give you a char that represents some whitespace character (since those are represented as integers up to 32.)
What you actually want is a char representing a letter. The following code will give you the ith letter of the alphabet in lowercase:
char c = (char)((int)'a' + i - 1);
Or in uppercase:
char c = (char)((int)'A' + i - 1);
It uses the fact that letters are represented by consecutive integers.
You can offset by a character you want. In this case, I use 'a'.
Console.WriteLine((char)(5 + 'a'));
As your range starts with 1, you need to use 'a'-1.
int and char can be converted back and forth by using the ASCII table
ASCII value for A is 65. So you can get char A by doing
char a = (char) 65;
to convert it back using the 1-26 representation just do
int num = a - 65 + 1;
You would need to do some boundary check to make sure the number is within range of course.

How to validate 'live' input field with Regex?

Is there a way to validate 'live' input field using Regex in C#?
'live' means that I don't validate complete string, I want to validate the string while it's typed.
For example, I want my string to match the next pattern lalala111#alalala123, so I have to check each new char - is it # ? if it's # then is there a # already in the string? if yes, then I return a null, if no, then I return the char. And of course I have to check chars - is it letter or digit? if yes, then ok, if not, then not ok.
I hope you got my idea.
At now I have this code
private char ValidateEmail(string input, int charIndex, char charToValidate)
{
if (char.IsLetterOrDigit(charToValidate) &&
!(charToValidate >= 'а' && charToValidate <='я') &&
!(charToValidate >= 'А' && charToValidate <= 'Я') ||
charToValidate =='#' ||
"!#$%&'*+-/=?^_`{|}~#.".Contains(charToValidate.ToString()))
{
if ((charToValidate == '#' && input.Contains("#")) ||
(!input.Contains("#") && charIndex>=63) ||
(input.Contains("#") && charIndex >= 192))
return '\0';
}
else
{
return '\0';
}
return char.ToUpper(charToValidate);
}
it allows only latin letters with digits and some special characters, and also it allows first part of the string (before #) to have only 64 letters, and the second part (after #) to have only 128 letters, but the code looks ugly, don't it? So I want to do all these checks in one beauty regular expression.
lYou have to use the following code:
Declare this line at top:
System.Text.RegularExpressions.Regex remail = new System.Text.RegularExpressions.Regex(#"^([a-zA-Z0-9_\-\.]+)#((\[[0-9]{1,3}\.[0-9]{1,3}\.[0-9]{1,3}\.)|(([a-zA-Z0-9\-]+\.)+))([a-zA-Z]{2,4}|[0-9]{1,3})(\]?)$");
next either on button click or leave event pass the following code to check
if (textemail.Text != "" && !remail.IsMatch(textemail.Text))
{
errorProvider1.Clear();
textemail.Focus();
errorProvider1.SetError(textemail, "Wrong Email ID");
MessageBox.Show("Wrong Email ID");
textemail.SelectAll();
return;
}
After a character has been typed, you want the string that has been entered to match one of the following:
between 1 and 64 (inclusive) acceptablecharacters.
between 1 and 64 (inclusive) acceptable characters then an # character.
between 1 and 64 (inclusive) acceptable characters then an # character then 128 or fewer acceptable characters.
Note that the last two clauses can be combined to say:
between 1 and 64 (inclusive) acceptable characters then an # character then between 0 and 128 inclusive acceptable characters.
Hence the entire requirement can be expressed as:
between 1 and 64 (inclusive) acceptable characters, optionally followed by an # character then between 0 and 128 inclusive acceptable characters.
Where the definition of "acceptable characters" is not at all clear from the question. The code within ValidateEmail does range checks of 'a' to 'я' and of 'А' to 'Я'. It also checks "!#$%&'*+-/=?^_{|}~#.".Contains(...)`.
The text below assumes acceptable characters actually means the 26 letters, upper and lower case, plus the 10 digits.
The required regular expression is then ^\w{1,64}(#\w{0,128})?$
This regular expression can then be used to check the concatenation of the already validated input text plus the character just typed.
If additional characters are wanted to be considered as acceptable then change the \w, there are two of them. For example if underscores (_) and hyphens (-) are to be allowed then change both \ws to be [\w_-].

Why Char.IsDigit returns true for chars which can't be parsed to int?

I often use Char.IsDigit to check if a char is a digit which is especially handy in LINQ queries to pre-check int.Parse as here: "123".All(Char.IsDigit).
But there are chars which are digits but which can't be parsed to int like ۵.
// true
bool isDigit = Char.IsDigit('۵');
var cultures = CultureInfo.GetCultures(CultureTypes.SpecificCultures);
int num;
// false
bool isIntForAnyCulture = cultures
.Any(c => int.TryParse('۵'.ToString(), NumberStyles.Any, c, out num));
Why is that? Is my int.Parse-precheck via Char.IsDigit thus incorrect?
There are 310 chars which are digits:
List<char> digitList = Enumerable.Range(0, UInt16.MaxValue)
.Select(i => Convert.ToChar(i))
.Where(c => Char.IsDigit(c))
.ToList();
Here's the implementation of Char.IsDigit in .NET 4 (ILSpy):
public static bool IsDigit(char c)
{
if (char.IsLatin1(c))
{
return c >= '0' && c <= '9';
}
return CharUnicodeInfo.GetUnicodeCategory(c) == UnicodeCategory.DecimalDigitNumber;
}
So why are there chars that belong to the DecimalDigitNumber-category("Decimal digit character, that is, a character in the range 0 through 9...") which can't be parsed to an int in any culture?
It's because it is checking for all digits in the Unicode "Number, Decimal Digit" category, as listed here:
http://www.fileformat.info/info/unicode/category/Nd/list.htm
It doesn't mean that it is a valid numeric character in the current locale. In fact using int.Parse(), you can ONLY parse the normal English digits, regardless of the locale setting.
For example, this doesn't work:
int test = int.Parse("٣", CultureInfo.GetCultureInfo("ar"));
Even though ٣ is a valid Arabic digit character, and "ar" is the Arabic locale identifier.
The Microsoft article "How to: Parse Unicode Digits" states that:
The only Unicode digits that the .NET Framework parses as decimals are the ASCII digits 0 through 9, specified by the code values U+0030 through U+0039. The .NET Framework parses all other Unicode digits as characters.
However, note that you can use char.GetNumericValue() to convert a unicode numeric character to its numeric equivalent as a double.
The reason the return value is a double and not an int is because of things like this:
Console.WriteLine(char.GetNumericValue('¼')); // Prints 0.25
You could use something like this to convert all numeric characters in a string into their ASCII equivalent:
public string ConvertNumericChars(string input)
{
StringBuilder output = new StringBuilder();
foreach (char ch in input)
{
if (char.IsDigit(ch))
{
double value = char.GetNumericValue(ch);
if ((value >= 0) && (value <= 9) && (value == (int)value))
{
output.Append((char)('0'+(int)value));
continue;
}
}
output.Append(ch);
}
return output.ToString();
}
Decimal digits are 0 to 9, but they have many representations in Unicode. From Wikipedia:
The decimal digits are repeated in 23 separate blocks
MSDN specifies that .NET only parses Latin numerals:
However, the only numeric digits recognized by parsing methods are the basic Latin digits 0-9 with code points from U+0030 to U+0039

How can I limit user input to a single alpha character in c#?

I'm using the following code to accept user input. I want to limit user input to a single alpha (a-z) character only. I'm finding a lot of validations using IsNumber to validate integer input, and a lot of information about using a regex on an input String, but I've been unable to uncover how I would be able to restrict input possibilities with this code. Can someone point me in the right direction?
public char promptForGuess()
{
Console.Write("\nGuess a letter: ");
String pre = Console.ReadKey().Key.ToString();
string pre2 = pre.ToUpper();
char pre3 = Convert.ToChar(pre2);
}
You cannot limit the user only put in a-z chars on the console - you have to check the input, he can write in any character (just think about when the input is redirected to your program from a file with <, e.g. yourapp.exe < input.dat ).
But its easy to check a character is lowercase a-z letter. E.g. with plain, ASCII, C tactic (I will use your defined variables):
if('A' <= pre3 && pre3 <'Z') { // pre3 was made upper in your code
// input OK
} else {
// input NOK
}
With regex:
Regex r = new Regex(#"^[a-zA-Z]$");
return r.IsMatch(pre);
If you cannot allow case-insensitive characters, just change the code I wrote.
Anyway, I think you need Console.Read() (ReadKey also read keys like arrows, F1-F12 etc..., so ALL keys, even tab and caps lock). Refer to MSDN: http://msdn.microsoft.com/en-us/library/system.console.read.aspx
And maybe you should use this function, if you would support unicode letters: http://msdn.microsoft.com/en-us/library/yyxz6h5w.aspx
Note that unicode letters are usually not one bytes! But char can store it. These letters are for example beautiful Hungarian letters with acutes and these king of things: á, é, ő, ű, ö, ü etc (but also French have a lot, and also Dutch etc...)
For judging a valid string, you could judge by
str.length() == 1 && str[0] >= 'a' && str[1] <= 'z'
and for restricting input possibilities, you could write a loop that loops if the input is invalid.
pre = read();
while (!valid(pre))
pre = read();
why don't you use Regex
if (Regex.IsMatch(pre[0].ToString(), #"[A-Za-z]"))
{
//do someting
}
else
{
//do someting
}

Why does Visual Studio add a slash at the start of an int, when it's converted to char?

Why does Visual Studio add a slash at the start of an int, when it's converted to char?
When I convert int 0 to char, it changes to \0. Why? I need char 0.
\0 is just how Visual Studio shows the character null in debug windows.
The \ is an escape sequence, so \0 tells you this is the null character.
If you want the character 0, you need to use the correct ASCII value for that character - 48.
char n = (char)0; // The _null_ character, displayed \0
char z = (char)48; // The character 0
char z2 = '0'; // The character 0, using a character literal
To recive char '0' convert int 48 to char or assign simply by
var c = '0';
When you convert int 0 to char you receive ASCII symbol at 0 decimal position, which is null. Char '0' has ASCII value as 48, so converting 48 to char will result in '0' char.
Check ASCII symbols and their decimal representation at ASCII Table. Remember, that anytime you convert int to char, it takes this ASCII table into account
If you want the char 0, you need to use either a character literal:
'0'
or, you can use
0.ToString()[0]
Depending on where the value is coming from.
\0 is an escape sequence for the character with the ASCII value 0, and this is different from the character for the digit 0.

Categories