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