如何编写适用于两个动态数组的 strcat 函数
How to code a strcat function that works with two dynamic arrays
正如我们所知,strcat 函数将一个 C 字符串连接到另一个 C 字符串上,形成一个包含另外两个 C 字符串的大 C 字符串。
我的问题是如何创建一个 strcat
函数来处理两个动态分配的数组。
所需的 strcat
函数应该能够适用于任何大小的 myStr1 和 myStr2
//dynamic c-string array 1
char* myStr1 = new char [26];
strcpy(myStr1, "The dog on the farm goes ");
//dynamic c-string array 2
char* myStr2 = new char [6];
strcpy(myStr2, "bark.");
//desired function
strcat(myStr1,myStr2);
cout<<myStr1; //would output 'The dog on the farm goes bark.'
这是我自己能做到的:
//*& indicates that the dynamic c-string str1 is passed by reference
void strcat(char*& str1, char* str2)
{
int size1 = strlen(str1);
int size2 = strlen(str2);
//unknown code
//str1 = new char [size1+size2]; //Would wipe out str1's original contents
}
谢谢!
您分配内存并使您的指针指向该内存。然后你 覆盖 指针,使它们指向其他地方。例如的分配myStr1
导致变量指向字符串文字而不是您分配的内存。您需要将字符串复制到您分配的内存中。
当然,这种复制会导致另一个问题,因为您似乎忘记了 C 字符串需要一个额外的字符作为终止符。因此,具有 5 个字符的 C 字符串需要 space 六个 个字符。
至于你的串联功能,你也需要在这里做复制。为两个字符串 加上 分配足够的 space 一个终止符。然后将第一个字符串复制到新内存的开头,将第二个字符串复制到末尾。
您还需要一个临时指针变量来分配您分配的内存,否则 "would wipe out str1's original contents"(不完全正确,您只是让 str1
指向其他地方,丢失了原始指针)。
您首先需要更好地理解指针的工作原理。例如您的代码:
char* myStr1 = new char [25];
myStr1 = "The dog on the farm goes ";
首先分配 25 个字符,然后忽略指向该分配区域的指针(技术术语是 "leaks it")并设置 myStr1
指向字符串文字。
该代码应该使用 strcpy
而不是从字符串文字复制到分配的区域。除了该字符串是 25 个字符之外,因此您需要为至少 26 个字符分配 space,因为 ASCII NUL
终止符 (0x00
).
需要一个字符。
该部分的正确代码应该是:
char* myStr1 = new char [26]; // One more than the actual string length
strcpy(myStr1, "The dog on the farm goes ");
要连接 C 字符串,算法可以是:
- 测量两个字符串的长度
n1
和n2
(withstrlen
)
- 为目标缓冲区分配
n1+n2+1
个字符(C 字符串终止符需要 +1
)
strcpy
缓冲区开头的第一个字符串
strcat
第二个字符串到缓冲区(*)
delete[]
原始字符串缓冲区的内存 如果不需要它们(这是否正确取决于谁是 "owner" 的字符串...这部分很棘手,因为 C 字符串接口没有指定)。
(*) 这不是最有效的方法。 strcat
将遍历字符串的所有字符以找到它结束的位置,但是您已经知道第一个字符串的长度是 n1
并且也可以使用 strcpy
来完成连接选择正确的开始 buffer+n1
。如果您知道 strcpy
的计数,则可以在任何地方使用 memcpy
而不是 strcpy
更好,因为 strcpy
必须检查每个字符是否为 NUL
终止符。然而,在进行这种优化之前,您应该清楚地了解事情是如何工作的……只有当字符串连接代码正确并且对您来说完全显而易见时,您才有权开始考虑优化.
PS:一旦你获得了所有这些正确、有效和高效,你就会意识到使用 std::string
对象有多大的简化,所有这些复杂的代码都变成了 s1+s2
.
正如我们所知,strcat 函数将一个 C 字符串连接到另一个 C 字符串上,形成一个包含另外两个 C 字符串的大 C 字符串。
我的问题是如何创建一个 strcat
函数来处理两个动态分配的数组。
所需的 strcat
函数应该能够适用于任何大小的 myStr1 和 myStr2
//dynamic c-string array 1
char* myStr1 = new char [26];
strcpy(myStr1, "The dog on the farm goes ");
//dynamic c-string array 2
char* myStr2 = new char [6];
strcpy(myStr2, "bark.");
//desired function
strcat(myStr1,myStr2);
cout<<myStr1; //would output 'The dog on the farm goes bark.'
这是我自己能做到的:
//*& indicates that the dynamic c-string str1 is passed by reference
void strcat(char*& str1, char* str2)
{
int size1 = strlen(str1);
int size2 = strlen(str2);
//unknown code
//str1 = new char [size1+size2]; //Would wipe out str1's original contents
}
谢谢!
您分配内存并使您的指针指向该内存。然后你 覆盖 指针,使它们指向其他地方。例如的分配myStr1
导致变量指向字符串文字而不是您分配的内存。您需要将字符串复制到您分配的内存中。
当然,这种复制会导致另一个问题,因为您似乎忘记了 C 字符串需要一个额外的字符作为终止符。因此,具有 5 个字符的 C 字符串需要 space 六个 个字符。
至于你的串联功能,你也需要在这里做复制。为两个字符串 加上 分配足够的 space 一个终止符。然后将第一个字符串复制到新内存的开头,将第二个字符串复制到末尾。
您还需要一个临时指针变量来分配您分配的内存,否则 "would wipe out str1's original contents"(不完全正确,您只是让 str1
指向其他地方,丢失了原始指针)。
您首先需要更好地理解指针的工作原理。例如您的代码:
char* myStr1 = new char [25];
myStr1 = "The dog on the farm goes ";
首先分配 25 个字符,然后忽略指向该分配区域的指针(技术术语是 "leaks it")并设置 myStr1
指向字符串文字。
该代码应该使用 strcpy
而不是从字符串文字复制到分配的区域。除了该字符串是 25 个字符之外,因此您需要为至少 26 个字符分配 space,因为 ASCII NUL
终止符 (0x00
).
该部分的正确代码应该是:
char* myStr1 = new char [26]; // One more than the actual string length
strcpy(myStr1, "The dog on the farm goes ");
要连接 C 字符串,算法可以是:
- 测量两个字符串的长度
n1
和n2
(withstrlen
) - 为目标缓冲区分配
n1+n2+1
个字符(C 字符串终止符需要+1
) strcpy
缓冲区开头的第一个字符串strcat
第二个字符串到缓冲区(*)delete[]
原始字符串缓冲区的内存 如果不需要它们(这是否正确取决于谁是 "owner" 的字符串...这部分很棘手,因为 C 字符串接口没有指定)。
(*) 这不是最有效的方法。 strcat
将遍历字符串的所有字符以找到它结束的位置,但是您已经知道第一个字符串的长度是 n1
并且也可以使用 strcpy
来完成连接选择正确的开始 buffer+n1
。如果您知道 strcpy
的计数,则可以在任何地方使用 memcpy
而不是 strcpy
更好,因为 strcpy
必须检查每个字符是否为 NUL
终止符。然而,在进行这种优化之前,您应该清楚地了解事情是如何工作的……只有当字符串连接代码正确并且对您来说完全显而易见时,您才有权开始考虑优化.
PS:一旦你获得了所有这些正确、有效和高效,你就会意识到使用 std::string
对象有多大的简化,所有这些复杂的代码都变成了 s1+s2
.