我正在为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;
}
}
任何帮助将不胜感激。提前谢谢。
答案 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中访问缓冲区(读或写)时,此代码将无法正常工作。)