while循环for循环

时间:2018-05-26 18:28:32

标签: c++ for-loop while-loop

我在一本书中读到了这个示例代码。我无法弄清楚为什么以下示例代码的函数声明的这一部分是必要的:

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;
}

我删除后运行代码,没有问题。

1 个答案:

答案 0 :(得分:3)

循环是不必要的。以空值终止的字符串在第一个空字节处结束。如果分配的内存多于实际字符串所需的内存,则这些额外字节中的内容无关紧要。所有未破坏的C字符串处理代码在第一个空终止符处停止。所需要的只是一个

p[i] = '\0';

for循环之后。但是,一个空字节是必需的。 C字符串函数依赖于它,并且如果它丢失,将很乐意溢出分配的内存。基本上他们会(尝试)继续前进,直到他们偶然发现内存中的下一个空字节。如果超过分配的内存,则会导致未定义的行为,如果运气不好会导致崩溃;如果你不太幸运,可能会损坏数据。

那说:昨天扔掉那本书。代码是从第一行到最后一行的灾难。它几乎没有资格成为C ++。大多数都是简单的C.即使作为C代码,它也是非常值得怀疑的。

  • Why to avoid using namespace std。 @ vol7ron在评论中指出主要投诉是针对标题中的using namespace std。这里它用在 .cpp 文件中的函数内部,这显着减轻了影响。虽然在我看来仍然值得避免。如果您不深入了解标准库的实现,那么您并不了解所有符合范围的符号。如果您需要它以提高可读性,那么提取特定符号(例如using std::cout;)是更好的选择。此外,我相信我并不是唯一一个期待std::前缀的人。例如,std::string是我期望看到的。 string略显偏离。总是存在一个挥之不去的怀疑,它可能不是std库字符串,而是自定义字符串类型。因此,包含前缀也可以受益可读性。
  • 为什么所有的C弦都疼?我们暂时有std::string ...
  • 在循环中复制字符?真的吗?这就是std::strcpy()的用途。
  • 原始newdelete无处不在:因为您必须手动跟踪新/删除对以避免内存泄漏,因此容易出错。
  • 更糟糕的是:不对称拥有原始指针。 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);
}