[comp.sources.d] v06i100: Count program - leading zero enhancement

mason@tmsoft.uucp (Dave Mason) (05/16/89)

In article <54804@uunet.UU.NET> Jeff Beadles <jeff@quark.wv.tek.com>
gives us the classic little hack.  It's beautiful.  3 lines changed
and it now gives leading zeros useful for filenames.  (Note this may
not work on really old printf's.  I wasn't willing to add the 2 other
lines required to make it work everywhere.)
	../Dave

*** count.1.orig	Mon May 15 19:38:00 1989
--- count.1	Mon May 15 19:54:37 1989
***************
*** 27,31 ****
--- 27,35 ----
  .I 040
  ) between each number.
  
+ Leading zeros on the
+ .I Start
+ value will be reflected in the generated numbers.
  .SH AUTHOR
  Jeff Beadles	jeff@quark.WV.TEK.COM
+ Dave Mason	mason@tmsoft	(leading zeros hack)
*** count.c.orig	Mon May 15 19:38:02 1989
--- count.c	Mon May 15 19:55:28 1989
***************
*** 16,21 ****
--- 16,30 ----
   *
   */
  
+ /*	Great program!  Hacked by Dave Mason <mason@tmsoft> 890515 to:
+  *	Add leading zeros (string will always be at least as long as
+  *	the lower limit).  E.g.:
+  *		count 05 7
+  *	will produce:
+  *		05
+  *		06
+  *		07
+  */
  
  #include <stdio.h>
  #include <ctype.h>
***************
*** 37,42 ****
--- 46,52 ----
  	void usage();
  	int oatc();
  	int	start = 0;	/* Start count				*/
+ 	int	len;		/* Minimum length			*/
  	int	stop  = 0;	/* Stop  count				*/
  	int	pos   = 1;	/* Position in command line for parsing	*/
  	char	fs    = FS;	/* Field Separator			*/
***************
*** 51,56 ****
--- 61,67 ----
  			fs = argv[1][1];
  		pos++;		/* On to the next arg... */
  	}
+ 	len   = strlen(argv[pos]);	/* Minimum length */
  	start = atoi(argv[pos++]);	/* Start here, and... */
  
  	if ( argc <= pos)
***************
*** 67,73 ****
     Yes, this is it.  It even prints a '\n' when done, if the fs != '\n' (Wow)
   */
  	while ( start <= stop )
! 		printf("%d%c",start++,( (start != stop) ? fs : '\n' ) );
  }
  
  /*
--- 78,84 ----
     Yes, this is it.  It even prints a '\n' when done, if the fs != '\n' (Wow)
   */
  	while ( start <= stop )
! 		printf("%.*d%c",len,start++,( (start != stop) ? fs : '\n' ) );
  }
  
  /*

waynet@mongo.uucp (Wayne Thompson) (05/16/89)

Here's a short script that does the same.

Wayne

#! /bin/sh
# output sequence of integers - W. Thompson - 01/29/88
#
USAGE='usage: num [-wWIDTH] [firstn] lastn.'

if [ $# -eq 0 ] || [ $# -gt 3 ]
then
	echo "$USAGE"
	exit
fi

for i
do case "$i" in
      -w[0-9])	WIDTH=`expr substr $i 3 1`;
                shift;;
      -*)	echo "$i illegal option";
                exit;;
      *)	break;;
   esac
done

if [ $# -eq 1 ]
then
	START=0
	END=$1
else
	START=$1
	END=$2
fi

awk '
	END {
		for (i = '$START'; i <= '$END'; i++)
			printf ("%0'$WIDTH'd\n", i)
	}
' /dev/null

cosell@bbn.com (Bernie Cosell) (05/17/89)

In article <33795@mongo.uucp> waynet@mongo.uucp (Wayne Thompson) writes:
}Here's a short script that does the same.

I hate to be picky, but the script has a bit of a problem.  Try feeding it
     count 5 -w6 7
or
     count 5 xxy

On the other hand, here's a short perl script that also does the job.
It is a bit longer than the shell script, but a fair amount of that is doing
error checking and such.

   __
  /  )                              Bernie Cosell
 /--<  _  __  __   o _              BBN Sys & Tech, Cambridge, MA 02238
/___/_(<_/ (_/) )_(_(<_             cosell@bbn.com

#!/usr/local/bin/perl

# Output a sequence of integers

$Usage="usage: num [-wWIDTH] [firstn] lastn\n";

sub Usage { printf stderr $Usage ; exit 1; }

do Usage() if ($#ARGV < 0 || $#ARGV > 2);

$lastnum = pop(@ARGV);
do Usage() if $lastnum !~ /^[0-9]*$/;

if ($#ARGV >= 0 && $ARGV[0] =~ /^-w([0-9]*)$/)
{
    $width = $1;
    shift(@ARGV);
}
else
{
    $width = length($lastnum);
}

if ($#ARGV >= 0)
{
    $firstnum = $ARGV[0];
    do Usage() if $firstnum !~ /^[0-9]*$/ || $#ARGV != 0;
}
else
{
    $firstnum = 1;
}

for ($i = $firstnum; $i <= $lastnum; $i += 1)
{
    printf ("%0${width}d\n", $i);
}

exit 0;

waynet@mongo.uucp (Wayne Thompson) (05/19/89)

In article <40035@bbn.COM> cosell@bbn.com (Bernie Cosell) writes:
   I hate to be picky, but the script has a bit of a problem.
   [deleted error cases]
   On the other hand, here's a short perl script that also does the job.
   [deleted perl script]
I never seem to learn not to publish hacks (someone might use them :-)).
Here's a production version. I like perl, but it limits the potential
usefulness of a script 'cause not everyone has it.
Wayne

#! /bin/sh
#
#       @(#)num         1.0 (waynet@sun) 05/18/89
#
pathname=oculus:/HOME/waynet/bin/num
myname=`basename $0`
#
# Author:
#     Wayne Thompson
#
# Description:
#     This script will output a sequence of integers.
#
usage="usage: $myname [-wWIDTH] [firstn] lastn."
#
# Options:
#     -wN       field width of N, left zero padded.
#
# Files:
#
# Diagnostics:
#
# Dependencies:
#
# Bugs:
#

## >> BEGIN function: isnum >>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>> ##

# Function:
#     isnum
#
# Description:
#     This function tests whether it's argument is numeric.
#
# Variables:
#
# Usage:
#     if isnum 5
#     then
#         echo "true"
#     fi
#
# Diagnostics:
#

isnum () {
    expr ${1:-null} + 1 > /dev/null 2>&1
}

## << END function: isnum <<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<< ##

case $1 in
    -w*[0-9])
        width=`expr substr $1 3 1`
        shift
        ;;
esac

case $# in
    1)
        start=0
        end=$1
        ;;
    2)
        start=$1
        end=$2
        ;;
    *)
        echo >&2 "$usage"
        exit 1
        ;;      
esac

for i in $@
do
    isnum $i || {
        echo >&2 "$myname: $i: non-numeric argument."
        echo >&2 "$usage"
        exit 1
    }
done

if [ $start -gt $end ]
then
    echo >&2 "$myname: firstn greater than lastn."
    echo >&2 "$usage"
    exit 1
fi

awk '
    BEGIN {
        for (i = '$start'; i <= '$end'; i++) {
            printf ("%0'$width'd\n", i)
        }
    }
' /dev/null