I'm working on a version of the Unix tail command that works by iterating over a file, pushing line by line into a stack. Finally, the number of desired lines will be popped and printed to the screen. I have used void *
(void pointers) as the data
field of my stack nodes (the stack is basically a linked list with limitations) and due to that I had to do a bit of work with pointer casting and successive allocations with malloc()
(one chunk per line). I wonder if there isn't a better (as in simpler, more readable and less memory intensive) way of accomplishing the same goal.
Main tail.c file
#include <stdio.h>
#include <stdlib.h>
#include <string.h>
#include "../utils/type_definitions.h"
#include "../stack/stack_list/stack_list.h"
#define LINE_SIZE 256
int main(int argc, char *argv[])
{
int number_of_lines;
if (argc == 2) {
number_of_lines = atoi(argv[1]);
} else {
printf("%s\n", "Error!");
exit(1);
}
FILE *f;
if (!(f = fopen("file.txt", "r"))) {
printf("%s\n", "Error opening file!\n");
exit(1);
};
// pushing lines into stack
int i = 0;
char *line, *temp = (char*)malloc(LINE_SIZE);
Node *stack = stack_new();
while (fgets(temp, sizeof(line), f) != NULL) {
line = (char*)malloc(LINE_SIZE);
strcpy(line, temp);
stack_push((void*)line, &stack);
}
// poping and printing n lines to screen
for (int i = 0; i < number_of_lines; i++) {
printf("%s\n",(char*)stack_top(stack));
stack_pop(&stack);
}
return 0;
}
Stack header file
#ifndef __STACK_H__
#define __STACK_H__
#include <stdbool.h>
#include "../../utils/type_definitions.h"
Node *stack_new();
void *stack_top(Node *head);
void stack_pop(Node **head);
bool stack_is_empty(Node *head);
void stack_push(void *x, Node **head);
#endif
Implementation of stack functions
Node *stack_new() {
return NULL;
}
bool stack_is_empty(Node *head) {
return head == NULL;
}
void *stack_top(Node *head) {
return head->data;
}
void stack_pop(Node **head)
{
if (*head == NULL) return;
Node *temp = *head;
*head = (*head)->next;
free(temp);
}
void stack_push(void *x, Node **head)
{
Node *new_node = (Node*)malloc(sizeof(Node));
new_node->data = x;
new_node->next = *head;
*head = new_node;
}
Edit - following are the includes missing from the file "implementations of stack functions".
#include "stack_list.h"
#include <stdio.h>
#include <stdlib.h>
#include <stdbool.h>
utils/type_definitions.h
, too (or at least enough to defineNode
). \$\endgroup\$