patterncModerate
Tail implementation in C
Viewed 0 times
implementationtailstackoverflow
Problem
Write the program
prints the last
The exercise can be found on page 133 in K&R.
I will explain the way my program works.
First it parses the value of the symbolic argument(if any). Based on the value of the symbolic argument the program will initialize a queue which stores pointer to each line.
Then, the program will read lines and push every line in the queue until the end of files is reached. When the end of file is reached all elements of the queue are printed out.
There are multiple files in my project:
```
#include
#include
#include "alloc.h"
static char **queue;
static int queueSize;
static int head = -1;
static int rear = -1;
static int isEmpty(void) {
return (head == -1 && rear == -1);
}
static int isFull(void) {
return (rear + 1) % queueSize
tail, which prints the last n lines of its input. By default, n is 10, let us say, but it can be changed by an optional argument, si thattail -nprints the last
n lines. The program should behave rationally no matter how unresonable the input or the value n. Write the program so it makes the best use of available storage; lines should be stored as in the sorting program of section 5.6, not in a two-dimensional array of fixed size.The exercise can be found on page 133 in K&R.
I will explain the way my program works.
First it parses the value of the symbolic argument(if any). Based on the value of the symbolic argument the program will initialize a queue which stores pointer to each line.
Then, the program will read lines and push every line in the queue until the end of files is reached. When the end of file is reached all elements of the queue are printed out.
There are multiple files in my project:
main.c:#include
#include
#include "tail.h"
#define MAXLINES 100
#define LINESIZE 100
int main(int argc, char *argv[]) {
int linesNumber = 10;
if(argc > 2) {
return 1;
}
else if(argc == 2) {
linesNumber = atoi(argv[1] + 1);
if(linesNumber == 0) {
return 0;
}
initQueue(linesNumber, LINESIZE);
}
else {
initQueue(linesNumber, LINESIZE);
}
readLines(LINESIZE, MAXLINES);
printQueueElements();
return 0;
}linesNumber represent the variable that will store the size of the queue. By default this variable is 10. If the value of the symbolic argument is 0 there is no reasone to continue reading lines, so the program will terminate execution.queue.c```
#include
#include
#include "alloc.h"
static char **queue;
static int queueSize;
static int head = -1;
static int rear = -1;
static int isEmpty(void) {
return (head == -1 && rear == -1);
}
static int isFull(void) {
return (rear + 1) % queueSize
Solution
That is a lot of code for the job. It can be done significantly more easily in two areas:
If you don't want to use
Here is a version that uses an allocated array or char* pointers. The array is zeroed (by
- use an array instead of a queue
- use the POSIX function,
getline, which will handle lines of any size.
If you don't want to use
getline (which admittedly might not have existed when K&R wrote their book), concentrate on writing its equivalent. Here is a version that uses an allocated array or char* pointers. The array is zeroed (by
calloc) so that we can tell whether the entry holds a line (which might not be so if the input is less than 10 (or the requested number of) lines.int
tail(size_t n_lines, FILE *fp)
{
char **lines = calloc(sizeof(char*), n_lines);
if (!lines) {
perror("calloc");
return -1;
}
size_t size = 0;
size_t in = 0;
for (char *ln = 0; getline(&ln, &size, fp) > 0; in = (in + 1) % n_lines) {
if (lines[in]) {
free(lines[in]);
}
lines[in] = ln;
ln = NULL;
size = 0;
}
for (size_t i = 0; i < n_lines; ++i) {
if (lines[in]) {
printf("%s", lines[in]);
free(lines[in]);
}
in = (in + 1) % n_lines;
}
free(lines);
return 0;
}Code Snippets
int
tail(size_t n_lines, FILE *fp)
{
char **lines = calloc(sizeof(char*), n_lines);
if (!lines) {
perror("calloc");
return -1;
}
size_t size = 0;
size_t in = 0;
for (char *ln = 0; getline(&ln, &size, fp) > 0; in = (in + 1) % n_lines) {
if (lines[in]) {
free(lines[in]);
}
lines[in] = ln;
ln = NULL;
size = 0;
}
for (size_t i = 0; i < n_lines; ++i) {
if (lines[in]) {
printf("%s", lines[in]);
free(lines[in]);
}
in = (in + 1) % n_lines;
}
free(lines);
return 0;
}Context
StackExchange Code Review Q#43142, answer score: 11
Revisions (0)
No revisions yet.