どんなに変換する文字列を省略します。
-
06-09-2019 - |
質問
したい fit 文字列は特定の幅になります。例では、"こんにちは世界"->"...","こんにちは..."、"...rld".
いいでコードを教えて下さい。こころか、非常に有用な表情ていただきたいと思いますように添加できるようになっていっ用のコースを受講した。
編集:申し訳されてしまったのでしょに フォント ます。なのための固定幅を文字列にフォントです。
解決
このインターネットはモバイルアルゴリズムを書く自分でしなければならどこでも見かけの擬似コードのようなものです:
if theString.Length > desiredWidth:
theString = theString.Left(desiredWidth-3) + "...";
またはご希望の場合は省略記号は文字列に、その次の行することはできない。
theString = "..." + theString.Right(desiredWidth-3);
ただし、中間:
theString = theString.Left((desiredWidth-3)/2) + "..." + theString.Right((desiredWidth-3)/2 + ((desiredWidth-3) mod 2))
編集:
ょっとだけを使用MFC.ていたのでフォントを使用できるの CDC::GetOutputTextExtent 機能です。う:
CString fullString
CSize size = pDC->GetOutputTextExtent(fullString);
bool isTooWide = size.cx > desiredWidth;
それとも大きますので、そのしい検索をしてみては最長の文字列することができ;することとして巧みな検索したい-たとえば、だけない"こんにちは機会をつ..."そして"こんにちはWor..."そして"こんにちはWo...";削除文字までです。少し大きい バイナリ検索 しかできない"こんにちは機会をつ..."だな、それだけで使用半の文字の文:"こんにちは..."の場合に収まる、中間に位置す:"こんにちはWo..."を見つけるまでに長いるものです。やきい推定ヒューリスティック(分割により、ご希望の長さに比例的に見積り、必要な文字数で検索します。
は簡単に解決するようなもの:
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;
}
他のヒント
このかを明;とは思わないをチェックしてみて下さいコードしないというより構造化されたもの。
基本的にしたい:
- の文字列の長さまで、ウィンドウの幅になります。
- ど多くのcharatersできるから、元の文字列は、基本的にはウィンドウ幅3のとおりとする。このサイトのコン k.
- かどうかに応じてまいの省略時は右手を、いずれかけて行動を起こしてみてください階(k/2)文字から、連結され、"..."、処理してくれるかどうかは,最階(k/2)文字(おそらく文字が必要なのは、部門);または最初のk-文字ollowedによる"...".
と思いSmasheryの答えは一番良い準備をして臨みたいです。より、いろいろな方法をとるという結果を記述試験のコードも入を希望します。<br></p><まして試験セットアップ、実践できるだ文字列操作コードまで全ての試験を要します。
- 計算の幅がテキスト に基づくフォント)
を使用しているケースでは、MFCのAPI GetOutputTextExtent までの値です。
の場合の幅を超える指定された 特定の幅を計算し、楕円の幅には、最初の
ellipseWidth=計算の幅(...)
削除文字列の部分に幅ellipseWidthからの追加ます。
のようなもの:こんにちは...
の方に興味のある方のための完全な日常に、これは私の 答え :
/**
* Returns a string abbreviation
* example: "hello world" -> "...orld" or "hell..." or "he...rd" or "h...rld"
*
* style:
0: clip left
1: clip right
2: clip middle
3: pretty middle
*/
CString*
strabbr(
CDC* pdc,
const char* s,
const int area_width,
int style )
{
if ( !pdc || !s || !*s ) return new CString;
int len = strlen(s);
if ( pdc->GetTextExtent(s, len).cx <= area_width ) return new CString(s);
int dots_width = pdc->GetTextExtent("...", 3).cx;
if ( dots_width >= area_width ) return new CString;
// My algorithm uses 'left' and 'right' parts of the string, by turns.
int n = len;
int m = 1;
int n_width = 0;
int m_width = 0;
int tmpwidth;
// fromleft indicates where the clip is done so I can 'get' chars from the other part
bool fromleft = (style == 3 && n % 2 == 0)? false : (style > 0);
while ( TRUE ) {
if ( n_width + m_width + dots_width > area_width ) break;
if ( n <= m ) break; // keep my sanity check (WTF), it should never happen 'cause of the above line
// Here are extra 'swap turn' conditions
if ( style == 3 && (!(n & 1)) )
fromleft = (!fromleft);
else if ( style < 2 )
fromleft = (!fromleft); // (1)'disables' turn swapping for styles 0, 1
if ( fromleft ) {
pdc->GetCharWidth(*(s+n-1), *(s+n-1), &tmpwidth);
n_width += tmpwidth;
n--;
}
else {
pdc->GetCharWidth(*(s+m-1), *(s+m-1), &tmpwidth);
m_width += tmpwidth;
m++;
}
fromleft = (!fromleft); // (1)
}
if ( fromleft ) m--; else n++;
// Final steps
// 1. CString version
CString* abbr = new CString;
abbr->Format("%*.*s...%*.*s", m-1, m-1, s, len-n, len-n, s + n);
return abbr;
/* 2. char* version, if you dont want to use CString (efficiency), replace CString with char*,
new CString with _strdup("") and use this code for the final steps:
char* abbr = (char*)malloc(m + (len-n) + 3 +1);
strncpy(abbr, s, m-1);
strcpy(abbr + (m-1), "...");
strncpy(abbr+ (m-1) + 3, s + n, len-n);
abbr[(m-1) + (len-n) + 3] = 0;
return abbr;
*/
}