Friday, June 17, 2022

Day 5/100 Sequence

 5/100 Sequence

Seq for short


Yes, I know that Linux has a utility called 'seq' that can be used to generate line numbers. The problem is that it doesn't accept file input, so that making up numbered lines is quite a hassle. I believe that I used awk, the last time I did it. I think it's overkill.


So, I went ahead and did it. Of course, it's supposed to be a short 1 hour project. Turns out I was tired or something, since it became a 2 hour project. It's the end of the day, and I was tired!


The hardest part turns out to be the one I thought would be the easiest: GetOpt(). It's certainly unique in the parameter settings.


Usage: seq [OPTION]... LAST
  or:  seq [OPTION]... FIRST LAST
  or:  seq [OPTION]... FIRST INCREMENT LAST


Not pretty. I used more variables than what I usually tolerate. At least it works fine. Then the usual testing that FIRST may be less than LAST, and that the sequence should work the other way. By the way, it's possible to set the INCREMENT wrong and have a runaway program!


The core of the program turns out to be short enough at only 15 lines. That includes stdin feature for an extra 6 lines of code with 2 of them curly braces.


Well, it's getting long on the tooth for the week. I should do something fun for the next project.


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

#define MAX_LINE 256
int First=1;
int Inc=1;
int Last=10;
int Curr=0;
int Dir=1;
int Debug=0;
char Liner[MAX_LINE];
char STR[256];
int  WDT=4;
void ShowMsg() {
puts("Usage: seq [OPTION]... LAST");
puts("  or:  seq [OPTION]... FIRST LAST");
puts("  or:  seq [OPTION]... FIRST INCREMENT LAST");
puts("Print numbers from FIRST to LAST, in steps of INCREMENT.");
puts("");
puts("  -sSTRING use STRING to separate numbers (default: \n)");
puts("  -wWIDTH  equalize width by padding with leading zeroes");
puts("  --help     display this help and exit");
puts("  --debug    set debug mode");
puts("");
puts("If FIRST or INCREMENT is omitted, it defaults to 1.  That is, an");
puts("omitted INCREMENT defaults to 1 even when LAST is smaller than FIRST.");
puts("The sequence of numbers ends when the sum of the current number and");
puts("INCREMENT would become greater than LAST.");
puts("INCREMENT is usually positive if FIRST is smaller than LAST, and");
puts("INCREMENT is usually negative if FIRST is greater than LAST.");
puts("If LAST is 0, stdin is read for lines until exhausted.");
}

int GetOpt(int argc, char *argv[]) {
int i;
int l=0,l1=0,l2=0,l3=0;
  for (i=1;i<argc;i++) {
    if (!strncmp("-s",argv[i],2))
      { strcpy(STR,argv[i]+2); continue; }
    if (!strncmp("-w",argv[i],2))
      { WDT=atoi(argv[i]+2); continue; }
    if (!strncmp("--help",argv[i],6))
      { ShowMsg(); return 1; }
    if (!strncmp("--debug",argv[i],7))
      { Debug=1; continue; }
    if (l==0) { l1=atoi(argv[i]); l++; continue; }
    if (l==1) { l2=atoi(argv[i]); l++; continue; }
    if (l==2) { l3=atoi(argv[i]); l++; continue; }
  }

  if (Debug) printf("l=%d\n",l);
  switch (l) {
    case 1: Last=l1; break;
    case 2: First=l1; Last=l2; break;
    case 3: First=l1; Inc=l2; Last=l3; break;
    default: return 1;
  }
  Curr=First; Dir=(First<Last)?1:-1;

  if (Debug) {
    printf("First=%d\n",First);
    printf("Inc=%d\n", Inc);
    printf("Last=%d\n", Last);
    printf("Dir=%d\n",Dir);
    printf("STR =%s=\n",STR);
    printf("WDT=%d\n",WDT);
  }
  return 0;
}


int Seq() {
  char *buf;
  if (Last==0) {
    while (buf=fgets(Liner,MAX_LINE,stdin)) {
      printf("%d %s",Curr,buf);
      Curr+=Inc;
    }
  }
  for (;Last!=0;Curr+=Inc) {
    if (Dir>0 && Curr>Last) break;
    if (Dir<0 && Curr<Last) break;
    printf("%s%d",(Curr==First)?"":STR,Curr);
  }
  putchar('\n'); return 0;
}
int main (int argc, char *argv[] ) {
  int e=0;
  strcpy(STR,"\n");
  if   (argc<2) { ShowMsg(); return 0; }
  e=GetOpt(argc, argv);
  if (!e) e=Seq();
  return e;
}


At the end of the day, I use the program a lot. Specifically, line numbering the programs I'm writing since I still don't know how to enable line numbering using nano!



No comments:

Post a Comment