I have multiple textboxes which asks the user to enter coordinates in the form (x,y) such as 5.5,7. I want to validate both the x and y coordinate to make sure that they are numbers. I was thinking that I could maybe split the coordinates by comma and validate each seperatly, but I think doing it that way would be long winded?.
private bool CoordinatesValidation()
{
bool status = true;
decimal temp;
foreach (TextBox tb in pointsPanel.Controls)
{
if (!decimal.TryParse(tb.Text, out temp))
{
errorProvider1.SetError(tb, "Invalid value, please enter a number!");
status = false;
}
else
{
errorProvider1.SetError(tb, "");
}
}
return status;
}
You can also use a regular expression to check if the format is as follows:
(\d+\.?\d+),\s*(\d+\.?\d+)
Which means:
Match on multiple decimals (\d+)
Match with a . dot in the middle
Match a comma between two decimals, with spaces, if there are any:
https://regexr.com/3vm63
Regex regex = new Regex(#"(\d+\.?\d+),\s*(\d+\.?\d+)");
Match match = regex.Match(tb.Text);
if(!match.Success)
{
//append the error message
}
You can leverage Object Orientation by introducing a Coordinate class that can handle the parsing and validation.
The advantage of this approach is that you can extend this class with additional functionality, e.g. by implementing IEquatable<Coordinate> or IComparable<Coordinate>.
public class Coordinate {
// Hidden parameterless ctor
private Coordinate() {}
// Public ctor requires two numbers
public Coordinate(decimal x, decimal y) : this() {
X = x;
Y = y;
}
public decimal? X { get; set; }
public decimal? Y { get; set; }
public const char AxisSeparator = ',';
public bool IsValid() {
return X.HasValue && Y.HasValue;
}
// Try to parse a coordinate text in the format "X.XX{AxisSeparator}Y.YY"
// If the parsing is not successful, returns false and error message as out variable
// Else returns true and the parsed Coordinate as out variable
public static bool TryParse(string input, out Coordinate result, out string errorMessage) {
errorMessage = string.Empty;
result = new Coordinate();
var parts = input.Split(AxisSeparator);
if (parts.Count() != 2) {
errorMessage = "Expected input in format 'X.XX, Y.YY' with '" + AxisSeparator + "' to separate X and Y coordinates.";
return false;
}
decimal x;
decimal y;
if (!decimal.TryParse(parts[0], out x)) {
errorMessage = "Expected input in format 'X.XX, Y.YY' with X.XX as number, but it was '" + parts[0] + "'.";
return false;
}
if (!decimal.TryParse(parts[1], out y)) {
errorMessage = "Expected input in format 'X.XX, Y.YY' with Y.YY as number, but it was '" + parts[1] + "'.";
return false;
}
result = new Coordinate(x, y);
return true;
}
public override string ToString() { return X.ToString() + AxisSeparator + " " + Y.ToString(); }
}
Usage example:
Coordinate coord = null;
string errorMessage = string.Empty;
var success = Coordinate.TryParse("3.14, 15.28b", out coord, out errorMessage);
if (!success) {
Console.WriteLine("Error: " + errorMessage);
Console.WriteLine("Coordinate is valid?: " + coord.IsValid());
}
else {
Console.WriteLine("Success: " + coord.ToString());
}
This usage (with the string "3.14, 15.28b") prints the message:
Error: Expected input in format 'X.XX, Y.YY' with Y.YY as number, but it was ' 15.28b'.
Coordinate is valid?: False
C# Fiddle for this example
Can't you mask the text boxes so that only numbers, or only a specified format, can be entered? Then you wouldn't have to check them after the fact. https://learn.microsoft.com/en-us/dotnet/api/system.windows.forms.maskedtextbox.mask?view=netframework-4.7.2
Related
I'm trying to make a simple calculator and its fully working but when I calculate without a = button, my program completely crashes and gives the error:
System.FormatException: 'Input string was not in correct format.'
This is the code that it throws an error to:
second = double.Parse(aNumber);
// the strings and doubles:
String aNumber = "";
double first = 0.0;
b will be true or false if the try parse worked
d will contain the double or 0 if it fails
change anum to a valid number to test.
String anum = "";
double d = 0.0;
bool b = double.TryParse(anum, out d);
double.Parse will throw an exception if the input is not valid. So you either need to use try catch - or the preferred way would be to use double.TryParse as below. The value of y below will be set to the value if TryParse returns true.
class Program
{
static void Main(string[] args)
{
// This will cause an exception
var someString = "SomeValue";
var x = double.Parse(someString); // Comment this line out to run this example
// This will work
double y;
if (double.TryParse(someString, out y))
{
Console.WriteLine(someString + " is a valid decimal");
}
else
{
Console.WriteLine(someString + " is not a valid decimal");
}
someString = "14.7";
if (double.TryParse(someString, out y))
{
Console.WriteLine(someString + " is a valid decimal");
}
else
{
Console.WriteLine(someString + " is not a valid decimal");
}
}
}
How can I parse C#-style generic type names of the format List<int> or Dictionary<string,int> or even more complex Dictionary<string,Dictionary<System.String,int[]>>. Assume that these names are strings and may not actually represent existing types. It should just as easily be be able to parse BogusClass<A,B,Vector<C>>. To be clear, I am NOT interested in parsing .NET internal type names of the format List`1[[System.Int32]], but actual C# type names as they would appear in the source code, with or without namespace qualifiers using dot notation.
Regular expressions are out because these are nested structures. I thought perhaps the System.CodeDom.CodeTypeReference constructor would parse it for me since it has string BaseType and CodeTypeReferenceCollection TypeArguments members, but those apparently need to be set manually.
CodeTypeReference is the kind of structure I need:
class TypeNameStructure
{
public string Name;
public TypeNameStructure[] GenericTypeArguments;
public bool IsGenericType{get;}
public bool IsArray{get;} //would be nice to detect this as well
public TypeNameStructure( string friendlyCSharpName )
{
//Parse friendlyCSharpName into name and generic type arguments recursively
}
}
Are there any existing classes in the framework to achieve this kind of type name parsing? If not, how would I go about parsing this?
Well, I had a lot of fun writing this little parsing class using Regex and named capture groups (?<Name>group).
My approach was that each 'type definition' string could be broken up as a set of the following: Type Name, optional Generic Type, and optional array marker '[ ]'.
So given the classic Dictionary<string, byte[]> you would have Dictionary as the type name and string, byte[] as your inner generic type string.
We can split the inner generic type on the comma (',') character and recursively parse each type string using the same Regex. Each successful parse should be added to the parent type information and you can build a tree hierarchy.
With the previous example, we would end up with an array of {string, byte[]} to parse. Both of these are easily parsed and set to part of Dictionary's inner types.
On ToString() it's simply a matter of recursively outputting each type's friendly name, including inner types. So Dictionary would output his type name, and iterate through all inner types, outputting their type names and so forth.
class TypeInformation
{
static readonly Regex TypeNameRegex = new Regex(#"^(?<TypeName>[a-zA-Z0-9_]+)(<(?<InnerTypeName>[a-zA-Z0-9_,\<\>\s\[\]]+)>)?(?<Array>(\[\]))?$", RegexOptions.Compiled);
readonly List<TypeInformation> innerTypes = new List<TypeInformation>();
public string TypeName
{
get;
private set;
}
public bool IsArray
{
get;
private set;
}
public bool IsGeneric
{
get { return innerTypes.Count > 0; }
}
public IEnumerable<TypeInformation> InnerTypes
{
get { return innerTypes; }
}
private void AddInnerType(TypeInformation type)
{
innerTypes.Add(type);
}
private static IEnumerable<string> SplitByComma(string value)
{
var strings = new List<string>();
var sb = new StringBuilder();
var level = 0;
foreach (var c in value)
{
if (c == ',' && level == 0)
{
strings.Add(sb.ToString());
sb.Clear();
}
else
{
sb.Append(c);
}
if (c == '<')
level++;
if(c == '>')
level--;
}
strings.Add(sb.ToString());
return strings;
}
public static bool TryParse(string friendlyTypeName, out TypeInformation typeInformation)
{
typeInformation = null;
// Try to match the type to our regular expression.
var match = TypeNameRegex.Match(friendlyTypeName);
// If that fails, the format is incorrect.
if (!match.Success)
return false;
// Scrub the type name, inner type name, and array '[]' marker (if present).
var typeName = match.Groups["TypeName"].Value;
var innerTypeFriendlyName = match.Groups["InnerTypeName"].Value;
var isArray = !string.IsNullOrWhiteSpace(match.Groups["Array"].Value);
// Create the root type information.
TypeInformation type = new TypeInformation
{
TypeName = typeName,
IsArray = isArray
};
// Check if we have an inner type name (in the case of generics).
if (!string.IsNullOrWhiteSpace(innerTypeFriendlyName))
{
// Split each type by the comma character.
var innerTypeNames = SplitByComma(innerTypeFriendlyName);
// Iterate through all inner type names and attempt to parse them recursively.
foreach (string innerTypeName in innerTypeNames)
{
TypeInformation innerType = null;
var trimmedInnerTypeName = innerTypeName.Trim();
var success = TypeInformation.TryParse(trimmedInnerTypeName, out innerType);
// If the inner type fails, so does the parent.
if (!success)
return false;
// Success! Add the inner type to the parent.
type.AddInnerType(innerType);
}
}
// Return the parsed type information.
typeInformation = type;
return true;
}
public override string ToString()
{
// Create a string builder with the type name prefilled.
var sb = new StringBuilder(this.TypeName);
// If this type is generic (has inner types), append each recursively.
if (this.IsGeneric)
{
sb.Append("<");
// Get the number of inner types.
int innerTypeCount = this.InnerTypes.Count();
// Append each inner type's friendly string recursively.
for (int i = 0; i < innerTypeCount; i++)
{
sb.Append(innerTypes[i].ToString());
// Check if we need to add a comma to separate from the next inner type name.
if (i + 1 < innerTypeCount)
sb.Append(", ");
}
sb.Append(">");
}
// If this type is an array, we append the array '[]' marker.
if (this.IsArray)
sb.Append("[]");
return sb.ToString();
}
}
I made a console app to test it, it seems to work with most cases I threw at it.
Here's the code:
class MainClass
{
static readonly int RootIndentLevel = 2;
static readonly string InputString = #"BogusClass<A,B,Vector<C>>";
public static void Main(string[] args)
{
TypeInformation type = null;
Console.WriteLine("Input = {0}", InputString);
var success = TypeInformation.TryParse(InputString, out type);
if (success)
{
Console.WriteLine("Output = {0}", type.ToString());
Console.WriteLine("Graph:");
OutputGraph(type, RootIndentLevel);
}
else
Console.WriteLine("Parsing error!");
}
static void OutputGraph(TypeInformation type, int indentLevel = 0)
{
Console.WriteLine("{0}{1}{2}", new string(' ', indentLevel), type.TypeName, type.IsArray ? "[]" : string.Empty);
foreach (var innerType in type.InnerTypes)
OutputGraph(innerType, indentLevel + 2);
}
}
And here's the output:
Input = BogusClass<A,B,Vector<C>>
Output = BogusClass<A, B, Vector<C>>
Graph:
BogusClass
A
B
Vector
C
There are some possible lingering issues, such as multidimensional arrays. It will more than likely fail on something like int[,] or string[][].
Answering own question. I wrote the following class achieve the results I need; give it a spin.
public class TypeName
{
public string Name;
public bool IsGeneric;
public List<ArrayDimension> ArrayDimensions;
public List<TypeName> TypeArguments;
public class ArrayDimension
{
public int Dimensions;
public ArrayDimension()
{
Dimensions = 1;
}
public override string ToString()
{
return "[" + new String(',', Dimensions - 1) + "]";
}
}
public TypeName()
{
Name = null;
IsGeneric = false;
ArrayDimensions = new List<ArrayDimension>();
TypeArguments = new List<TypeName>();
}
public static string MatchStructure( TypeName toMatch, TypeName toType )
{
return null;
}
public override string ToString()
{
string str = Name;
if (IsGeneric)
str += "<" + string.Join( ",", TypeArguments.Select<TypeName,string>( tn => tn.ToString() ) ) + ">";
foreach (ArrayDimension d in ArrayDimensions)
str += d.ToString();
return str;
}
public string FormatForDisplay( int indent = 0 )
{
var spacing = new string(' ', indent );
string str = spacing + "Name: " + Name + "\r\n" +
spacing + "IsGeneric: " + IsGeneric + "\r\n" +
spacing + "ArraySpec: " + string.Join( "", ArrayDimensions.Select<ArrayDimension,string>( d => d.ToString() ) ) + "\r\n";
if (IsGeneric)
{
str += spacing + "GenericParameters: {\r\n" + string.Join( spacing + "},{\r\n", TypeArguments.Select<TypeName,string>( t => t.FormatForDisplay( indent + 4 ) ) ) + spacing + "}\r\n";
}
return str;
}
public static TypeName Parse( string name )
{
int pos = 0;
bool dummy;
return ParseInternal( name, ref pos, out dummy );
}
private static TypeName ParseInternal( string name, ref int pos, out bool listTerminated )
{
StringBuilder sb = new StringBuilder();
TypeName tn = new TypeName();
listTerminated = true;
while (pos < name.Length)
{
char c = name[pos++];
switch (c)
{
case ',':
if (tn.Name == null)
tn.Name = sb.ToString();
listTerminated = false;
return tn;
case '>':
if (tn.Name == null)
tn.Name = sb.ToString();
listTerminated = true;
return tn;
case '<':
{
tn.Name = sb.ToString();
tn.IsGeneric = true;
sb.Length = 0;
bool terminated = false;
while (!terminated)
tn.TypeArguments.Add( ParseInternal( name, ref pos, out terminated ) );
var t = name[pos-1];
if (t == '>')
continue;
else
throw new Exception( "Missing closing > of generic type list." );
}
case '[':
ArrayDimension d = new ArrayDimension();
tn.ArrayDimensions.Add( d );
analyzeArrayDimension: //label for looping over multidimensional arrays
if (pos < name.Length)
{
char nextChar = name[pos++];
switch (nextChar)
{
case ']':
continue; //array specifier terminated
case ',': //multidimensional array
d.Dimensions++;
goto analyzeArrayDimension;
default:
throw new Exception( #"Expecting ""]"" or "","" after ""["" for array specifier but encountered """ + nextChar + #"""." );
}
}
throw new Exception( "Expecting ] or , after [ for array type, but reached end of string." );
default:
sb.Append(c);
continue;
}
}
if (tn.Name == null)
tn.Name = sb.ToString();
return tn;
}
}
If I run the following:
Console.WriteLine( TypeName.Parse( "System.Collections.Generic.Dictionary<Vector<T>,int<long[]>[],bool>" ).ToString() );
It correctly produces the following output, representing the TypeName as a string:
Name: System.Collections.Generic.Dictionary
IsGeneric: True
ArraySpec:
GenericParameters: {
Name: Vector
IsGeneric: True
ArraySpec:
GenericParameters: {
Name: T
IsGeneric: False
ArraySpec:
}
},{
Name: int
IsGeneric: True
ArraySpec: []
GenericParameters: {
Name: long
IsGeneric: False
ArraySpec: []
}
},{
Name: bool
IsGeneric: False
ArraySpec:
}
Let's say I have this code:
int i = 31240;
string Number = ((double)i / 1000).ToString("0.#k");
I get this result as a string for Number: 31,2k
And now, I wanna do the exact opposite, that is to take this string "31,2k" and take it back to 31240 or even to 31200, but I don't know how to do...
Any idea?
Someone said that was impossible.
BUT Finally I found the perfect way to achieve my goal. I post the solution for those who could be willing to know.
The use is simple, and it allows to make 2 kind of conversions:
Thousands, Example: 45831 <=> 45,8k <=> 45831
Millions, Example: 123852376 <=> 123,5m <=> 123852376
int i = (int)(Double.Parse(Number.Substring(0, Number.Length - 1)) * 1000);
We remove the k with Number.Substring(0, Number.Length - 1), transform it to double with Double.Parse, multiply by 1000 and in the end convert to int. The order of the things is very important! The first time I was doing (int)Double.Parse(Number.Substring(0, Number.Length - 1)) * 1000 that was converting to int before multiplying (so I got 31000 instead of 31200)
I'll add that if I had to write that code, I would sleep VERY much better if I used the Decimal.Parse instead of the Double.Parse (so I would be sure against the vagaries of floating points)
I'll add a better method:
int i2 = int.Parse(Number.Substring(0, Number.Length - 1).Replace(CultureInfo.CurrentCulture.NumberFormat.NumberDecimalSeparator, string.Empty)) * 100;
This is much more interesting. We remove the k as in the other method but this time we remove the , from the string too and we multiply by 100.
The interesting trick is that instead of simply ("bovinamente" in italian slang, as bovines would do) replace the , with an empty string, we get the current decimal separator (CultureInfo.CurrentCulture.NumberFormat.NumberDecimalSeparator) and we replace THAT with an empty string.
Clearly had we used another culture in composing the original string (for example the always good CultureInfo.InvariantCulture) we would use that to get the NumberDecimalSeparator
Here is the solution I went through:
public class StringFromInt
{
public enum FormatStyle
{
Kilo = 1000,
Mega = 1000000
}
public int Number;
public FormatStyle Format
{
get
{
switch (LimitValueBeforeConversion)
{
case 1000: return FormatStyle.Kilo;
case 1000000: return FormatStyle.Mega;
default:
throw new NotImplementedException("You must implement the code for this kind of value");
}
}
set
{
if (value == FormatStyle.Kilo)
{
LimitValueBeforeConversion = 1000;
}
else if (value == FormatStyle.Mega)
{
LimitValueBeforeConversion = 1000000;
}
}
}
public int LimitValueBeforeConversion
{ get; set; }
public static implicit operator int(StringFromInt s)
{
return s.Number;
}
public static implicit operator StringFromInt(int number)
{
StringFromInt s = new StringFromInt(number);
return s;
}
#region Constructors
public StringFromInt(int number, FormatStyle format)
{
this.Number = number;
Format = format;
}
public StringFromInt(int number)
: this(number, FormatStyle.Kilo)
{
if (number >= 1000000)
{
this.Format = FormatStyle.Mega;
}
}
#endregion
public override string ToString()
{
if (Number >= LimitValueBeforeConversion)
{
string formatString = "0.#k";
switch (Format)
{
case FormatStyle.Kilo:
formatString = "0.#k";
break;
case FormatStyle.Mega:
formatString = "0.#m";
break;
default:
throw new NotImplementedException("You must implement the code for this kind of value");
}
return ((double)Number / LimitValueBeforeConversion).ToString(formatString);
}
else
{
return Number.ToString();
}
}
}
And here is a test program:
class Program
{
static void Main(string[] args)
{
int i = 31240;
string StringRepresentation = ((double)i / 1000).ToString("0.#k");
int resultBackWithParse = int.Parse(StringRepresentation.Substring(0, StringRepresentation.Length - 1).Replace(CultureInfo.CurrentCulture.NumberFormat.NumberDecimalSeparator, string.Empty)) * 100;
Console.WriteLine("Base number: " + i.ToString());
Console.WriteLine(new string('-', 35));
Console.WriteLine("String representation: " + StringRepresentation);
Console.WriteLine("Int representation With Int.Parse: " + resultBackWithParse.ToString());
Console.WriteLine();
StringFromInt MySolutionNumber = i;
int resultBackWithStringFromInt = MySolutionNumber;
Console.WriteLine("String representation With StringFromInt: " + MySolutionNumber.ToString());
Console.WriteLine("Int representation With StringFromInt: " + resultBackWithStringFromInt);
Console.WriteLine(new string('=', 35) + "\n");
i = 123456789;
StringFromInt MyNumber = 123456789;
int resultBack = MyNumber;
Console.WriteLine("Base number: " + i.ToString());
Console.WriteLine(new string('-', 35));
Console.WriteLine("String representation With StringFromInt: " + MyNumber);
Console.WriteLine("Int representation With StringFromInt: " + resultBack);
Console.ReadKey(true);
}
}
As you can notice, there is no need to use the "new" initializer, I mean no need to do:
StringFromInt Number = new StringFromInt(YourNumber)
Thanks to the implicit operator, you can do:
StringFromInt Number = YourNumber
I don't know, but I think it's a good beginning, what do you think?
Anyway, I managed to do what I wanted, so for people who thought it couldn't be done, you see, that's possible :-)
Obviously this can be improved: this version works for thousands and millions only.
Greetings
I'd like to know on C# how to check if a string is a number (and just a number).
Example :
141241 Yes
232a23 No
12412a No
and so on...
Is there a specific function?
Look up double.TryParse() if you're talking about numbers like 1, -2 and 3.14159. Some others are suggesting int.TryParse(), but that will fail on decimals.
string candidate = "3.14159";
if (double.TryParse(candidate, out var parsedNumber))
{
// parsedNumber is a valid number!
}
EDIT: As Lukasz points out below, we should be mindful of the thread culture when parsing numbers with a decimal separator, i.e. do this to be safe:
double.TryParse(candidate, NumberStyles.AllowDecimalPoint, CultureInfo.InvariantCulture, out var parsedNumber)
If you just want to check if a string is all digits (without being within a particular number range) you can use:
string test = "123";
bool allDigits = test.All(char.IsDigit);
Yes there is
int temp;
int.TryParse("141241", out temp) = true
int.TryParse("232a23", out temp) = false
int.TryParse("12412a", out temp) = false
Hope this helps.
Use Int32.TryParse()
int num;
bool isNum = Int32.TryParse("[string to test]", out num);
if (isNum)
{
//Is a Number
}
else
{
//Not a number
}
MSDN Reference
Use int.TryParse():
string input = "141241";
int ouput;
bool result = int.TryParse(input, out output);
result will be true if it was.
Yep - you can use the Visual Basic one in C#.It's all .NET; the VB functions IsNumeric, IsDate, etc are actually static methods of the Information class. So here's your code:
using Microsoft.VisualBasic;
...
Information.IsNumeric( object );
int value;
if (int.TryParse("your string", out value))
{
Console.WriteLine(value);
}
This is my personal favorite
private static bool IsItOnlyNumbers(string searchString)
{
return !String.IsNullOrEmpty(searchString) && searchString.All(char.IsDigit);
}
Perhaps you're looking for the int.TryParse function.
http://msdn.microsoft.com/en-us/library/system.int32.tryparse.aspx
Many datatypes have a TryParse-method that will return true if it managed to successfully convert to that specific type, with the parsed value as an out-parameter.
In your case these might be of interest:
http://msdn.microsoft.com/en-us/library/system.int32.tryparse.aspx
http://msdn.microsoft.com/en-us/library/system.decimal.tryparse.aspx
int result = 0;
bool isValidInt = int.TryParse("1234", out result);
//isValidInt should be true
//result is the integer 1234
Of course, you can check against other number types, like decimal or double.
You should use the TryParse method for the int
string text1 = "x";
int num1;
bool res = int.TryParse(text1, out num1);
if (res == false)
{
// String is not a number.
}
If you want to validate if each character is a digit and also return the character that is not a digit as part of the error message validation, then you can loop through each char.
string num = "123x";
foreach (char c in num.ToArray())
{
if (!Char.IsDigit(c))
{
Console.WriteLine("character " + c + " is not a number");
return;
}
}
int.TryPasrse() Methode is the best way
so if the value was string you will never have an exception , instead of the TryParse Methode return to you bool value so you will know if the parse operation succeeded or failed
string yourText = "2";
int num;
bool res = int.TryParse(yourText, out num);
if (res == true)
{
// the operation succeeded and you got the number in num parameter
}
else
{
// the operation failed
}
string str = "123";
int i = Int.Parse(str);
If str is a valid integer string then it will be converted to integer and stored in i other wise Exception occur.
Starting with C# 7.0, you can declare the out variable in the argument
list of the method call, rather than in a separate variable
declaration. This produces more compact, readable code, and also
prevents you from inadvertently assigning a value to the variable
before the method call.
bool isDouble = double.TryParse(yourString, out double result);
https://learn.microsoft.com/en-us/dotnet/csharp/language-reference/keywords/out-parameter-modifier
You could use something like the following code:
string numbers = "numbers you want to check";
Regex regex = new Regex("^[0-9]+$"));
if (regex.IsMatch(numbers))
{
//string value is a number
}
public static void Main()
{
string id = "141241";
string id1 = "232a23";
string id2 = "12412a";
validation( id, id1, id2);
}
public static void validation(params object[] list)
{
string s = "";
int result;
string _Msg = "";
for (int i = 0; i < list.Length; i++)
{
s = (list[i].ToString());
if (string.IsNullOrEmpty(s))
{
_Msg = "Please Enter the value";
}
if (int.TryParse(s, out result))
{
_Msg = "Enter " + s.ToString() + ", value is Integer";
}
else
{
_Msg = "This is not Integer value ";
}
}
}
Try This
here i perform addition of no and concatenation of string
private void button1_Click(object sender, EventArgs e)
{
bool chk,chk1;
int chkq;
chk = int.TryParse(textBox1.Text, out chkq);
chk1 = int.TryParse(textBox2.Text, out chkq);
if (chk1 && chk)
{
double a = Convert.ToDouble(textBox1.Text);
double b = Convert.ToDouble(textBox2.Text);
double c = a + b;
textBox3.Text = Convert.ToString(c);
}
else
{
string f, d,s;
f = textBox1.Text;
d = textBox2.Text;
s = f + d;
textBox3.Text = s;
}
}
I'm not a programmer of particularly high skills, but when I needed to solve this, I chose what is probably a very non-elegant solution, but it suits my needs.
private bool IsValidNumber(string _checkString, string _checkType)
{
float _checkF;
int _checkI;
bool _result = false;
switch (_checkType)
{
case "int":
_result = int.TryParse(_checkString, out _checkI);
break;
case "float":
_result = Single.TryParse(_checkString, out _checkF);
break;
}
return _result;
}
I simply call this with something like:
if (IsValidNumber("1.2", "float")) etc...
It means that I can get a simple true/false answer back during If... Then comparisons, and that was the important factor for me. If I need to check for other types, then I add a variable, and a case statement as required.
use this
double num;
string candidate = "1";
if (double.TryParse(candidate, out num))
{
// It's a number!
}
int num;
bool isNumeric = int.TryParse("123", out num);
namespace Exception
{
class Program
{
static void Main(string[] args)
{
bool isNumeric;
int n;
do
{
Console.Write("Enter a number:");
isNumeric = int.TryParse(Console.ReadLine(), out n);
} while (isNumeric == false);
Console.WriteLine("Thanks for entering number" + n);
Console.Read();
}
}
}
Regex.IsMatch(stringToBeChecked, #"^\d+$")
Regex.IsMatch("141241", #"^\d+$") // True
Regex.IsMatch("232a23", #"^\d+$") // False
Regex.IsMatch("12412a", #"^\d+$") // False
The problem with some of the suggested solutions is that they don't take into account various float number formats. The following function does it:
public bool IsNumber(String value)
{
double d;
if (string.IsNullOrWhiteSpace(value))
return false;
else
return double.TryParse(value.Trim(), System.Globalization.NumberStyles.Any,
System.Globalization.CultureInfo.InvariantCulture, out d);
}
It assumes that the various float number styles such es decimal point (English) and decima comma (German) are all allowed. If that is not the case, change the number styles paramater. Note that Any does not include hex mumbers, because the type double does not support it.
I'm trying to recognize string literal by reading string per symbol.
Example of my scanner skeleton:
public sealed class Scanner
{
// some class inner implementations
/// <summary>
///
/// </summary>
/// <param name="Line"></param>
/// <param name="LineNumber"></param>
public void Run(String Line, Int32 LineNumber)
{
var ChPosition = default(Int32);
var ChCurrent = default(Char);
var Value = new StringBuilder();
while (default(Char) != Line.ElementAtOrDefault<Char>(ChPosition))
{
ChCurrent = Line.ElementAtOrDefault<Char>(ChPosition);
#region [Whitespace]
if (Char.IsWhiteSpace(ChCurrent))
{
ChPosition++;
}
#endregion
else
{
switch (ChCurrent)
{
#region [String Literal (")]
case '"':
{
// skipping " sign, include only string inner value
ChCurrent = Line.ElementAtOrDefault<Char>(++ChPosition);
// ...? Problematic place!!!
this.Tokens.Enqueue(new SharedEntities.Token
{
Class = SharedEntities.Token.TokenClass.StringLiteral,
Value = Value.ToString()
}
);
Value.Clear();
ChPosition++;
break;
}
#endregion
{
throw new ScanningException(
"<syntax_error#" + ChCurrent.ToString() + ">\n"
+ "Unsupported character appeared at: {ln: "
+ LineNumber.ToString()
+ "; pos: "
+ (ChPosition + 1).ToString()
+ "}"
);
}
} // [switch(ChCurrent)]
} // [if(Char.IsWhiteSpace(ChCurrent))...else]
} // [while(default(Char) != Line.ElementAtOrDefault<Char>(ChPosition))]
} // [public void Run(String Line, Int32 LineNumber)]
} // [public sealed class Scanner]
My target is to parse pascal-like string: "{everything enclosed, but ", only "" pair is allowed}".
First, you are obviously using some kind of parsing library, you would have better chance if you had modified your code, e.g. to something like I did, so that anybody can copy, paste, run your code.
Answer is simple, your (string literal)-parsing region does not parse all input. Here is your code modified to be used without any additional library:
public class Test
{
static char ElementAtOrDefault(string value, int position)
{
return position >= value.Length ? default(char) : value[position];
}
static string parseStringLiteral(string value, ref int ChPosition)
{
StringBuilder Value = new StringBuilder();
char ChCurrent = ElementAtOrDefault(value, ++ChPosition);
while (ChCurrent != '"')
{
Value.Append(ChCurrent);
ChCurrent = ElementAtOrDefault(value, ++ChPosition);
if (ChCurrent == '"')
{
// "" sequence only acceptable
if (ElementAtOrDefault(value, ChPosition + 1) == '"')
{
Value.Append(ChCurrent);
// skip 2nd double quote
ChPosition++;
// move position next
ChCurrent = ElementAtOrDefault(value, ++ChPosition);
}
}
else if (default(Char) == ChCurrent)
{
// message: unterminated string
throw new Exception("ScanningException");
}
}
ChPosition++;
return Value.ToString();
}
public static void test(string literal)
{
Console.WriteLine("testing literal with " + literal.Length +
" chars:\n" + literal);
try
{
int pos = 0;
string res = parseStringLiteral(literal, ref pos);
Console.WriteLine("Parsed " + res.Length + " chars:\n" + res);
}
catch (Exception ex)
{
Console.WriteLine("Error: " + ex.Message);
}
Console.WriteLine();
}
public static int Main(string[] args)
{
test(#"""Hello Language Design""");
test(#"""Is there any problems with the """"strings""""?""");
test(#"""v#:';?325;.<>,|+_)""(*&^%$##![]{}\|-_=""");
return 0;
}
}
Running this program produces output:
testing literal with 23 chars:
"Hello Language Design"
Parsed 21 chars:
Hello Language Design
testing literal with 45 chars:
"Is there any problems with the ""strings""?"
Parsed 41 chars:
Is there any problems with the "strings"?
testing literal with 39 chars:
"v#:';?325;.,|+_)"(*&^%$##![]{}\|-_="
Parsed 18 chars:
v#:';?325;.,|+_)
So it works for your testing, but algorithm is not correct, try running:
//literal with "", should produce ", but it does not
test(#"""""""""");
And you will incorrectly get:
testing literal with 4 chars:
""""
Parsed 0 chars:
Problem is, if you encounter character " in your while condition, you do not check next character, if it is " or not:
while (ChCurrent != '"') //bug
Of course, I created correct version for you :-)
Here it is (it uses your style, just edited version of yours):
static string parseStringLiteral(string value, ref int ChPosition)
{
StringBuilder Value = new StringBuilder();
char ChCurrent = ElementAtOrDefault(value, ++ChPosition);
bool goon = true;
while (goon)
{
if (ChCurrent == '"')
{
// "" sequence only acceptable
if (ElementAtOrDefault(value, ChPosition + 1) == '"')
{
Value.Append(ChCurrent);
// skip 2nd double quote
ChPosition++;
// move position next
ChCurrent = ElementAtOrDefault(value, ++ChPosition);
}
else goon = false; //break;
}
else if (default(Char) == ChCurrent)
{
// message: unterminated string
throw new Exception("ScanningException");
}
else
{
Value.Append(ChCurrent);
ChCurrent = ElementAtOrDefault(value, ++ChPosition);
}
}
ChPosition++;
return Value.ToString();
}
Happy coding :-)