удобное и функциональное использование строки в C++
От: Speakus  
Дата: 01.10.07 09:36
Оценка:
Здравствуйте,
Подскажите, пожалуйста, какой класс лучше использовать для строк?
include <string>
std::string

include <atlstr.h>
CString

Может какой-то другой? А есть ли другие?
Ну и конечно же — почему именно этот?

01.10.07 18:27: Перенесено модератором из '.NET' — AndrewVK
Re: удобное и функциональное использование строки в C++
От: _FRED_ Черногория
Дата: 01.10.07 09:41
Оценка:
Здравствуйте, Speakus, Вы писали:

S>Подскажите, пожалуйста, какой класс лучше использовать для строк?

[ccode]
S>include <string>
S>std::string

S>include <atlstr.h>
S>CString

[/ccode]

S>Может какой-то другой? А есть ли другие?

S>Ну и конечно же — почему именно этот?

А почему в этот форум? Разговор о Managed C++ или C++/CLI?
... << RSDN@Home 1.2.0 alpha rev. 717>>
Help will always be given at Hogwarts to those who ask for it.
Re: удобное и функциональное использование строки в C++
От: Vamp Россия  
Дата: 01.10.07 14:31
Оценка: +1
Я рекомендую вариант с std::string.
Почему?
1. Входит в стандарт — будет работать на любом совместимом компиляторе
2. Является частью стандартной библиотеки — сочетается со стандартными алгоритмами
Да здравствует мыло душистое и веревка пушистая.
Re: удобное и функциональное использование строки в C++
От: MasterZiv СССР  
Дата: 01.10.07 17:17
Оценка:
Speakus пишет:
> Подскажите, пожалуйста, какой класс лучше использовать для строк?

Ответа на ваш вопрос нет и быть не может. Потому что "зависит от"
многих-многих факторов. В первом приближении это должно быть std::string,
если у вам не будет проблем с производительностью.
Posted via RSDN NNTP Server 2.1 beta
Re: удобное и функциональное использование строки в C++
От: Erop Россия  
Дата: 01.10.07 17:19
Оценка: 2 (1) +1
Здравствуйте, Speakus, Вы писали:

include <string>
std::string

include <atlstr.h>
CString

S>Ну и конечно же — почему именно этот?

А для чего тебе нужны строки? Что за операции над ними ты планируешь делать? Как часто порождать/разрушшать и т. д.?

Конкретно два приведённых тобой варианта отличаются AFAIK примерно следующим
1) Удобстовом использования вместо const char*
2) Безопасностью того же
3) Возможностью получить из char*-API строку непосредсвенно внутрь буфера строки\
4) Возможностью организовать строку любых копибл элементов
и т. д.

Если строка тебе нужна несколько раз за программу, то всё равно кукую использовать
Если строка тебе нужна именно как строка, а не как stl-контейнер (то есть если ты не хранишь в строках, например, аттрибутиванные буквы, не используешь всякие алгоритмы вроде std::sort), то проще наверное пользоваться ATL строкой.
Если тебе важно переносимость и прочие выгоды стандартизации, то проще STL-строкой
Ну а если строки это главная или одна из главных структур данных в твоей сложной программе, то, скорее всего, прийдётся написать свою строку
Все эмоциональные формулировки не соотвествуют действительному положению вещей и приведены мной исключительно "ради красного словца". За корректными формулировками и неискажённым изложением идей, следует обращаться к их автором или воспользоваться поиском
Re: удобное и функциональное использование строки в C++
От: Аноним  
Дата: 02.10.07 08:55
Оценка:
Здравствуйте, Speakus, Вы писали:

S>Здравствуйте,

S>Подскажите, пожалуйста, какой класс лучше использовать для строк?
S>include <string>
S>std::string

S>include <atlstr.h>

S>CString

S>Может какой-то другой? А есть ли другие?

S>Ну и конечно же — почему именно этот?

По крайней мере несколько раз встречал некорректное поведение класса CString (MFC, MSVC 6.0) при присваивании значения (операторы = и +=), поэтому в средних и больших проектах скорее всего буду использовать std::string и std::wstring.
Re: удобное и функциональное использование строки в C++
От: Awaken Украина  
Дата: 02.10.07 09:14
Оценка: +1
S>Может какой-то другой? А есть ли другие?
S>Ну и конечно же — почему именно этот?

есть еще QString, XMLString и т.д.
Re: удобное и функциональное использование строки в C++
От: ScarryDen  
Дата: 02.10.07 10:34
Оценка:
Здравствуйте, Speakus, Вы писали:

S>Здравствуйте,

S>Подскажите, пожалуйста, какой класс лучше использовать для строк?
S>include <string>
S>std::string

S>include <atlstr.h>

S>CString

S>Может какой-то другой? А есть ли другие?

S>Ну и конечно же — почему именно этот?

имхо, юзал бы std::string , но как то приходилось реализовать свой класс строки,
чисто для своих нужд, без всяких излишеств, с обрезаным функционалом.
Re[2]: удобное и функциональное использование строки в C++
От: Erop Россия  
Дата: 02.10.07 12:21
Оценка:
Здравствуйте, Аноним, Вы писали:

А>По крайней мере несколько раз встречал некорректное поведение класса CString (MFC, MSVC 6.0) при присваивании значения (операторы = и +=)


А можно рассказать поподробнее? Что за проблемы, в каких контекстах?
Как-то странно, строка вещь часто используемая, должна бы быть отлажена...
Так что все косяки хочется знать
Все эмоциональные формулировки не соотвествуют действительному положению вещей и приведены мной исключительно "ради красного словца". За корректными формулировками и неискажённым изложением идей, следует обращаться к их автором или воспользоваться поиском
Re[3]: удобное и функциональное использование строки в C++
От: Awaken Украина  
Дата: 02.10.07 12:33
Оценка: 12 (1)
А>>По крайней мере несколько раз встречал некорректное поведение класса CString (MFC, MSVC 6.0) при присваивании значения (операторы = и +=)
E>А можно рассказать поподробнее? Что за проблемы, в каких контекстах?

проблема может быть в неявных преобразованиях строки в указатель на нижележащий тип,
что может вызывать побочные эффекты
Re[4]: А пример приведёшь?
От: Erop Россия  
Дата: 02.10.07 13:22
Оценка: 1 (1)
Здравствуйте, Awaken, Вы писали:

A>проблема может быть в неявных преобразованиях строки в указатель на нижележащий тип,

A>что может вызывать побочные эффекты


Приведи пример.
Что-то типа:
CString str;
str += stsstr( str, str );
или как-то иначе?

О чём идёт речь?
Казалось бы оба оператора ничего никуда не приводят, а просто приписывают в строку новое значение, или приписывают его в конец строки.
Единственный путь глюков, который я тут вижу, это сослаться на конец строки припомощи const char*, да этот вот указатель и передать в += того же объекта.
Ну там
CString str = "idfhkdsfjv";
const char* text = str;
str += text + str.Length() / 2;

Такой какой-то контекст?
Но это же понятно, что так писать нехорошо и опасно...

А как такая проблема может возникнуть в нормальном коде?
Или проблема вообще какая-то другая.
Скажем такая:
CString str;
if( str ) {
    std::cout << "Ленин всегда с тобой, Ленин всегда живой...\n"; 
}
Все эмоциональные формулировки не соотвествуют действительному положению вещей и приведены мной исключительно "ради красного словца". За корректными формулировками и неискажённым изложением идей, следует обращаться к их автором или воспользоваться поиском
Re[5]: А пример приведёшь?
От: Roman Odaisky Украина  
Дата: 02.10.07 15:06
Оценка:
Здравствуйте, Erop, Вы писали:

A>>проблема может быть в неявных преобразованиях строки в указатель на нижележащий тип,

A>>что может вызывать побочные эффекты

E>Приведи пример.


s = s1 - s2 + s3;
//     ↑ ой, должен был быть «+»

// а на самом деле это эквивалентно:

s = CString(LPCTSTR(ptrdiff_t(LPCTSTR(s1) - LPCTSTR(s2)) + LPCTSTR(s3)));


Или просто delete CString(). Или if(CString()) { }.
До последнего не верил в пирамиду Лебедева.
Re[6]: А пример приведёшь?
От: Erop Россия  
Дата: 02.10.07 15:55
Оценка:
Здравствуйте, Roman Odaisky, Вы писали:

E>>Приведи пример.


RO>
RO>s = s1 - s2 + s3;
RO>//     ↑ ой, должен был быть «+»

RO>// а на самом деле это эквивалентно:

RO>s = CString(LPCTSTR(ptrdiff_t(LPCTSTR(s1) - LPCTSTR(s2)) + LPCTSTR(s3)));
RO>

А что такое CString( int )?

RO>Или просто delete CString(). Или if(CString()) { }.

Вот с if я ещё понимаю, но это же просто клиника, так писать. А с delete, ИМХО, не страшно.
Так как delete в программах вообще аккуратно надо использовать, никто тебе не мешает ещё как-нибудь не то удалить, скажем так:
std::string str;
delete &str;
...
Все эмоциональные формулировки не соотвествуют действительному положению вещей и приведены мной исключительно "ради красного словца". За корректными формулировками и неискажённым изложением идей, следует обращаться к их автором или воспользоваться поиском
Re[2]: удобное и функциональное использование строки в C++
От: Speakus  
Дата: 03.10.07 10:52
Оценка:
Здравствуйте, Erop, Вы писали:

E>А для чего тебе нужны строки? Что за операции над ними ты планируешь делать? Как часто порождать/разрушшать и т. д.?


E>Конкретно два приведённых тобой варианта отличаются AFAIK примерно следующим

E>1) Удобстовом использования вместо const char*
E>2) Безопасностью того же
E>3) Возможностью получить из char*-API строку непосредсвенно внутрь буфера строки\
E>4) Возможностью организовать строку любых копибл элементов
E>и т. д.

E>Если строка тебе нужна несколько раз за программу, то всё равно кукую использовать

E>Если строка тебе нужна именно как строка, а не как stl-контейнер (то есть если ты не хранишь в строках, например, аттрибутиванные буквы, не используешь всякие алгоритмы вроде std::sort), то проще наверное пользоваться ATL строкой.
E>Если тебе важно переносимость и прочие выгоды стандартизации, то проще STL-строкой
E>Ну а если строки это главная или одна из главных структур данных в твоей сложной программе, то, скорее всего, прийдётся написать свою строку

Спасибо.
по пунктам
2) — вроде как в параллельной ветке так и не нашли причин опасности этого пункта — или имеется в виду что-то другое?.
3) — тоже не ясно
про стандартизацию — понял. Конечно лучше со стандартизацией чем без.
1) Скажите а нет ли возможности заставить работать string c const char* (ну т.е. получить выгоду пункта 1 — не теряя возможности использования GNU компиляторов) ?
пробовал двумя способами:
class mystring: public std::string
{
public:
mystring(const std::string & x) {*this = x;}
operator const char*() const {return this->c_str();}
};
и
operator const char*(const std::string &x) {return x.c_str();}

второй случай вообще не компилируется — нельзя видать делать преобразование типов не своего класса.
Хотелось бы чтобы код подобный этому работал:
mystring var("x");
_putenv("myvar=" + var); //здесь происходит преобразование типа в std::string результирующей строки — а она уже в const char * автоматом преобразовываться не умеет.
Re[5]: А пример приведёшь?
От: Speakus  
Дата: 03.10.07 11:04
Оценка: :)
Здравствуйте, Erop, Вы писали:

E>Что-то типа:
CString str;
E>str += stsstr( str, str );
или как-то иначе?

Извините, а какая здесь проблема?

E>О чём идёт речь?

E>Казалось бы оба оператора ничего никуда не приводят, а просто приписывают в строку новое значение, или приписывают его в конец строки.
E>Единственный путь глюков, который я тут вижу, это сослаться на конец строки припомощи const char*, да этот вот указатель и передать в += того же объекта.
E>Ну там
CString str = "idfhkdsfjv";
E>const char* text = str;
E>str += text + str.Length() / 2;

E>Такой какой-то контекст?
E>Но это же понятно, что так писать нехорошо и опасно...
И здесь не могли бы объяснить почему так писать не хорошо? str.Length() — не компилится кстати

E>А как такая проблема может возникнуть в нормальном коде?

E>Или проблема вообще какая-то другая.
E>Скажем такая:
CString str;
E>if( str ) {
E>    std::cout << "Ленин всегда с тобой, Ленин всегда живой...\n"; 
E>}

а что подразумевается под if (str) ? разве это нормальное использование класса? а почему кстати тут не генерируется сообщения об ошибке C2451 ?
Re[2]: удобное и функциональное использование строки в C++
От: Speakus  
Дата: 03.10.07 11:11
Оценка: 21 (1) :)))
Здравствуйте, Awaken, Вы писали:

S>>Может какой-то другой? А есть ли другие?

S>>Ну и конечно же — почему именно этот?

A>есть еще QString, XMLString и т.д.

MSDN о них не в курсе — самописные что ли?
Re[3]: удобное и функциональное использование строки в C++
От: Аноним  
Дата: 03.10.07 11:11
Оценка:
Здравствуйте, Erop, Вы писали:

E>А можно рассказать поподробнее? Что за проблемы, в каких контекстах?

E>Как-то странно, строка вещь часто используемая, должна бы быть отлажена...
E>Так что все косяки хочется знать

Пожалуйста, без слипа у меня правильно работает через 2 — 3 раза


BOOL CReg::GetArray(CString strValueName, void * pArr, size_t sizeArr)
{
    if(pArr && sizeArr && strValueName.GetLength())
    {
        CString strSK;
        GetSubKeyString(strSK);

        //
        // it is essential to call Sleep(0) here
        // because there is seems to be a bug in MSVC,
        // and without Sleep(0) call 
        // functions GetSubKeyString && GetArray
        // will not work properly
        //

        Sleep(0);
        
        return GetArray(CReg::HKCU,
            (LPCTSTR)strSK,
            (LPCTSTR) strValueName,
            pArr,
            sizeArr);
    }
    return FALSE;
}

BOOL CReg::GetSubKeyString(CString& str)
{
    CString s;
    str = _T("Software\\");
    str += CMfcieApp::_strRegKey;
    str += _T("\\");
    s.LoadString(AFX_IDS_APP_TITLE);
    str += s;
    str += _T("\\");
    str += this->_strSubSectionName;
    return TRUE;
}
Re[4]: удобное и функциональное использование строки в C++
От: Аноним  
Дата: 03.10.07 11:17
Оценка:
Здравствуйте, Аноним, Вы писали:
А>Пожалуйста, без слипа у меня правильно работает через 2 — 3 раза

{}


ЗЫ
Вызывается это в InitInstance()
Re[3]: удобное и функциональное использование строки в C++
От: Константин Россия  
Дата: 03.10.07 16:22
Оценка:
Здравствуйте, Speakus, Вы писали:

S>1) Скажите а нет ли возможности заставить работать string c const char* (ну т.е. получить выгоду пункта 1 — не теряя возможности использования GNU компиляторов) ?


А оно точно надо? Выгода очень сомнительна (С VisualAssist и ему подобными так вообще пофигу), а недостатки налицо.
Может стоит озаботиться решаемой задачей, а не играться в бирюльки..
Re[3]: удобное и функциональное использование строки в C++
От: Erop Россия  
Дата: 03.10.07 20:59
Оценка: 6 (1)
Здравствуйте, Speakus, Вы писали:

E>>Конкретно два приведённых тобой варианта отличаются AFAIK примерно следующим

E>>1) Удобстовом использования вместо const char*
E>>2) Безопасностью того же
E>>3) Возможностью получить из char*-API строку непосредсвенно внутрь буфера строки\
E>>4) Возможностью организовать строку любых копибл элементов
E>>и т. д.

E>>Если строка тебе нужна несколько раз за программу, то всё равно кукую использовать

E>>Если строка тебе нужна именно как строка, а не как stl-контейнер (то есть если ты не хранишь в строках, например, аттрибутиванные буквы, не используешь всякие алгоритмы вроде std::sort), то проще наверное пользоваться ATL строкой.
E>>Если тебе важно переносимость и прочие выгоды стандартизации, то проще STL-строкой
E>>Ну а если строки это главная или одна из главных структур данных в твоей сложной программе, то, скорее всего, прийдётся написать свою строку

S>2) — вроде как в параллельной ветке так и не нашли причин опасности этого пункта — или имеется в виду что-то другое?.

Ну, например, тот же самый if( str )...
Ну и вообще, лёгкость неявного получения из объекта const char* многими рассматривается, как источник опасности. Типа нужно редко, а вредит часто. Некоторые наоборот считают, что это надо и удобно...
S>3) — тоже не ясно
Ну вот есть у тебя API функция какакя-то, скажем GetUserName( char*, UINT* count ).
Вот хочешь ты получить из неё результат сразу в строку.
С одной строкой ты пишешь так
CString str;
UINT len = MAX_USER_NAME_LENGTH;
GetUserName( str.GetBuffer( len ), &len );
str.Release( len );


А с другой прийдётся использовать промежуточный буффер, как-то так:
vector<char> buffer;
UINT len = MAX_USER_NAME_LENGTH;
buffer.set_size( len + 1 );
GetUserName( &buffer[0], &len );
buffer.set_size( len );
buffer.push_back( 0 );
string str = &buffer[0]; // типа лишнее копирование :(


S>Хотелось бы чтобы код подобный этому работал:

S>_putenv("myvar=" + var); //здесь происходит преобразование типа в std::string результирующей строки — а она уже в const char * автоматом преобразовываться не умеет.
Ну так string специально так спроектирована, чтобы обломать тебя
Тока так:
_putenv( ("myvar=" + var ).c_str() );


Можно коенчно хакануть по другому:
static const class to_c_str_t {
public:
    to_c_str_t() {}
    to_c_str_t( const string& src ) : text( src ) {}
    
    operator const char*() const { return text.c_str(); }
    operator const string() const { return text; }
    
    to_c_str_t& operator += ( const to_c_str_t& toAdd ) { text += toAdd; return *this; }
    to_c_str_t& operator += ( const string& toAdd ) { text += toAdd; return *this; }
    to_c_str_t& operator += ( const char* toAdd ) { text += toAdd; return *this; }

private:
    string text;
} to_c_str;

inline to_c_str_t operator( to_c_str_t left, const to_c_str_t& right ) { return left += right; }
inline to_c_str_t operator( to_c_str_t left, const string& right ) { return left += right; }
inline to_c_str_t operator( to_c_str_t left, const char* right ) { return left += right; }
inline to_c_str_t operator( const string& left, const to_c_str_t& right ) 
    { return to_c_str_t( left ) + right; }
inline to_c_str_t operator( const char* left, const to_c_str_t& right ) 
    { return to_c_str_t( left ) + right; }


И теперь можно писать и так:
_putenv(to_c_str + "myvar=" + var);
или так:
_putenv("myvar=" + var + to_c_str);


но нужно ли это всё?

ИМХО AtlString -- твой выбор
Все эмоциональные формулировки не соотвествуют действительному положению вещей и приведены мной исключительно "ради красного словца". За корректными формулировками и неискажённым изложением идей, следует обращаться к их автором или воспользоваться поиском
Подождите ...
Wait...
Пока на собственное сообщение не было ответов, его можно удалить.