全角文字列取得
全角文字列取得
初めまして、いけやんと申します。
さっそく質問します。
開発環境
Windows XP sp2
Visual C++6.0
MFC ダイアログベース
----+--------+--------------------
2000|02-00-00|《ああああああ》
2000|02-01-00| いい掛/うう
現在上記の様な、テキストデータを読み込んで、CTreeCtrlに表示させているのですが
今strtok関数を使ってテキストの中の必要のない物をどけて、文字列を摘出しています。
しかしstrtok関数は、半角の物を意識して作ってあるらしく
全角文字列を読み込ませるのは、よろしくないみたいです。
実際に今のプログラムでは、
実行結果
<<ああああああ>>
いい
/うう
「掛」この文字だけなくなり、
こういった表示になります。
原因は、「全角1文字を半角2文字として扱うため、
場合によっては全角文字の一部が区切り文字と誤認識され、ぶった切られます。」
なので、wcstok関数を使えば全角文字列も読み込み
できるみたいなのでwcstok関数を使う事にしました。
リファレンスより
wchar_t *wcstok(
wchar_t *strToken,
const wchar_t *strDelimit
);
wcstokの第一引数をUnsigned shortに変換に変換できません
というエラーがでます。
http://hw001.gate01.com/eggplant/tcf/cp ... _trap.html
この関係なんですかね?
無理やりですが、キャストしたりしてみてもエラーがでます。
使い方に困っています。
なので、wcstok関数の使い方がわかる方
すいませんが、お願いたします。
またwcstok関数以外でも結構ですので
よろしくお願いします。
さっそく質問します。
開発環境
Windows XP sp2
Visual C++6.0
MFC ダイアログベース
----+--------+--------------------
2000|02-00-00|《ああああああ》
2000|02-01-00| いい掛/うう
現在上記の様な、テキストデータを読み込んで、CTreeCtrlに表示させているのですが
今strtok関数を使ってテキストの中の必要のない物をどけて、文字列を摘出しています。
しかしstrtok関数は、半角の物を意識して作ってあるらしく
全角文字列を読み込ませるのは、よろしくないみたいです。
実際に今のプログラムでは、
実行結果
<<ああああああ>>
いい
/うう
「掛」この文字だけなくなり、
こういった表示になります。
原因は、「全角1文字を半角2文字として扱うため、
場合によっては全角文字の一部が区切り文字と誤認識され、ぶった切られます。」
なので、wcstok関数を使えば全角文字列も読み込み
できるみたいなのでwcstok関数を使う事にしました。
リファレンスより
wchar_t *wcstok(
wchar_t *strToken,
const wchar_t *strDelimit
);
wcstokの第一引数をUnsigned shortに変換に変換できません
というエラーがでます。
http://hw001.gate01.com/eggplant/tcf/cp ... _trap.html
この関係なんですかね?
無理やりですが、キャストしたりしてみてもエラーがでます。
使い方に困っています。
なので、wcstok関数の使い方がわかる方
すいませんが、お願いたします。
またwcstok関数以外でも結構ですので
よろしくお願いします。
Re:全角文字列取得
これがソースです。
CStdioFile fin;//ファイル変数 CString str;//1行文読込用 int i = 0,count; if ( !fin.Open("部材.txt", CFile::modeRead, NULL ) ) {return -1;} while ( fin.ReadString(str) != NULL ) { int i = 0; reinterpret_cast<unsigned short *>(str); for (const char *token = wcstok(str.GetBuffer(str.GetLength()),"+-|0123456789 "); token != NULL; token = wcstok(0,"-+|0123456789 ")){ m_HndTree[0] = m_tree.InsertItem(token,TVI_ROOT); m_HndTree[1] = m_tree.InsertItem(token,m_HndTree[0]); 省略 }
Re:全角文字列取得
第1引数は、ポインターでなければならないはずです。 私はwcstok関数を使ったことがないのでナニですが、 > token = wcstok(0,"-+|0123456789 ")){ ここの第1引数は NULL あたりにしなければならないのではないでしょうか。
Re:全角文字列取得
部材.txtはシフトJISで書かれているのですよね
掛の0x7Cが'|'とかぶりますね
wcstok( )を使うにはUTF-16にコンバートしないといけません
ファイル自体を変えるか読み込んでから
MultiByteToWideChar( )
で変更するか
でもファイル自体の文字コードを変更できるならEUC-JPにしたら区切り文字とかぶることはなくなりますよ
掛の0x7Cが'|'とかぶりますね
wcstok( )を使うにはUTF-16にコンバートしないといけません
ファイル自体を変えるか読み込んでから
MultiByteToWideChar( )
で変更するか
でもファイル自体の文字コードを変更できるならEUC-JPにしたら区切り文字とかぶることはなくなりますよ
Re:全角文字列取得
すいません返信遅れました。
>token = wcstok(0,"-+|0123456789 ")){
直しました。ありがとうございます。
すいません。文字コードの前に
文字列をキャストしているところエラーが出てました。
すいませんが、CStringからunsgined shortへの変換の仕方
教えて頂けないでしょうか。お願いします。
>token = wcstok(0,"-+|0123456789 ")){
直しました。ありがとうございます。
すいません。文字コードの前に
文字列をキャストしているところエラーが出てました。
reinterpret_cast<unsigned short *>(str); for (const char *token = wcstok(str.GetBuffer(str.GetLength()),"+-|0123456789 ");//エラー token != NULL; token = wcstok(NULL,"+-|0123456789 ") ) {//エラーclass CString' から 'unsigned short *' に変換することはできません。
すいませんが、CStringからunsgined shortへの変換の仕方
教えて頂けないでしょうか。お願いします。
Re:全角文字列取得
単純なキャストだとASCII文字が2文字で1文字として扱われてしまうのでだめですね
wchar_t型にするなら文字コードもユニコードにするのが本来の使い方だと思います
wchar_t buf[256];
MultiByteToWideChar(CP_THREAD_ACP, MB_PRECOMPOSED, str, 256, buf, 256);
でどうでしょう
あとwcstok関数は第2引数もwchar_t型なので
wcstok(NULL, L"+-|0123456789 ")
とLを付けないといけませんね
個人的な意見としてはマルチバイト文字をユニコード用の関数で扱うのはあまりいいやり方ではないような気がします。
自分ならstr.Mid( )で1バイトずつチェックして0x80以上なら2バイト文字なので読み飛ばすようにします。
wchar_t型にするなら文字コードもユニコードにするのが本来の使い方だと思います
wchar_t buf[256];
MultiByteToWideChar(CP_THREAD_ACP, MB_PRECOMPOSED, str, 256, buf, 256);
でどうでしょう
あとwcstok関数は第2引数もwchar_t型なので
wcstok(NULL, L"+-|0123456789 ")
とLを付けないといけませんね
個人的な意見としてはマルチバイト文字をユニコード用の関数で扱うのはあまりいいやり方ではないような気がします。
自分ならstr.Mid( )で1バイトずつチェックして0x80以上なら2バイト文字なので読み飛ばすようにします。
Re:全角文字列取得
う~ん、MultiByteToWideCharを使ってみたのですが
やっぱりchar * から unsigned short *変換できません
エラーになりますね。
>あまりいいやり方ではないような気がします。
これは、下記の様な無理?に変換して使うのは、
あまりよろしくないという事ですね?
MultiByteToWideChar(CP_THREAD_ACP, MB_PRECOMPOSED, str, 256, buf, 256);
>str.Mid( )で1バイトずつチェックして0x80以上なら2バイト文字なので読み飛ばすようにします。
toyoさんありがとうございます。
上記の件試したいと思います。
あまりC初心者なので、エラー出しながらなので、返信遅くなると思います。
やっぱりchar * から unsigned short *変換できません
エラーになりますね。
if ( !fin.Open("部材.txt", CFile::modeRead, NULL ) ) {return -1;} while ( fin.ReadString(str) != NULL ) { int i = 0; MultiByteToWideChar(CP_THREAD_ACP,MB_PRECOMPOSED,str,256,buf,256); //const char *str2 = new char[str.GetLength()+1] = strcpy(str2,str); //reinterpret_cast<unsigned short *>(str); for (const char *token = wcstok(str.GetBuffer(str.GetLength()),L"+-|0123456789 "); token != NULL; token = wcstok(NULL,L"+-|0123456789 ") ) {>個人的な意見としてはマルチバイト文字をユニコード用の関数で扱うのは
>あまりいいやり方ではないような気がします。
これは、下記の様な無理?に変換して使うのは、
あまりよろしくないという事ですね?
MultiByteToWideChar(CP_THREAD_ACP, MB_PRECOMPOSED, str, 256, buf, 256);
>str.Mid( )で1バイトずつチェックして0x80以上なら2バイト文字なので読み飛ばすようにします。
toyoさんありがとうございます。
上記の件試したいと思います。
あまりC初心者なので、エラー出しながらなので、返信遅くなると思います。
Re:全角文字列取得
Visual C++6.0 で可能かどうか分かりませんが、以下の方法はどうでしょうか。
wchar_t buf[256]; swprintf(buf,L"%S",str);もし実行時に日本語部分が出なければ、以下の処理を事前に実行しておくと出ると思います。
// ↓をインクルードする // #include <locale.h> set_locale(LC_ALL,"jpn");MultiByteToWideChar でも上記処理は有効だと思います。
Re:全角文字列取得
返信、遅くなってすいません。
>Visual C++6.0 で可能かどうか分かりませんが、以下の方法はどうでしょうか。
>もし実行時に日本語部分が出なければ、以下の処理を事前に実行しておくと出ると思います。
御津凪さん参考にさして頂きます。
>自分ならstr.Mid( )で1バイトずつチェックして0x80以上なら2バイト文字なので読み飛ばすようにします。
リファレンスを見ながらやってみたのが
下記の警告がでます。
argument 'const int' から 'char' へ切り詰めます
引数で怒られているみたいなのですが、
使い方をご教授頂けないでしょうか?
>Visual C++6.0 で可能かどうか分かりませんが、以下の方法はどうでしょうか。
>もし実行時に日本語部分が出なければ、以下の処理を事前に実行しておくと出ると思います。
御津凪さん参考にさして頂きます。
>自分ならstr.Mid( )で1バイトずつチェックして0x80以上なら2バイト文字なので読み飛ばすようにします。
リファレンスを見ながらやってみたのが
下記の警告がでます。
argument 'const int' から 'char' へ切り詰めます
引数で怒られているみたいなのですが、
使い方をご教授頂けないでしょうか?
#define String str2 while ( fin.ReadString(str) != NULL ) { //MultiByteToWideChar(CP_THREAD_ACP,MB_PRECOMPOSED,str,256,buf,256); if(str.Mid(2) >= 0x80 ){ str2 = str.Mid(1); m_HndTree[0] = m_tree.InsertItem(String,TVI_ROOT); m_HndTree[1] = m_tree.InsertItem(String,m_HndTree[0]);
Re:全角文字列取得
test用のプログラムを作ってみました
参考になりますでしょうか
参考になりますでしょうか
// 対象文字列 CString str = "2000|02-01-00| いい掛/うう"; // 抜き出し用文字列 CString str2; // 対象文字列の長さ(バイト数で文字数ではない)だけ繰り返す for (int i = 0; i < str.GetLength(); i++) { // 区切り文字でない場所を探す if (str == '+' || str == '-' || str == '|' || (str >= '0' && str <= '9') || str == ' ') { continue; } // 文字列抜き出しの開始 str2.Empty(); while (i < str.GetLength()) { // 区切り文字があればそこで抜き出し終了 if (str == '+' || str == '-' || str == '|' || (str >= '0' && str[i] <= '9') || str[i] == ' ') { break; } // 抜き出し用の文字列に1バイト追加 str2 += str[i]; // 2バイト文字の場合は無条件でもう1バイト追加 // 0xA1-0xDFは半角カナで1バイトなので除外 if ((UCHAR)str[i] >= 0x80 && ((UCHAR)str[i] < 0xA1 || (UCHAR)str[i] > 0xDF)) { i++; str2 += str[i]; } i++; } // 確認用のメッセージボックス表示 AfxMessageBox(str2, MB_OK, 0); }
Re:全角文字列取得
2バイト文字を弾いてコピーする関数を作っては駄目ですか?
void Copy1ByteOnly(unsigned char *src,unsigned char *dest){ //オーバフロー対策はしてません。 while(*src){ if((*src>=0x81 && *src<=0x9F) || (*src>=0xE0 && *src<=0xFC)) //2byteなら src++; //取り敢えず1byte進める else *dest++=*src; src++; } *dest='\0'; }
Re:全角文字列取得
toyoさん、lbfuvabさん
サンプルありがとうございます。
すいませんが、上記のサンプルで解らない部分があり
自分的には、解らない所を解らないまま書くのは
良くないと思っているので、教えて頂けないでしょう?
①str2.Empty();
リファレンスを見ても「空の文字列を表します。このフィールドは読み取り専用です。 」
としか書いてありませんでした。
これはEmpty()関数で、str2を初期化する又は、空にするという解釈で合っていますか?
お願いします。
②0x80が2バイトなら・・・、0xA1-0xDFは半角カナで1バイト、等と書いてあるのですが
どこで、そういった事が解るのですか?
「文字コード」で検索してもありませんでした。
基本的な事なら、すいません。
教えて頂けないでしょうか?
「○○○」で調べて、出直して来いでも結構です。お願いします。
サンプルありがとうございます。
すいませんが、上記のサンプルで解らない部分があり
自分的には、解らない所を解らないまま書くのは
良くないと思っているので、教えて頂けないでしょう?
①str2.Empty();
リファレンスを見ても「空の文字列を表します。このフィールドは読み取り専用です。 」
としか書いてありませんでした。
これはEmpty()関数で、str2を初期化する又は、空にするという解釈で合っていますか?
お願いします。
②0x80が2バイトなら・・・、0xA1-0xDFは半角カナで1バイト、等と書いてあるのですが
どこで、そういった事が解るのですか?
「文字コード」で検索してもありませんでした。
基本的な事なら、すいません。
教えて頂けないでしょうか?
「○○○」で調べて、出直して来いでも結構です。お願いします。
Re:全角文字列取得
str2.Empty(); に関してはstr2の初期化(文字列を空にする)であっています。
str2 = "";
でも同じです。
文字コードの件ですが
「shift jis コード表」あたりで検索すると出てくるかもしれません
実際には1バイト目はlbfuvabさんのように
(*src>=0x81 && *src<=0x9F) || (*src>=0xE0 && *src<=0xFC)
のほうがより正確です。
厳密に言うと2バイト目も0x40~0x7E, 0x80~0xFCになるのをチェックしないといけないのでしょうが
今回の例ではASCII文字と半角カナ以外で始まる文字をすべて2バイト文字として扱いました。
str2 = "";
でも同じです。
文字コードの件ですが
「shift jis コード表」あたりで検索すると出てくるかもしれません
実際には1バイト目はlbfuvabさんのように
(*src>=0x81 && *src<=0x9F) || (*src>=0xE0 && *src<=0xFC)
のほうがより正確です。
厳密に言うと2バイト目も0x40~0x7E, 0x80~0xFCになるのをチェックしないといけないのでしょうが
今回の例ではASCII文字と半角カナ以外で始まる文字をすべて2バイト文字として扱いました。
Re:全角文字列取得
toyoさんありがとうございます。
shift jis コード表で調べてみます。
後、本当に勝手なのですが、
これから、ちょっと連休に入るのでサンプル等の返事が
来週の水曜なると思いますので
ご了承下さい。
shift jis コード表で調べてみます。
後、本当に勝手なのですが、
これから、ちょっと連休に入るのでサンプル等の返事が
来週の水曜なると思いますので
ご了承下さい。
Re:全角文字列取得
返信遅くなりました。文字列表示できました。
下記で解決しました。
shift jisの件,
調べてみるとあるページに下記の事が書いてありました。
制御コード
0x00~0x1F、0x7F
ASCII文字
0x20~0x7E
半角カタカナ
0xA1~0xDF
漢字
0x8140~0x9FFC、0xE040~0xFCFC
(第1バイト: 0x81~0x9F、0xE0~0xFC 第2バイト: 0x40~0x7E、0x80~0xFC)
すいません、もう少し聞きたいのですが
>実際には1バイト目はlbfuvabさんのように
>(*src>=0x81 && *src<=0x9F) || (*src>=0xE0 && *src<=0xFC)
>厳密に言うと2バイト目も0x40~0x7E, 0x80~0xFCになるのをチェックしないといけないのでしょうが
上記の事を自分なりに解釈すると、
もう少し厳密な、2byte漢字処理が必要という事ですか?
またそれは、何のために必要なんでしょうか?
お手数ですが、お願いします。
<!--1
下記で解決しました。
if ( !fin.Open("部材.txt", CFile::modeRead, NULL ) ) {return -1;} while ( fin.ReadString(str) != NULL ) { toyoさんのサンプル m_HndTree[0] = m_tree.InsertItem(String,TVI_ROOT); }toyoさんのサンプルを殆ど使わして頂きました。
shift jisの件,
調べてみるとあるページに下記の事が書いてありました。
制御コード
0x00~0x1F、0x7F
ASCII文字
0x20~0x7E
半角カタカナ
0xA1~0xDF
漢字
0x8140~0x9FFC、0xE040~0xFCFC
(第1バイト: 0x81~0x9F、0xE0~0xFC 第2バイト: 0x40~0x7E、0x80~0xFC)
すいません、もう少し聞きたいのですが
>実際には1バイト目はlbfuvabさんのように
>(*src>=0x81 && *src<=0x9F) || (*src>=0xE0 && *src<=0xFC)
>厳密に言うと2バイト目も0x40~0x7E, 0x80~0xFCになるのをチェックしないといけないのでしょうが
上記の事を自分なりに解釈すると、
もう少し厳密な、2byte漢字処理が必要という事ですか?
またそれは、何のために必要なんでしょうか?
お手数ですが、お願いします。
<!--1
Flying Fly
Bugさんのつくっていた「Flying Fly」と言うゲームを
友人に見せようと思ったのですがどこにおいてあるのでしょうか?
「その他のソフト紹介」の中にも見当たりません。<!--23-->
友人に見せようと思ったのですがどこにおいてあるのでしょうか?
「その他のソフト紹介」の中にも見当たりません。<!--23-->