Преобразование строки в символ * - PullRequest
1 голос
/ 23 февраля 2012

Я пытаюсь написать функцию для преобразования std :: string в char *.Первое, что я написал, было:

char* $ (string str)
{
    char* cstr;
    const unsigned int length=str.size();
    cstr=new char[1000];
    for(int i=0;i<length;i++)
        cstr[i]=str[i];
    cstr[length]=0;
    return cstr;
}

Но проблема была в утечке памяти: предположим, что я делаю это:

char* cstr;
string str1("hello"),str2("hello2");
cstr=$(str1);
cstr=$(str2);

В этом случае произошла утечка памяти. Первая выделенная строка недоступна, но ее ссылка потеряна.Поэтому я сделал то же самое, используя static:

char* $ (string str)
{
    static char cstr[1000];
    const unsigned int length=str.size();
    for(int i=0;i<length;i++)
        cstr[i]=str[i];
    cstr[length]=0;
    return cstr;
}

Но теперь проблема в том, что поля static char доступны:

char* cstr;
string str("hello");
cstr=$(str);
$(str)[5]='!';

Это возможно, 6-й символ изменен и тактакже изменена строка в стиле C, на которую указывает cstr.

Использование const:

const char* $ (string str)
{
    static char cstr[1000];
    const unsigned int length=str.size();
    for(int i=0;i<length;i++)
        cstr[i]=str[i];
    cstr[length]=0;
    return cstr;
}

Проблема в том, что указатель char не совместим с указателем const char, поэтому я могу 'сделать это:

string str("hello");
char* cstr;
cstr=$(str);

Но я могу использовать только указатель на константный символ.Я хотел бы иметь функцию, которую возвращаемое значение можно было бы разместить только как правый операнд, но не как левый операнд присваивания. Как это можно сделать?

Я пытался сделать это:

char* toCharArray(string& str)
{
    std::unique_ptr<char>p(new char[1000]);
    char* temp=p.get();
    for(unsigned int i=0;i<str.size();i++)
    {
        *temp=str[i];
        temp++;
    }
    return p.get();
}

Но проблема все еще существует, я не вижу разницы между этим и другим решением, которое я выложил, используя static.Since такой код:

char* cstr;
string str("hello");
cstr=toCharArray(str);
toCharArray(str)[0]='o';
cout << cstr;

Изменяет строку(печатает "oello").Проблема все еще не решена.

Ответы [ 5 ]

2 голосов
/ 23 февраля 2012

Вы можете предотвратить утечки памяти, возвращая выделенный массив как std::unique_ptr<char[]> или std::vector<char>; оба освободят память, если они переназначатся или выйдут из области видимости.

Вы можете получить указатель char* на содержимое как ptr.get() или &vec[0] соответственно.

Кстати, поскольку длина известна, длина массива действительно должна быть length+1, а не 1000. Буферы фиксированного размера - переполнение, ожидающее, чтобы произойти. Кроме того, $ не является переносимым именем для функции.

1 голос
/ 23 февраля 2012

Вам нужно создать новый char * и скопировать поверх него содержимое std::string.

Вы можете использовать strcpy .

1 голос
/ 23 февраля 2012

http://www.cplusplus.com/reference/string/string/c_str/

Посмотрите на пример, а именно:

char * cstr, *p;

string str ("Please split this phrase into tokens");

cstr = new char [str.size()+1];
strcpy (cstr, str.c_str());
0 голосов
/ 23 февраля 2012

Не понимаю, почему ты удивлен утечкой памяти. Если вы делаете копию чего-либо, вы должны положить ее куда-нибудь.

Вы можете либо поместить все копии в одно и то же место (риск переполнения и взять на себя ответственность за получение правильной копии на клиенте, либо они рискуют неожиданно повредить), либо вы делаете выделение ( они все еще должны делать освобождение, но, по крайней мере, они не должны копировать), или вы заставляете их передавать буфер и размер в вашу функцию.

А если серьезно, $ как имя функции?

0 голосов
/ 23 февраля 2012

А как насчет str.c_str()? Или strdup(str.c_str()), если вам нужна копия.

Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...