Take the 2-minute tour ×
Stack Overflow is a question and answer site for professional and enthusiast programmers. It's 100% free, no registration required.

Quick question, I just can't seem to find the answer on google

I've been using C# String.Format for formatting numbers before like this (in this example I simply want to insert a space):

String.Format("{0:### ###}", 123456);

output:

"123 456"

Here's the thing, in this particular case, the number is a string. My first thought was to simply parse it to a number, but it makes no sense in the context, and there must be a prettier way.

Following does not work, as ## looks for numbers

String.Format("{0:### ###}", "123456");

output:

"123456"

I'm sure the answer is super obvious, but I just can't seem to figure it out, What is the string equivalent to # when formatting? The awesomeness of String.Format is still fairly new to me

share|improve this question
    
i believe parsing it to int is the only way to go –  Lee Gary 13 hours ago
    
Yes, you need to parse it first. You are tryingto apply a numeric format. In order to do that you first need to have...you guessed it, a number. There is no way around it unless you want to implement some custom string formatting that covers your needs (not really worth it IMHO). –  InBetween 13 hours ago
    
@InBetween, Technically I wasn't "trying" to apply a numeric format. I was showing an example, and why it was wrong. This issue is interesting, because it turns out there is no char equivalent to # in the string.format method - which means you are forced to use less pretty / less readable solutions to the problem. In my particular context - the number isn't used as a numeric value, but rather an identifier - the fact that it happens to be numbers is irrelevant. –  Scherling 11 hours ago
    
@Scherling, I understand. But alas, the way you were trying is only applicable to numeric formatting. As you well say there is no general formatting tool available for strings, you'll have to build it yourself. –  InBetween 10 hours ago

7 Answers 7

You have to parse the string to a number first.

int number = int.Parse("123456");
String.Format("{0:### ###}", number);

of course you could also use string methods but that's not as reliable and less safe:

string strNumber =  "123456";
String.Format("{0} {1}", strNumber.Remove(3), strNumber.Substring(3));
share|improve this answer
1  
Yeah, but that makes no sense in the context. Parsing string to number for the sake of parsing it back to a string feels... wrong –  Scherling 13 hours ago
2  
@Scherling well, you could manually process the character data (a lot of work, in the general case), but ultimately you are parsing it to a number so that number-based operations work correctly - and the # usage is: number-based. –  Marc Gravell 13 hours ago

As Heinzi pointed out, you can not have format specifier for string arguments.

So, instead of String.Format, you may use following:

string myNum="123456";
myNum=myNum.Insert(3," ");
share|improve this answer
    
This might actually be the "prettiest" solution considering the alternatives, except for the fact that I need to insert multiple spaces, which makes the indexes shift –  Scherling 13 hours ago
    
You could then remove all spaces and you had the original indexes back –  user2414460 10 hours ago
1  
@Scherling If you know in advance where the spaces will be, you can insert them from the end back to the start, possibly (slightly) less efficient but the indexes won't change. (i.e. instead of inserting at (3,7,11 - n+3) you can insert at 9,6 and 3 in order.) Actually, if it is always going to be spaces seperating groups of 3 chars, just myNum.insert(i+3," ") in a loop. –  Baldrickk 10 hours ago
    
@Baldrickk lol, inserting from the back actually isn't a bad idea. I would still rather have seen a char equivalent to #. So you could simply do something like string.format("{0:cc cc}", "1234"); –  Scherling 10 hours ago
1  
@Scherling for more lols have a peek at my answer. our problem is modifiying strings so the obvious solution is to use a regex! (now we have two problems) –  Baldrickk 9 hours ago

Not very beautiful, and the extra work might outweigh the gains, but if the input is a string on that format, you could do:

var str = "123456";
var result = String.Format("{0} {1}", str.Substring(0,3), str.Substring(3));
share|improve this answer
1  
I agree, this is exactly what I was trying to avoid :) –  Scherling 13 hours ago

string is not a IFormattable

Console.WriteLine("123456" is IFormattable); // False
Console.WriteLine(21321 is IFormattable); // True

No point to supply a format if the argument is not IFormattable only way is to convert your string to int or long

share|improve this answer

We're doing string manipulation, so we could always use a regex.

Adapted slightly from here:

class MyClass
{
   static void Main(string[] args)
   {
      string sInput, sRegex;

      // The string to search.
      sInput = "123456789";

      // The regular expression.
      sRegex = "[0-9][0-9][0-9]";

      Regex r = new Regex(sRegex);

      MyClass c = new MyClass();

      // Assign the replace method to the MatchEvaluator delegate.
      MatchEvaluator myEvaluator = new MatchEvaluator(c.ReplaceNums);

      // Replace matched characters using the delegate method.
      sInput = r.Replace(sInput, myEvaluator);

      // Write out the modified string.
      Console.WriteLine(sInput);
   }

   public string ReplaceNums(Match m)
   // Replace each Regex match with match + " "
   {
      return m.ToString()+" ";
   }

}

How's that?

It's been ages since I used C# and I can't test, but this may work as a one-liner which may be "neater" if you only need it once:

sInput = Regex("[0-9][0-9][0-9]").Replace(sInput,MatchEvaluator(Match m => m.ToString()+" "));
share|improve this answer
    
Some people, when confronted with a problem, think “I know, I'll use regular expressions.” Now they have two problems. Jamie Zawinski –  Baldrickk 9 hours ago
    
Added a one liner that might work, it depends if lambda functions are accepted as inputs to MatchEvaluator –  Baldrickk 9 hours ago

There is no way to do what you want unless you parse the string first.

Based on your comments, you only really need a simple formatting so you are better off just implementing a small helper method and thats it. (IMHO it's not really a good idea to parse the string if it isn't logically a number; you can't really be sure that in the future the input string might not be a number at all.

I'd go for something similar to:

 public static string Group(this string s, int groupSize = 3, char groupSeparator = ' ')
 {
     var formattedIdentifierBuilder = new StringBuilder();

     for (int i = 0; i < s.Length; i++)
     {
         if (i != 0 && (s.Length - i) % groupSize == 0)
         {
             formattedIdentifierBuilder.Append(groupSeparator);
         }

         formattedIdentifierBuilder.Append(s[i]);
     }

     return formattedIdentifierBuilder.ToString();
 }

EDIT: Generalized to generic grouping size and group separator.

share|improve this answer

The problem is that # is a Digit placeholder and it is specific to numeric formatting only. Hence, you can't use this on strings.

Either parse the string to a numeric, so the formatting rules apply, or use other methods to split the string in two.

string.Format("{0:### ###}", int.Parse("123456"));
share|improve this answer
    
Yeah, it just goes against my basic principles of programming. I don't want to parse a string to a number in order to turn it into a string. It's actually interesting that the functionatlity I'm looking for does not exist. The fact that it's a number shouldn't be important in this case. –  Scherling 13 hours ago
    
Well, it is. This is specific to numbers since it addresses a problem concerning numbers, not strings. –  Patrick Hofman 13 hours ago
    
But consider if I had a hexadecimal ID, that I wanted to format. It's a shame that I cannot do it without the pain of substrings... or regex –  Scherling 13 hours ago

Your Answer

 
discard

By posting your answer, you agree to the privacy policy and terms of service.

Not the answer you're looking for? Browse other questions tagged or ask your own question.