【问题标题】:std::copy doesn't copy vector in C++std::copy 不会在 C++ 中复制向量
【发布时间】:2022-01-14 08:18:09
【问题描述】:

要查找仅包含 0 和 1 的所有固定长度序列,我使用以下代码:

#include <bits/stdc++.h>

typedef long long int lli;
typedef std::vector<lli> vec_lli;
typedef std::vector<std::string> vec_s;

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

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

int main(int argc, char const *argv[]) {
  int n;
  std::cin >> n;
  vec_s mb = get_variants(n);
  print_array(mb);
  return 0;
}

但向量temp 是空的,在第1 行和之后的复制之前。所以,我的程序的输出是 [0111, 1111]。我做错了什么?

【问题讨论】:

  • 您的代码带有所谓的“竞争”和“在线评判”网站的所有标志。此类网站不是任何类型的教学或学习资源,使用它们可能会直接损害您的学习过程,因为此类网站所教授的所有内容似乎都是非常糟糕的习惯,而且通常还会直接使用无效代码。投资some good books,上课,远离这些网站,直到你改掉坏习惯并用好习惯取而代之。
  • 您正在写信给temp.end()result.end()。这些是占位符元素的迭代器,attempting to write to them results in Undefined Behavior.
  • @DrewDormann,将其发布为答案,我会将其标记为解决方案
  • 您的代码似乎比仅仅尝试写入向量的.end() 迭代器更错误。

标签: c++ c++11 vector stl


【解决方案1】:

您正在写信给temp.end()result.end()。这些迭代器代表“一个结束”,因此写入这些迭代器是未定义的行为。

您似乎在寻找std::back_inserter。这将创建一个迭代器,该迭代器将在写入时将一个新元素插入到您的容器中。

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

虽然这回答了发布的问题,但您的代码中仍然存在其他导致未定义行为的错误。

【讨论】:

  • std::back_inserter 不是迭代器。 std::back_insert_iterator 是。 std::back_inserter 只是一个处理模板参数推导的便捷函数,如std::make_pair
  • @ArmenTsirunyan 谢谢!已编辑。
【解决方案2】:

比使用std::copy 更直接的方法是使用.insert()

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

【讨论】:

    【解决方案3】:

    *尝试使用 C++ 编译器编译程序是行不通的,因为您包含了 #include &lt;bits/stdc++.h&gt;,这是一个不符合 tC++ 标准的头文件。

    您永远不应包含此文件。从不。

    所以,您使用的是典型的竞争性编程材料,但为什么要包含所有 C++ 标头而不使用它们。这是浪费时间。

    然后,您键入定义典型的无意义竞争性编程缩写。其中2个,你不使用,为什么要定义它们?

    不要再这样做了。在 C++ 中,请使用 using 语句。

    然后,尽管您想快点,但您将 arr 按值传递给您的打印函数。这将复制整个向量。

    您分配/比较了很多 int 与 unsigned int 值。这是你不应该做的。

    另外:使用有意义的变量名并编写 cmets。越多越好。


    关于算法。我花了一段时间才意识到你基本上想要创建二进制数。没有其他的。不幸的是,您翻译的方式非常复杂。

    通常,您只需从 0 数到 2^n-1,然后显示数据。就这样。因为数字可能是任意长度,我们将使用手动添加数字,就像在 scholl 中在一张纸上一样。很简单。

    然后一切都归结为几行代码。

    请看:

    #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 << ']';
        }
    }
    

    【讨论】:

      猜你喜欢
      • 2021-08-25
      • 1970-01-01
      • 2016-04-03
      • 2011-07-12
      • 1970-01-01
      • 1970-01-01
      • 2015-01-05
      • 1970-01-01
      • 2013-08-21
      相关资源
      最近更新 更多