Преобразование различных строковых типов в MFC
От: RussianFellow Россия http://russianfellow.livejournal.com
Дата: 08.12.16 13:33
Оценка:
Как преобразовать между собой различные строковые типа в MFC?

Есть типы char* ( char[] ), wchar* ( wchar[] ), std::string, LPTSTR, LPCTSTR, CString и другие. Как преобразовывать данные из одного такого типа в другой?
1613 г. = 2024 г.
Re: Преобразование различных строковых типов в MFC
От: Evgeniy Skvortsov Россия  
Дата: 08.12.16 14:06
Оценка:
Здравствуйте, RussianFellow, Вы писали:

RF>Есть типы char* ( char[] ), wchar* ( wchar[] ), std::string, LPTSTR, LPCTSTR, CString и другие. Как преобразовывать данные из одного такого типа в другой?


В общем случае никак.
Для перевода из анси в юникод — WideCharToMultiByte и MultiByteToWideChar или макросы T2A и A2T, но их нужно использовать осторожно, есть побочные эффекты.

Классы имеют конструкторы принимающие указатели, а так же функции возвращающие указатель типа c_str()

Так что, что конкретно тебе нужно в данном случае, то и используй.
Отредактировано 08.12.2016 14:07 Evgeniy Skvortsov . Предыдущая версия .
Re: Преобразование различных строковых типов в MFC
От: SkyKnight Швейцария https://github.com/dmitrigrigoriev/
Дата: 08.12.16 16:25
Оценка:
Здравствуйте, RussianFellow, Вы писали:

RF>Как преобразовать между собой различные строковые типа в MFC?


RF>Есть типы char* ( char[] ), wchar* ( wchar[] ), std::string, LPTSTR, LPCTSTR, CString и другие. Как преобразовывать данные из одного такого типа в другой?


LPTSTR в зависимости юникодный у тебя проект или нет будут либо char* или wchar*

У CString есть соотвествующий конструктор, чтобы создать из char* или wchar*

преобразовать из char в wchar уже описали выше. Я бы пользовал только функции, потому что макросы, по-моему, используют стек для конвертации.

std::string это не MFC-шный тип.
github.com/dmitrigrigoriev/
Re: Преобразование различных строковых типов в MFC
От: VladFein США  
Дата: 16.12.16 18:40
Оценка:
Здравствуйте, RussianFellow, Вы писали:

RF>Как преобразовать между собой различные строковые типа в MFC?


RF>Есть типы char* ( char[] ), wchar* ( wchar[] ), std::string, LPTSTR, LPCTSTR, CString и другие. Как преобразовывать данные из одного такого типа в другой?


MFC-way:

    CString csA("Narrow");
    CString csW(L"Wide");
    CStringA csA2(csW);
    CStringW csW2(csA);
Re: Преобразование различных строковых типов в MFC
От: RussianFellow Россия http://russianfellow.livejournal.com
Дата: 27.12.17 06:35
Оценка:
Я нашёл хорошую статью на эту тему:

https://habrahabr.ru/post/164193/
1613 г. = 2024 г.
Re: Преобразование различных строковых типов в MFC
От: Carc Россия https://vk.com/gosha_mazov
Дата: 28.12.17 11:59
Оценка:
Здравствуйте, RussianFellow, Вы писали:

RF>Как преобразовать между собой различные строковые типа в MFC?


RF>Есть типы char* ( char[] ), wchar* ( wchar[] ), std::string, LPTSTR, LPCTSTR, CString и другие. Как преобразовывать данные из одного такого типа в другой?


Моя поделка, завязана на WinAPI, но напрочь отвязана ото всяких MFC\ATL\WTL
  WPString (Header)
// WPString.h: interface for the WPString class.
//
//////////////////////////////////////////////////////////////////////

#if !defined(AFX_WPSTRING_H__A1A6494F_67C6_494A_81BA_4B053AEDA19D__INCLUDED_)
#define AFX_WPSTRING_H__A1A6494F_67C6_494A_81BA_4B053AEDA19D__INCLUDED_

#if _MSC_VER > 1000
#pragma once
#endif // _MSC_VER > 1000

#include <string>

typedef std::basic_string<char>        astring;
typedef std::basic_string<wchar_t>    wstring;

#define SAFE_COPY_STRING(t,s) {_tcsncpy(t,s,sizeof(t)/sizeof(t[0]-1));}

class WPString  
{
public:
    static wstring _OemStringToWide(LPCSTR lpszSrc);

    static int CompareWP(LPCTSTR sz1, LPCTSTR sz2, const BOOL bCaseSensitive);
    static int FindInStrWP2(const LPCTSTR lpszFindString
                              , LPCTSTR lpszText
                              , const BOOL bCaseSensitive
                              ,const int nStart);


    static astring _AStringToUTF8(LPCSTR lpszSrc);

    static astring _WideStringToCodePage(LPCWSTR lpszW, const DWORD code_page);
    static astring _WideStringToACP(LPCWSTR lpszW);
    static astring _WideStringToUTF(LPCWSTR lpszWide);
    
    static wstring _UTFStringToWide(LPCSTR lpszUTF8);
    static astring _UTFStringToANSI(LPCSTR lpszUTF8);

    static wstring _AStringToWide(LPCSTR lpszSrc);
    static wstring _AStringToWide_ByANSICodePageThread(LPCSTR lpszSrc);
    static wstring _MBStringToWideWithCodePage(LPCSTR lpszSRC, const DWORD dwCodePage);
    
private:
    static astring _Internal_WideStringToMBCS(LPCWSTR lpszWide, const UINT nMBCodePage);
    static wstring _Internal_MBStringToWide(LPCSTR lpszSrc, const UINT nSrcCodePage);
    
};

#endif // !defined(AFX_WPSTRING_H__A1A6494F_67C6_494A_81BA_4B053AEDA19D__INCLUDED_)



  WPString implementation
// WPString.cpp: implementation of the WPString class.
//
//////////////////////////////////////////////////////////////////////

#include "stdafx.h"
#include "WPString.h"

wstring WPString::_AStringToWide(LPCSTR lpszSrc)
{
    return _Internal_MBStringToWide(lpszSrc,CP_ACP);
}

wstring WPString::_UTFStringToWide(LPCSTR lpszUTF8)
{
    return _Internal_MBStringToWide(lpszUTF8,CP_UTF8);
}

wstring WPString::_Internal_MBStringToWide(LPCSTR lpszSrc, const UINT nSrcCodePage)
{
    wstring wstrRet=L"";
    if (NULL == lpszSrc)
        return wstrRet;


    const int nALen=(int)strlen(lpszSrc);
    if (0 == nALen)
        return wstrRet;

    const int nNeeded=MultiByteToWideChar(nSrcCodePage,0,lpszSrc,nALen,NULL,0);
    if (0 == nNeeded)
        return wstrRet;

    enum {STACK_SIZE_MAX=2000};
    const BOOL bDelete=nNeeded > (STACK_SIZE_MAX-1);
    wchar_t szBuffer[STACK_SIZE_MAX];

    wchar_t* const pBuffer=bDelete ? new wchar_t[nNeeded+1] : szBuffer;
    if (NULL == pBuffer)
        return wstrRet;

    const int nEncode=MultiByteToWideChar(nSrcCodePage,0,lpszSrc,nALen,pBuffer,nNeeded);
    if (0 == nEncode) {
        if (bDelete)
            delete[] pBuffer;
        
        return wstrRet;
    }

    *(pBuffer+nEncode)=L'\0';
    
    wstrRet.reserve(nEncode);
    wstrRet=wstring(pBuffer);

    if (bDelete)
        delete[] pBuffer;

    return wstrRet;
}

wstring WPString::_AStringToWide_ByANSICodePageThread(LPCSTR lpszSrc)
{
    return _Internal_MBStringToWide(lpszSrc,    CP_THREAD_ACP);
}

astring WPString::_WideStringToACP(LPCWSTR lpszW)
{
    return _Internal_WideStringToMBCS(lpszW,CP_THREAD_ACP);
}

astring WPString::_WideStringToCodePage(LPCWSTR lpszW, const DWORD code_page)
{
    return _Internal_WideStringToMBCS(lpszW,code_page);
}


astring WPString::_WideStringToUTF(LPCWSTR lpszWide)
{
    return _Internal_WideStringToMBCS(lpszWide,CP_UTF8);
}


astring WPString::_Internal_WideStringToMBCS(LPCWSTR lpszWide, const UINT nMBCodePage)
{
    astring astrRet="";

    if (NULL == lpszWide)
        return astrRet;
    
    const int nWLen=(int)wcslen(lpszWide);
    
    if (0==nWLen)
        return astrRet;

    const int nNeedChar=WideCharToMultiByte(nMBCodePage,0,lpszWide,nWLen,NULL,0,NULL,NULL);
    if (0 == nNeedChar)
        return astrRet;

    enum {STACK_SIZE_MAX=2000};
    const BOOL bDelete=nNeedChar > (STACK_SIZE_MAX-1);
    char szBuffer[STACK_SIZE_MAX];

    char* const pBuffer=bDelete ? new char[nNeedChar+1] : szBuffer;
    if (NULL == pBuffer)
        return astrRet;
    
    const int nEncode=WideCharToMultiByte(nMBCodePage,0,lpszWide,nWLen,pBuffer,nNeedChar,NULL,NULL);
    if (0 == nEncode) {
        if (bDelete)
            delete[] pBuffer;

        return astrRet;
    }

    *(pBuffer+nEncode)='\0';

    astrRet.reserve(nEncode);
    astrRet=astring(pBuffer);

    if (bDelete)
        delete[] pBuffer;

    return astrRet;
}

astring WPString::_UTFStringToANSI(LPCSTR lpszUTF8)
{
    const wstring ws=_UTFStringToWide(lpszUTF8);
    if (ws.empty())
        return "";

    const astring as=_WideStringToACP(ws.c_str());
    return as;
}

wstring WPString::_MBStringToWideWithCodePage(LPCSTR lpszSRC, const DWORD dwCodePage)
{
    return _Internal_MBStringToWide(lpszSRC,dwCodePage);
}

astring WPString::_AStringToUTF8(LPCSTR lpszSrc)
{
    const wstring wsU=_AStringToWide(lpszSrc);
    if (wsU.empty())
        return "";

    const astring a=_WideStringToUTF(wsU.c_str());
    return a;
}

static
wchar_t ToUpperInvariant(wchar_t input)
{
    wchar_t result;
 
    LONG lres = LCMapStringW(
        LOCALE_INVARIANT,
        LCMAP_UPPERCASE,
        &input,
        1,
        &result,
        1
        );
 
    if (lres == 0)
    {
        ASSERT(!"LCMapStringW failed to convert a character to upper case");
 
        result = input;
    }
 
    return result;
}

int WPString::CompareWP(LPCTSTR sz1, LPCTSTR sz2, const BOOL bCaseSensitive)
{
    if (sz1 == sz2)
    {
        return 0;
    }
 
    if (sz1 == NULL) sz1 = TEXT("");
    if (sz2 == NULL) sz2 = TEXT("");
 
    for (;; sz1++, sz2++)
    {
        const wchar_t c1 = *sz1;
        const wchar_t c2 = *sz2;
 
        // check for binary equality first
        if (c1 == c2)
        {
            if (c1 == 0)
            {
                return 0; // We have reached the end of both strings. No difference found.
            }
        }
        else
        {
            if (c1 == 0 || c2 == 0)
            {
                return (c1-c2); // We have reached the end of one string
            }
 
            // IMPORTANT: this needs to be upper case to match the behavior of the operating system.
            // See http://msdn.microsoft.com/library/default.asp?url=/library/en-us/dndotnet/html/StringsinNET20.asp
            const wchar_t u1 = bCaseSensitive ? c1 : ToUpperInvariant(c1);
            const wchar_t u2 = bCaseSensitive ? c2 : ToUpperInvariant(c2);
            if (u1 != u2)
            {
                return (u1-u2); // strings are different
            }
        }
    }
}

static
wstring MFCStringToWPString(LPCWSTR lpsz, const BOOL bCaseSensitive)
{
    const int nLen=wcslen(lpsz);
    ASSERT(nLen);
    if (0 == nLen)
        return L"";

    wchar_t* p=new wchar_t[nLen+1];
    ASSERT(p);
    memset(p,0,(nLen+1)*sizeof(wchar_t));

    const DWORD dwFlags=bCaseSensitive ? 0 : LCMAP_UPPERCASE;
    const LONG lres = LCMapStringW(
        LOCALE_INVARIANT,
        dwFlags,
        lpsz,
        nLen,
        p,
        nLen
        );
    ASSERT(lres > 0);
    if (lres <= 0) {
        delete[] p;
        return L"";
    }

    ASSERT(!IsBadStringPtrW(p,INFINITE));
    const wstring ws(p);
    delete[] p;

    return ws;
}



int WPString::FindInStrWP2(const LPCTSTR lpszFindString
                              , LPCTSTR lpszText
                              , const BOOL bCaseSensitive
                              ,const int nStart)
{
    ASSERT(lpszFindString);
    ASSERT(!IsBadStringPtr(lpszFindString,INFINITE));
    ASSERT(_tcslen(lpszFindString));

    ASSERT(lpszText);
    ASSERT(!IsBadStringPtr(lpszText,INFINITE));
    ASSERT(_tcslen(lpszText));

    if (0 == _tcslen(lpszText))
        return -1;

    if (0 == _tcslen(lpszFindString))
        return -1;

    const wstring wsFindString=MFCStringToWPString(lpszFindString,bCaseSensitive);        
    const wstring wsText=MFCStringToWPString(lpszText,bCaseSensitive);

    const CString strFind(wsFindString.c_str());
    const CString strText(wsText.c_str());

    const int nFind=strText.Find(strFind,nStart);
    return nFind;


    //const int szT=wsText.find(wsFindString.c_str(),nStart);
    //return szT;
}

wstring WPString::_OemStringToWide(LPCSTR lpszSrc)
{
    const int nLen=strlen(lpszSrc);
    ASSERT(nLen);

    if (0 == nLen)
        return L"";

    wchar_t* const pChar=new wchar_t[nLen*2];
    ASSERT(pChar);
    if (NULL == pChar)
        return L"";

    memset(pChar,0,(nLen*sizeof(wchar_t)*2));

    const BOOL b=OemToCharW(lpszSrc,pChar);
    ASSERT(b);
    if (!b) {
        delete[] pChar;
    }

    const wstring ws(pChar);
    delete[] pChar;

    return ws;
}
Aml Pages Home
Re: Преобразование различных строковых типов в MFC
От: RussianFellow Россия http://russianfellow.livejournal.com
Дата: 28.12.17 12:57
Оценка:
И ещё вопрос: как лучше всего преобразовать CString в char* ?

Для этих целей я использую следующий код:

CString  mystr;
int  i, len;
char  s[40];
LPCTSTR  pzText;

m_IDC_EDIT1.GetWindowText(mystr);
mystr = mystr.Trim(); // удаляю пробелы слева и справа
len = mystr.GetLength();
pzText = mystr.GetBuffer();
for (i=0; i<len; i++)  s[i] = pzText[i];
s[len] = '\0';


Это нормально работает. Но можно ли сделать лучше?
1613 г. = 2024 г.
Re[2]: Преобразование различных строковых типов в MFC
От: Amon_RA Россия  
Дата: 28.12.17 13:03
Оценка:
Здравствуйте, RussianFellow, Вы писали:

RF>Это нормально работает. Но можно ли сделать лучше?


Насколько я помню, лет 8 назад в тех версиях MFC при вызове GetBuffer надо было освобождать память то ли через FreeBuffer то ли через ReleaseBuffer.
Не знаю как в нынешних версиях MFC, но ты б уточнил на всякий, чтоб утечек не было.
Re[3]: Преобразование различных строковых типов в MFC
От: RussianFellow Россия http://russianfellow.livejournal.com
Дата: 28.12.17 13:21
Оценка:
Здравствуйте, Amon_RA, Вы писали:

A_R>Здравствуйте, RussianFellow, Вы писали:


RF>>Это нормально работает. Но можно ли сделать лучше?


A_R>Насколько я помню, лет 8 назад в тех версиях MFC при вызове GetBuffer надо было освобождать память то ли через FreeBuffer то ли через ReleaseBuffer.

A_R>Не знаю как в нынешних версиях MFC, но ты б уточнил на всякий, чтоб утечек не было.

Visual Studio 2012.
1613 г. = 2024 г.
Re[4]: Преобразование различных строковых типов в MFC
От: Amon_RA Россия  
Дата: 28.12.17 13:22
Оценка:
Здравствуйте, RussianFellow, Вы писали:

RF>Visual Studio 2012.


Ты предлагаешь мне посмотреть надо освобождать или нет?
Re[5]: Преобразование различных строковых типов в MFC
От: RussianFellow Россия http://russianfellow.livejournal.com
Дата: 28.12.17 13:34
Оценка:
Здравствуйте, Amon_RA, Вы писали:

A_R>Здравствуйте, RussianFellow, Вы писали:


RF>>Visual Studio 2012.


A_R>Ты предлагаешь мне посмотреть надо освобождать или нет?


Вот нашёл:

https://msdn.microsoft.com/en-us/library/aa300574(v=vs.60).aspx

А так, чтобы обязательно надо освобождать буфер после CString::GetBuffer -- этого нигде не написано.
Но если так желательно писать--что же, буду знать.
1613 г. = 2024 г.
 
Подождите ...
Wait...
Пока на собственное сообщение не было ответов, его можно удалить.