Allegro.cc - Online Community

Allegro.cc Forums » Programming Questions » FIFO data structure

This thread is locked; no one can reply to it. rss feed Print
FIFO data structure
ngiacomelli
Member #5,114
October 2004

I believe that FIFO is the data structure that I am after in my game. Basically when text needs to be displayed, I want it added to list (a maximum of five messages may be shown at once). New messages are added to the bottom of the list and have a lifetime variable that slowly ticks upwards. Once a message has been displayed for X amount of seconds, it perishes. In-game the messages would be rendered in order of oldest to newest:

Old message
New message

Which would mean that, once Old message perishes, the New message will move up and take its place.

Now, does anyone have any friendly C examples of a nice simple FIFO structure?

Onewing
Member #6,152
August 2005
avatar

FIFO is just First In First Out. You could do it easily with a linked list, always adding to the beginning of the list and removing from the beginning of the list.

A small C-like example would be:

[EDIT] - OOops got my FIFO and FILO mixed...editing post...
[EDIT 2] - Actually, even witht the code for a FILO below, you should be able to figure out how to change it to a FIFO. The only function that needs changing would be the remove() function (since it removes from the end of the list instead of the beginning).

1typedef struct list
2{
3 char *cMessage;
4 LIST *next;
5} LIST;
6 
7LIST *add(LIST *lList, char *message)
8{
9 LIST *lTemp = (LIST *) malloc(sizeof(LIST));
10 strcpy(lTemp->cMessage, message);
11 lTemp->next = lList;
12 
13 return lTemp;
14}
15 
16LIST *remove(LIST *lList)
17{
18 LIST *lTemp = lList->next;
19 free(lList);
20 return lTemp;
21}
22 
23int main()
24{
25 LIST *myList = NULL;
26 myList = add(myList, "Hello");
27 myList = add(myList, "World");
28 myList = remove(myList);
29 return 0;
30}

myList would then only contain the message "Hello".

------------
Solo-Games.org | My Tech Blog: The Digital Helm

BAF
Member #2,981
December 2002
avatar

No... he wants FIFO. The older messages (first ones in) will expire before the new ones (last ones in), so the first ones in go out first.

Onewing
Member #6,152
August 2005
avatar

I noticed that after I wrote my post and tried to stick a quick edit in saying I was changing the post. Guess it wasn't quick enough. :-/

------------
Solo-Games.org | My Tech Blog: The Digital Helm

ReyBrujo
Moderator
January 2001
avatar

I think it is something similar to this:

1typedef struct node_st {
2 int data;
3 struct node_st *next;
4} node_t;
5 
6node_t *head;
7node_t *tail;
8 
9void push(node_t *node) {
10 if (head == NULL) {
11 head = node;
12 tail = node;
13 }
14 else {
15 tail->next = node;
16 tail = node;
17 }
18}
19 
20node_t *pop() {
21 node_t *node;
22 
23 node = head;
24 if (head != NULL)
25 head = head->next;
26 
27 if (head == NULL)
28 tail = NULL;
29 
30 return (node);
31}

(Edited: Fixed pop, was doing a pile instead of a queue. Also removed the previous link as it is not a pile and cleared the tail if the last element is popped from the queue).

--
RB
光子「あたしただ…奪う側に回ろうと思っただけよ」
Mitsuko's last words, Battle Royale

ngiacomelli
Member #5,114
October 2004

Okay, as far as the push and pop commands are concerned: I'm slightly confused as to how the data is actually taken into account?

As for the other example of remove... I'm not very familiar with pointers... but I'm assuming I would have to adjust it to loop through lList until lList->next == NULL?

Something like:

LIST *remove(LIST *lList)
{
     LIST *lTemp = lList->next;

     for(;;) {
        lTemp = lTemp->next;
        if( lTemp->next == NULL ) break;
     }

     free(lList);
     return lTemp;
}

ReyBrujo
Moderator
January 2001
avatar

In a queue and a pile, data is never taken into account. It doesn't matter what the node is holding, but when it was inserted into the list. In a [ordered] list, the data is used to sort the nodes as they are inserted into the list, but you are not doing that.

The problem with your remove is having to iteract until finding the last one. That is why you should keep a pointer to the tail. However, if you are going to remove the last one (which I guess is the last one to be inserted) you are using a LIFO (last in, first out), which is a pile, not a queue.

--
RB
光子「あたしただ…奪う側に回ろうと思っただけよ」
Mitsuko's last words, Battle Royale

ngiacomelli
Member #5,114
October 2004

If data is not taken into account (I see what you are saying)... then why have you included a data integer in the node_st struct?

I've explained my situation (and what I'm looking to achieve)... but now I'm even more confused as to which data structure I actually need!

Carrus85
Member #2,633
August 2002
avatar

Just as a side note, the term used for a LIFO data structure is typically stack, not pile (at least in english).;)

ReyBrujo
Moderator
January 2001
avatar

The data is there just to let you know there is some data in the node. In other words, instead of 'int data' put all the information you need, like text, length, health point, etc, or a struct with your data. The important thing is that the node encapsulates your data, being it a simple integer or a full class.

Oh, stack... I always say pile instead of stack :P

--
RB
光子「あたしただ…奪う側に回ろうと思っただけよ」
Mitsuko's last words, Battle Royale

Goalie Ca
Member #2,579
July 2002
avatar

Quote:

Now, does anyone have any friendly C examples of a nice simple FIFO structure?

Google search for queue structure. If you are coding in c++ there is one in STL and probably one in BOOST as well.

-------------
Bah weep granah weep nini bong!

ngiacomelli
Member #5,114
October 2004

Here's my attempt using some Queue structure code I found via Google:

Most of it works well (messages are added and can be displayed). Except, after the first message dies (see SortQueue), garbage is displayed for that specific string and then the rest functions normally for a few more messages before crashing. I'm guess this is down to me breaking the link between the list elements, but I'm not sure how I should really go about it?

1void SortQueue(listelement * listpointer) {
2
3 if (listpointer == NULL) {
4 } else {
5 while (listpointer != NULL) {
6
7 listpointer->lifetime++;
8 if((listpointer->lifetime/60)>MSG_LIFE){
9 if (listpointer == NULL) {
10 } else {
11 listpointer = RemoveItem(listpointer);
12 message_count = QueueCount(listpointer);
13 }
14 }
15 listpointer = listpointer -> link;
16 
17 }
18 }
19
20}

typedef struct {
    char message[MSG_SIZE];
    int lifetime, type;
    struct listelement *link;
} listelement;

1listelement * AddItem (listelement * listpointer, int type, char *msg) {
2 
3 listelement * lp = listpointer;
4 
5 if (listpointer != NULL) {
6 while (listpointer -> link != NULL)
7 listpointer = listpointer -> link;
8 listpointer -> link = (struct listelement *) malloc (sizeof (listelement));
9 listpointer = listpointer -> link;
10 listpointer -> link = NULL;
11 listpointer -> type = type;
12 listpointer -> lifetime = 0;
13 snprintf( listpointer -> message, sizeof(listpointer -> message), msg);
14 return lp;
15 }
16 else {
17 listpointer = (struct listelement *) malloc (sizeof (listelement));
18 listpointer -> link = NULL;
19 listpointer -> type = type;
20 listpointer -> lifetime = 0;
21 snprintf( listpointer -> message, sizeof(listpointer -> message), msg);
22 return listpointer;
23 }
24}
25 
26listelement * RemoveItem (listelement * listpointer) {
27 
28 listelement * tempp;
29 tempp = listpointer -> link;
30 free (listpointer);
31 return tempp;
32
33}
34 
35void PrintQueue (BITMAP *bmp, listelement * listpointer, int x, int y) {
36 
37 if (listpointer == NULL) {
38 } else {
39 while (listpointer != NULL) {
40 draw_sprite( bmp, chatImg[listpointer->type], x, (y - 3) );
41 render_outline_text( bmp, font, listpointer->message, x + 20, y, 0 );
42 listpointer = listpointer -> link;
43 y+=15;
44 }
45 }
46 
47}
48 
49int QueueCount (listelement * listpointer) {
50 
51 int count=0;
52 
53 if (listpointer == NULL) {
54 } else {
55 while (listpointer != NULL) {
56 count++;
57 listpointer = listpointer -> link;
58 }
59 }
60
61 return count;
62 
63}
64 
65void ClearQueue (listelement * listpointer) {
66 
67 while (listpointer != NULL) {
68 listpointer = RemoveItem (listpointer);
69 }
70
71}
72 
73// Read through messages (back->front)
74void render_messages(BITMAP *bmp, FONT *font, int x, int y) {
75
76 if( message_count > 0 ) {
77
78 clear_to_color( hud, makecol(255,0,255));
79 rectfill( hud, x, y, (x + (bmp->w - (x * 2))), y + (message_count * 15), makecol(0,0,0));
80
81 set_trans_blender( 0, 0, 0, 55 );
82 draw_trans_sprite( buffer, hud, 0, 0 );
83
84 y += 4; x += 15;
85 
86 PrintQueue (bmp, listpointer, x, y);
87
88 }
89
90 render_error_messages( bmp, def_large_text, 300, 453 );
91
92}
93 
94void SortQueue(listelement * listpointer) {
95
96 if (listpointer == NULL) {
97 } else {
98 while (listpointer != NULL) {
99
100 listpointer->lifetime++;
101 if((listpointer->lifetime/60)>MSG_LIFE){
102 if (listpointer == NULL) {
103 } else {
104 listpointer = RemoveItem(listpointer);
105 message_count = QueueCount(listpointer);
106 }
107 }
108 listpointer = listpointer -> link;
109 
110 }
111 }
112
113}
114 
115void local_sort_messages(void) {
116
117 SortQueue( listpointer );
118
119}

Tobias Dammers
Member #2,604
August 2002
avatar

If you have a fixed number of messages, then it can be even easier. Just use a ring buffer.

1class RINGBUFFER {
2 protected:
3 string data[MAX_RINGBUFFER_SIZE];
4 int top;
5 int cur;
6 public:
7 RINGBUFFER(): top(0), cur(0) {}
8 
9 void clear() {
10 top = cur = 0;
11 }
12 
13 void push(string s) {
14 data[cur] = s;
15 ++cur;
16 cur %= MAX_RINGBUFFER_SIZE;
17 if (cur == top)
18 ++top;
19 top %= MAX_RINGBUFFER_SIZE;
20 }
21 
22 void render(BITMAP* bmp) {
23 int y = 0;
24 for (int i = top; i != cur; i = (i+1) % MAX_RINGBUFFER_SIZE) {
25 textprintf_ex(bmp, font, 0, y, makecol(0, 255, 0), -1, "%40s", data<i>.c_str());
26 y += text_height(font);
27 }
28 }
29};

Something like that.

---
Me make music: Triofobie
---
"We need Tobias and his awesome trombone, too." - Johan Halmén

Paul whoknows
Member #5,081
September 2004
avatar

Quote:

Just as a side note, the term used for a LIFO data structure is typically stack, not pile (at least in english).;)

"Pila" is the Spanish word we use for stack(LIFO), and "pile" is the most common mistake you can expect from a Spanish talker.
There is also another stupid examples of course, like "cola" which also means a$$, we say "cola" instead of buffer:D

____

"The unlimited potential has been replaced by the concrete reality of what I programmed today." - Jordan Mechner.

A J
Member #3,025
December 2002
avatar

for 5 text strings
just have 5 const char*'s and manually move the ptrs, until you need a serious use for a FIFO LIFO FILO MOMO you should just keep things as simple as possible.

___________________________
The more you talk, the more AJ is right. - ML

Tobias Dammers
Member #2,604
August 2002
avatar

Wow, didn't notice you're from Argentina, Paul. Your English certainly doesn't tell. There are quite a few "false friends" between Spanish and most Germanic languages (English, German and Dutch are the ones I use). Took me a few weeks to find out that German / Dutch / English "tempo" (in music) unfortunately doesn't correspond to "tiempo", but rather to "aire", which, in turn, I had taken to mean something like "atmosphere" or "general feel".
In Cuban music, there is also the disturbing fact that one word usually means at least 3 things. For example, a "montuno" can be:
- a pattern the piano, guitar, or tres, plays (a.k.a. "guajeo", "tumbao")
- the second part of a salsa or son, sort of an open vamp section
- the chord sequence used in that part of the music
- a music genre
- a dance
It gets less disturbing once one understands that these seemingly different things, after all, are manifestations of the same thing.
Also, Cubans seem to use the words "bailar" and "tocar" interchangeably when referring to playing an instrument.

Enough OT.

---
Me make music: Triofobie
---
"We need Tobias and his awesome trombone, too." - Johan Halmén

Go to: