I know that string.Format and ToString() can apply formatting to a string,
In my case i have a string with the value (typically it will have a string representation of a data but can have string representations of other base datatypes) and i have another string that represents the desired format. These values are coming from a database, what i need is to apply one to the other
I'm not even sure this is possible at all, so any pointers are welcome. I haven't been able to apply any version of ToString or Format. because these require that you declare on the spot what format you want and mine are dynamic
Is there some formatting method like the tryParse (in the sense that it would try any possible formatting for the data it is given?
EDIT: some examples as requested:
stringInput = "Jan 31 2012"; //string representation of a date
inputFormat="dd/MM/yyyy, HH mm"
outputString = "31/Jan/2015, 00:00";
stringInput = "100"; //string representation of a number
inputFormat="D6"
outputString = "000100";
string.Format(string, string) takes 2 string arguments so you can take them from db and apply them directly:
string formatToApply = "{0} and some text and then the {1}";
string firstText = "Text";
string secondText = "finsh.";
// suppose that those strings are from db, not declared locally
var finalString = string.Format(formatToApply, firstText, secondText);
// finalString = "Text and some text and then the finish."
However, there is a great risk to have wrong number of specifiers or wrong number of arguments. If you have a call like this, it will throw an exception:
var finalString = string.Format(formatToApply, firstText);
//An unhandled exception of type 'System.FormatException' occurred in mscorlib.dll;
//Additional information: Index (zero based) must be greater than or
//equal to zero and less than the size of the argument list.
So wrap your call into a try/catch/ (maybe) finally to handle this situation accordingly to your needs.
Later Edit after desired examples were posted:
First example: you might want to take advantage of DateTime class from C# which knows to format its output values. So you need first to convert stringInput into a DateTime:
var inputDateTime = DateTime.Parse(stringInput);
var outputString = inputDateTime.ToString(inputFormat);
Second example: again, you might want to take advantage of Double class and conversion occurs again:
var inputDouble = Double.Parse(stringInput);
var outputString = inputDouble.ToString(inputFormat);
In summary of those two examples, you need to know the type of input string, type which you specified in your comments ("string representation of a date"). Knowing this you can take advantage of each specific class and its ability to format output strings. Otherwise it would be difficult to design yourself some kind of general formatter. A simple method might look like this:
public string GetFormattedString(string inputString, string inputFormat, string type)
{
switch (type)
{
case "double":
var inputDouble = Double.Parse(inputString);
return inputDouble.ToString(inputFormat);
break;
case "datetime":
var inputDateTime = DateTime.Parse(inputString);
return inputDateTime.ToString(inputFormat);
break;
case "...": // other types which you need to support
default: throw new ArgumentException("Type not supported: " + type);
}
}
This switch is only an idea of how the logic may occur but you will need to handle errors for Parse methods and for ToString methods and if you have many types to support is better to take advantage of some design patterns like Factory.
Related
I have as input the string format CST-000000 and an integer with value 1
Upon using
string result = string.Format("CST-000000", 1);
the expected result should be CST-000001 instead of CST-000000
How could i create this string format dynamically?
For example
- CST-000 should produce CST-001
- HELLO000 should produce HELLO001
- CUSTOMER0000 should produce CUSTOMER0001
Assuming that:
You receive your format string from somewhere and you can't control what it looks like
Your format string ends with 1 or more zeros
If the format string is e.g. CST-00000 and your value is 123, you want the result to be CST-00123
You can do something like this:
Inspect your format string, and separate out the stuff at the beginning from the zeros at the end. It's easy to do this with Regex, e.g.:
string format = "CST-000000";
// "Zero or more of anything, followed by one or more zeros at the end of the string"
var match = Regex.Match(format, "(.*?)(0+)$");
if (!match.Success)
{
throw new ArgumentException("Format must end with one or more zeros");
}
string prefix = match.Groups[1].Value; // E.g. CST-
string zeros = match.Groups[2].Value; // E.g. 000000
Once you have these, note the "Zero placeholder" in this list of custom numeric format strings -- you can write e.g. 123.ToString("0000") and the output will be 0123. This lets you finish off with:
int value = 123;
string result = prefix + value.ToString(zeros);
See it on dotnetfiddle
String.Format requires a placeholder {n} with a zero-based argument number. You can also add it a format {n:format}.
string result = String.Format("CST-{0:000000}", 1);
You can also use String interpolation
string result = $"CST-{1:000000}"
The difference is that instead of a placeholder you specify the value directly (or as an expression). Instead of the Custom numeric format string, you can also use the Standard numeric format string d6: $"CST-{1:d6}"
If you want to change the format template dynamically, String.Format will work better, as you can specify the format and the value as separate arguments.
(Example assumes an enum FormatKind and C# >= 8.0)
int value = 1;
string format = formatKind switch {
FormatKind.CstSmall => "CST-{0:d3}",
FormatKind.CstLarge => "CST-{0:d6}",
FormatKind.Hello => "HELLO{0:d3}",
FormatEnum.Customer => "CUSTOMER{0:d4}"
};
string result = String.Format(format, value);
Also note that the value to be formatted must be of a numeric type. Strings cannot be formatted.
See also: Composite formatting
It seems .toString("CST-000"), .toString("HELLO000") and so on, does the trick.
ToString and String.Format can do much more than use predefined formats.
For example :
string result = string.Format("CST-{0:000000}", 1);
string result = 1.ToString("CST-000000");
Should both do what you want.
(Of course you could replace "1" by any variable, even a decimal one).
the interpolated string is easy, just a string lead with $ sign. But what if the string template is coming from outside of your code. For example assume you have a XML file containing following line:
<filePath from="C:\data\settle{date}.csv" to="D:\data\settle{date}.csv"/>
Then you can use LINQ to XML read the content of the attributes in.
//assume the ele is the node <filePath></filePath>
string pathFrom = ele.Attribute("from").value;
string pathTo = ele.Attibute("to").value;
string date = DateTime.Today.ToString("MMddyyyy");
Now how can I inject the date into the pathFrom variable and pathTo variable?
If I have the control of the string itself, things are easy. I can just do var xxx=$"C:\data\settle{date}.csv";But now, what I have is only the variable that I know contains the placeholder date
String interpolation is a compiler feature, so it cannot be used at runtime. This should be clear from the fact that the names of the variables in the scope will in general not be availabe at runtime.
So you will have to roll your own replacement mechanism. It depends on your exact requirements what is best here.
If you only have one (or very few replacements), just do
output = input.Replace("{date}", date);
If the possible replacements are a long list, it might be better to use
output = Regex.Replace(input, #"\{\w+?\}",
match => GetValue(match.Value));
with
string GetValue(string variable)
{
switch (variable)
{
case "{date}":
return DateTime.Today.ToString("MMddyyyy");
default:
return "";
}
}
If you can get an IDictionary<string, string> mapping variable names to values you may simplify this to
output = Regex.Replace(input, #"\{\w+?\}",
match => replacements[match.Value.Substring(1, match.Value.Length-2)]);
You can't directly; the compiler turns your:
string world = "world";
var hw = $"Hello {world}"
Into something like:
string world = "world";
var hw = string.Format("Hello {0}", world);
(It chooses concat, format or formattablestring depending on the situation)
You could engage in a similar process yourself, by replacing "{date" with "{0" and putting the date as the second argument to a string format, etc.
SOLUTION 1:
If you have the ability to change something on xml template change {date} to {0}.
<filePath from="C:\data\settle{0}.csv" to="D:\data\settle{0}.csv" />
Then you can set the value of that like this.
var elementString = string.Format(element.ToString(), DateTime.Now.ToString("MMddyyyy"));
Output: <filePath from="C:\data\settle08092020.csv" to="D:\data\settle08092020.csv" />
SOLUTION 2:
If you can't change the xml template, then this might be my personal course to go.
<filePath from="C:\data\settle{date}.csv" to="D:\data\settle{date}.csv" />
Set the placeholder like this.
element.Attribute("to").Value = element.Attribute("to").Value.Replace("{date}", DateTime.Now.ToString("MMddyyyy"));
element.Attribute("from").Value = element.Attribute("from").Value.Replace("{date}", DateTime.Now.ToString("MMddyyyy"));
Output: <filePath from="C:\data\settle08092020.csv" to="D:\data\settle08092020.csv" />
I hope it helps. Kind regards.
If you treat your original string as a user-input string (or anything that is not processed by the compiler to replace the placeholder, then the question is simple - just use String.Replace() to replace the placehoder {date}, with the value of the date as you wish. Now the followup question is: are you sure that the compiler is not substituting it during compile time, and leaving it untouched for handling at the runtime?
String interpolation allows the developer to combine variables and text to form a string.
Example
Two int variables are created: foo and bar.
int foo = 34;
int bar = 42;
string resultString = $"The foo is {foo}, and the bar is {bar}.";
Console.WriteLine(resultString);
Output:
The foo is 34, and the bar is 42.
Is it good practice to convert a number to a string directly using ToString()? Like this:
string numStr = 0.ToString();
Or should the number be entered into an int variable first and then use ToString() on that? Like this:
int num = 0;
string numStr = num.ToString();
Its a Good practice to store your numbers in a Variable and then using the ToString() See example at the end
ToString() accepts an over load like ToString(IFormatProvider provider) where you can specify culture-specific format information
Console.WriteLine(value.ToString(CultureInfo.InvariantCulture));
The Alternative to ToString() is to use Convert.ToString(Int value) the difference is that Convert also handles null values
var str = Convert.ToString(value);
var str1 = Convert.ToString(value,CultureInfo.InvariantCulture);
Is it good practice to convert a number to a string directly using
ToString()? Like this:
Example
1.ToString(); // Compiles fine
-1.ToString(); // Compile error, note you can surround it with parenthesis to get it to compile
when you say "string a = 0.ToString();"
----------------------^-----here you are already declaring that its a string so saying .ToString(); is redundant
Background: We have a system that receives data from another backend system. We handle the displaying of that data, and we have our own XML templates to control how certain things are displayed (i.e. we have our own column templates to dictate what the column headers are, etc.) One thing we would like to support is the ability to provide a mask for these column templates that would apply to the values coming from the backend. Below is a scenario that I'm having trouble with.
Problem: I can't seem to get a simple string format working. I'd like to format a STRING value of four digits (i.e. "1444") in a time format (i.e. "14:44"). I've tried:
String.Format("{0:00:00}", "1444")
Note the importance of the input being a STRING. If I supply an int value, the format will work. The reason I cannot use this is because all the data we receive from the backend is in string format, and we'd like for this to be generic (so casting isn't really an option).
By generic, I mean I'd like to specify a mask in our own XML templates, something like:
<MyColumnTemplate Id="MyColumn" Mask="00:00" />
and to use that mask in a string format call for string values? If the mask fails, we could just simply return the original value (as the String.Format() method already does by default).
Edit: To help clarify, here is a simplified version of what I'd like to be able to do in code:
string inputValue = "1444";
string maskValueFromXml = "00:00";
string mask = "{0:" + maskValueFromXml + "}";
string myDesiredEndResult = String.Format(mask, inputValue);
The thing is you are working string to string,since you ask for time and phone number they are all numbers then try this trick(if we can call it that :)):
string result = string.Format("{0:00:00}", int.Parse("1444"));
For phone number:
string result = string.Format("{0:000-000-0000}", int.Parse("1234560789"));
You can even place your desired masks in a dictionary for example and do this:
Dictionary<string, string> masks = new Dictionary<string, string>();
masks.Add("Phone", "{0:000-000-0000}");
masks.Add("Time", "{0:00:00}");
string test = "1234560789";
string result = string.Format(masks["Phone"], int.Parse(test));
Try with DateTime.TryParseExact, e.g:
DateTime dateEntered;
string input = "1444";
if (DateTime.TryParseExact(input, "HH:mm", System.Globalization.CultureInfo.CurrentCulture, System.Globalization.DateTimeStyles.None, out dateEntered))
{
MessageBox.Show(dateEntered.ToString());
}
else
{
MessageBox.Show("You need to enter valid 24hr time");
}
After that, you can use string.Format, predefined formats on MSDN.
In C#.Net, here's a simple example of how to format numbers into strings using custom format strings:
(example taken from: http://www.csharp-examples.net/string-format-int/)
String.Format("{0:+### ### ### ###}", 447900123456); // "+447 900 123 456"
String.Format("{0:##-####-####}", 8958712551); // "89-5871-2551"
Is there a way to convert this formatted string back into a long/integer ? Is there someway to do this :
long PhoneNumber = Int32.Parse("89-5871-2551", "{0:##-####-####}");
I saw that DateTime has a method ParseExact which can do this work well. But I did not see any such thing for int/long/decimal/double.
You can regex out all of the non numeric numbers, and what you're left with is a string of numbers that you can parse.
var myPhoneNumber = "89-5871-2551";
var strippedPhoneNumber = Regex.Replace(myPhoneNumber, #"[^\d]", "");
int intRepresentation;
if (Int32.TryParse(strippedPhoneNumber, out intRepresentation))
{
// It was assigned, intRepresentation = 8958712551
// now you can use intRepresentation.
} else {
// It was not assigned, intRepresentation is still null.
}
Well, you can always do
long PhoneNumber = Int32.Parse("89-5871-2551".
Replace(new char[]{'-','+',whatever..}).Trim());
By the way, considering that you're parsing a string received from some IO, I would suggest to use more secure (in terms of conversion) Int32.TryParse method.
The way like you described doesn't actually exist.
Just Regex out all of the non-numeric characters, then parse that string.