UNICODE下での文字列のバイト数 – プログラミング – Home

UNICODE下での文字列のバイト数
 
通知
すべてクリア

[解決済] UNICODE下での文字列のバイト数

固定ページ 1 / 2

ブブゼラ
 ブブゼラ
(@ブブゼラ)
ゲスト
結合: 14年前
投稿: 6
Topic starter  

VC++ MFC SDI アプリです。
「UNICODE文字セットを使用する」でコンパイルしています。
文字列の総バイト数を求めたいのです。
例えば、
CString str = _T(12345あいうえお);
の場合、総バイト数は15なので、これを求めたいのですが、
int nLen = str.GetLength() * sizeof(TCHAR);
とすると、nLen には20が返ってきます。
ネット上で調べると、GetLength() * sizeof(TCHAR) でいいように書いてありますが、
どうやっても 文字数X2 の値が返ってきます。
バイト数を正しく取得する関数はないでしょうか?
よろしくお願いいたします。


引用未解決
トピックタグ
tetrapod
 tetrapod
(@tetrapod)
ゲスト
結合: 21年前
投稿: 830
 

文字セットとエンコーディングとは別物であることは理解している?
Windows 上で UNICODE というと、実際には UTF16 で BMP のみ利用、ということで
L12345あいうえお のバイト数は20になるよ。
12345あいうえお が15バイトになるのは MBCS の場合だ。


返信引用
tetrapod
 tetrapod
(@tetrapod)
ゲスト
結合: 21年前
投稿: 830
 

上記記述では \0 の分が入っていないので注意な
文字列の総バイト数だと UNICODE(UTF16) では 22 MBCS では 16 になるよ


返信引用
ブブゼラ
 ブブゼラ
(@ブブゼラ)
ゲスト
結合: 14年前
投稿: 6
Topic starter  

terapadさん、素早い応答で有り難うございます。
「バイト数」といったのがまずかったようです。文字列の「長さ」または「サイズ」と
いうべきでしょうか。
とにかく、12345あいうえお が15になるように求めたいのです。
よろしくお願いいたします。


返信引用
tetrapod
 tetrapod
(@tetrapod)
ゲスト
結合: 21年前
投稿: 830
 

UTF-16 エンコーディング配下では L12345あいうえお の
文字数は10 (GetLength の返す値)
バイト数(オクテット数)は20 (GetLength * sizeof(wchar_t))
なのであって、どこからどうやっても15などという数値は出てこない。
(\0 の分を含まず)

> 「長さ」または「サイズ」
とはなんのこと?それを定義しておくんなまし。


返信引用
ブブゼラ
 ブブゼラ
(@ブブゼラ)
ゲスト
結合: 14年前
投稿: 6
Topic starter  

例題ですが、
あいうえおかきくけこを TextOut で画面に書いたとき、その長さが20cmだとしま
す。(等幅フォント)
12345あいうえおを TextOut で書けば、約15cmになります。
では、123あいうは何cmになるでしょう?
9cmという答えが欲しいのです。


返信引用
ryo
 ryo
(@ryo)
ゲスト
結合: 23年前
投稿: 252
 

本当に表示上の長さがほしいのですか?

「半角を1、全角を2として、カウントしたい」ではなくて?


返信引用
tetrapod
 tetrapod
(@tetrapod)
ゲスト
結合: 21年前
投稿: 830
 

欲しいのは「画面上の大きさ」であるとして

いまどき「半角・全角」という用語にはほとんど意味がない。
(特に UNICODE を使うという状況下においては)
等幅フォントに限定すると後から困ること必至。

というわけで、多分やりたいことは GetTextExtent で出来る(と思う)
# GetOutputTextExtent とか GetTextExtentPoint32 とか
# 必要に応じて自分で調べて欲しい


返信引用
ブブゼラ
 ブブゼラ
(@ブブゼラ)
ゲスト
結合: 14年前
投稿: 6
Topic starter  

済みません。こっちの方です。
        ↓
「半角を1、全角を2として、カウントしたい」


返信引用
PATIO
(@patio)
Famed Member
結合: 3年前
投稿: 2660
 

なぜ、そのようなカウントがしたいのでしょう?

実際の画面上のサイズが知りたいのであれば、
まだわかるのですが、

「半角を1、全角を2として、カウントしたい」

とする用途が思い浮かびません。

MBCSでバイト数がほしいと言うのであれば話は別ですけれど。
使用するフォントによって画面上のサイズは変わるので
画面上のサイズがほしいのであれば、どのフォントを使った
時にこのサイズになるという言い方しか出来ません。
ちなみに画面上で半角文字が全角文字の半分のサイズになる
とは限りません。

何をしたくてそのようなカウントをしようとしているのかを
提示できれば、より適切なアドバイスがもらえるかもしれません。

単純にASCIIコードの領域を1とカウントしたいだけなのであれば、
文字コードのここからこの範囲は1で、それ以外は2と一文字ずつ
チェックしてカウントすれば良いだけだと思います。
関数一発でそれが取得できるというような事は無いと思います。


返信引用
NOR
 NOR
(@NOR)
ゲスト
結合: 23年前
投稿: 128
 

> 「半角を1、全角を2として、カウントしたい」

GetStringTypeExでC3_HALFWIDTHになるのが半角です。


返信引用
ブブゼラ
 ブブゼラ
(@ブブゼラ)
ゲスト
結合: 14年前
投稿: 6
Topic starter  

やりたいことを述べます。
用紙上に横書きで10cmの幅に、12345あいうえおを印刷したいです。
また、文字列があいうえおかきくけこと変わっても、同じ10cmの幅に印刷したい
です。
そのため、フォントのサイズを計算で求めたいのです。
GetOutputTextExtent で文字列の長さを得るには、フォントを先に設定しなければなら
ないので、堂々巡りになっちゃいます。


返信引用
maru
 maru
(@maru)
ゲスト
結合: 17年前
投稿: 358
 

> GetOutputTextExtent で文字列の長さを得るには、フォントを先に設定しなければな

> ないので、堂々巡りになっちゃいます。
どうして?
仮のフォントサイズを決めて長さを算出、その値でサイズを修正すればいいんじゃない
の?
まぁ、正確に10センチの幅に印刷できるかどうかは不明ですが。


返信引用
仲澤@失業者
(@uncle_kei)
Prominent Member
結合: 5年前
投稿: 828
 

>GetOutputTextExtent で文字列の長さを得るには、フォントを先に設定しなければなら
>ないので、堂々巡りになっちゃいます。

一般に、フォントが決まっていない状態では
「文字数とそれを描画したときのピクセル数とは無関係」
なので、文字数を求めてもあまり意味はありません。
つまり、その「堂々巡り」で解決する以外に方法はないわけです。

画面上の固定幅内に単一行で文字列の描画を行う場合のフォントの求め方は

1.GetDCでhDCを取得
2.仮のフォントを作成(CreateFontIndirect使用)
3.仮のフォントをHDCに選択
4.フォントメトリックスを取得(GetTextMetrics使用)
5.GetTextExtent()で描画時の幅を取得
6.固定幅との比較によりLOGFONTのlfHeightを調整
7.HDCのフォントの選択を解除
8.フォントを破棄
9.2.に戻る

てな感じです。頭悪そうな方法ですが、これ以外の
「画期的な方法」は見つかりませんでした(vv;)。


返信引用
NOR
 NOR
(@NOR)
ゲスト
結合: 23年前
投稿: 128
 

> 用紙上に横書きで10cmの幅に、12345あいうえおを印刷したいです。

12345あいうえおから15が欲しいのなら前述の通りGetStringTypeExで行けますが、
印刷幅の計算が目的なら、「半角を1、全角を2」は全く関係ありませんよ。
実際のフォントを使って調べないとわかりません。


返信引用
固定ページ 1 / 2

返信する

投稿者名

投稿者メールアドレス

タイトル *

プレビュー 0リビジョン 保存しました
共有:
タイトルとURLをコピーしました