为什么我不能直接从cin读取到数组索引?

时间:2019-07-16 09:49:15

标签: c++ arrays

我正在尝试在HackerRank上学习C ++,但是在其中一项练习中遇到了一种奇怪的情况。

练习是读入一个数字列表,并将其打印出来。但是,我的代码似乎为其中一个测试用例吐出了垃圾值。

#include <cmath>
#include <cstdio>
#include <vector>
#include <iostream>
#include <algorithm>
using namespace std;


int main() {
    /* Enter your code here. Read input from STDIN. Print output to STDOUT */
    int n;
    int temp;
    int *arr = new int[n]();

    cin >> n;

    for (int i = 0; i < n; i++) {
        // This works
        /*
         cin >> temp;
         arr[i] = temp;
        */
        cin >> arr[i]; // But this doesn't
    }

    for (int j = n - 1; j >= 0; j--) {
        cout << arr[j] << " ";
    }

    return 0;
}

有问题的测试用例的输入有点长,所以我将其放入了一个pastebin:https://pastebin.com/VCjciUet

直接从cin(即cin >> arr [i])读取时,输出如下:

6002 {...truncated...} 8084 3909 5426 808465952 942682421 540227121 824194360 909189169 959526176 825243441 540619576 891304241 842539056 825374240 960050744 540619575 958412851 892805173 808722489 960050720 959460408 540553528 891302967 926425141 909718304 859189816 540226104 941634871 842342452 808662048 809054519 540160311 891303224 875634745 808466464 876034355 540423990 958412593 925966391 892613920 808662321 540422194 958411319 840972592 876159030 825374752 926364977 540553273 874526514 924858416 876093495 875770144 858928434 540030771 941634360 875831350 959788576 842413112 540095796 874525239 959651892 959723040 842018869 540096056 874525751 540424244 908079412 859185206 960051232 875901235 540028978 924857392 926228532 808925216 959526195 540095028 908079408 960045108 825308448 942684471 540096306 840971065 858857522 892739637 926103072 842150707 540291892 941634608 875700275 876033824 909457721 540160822 824194100 859250740 825766688 875706678 540356912 840972345 875962418 808923936 825242421 540226869 924856887 892608560 825439520 909130037 540620083 857749813 943267896 943011360 925972531 540094773 840971319 825368627 808728608 808728374 540161588 908079666 842080313 909652512 876032561 540554040 941635895 808788017 808858144 825505842 540555320 840972344 892870710 825832480 842150450 540422199 874526264 909713464 892482592 926366005 540094769 924857396 842407992 892811040 875705656 540619320 908080177 857748528 875962423 909652256 892745779 540226866 540423479 540554291 540619064 540096820 891302709 926294071 808597792 892679200 909522745 540555315 924858417 891303988 909451315 859054128 909523232 942684473 540031287 857748019 808984630 959591456 925971510 540619057 958411316 909385783 825506080 858927392 808597810 540357168 908080176 909385778 858993440 875705632 892679737 540422960 924858672 875896883 875967520 842283065 540358967 908079669 859381815 943273248 825439288 540422969 908081465 926162994 925905440 959591735 540094512 824193335 859054130 875896889 876098848 959459892 540358706 540028977 2139 7277 9113 6303 924 7608 749 6043 

但是,当我首先使用临时变量时,输出是准确的(整个数字列表都被反转了)。

为什么会这样?

2 个答案:

答案 0 :(得分:2)

之所以这样,是因为您没有收听编译器:

main.cpp: In function 'int main()':
main.cpp:13:27: warning: 'n' is used uninitialized in this function [-Wuninitialized]
     int *arr = new int[n]();
                       ^

编写低级代码很容易发生此类错误。优先选择阻止它们的高级库功能。如果您的目标是读取一组数字并打印出来,那么可以完全没有任何循环:

#include <vector>
#include <iostream>
#include <algorithm>

int main() {
    std::vector<int> v;

    std::copy(
        std::istream_iterator<int>(std::cin),
        std::istream_iterator<int>(),
        std::back_inserter(v)
    );

    std::copy(v.begin(), v.end(), std::ostream_iterator<int>(std::cout));
}

该代码将一直读取直到数字结束。如果您想先阅读它们的计数,则仍应事先检查它们是否未结束。通过HackerRank之类的东西进行学习的一个问题是,他们完全省略了学习输入清理和错误处理的知识,这在现实世界的编码中至关重要。

答案 1 :(得分:1)

打开compiler warnings

source>:13:24: error: 'n' is used uninitialized in this function [-Werror=uninitialized]

13 |     int *arr = new int[n]();

   | 

n在使用时未初始化。另外,您永远不会delete d数组。是的,操作系统将在您清除后清除,但最好释放已分配的内存。这是固定版本:

#include <iostream>

int main() {
    int n;
    std::cin >> n;
    int *arr = new int[n]();

    for (int i = 0; i < n; i++) {
        std::cin >> arr[i]; 
    }

    for (int j = n - 1; j >= 0; j--) {
        std::cout << arr[j] << " ";
    }

    delete[] arr;
    return 0;
}

话虽如此,使用std::vectorstd::size_t可能是一个更好的主意。这是您要做的事情:

#include <iostream>
#include <vector>

int main() {
    std::size_t n{};
    std::vector<int> vec{};
    std::cin >> n;
    vec.resize(n);

    for (auto&& elm : vec)
        std::cin >> elm;

    for (auto rit = vec.crbegin(), rend = vec.crend(); rit != rend; ++rit)
        std::cout << *rit << ' ';

    return 0;
}

Boost的帮助下,该示例可以简化。

#include <iostream>
#include <vector>
#include <boost/range/adaptor/reversed.hpp>

int main() {
    std::size_t n{};
    std::vector<int> vec{};
    std::cin >> n;
    vec.resize(n);

    for (auto&& elm : vec)
        std::cin >> elm;

    for (auto&& elm : boost::adaptors::reverse(vec))
        std::cout << elm << ' ';
}