简体   繁体   English

std::copy 不会在 C++ 中复制向量

[英]std::copy doesn't copy vector in C++

To find all sequences of fixed length which contain only 0 and 1 I use this code:要查找仅包含 0 和 1 的所有固定长度序列,我使用以下代码:

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

using namespace std;

void print_array(vector<string> arr) {
  cout << '[';
  int n = arr.size();
  for (size_t i = 0; i < n; i++) {
    cout << arr[i];
    if (i < (n - 1)) {
      cout << ", ";
    }
  }
  cout << ']' << endl;
}

vector<string> get_variants(int n) {
  vector<string> result = {"0", "1"};
  vector<string> temp;
  temp.reserve(2);
  result.reserve(2);
  for (int i=0; i < (n - 1); ++i) {
    copy(result.begin(), result.end(), temp.end()); // [1]
    for (int j=0; j < result.size(); ++j) {
      temp[j] += "0";
      result[j] += "1";
    }
    copy(temp.begin(),temp.end(), result.end());
    temp.clear();
  }
  return result;
}

int main(int argc, char const *argv[]) {
  int n;
  cin >> n;
  vector<string> maybe = get_variants(n);
  print_array(maybe);
  return 0;
}

But vector temp is empty, before copying in line which I marked [1] and after.但是向量temp是空的,在我标记为 [1] 的行中复制之前以及之后。 So, my program's output was [0111, 1111] .所以,我的程序的 output 是[0111, 1111] What I'm doing wrong?我做错了什么?

A more straightforward way than using std::copy is the use of .insert() :比使用std::copy更直接的方法是使用.insert()

temp.insert(temp.end(), result.begin(), result.end()); //1
...
result.insert(result.end(), temp.begin(), temp.end()); // 2nd copy

You are writing to temp.end() and result.end() .您正在写信给temp.end()result.end() These iterators represent "one past the end", and therefore writing to these iterators is Undefined Behavior.这些迭代器代表“一个结束”,因此写入这些迭代器是未定义的行为。

You seem to be looking for std::back_inserter .您似乎正在寻找std::back_inserter This will create an iterator that will insert a new element to your container when it is written through.这将创建一个迭代器,该迭代器将在写入时将新元素插入到您的容器中。

std::copy(result.begin(), result.end(), std::back_inserter(temp));

While this answers the posted question, there remain other errors in your code leading to Undefined Behavior.虽然这回答了发布的问题,但您的代码中仍然存在其他导致未定义行为的错误。

Trying to compile your program with a C++ compiler will not work, because you include #include <bits/stdc++.h> which is a non tC++ standard compliant header.尝试使用 C++ 编译器编译您的程序将不起作用,因为您包含了#include <bits/stdc++.h> ,它是不符合 tC++ 标准的 header。

You should never include this file.你永远不应该包含这个文件。

You are using typical competitive programming stuff, but including all C++ headers and not use them will eat up Compile time for no good reason.您正在使用典型的竞争性编程材料,但包括所有 C++ 头文件并且不使用它们会无缘无故地占用编译时间。

Then, you typedef the typical competitive programming abbreviations.然后,您键入定义典型的竞争性编程缩写。 2 of them, you do not use.其中2个,你不使用。 Then there is no reason to define them.那么就没有理由定义它们了。

I recommend to not do this any longer.我建议不要再这样做了。 And in C++, please use the using statement.在 C++ 中,请使用using语句。

Then, although you want to be fast, you pass arr by value to your print function.然后,虽然你想快点,但你将arr按值传递给你的 print function。 This will copy the whole vector.这将复制整个向量。

You assign/compare a lot of int with unsigned int values.您分配/比较了很多 int 与 unsigned int 值。 This you should not do.这是你不应该做的。

Additionally: Please use meaningful variable names and write comments.另外:请使用有意义的变量名并写注释。 The more the better.越多越好。


Regarding your specific bug.关于您的特定错误。 Both std::copy statements use end iterator as target.两个std::copy语句都使用end迭代器作为目标。 End is end.结束就是结束。 It is past the end of the vector.它超过了向量的末尾。 Please use std::back_inserter instead.请改用std::back_inserter


Regarding the algorithm.关于算法。 I took a while for me to realize that you basically want to create binary numbers.我花了一段时间才意识到你基本上想要创建二进制数。 Nothing else.没有其他的。 Unfortunately you translated that in a very complicated way.不幸的是,您以非常复杂的方式翻译了它。

Normally, you just would count from 0 to 2^n-1 and then show the data.通常,您只需从 0 数到 2^n-1,然后显示数据。 Thats all.就这样。 Becuase the numbers may be of arbitraty length, we will use manual addition of digits like in scholl on a peice of paper.因为数字可能是任意长度,我们将使用手动添加数字,就像在 scholl 中在一张纸上一样。 Very simple.很简单。

Everthing then biols down to some lines of code.然后一切都归结为几行代码。

Please see:请参见:

#include <iostream>
#include <vector>

int main() {
    // Read length of binary number to create and validate input
    if (int numberOfDigits{}; (std::cin >> numberOfDigits and numberOfDigits > 0)) {

        // Here we will store the binary digits, so 0s or 1s
        std::vector<int> digits(numberOfDigits,0);

        // Som printing helper
        std::cout << '[';
        bool printComma{};

        // We need to print 2^n possible combinations
        for (int i = 0; i < (1 << numberOfDigits); ++i) {

            // Print comma, if need
            if (printComma) std::cout << ','; printComma = true;

            // Print all digits of the binary number
            for (const int d : digits) std::cout << d;
           
            // Calculate next binary number
           int carry = 0;
           for (int index=numberOfDigits -1; index >=0; --index)  {
                
                const int sum = digits[index] + ((index == (numberOfDigits - 1)?1:0)) + carry;
                carry = sum / 2;
                digits[index] = sum % 2;
            } 
        }
        std::cout << ']';
    }
}

If there should be questions, then I am happy to answer.如果有问题,我很乐意回答。

reserve does't increse vector size.保留不会增加向量大小。

Trying to compile your program with a C++ compiler will not work, because you include #include <bits/stdc++.h> which is a non tC++ standard compliant header.尝试使用 C++ 编译器编译您的程序将不起作用,因为您包含了#include <bits/stdc++.h> ,它是不符合 tC++ 标准的 header。

You should never include this file.你永远不应该包含这个文件。 Never.绝不。

So, you are using typical competitive programming stuff, but why include all C++ headers and not use them.因此,您使用的是典型的竞争性编程材料,但为什么要包含所有 C++ 标头而不使用它们。 This is a waste of time.这是浪费时间。

Then, you typedef the typical nonsens competitive programming abbreviations.然后,您键入定义典型的无意义的竞争性编程缩写。 2 of them, you do not use, so why define them?其中2个,你不使用,为什么要定义它们?

Do not do this any longer.不要再这样做了。 And in C++, please use the using statement.在 C++ 中,请使用using语句。

Then, although you want to be fast, you pass arr by value to your print function.然后,虽然你想快点,但你将arr按值传递给你的 print function。 This will copy the whole vector.这将复制整个向量。

You assign/compare a lot of int with unsigned int values.您分配/比较了很多 int 与 unsigned int 值。 This you should not do.这是你不应该做的。

Additionally: Use meaningful variable names and write comments.另外:使用有意义的变量名并写注释。 The more the better.越多越好。


Regarding the algorithm.关于算法。 I took a while for me to realize that you basically want to create binary numbers.我花了一段时间才意识到你基本上想要创建二进制数。 Nothing else.没有其他的。 Unfortunately you translated that in a very complicated way.不幸的是,您以非常复杂的方式翻译了它。

Normally, you just would count from 0 to n-1 and then show the data.通常,您只需从 0 数到 n-1,然后显示数据。 Thats all.就这样。 Becuase the numbers may be of arbitraty length, we will use manual addition of digits like in scholl on a peice of paper.因为数字可能是任意长度,我们将使用手动添加数字,就像在 scholl 中在一张纸上一样。 Very simple.很简单。

Everthing then biols down to some lines of code.然后一切都归结为几行代码。

Please see:请参见:

#include <iostream>
#include <vector>

int main() {
    // Read length of binary number to create and validate input
    if (int numberOfDigits{}; (std::cin >> numberOfDigits and numberOfDigits > 0)) {

        // Here we will store the binary digits, so 0s or 1s
        std::vector<int> digits(numberOfDigits,0);

        // Som printing helper
        std::cout << '[';
        bool printComma{};

        // We need to print 2^n possible combinations
        for (int i = 0; i < (1 << numberOfDigits); ++i) {

            // Print comma, if need
            if (printComma) std::cout << ','; printComma = true;

            // Print all digits of the binary number
            for (const int d : digits) std::cout << d;
           
            // Calculate next binary number
           int carry = 0;
           for (int index=numberOfDigits -1; index >=0; --index)  {
                
                const int sum = digits[index] + ((index == (numberOfDigits - 1)?1:0)) + carry;
                carry = sum / 2;
                digits[index] = sum % 2;
            } 
        }
        std::cout << ']';
    }
}

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM