Solved

Fix Tail

Posted on 1998-11-24
7
312 Views
Last Modified: 2010-04-15
/*I found this example in one of my book's given to me.  The problem with this it will not compile.  Could someone show me what the problem is.  I guess this is really a two part question.  By the looks the of the program is should print out the last ten lines of something.  Does this mean it should look at a file, if so could you bump it up so that it could do that.  I'm just curious on how this would work.

#include <stdio.h>
#include <stdlib.h>
#include <string.h>

#define DEFLINES 10
#define LINES    100
#define MAXLEN   100

void error(char *);
int getline(char *, int);

main(int argc, char *argv[])
{
        char *p;
        char *buf;
        char *bufend;
        char line[MAXLEN];
        char *lineptr[LINES];
        int first, i, last, len, n, nlines;

        if (argc == 1)
                n = DEFLINES;
        else if (argc == 2 && (*++argv)[0] == '-')
                n = atoi(argv[0] + 1);
        else
                error("usage: tail [-n]");
        if(n < 1 || n > LINES)
                n = LINES;
        for (i = 0; i < LINES; i++)
                lineptr[i] = NULL;
        if((p = buf = malloc(LINES * MAXLEN)) == NULL)
                error("tail: cannot allocate buf");
        bufend = buf + LINES * MAXLEN;
        last = 0;
        nlines = 0;

        while ((len = getline(line, MAXLEN)) > 0)
        {
                if(p + len + 1 >= bufend)
                        p = buf;
                lineptr[last] = p;
                strcpy(lineptr[last], line);
                if(++last >= LINES)
                        last = 0;
                p += len + 1;
                nlines++;
        }
        if (n > nlines)
                n = nlines;
        first = last - n;
        if(first < 0)
                first += LINES;
        for ( i = first; n --> 0; i = ( i + 1 ) % LINES )
                printf("%s", lineptr[i]);
        return 0;
}
void error(char *s)
{
        printf("%s\n", s);
        exit(1);
}
0
Comment
Question by:newpoint
7 Comments
 
LVL 3

Expert Comment

by:marcjb
ID: 1254612
The getline function is never defined.  It is declared at the beginning of the program, but there is no code for it.  As a result, the program will not link.
Also, no file is indicated.  What is being tailed?  I will try to touch up the code so that you can tail a user-specified file.
0
 
LVL 1

Expert Comment

by:MatthewL
ID: 1254613
Hi newpoint;

1.   Adding a (char *) will get rid of the compile error message.  
                  if((p = buf =(char *) malloc(LINES * MAXLEN)) == NULL)

2.   It's also missing the function definition for getline().  Is that earlier in the book?

3.   Are you aware that this program uses command line arguments?  ( e.g. dir /w )  That       is where the string is coming from, not a file.

Matt
0
 
LVL 27

Expert Comment

by:BigRat
ID: 1254614
  I suspect that "it won't compile" means that the procedure getline is missing.It is declared at the top but it's missing at the bottom (unlike error).
   Rat's have tails but what is meant here is the Unix utility command tail which takes an optional parameter, namely a number of lines n, here defaulted to DEFLINES or 10, up to a maximum value (here LINES or 100) and prints out the last n lines from a file. The "print out" is acutally standard output (stdout) and it would very much surprise me that, if we had the source of getline, it wouldnot  take them from standard input (stdin). The usage would be (if we had a program called fred which outputs text) :-

      fred | tail -23                -- the | means pipe as in water-pipe

which would print out the last 23 lines of fred's output
What's the book incidentally?
   
0
Why are Office 365 signatures so complicated?

Trying to setup transport rules for Office 365 email signatures and can’t quite figure it out? Having to test the signature over and over? Make things simple by using Exclaimer Cloud - Signatures for Office 365.

 
LVL 3

Expert Comment

by:marcjb
ID: 1254615
/*  Sorry if this posts twice, but I had trouble with my browser.

    I replaced getline with fgets, and eliminated a few other
    variables.  Also, I changed the way the lines are stored by
    the program.  I believe it is still readable.
    The program will also need a file as an argument
    ex:  tail test.txt -25
             or
         tail test.txt

*/

#include <stdio.h>
#include <stdlib.h>
#include <string.h>

#define DEFLINES 10
#define LINES    100
#define MAXLEN   100

void error(char *);

main(int argc, char *argv[])
    {
    FILE *input;
    char *buf[LINES];
    char line[MAXLEN];
    int i, n, nlines;
    int last;

    if (argc == 2)
      {
      if ( (input = fopen(argv[1], "r")) == NULL)
          error("could not open file");
      n = DEFLINES;
      }
    else if (argc == 3 && argv[2][0] == '-')
      {
      if ( (input = fopen(argv[1], "r")) == NULL)
          error("could not open file");
      n = atoi(argv[2] + 1);
      }
    else
      error("usage: tail <filename> [-n]");

    if(n < 1 || n > LINES) /* Default to 10 lines in bad input */
      n = DEFLINES;

    for (i = 0; i < n; ++i)
      if((buf[i] = malloc(MAXLEN*sizeof(char))) == NULL)
          error("tail: cannot allocate buf");

    nlines = 0;
    last = 0;

    while ( fgets(line, MAXLEN, input) != NULL )
      {
      strcpy(buf[last++], line);
      if (last == n)
          last = 0;
      nlines++;
      } /* END READING INPUT FILE */

    if (n > nlines)
      n = nlines;
    if (last != 0)
      --last;
    for ( i = 0; i < n; ++i)
      {
      printf("%s", buf[last++]);
      if (last == n)
          last = 0;
      }

    for (i = 0; i < n; ++i)
      free(buf[i]);
    fclose(input);
    return 0;
    }

void error(char *s)
    {
          printf("%s\n", s);
          exit(1);
    }
0
 

Author Comment

by:newpoint
ID: 1254616
The books my wife bought me for a hobby are "The C Programming Language, second edition" and "The C Answer Book".  The reason I posted this question was so I could use it as a tool to scroll to a bottom of a file.  Any help that can show how this program can run and work would be helpful.
0
 

Author Comment

by:newpoint
ID: 1254617
I still receive a error message when I compile the program.  
0
 
LVL 14

Accepted Solution

by:
AlexVirochovsky earned 250 total points
ID: 1254618
It is you programm
#include <stdio.h>
#include <stdlib.h>
#include <string.h>

#define DEFLINES 10
#define LINES    100
#define MAXLEN   100

void error(char *);
int getline(FILE *,char *, int);

main(int argc, char *argv[])
{
      char *p;
      char *buf;
      char *bufend;
      char line[MAXLEN+1];
      char *lineptr[LINES];
      int first, i, last, len, n, nlines;
      FILE *fIn = fopen ("NONAME1.cpp","rt");
      if (!fIn)
        {
            error("File not exist"); exit(4);
        }
      if (argc == 1)
            n = DEFLINES;
      else if (argc == 2 && (*++argv)[0] == '-')
            n = atoi(argv[0] + 1);
      else
            error("usage: tail [-n]");
      if(n < 1 || n > LINES)
            n = LINES;
      for (i = 0; i < LINES; i++)
            lineptr[i] = NULL;
      if((p = buf = (char *)malloc(LINES * MAXLEN)) == NULL)
            error("tail: cannot allocate buf");
      bufend = buf + LINES * MAXLEN;
      last = 0;
      nlines = 0;

      while ((len = getline(fIn,line, MAXLEN)) > 0)
      {
            if(p + len + 1 >= bufend)
                  p = buf;
                lineptr[last] = p;
            strcpy(lineptr[last], line);
                if(++last >= LINES)
                  last = 0;
            p += len + 1;
                nlines++;
      }
      if (n > nlines)
            n = nlines;
      first = last - n;
      if(first < 0)
            first += LINES;
      for ( i = first; n --> 0; i = ( i + 1 ) % LINES )
            printf("%s", lineptr[i]);
      fclose(fIn);
      return 0;
}
void error(char *s)
{
      printf("%s\n", s);
      exit(1);
}
int getline(FILE *fIn,char *s, int nLen)
{
  memset(s,0,nLen);
  fgets(s, nLen,fIn);
  return strlen (s);
}
Regards, Alex
0

Featured Post

Are your AD admin tools letting you down?

Managing Active Directory can get complicated.  Often, the native tools for managing AD are just not up to the task.  The largest Active Directory installations in the world have relied on one tool to manage their day-to-day administration tasks: Hyena. Start your trial today.

Question has a verified solution.

If you are experiencing a similar issue, please ask a related question

Suggested Solutions

This tutorial is posted by Aaron Wojnowski, administrator at SDKExpert.net.  To view more iPhone tutorials, visit www.sdkexpert.net. This is a very simple tutorial on finding the user's current location easily. In this tutorial, you will learn ho…
Summary: This tutorial covers some basics of pointer, pointer arithmetic and function pointer. What is a pointer: A pointer is a variable which holds an address. This address might be address of another variable/address of devices/address of fu…
Video by: Grant
The goal of this video is to provide viewers with basic examples to understand and use nested-loops in the C programming language.
The goal of this video is to provide viewers with basic examples to understand and use switch statements in the C programming language.

920 members asked questions and received personalized solutions in the past 7 days.

Join the community of 500,000 technology professionals and ask your questions.

Join & Ask a Question

Need Help in Real-Time?

Connect with top rated Experts

12 Experts available now in Live!

Get 1:1 Help Now