S
sugaray
hi, i wrote a simple base-conveter utility for practice, it seems
works fine right now, hope any gurus out there can give me some
suggestions to, critics of, optimisations on this program or my
programming practice. the code are mainly written in C, but need to be
compiled using a C++ compiler because of the using of builtin Boolean
type. it has been tested under VC7 and GCC 3.3.1. thanx in advance.
/////////////////////// code start /////////////////////
#include <math.h>
#include <stdio.h>
#include <stdlib.h>
#include <ctype.h>
#include <string.h>
typedef enum {DEC,OCT,HEX,UNKNOWN} BASE; // test for the base of the
user input
static char *TrimLeadingZero(char *s) {
char *tmp=s;
while(*tmp=='0') tmp++;
return tmp;
}
static bool isHexChar(char c) {
return ((c>='a' && c<='f')||(c>='A' && c<='F')); // whether a valid
hex char
}
static bool isHexString(char *s) {
char *tmp=s;
size_t l,i;
if((l=strlen(s))==0) // expect no empty strings
return false;
for(i=0;i<l;++i)
if(!isHexChar(tmp) && !isdigit(tmp)) // neither a valid hex
char nor a digit
return false;
return true;
}
static int Hex2Dec(char hex) {
if(isupper(hex))
return hex-'7'; // upper hex chars to integers
else if(islower(hex))
return hex-'W'; // lower hex chars to integers
else return hex-'0'; // digit chars to their corresponding integers
}
static int HexString2Int(char *s) {
char *tmp;
tmp=TrimLeadingZero(s);
int i,t;
int n=0;
size_t l=strlen(tmp);
for(i=l-1;i>=0;--i) {
t=Hex2Dec(*tmp);
if(t==0) {
tmp++;
continue; // jump out if is 0
}
n+=t*(int)pow(16,i);
++tmp;
}
return n;
}
static bool isOctChar(char c) {
return (c>='0' && c<='7'); // whether a valid octal char
}
static int Oct2Dec(char c) {
return c-'0'; // octal to it's corresponding decimal
integer
}
static bool isOctString(char *s) {
char *tmp=s;
if(strlen(s)==0)
return false;
while(*tmp!='\0') {
if(!isOctChar(*tmp))
return false;
++tmp;
}
return true;
}
static int OctString2Int(char *s) {
char *tmp;
tmp=TrimLeadingZero(s);
size_t l=strlen(tmp);
int i,t;
int n=0;
for(i=l-1;i>=0;--i) {
t=Oct2Dec(*tmp);
if(t==0) {
++tmp;
continue;
}
n+=t*(int)pow(8,i);
tmp++;
}
return n;
}
static BASE Base(char *nstr) {
char input[64];
strcpy(input,nstr);
if(input[0]=='0') // case for hex or octal
if(input[1]=='x' || input[1]=='X') // hex
return HEX;
else return OCT; // octal
else if(isdigit(input[0]) && input[0]!='0') // decimal
return DEC;
else return UNKNOWN; // unknown base
}
static void MakeAFuss(void) {
fprintf(stderr,"Hey pal, what the hell's that ?\n");
}
int main(int argc,char **argv)
{
BASE base;
char tmp[64]={0};
int integer;
if(argc!=2) {
fprintf(stderr,"Usage:\n\t%s <number>\n",argv[0]);
return 1;
}
base=Base((char *)argv[1]);
switch(base) {
case DEC:
printf("%#x\t%#o\n",atol(argv[1]),atol(argv[1]));
break;
case OCT:
strcpy(tmp,&argv[1][1]); // strip the oct-base header '0'
if(isOctString(tmp)) {
integer=OctString2Int(tmp);
printf("%u\t%#x\n",integer,integer);
}
else MakeAFuss();
break;
case HEX:
strcpy(tmp,&argv[1][2]); // strip the hex-base header '0x' or '0X'
if(isHexString(tmp)) {
integer=HexString2Int(tmp);
printf("%u\t%#o",integer,integer);
}
else MakeAFuss();
break;
default:
MakeAFuss();
}
return 0;
}
////////////////////// code end /////////////////////////
works fine right now, hope any gurus out there can give me some
suggestions to, critics of, optimisations on this program or my
programming practice. the code are mainly written in C, but need to be
compiled using a C++ compiler because of the using of builtin Boolean
type. it has been tested under VC7 and GCC 3.3.1. thanx in advance.
/////////////////////// code start /////////////////////
#include <math.h>
#include <stdio.h>
#include <stdlib.h>
#include <ctype.h>
#include <string.h>
typedef enum {DEC,OCT,HEX,UNKNOWN} BASE; // test for the base of the
user input
static char *TrimLeadingZero(char *s) {
char *tmp=s;
while(*tmp=='0') tmp++;
return tmp;
}
static bool isHexChar(char c) {
return ((c>='a' && c<='f')||(c>='A' && c<='F')); // whether a valid
hex char
}
static bool isHexString(char *s) {
char *tmp=s;
size_t l,i;
if((l=strlen(s))==0) // expect no empty strings
return false;
for(i=0;i<l;++i)
if(!isHexChar(tmp) && !isdigit(tmp)) // neither a valid hex
char nor a digit
return false;
return true;
}
static int Hex2Dec(char hex) {
if(isupper(hex))
return hex-'7'; // upper hex chars to integers
else if(islower(hex))
return hex-'W'; // lower hex chars to integers
else return hex-'0'; // digit chars to their corresponding integers
}
static int HexString2Int(char *s) {
char *tmp;
tmp=TrimLeadingZero(s);
int i,t;
int n=0;
size_t l=strlen(tmp);
for(i=l-1;i>=0;--i) {
t=Hex2Dec(*tmp);
if(t==0) {
tmp++;
continue; // jump out if is 0
}
n+=t*(int)pow(16,i);
++tmp;
}
return n;
}
static bool isOctChar(char c) {
return (c>='0' && c<='7'); // whether a valid octal char
}
static int Oct2Dec(char c) {
return c-'0'; // octal to it's corresponding decimal
integer
}
static bool isOctString(char *s) {
char *tmp=s;
if(strlen(s)==0)
return false;
while(*tmp!='\0') {
if(!isOctChar(*tmp))
return false;
++tmp;
}
return true;
}
static int OctString2Int(char *s) {
char *tmp;
tmp=TrimLeadingZero(s);
size_t l=strlen(tmp);
int i,t;
int n=0;
for(i=l-1;i>=0;--i) {
t=Oct2Dec(*tmp);
if(t==0) {
++tmp;
continue;
}
n+=t*(int)pow(8,i);
tmp++;
}
return n;
}
static BASE Base(char *nstr) {
char input[64];
strcpy(input,nstr);
if(input[0]=='0') // case for hex or octal
if(input[1]=='x' || input[1]=='X') // hex
return HEX;
else return OCT; // octal
else if(isdigit(input[0]) && input[0]!='0') // decimal
return DEC;
else return UNKNOWN; // unknown base
}
static void MakeAFuss(void) {
fprintf(stderr,"Hey pal, what the hell's that ?\n");
}
int main(int argc,char **argv)
{
BASE base;
char tmp[64]={0};
int integer;
if(argc!=2) {
fprintf(stderr,"Usage:\n\t%s <number>\n",argv[0]);
return 1;
}
base=Base((char *)argv[1]);
switch(base) {
case DEC:
printf("%#x\t%#o\n",atol(argv[1]),atol(argv[1]));
break;
case OCT:
strcpy(tmp,&argv[1][1]); // strip the oct-base header '0'
if(isOctString(tmp)) {
integer=OctString2Int(tmp);
printf("%u\t%#x\n",integer,integer);
}
else MakeAFuss();
break;
case HEX:
strcpy(tmp,&argv[1][2]); // strip the hex-base header '0x' or '0X'
if(isHexString(tmp)) {
integer=HexString2Int(tmp);
printf("%u\t%#o",integer,integer);
}
else MakeAFuss();
break;
default:
MakeAFuss();
}
return 0;
}
////////////////////// code end /////////////////////////