djm@eng.umd.edu (David J. MacKenzie) (07/03/90)
/* conv - convert numbers between bases
Usage: conv [-dho] number...
Print the value of each given NUMBER in the output base selected
by the options.
Options:
-d Output in decimal.
-h Output in hexadecimal.
-o Output in octal.
Non-option arguments are taken to be numbers in one of the three
bases. Hex numbers start with 0x; octal numbers start with 0; all
other arguments are assumed to be decimal numbers.
David MacKenzie <djm@eng.umd.edu>
Public domain.
Latest revision: 07/02/90 */
#include <stdio.h>
long convert ();
void invalid_num ();
void output ();
/* The name this program was run with. */
char *program_name;
void
main (argc, argv)
int argc;
char **argv;
{
extern int optind;
int optc;
int output_base;
program_name = argv[0];
output_base = 0;
while ((optc = getopt (argc, argv, "dho")) != EOF)
{
switch (optc)
{
case 'd':
output_base = 10;
break;
case 'h':
output_base = 16;
break;
case 'o':
output_base = 8;
break;
default:
output_base = 0;
goto usage;
}
}
usage:
if (optind == argc || output_base == 0)
{
fprintf (stderr, "\
Usage: %s [-dho] [0xhexnum] [0octnum] [decnum] ...\n", argv[0]);
exit (1);
}
for (; optind < argc; ++optind)
output (convert (argv[optind]), output_base);
putchar ('\n');
exit (0);
}
long
convert (anumber)
char *anumber;
{
long number;
if (anumber[0] == '0' && anumber[1] == 'x')
{
/* Convert from hex; sscanf returns number of conversions performed. */
if (anumber[2] == '\0' || sscanf (anumber + 2, "%lx", &number) == 0)
invalid_num (anumber);
}
else if (anumber[0] == '0')
{
/* Convert from octal. */
if (anumber[1] == '\0')
number = 0L;
else if (sscanf (anumber + 1, "%lo", &number) == 0)
invalid_num (anumber);
}
else
{
/* Convert from decimal. */
if (anumber[0] == '\0' || sscanf (anumber, "%ld", &number) == 0)
invalid_num (anumber);
}
return number;
}
void
output (number, base)
long number;
int base;
{
switch (base)
{
case 10:
printf ("%ld ", number);
break;
case 8:
printf ("0%lo ", number);
break;
case 16:
printf ("0x%lx ", number);
break;
}
}
void
invalid_num (anumber)
char *anumber;
{
fprintf (stderr, "%s: %s: invalid number\n", program_name, anumber);
exit (1);
}
--
David J. MacKenzie <djm@eng.umd.edu> <djm@ai.mit.edu>jef@well.sf.ca.us (Jef Poskanzer) (07/03/90)
For such a simple interface, a script front-ending for bc would
work too. For a somewhat more interesting interface, see below.
It's a base-conversion filter -- looks for any numbers in stdin,
converts them from any base to any base in [2..36], and leaves
non-numeric text alone.
---
Jef
Jef Poskanzer jef@well.sf.ca.us {ucbvax, apple, hplabs}!well!jef
"Publish and be damned." -- Wellesley, Duke of Wellington
/*
** baseconvert.c - base conversion filter
**
** Copyright (C) 1989 by Jef Poskanzer.
**
** Permission to use, copy, modify, and distribute this software and its
** documentation for any purpose and without fee is hereby granted, provided
** that the above copyright notice appear in all copies and that both that
** copyright notice and this permission notice appear in supporting
** documentation. This software is provided "as is" without express or
** implied warranty.
*/
#include <stdio.h>
#include <strings.h>
#include <ctype.h>
static char *idigits = "0123456789abcdefghijklmnopqrstuvwxyz";
static char *odigits = "0123456789abcdefghijklmnopqrstuvwxyz";
main( argc, argv )
int argc;
char *argv[];
{
int ibase, obase;
char *usage = "usage: %s <ibase> <obase>\n";
int ic, i, gettingi, digit;
char c, lc;
char *digitp;
void putint( );
if ( argc != 3 ||
( ibase = atoi( argv[1] ) ) < 2 || ibase > 36 ||
( obase = atoi( argv[2] ) ) < 2 || obase > 36 )
{
fprintf( stderr, usage, argv[0] );
exit( 1 );
}
idigits[ibase] = '\0';
gettingi = 0;
for ( ; ; )
{
ic = getchar( );
if ( ic == EOF ) break;
c = ic;
if ( isupper( c ) )
lc = tolower( c );
else
lc = c;
digitp = index( idigits, lc );
if ( digitp == (char *) 0 )
{
if ( gettingi )
{
putint( i, obase );
gettingi = 0;
}
putchar( c );
}
else
{
digit = digitp - idigits;
if ( gettingi )
{
i = i * ibase + digit;
}
else
{
gettingi = 1;
i = digit;
}
}
}
if ( gettingi )
putint( i, obase );
exit( 0 );
}
void
putint( i, base )
int i, base;
{
if ( i >= base )
putint( i / base, base );
putchar( odigits[i % base] );
}koblas@mips.COM (David Koblas) (07/09/90)
Yet another base converter, but written as a replacement for atof.
Called as:
val = atov("0x123", 0);
val = atov("abz", 36);
Where the second argument is the default base, if == 0 then use
default conventions: 0x = 16, 0 = 8, 0% = binary, else base 10.
-----CUT---HERE----------------------------------------------------------
/* +------------------------------------------------------------------+ */
/* | Copyright 1989, David Koblas. | */
/* | You may copy this file in whole or in part as long as you | */
/* | don't try to make money off it, or pretend that you wrote it. | */
/* +------------------------------------------------------------------+ */
#include <ctype.h>
#ifdef TEST
main(argc,argv)
int argc;
char **argv;
{
int i;
for (i=1;i<argc;i++)
printf("%10s == %d\n",argv[i],atov(argv[i],0));
}
#endif
atov(str,type)
char *str;
int type;
{
int sign = 1;
int i;
char c;
int val=0,n;
i=0;
while ((str[i]==' ') || (str[i]=='\t')) i++;
if (str[i]=='-') {
sign = -1;
i++;
} else if (str[i]=='+') {
sign = 1;
i++;
}
if (type==0) {
if (str[i]=='0') {
i++;
if (str[i]=='%') {
i++;
type=2;
} else if (str[i]=='x') {
i++;
type=16;
} else {
type=8;
}
} else {
type=10;
}
}
for (;i<strlen(str);i++) {
c=str[i];
if (isdigit(c)) {
n = c - '0';
} else if (isupper(c)) {
n = c - 'A' + 10;
} else if (islower(c)) {
n = c - 'a' + 10;
} else {
goto out;
}
if (n>=type)
goto out;
val = (val*type)+n;
}
out:
return(val * sign);
}
--
name : David Koblas domain: koblas@cs.uoregon.edu
place: Nowhere, I'm just an AI batch job. domain: koblas@mips.com
quote: "Time has little to do with domain: koblas@riacs.edu
infinity and jelly donuts." domain: koblas@stellar.arc.nasa.gov