下一段代码有一些理解上的问题。
#include<iostream>
using namespace std;
int main() {
char *str = "hi";
char *p = new char[strlen(str) + 1];
for (int i = 0; *(str + i); i++)
*(p + i) = *(str + i);
cout << p << endl;
return 0;
}
结果如下:
hi═¤¤¤¤
当我使用调试器时,我可以看到我的 p 指向一个由10或15或其他数量的符号组成的数组(取决于编译情况),所以我得到了更多“ hi”之后的符号。但是,当我使用strcpy()时:
#include<iostream>
using namespace std;
int main() {
char *str = "hi";
char *p = new char[strlen(str) + 1];
strcpy(p, str);
cout << p << endl;
return 0;
}
我得到结果:
hi
所以,有人可以向我解释一下,为什么我在程序的第一个示例中得到了这样的结果,以及如何像在第二个示例中那样对它进行重新处理以得到结果。 预先感谢。
答案 0 :(得分:2)
您没有将终止空字符添加到p
。
添加行
*(p + i) = '\0';
在for
循环之后。但是,为此,您必须在i
循环之前声明for
。
int i = 0;
for (i = 0; *(str + i); i++)
*(p + i) = *(str + i);
*(p + i) = '\0';
cout << p << endl;
答案 1 :(得分:2)
您忘记在第一个示例中以零终止字符串:
#include <cstddef>
#include <iostream>
int main()
{
char const *str = "hi";
std::size_t length = std::strlen(str);
char *p = new char[length + 1];
for (std::size_t i = 0; i < length; ++i)
p[i] = str[i];
str[length] = '\0';
std::cout << p << '\n';
delete[] p;
}
请注意:字符串文字是不可变的,因此应由char const*
指向。用于保存内存中对象大小或索引大小的正确类型是std::size_t
,而不是int
。如果您执行手动内存管理,则必须确保通过将使用new
获得的指针传递到delete
并将指针从new[]
传递到delete[]
来释放分配的内存。>
但是,您不应该手动进行内存管理。使用容器std::string
或std::vector
,或至少使用智能指针,例如std::shared_ptr<>
或std::unique_ptr<>
。
答案 2 :(得分:2)
答案是在循环的停止条件下,即*(str + i)
:
for (int i = 0 ; *(str + i) ; i++)
*(p + i) = *(str + i);
请注意,表达式中没有比较运算符。在需要逻辑条件的上下文中使用像这样的表达式时,存在与零的隐式比较,即*(str + i)
与*(str + i) != 0
的含义相同。
现在应该清楚为什么字符串保持未终止:循环在发现空终止符时停止,并且不将其复制到目标字符串中。
做同一件事的一种稍微“神秘”的方法是将比较与赋值结合起来,就像K&R书那样:
for (int i = 0 ; *(p + i) = *(str + i) ; i++)
;
现在,在分配后进行null测试,以确保目的地为null终止。