我应该如何为c-string char数组分配内存?

时间:2013-03-02 22:08:51

标签: c++ c memory-management string-concatenation cstring

因此,在尝试学习如何在C ++中使用C-Strings时,我遇到了内存分配问题。

这里的想法是创建一个新的字符串格式(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;
    }
    
  3. 编辑了,所以现在我没有编译错误但是......

    对函数的调用如下:

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

    我的输出变为:

    这是字符串onec ================== 22221/21/21/21/2 / (等。) /这是字符串2

3 个答案:

答案 0 :(得分:9)

错误是返回本地数组变量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,并确保在调用{{{{}}之前需要在str1sep之后附加'\ 0' 1}}

答案 1 :(得分:4)

您可以使用C ++中的new[](或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()分配,则使用std::string。 / p>

这很复杂。

如果使用健壮的C ++字符串类(如 operator+ ),您将大大简化代码,其方便的构造函数可以分配内存,析构函数可以自动释放它,并operator+=std::string重载以连接字符串。使用#include <string> // for std::string std::string str = s1; str += sep; str += s2; 了解您的代码是如何简化的:

std::string

(请注意,使用原始C字符串也会使您的代码更容易受到安全问题的影响,因为您必须非常注意正确调整目标字符串,避免缓冲区溢出等。这是另一个我更喜欢像{{1}}这样的RAII健壮字符串类。)

答案 2 :(得分:1)

sizeof(s1)返回指针变量的大小,它指向的数组的长度。由于您知道s1指向C字符串,因此您应该使用strlen()函数。