【问题标题】:Circular shift a dynamic c array by n elements将动态 c 数组循环移动 n 个元素
【发布时间】:2012-08-25 03:38:51
【问题描述】:

我有一个设置长度的队列实现为动态 c 数组,如下所示:

typedef struct {
    float* queue;
    int size;
    int pointer;
} QueueStruct;

void createQueue(QueueStruct* queueInstance, int size){
    queueInstance->queue = malloc(sizeof(float)*size);
    queueInstance->size = size;
    queueInstance->pointer = 0;
}

void addElementToQueue(QueueStruct* queueInstance,float element){
    queueInstance->queue[pointer] = element;
    if (queueInstance->pointer == queueInstance.size - 1){
        queueInstance->pointer = 0;
    } else {
        ++queueInstance->pointer;
    }
}

void freeQueue(QueueStruct* queueInstance){
    free(queueInstance->queue);
}

我想实现这个功能:

float* returnQueue(QueueStruct queueInstance){
    //I want this function to malloc a new float* and then put the queue in it in the
    // correct order, from start to finish, as pointed too by the pointer.  
    //Im not sure how to do this.
}

任何帮助将不胜感激。

编辑:更正了一个愚蠢的编程错误 - 这是我程序中实际内容的简化版本。

【问题讨论】:

  • 对不起,但是:queueInstance = QueueStruct;这样可行?你不应该分配内存或其他东西吗?当您尝试将类型分配给变量指针时,编译器不会对您大喊大叫吗?
  • 根据我的编辑,这不是我的实际代码。我在无法访问网络的 hackintosh 上编程...所以我无法复制和粘贴我的实际代码。
  • 我不确定我是否遵循...您是说您想要返回的队列的精确副本,还是队列的子集?您的意思是将“QueueStruct”或“QueueStruct*”传递给 returnQueue 函数吗?
  • @Mike 我很确定它应该是一个指针,但感谢您指出。老实说,我错过了它。按照我的理解,他想要他的动态数组的有序数组表示。含义:从指针到终点,从锚点到指针。
  • @ATaylor 正确。谢谢你的措辞更好。

标签: c arrays dynamic queue shift


【解决方案1】:

我认为你也应该为你的结构分配内存。 您已经创建了结构指针,但忘记为该结构分配内存

使用 QueueStruct queuestruct= malloc(sizeof(Queuestruct))

然后,当您将其传递给上述任何函数时,您就可以轻松分配 队列指针的内存,您可以在其中存储队列数组的元素

【讨论】:

  • 按照我的理解,结构体本身是预先分配好的。或者你想每次都重新分配内存,你想添加一个成员?我假设,OP 在某处有一个“InitStruct”函数。
  • 我会正常声明(QueueStruct queueInstance)然后通过地址createQueue(&queueInstance,10);
【解决方案2】:

这个实现是不够的。 pointer 变量为我们提供了队列尾部的位置,但什么指向它的头部?

【讨论】:

  • float * 变量是锚点,而不是尾巴。 “指针”是一个数组计数器。
  • 所以,如果我正好添加queueInstance->size + i 元素,它将与i 元素一起排队,对吧?我怎样才能从这个队列中取出一个元素? “队列”是一个 FIFO 缓冲区,而不是简单的数据累加器。
  • Err..no.大小给了我们:这个数组中元素的数量。这背后的逻辑更像是 queueInstance->queue + x 会给你数组的第 x 个元素,其中 x 不能高于 queueInstance->size。如果添加超出大小的元素...超出分配的内存...就会发生坏事。
  • 数据重叠也不好。在这种情况下,函数addElementToQueue 必须产生异常。
  • addElementToQueue 在哪里导致重叠?它不调用 malloc 或任何东西。它所做的只是用一个新的替换“指针(一个整数,而不是实际的指针)”的值......这就像调用 int i = 42;
【解决方案3】:

让我们看看我是否正确。

float* returnQueue(QueueStruct *queueInstance){
    int j = 0;
    float *ret = malloc(sizeof(float)*queueInstance->size);  //Allocates the memory you want.
    //Copies the elements from pointer to End into the new buffer (assumes, that the array has been filled at least once, add a marker to make sure)
    if(queueInstance->FilledOnce) { //Marker variable, explanation as above.
        for(int i = queueInstance->pointer; i < queueInstance->size; ++i, ++j)
            ret[j] = queueInstance->queue[i];
    }
    //Copies the newest elements (from beginning to pointer) into the buffer.
    for(int i = 0; i < queueInstance->pointer; ++i, ++j)
        ret[j] = queueInstance->queue[i];
    return ret; //Returns the code in question.
}

要使此代码正常工作,您必须将“FilledOnce”添加到您的结构中,并按如下方式修改您的“添加”代码:

void addElementToQueue(QueueStruct* queueInstance, float element){
    queueInstance->queue[queueInstance->pointer] = element;
    if (queueInstance->pointer == queueInstance.size - 1){
        queueInstance->pointer = 0;
        queueInstance->FilledOnce = 1;
    } else {
        ++queueInstance->pointer;
    }
}

我还建议您在完成后重新设置变量。

void freeQueue(QueueStruct* queueInstance){
    free(queueInstance->queue);  //Frees the queue
    queueInstance->queue = NULL; //Nulls the reference
    queueInstance->FilledOnce = 0;
    queueInstance->pointer = 0;
    queueInstance->size = 0;
}

这样,如果你重用结构,你就不会遇到试图访问未分配内存的问题。请务必检查这些变量。

我希望这会有所帮助。

【讨论】:

    猜你喜欢
    • 1970-01-01
    • 1970-01-01
    • 2019-01-07
    • 1970-01-01
    • 1970-01-01
    • 2017-04-21
    • 2021-12-31
    • 2017-02-28
    • 1970-01-01
    相关资源
    最近更新 更多