我在一本书中读到了这个示例代码。我无法弄清楚为什么以下示例代码的函数声明的这一部分是必要的:
while (i <= n)
p[i++] = '\0'; // set rest of string to '\0'
以下是整个代码:
#include <iostream>
const int ArSize = 80;
char * left(const char * str, int n = 1);
int main()
{
using namespace std;
char sample[ArSize];
cout << "Enter a string:\n";
cin.get(sample,ArSize);
char *ps = left(sample, 4);
cout << ps << endl;
delete [] ps; // free old string
ps = left(sample);
cout << ps << endl;
delete [] ps; // free new string
return 0;
}
// This function returns a pointer to a new string
// consisting of the first n characters in the str string.
char * left(const char * str, int n)
{
if(n < 0)
n = 0;
char * p = new char[n+1];
int i;
for (i = 0; i < n && str[i]; i++)
p[i] = str[i]; // copy characters
while (i <= n)
p[i++] = '\0'; // set rest of string to '\0'
return p;
}
我删除后运行代码,没有问题。
答案 0 :(得分:3)
循环是不必要的。以空值终止的字符串在第一个空字节处结束。如果分配的内存多于实际字符串所需的内存,则这些额外字节中的内容无关紧要。所有未破坏的C字符串处理代码在第一个空终止符处停止。所需要的只是一个
p[i] = '\0';
在for
循环之后。但是,一个空字节是必需的。 C字符串函数依赖于它,并且如果它丢失,将很乐意溢出分配的内存。基本上他们会(尝试)继续前进,直到他们偶然发现内存中的下一个空字节。如果超过分配的内存,则会导致未定义的行为,如果运气不好会导致崩溃;如果你不太幸运,可能会损坏数据。
那说:昨天扔掉那本书。代码是从第一行到最后一行的灾难。它几乎没有资格成为C ++。大多数都是简单的C.即使作为C代码,它也是非常值得怀疑的。
using namespace std
。这里它用在 .cpp 文件中的函数内部,这显着减轻了影响。虽然在我看来仍然值得避免。如果您不深入了解标准库的实现,那么您并不了解所有符合范围的符号。如果您需要它以提高可读性,那么提取特定符号(例如using std::cout;
)是更好的选择。此外,我相信我并不是唯一一个期待std::
前缀的人。例如,std::string
是我期望看到的。 string
略显偏离。总是存在一个挥之不去的怀疑,它可能不是std库字符串,而是自定义字符串类型。因此,包含前缀也可以受益可读性。std::string
... std::strcpy()
的用途。new
和delete
无处不在:因为您必须手动跟踪新/删除对以避免内存泄漏,因此容易出错。left()
分配并返回一个指针;并且调用者的责任将其删除。它不会比那更容易出错。......这些只是乍看之下的问题。
这段代码应该是什么样的:
#include <iostream>
#include <string>
std::string left(const std::string& str, std::size_t len = 1);
int main()
{
// getline can fail. If that happens we get an empty string.
std::string sample;
std::getline(std::cin, sample);
auto ps = left(sample, 4);
std::cout << ps << '\n';
ps = left(sample);
std::cout << ps << '\n';
return 0;
}
// `len` may be longer than the string. In that case a copy
// of the complete input string is returned.
std::string left(const std::string& str, std::size_t len)
{
return str.substr(0, len);
}