R G B 元素数组交换
R G B element array swap
我正在尝试创建这个c ++程序来执行下面的描述。 我很确定问题出在递归中,但不确定如何解决它。 我猜它只是不断迭代到无穷大并崩溃。 我什至没有得到输出。 我想我可以比较以前的和当前的指针,并根据词典编纂执行 3 件式临时交换。 我会使用指针遍历数组并在每次交换后递减它,然后以该 ptr 作为参数递归调用。 没用,我在这里,请帮我:)。 如果有一个更简单的解决方案也可以工作,但更愿意了解我用这段代码出错的地方。
#include <string>
#include <iostream>
using namespace std;
// Given an array of strictly the characters 'R', 'G', and
// 'B', segregate the values of the array so that all the
// Rs come first, the Gs come second, and the Bs come last.
// You can only swap elements of the array.
char* RGBorder(char* c_a)
{
size_t sz = sizeof(c_a)/sizeof(*c_a);
char* ptr_ca = c_a;
char* prv_ptr = ptr_ca;
ptr_ca++;
char temp;
while(*ptr_ca)
{
switch(*ptr_ca)
{
case 'R' :
if( *prv_ptr < *ptr_ca ) {
temp = *prv_ptr; *prv_ptr = *ptr_ca; *ptr_ca = temp;
} else if( *prv_ptr == *ptr_ca ) {
continue;
} else { ptr_ca--; RGBorder(ptr_ca); }
case 'G' :
if( *prv_ptr < *ptr_ca ) {
temp = *prv_ptr; *prv_ptr = *ptr_ca; *ptr_ca = temp;
} else if( *prv_ptr == *ptr_ca ) {
continue;
} else { ptr_ca--; RGBorder(ptr_ca); }
default:
ptr_ca++;
continue;
}
ptr_ca++;
cout << *ptr_ca;
}
return c_a;
}
int main()
{
char ca[] = {'G', 'B', 'R', 'R', 'B', 'R', 'G'};
char *oca =RGBorder(ca);
char *pca = oca;
while(*pca)
{
cout << *pca << endl;
pca++;
}
}
您的代码存在许多问题。
1) 使用字符指针调用函数RGBorder
,然后尝试使用以下方法获取字符数:
size_t sz = sizeof(c_a)/sizeof(*c_a);
这不会为您提供字符数。 相反,这只会让你
sizeof(char *) / sizeof(char)
通常是 4 或 8。 使用 char 数组调用函数的唯一方法是提供一个以 null 结尾的数组(因此您可以使用strlen
),或者您必须将数组中的字符数作为单独的参数传递:
char *RGBorder(char *c_a, int size)
2)我没有浏览您的代码,但是有更简单的方法可以在数组中进行3向分区。 一种流行的算法是基于荷兰国旗问题的算法。
由于您希望数组按RGB
顺序排列,因此您知道G
序列将始终位于序列的中间(某处),R
位于序列的左侧,B
始终位于序列的右侧。
因此,目标是简单地将R
交换到中间的左侧,B
交换到中间的右侧。 所以基本上你想要一个循环,在需要时增量更改"中间",同时在检测到R和B时交换到适当的位置。
以下代码对此进行了说明:
#include <algorithm>
char *RGBorder(char *c_a, int num)
{
int middle = 0; // assume we only want the middle element
int low = 0; // before the G's
int high = num - 1; // after the G's
while (middle <= high)
{
if ( c_a[middle] == 'R' ) // if we see an 'R' in the middle, it needs to go before the middle
{
std::swap(c_a[middle], c_a[low]); // swap it to a place before middle
++middle; // middle has creeped up one spot
++low; // so has the point where we will swap when we do this again
}
else
if (c_a[middle] == 'B') // if we see a 'B' as the middle element, it needs to go after the middle
{
std::swap(c_a[middle], c_a[high]); // place it as far back as you can
--high; // decrease the back position for next swap that comes here
}
else
++middle; // it is a 'G', do nothing
}
return c_a;
}
现场示例
这是另一个使用 std::p artition 的解决方案。
#include <algorithm>
#include <iostream>
char *RGBorder(char *c_a, int num)
{
auto iter = std::partition(c_a, c_a + num, [](char ch) {return ch == 'R';});
std::partition(iter, c_a + num, [](char ch) {return ch == 'G';});
return c_a;
}
现场示例
基本上,对std::partition
的第一次调用将R
放在数组的前面。由于std::partition
返回一个迭代器(在本例中为char *
)到分区发生的末尾,因此我们将其用作第二次调用std::partition
的起始位置,在那里我们对G
值进行分区。
请注意,std::partition
也通过交换来实现其目标。
给定此解决方案,我们可以通过使用循环将其推广到 n 路分区。 假设我们想按 RGBA 顺序放置东西(4 个值而不是 3 个)。
#include <algorithm>
#include <iostream>
#include <cstring>
char *RGBorder(char *c_a, int num, char *order, int num2)
{
auto iter = c_a;
for (int i = 0; i < num2 - 1; ++i)
iter = std::partition(iter, c_a + num, [&](char ch) {return ch == order[i];});
return c_a;
}
int main()
{
char ca[] = "AGBRRBARGGARRBGAGRARAA";
std::cout << RGBorder(ca, strlen(ca), "RGBA", 4);
}
输出:
RRRRRRRGGGGGBBBAAAAAAA
很抱歉说得直白了,但那段代码一团糟。我不是说错误,这些对于初学者来说是可以原谅的。我的意思是格式。一行中的多个语句使得阅读和调试代码变得非常困难。没有直接内在含义的短变量名称使得很难理解代码应该做什么。using namespace std;
也是非常糟糕的做法,但我可以想象你是由任何教授该课程的人教你这样做的。
第一个问题
你的case
不会break
,因此你执行R
的所有情况,以及G
的G
和default
。此外,您的代码永远不会到达循环的最后 2 行,正如您之前在每种情况下continue
的那样。
第二个问题
你有一个无限循环。在这两种case
中,您都有两种情况,最终会陷入无限循环:
-
在
else if( *prv_ptr == *ptr_ca )
分支中,您只需continue;
而无需更改指针。 -
在
else
分支中,您执行ptr_ca--;
,但在default
中,您再次呼叫ptr_ca++;
。
(请注意,即使使用break
,您仍然会在循环结束时调用ptr_ca++;
。
在这两种情况下,指针都不会改变,所以一旦你最终进入任何这些条件,你的循环将永远不会退出。
可能的第三个问题
我只能猜测,因为从名称上看不出来,但似乎prv_ptr
应该持有循环中的最后一个指针?如果是这样,那么您永远不更新该指针似乎是错误的。无论哪种方式,正确的变量名称都会更清楚地表明此指针的确切用途。(附带说明一下,一致使用const
可以帮助识别此类问题。如果你有一个变量没有const
,但从未更新,你要么忘记添加const
,要么忘记更新它。
如何修复
设置代码格式:
- 不要使用
using namespace std;
. - 每行一个语句。
- 为您的变量提供正确的名称,以便轻松识别什么是什么。(这不是1993年,真的,我宁愿有
thisIsThePointerHoldingTheCharacterThatDoesTheThing
也不愿ptr_xy
。
修复上述问题(添加break
s,确保您的循环实际退出)。
然后调试代码。使用调试器。当它运行时。使用断点并逐行单步执行,在代码执行时检查指针的值。花哨的东西。
祝你好运!
只需计算"R","G"和"B"字母的数量并从头开始填充数组。 更容易,没有递归。
- 通过交换元素使数组相同
- 如何在数组中交换最小和最大的位置?
- 交换函数不是在 C++ 中交换 2D 数组的元素
- 如何交换数组中的元素?
- C++:交换矩阵的行:使用单维数组
- 使用指针 c++ 交换结构数组中的元素
- 使用指针交换数组的内容
- C++数组交换并查找最小元素
- 使用指针交换而不引用数组C++
- 指针数组交换无需直接访问数组
- 交换数组
- 如何在C++中交换对象数组的 2 个不同对象
- 如何将元素的索引从2D数组存储到1D数组中,然后交换这些值
- 在C++中使用 2D 数组进行交换
- 代码是否交换数组的两个数字
- std::在 std::shared_ptr 之间交换,<A>其中 A 具有动态数组
- 在2D数组中交换行的最佳方法
- 如何在 2D 数组 c++ 中交换元素
- 交换二维数组中的两个值
- 如何使用数组交换对象,c++.我想改变