/* longdiv.c: program to print out examples of "long-division" problems. * (Sure wish I had one of these in grade school.) * * By Terry R. McConnell 12/97 * * Usage: longdiv * Here both dividend and divisor must be positive integers. At some point * we should improve the program to handle decimal points, negative * numbers, and other bases, * but this should be sufficient to establish the concept. * * Dividend and divisor can be arbitrarily long, subject only to the size of * ARG_MAX on your system. POSIX.1 ensures that this is at least 4096 bytes. * I.e, this can handle REALLY LARGE division problems! * * A bit of useful terminology: * dividend = that which is divided into ( = numerator ). * divisor = that which is divided by ( = denominator ). * subtrahend = that which is subtracted. * minuend = that which is subtracted from. */ #define _POSIX_SOURCE #define USAGE "Usage: longdiv " #define DIGITS "123456789" #include #include #include #include #include #define TRUE 1 #define FALSE 0 #define RADIX 10 /* Actually, base 10 is assumed at many points in the pgm, so porting this to handle other bases will involve more than just changing this define. */ #define BORROW 1 #define NO_BORROW 0 /* The main routine is at the bottom, following a number of auxiliary routines. */ /* Subtracts digits and stores result in res. Returns indicator of whether or not borrow is needed. */ int sub( char x, char y, char *res) { if( x >= y){ *res = '0' + x - y; return FALSE; } *res = '0' + x - y + 10; return TRUE; } /* Isgte: returns TRUE if first digit string is >= the second */ int isgte( char *A, char *B) { int a,b,i; char *AA, *BB; if(B==NULL) return TRUE; if(A==NULL) return FALSE; /* Normalize by stripping off leading zeros */ AA = strpbrk(A,DIGITS); BB = strpbrk(B,DIGITS); if(BB == NULL) return TRUE; if(AA == NULL) return FALSE; if((b=strlen(BB ))>(a=strlen(AA)))return FALSE; if(a > b) return TRUE; for(i=0;iBB[i]) return TRUE; if(AA[i]= shend, this returns a pointer to the string corresponding to minuend - subtrahend. Returns NULL if minuend < subtrahend. Result array is padded with leading zeros. */ char *sbc(char *mend, char *shend) { int need_borrow = FALSE; int lm,ls,i; char *res; char *mnd,*p; if(!isgte(mend,shend))return NULL; lm = strlen(mend); ls = strlen(shend); res = (char *)malloc(strlen(mend)+1); if(res == NULL){ fprintf(stderr,"sbc: Unable to malloc space for result\n"); exit(1); } p = mnd = (char *)malloc(strlen(mend)+1); if(mnd == NULL){ fprintf(stderr,"sbc: Unable to malloc\n"); exit(1); } strcpy(mnd,mend); /* Fill result array with digit zero */ for(i=0;i k ? k : n ); res = (char *)calloc(sizeof(char),(k+1)); if(res == NULL){ fprintf(stderr,"cut_off: Unable to malloc\n"); return NULL; } strncpy(res,source,k); return res; } int main(int argc, char **argv) { int dsr_len,ddnd_len; int dgts_fwd; /* digits carried forward from previous step */ int i,j,k; int step = 0; char *quotient; char *dsr; /* Divisor */ char *ddnds[ARG_MAX]; /* Successive dividends */ char *shends[ARG_MAX]; /* Successive subtrahends */ char *mend; /* Current minuend: see example below */ char *pend; /* Points to 1st char beyond current minuend */ char *ptr; if(argc != 3){ fprintf(stderr,"%s\n", USAGE); return FALSE; } /* Do sanity checks on args */ for(i=0; i='1';i--){ shends[step] = times_digit(dsr,i); if(isgte(mend,shends[step]))break; free(shends[step]); } /* Insert the new digit in the quotient. */ quotient[strlen(quotient)]=i; /* Now, subtract the current subtrahend from the current minuend, and splice the result with pend to form the next dividend */ ptr = sbc(mend,shends[step]); if(strpbrk(ptr,DIGITS)==NULL)dgts_fwd = 0; else dgts_fwd = strlen(strpbrk(ptr,DIGITS)); /* A special situation arises here if dgts_fwd = 0 and pend points to a zero: since we strip off leading zeros when defining the new dividend, we would miss the need to append zero digits to the quotient. */ if(dgts_fwd == 0) while ((*pend == '0') && (*pend != '\0')){ strcat(quotient,"0"); pend++; } ddnds[step+1] = strpbrk(splice(ptr,pend), DIGITS); if(ddnds[step+1]==NULL){ ddnds[step+1]= malloc(2*sizeof(char)); strcpy(ddnds[step+1],"0"); } free(mend); step++; } /* repeat with new dividend */ /* Add any necessary trailing zeros to quotient */ j = strlen(quotient); for(i=0;i