如何编写一个函数来修改列表,使所有奇数元素都被复制,所有偶数元素都被删除



我正试图编写一个函数,通过删除偶数和复制奇数来修改数组列表。我的代码可以很好地去除偶数。然而,它只复制了一些奇数。

例如,我的清单包括:12 11 13 14 15 13 10L.duplicateORremove((之后的列表L应包含:11 11 13 13 15 15 13 13

但这就是我得到的:11 13 13 15 13 13

我想帮我弄清楚为什么我会得到这个结果。

这是我迄今为止的代码:

template <class Type>
void arrayListType <Type>::duplicateORremove()
{
for(int i=0; i<length; i++)
{
if(list[i]%2==0)
{
for (int j = i; j < length - 1; j++)
list[j] = list[j + 1];
length--;
}
else
{
for (int j = length; j > i; j--)
list[j] = list[j - 1]; 
list[i+1] = list[i];
i++;
length++;
}
}
}

这就是我的类定义和main的样子:

template < class Type >
class arrayListType {
public:
arrayListType(int size = 100);
~arrayListType();
void insertEnd(const Type & insertItem);
void print() const;
void duplicateORremove();
protected:
Type * list; //array to hold the list elements
int length; //stores length of list
int maxSize; //stores maximum size of the list
};
template < class Type >
arrayListType < Type > ::arrayListType(int size) {
if (size < 0) {
cerr << "The array size must be positive. Creating " <<
"an array of size 100. " << endl;
maxSize = 100;
} else
maxSize = size;
length = 0;
list = new Type[maxSize];
assert(list != NULL);
}
template < class Type >
arrayListType < Type > ::~arrayListType() {
delete[] list;
}
template < class Type >
void arrayListType < Type > ::insertEnd(const Type & insertItem) {
if (length >= maxSize)
cerr<<"Cannot insert in a full list" << endl;
else {
list[length] = insertItem; 
length++;
}
}
template < class Type >
void arrayListType < Type > ::print() const {
for (int i = 0; i < length; i++)
cout << list[i] << " ";
cout << endl;
}
int main()
{
arrayListType <int> L;
L.insertEnd(12);
L.insertEnd(11);
L.insertEnd(13);
L.insertEnd(14);
L.insertEnd(15);
L.insertEnd(13);
L.insertEnd(10);
cout << "List L before L.duplicateORremove() contains:" << endl;
L.print();
L.duplicateORremove();
cout << "List L after L.duplicateORremove() contains:" << endl;
L.print();
#include <iostream>
using namespace std;
void duplicateORremove(int list[], int length) {
for(int i=0; i<length; i++)
{
if(list[i]%2==0)
{
for (int j = i; j < length - 1; j++)
list[j] = list[j + 1];
length--;
i-=1;
}
else
{
for (int j = length; j > i; j--)
list[j] = list[j - 1]; 
list[i+1] = list[i];
i++;
length++;
}
}
for (int i=0; i<length; i++) {
cout << list[i];
cout << " ";
}
}
int main()
{
int arrlist[] = {12, 11, 13, 14, 15, 13, 10};
duplicateORremove(arrlist, 7);
return 0;
}

当找到偶数时,您没有将"i"值重置为从以前的状态遍历。因为奇数代替了偶数,所以在循环时会跳过,因此您最终会得到一个结果,该结果中缺少一些值。丢失值的计数将等于输入中偶数的计数。

只要添加重置条件,它就会起作用。

运行上述代码的链接:在线cpp编译器

这里有一个使用Range-v3库的解决方案。

  • 您可以对原始范围的视图进行操作
  • 拆下均匀的滤芯
  • 复制剩余列表中的每个元素(奇数元素(
  • 然后将视图转换回矢量并返回

【演示】

#include <fmt/ranges.h>
#include <range/v3/all.hpp>
template <typename Range>
auto duplicate_or_remove(Range&& r) {
using namespace ranges::v3;
auto even = [](int i) { return 0 == i % 2; };

return r
| views::remove_if(even)
| views::for_each([](auto e){ return yield_from(views::repeat_n(e, 2)); })
| to_vector;
}
int main() {
std::vector<int> v{12, 11, 13, 14, 15, 13, 10};
fmt::print("{}", duplicate_or_remove(v));
}
// Outputs:
//
//   [11, 11, 13, 13, 15, 15, 13, 13]

回到您的代码,注意您不能简单地处理您的输入列表。如果列表中只包含奇数,会发生什么?对于第一个元素,您将在为列表保留的内存之外进行写入。相反,如果你需要坚持使用数组,你可以做的是:

  • 计算输入列表中的奇数元素
  • 创建一个新数组,其大小是输入列表中奇数元素数量的两倍
  • 遍历输入列表,对于每个奇数元素,将其添加到新创建的数组中两次
  • 返回一个由新数组及其大小组成的对
  • 下面的代码还使用了一个很好的技巧来避免在传递的是数组而不是指针的情况下将数组的长度传递给函数

【演示】

#include <iostream>  // cout
#include <utility>  // pair
auto is_odd = [](int i){ return (i % 2) == 1; };
template <size_t length>
size_t count_odd_elements(int (&list)[length]) {
size_t ret{};
for (size_t i{0}; i < length; ++i) {
if (is_odd(list[i])) {
ret++;
}
}
return ret;
}
template <size_t length>
auto duplicate_or_remove(int (&list)[length]) {
size_t odd_elements{ count_odd_elements(list) };
size_t ret_size{odd_elements * 2};
int* ret = new int[ret_size];
size_t head{};
for (size_t i{0}; i < length; ++i) {
int n{ list[i] };
if (is_odd(n)) {
ret[head++] = n;
ret[head++] = n;
}
}
return std::pair<int*, size_t>{ret, ret_size};
}
void print_list(int list[], size_t length) {
std::cout << "[";
for (size_t i{0}; i < length; ++i) {
std::cout << ((i == 0) ? "" : ", ") << list[i];
}
std::cout << "]";
}
int main() {
int arrlist[] = {12, 11, 13, 14, 15, 13, 10};
auto [result, result_size] = duplicate_or_remove(arrlist);
print_list(result, result_size);
delete[] result;
}
// Outputs:
//
//   [11, 11, 13, 13, 15, 15, 13, 13]

同样,使用std::vector而不是数组可以简化很多事情:

【演示】

#include <fmt/ranges.h>
#include <iostream>  // cout
#include <vector>
auto is_odd = [](int i){ return (i % 2) == 1; };
auto duplicate_or_remove(const std::vector<int>& list) {
std::vector<int> ret{};
for (auto i : list) {
if (is_odd(i)) {
ret.push_back(i);
ret.push_back(i);
}
}
return ret;
}
int main() {
std::vector<int> v{12, 11, 13, 14, 15, 13, 10};
auto result{ duplicate_or_remove(v) };
fmt::print("{}", result);
}

最新更新