If you’re using the macros from <sys/queue.h>
to implement a circular doubly linked list (TAILQ), the inversion issue occurs because you’re using LIST_INSERT_HEAD
, which inserts at the head of the list. Instead, to maintain the original order (FIFO), you should use TAILQ_INSERT_TAIL
.
Here’s how you can create a circular doubly linked list and add lines to it while preserving their order:
Steps:
- Include the necessary header: Use
<sys/queue.h>
. - Define a struct for the list entry: Each entry holds a line of text and pointers for the circular doubly linked list.
- Initialize the list: Use
TAILQ_HEAD
andTAILQ_INIT
. - Insert lines: Use
TAILQ_INSERT_TAIL
to add lines at the end.
Example Code:
#include <stdio.h>
#include <stdlib.h>
#include <string.h>
#include <sys/queue.h>
#define LINE_MAX 128
// Define the structure for each list entry
struct Line {
char text[LINE_MAX]; // Holds the line text
TAILQ_ENTRY(Line) entries; // Macro for pointers
};
// Define the head of the list
TAILQ_HEAD(LineList, Line);
int main() {
struct LineList list; // Declare the list
struct Line *line; // Temporary pointer for a line
char buffer[LINE_MAX]; // Buffer to hold input lines
// Initialize the list
TAILQ_INIT(&list);
// Example: Adding lines to the list
printf("Enter lines of text (empty line to finish):\n");
while (fgets(buffer, LINE_MAX, stdin) != NULL) {
// Remove the newline character
size_t len = strlen(buffer);
if (len > 0 && buffer[len - 1] == '\n') {
buffer[len - 1] = '\0';
}
// Stop if the input is empty
if (strlen(buffer) == 0) {
break;
}
// Allocate memory for a new line
line = malloc(sizeof(struct Line));
if (line == NULL) {
perror("malloc failed");
exit(EXIT_FAILURE);
}
// Copy the text into the line structure
strncpy(line->text, buffer, LINE_MAX);
// Insert the line at the tail of the list
TAILQ_INSERT_TAIL(&list, line, entries);
}
// Print all lines in the list
printf("\nLines in the list:\n");
TAILQ_FOREACH(line, &list, entries) {
printf("%s\n", line->text);
}
// Free memory and clear the list
while ((line = TAILQ_FIRST(&list)) != NULL) {
TAILQ_REMOVE(&list, line, entries);
free(line);
}
return 0;
}
Explanation:
- Circular Doubly Linked List:
- The
TAILQ
macros create a circular doubly linked list. -
TAILQ_INSERT_TAIL
ensures lines are appended at the end, preserving their order (FIFO).
- Key Macros:
-
TAILQ_INIT(&list)
: Initializes the list. -
TAILQ_INSERT_TAIL(&list, line, entries)
: Inserts a new entry at the tail. -
TAILQ_REMOVE(&list, line, entries)
: Removes an entry from the list. -
TAILQ_FOREACH(line, &list, entries)
: Iterates over the list.
- Buffer Handling:
- The buffer size is
128
characters, matching the problem’s requirements. - Newline characters are removed for clean output.
Output Example:
Input:
Hello, World!
This is a test.
Another line.
<empty line>
Output:
Lines in the list:
Hello, World!
This is a test.
Another line.
This approach maintains the original input order (FIFO) without inversion.