【C++练习】26.在 C++ 中,不使用 “strcpy“ 函数将一个字符串复制到另一个字符串
·
目录
- 方法概览
-
- 1. C风格字符数组的复制
-
- 1.1 循环逐个字符复制
- 1.3 使用 "memcpy" 函数
- 2. 使用 C++ "std::string" 类
-
- 2.1 使用赋值运算符 "="
- 2.2 使用拷贝构造函数
- 2.3 使用 "assign()" 方法
- 选择建议
- 注意事项
在 C++ 中,不使用 “strcpy” 函数将一个字符串复制到另一个字符串有多种方法,主要可分为使用 C 风格字符数组 和 C++ “std::string” 类 两大方向。
方法概览
| 方法类别 | 具体方法 | 关键特点 | 适用场景 |
|---|---|---|---|
| C风格字符数组 | 循环逐个字符复制 | 最基础,手动管理内存和结束符 | 需要完全控制底层操作或受限环境 |
| - | 使用指针操作 | 更接近底层,可能更高效 | 理解指针操作,追求性能 |
| - | 使用 “memcpy” | 按字节块复制,效率高 | 复制包括 “’\0’” 在内的整个字符串数据 |
| C++ “std::string” | 赋值运算符 “=” | 最简单、安全,自动管理内存 | 现代C++代码的推荐方式 |
| - | 拷贝构造函数 | 在创建新对象时直接初始化 | 需要在对象构造时复制字符串 |
| - | “assign()” 方法 | 提供更灵活的复制选项(如子串) | 需要更复杂的复制逻辑 |
1. C风格字符数组的复制
C风格的字符串是以空字符 ("’\0’") 结尾的字符数组。复制时需要确保目标数组有足够空间,并手动添加结束符。
1.1 循环逐个字符复制
思路:遍历源字符串的每个字符(直到遇到 “’\0’”),逐个赋值给目标数组,最后在目标数组末尾手动添加 “’\0’”。
#include <iostream>
void copyString(const char* src, char* dest) {
int i = 0;
// 循环复制字符,直到遇到源字符串的结束符
while (src[i] != '\0') {
dest[i] = src[i];
i++;
}
dest[i] = '\0'; // 手动添加结束符
}
int main() {
const char* src = "Hello, World!";
char dest[20]; // 确保目标数组足够大
copyString(src, dest);
std::cout << "Copied string: " << dest << std::endl;
return 0;
}
###cpp1.2 使用指针操作
思路:使用指针而非数组索引进行遍历和复制,原理与循环类似。
#include <iostream>
void copyString(const char* src, char* dest) {
// 使用指针移动并复制,直到遇到源字符串的结束符
while (*src != '\0') {
*dest = *src;
src++;
dest++;
}
*dest = '\0'; // 手动添加结束符
}
// 更简洁的写法:
// void copyString(const char* src, char* dest) {
// while ((*dest++ = *src++)) != '\0');
// }
int main() {
const char* src = "Hello, World!";
char dest[20]; // 确保目标数组足够大
copyString(src, dest);
std::cout << "Copied string: " << dest << std::endl;
return 0;
}
1.3 使用 “memcpy” 函数
思路:计算源字符串的长度(包括结尾的 “’\0’”),然后使用 “memcpy” 按字节批量复制。这通常比逐个字符复制效率更高。
#include <iostream>
#include <cstring> // 提供 memcpy 和 strlen
int main() {
const char* src = "Hello, World!";
size_t length = std::strlen(src) + 1; // +1 是为了包含结束符 '\0'
char* dest = new char[length]; // 动态分配内存
std::memcpy(dest, src, length); // 复制字节块
std::cout << "Copied string: " << dest << std::endl;
delete[] dest; // 释放内存
return 0;
}
2. 使用 C++ “std::string” 类
“std::string” 自动管理内存,无需担心缓冲区大小和结束符,是现代C++更安全、便捷的选择。
2.1 使用赋值运算符 “=”
思路:直接使用
“std::string” 的赋值运算符,这是最直观的方式。
#include <iostream>
#include <string>
int main() {
std::string str1 = "Hello, World!";
std::string str2;
str2 = str1; // 使用赋值运算符
std::cout << "Copied string: " << str2 << std::endl;
return 0;
}
2.2 使用拷贝构造函数
思路:在定义新的
“std::string” 对象时,直接用源字符串进行初始化。
#include <iostream>
#include <string>
int main() {
std::string str1 = "Hello, World!";
std::string str2(str1); // 使用拷贝构造函数
std::cout << "Copied string: " << str2 << std::endl;
return 0;
}
2.3 使用 “assign()” 方法
思路:
“std::string” 的 “assign()” 方法提供了多种重载,可以复制整个字符串或其中一部分。
#include <iostream>
#include <string>
int main() {
std::string str1 = "Hello, World!";
std::string str2;
str2.assign(str1); // 复制整个字符串
std::cout << "Copied string: " << str2 << std::endl;
return 0;
}
选择建议
- 首选 “std::string”:对于现代C++开发,强烈推荐使用 “std::string”。它更安全(自动管理内存,避免缓冲区溢出)、更便捷(代码简洁),且功能强大。
- 谨慎使用字符数组:只有在处理遗留代码、特定底层操作或特殊性能要求时,才考虑使用C风格字符数组。使用时务必仔细管理内存和结束符。
注意事项
-
缓冲区溢出:使用字符数组时,必须确保目标数组有足够的空间容纳源字符串(包括结尾的
“’\0’”),否则会导致严重的程序错误或安全漏洞。 -
手动添加结束符:使用字符数组且自行实现复制逻辑时,切勿忘记在目标字符串末尾手动添加
“’\0’”,否则它就不是一个有效的C字符串,后续操作(如打印)会出现未定义行为。 -
“memcpy” 的适用性:“memcpy” 是内存块的复制,不关心内容。用于复制字符串时,需确保复制的长度包含了结尾的 “’\0’”。
希望这些方法和代码示例能帮助你更好地理解如何在C++中复制字符串。根据你的具体场景选择最合适的方法吧。
更多推荐


所有评论(0)