【C++练习】25.在不使用标准库函数 “strlen“ 的情况下,C++ 中计算字符串长度
·
目录
-
- 方法一:使用计数器循环遍历
- 方法二:使用指针算术
- 方法三:递归
-
- 重要注意事项
- 更高效的写法 (方法二的变种)
- 总结
在不使用标准库函数 “strlen” 的情况下,C++ 中计算字符串长度(特指 C 风格字符串)的核心方法是遍历字符数组,直到遇到字符串结束符 “’\0’”。C 风格字符串以空字符 “’\0’” 作为结束标志,其长度不包括这个结束符。
方法一:使用计数器循环遍历
这是最直观的方法。初始化一个计数器为 0,然后从字符串的第一个字符开始,逐个检查字符是否为 “’\0’”,如果不是,计数器加一并继续检查下一个字符,直到遇到 “’\0’” 为止。
#include <iostream>
int stringLength(const char* str) {
int count = 0; // 初始化长度计数器
while (str[count] != '\0') { // 检查当前字符是否为字符串结束符
count++;
}
return count; // 返回计数结果
}
int main() {
const char* myString = "Hello, World!";
int len = stringLength(myString);
std::cout << "The length of the string is: " << len << std::endl; // 输出 13
return 0;
}
方法二:使用指针算术
这种方法利用指针的移动和算术运算。使用一个指针 “start” 记录字符串的起始地址,然后让另一个指针 “ptr” 从头开始向后移动,直到指向 “’\0’”。字符串的长度就是 “ptr” 和 “start” 之间的差值。
#include <iostream>
int stringLength(const char* str) {
const char* start = str; // 保存字符串的起始地址
while (*str != '\0') { // 检查当前指针所指的字符是否为结束符
str++; // 指针移动到下一个字符
}
return str - start; // 指针相减得到字符个数,即长度
}
int main() {
const char* myString = "Hello, C++!";
int len = stringLength(myString);
std::cout << "The length of the string is: " << len << std::endl; // 输出 11
return 0;
}
方法三:递归
递归方法通过将大问题分解为小问题来求解。如果当前字符不是 “’\0’”,那么字符串的长度就是 “1” 加上 “从下一个字符开始的子串的长度”。
#include <iostream>
int stringLength(const char* str) {
if (*str == '\0') { // 基准情况:如果当前字符是结束符
return 0;
} else {
return 1 + stringLength(str + 1); // 递归计算剩余子串的长度并加1
}
}
int main() {
const char* myString = "Recursion";
int len = stringLength(myString);
std::cout << "The length of the string is: " << len << std::endl; // 输出 9
return 0;
}
注意:递归写法代码简洁,但递归调用会有函数调用开销,对于非常长的字符串可能导致栈溢出,性能通常不如循环。
重要注意事项
- 空指针检查:在实际代码中,如果传入的字符指针可能是
“nullptr”,应在函数开始处进行检查,以避免解引用空指针导致未定义行为(如程序崩溃)。
int stringLength(const char* str) {
if (str == nullptr) { // 检查空指针
return 0;
}
int count = 0;
while (str[count] != '\0') {
count++;
}
return count;
}
- 确保字符串以 ‘\0’ 结尾:这些方法都依赖于字符串以空字符 “’\0’” 正确终止。如果传入的字符数组没有以 “’\0’” 结尾,函数将会一直遍历下去,导致缓冲区溢出,访问未分配的内存,产生不可预知的结果(如崩溃、错误数据)。
更高效的写法 (方法二的变种)
方法二的逻辑可以写得更加简洁:
int stringLength(const char* str) {
const char* ptr = str;
while (*ptr) { // '\0' 的 ASCII 值为 0, while(*ptr != '\0') 等价于 while(*ptr)
ptr++;
}
return ptr - str;
}
总结
| 方法 | 优点 | 缺点 | 适用场景 |
|---|---|---|---|
| 计数器循环 | 直观易懂,效率高 | 需要维护一个计数器变量 | 一般场景,最常用 |
| 指针算术 | 代码相对简洁,效率高 | 需要理解指针运算 | 追求代码简洁和效率的场景 |
| 递归 | 代码形式简洁,不创建局部变量计数器 | 递归开销大,可能栈溢出,性能较差 | 对代码简洁性有要求且字符串长度可控的场景 |
这些方法本质上都是遍历字符串直到遇到空字符
“’\0’”,时间复杂度都是 O(n),其中 n 是字符串的长度。
对于 C++ “std::string” 对象,不应使用上述方法。直接使用其 “length()” 或 “size()” 成员函数即可,它们能在常数时间 O(1) 内返回结果,且更安全。
#include <iostream>
#include <string>
int main() {
std::string str = "Hello, World!";
std::cout << "The length of the string is: " << str.length() << std::endl; // 或者 str.size()
return 0;
}
希望这些解释和示例能帮助你理解如何在不使用
“strlen” 的情况下计算 C 风格字符串的长度。
更多推荐


所有评论(0)