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

Kur*_*orf 6 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;
    }
    
    Run Code Online (Sandbox Code Playgroud)

编辑,所以现在我没有编译错误,但...

对函数的调用如下:

    char* str = concatStrings("Here is String one", "Here is String two" , c);
    cout<< str;
Run Code Online (Sandbox Code Playgroud)

我的输出成为:

这里是String onec ================== 22221/21/21/21/2/(等) /这里是String 2

Tux*_*ude 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;
}
Run Code Online (Sandbox Code Playgroud)

在程序完成后,使用从concatStrings它返回的字符串应确保通过调用释放内存delete

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

// Do something

// Free up memory used by str
delete[] str; 
Run Code Online (Sandbox Code Playgroud)

我还编辑了concatStrings()要使用的功能strlen而不是sizeof

更新:感谢指出我们只需要做+2而不是+3并确保在调用之前str1sep之后需要附加'\ 0'strcat

  • 我从90年代中期开始就没有触及过C++,但需要重新回到秋千上......但是IIRC,不应该'删除str'是'delete [] str',因为字符串是用new分配的[ ]? (3认同)

Mr.*_*C64 5

您可以使用C ++(或用于更类似于C的样式)动态地(在运行时,在堆上)分配结果字符串内存:new[]malloc

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;
}
Run Code Online (Sandbox Code Playgroud)

请注意,此内存必须在代码中的某个位置释放,使用delete[]是通过分配的new[],还是free()通过分配的malloc()

这很复杂。

如果使用健壮的C ++字符串类(std::string)以及方便的构造函数来分配内存,析构函数以自动释放它operator+以及operator+=重载以串联字符串,则将大大简化代码。查看如何使用简化代码std::string

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

std::string str = s1;
str += sep;
str += s2;
Run Code Online (Sandbox Code Playgroud)

(请注意,使用原始C字符串还会使您的代码更容易受到安全问题的影响,因为您必须特别注意适当调整目标字符串的大小,避免缓冲区溢出等。这是偏爱RAII健壮字符串类的另一个原因std::string。 )