WCHARの1文字比較

解決


すだこ  2007-09-21 18:15:23  No: 66400

VS2005でMFCアプリケーションを作成していますが、CStringを
使わずに処理しようと思っています。
charの配列の末尾から半角空白と改行コード(\r\n)を削除するのに
下のコードを使っていました。
TrimRigth(char* pcRec)
{
  long  lCnt;
  lCnt = strlen(pcRec)-1;
  for(long l=lCnt;l>=0;l--){
    if(pcRec[l] == ' '){
      pcRec[l] = '\0';
    }else if(pcRec[l] == '\n'){
      pcRec[l] = '\0';
    }else if(pcRec[l] == '\r'){
      pcRec[l] = '\0';
    }else{
      break;
    }
  }
}

これをUNICODE対応のプログラムで使おうと思い次のように修正しました。
( _T()で括っているのは試行錯誤時の名残です)
TrimRigth(WCHAR* pcRec)
{
  long  lCnt;
  lCnt = wcslen(pcRec)-1;
  for(long l=lCnt;l>=0;l--){
    if(pcRec[l] == ' '){
      pcRec[l]=_T('\0');
    }else if(pcRec[l] == _T('\n')){
      pcRec[l]=_T('\0');
    }else if(pcRec[l] == _T('\r')){
      pcRec[l]=_T('\0');
    }else{
      break;
    }
  }
}

この処理だと、半角空白は削除されるのですが改行コードは削除
されませんでした。
エディットボックス内の改行コード"\r\n"では0x1000が入ってくるし
テキストファイルから取得したデータでは、0x10が入っているのに
なぜか「}else if(pcRec[l] == _T('\n')){」ここにヒットしてくれません。
仕方がないので現在は下のようにしています。
}else if(pcRec[l] == 4096){  // 16進の0x1000
}else if(pcRec[l] == 10){    // 16進の0x0a
}else if(pcRec[l] == 13){    // 16進の0x0d

UNICODEの場合は、2バイトで1文字というのは分かっているのですが
この場合、\r\nのコードは「0D 00 0A 00」という感じで入っていて
0x1000とはこの2バイト分を見ているから、「0A 00」がそういう風に見え
ているのだと思います。(半角空白が1バイトで見えているのは説明できませんが)

そこで質問なんですが、UNICODEの2バイト1文字の1文字ずつ比較するには
どうしたら良いのでしょうか?
よろしくお願いします。


tetrapod  2007-09-21 19:45:04  No: 66401

TCHAR で切り替えるのではなくて常に UNICODE にしたいの?
ならば if (c==L'\n') で OK
というか _T('x') をすべて L'x' に置き換えるといい。
お試しコード
#include <stdio.h>
#include <string.h>
int main() {
    wchar_t const text[]=L"a\nb\r\n機能\n";
    size_t i, n=wcslen(text);
    for (i=0; i<n; ++i) {
  printf("%04X ", text[i]);
  if (text[i]==L'\r') printf("CR ");
  if (text[i]==L'\n') printf("LF ");
    }
    return 0;
}


すだこ  2007-09-25 18:57:04  No: 66402

tetrapodさん、回答ありがとうございます。
色々やってみたのですが、ファイルから読み込んだ
改行コード(\r\n)は
if (text[i]==L'\r')
if (text[i]==L'\n')
これにヒットするようになりました。
しかし、エディットボックスの改行のみの行に入って
いる改行コードはやはりダメでした。

不思議なのは、「文字+改行」だと改行コードは付加されていないのに
「改行」のみだと改行コード(0x1000)が入ってきます。
UNICODEコンパイル時のエディットボックスの改行はマルチバイトの
時と違うんですかね。。。
もしかしたら改行コードではないのかもしれませんが、
エディットボックスの改行は
}else if(pcRec[l] == 4096){ // 16進の0x1000
これで削除するようにしました。

まだ作業中ですので、他に何か情報がありましたら、よろしくお願いします。


subaru  2007-09-25 19:49:50  No: 66403

エディットボックスの値をどのように取得しているのでしょうか?
UNICODEコンパイルでも改行は\r\nだと思うのですが。


すだこ  2007-09-25 20:12:46  No: 66404

>UNICODEコンパイルでも改行は\r\nだと思うのですが。
そうですよね、だからコレは改行コードではないような気がしてきています。
改行のみの行にしか入ってきませんし。

エディットボックスの行データの取得は以下のようにしています。

CEdit m_Edit05;  // 本当はヘッダー定義
TCHAR wzBuff[2048];
long  lMax;

lMax = m_Edit05.GetLineCount();
for(long l=0L;l<lMax;l++){
    memset(wzBuff, '\0', sizeof(wzBuff));
    m_Edit05.GetLine(l, wzBuff, sizeof(wzBuff));
    TrimRight(wzBuff);  // これが例の関数
}


subaru  2007-09-25 21:05:03  No: 66405

CEdit::GetLineの仕様みたいです。
http://msdn2.microsoft.com/ja-jp/library/7775836w(VS.80).aspx

 lpszBuffer
 コピーされる行を受け取るバッファへのポインタ。バッファの最初のワードには、バッファにコピーできる最大バイト数を指定します。

バッファの最初のワード値が上書きされないままゴミになってるのではないでしょうか。
戻り値で実際にコピーされた文字数を調べる必要がありそうです。


すだこ  2007-09-25 23:08:57  No: 66406

subaruさん、ありがとうございます。
正体不明な値の対応をするよりも、GetLine()の戻り値を見て
処理をしないようする方が正しいと思いますので
GetLine()の戻り値が0の場合は処理しないようにしました。
これで、スッキリしました。
ありがとうございます。


※返信する前に利用規約をご確認ください。

※Google reCAPTCHA認証からCloudflare Turnstile認証へ変更しました。






  このエントリーをはてなブックマークに追加