【问题标题】:how can i split an uninitialized array in half?如何将未初始化的数组分成两半?
【发布时间】:2021-05-12 09:17:54
【问题描述】:

所以我在 C++ 中有这个代码,其中我有一个未定义的初始值的数组,并且用户应该继续输入数组的值,直到退出代码 -1。一旦输入,数组大小由输入的数量决定。然后它必须被分成两半成两个数组,第一个具有原始数组的前半部分,第二个具有原始数组的后半部分。

#include <iostream>
using namespace std;

int main()
{
    int n;
    n++;
    int a[n];
    for (int i = 0; i < n; i++)
    {
        cin >> a[i];
        n++;
        if (a[i] == -1)
        {
            n--;
            break;
        }
    }
    cout << n << endl;
    int e[n / 2];
    for (int j = 0; j < (n / 2); j++)
    {
        e[j] = a[j];
    }
    int q = 0;
    int o[n / 2];
    for (int l = (n / 2); l < n; l++)
    {
        o[q] = a[l];
        q++;
    }
    for (int h = 0; h < n / 2; h++)
    {
        cout << e[h] << "  ";
    }
    cout << '\n';

    for (int h = 0; h < n / 2; h++)
    {
        cout << o[h] << "  ";
    }
    return 0;
}

我面临的问题是,当数组大小为 4 时,它工作正常,但当它的大小为 6 时,第 5 和第 6 个值变为 3 0 。而不是我输入的值。制作更大的数组也有类似的问题,数组中的某些值被损坏。

【问题讨论】:

  • int a[n]; 不是标准 c++,请改用 std::vectorWhy aren't variable-length arrays part of the C++ standard?
  • @largest_prime_is_463035818,这是否意味着 OP 正在编译一些选项以使其正常工作?
  • @Enlico gcc 需要通过-pedantic 进行一些推送以禁用扩展。我的意思是使用扩展很好,只要知道它是一个扩展并且代码是不可移植的。虽然,经常被忽略和误解,这里既不需要 VLA,也不是正确的工具(一些“教程”推广它们,我不知道为什么)
  • 谢谢!我很高兴很久以前没有看到这样的东西:D

标签: c++ arrays sorting


【解决方案1】:
int n;
n++;

您正在递增一个具有不确定值的变量。程序的行为是未定义的。数组应该有多大?

int a[n];

数组变量的大小不是编译时间常数。该程序格式不正确。要么使用编译时常量大小,要么动态分配数组。实现后者的最简单方法是使用std::vector

那么它必须分成两半成两个数组

我怀疑这里可能存在 XY 问题。对原始数组的不同部分有迭代器就足够了吗?这样就不需要创建额外的数组,也不需要将值复制到这些数组中。

这是一个这样的解决方案:

auto first  = std::begin(a);
auto middle = std::next(first, n/2);
auto last   = std::end(a);
std::span first_half  {first,  middle};
std::span second_half {middle, last  };

【讨论】:

    【解决方案2】:

    您的代码很好地拆分了数组。只有在从输入中获取数组元素并打印数组时才会出错。

    正如 maximum-prime-is-463035818 所说,std::vector 是一种更好的数据结构。但是,如果您只允许使用数组,请假定数组大小的最大大小,因为数组在声明时需要一个大小。

    #include <iostream>
    #define MAX 1000
    using namespace std;
    int main()
    {
        int n;
        n++;
        int a[MAX];
        for (int i = 0; i < MAX; i++)
    

    n 初始化为0。这是为了避免n 带有垃圾值。删除 n++;,因为您不应该在开始时增加它。

    int main()
    {
        int n = 0;
        int a[MAX];
        for (int i = 0; i < MAX; i++)
    

    要正确打印另一个数组,请改用n - n / 2 来计算另一个数组的正确大小。

    int o[n - n / 2];
    for (int l = (n / 2); l < n; l++)
    {
        o[q] = a[l];
        q++;
    ...
    for (int h = 0; h < n - n / 2; h++)
    {
        cout << o[h] << "  ";
    }
    

    注意:当块只有一个语句时,您可以省略 for 循环中的大括号。另外,使用更有意义的标识符使其更具可读性(q 是什么?o 数组代表什么?)

    【讨论】:

    • 解释为什么它被投票-1 或提出改进我的答案的建议
    • 假设MAX size 当大小由用户输入确定时,这是一个不好的建议。对常量使用宏是不好的建议。在for 上省略大括号是不好的建议。在 OP 代码中不提及未定义的行为是缺少重要方面,而提及“垃圾”则支持关于 UB 的无用神话。
    • 输入中的size是如何确定的?用户放了任意数量的元素,在程序启动之前是无法知道的。使用宏有什么不好?它使代码更具可读性。省略括号? for 循环只有一条语句要执行。你的意思是什么神话?
    • 在程序开始之前无法知道,这就是重点。没有std::vector,数组也可以具有动态大小。宏对于这项工作来说是错误的工具,它们有这里不需要的缺点。 const size_t size = 1000; 的可读性不低。我指的是“垃圾”神话。代码需要修复不是因为它可能会产生垃圾输出,而是因为即使它可以产生看起来不错的输出,它也会被破坏。顺便说一句,我不是“解释投票”,选民不必也不应该解释他们的投票(我会搜索相关的元帖子)。只是提出改进建议
    猜你喜欢
    • 2021-09-24
    • 1970-01-01
    • 1970-01-01
    • 2020-09-21
    • 2017-11-25
    • 1970-01-01
    • 2023-01-17
    • 2017-04-22
    • 1970-01-01
    相关资源
    最近更新 更多