简体   繁体   English

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

[英]How should I allocate memory for c-string char array?

So in attempting to learn how to use C-Strings in C++, I'm running into issues with memory allocation. 因此,在尝试学习如何在C ++中使用C-Strings时,我遇到了内存分配问题。

The idea here is that a new string is created of the format (s1 + sep + s2) The text I'm using provided the header, so I can't change that, but I'm running into issues trying to set the size of char str[]. 这里的想法是创建一个新的字符串格式(s1 + sep + s2)我正在使用的文本提供了标题,所以我不能改变它,但我遇到了试图设置大小的问题char str []。 I am getting an error saying that sLength is not constant, and therefore cannot be used to set the size of an array. 我收到一个错误,说sLength不是常量,因此不能用于设置数组的大小。 I'm relatively new to C++ so this is a two part question. 我对C ++比较陌生,所以这是一个两部分问题。

  1. Is this strategy actually allocating memory for the new array? 这个策略实际上是为新阵列分配内存吗?

  2. How do I set the array size correctly if I can't get a constant value using strlen(char*)? 如果使用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; } 

Edits made, so now I'm getting no compiler errors but... 编辑,所以现在我没有编译错误,但...

The call to the function is here: 对函数的调用如下:

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

My output becomes: 我的输出成为:

Here is String onec==================22221/21/21/21/2 / (etc.) / Here is String two 这里是String onec ================== 22221/21/21/21/2 / (等) /这里是String 2

Error is returning address of local array variable str . 错误是返回本地数组变量str地址。 Its scope is within function concatStrings() where you declared, and can't be accessed once control returns from the function. 它的作用域在你声明的函数concatStrings()中,一旦控制从函数返回就无法访问。

To access it outside, you need to dynamically allocate memory for the string from the heap using the new operator. 要在外部访问它,您需要使用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;
}

And after the program is done using the string returned from concatStrings it should ensure to free up the memory by invoking delete 在使用从concatStrings返回的字符串完成程序之后,它应该确保通过调用delete来释放内存

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

// Do something

// Free up memory used by str
delete[] str; 

Must use delete[] here instead of delete, or it results in undefined behaviour 必须在此处使用delete []而不是delete,否则会导致未定义的行为

I've also edited the concatStrings() function to use strlen instead of sizeof 我还编辑了concatStrings()函数来使用strlen而不是sizeof

UPDATE: Thanks for pointing out that we only need to do +2 and not +3 and for making sure a '\\0' needs to be appended after str1 and sep before invoking strcat 更新:感谢指出我们只需要做+2而不是+3并确保在调用strcat之前需要在str1sep之后追加'\\ 0'

You can allocate the resulting string memory dynamically (at run-time, on the heap), using new[] in C++ (or malloc for a more C-like style): 您可以使用C ++中的new[] (或者更像C的样式的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;
}

Note that this memory must be released somewhere in your code, using delete[] if it was allocated with new[] , or free() if it was allocated using malloc() . 请注意,此内存必须在你的代码的某处释放了,使用delete[]如果它与分配new[]free()如果它是使用分配malloc()

This is quite complicated. 这很复杂。

You will simplify your code a lot if you use a robust C++ string class like std::string , with its convenient constructors to allocate memory, destructor to automatically free it, and operator+ and operator+= overloads to concatenate strings. 如果使用强大的C ++字符串类(std::string ,并使用方便的构造函数来分配内存,析构函数自动释放它,以及operator+operator+=重载来连接字符串,那么您将大大简化代码。 See how your code is simplified using std::string : 使用std::string查看代码的简化方式:

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

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

(Note that using raw C strings can also make your code more vulnerable to safety problems, since you must pay lot of attention to proper sizing destination strings, avoid buffer overruns , etc. This is another reason to prefer a RAII robust string class like std::string .) (请注意,使用原始C字符串也会使您的代码更容易受到安全问题的影响,因为您必须非常注意正确的大小调整目标字符串,避免缓冲区溢出等。这是另一个更喜欢RAII健壮字符串类的原因,如std::string 。)

sizeof(s1) returns the size of a pointer variable, not the length of the array which it points to. sizeof(s1)返回指针变量的大小, 而不是它指向的数组的长度。 Since you know that s1 points to a C-string, you should use the strlen() function instead. 既然你知道s1指向一个C字符串,你应该使用strlen()函数。

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM