none
文字列の扱い RRS feed

  • 質問

  • はじめまして。

    早速ですが、Visual Stadio 2005 VC++で開発しているのですが、

    文字のエンコード・デコード等がよくわかりません。

    できれば、普通の文字列(char)等で扱いたいのですが。

     

    txtServer.GetWindowTextW((LPTSTR)buf1,_MAX_PATH);

    とすると、buf1には半角文字の次にNULLが入ってきます。

     

     hModule = GetModuleHandle(_T("AutoUpdateSetup.exe"));
     ::GetModuleFileName(hModule, (LPWCH)EPath1, sizeof(EPath1));
    でも、EPath1には半角文字の次にNULLが入ってきます。

    さらに、パスに2バイト文字が入ると文字化けします。

     

    できれば、エンコードとかデコードと意識しないでコーディングできればと思っています。

    何か良い方法はあるのでしょうか?

    宜しくお願いいたします。

    2007年10月21日 7:17

回答

  • MFCを使っているのでしょうか?(質問時には必ず明記すべき)

    txtServer.GetWindowTextW((LPTSTR)buf1,_MAX_PATH);

    buf1はchar型配列ですか?
    だったらLPTSTR型に無理やりキャストするのは無茶があります。
    もとからchar型配列を渡せる、GetWindowTextA APIを経由すればchar型配列であ使える文字列が取得できます。

     

    char buf1[_MAX_PATH];

    ::GetWindowTextA(txtServer.GetSafeHwnd(), buf1, _MAX_PATH);

     

     

    とりあえず、「Unicode文字セットを使用する」を前提にしていて、それを意識しないでというのは無理です。

    →「マルチバイト文字セットを使用する」に変更するしかない

     

    また、TCHARの知識が不足しているように思えます。
    http://www.ruche-home.net/program/tips/tchar.php

    を参考にしてみてください。

     

    それと、MFCならCStringAクラスを使うとUnicode文字列の変換が簡単に行えます。


    char buf1[_MAX_PATH];

    txtServer.GetWindowTextW((LPTSTR)buf1,_MAX_PATH);

     

    なら

     

    CString buf1;

    txtServer.GetWindowText(buf1);

    CStringA buf2(buf1);  // ここでCStringAクラスが文字コード変換してくれる※

    char buf3[_MAX_PATH];

    strcpy_s(buf3, buf2);

    ※変換できない文字はどうなるかは微妙。多分変換できたとこまでの文字列になるような。

     

    とすれば(マルチバイト文字列に変換された文字列が)char型配列に文字列を入れることができます。

    (comdef.hの_bstr_tクラスも使えます。)

     

     hModule = GetModuleHandle(_T("AutoUpdateSetup.exe"));
     ::GetModuleFileName(hModule, (LPWCH)EPath1, sizeof(EPath1));

    こちらの場合は、GetModuleFileNameAを使えば終わり。

     

    char EPath1[_MAX_PATH];

    HANDLE hModule = GetModuleHandle(_T("AutoUpdateSetup.exe"));

    ::GetModuleFileNameA(hModule, EPath1, sizeof(EPath1));

     

     

     

     

    で、やはり、char型を使うってことを前提に考えないほうが良いかと思います。(TCHARを前提にすべき)

    char型を使わなければならない前提があるのでしょうか?

    # というか char型配列が普通の文字列と思っている時点でなんか違うような。

    # wchar_t型配列でも同様に文字列として扱うことができるのですけどね。

    2007年10月21日 7:41

すべての返信

  • MFCを使っているのでしょうか?(質問時には必ず明記すべき)

    txtServer.GetWindowTextW((LPTSTR)buf1,_MAX_PATH);

    buf1はchar型配列ですか?
    だったらLPTSTR型に無理やりキャストするのは無茶があります。
    もとからchar型配列を渡せる、GetWindowTextA APIを経由すればchar型配列であ使える文字列が取得できます。

     

    char buf1[_MAX_PATH];

    ::GetWindowTextA(txtServer.GetSafeHwnd(), buf1, _MAX_PATH);

     

     

    とりあえず、「Unicode文字セットを使用する」を前提にしていて、それを意識しないでというのは無理です。

    →「マルチバイト文字セットを使用する」に変更するしかない

     

    また、TCHARの知識が不足しているように思えます。
    http://www.ruche-home.net/program/tips/tchar.php

    を参考にしてみてください。

     

    それと、MFCならCStringAクラスを使うとUnicode文字列の変換が簡単に行えます。


    char buf1[_MAX_PATH];

    txtServer.GetWindowTextW((LPTSTR)buf1,_MAX_PATH);

     

    なら

     

    CString buf1;

    txtServer.GetWindowText(buf1);

    CStringA buf2(buf1);  // ここでCStringAクラスが文字コード変換してくれる※

    char buf3[_MAX_PATH];

    strcpy_s(buf3, buf2);

    ※変換できない文字はどうなるかは微妙。多分変換できたとこまでの文字列になるような。

     

    とすれば(マルチバイト文字列に変換された文字列が)char型配列に文字列を入れることができます。

    (comdef.hの_bstr_tクラスも使えます。)

     

     hModule = GetModuleHandle(_T("AutoUpdateSetup.exe"));
     ::GetModuleFileName(hModule, (LPWCH)EPath1, sizeof(EPath1));

    こちらの場合は、GetModuleFileNameAを使えば終わり。

     

    char EPath1[_MAX_PATH];

    HANDLE hModule = GetModuleHandle(_T("AutoUpdateSetup.exe"));

    ::GetModuleFileNameA(hModule, EPath1, sizeof(EPath1));

     

     

     

     

    で、やはり、char型を使うってことを前提に考えないほうが良いかと思います。(TCHARを前提にすべき)

    char型を使わなければならない前提があるのでしょうか?

    # というか char型配列が普通の文字列と思っている時点でなんか違うような。

    # wchar_t型配列でも同様に文字列として扱うことができるのですけどね。

    2007年10月21日 7:41
  • 早速の回答ありがとうございます。

    本当に助かりました。

    私自身、自分のスキル不足は認識しています。

    また、お世話になると思いますので。

    その節は宜しくお願い致します。

     

    本当にありがとうございました。

     

     

    2007年10月21日 8:16
  • お世話になっております。

    教えを参考にさせて頂、コードを全面的に見直しました。

    (.h)

    public:
     TCHAR FNameIni[_MAX_PATH];
     TCHAR FNameServer[_MAX_PATH];
     TCHAR FNameClient[_MAX_PATH];

     

    (.cpp)

     TCHAR   EPath[_MAX_PATH];
        TCHAR   *p;
     HMODULE hModule;

     memset(FNameIni,   NULL,sizeof(FNameIni));
     memset(FNameServer,NULL,sizeof(FNameServer));
     memset(FNameClient,NULL,sizeof(FNameClient));
     memset(EPath,      NULL,sizeof(EPath));

     hModule = GetModuleHandle(_T("AutoUpdateSetup.exe"));
     ::GetModuleFileName(hModule, EPath, sizeof(EPath));

     p = ::wcsrchr(EPath,'\\');
     if(p != NULL)
     {
      *(p+1) = NULL;
     }
       
     swprintf_s(FNameIni,sizeof(FNameIni),_T("%s%s"),EPath,_T("AutoUpDate.ini"));

     FILE    *fp;
     TCHAR   *e;
     TCHAR   buf[_MAX_PATH];
        int     no = 0;

     if( _wfopen_s( &fp, FNameIni, _T("r") ) )
     {
     }else{
      while(1)
      {
       if( (e = fgetws( buf, _MAX_PATH, fp )) == NULL )
       {
        break;
       }else{
        switch(no)
        {
        case 0: swprintf_s(FNameServer,_T("%s"),buf); break;
        case 1: swprintf_s(FNameClient,_T("%s"),buf); break;
        }
        no++;
       }
      }
      fclose( fp );
     }

     p = ::wcsrchr(FNameServer,0x0A);
        if(p != NULL) *(p) = NULL;
     p = ::wcsrchr(FNameServer,0x0D);
        if(p != NULL) *(p) = NULL;
     p = ::wcsrchr(FNameClient,0x0A);
        if(p != NULL) *(p) = NULL;
     p = ::wcsrchr(FNameClient,0x0D);
        if(p != NULL) *(p) = NULL;

        txtServer.SetWindowTextW(FNameServer);
        txtClient.SetWindowTextW(FNameClient);

     FILE    *fp;
     TCHAR   buf[_MAX_PATH];

     if( _wfopen_s( &fp, FNameIni, _T("w") ) )
     {
     }else{
            memset(buf,NULL,sizeof(buf));
            txtServer.GetWindowTextW(buf,_MAX_PATH);
      fputws(buf,fp);
      fputws(_T("\n"),fp);

            memset(buf,NULL,sizeof(buf));
            txtClient.GetWindowTextW(buf,_MAX_PATH);
            fputws(buf,fp);
      fputws(_T("\n"),fp);

      fclose( fp );
    です。

    大変すっきりとした内容になりました。

    ただ、1点、  fputws(buf,fp);を実行すると、"C:\yo1\日本語\tset.exe"の

    "C:\yo1"まではファイルに書き込めるのですが、日本語の部分以下が書き込めませんでした。

    これは、fputws関数の使用が間違っているのでしょうか?

    宜しくお願い致します。


     

    2007年10月21日 9:27