Thursday, June 16, 2022

Head Or Tail 4/100

 Day 4/100 Head or Tail

I want them both!


I've always wanted to have my own head and tail program. The reason being is that so I can control exactly where the cutoff line would be. Right now, if I wanted a certain line in the middle, I have to pipe head into tail. I wanted my own file slicing program, so to speak. And here it is...


I think the first thing you notice would be the fact that there's a help instruction on the program. That is because I design it to be used. Granted it's not perfect. Array of pointers have a fixed size, and no WARNING available when the limit is exceeded. Also, the only input available is via stdin. 


Another noticeable feature would be the DEBUG option. It has helped me greatly as several instances of SEGMENTATION FAULT occurred while I was developing the program. Heh. And given the lack of sophisticated error message does make it a bit harder to figure out. Would you believe the biggest stumble was in printf()? I was still shaking my head on that one...


The name of the program is HeadOrTail, and it is because the program features both options. And rightly so, because they both are similar in size and features. Or rather, HEAD is very easy to write, while TAIL is very hard to write due to the need of dynamic memory allocations. I cheated a bit and use the recursive feature of the C language to do it. It does complicated matter, and I had to build my own stack to simulate QUEUE. Sigh.


Still not too bad. Not counting code for input, it's only 1 line for HEAD, and 3 lines for TAIL. Now that's neat! Recursion to the max for the win!


So, yes, the program works, and it's usable. That's what matters. The fact that it's done in about 3 hours or so, including this write up is a nice bonus.


#include <stdio.h>
#include <stdlib.h>
#include <string.h>
int HeadOn=0;
int HeadOf=0;
int TailOn=0;
int TailOf=0;
int Debug=0;
#define MAXARR 65535
char *StrArr[MAXARR]; //For Tail
int tstackptr=0;

void ShowMsg() {
    puts("Usage: hot [OPTION]...");
    puts("Head or Tail prints both head lines and tail lines.");
    puts("It takes stdin as input.");
    puts("If options are not specified, it prints nothing.");
    puts("  -hNUM   print the first NUM lines of each input.");
    puts("  -HNUM   skip the first NUM lines of each input.");
    puts("  -tNUM   print the last NUM lines of each input.");
    puts("  -TNUM   skip the last NUM lines of each input.");
    puts("  --help  print this message.");
    puts("  --debug show debug messages.");
    puts("\nExample:");
    puts("  hot -h10 -H5 -t20 -T15\n");
    puts("  The above example will print the first 10 lines,");
    puts("  EXCEPT the first 5 lines (i.e. 6-10).");
    puts("  It will also print the last 20 lines,");
    puts("  EXCEPT the last 15 lines.");
}
int GetOpt(int argc, char *argv[]) {
int i;
  for (i=1;i<argc;i++) {
    if (!strncmp("-h",argv[i],2)) HeadOn=atoi(argv[i]+2);
    if (!strncmp("-H",argv[i],2)) HeadOf=atoi(argv[i]+2);
    if (!strncmp("-t",argv[i],2)) TailOn=atoi(argv[i]+2);
    if (!strncmp("-T",argv[i],2)) TailOf=atoi(argv[i]+2);
    if (!strncmp("--help",argv[i],6)) ShowMsg();
    if (!strncmp("--debug",argv[i],7)) Debug=1;
  }
  if (Debug) {
    printf("HeadOn =%d\n",HeadOn);
    printf("HeadOff=%d\n",HeadOf);
    printf("TailOn =%d\n",TailOn);
    printf("TailOff=%d\n",TailOf);
  }
  return 0;
}
void PushStk(char *buffer, size_t size) {
  if (Debug) puts("PushStk start");
  StrArr[tstackptr] = (char *) malloc(size);
  strcpy(StrArr[tstackptr],buffer);
  tstackptr++;
  if (Debug) puts("PushStk end");
}
void PopStk() {
  while (0<tstackptr--) {
    printf("%s",StrArr[tstackptr]);
    free(StrArr[tstackptr]);
  }
}

int HeadOrTail(int linenum) {
  char *buffer=NULL; size_t bufLen=0;
  ssize_t bufSize=0; int r,maxnum;
     maxnum=linenum;
  bufSize=getline(&buffer, &bufLen, stdin);  
  if (linenum<=HeadOn && linenum>HeadOf)
    printf("%s",buffer);
  if (bufSize>0) {
    r=(maxnum=HeadOrTail(linenum+1))-linenum;
    if (r<=TailOn && r>TailOf
    && linenum < MAXARR) PushStk(buffer,bufSize);
  } 
  free(buffer); return maxnum;
 }

int main (int argc, char *argv[] ) {
  int e=0;
  if   (argc<2) { ShowMsg(); return 0; }
  GetOpt(argc, argv);
  e=HeadOrTail(1);
  PopStk();
  return e;
}


One final note: Would you believe I got hung up because I put semi-colon on my #define? SMH.


No comments:

Post a Comment