1

I have a string that contains 8 to 12 characters (alphanumeric). I would like to use the Format function to format it such that after first 4 characters a hyphen to be inserted and after next 3 characters another hyphen to be inserted:

cccc-ccc-c

if string has 8 chrs

cccc-ccc-cc

if string has 9 chrs

cccc-ccc-ccc

if string has 10 chrs

cccc-ccc-cccc

if string has 11 chrs

cccc-ccc-ccccc

if string has 12 chrs

Is it possible to use a single lined Format function to acquire the effect? I admit that the usage of Format function is beyond my grasp.

4
  • 3
    Format('%s-%s-%s', [Copy(S, 1, 4), Copy(S, 5, 3), Copy(S, 8, MaxInt)]); Commented Apr 11, 2014 at 20:04
  • 2
    TLama: please post this as an answer. Commented Apr 11, 2014 at 20:16
  • 1
    Why do you decide what the solution is? If you know the solution, why ask the question? Why mandate Format? Commented Apr 11, 2014 at 20:24
  • 1
    :) I believe that "I would like to use the Format function" accompanied by "Is it possible to use Format?" exclude the single (mandatory) solution of Format usage. I was curious if there is a possibility to achieve the desired effect by using Format function, because other ways I already know. But the solutions given here are correct and I thank everybody for them. Commented Apr 12, 2014 at 1:03

3 Answers 3

7

The function you are looking for is FormatMaskText located in System.MaskUtils. The Mask to be used is 'cccc-ccc-ccccc;0;'.

Sign up to request clarification or add additional context in comments.

Comments

2

There is no built-in format specifier (or combination of them) that will do the formatting you're looking to do.

You can, of course, write your own function to do so (name it, of course, with something meaningful to the values you're formatting):

function MyFormat(Value: string): String;
begin
  Assert(Length(Value) >= 8);
  Result := System.Insert(Value, '-', 5);
  Result := System.Insert(Result,'-', 9);
end;

Use it:

Value := MyFormat('12345678');      // Returns '1234-567-8'
Value := MyFormat('123456789');     // Returns '1234-567-89'
Value := MyFormat('1234567890');    // Returns '1234-567-890'

If you insist on trying to do it with Format, you need multiple calls to Copy (although you can skip the first one by using a width specifier). These can be done, of course, on a single line; I've spread it across multiple just for formatting here to eliminate horizontal scrolling.

Str := '12345678';
Value := Format('%.4s-%s-%s', 
                [Str, 
                 Copy(Str, 5, 3), 
                 Copy(Str, 8, MaxInt)]);     // Return '1234-567-8'
Str := '1234567890';
Value := Format('%.4s-%s-%s', 
                [Str, 
                 Copy(Str, 5, 3), 
                 Copy(Str, 8, MaxInt)]);     // Return '1234-567-890'

There is no way to use a "width specifer" type method to extract substrings within a string, though. (You can extract the first n characters using %.ns, but you can't do the first n characters starting at the fourth with any combination of specifiers.)

4 Comments

It might be interesting as to which option is faster. The inserts or the format and copy.
@GrayMatter: Unless it's called very frequently, it probably isn't important. I'd only worry about it if I identified it as a bottleneck with a profiler, and I'm not sure the differences would be meaningful even then.
The reason why I mentioned it is that the OP asked specifically for a format command. Sometimes it's better to look at other alternatives. TRegEx.Replace might also be an alternative.
@Graymatter: Regex would most likely be slower overall, and would definitely use more memory. They're great for searching or more complex replaces, but I'd bet on Insert or multiple Copy calls for speed on this type of thing any day. There is no built-in format specifier (or combination of them) that will do what the poster is asking, which is why I posted two possibilities that would work instead. The closest possible one is the use of the first one in the format string I supplied, which uses a width specifier to remove one call to Copy, but there's no way to do other chunks of the string.
1

Use Insert instead of Format:

Insert(s, '-', 5);
Insert(s, '-', 9);

4 Comments

nice and simple, but violates the query's specification
@Argalatyr: How so? (Other than not being a single Format statement, which is actually more difficult because of the repeated Copy calls required.)
"single line" and "format function" - while these are somewhat arbitrary, they are explicit
I think TLama's comment nicely illustrates what the querant wanted

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service and acknowledge you have read our privacy policy.

Start asking to get answers

Find the answer to your question by asking.

Ask question

Explore related questions

See similar questions with these tags.