簡體   English   中英

RGB元素陣列交換

[英]R G B element array swap

我正在嘗試創建此c ++程序以執行以下描述。 我非常確定問題在於遞歸,但不確定如何解決。 我猜想它只會不斷迭代到無窮大並崩潰。 我什至沒有輸出。 我以為我可以比較以前的指針和當前的指針,並根據詞典順序執行一個三段式的臨時交換。 我將使用一個指針來遍歷數組,並在每次交換后將其遞減,然后以該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++;
    }
}

坦白地說,很抱歉,但是該代碼是一團糟。 我並不是說那些錯誤,對於初學者來說,這些錯誤是可以原諒的。 我的意思是格式化。 一行中的多個語句使讀取和調試代碼變得異常困難。 簡短的變量名沒有立即的內在含義,這使得很難理解代碼應該做什么。 using namespace std; 這也是非常不好的做法,但是我可以想象,任何提供該課程的人都會教你做這件事。

第一個問題

你的case就做不break ,所以你執行所有情況下, RGdefaultG 同樣,您的代碼將永遠不會到達循環的最后兩行,因為您在每種情況下都將continue

第二個問題

你有無盡的循環。 在這兩種case您都有兩種情況會陷入無限循環:

  1. else if( *prv_ptr == *ptr_ca )分支中,您只需continue; 無需更改指針。

  2. else分支中,執行ptr_ca--; ,但是default您調用ptr_ca++; 再次。
    (請注意,即使使用break您仍會在循環結束時調用ptr_ca++;

在這兩種情況下,指針都不會改變,因此一旦您遇到這些情況中的任何一個,您的循環就永遠不會退出。

可能的第三個問題

我只能猜測,因為從名稱prv_ptr不出來,但是似乎prv_ptr應該保存循環中最后一個指針是什么? 如果是這樣,永遠不更新該指針似乎是錯誤的。 無論哪種方式,適當的變量名都會使該指針的目的更加清楚。 (另一方面,恆定使用const可以幫助識別此類問題。如果您擁有的變量不是const ,但從未更新,則要么忘記添加const要么忘記對其進行更新。)

怎么修

格式化代碼:

  • 不要using namespace std;
  • 每行一個聲明。
  • 給您的變量起個適當的名字,這樣很容易識別出什么是什么。 (這不是1993年,真的,我寧願有一個thisIsThePointerHoldingTheCharacterThatDoesTheThing不是ptr_xy 。)

解決上述問題(添加break ,確保您的循環實際退出)。

然后調試您的代碼。 用調試器。 運行時。 使用斷點並逐行瀏覽,在代碼執行時檢查指針的值。 花哨的東西。

祝好運!

您的代碼有很多問題。

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)我沒有遍歷您的代碼,但是有更簡單的方法可以在數組中進行三向分區。 一種流行的算法是基於荷蘭國旗問題的算法。

由於您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 :: partition的解決方案。

#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

只需計算“ R”,“ G”和“ B”字母的數量,然后從頭開始填寫數組即可。 容易得多,沒有遞歸。

暫無
暫無

聲明:本站的技術帖子網頁,遵循CC BY-SA 4.0協議,如果您需要轉載,請注明本站網址或者原文地址。任何問題請咨詢:yoyou2525@163.com.

 
粵ICP備18138465號  © 2020-2024 STACKOOM.COM