23

Didn't find how to do that. What I found was more or less on the lines of this (http://blog.stevex.net/string-formatting-in-csharp/):

There really isn’t any formatting within a string, beyond it’s alignment. Alignment works for any argument being printed in a String.Format call. Sample Generates

String.Format(“->{1,10}<-”, “Hello”);  // gives "->     Hello<-" (left padded to 10)
String.Format(“->{1,-10}<-”, “Hello”); // gives "->Hello     <-" (right padded to 10)
Dusty
  • 3,946
  • 2
  • 27
  • 41
char m
  • 7,840
  • 14
  • 68
  • 117
  • What exactly are you trying to achieve? Can you post examples of what you would like to see? – Oded Nov 05 '10 at 11:24
  • i'm trying to convert C format strings to C# format strings. in C you can specify %-4.4s and similar. – char m Nov 05 '10 at 11:37
  • why the down vote? this is essential question! – char m Nov 05 '10 at 12:04
  • 1
    and more importantly if not present a flaw in C# format string design. – char m Nov 05 '10 at 12:05
  • 3
    I wouldn't call it a *flaw*. It's more that the specific feature that you're looking for is not available. String.Format also supports several features not present in C format strings. Does that mean that C's format strings are necessarily flawed? – Ruben Nov 05 '10 at 13:12

6 Answers6

7

What you want is not "natively" supported by C# string formatting, as the String.ToString methods of the string object just return the string itself.

When you call

string.Format("{0:xxx}",someobject);

if someobject implements the IFormattable interface, the overload ToString(string format,IFormatProvider formatProvider) method gets called, with "xxx" as format parameter.

So, at most, this is not a flaw in the design of .NET string formatting, but just a lack of functionality in the string class.

If you really need this, you can use any of the suggested workarounds, or create your own class implementing IFormattable interface.

Paolo Tedesco
  • 55,237
  • 33
  • 144
  • 193
  • thanks! u're definitely right. it's the string class that lacks something. but did u use xxx as an example of some format or does it really mean something (e.g. 3 characters)? – char m Nov 05 '10 at 13:03
  • @matti, no xxx was just an example. Actually, what it means is decided by the implementation of the IFormattable interface. Anyway (speaking as a c++ lover), string formatting in c++ compared to the one in c# *sucks*, talking about a flaw for the fact that this particular feature is missing seems rather strange to me ;) – Paolo Tedesco Nov 05 '10 at 16:03
7

This is not an answer on how to use string.format, but another way of shortening a string using extension methods. This way enables you to add the max length to the string directly, even without string.format.

public static class ExtensionMethods
{
    /// <summary>
    ///  Shortens string to Max length
    /// </summary>
    /// <param name="input">String to shortent</param>
    /// <returns>shortened string</returns>
    public static string MaxLength(this string input, int length)
    {
        if (input == null) return null;
        return input.Substring(0, Math.Min(length, input.Length));
    }
}

sample usage:

string Test = "1234567890";
string.Format("Shortened String = {0}", Test.MaxLength(5));
string.Format("Shortened String = {0}", Test.MaxLength(50));

Output: 
Shortened String = 12345
Shortened String = 1234567890
Andy
  • 842
  • 1
  • 12
  • 24
3

I've written a custom formatter that implements an "L" format specifier used to set maximum width. This is useful when we need to control the size of our formatted output say when destined for a database column or Dynamics CRM field.

public class StringFormatEx : IFormatProvider, ICustomFormatter
{
    /// <summary>
    /// ICustomFormatter member
    /// </summary>
    public string Format(string format, object argument, IFormatProvider formatProvider)
    {
        #region func-y town
        Func<string, object, string> handleOtherFormats = (f, a) => 
        {
            var result = String.Empty;
            if (a is IFormattable) { result = ((IFormattable)a).ToString(f, CultureInfo.CurrentCulture); }
            else if (a != null) { result = a.ToString(); }
            return result;
        };
        #endregion

        //reality check.
        if (format == null || argument == null) { return argument as string; }

        //perform default formatting if arg is not a string.
        if (argument.GetType() != typeof(string)) { return handleOtherFormats(format, argument); }

        //get the format specifier.
        var specifier = format.Substring(0, 1).ToUpper(CultureInfo.InvariantCulture);

        //perform extended formatting based on format specifier.
        switch(specifier)
        {
            case "L": 
                return LengthFormatter(format, argument);
            default:
                return handleOtherFormats(format, argument);
        }
    }

    /// <summary>
    /// IFormatProvider member
    /// </summary>
    public object GetFormat(Type formatType)
    {
        if (formatType == typeof(ICustomFormatter))
            return this;
        else
            return null;
    }

    /// <summary>
    /// Custom length formatter.
    /// </summary>
    private string LengthFormatter(string format, object argument)
    {
        //specifier requires length number.
        if (format.Length == 1)
        {
            throw new FormatException(String.Format("The format of '{0}' is invalid; length is in the form of Ln where n is the maximum length of the resultant string.", format));
        }

        //get the length from the format string.
        int length = int.MaxValue;
        int.TryParse(format.Substring(1, format.Length - 1), out length);

        //returned the argument with length applied.
        return argument.ToString().Substring(0, length);
    }
}

Usage is

var result = String.Format(
    new StringFormatEx(),
    "{0:L4} {1:L7}",
    "Stack",
    "Overflow");

Assert.AreEqual("Stac Overflo", result);
Douglas Wiley
  • 483
  • 1
  • 7
  • 10
0

Can't you just apply length arguments using the parameter rather than the format?

String.Format("->{0}<-", toFormat.PadRight(10)); // ->Hello <-

Or write your own formatter to allow you to do this?

Ian Johnson
  • 2,224
  • 1
  • 13
  • 9
0

Why not just use Substr to limit the length of your string?

String s = "abcdefghijklmnopqrstuvwxyz";
String.Format("Character limited: {0}", s.Substr(0, 10));
Moo-Juice
  • 38,257
  • 10
  • 78
  • 128
  • I missed the fact that even Substr has some awkward implementation different from every other language. I used this workaround as it is and it fails, when the string is shorter than 10 characters... – V-X Sep 15 '15 at 13:05
0

You may want to use this helper in future application, it limits the string at given maximum length and also pads if it is shorter than the given limit.

public static class StringHelper
{

    public static string ToString(this string input , int maxLength , char paddingChar = ' ', bool isPaddingLeft = true)
    {
        if (string.IsNullOrEmpty(input))
            return new string('-', maxLength);
        else if (input.Length > maxLength)
            return input.Substring(0, maxLength);
        else
        {
            int padAmount = maxLength - input.Length;
            if (isPaddingLeft)
                return input + new string(paddingChar, padAmount);
            else
                return new string(paddingChar, padAmount) + input;
        }
    }
}

and you could use it as:

 string inputStrShort = "testString";
 string inputStrLong = "mylongteststringexample";
 Console.WriteLine(inputStrShort.ToString(20, '*', true)); // Output : testString**********
 Console.WriteLine(inputStrLong.ToString(20, '*', true));  // Output : mylongteststringexam