【问题标题】:Array loop termination in dynamic array动态数组中的数组循环终止
【发布时间】:2020-05-21 18:03:32
【问题描述】:

我正在练习数组中的循环,动态数组的循环不能用空字符终止吗?

for (int i=0; arr[i]!='\0'; i++)

以及如何在不使用这种格式的情况下终止这些循环:

for (const auto& value : arr)

【问题讨论】:

  • 你必须以某种方式知道数组的大小。没有什么神奇的方法可以做到。
  • Plus for(const auto& value : arr) 不适用于动态数组,原因很简单,无法从数组本身知道动态数组的大小。

标签: c++ arrays loops


【解决方案1】:

对于分配在空闲存储区的数组

int* arr = new int[size];

有两种方法可以知道终点在哪里。最直接的就是记住它有多大:

for (int i = 0; i < size; ++i)
    // do something with arr[i]

另一种方法是将数组的最后一个元素设置为 sentinel 值——该值不会显示在您正在使用的数据中,因此当您看到你知道你在数组的末尾:

for (int i = 0; i < size; ++i)
    arr[i] = i;
arr[size - 1] = -1;

现在您可以遍历数组查看值:

for (int i = 0; arr[i] != -1; ++i)
    // do something with arr[i]

这就是文字字符串的工作原理(尽管它们不是在免费存储中分配的):

const char *str = "Hello, world!";
for (int i = 0; str[i] != '\0'; ++i)
    std::cout << str[i];
std::cout << '\n';

这里的权衡是,第一种方法你必须传递一个额外的参数来告诉其他代码数组有多大:

void do_something(int* arr, int size) {
    for (int i = 0; i < size; ++i)
        // whatever
}

另一方面,有一个哨兵意味着你浪费了最后一个元素:

void do_something(int* arr) {
    for (int i = 0; arr[i] != -1; ++i)
        // whatever
}

最后一个元素没有您正在使用的任何数据;它只是为了标记结束。

当然,对于哨兵,存在您没有选择好的哨兵值的风险。如果您在数据中间的某处发现该值,则代码将停止循环,并且不会处理其余数据。

【讨论】:

  • 谢谢,这不仅帮助我纠正了我的错误,还帮助我清楚地理解了这个概念。
【解决方案2】:

你可以这样做:

int* arr = new int[size];
for(int i=0; i< size; ++i)
{
    //do somtiong;
}

但不要忘记删除最后的数组:

delete[] arr;

也正如@john 在评论范围中所写,基本循环仅适用于 STL 容器并静态创建了一个这样的容器: int arr[size]; 不支持动态分配数组。

【讨论】:

  • 我认为它们也适用于静态数组,但绝对不适用于动态数组。
  • 你是对的我现在检查它对我来说是新的:) onlinegdb.com/BJSZ8S4i8
【解决方案3】:

空字符将根据您的应用程序目的起作用。例如,如果给您一个数组,并且您事先知道数组中的最后一个元素是空字符,那么您可以使用空字符来终止循环。

请注意,如果使用空字符终止,则数组不能保存值 0,因为空字符的 ASCII 值为 0,并且只要数组包含 0,循环就会结束。在标准 C/C++ 中,空终止用于字符串。字符串是字符数组,以空字符标记数组的结尾。

一般情况下,使用数组时,您需要知道数组的大小。如果给你一个像vector 这样的STL 容器,那么你可以使用size() 操作符来访问它的大小。但是对于好的旧数组,您需要以某种方式知道大小。

【讨论】:

    【解决方案4】:

    如果你有一个动态字符数组:

    char* str = new char[size];
    

    除非你把它放在那里,否则没有空终止符。

    如果你知道有一个空终止符,你只能依赖它:

    char[] str1 = "Hello world"; // null terminated by default
    char* str2 = new char[16]; // enough space for copy
    strcpy(str2, str1); // strcpy also copies '\0'
    
    // now you can iterate
    for(int i = 0; str2[i] != '\0'; i++)
    {
        std::cout << str2[i];
    }
    

    但以上所有内容仅适用于char数组,不能适用于其他数据类型。因此,要遍历数组的所有元素,您需要事先知道它们的计数:

    int* arr = new int[size];
    for(int i = 0; i < size; i++)
    {
        // do something
    }
    

    【讨论】:

      猜你喜欢
      • 1970-01-01
      • 1970-01-01
      • 2021-01-11
      • 1970-01-01
      • 2014-12-10
      • 2017-04-30
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      相关资源
      最近更新 更多