簡體   English   中英

帶有指針的 C++ 程序顯示異常行為

[英]C++ program with pointer shows unusual behaviour

所以我正在編寫一個代碼來實現一個有點類似於部分樹狀結構的數據結構。 這是代碼

#include<bits/stdc++.h>
#include"utils.h"

using namespace std;

template<std::size_t N>
struct node_x_t {
    static_assert(N <= 256, "N must be <= 256");
    int num_elements;
    char chars[N];
    node_x_t<256>* children[N];
};

node_x_t<256>* root;

node_x_t<256>* createNode(char c){
    node_x_t<1>* temp = new node_x_t<1>;
    temp->num_elements = 1;
    temp->chars[0] = c;
    temp->children[0] = NULL;
    return (node_x_t<256>*)temp;
}

void add(string key){
    node_x_t<256>* nav = root;
    node_x_t<256>* prev = root;
    int prevIdx=0;
    int size = key.size();
    for(int i=0;i<size;i++){
        int idx = -1;
        if(nav==NULL){
            nav = createNode(key[i]);
            if(i!=0){
                prev->children[prevIdx] = nav;
                prev = nav;
                prevIdx=0;
            }
            else{
                prev = nav;
                root = nav;
                prevIdx=0;
            }
            cout<<"NEW: "<<nav->chars[0]<<" ";
            nav = nav->children[0];
            continue;
        }

        int nodeSize = nav->num_elements;
        for(int j=0;j<nodeSize;j++){
            if(nav->chars[j] == key[i]){
                idx = j;
                break;
            }
        }

           
        if(idx!=-1){
            prev = nav;
            prevIdx = idx;
            nav = nav->children[idx];
            cout<<"HIT: "<<prev->chars[idx]<<" ";
        }
    }
    cout<<"\n";
}


void test(){
    root=createNode('0');
    add("a");
    add("ab");
    add("abc");
    add("abcd");
    add("abcde");
    add("abcdef");
    add("abcdefg");
    add("abcdefgh");
    add("abcdefghi");
    add("abcdefghij");
    add("abcdefghijk");
}

int main(){
    test();
}

chars[]數組存儲當前節點旁邊的字符, children[]數組有一個指向包含下一個字符的節點的指針

我添加了“NEW”和“HIT”語句來指示要添加的當前字符串的前綴是否已經在之前添加過(測試目的)。

這是輸出

NEW: a 
HIT: a NEW: b 
HIT: a HIT: b NEW: c 
HIT: a HIT: b HIT: c NEW: d 
HIT: a HIT: b HIT: c HIT: d NEW: e 
HIT: a HIT: b HIT: c HIT: d HIT: e NEW: f 
HIT: a HIT: b HIT: c HIT: d HIT: e HIT: f NEW: g 
HIT: a HIT: b HIT: c HIT: d HIT: e HIT: f HIT: g NEW: h 
HIT: a HIT: b HIT: c HIT: d HIT: e HIT: f HIT: g HIT: h NEW: i 
HIT: a HIT: b HIT: c HIT: d HIT: e HIT: f HIT: g HIT: h HIT: i NEW: j 
HIT: a HIT: b NEW: c NEW: d NEW: e NEW: f NEW: g NEW: h NEW: i NEW: j NEW: k 

基本上在添加第 10 個字符串之后,似乎大多數節點都被自動刪除並重新創建。 但是,理想情況下,代碼必須也為字符串“abcdefghijk”提供了HIT 。您能在代碼中找到錯誤嗎?

你能找到代碼中的錯誤嗎?

您代碼中的錯誤是假設模板類型可以使用修改后的模板參數相互轉換。 這種假設顯然是錯誤的。 node_x_t<1>是一種node_x_t<256>不同的類型,並且使用指向另一種類型的指針訪問一個對象與通過int指針訪問double一樣錯誤。 總體而言,如果您轉換指針或使用reinterpret_cast則可能需要重新考慮您的方法。

在這種情況下, node_x_t可以動態分配它存儲的元素數量,如果意圖是元素數量在運行時發生變化。 例如,一些東西:

struct node_x_t {
    node_x_t(std::size_t N) : num_elements(N), chars(N), children(N)
    {
        assert(N <= 256); // TODO: throw exception
    }
    node_x_t() : node_x_t(0) {}
    node_x_t(char c) : node_x_t(1) {
         chars.at(0) = c;
    }
    int num_elements;
    // at least use std::array
    std::vector<char> chars;
    std::vector<std::shared_ptr<node_x_t>> children;
};

或者您可以堅持對元素數量的恆定編譯時限制,然后您只需要使用一種類型。 那么您的函數也應該始終使用該模板類型。 真的,這些函數看起來應該是成員函數。

template<std::size_t N>
struct node_x_t {
    static_assert(N <= 256, "N must be <= 256");
    int num_elements;
    std::array<char, N> chars;
    std::array<std::shared_ptr<node_x_t>, N> children;

    static std::shared_ptr<node_x_t<N>> createNode(char c);
    void add(std::string key) {
       // maybe shared_ptr is too much - no idea, I do not understand the algorithm
       node_x_t<N>* nav = *this;
       node_x_t<N>* nav = *this; // use N everywhere!
       // blabla
    }
};

暫無
暫無

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

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