2013-03-02 2 views
4

Итак, пытаясь научиться использовать C-Strings в C++, у меня возникают проблемы с распределением памяти.Как выделить память для массива символов c-string?

Идея состоит в том, что создается новая строка формата (s1 + sep + s2) Текст, который я использую, содержит заголовок, поэтому я не могу его изменить, но у меня возникают проблемы пытаясь установить размер char str []. Я получаю сообщение о том, что sLength не является константой и поэтому не может использоваться для установки размера массива. Я относительно новичок в C++, так что это вопрос из двух частей.

  1. Эта стратегия фактически выделяет память для нового массива?

  2. Как установить размер массива правильно, если я не могу получить постоянное значение с помощью strlen (char *)?

    char* concatStrings(char* s1, char* s2, char sep){ 
        int sLength = strlen(s1) + strlen(s2) + 3; 
        //+1 for char sep +2 for \0 at end of string 
        char *str = new char[sLength]; 
        strcpy (str, s1); 
        str [sLength(s1)] = sep; 
        strcat (str, s2); 
        return str; 
    } 
    

редактирует сделал, так что теперь я не получаю никаких ошибок компилятора, но ...

вызов к функции здесь:

char* str = concatStrings("Here is String one", "Here is String two" , c); 
    cout<< str; 

Мой выход становится:

Здесь находится String onec =================== 22221/21/21/21/2/(и т.д.)/Здесь S tring two

+4

Вам необходимо динамически распределить его. Если вы новичок в C++, я предлагаю придерживаться 'std :: string' некоторое время, прежде чем смотреть в строки C. Не выбирайте строки C поверх 'std :: string' для использования, так как есть всевозможные проблемы. – chris

+0

Какие ошибки компилятора вы получаете? –

+0

@chris В общем, я согласен с предложением предпочесть 'std :: string' над строками C. Тем не менее, OP четко заявляет, что это учебное упражнение, которое является вполне обоснованной причиной (ИМО) для использования строк C. –

ответ

8

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

Чтобы получить доступ к нему снаружи, вам необходимо динамически выделить память для строки из кучи, используя оператор new.

char* concatStrings(char* s1, char* s2, char sep){ 
    int s1Length = strlen(s1); 
    int sLength = s1Length + strlen(s2) + 2; 
    // +1 for sep and +1 \0 at end of string 
    char* str = new char[sLength]; 
    strcpy (str, s1); 
    // Use strlen here instead of sizeof() 
    str [s1Length] = sep; 
    str [s1Length + 1] = '\0'; 
    strcat (str, s2); 
    return str; 
} 

И после того, как программа выполняется с помощью строки, возвращенной из concatStrings он должен обеспечить, чтобы освободить память, вызывая delete

char* str = concatStrings(s1, s2, sep); 

// Do something 

// Free up memory used by str 
delete str; 

Я также редактировал функцию concatStrings()strlen использовать вместо sizeof

ОБНОВЛЕНИЕ: Спасибо, что указали, что нам нужно только сделать +2, а не +3, и для обеспечения того, чтобы после добавлениябыло добавлено '\ 0'и sep перед вызовом strcat

+0

Хороший ответ, хотя 'strlen (s1)' должен быть действительно кэширован; это 'O (N)' в конце концов ... –

+0

@gnome: strcat() добавить \ 0 он сам вам не нужен явно –

+0

@Alex - Хороший улов. – Tuxdude

1

sizeof(s1) возвращает размер указательной переменной, не длина массива, на который указывает. Поскольку вы знаете, что s1 указывает на C-строку, вы должны использовать функцию strlen().

+0

Спасибо за это, я изначально использовал sizeof() для всего этого и хотел изменить все их, пропустил один. –

+0

@KurtVonDaimondorf Существуют и другие проблемы с вашим кодом. Прежде чем я расскажу о своем ответе, вы можете отредактировать свой вопрос с ошибками компилятора, которые вы получаете? –

+0

вчера я редактирую два ответа, и вы присутствовали в обеих формах. –

3

можно выделить полученную строку памяти динамически (во время выполнения, в куче), используя new[] в C++ (или malloc для более C-подобный стиль):

char* concatStrings(const char* s1, const char* s2, char sep) // enforced const correctness 
{ 
    const size_t totalLength = strlen(s1) + strlen(s2) 
          + 2; // +1 for sep char, +1 for '\0' 

    // Dynamically allocate room for the new string (on the heap) 
    char* str = new char[totalLength];  

    strcpy(str, s1); 
    str[strlen(s1)] = sep; // note that you had a typo with sizeof(s1) here 
    strcat(str, s2); 
    return str; 
} 

Обратите внимание, что эта память должна быть выпущена где-то в вашем коде, используя delete[], если он был выделен с new[] или free(), если он был выделен с помощью malloc().

Это довольно сложно.

Вы упростите ваш код много, если вы используете надежных C струнного ++ класса как std::string, с его удобными конструкторами выделить память, деструктор автоматически освободить его, и operator+ и operator+= перегрузок для конкатенации строк. Посмотрите, как ваш код упрощен с помощью std::string:

#include <string> // for std::string 

std::string str = s1; 
str += sep; 
str += s2; 

(Обратите внимание, что с использованием исходных строк C также может сделать код более уязвимым к проблемам безопасности, так как вы должны платить много внимания соответствующих строк проклейки назначения, избежать буфера переполнения и т. д. Это еще одна причина, чтобы предпочесть класс строгих строк RAII, например std::string.)

Смежные вопросы