Take next parameter as field width in String.Format - c#

In C#, I have a width I want to use for some strings, but I won't know that width until runtime. I'm doing something like this:
string.Format("{0, " + digits + "}", value) // prints 123 as " 123"
Is there a string formatting directive that lets me specify this without smashing my own format string together like this?
I looked around on MSDN for a little while and I feel like I'm missing a whole chapter on format strings or something.

Take a look at PadLeft:
s = "123".PadLeft(5); // Defaults to spaces
s = "123".PadLeft(5, '.'); // Pads with dots

You can use the PadLeft and PadRight methods:
http://msdn.microsoft.com/en-us/library/system.string.padleft%28VS.71%29.aspx

you can do something like
string test = valueString.PadLeft(10,' ');
or even sillier
string spaces = String.Concat(Enumerable.Repeat(" ", digits).ToArray());

The functions mentioned by others will work, but this MSDN page has a more general solution to formatting that changes at runtime:
Composite Formatting
They give examples much like yours.
Edit: I thought you were trying to solve the general case of composing a format string at runtime. For example, if there were no built in PadLeft(), you could do this:
int myInt = 123;
int nColumnWidth = 10;
string fmt = string.Format("Price = |{{0,{0}}}|", nColumnWidth);
// now fmt = "Price = |{0,5}|"
string s = string.Format(fmt, myInt);
You can even do all that in one line, but it's ugly:
string s = string.Format(
string.Format("Price = |{{0,{0}}}|", nColumnWidth),
myInt);

Perhaps this will help with your research on formatting:
Formatting Types
Composite Formatting
However, I don't think you're going to do much better than this, as the alignment parameter must be part of the format string and does not seem to be represented by a property.

Probably overkill but just to illustrate a way to encapsulate the format specification and use an overload of String.Format that accepts an IFormatProvider.
class Program
{
public static void Main(string[] args)
{
int digits = 7;
var format = new PaddedNumberFormatInfo(digits);
Console.WriteLine(String.Format(format, "{0}", 123));
}
}
class PaddedNumberFormatInfo : IFormatProvider, ICustomFormatter
{
public PaddedNumberFormatInfo(int digits)
{
this.DigitsCount = digits;
}
public int DigitsCount { get; set; }
// IFormatProvider Members
public object GetFormat(Type formatType)
{
if (formatType == typeof(ICustomFormatter))
return this;
return null;
}
// ICustomFormatter Members
public string Format(string format, object arg, IFormatProvider provider)
{
return String.Format(
String.Concat("{0, ", this.DigitsCount, "}"), arg);
}
}

I posted a CodeProject article that may be what you want.
See: A C# way for indirect width and style formatting.
Basically it is a method, FormatEx, that acts like String.Format, except it allows for indirect alignment and formatString specifiers.
FormatEx("{0,{1}:{2}}", value, width, formatString);
Means format the value of varArgs 0, in a field width specified by varArgs 1, using a formattingString code specified by varArgs 2.
Edit: Internally, it does what many others have suggested in their answers. I've just wrapped the parsing and determination of the final values to use for alignment and formatString. I also added a "center alignment" modifier.
-Jesse

String has a constructor that creates a string with a given character repeated n times.
https://msdn.microsoft.com/en-us/library/xsa4321w(v=vs.110).aspx
// prints 123 as " 123"
string.Format(new string(' ', digits) + "{0}", value)

Related

Format a string in C# (not number or date) to a given pattern

Is there something like string.format for formatting strings where I can pass a the goal pattern. string.format seems to be only for formatting numbers and patterns and inserting values inside a given position. Is there a general solution to formatting strings after a given pattern than programming it out myself?
I want to give the goal pattern and an input string and get out the string in the pattern I’ve provided.
I can give some examples.
Input Output Input pattern (idea)
---------------------------------------------------------
123.456.001 00123.456.001 00000.000.###
D1234567 D-123-4567 D-000-#### (where D is literal)
So, my question is: Is there a way to format a string to a given pattern like there is for number and dates?
I would consider making customer formatter classes for each of the different formats you require. There is a very simple example below with no error handling etc...
// custom formatter class
public class FormatD : IFormattable
{
public string ToString(string format, IFormatProvider provider)
{
return format[0] + "-" + format.Substring(1,3) + "-" + format.Substring(4);
}
}
To call:
var input = "D1234567";
var ouput = String.Format("{0:" + input + "}", new FormatD());
This is not really possible with String.Format(). You would need to dissect the different parts of your pattern using regular expressions or similar.
For your example a solution could be
public string ReplacePattern(string input)
{
var match = Regex.Match(input, #"([A-Z])(\d{3})(\d{4})");
if(match.Groups.Count == 4) // The first group is always the input
{
return String.Format("{0}-{1}-{2}", match.Groups.Skip(1).Take(3).ToArray());
}
return "";
}
Edit: I forgot: of course you can always use regular expression replacements:
public string ReplacePattern(string input)
{
return Regex.Replace(input, #"([A-Z])(\d{3})(\d{4})", "$1-$2-$3");
}

C# custom string alignment

I have to manage a particular string formatting/padding condition. To be short I need to pad a string argument only if the argument length is 0. If I use the typical aligment parameter the padding is made if the length of the argument is smaller then the provided alignment value. For example:
string format = "#{0,10}#";
string argument;
string output;
argument = Console.ReadLine();
output = String.Format(format, argument);
String.WriteLine(output);
If I enter "try" as a value I got this result:
#try #
If I enter "trytrytrytry" I got:
#trytrytrytry#
What I would like to happen is depicted below:
Entering "" I would like to have:
# #
but entering "try" I would like to have:
#try#
The code I'm going to write should be as much generic as possibile since the format parameter is not static and is defined at runtime.
The best practice to do this is to define a custom string formatter. Unluckly it seems that the customization code can only act on the 'format' portion of the format parameter of the String.Format() method.
Indeed If I define a custom formatter:
public class EmptyFormatter : IFormatProvider, ICustomFormatter
{
public object GetFormat(Type formatType)
{
if (formatType == typeof(ICustomFormatter))
return this;
else
return null;
}
public string Format(string format, object arg, IFormatProvider formatProvider)
{
if (!this.Equals(formatProvider))
return null;
if (string.IsNullOrEmpty(format))
throw new ArgumentNullException();
return numericString;
}
}
The format and arg parameters of the Format method didn't contain the alignment parameter then I cannot actually check what lenght of the padding value should be applied and therefore I cannot act properly. Moreover this part of the 'formatting' of the string seems to be applied somewhere else but I have not idea where.
Is there a way to 'alter' this behaviour ?
A format item has the following syntax:
index[,alignment][ :formatString] }
The reason the format parameter is null is because there is no formatString component, there is only alignment. I couldn't find a way to access the alignment component from the Format method. However, one (ugly) solution is to set the formatString to be the same as the alignment, so that you can access it using the format parameter:
#{0,10:10}#
A less ugly solution would be to create your own method extension that first extracts the alignment from the given format and then calls the traditional String.Format method.
For example:
public static string StringFormat(this string Arg, string Format) {
//extract alignment from string
Regex reg = new Regex(#"{[-+]?\d+\,[-+]?(\d+)(?::[-+]?\d+)?}");
Match m = reg.Match(Format);
if (m != null) { //check if alignment exists
int allignment = int.Parse(m.Groups[1].Value); //get alignment
Arg = Arg.PadLeft(allignment); //pad left, you can make the length check here
Format = Format.Remove(m.Groups[1].Index - 1, m.Groups[1].Length + 1); //remove alignment from format
}
return (string.Format(Format, Arg));
}
To use the code:
string format = "#{0,10}#";
string argument = "try";
string output = argument.StringFormat(format); //"# try#"

Adding comma between longer numbers [duplicate]

This question already has answers here:
.NET String.Format() to add commas in thousands place for a number
(23 answers)
Closed 9 years ago.
I'm trying to put comma's between long numbers automatically, but so far without success. I'm probably making a very simple mistake, but so far I can't figure it out. This is the code I currently have, but for some reason I'm getting 123456789 as the output.
string s = "123456789";
string.Format("{0:#,###0}", s);
MessageBox.Show(s); // Needs to output 123,456,789
var input = 123456789;
// these two lines amount to the same thing
Console.WriteLine(input.ToString("N0"));
Console.WriteLine(string.Format("{0:N0}", input));
If, as per your question, you need to start with a string:
var stringInput = "123456789";
var input = int.Parse(stringInput);
// these two lines amount to the same thing
Console.WriteLine(input.ToString("N0"));
Console.WriteLine(string.Format("{0:N0}", input));
You'll possibly also need to take culture into account when parsing/formatting. See the overloads that take an IFormatProvider.
Try this:
string value = string.Format("{0:#,###0}", 123456789);
In your code you are missing the initial { in the format string, and then number formatting options apply to numbers, while your s is a string.
You could convert the string to a number with int.Parse:
int s = int.Parse("123456789");
string value = string.Format("{0:#,###0}", 123456789);
MessageBox.Show(value);
This should work (you need to pass String.Format() a number, not another String):
Int32 i = 123456789;
String s = String.Format("{0:#,###0}", i);
MessageBox.Show(s);
But consider the format string you're using...there are cleaner options available, as others are suggesting.
Look at the number formatting information on MSDN: Standard Numeric Format Strings, or optionally at the custom format strings: Custom Numeric Format Strings.
For custom number formats:
The "," character serves as both a group separator and a number scaling specifier.
double value = 1234567890;
Console.WriteLine(value.ToString("#,#", CultureInfo.InvariantCulture));
// Displays 1,234,567,890
Console.WriteLine(value.ToString("#,##0,,", CultureInfo.InvariantCulture));
// Displays 1,235
There is so much wrong with your code, that's it's hard to describe every detail.
Look at this example:
namespace ConsoleApplication1
{
using System;
public class Program
{
public static void Main()
{
const int Number = 123456789;
var formatted = string.Format("{0:#,###0}", Number);
Console.WriteLine(formatted);
Console.ReadLine();
}
}
}

Remove last characters from a string in C#. An elegant way?

I have a numeric string like this 2223,00. I would like to transform it to 2223. This is: without the information after the ",". Assume that there will be only two decimals after the ",".
I did:
str = str.Remove(str.Length - 3, 3);
Is there a more elegant solution? Maybe using another function? -I don´t like putting explicit numbers-
You can actually just use the Remove overload that takes one parameter:
str = str.Remove(str.Length - 3);
However, if you're trying to avoid hard coding the length, you can use:
str = str.Remove(str.IndexOf(','));
Perhaps this:
str = str.Split(",").First();
This will return to you a string excluding everything after the comma
str = str.Substring(0, str.IndexOf(','));
Of course, this assumes your string actually has a comma with decimals. The above code will fail if it doesn't. You'd want to do more checks:
commaPos = str.IndexOf(',');
if(commaPos != -1)
str = str.Substring(0, commaPos)
I'm assuming you're working with a string to begin with. Ideally, if you're working with a number to begin with, like a float or double, you could just cast it to an int, then do myInt.ToString() like:
myInt = (int)double.Parse(myString)
This parses the double using the current culture (here in the US, we use . for decimal points). However, this again assumes that your input string is can be parsed.
String.Format("{0:0}", 123.4567); // "123"
If your initial value is a decimal into a string, you will need to convert
String.Format("{0:0}", double.Parse("3.5", CultureInfo.InvariantCulture)) //3.5
In this example, I choose Invariant culture but you could use the one you want.
I prefer using the Formatting function because you never know if the decimal may contain 2 or 3 leading number in the future.
Edit: You can also use Truncate to remove all after the , or .
Console.WriteLine(Decimal.Truncate(Convert.ToDecimal("3,5")));
Use:
public static class StringExtensions
{
/// <summary>
/// Cut End. "12".SubstringFromEnd(1) -> "1"
/// </summary>
public static string SubstringFromEnd(this string value, int startindex)
{
if (string.IsNullOrEmpty(value)) return value;
return value.Substring(0, value.Length - startindex);
}
}
I prefer an extension method here for two reasons:
I can chain it with Substring.
Example: f1.Substring(directorypathLength).SubstringFromEnd(1)
Speed.
You could use LastIndexOf and Substring combined to get all characters to the left of the last index of the comma within the sting.
string var = var.Substring(0, var.LastIndexOf(','));
You can use TrimEnd. It's efficient as well and looks clean.
"Name,".TrimEnd(',');
Try the following. It worked for me:
str = str.Split(',').Last();
Since C# 8.0 it has been possible to do this with a range operator.
string textValue = "2223,00";
textValue = textValue[0..^3];
Console.WriteLine(textValue);
This would output the string 2223.
The 0 says that it should start from the zeroth position in the string
The .. says that it should take the range between the operands on either side
The ^ says that it should take the operand relative to the end of the sequence
The 3 says that it should end from the third position in the string
Use lastIndexOf. Like:
string var = var.lastIndexOf(',');

formatting string in C#?

I've a predefined string format. For instance '>>>,>>>,>>9.99' this means that the system should display string in this '500,000,000.10'. The format can change based on the users using it. How can I write a common function to display stings on the given format passing
the input value and the format as the parameter using C#
You can use the ToString method with a standard or custom format string
For example:
string format = "{0:000,000,000.00}";
string val = 12.3456;
Console.WriteLine(string.Format(format, value)); // it prints "000,000,123.23"
You can read more about formating values here http://www.csharp-examples.net/string-format-double/
decimal value = 1.2345;
string rounded = value.ToString("d2");
private string sDecimalFormat = "0.00";
decimal d = 120M;
txtText.Text = d.ToString(sDecimalFormat);
You could then have a setting for decimal format eg:
txtText.Text = d.ToString(Settings.DecimalFormat);
String.formate can be used for formating.
Go there if you want examples
http://www.csharp-examples.net/string-format-double/
I think the following might work:
String result = String.Format(fmt.Replace('>', '#').Replace('9', '0'), inpString);
fmt being the format you want to use and inpString being the string entered by the user.
Just replace the > with # and the 9 with 0 and it'll be a valid .Net formatstring.
There is a Format method on String.
String.Format("{0:X}", 10); // prints A (hex 10)
There are several methods to format numbers, date...
I dont seem to understand how you can make 500,000,000.10 from >>>,>>>,>>9.99' but I believe the answer would be
But I assume something you are looking for is: string.Format("500,000,00{0:0.##}", 9.9915)
You can then make a method like
Public string GetString(string Format, object value)
{
return string.Format(Format, value);
}
Something like this?

Categories