Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

How can I transform a string into an abbreviated form?

I want to fit strings into a specific width. Example, "Hello world" -> "...world", "Hello...", "He...rld".

Do you know where I can find code for that? It's a neat trick, very useful for representing information, and I'd like to add it in my applications (of course).

Edit: Sorry, I forgot to mention the Font part. Not just for fixed width strings but according to the font face.

like image 302
Nick Dandoulakis Avatar asked May 27 '09 05:05

Nick Dandoulakis


1 Answers

It's a pretty simple algorithm to write yourself if you can't find it anywhere - the pseudocode would be something like:

if theString.Length > desiredWidth:
    theString = theString.Left(desiredWidth-3) + "...";

or if you want the ellipsis at the start of the string, that second line would be:

    theString = "..." + theString.Right(desiredWidth-3);

or if you want it in the middle:

    theString = theString.Left((desiredWidth-3)/2) + "..." + theString.Right((desiredWidth-3)/2 + ((desiredWidth-3) mod 2))

Edit:
I'll assume you're using MFC. Since you're wanting it with fonts, you could use the CDC::GetOutputTextExtent function. Try:

CString fullString
CSize size = pDC->GetOutputTextExtent(fullString);
bool isTooWide = size.cx > desiredWidth;

If that's too big, then you can then do a search to try and find the longest string you can fit; and it could be as clever a search as you want - for instance, you could just try "Hello Worl..." and then "Hello Wor..." and then "Hello Wo..."; removing one character until you find it fits. Alternatively, you could do a binary search - try "Hello Worl..." - if that doesn't work, then just use half the characters of the original text: "Hello..." - if that fits, try halfway between it and : "Hello Wo..." until you find the longest that does still fit. Or you could try some estimating heuristic (divide the total length by the desired length, proportionately estimate the required number of characters, and search from there.

The simple solution is something like:

unsigned int numberOfCharsToUse = fullString.GetLength();
bool isTooWide = true;
CString ellipsis = "...";
while (isTooWide)
{
    numberOfCharsToUse--;
    CString string = fullString.Left(numberOfCharsToUse) + ellipsis;
    CSize size = pDC->GetOutputTextExtent(string);
    isTooWide = size.cx > desiredWidth;
}
like image 189
Smashery Avatar answered Nov 15 '22 07:11

Smashery