c++ - for 循环内的 while 循环

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

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

最佳答案

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

p[i] = '\0';

for循环之后。然而,该一个空字节是强制性的。 C 字符串函数依赖于它,如果它丢失,将会很高兴地溢出分配的内存。本质上,他们会(尝试)继续前进,直到偶然发现内存中的下一个空字节。如果超过了分配的内存,则会导致未定义的行为,如果幸运的话,会导致崩溃;或者如果您不那么幸运的话,数据也会损坏。

也就是说:扔掉昨天的那本书。这段代码从第一行到最后一行都是一场灾难。它勉强符合 C++ 的资格。大部分都是纯 C 代码。即使作为 C 代码,它也很值得怀疑。

  • Why to avoid using namespace std 。 @vol7ron 在评论中指出,主要的提示是反对在 header 使用命名空间std。这里它在 .cpp 文件的函数内部使用,这显着减少了影响。尽管在我看来,这仍然值得避免。如果您不深入了解标准库的实现,您就不会真正了解您拉入范围的所有符号。如果您需要它来提高可读性,则引入特定符号(例如 using std::cout;)是更好的选择。另外,我相信我并不是唯一一个期待 std:: 前缀的人。例如, std::string 是我期望看到的。 string 看起来有点不对劲。总是有一个挥之不去的疑问,它可能不是标准库字符串,而是自定义字符串类型。因此,包含前缀也可以提高可读性。
  • 为什么 C 弦疼痛?我们已经使用 std::string 一段时间了……
  • 循环复制字符?严重地?这就是 std::strcpy() 的用途。
  • 原始newdelete无处不在:容易出错,因为您必须手动跟踪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);
}

关于c++ - for 循环内的 while 循环,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/50545859/

相关文章:

c++ - 为什么我应该在 scanf() 系列成员中加入一个长度修饰符作为参数?有什么好处?带有长度修饰符的 scanf 有什么作用?

c++指向基类的指针没有派生类成员函数,但是指针是用派生创建的

C++:文本文件中的数据是什么类型?

java - 如何在按钮操作中用 int 替换 string?

PHP while循环基于MYSQL查询结果丢失第一行

java - 如何强制正在读取行的 while 循环在 3 个空行之前不停止?

带有 vector 、指针的 C++ 析构函数,

javascript - 如何使用 for 循环遍历未知值

c++ - 如何计算排序数组中的重复数字

java - 正确获取数组中的单词