C中队列的字符数组

时间:2016-03-05 08:45:28

标签: c arrays queue avr

我正在为AVR编写一段代码。我想构建一个可以推送和弹出的队列,这个队列是一个字符数组(字符串)。所以当我推'a'时: ['b', 'c', 'd', 'e', 'f']
变为:
['a','b', 'c', 'd', 'e', 'f']
当我弹出时,f出来了。我编写了这段代码,但它只将1个字符串推送到队列中,就好像它会删除整个队列一样。这是我的队列代码:

char queue[50] = "";
char* queue_tail = &queue[0];
char* queue_head = &queue[0];

void queue_push(char l_item)
{
    if(queue_head != &queue[strlen(queue) - 1]) //if queue is not full, do the job
    {
        //Push all elements one step further
        char* traveler = queue_head;
        for(; traveler != queue_tail; --traveler)
        {
            *(traveler+1) = *traveler;
            *traveler = '';
        }
        ++queue_head;
        *queue_tail = l_item;
    }
}

char queue_pop()
{
    char temp = *queue_head;
    *queue_head = '';
    --queue_head;
    return temp;
}

这是我的主要功能:

#include <mega32.h>
#include <alcd.h>
#include <delay.h>
#include <string.h>

void main(void)
{

const char text[] = "Hello world!";
int col_counter = 0;
char* p_head = '';

lcd_init(32);
p_head = &text[12];

while(1)
{
    lcd_clear();

    if(col_counter + strlen(text) > 32)
    {
        queue_push(*p_head);
        --p_head;
    }

    lcd_gotoxy(col_counter, 0);
    lcd_puts(text);
    lcd_gotoxy(0,0);
    lcd_puts(queue);
    delay_ms(200);
    ++col_counter;

}
}

任何帮助将不胜感激。提前谢谢。

2 个答案:

答案 0 :(得分:1)

我将queue_head的含义从最后一个元素更改为超过队列中最后一个元素的含义,并调整了代码。

以下是更正后的代码(此代码中的main()是普通PC的测试代码):

#include <stdio.h>

char queue[50] = "";
char* queue_tail = &queue[0];
char* queue_head = &queue[0];

void queue_push(char l_item)
{
    if(queue_head != queue + sizeof(queue)/sizeof(*queue)) //if queue is not full, do the job
    {
        //Push all elements one step further
        char* traveler = queue_head;
        for(; traveler != queue_tail; --traveler)
        {
            *traveler = *(traveler - 1);
        }
        ++queue_head;
        *queue_tail = l_item;
    }
}

char queue_pop(void)
{
    char temp;
    if (queue_head == queue_tail) return '\0'; // the queue is empty
    --queue_head;
    temp = *queue_head;
    *queue_head = '\0';
    return temp;
}

int main(void) {
    queue_push(100);
    queue_push(110);
    printf("%d\n",queue_pop());
    printf("%d\n",queue_pop());
    return 0;
}

答案 1 :(得分:0)

建议循环缓冲区实现(无需来回复制缓冲区内容):

char queue[50] = "";
char* queue_tail = &queue[0];
char* queue_head = &queue[0];

#define END_OF_QUEUE (&queue[sizeof(queue)/sizeof(*queue)]) // The first element _after_ the buffer.

#define QUEUE_NOT_FULL   0
#define QUEUE_IS_FULL    1

uint8_t queueState;

void queue_push(const char l_item)
{
    // 0) Addition is always modulus buffer size (50)
    // 1) head points to the next empty location which can store an incoming byte
    // 2) tail points to the next location from where a byte may be read
    // 3) Queue is empty iff tail == head && queueState == QUEUE_NOT_FULL
    // 4) Queue is full iff tail == head && queueState == QUEUE_IS_FULL

    if ( queueState == QUEUE_NOT_FULL ) {

        // Store item to the current head:
        *queue_head = l_item;

        // Advance head by one:
        queue_head++;

        if ( queue_head == END_OF_QUEUE ) {
            // head passed the end of buffer -> continue at the start:
            queue_head = &queue[0];
        }

        // If head meets tail after appending the new element, the buffer is now full.
        if ( queue_head == queue_tail ) {
            queueState = QUEUE_IS_FULL;
        }

    } else {
        // Buffer overflow! - Options: Ignore new data, overwrite old data, wait until not full, signal an error somehow.
    }

}

char queue_pop()
{

    if ( (queue_tail == queue_head) && (queueState == QUEUE_NOT_FULL) ) {
        // Queue is empty. "Buffer underflow." - Options: Return dummy value, wait until data available, signal an error somehow.
        return '\0';
    } else {
        const char result = *queue_tail;
        queue_tail++;

        if ( queue_tail == END_OF_QUEUE ) {
            // tail passed the end of buffer -> continue at the start:
            queue_tail = &queue[0];        
        }

        // We just removed an element from the queue, so the queue cannot be full now even if it was full a moment ago.
        queueState = QUEUE_NOT_FULL;

        return result;
    }

}

(注意,如果没有进一步的同步元素,当并发运行时,即从ISR中访问缓冲区(读或写)时,此代码将无法正常工作。)