/*/////////////////////////////////
 Data Structure Assignment #1 
과제1:
 Operand의 크기가 너무커서 integer type으로 처리하지 못하는 더하기 연산을 integer 덧셈처럼 처리하는 프로그램을 작성하시오.
채점에 사용될 양식
예)
input.txt
21123424543254546575767868
+4235465475678687979797
2335344365547657
-345463574687
25434665457655765879
+4547568798080980
3543454
-46576985679
..
..
..
EOF
output.txt
325243436576970808976
3655765876987908606080
654768780900897979799
..
..
..
답 생성시 음수는 숫자앞에 '-'기호를 붙이셔야 됩니다. 
위의 방식으로 하겠습니다. 
값 사이의 줄 공백은 input 파일에서는 처리하셔야 되고 
처리가 안되어 있다면 '순서대로 2줄을 읽어들여' 처리하는 식으로 되어 있으면 됩니다. 
output파일에서의 공백은 처리 안하셨어도 됩니다.
*/
#include <fstream.h> // includes iostream.h
#include <string.h>  // for strcmp()
#define IN_FILE "C:\\input.txt" // don't forget to use double '\\' instead of '\'
#define OUT_FILE "C:\\output.txt"
#define MAX_LEN 200 // up to 200 chars (w/ cr & sign, +1)
#define POSITIVE 0
#define NEGATIVE 1
void mysort(char *mychar) // clear out spaces;
{
 int j=0;
 char temp[MAX_LEN]=""; // clearing garbages out (will temporary store cleared *mychar values)
 for (int i=0;i<=MAX_LEN+1;i++)
 {
  if (mychar[i]!=' ') temp[j++]=mychar[i]; // if the character is not a blank, than save to the temp.
 }
 strcpy(mychar, temp); // overwrite strings with 'blank removed' ones.
}  
int signcheck_rmv(char *mychar) // check sign and return 1 if it's negative, else 0.
{
 int ret_key=0;
 for (int i=0;i<=MAX_LEN+1;i++)
 {
  switch(mychar[i])
  {
  case '-':
   ret_key=1;     // if it's negative turn the flag on.
  case '+':
   mychar[i]=' '; // and then change the sign symbol to a blank.
   break;
  }
 }
 mysort(mychar); // call sort function to remove spaces
 
 return ret_key; // return 1 if it's negative, otherwise 0
}
void remove_zeros(char* output) // remove front zeros, ej) 001023 -> 1023
{
 char temp[MAX_LEN]="";
 strcpy(temp,output);
 for (int i=0;(unsigned)i<strlen(temp);i++) {
  if(temp[i]>='1') break;
  else temp[i]=' ';
 }
 mysort(temp);
 
 if (strcmp(temp,"")==0) strcpy(temp,"0"); // leave one '0', if output is null.
 strcpy(output,temp);
}
inline int bigger(int a, int b){ if(a>b) return a; else return b; }  // return bigger integer, else return first input.
void reform(char *mychar, int len) //digit count and modify 11 as 0011 to fit for 2222
{
 int j=len-strlen(mychar); //+1 is for case of increase of number over 10
 if (strlen(mychar)==(unsigned)len) {} //skip if strlen(mychar) is equal to itself.
 else {
  while(j--) {
   for (int i=len; i>=0; i--) //repeat as length of mychar.
   {
    if(i<=0) mychar[i]='0'; // put '0' to mychar[i] if [i] is 0.
    else mychar[i]=mychar[i-1]; //otherwise 
   }
  }
 }
}
void calculate_plus(char* a, char* b, char *output, int last) // calculate and saves value to *output
{
 int c=0;
 int inta, intb;
char temp[MAX_LEN]="";
 // digit count and modify 11 as 0011 to fit for 2222
 reform(a, last); 
 reform(b, last);
 reform(temp, last); 
 for (int i=1;i<=last;i++)
 {
  inta=a[last-i]-'0'; 
  intb=b[last-i]-'0'; // converts a character to an integer
  //cout<<"inta+intb:"<<inta+intb<<endl;
temp[last-i]=(((inta+intb)%10)+c)+'0'; // perform plus calculation
  if((inta+intb)/10) // if a+b is over 10, then we need to 
  {
   c=1;    // set flag to 1 which says the output is more than 10.
   if(i==last) // in case the output have more digit than input, like 999+999. 
   {
    reform(temp,strlen(temp)+1); // increase one more digit
    temp[0]='1';                 // then put 1 in front.
   }
  }
  else c=0; // otherwise reset the flag
 }
 remove_zeros(temp);
 strcpy(output,temp); // copy temp to output
}
void calculate_minus(char* a, char* b, char *output, int last) // calculate and saves value to *output
{
 int inta=0, intb=0, c=0;
 char temp[MAX_LEN]="";
 char my_a[MAX_LEN]="";
 char my_b[MAX_LEN]="";
 strcpy(my_a,a);
 strcpy(my_b,b);
 // count digit and modify 11 as 0011 to fit for 2222
 reform(temp, last); 
 reform(my_a, last); 
 reform(my_b, last); 
 for (int i=1;i<=last;i++)
 {
  if((my_a[last-i]-'0')==0) inta=0;
  else inta=(my_a[last-i]-'0');
  if((my_b[last-i]-'0')==0) intb=0;
  else intb=(my_b[last-i]-'0'); // converts a character to an integer
  if(inta-intb-c>=0)
  {
   temp[last-i]=(((inta-intb)%10)-c)+'0'; // perform minus calculation
   c=0;
  }
  else //if(inta-intb-c<0)
  {
   temp[last-i]=(inta-intb-c+10)+'0';
   c=1;
  }
 }
 remove_zeros(temp);
 strcpy(output, temp);
}
int calculate(char *a, char *b, char *output, int a_is_neg, int b_is_neg) //(unsigned)bigger number comes to a, return 1 when the answer is MINUS.
{
 char temp[MAX_LEN]="";
 int type_a=0, type_b=0, i;
 int len_a=strlen(a);
 int len_b=strlen(b);
 int last=bigger(len_a,len_b);
int a_size=1, b_size=1;
 if(len_a==len_b) // assume that we have same length, because we already reform(a)&(b)
 {
  for (i=0;i<=last;i++) // compare one by one
  {
   if(a[i]>b[i]) a_size*=(i+1); // +1 to prevent result is 0,  when i==0;
   if(b[i]>a[i]) b_size*=(i+1);
  }
  //cout<<"a_size: "<<a_size<<endl<<"b_size: "<<b_size<<endl;
  if(a_size>b_size)
  {
   if(a_is_neg) {calculate_minus(a,b,output,last); return NEGATIVE;} // when a_is_big and a_is_neg, output must be NEGATIVE
   if(b_is_neg) {calculate_minus(a,b,output,last); return POSITIVE;}
   calculate_plus(a,b,output,last); return POSITIVE;
  }
  if(b_size>a_size) //switch between (a,b) is occuring here.
  {
   if(b_is_neg) {calculate_plus(b,a,output,last); return NEGATIVE;} // when b_is_big and b_is_neg, output must be NEGATIVE
   if(a_is_neg) {calculate_plus(b,a,output,last); return POSITIVE;}
   calculate_plus(a,b,output,last); return POSITIVE;
  }
  calculate_plus(a,b,output,last); return POSITIVE;
 }
 int LONG=1;  //define as variable because we have to change later..
 int SHORT=0;
 //negative=1
 //positive=0
 if (len_a>len_b) { type_a=LONG; type_b=SHORT; }
 if (len_b>len_a) { type_b=LONG; type_a=SHORT; }
 if (a_is_neg) type_a+=NEGATIVE; else type_a+=POSITIVE;
 if (b_is_neg) type_b+=NEGATIVE; else type_a+=POSITIVE;
 
 // long-  type_x=2,
 // long+  type_x=1, 
 // short- type_x=1,
 // short+ type_x=0.
 // first determine two definite situation.
 // long+a(1) - short-b(1) = 0 // minus_calc, return POSITIVE
 // long+a(1) - short+b(0) = 1 // plus_calc, return POSITIVE
 // long-a(2) - short-b(1) = 1 // plus_calc, return NEGATIVE
 // long-a(2) - short+b(0) = 2 // minus_calc, return NEGATIVE
 // short+a(0) - long-b(2) = -2 // switch, minus_calc, return NEGATIVE
 // short+a(0) - long+b(1) = -1 // plus_calc, return POSITIVE
 // short-a(1) - long-b(2) = -1 // plus_calc, return NEGATIVE
 // short-a(1) - long+b(1) = 0 // switch, minus_calc, return NEGATIVE
// now arranging by output, we can see top 2 has distinctive output.
 // long-a(2) - short+b(0) = 2 // minus_calc, return NEGATIVE
 // short+a(0) - long-b(2) = -2 // switch, minus_calc, return NEGATIVE
 // long+a(1) - short-b(1) = 0 // minus_calc, return POSITIVE
 // short-a(1) - long+b(1) = 0 // switch, minus_calc, return NEGATIVE
 // long+a(1) - short+b(0) = 1 // plus_calc, return POSITIVE
 // long-a(2) - short-b(1) = 1 // plus_calc, return NEGATIVE
 // short+a(0) - long+b(1) = -1 // plus_calc, return POSITIVE
 // short-a(1) - long-b(2) = -1 // plus_calc, return NEGATIVE
 // so we can write:
 if ( (type_a-type_b) == 2 ) { calculate_minus(a,b,output,last); return NEGATIVE; }
 else if ( (type_a-type_b) == -2 ) { calculate_minus(b,a,output,last); return NEGATIVE; }
 // now we have 6 conditions left, so we change the calculation from a-b to a+b.
 // then we'll have two distinctive output from them.
 // long+a(1) + short-b(1) = 2 // minus_calc, return POSITIVE
 // short-a(1) + long+b(1) = 0 // switch, minus_calc, return NEGATIVE
 // long+a(1) + short+b(0) = 1 // plus_calc, return POSITIVE
 // long-a(2) + short-b(1) = 3 // plus_calc, return NEGATIVE
 // short+a(0) + long+b(1) = 1 // plus_calc, return POSITIVE
 // short-a(1) + long-b(2) = 3 // plus_calc, return NEGATIVE
 // so we can write:
 else if ( (type_a+type_b) == 2 ) { calculate_minus(a,b,output,last); return POSITIVE; }
 else if ( (type_a+type_b) == 0 ) { calculate_minus(b,a,output,last); return NEGATIVE; }
 // now we have 4 conditions left, so we change the definition of long
 // now change the def of long.
 else{
  LONG=10;
  type_a=type_b=0; //reset type_a and type_b
 
  // recalculate then.
  if (len_a>len_b) { type_a=LONG; type_b=SHORT; }
  if (len_b>len_a) { type_b=LONG; type_a=SHORT; }
  if (a_is_neg) type_a+=NEGATIVE; else type_a+=POSITIVE;
  if (b_is_neg) type_b+=NEGATIVE; else type_a+=POSITIVE;
 
  // LONG=10
  // SHORT=0
  // NEGATIVE=1
  // POSITIVE=0
  
  // which makes
  // long-  type_x=11,
  // long+  type_x=10, 
  // short- type_x=1,
  // short+ type_x=0.
 
  // we perform the plus calculations to determine next top two.
  // long+a(10) + short+b(0) = 10 // plus_calc, return POSITIVE
  // short+a(0) + long+b(10) = 10 // plus_calc, return POSITIVE
  
  // long-a(11) + short-b(1) = 12 // plus_calc, return NEGATIVE
  // short-a(1) + long-b(11) = 12 // plus_calc, return NEGATIVE
 
  // so we now can write:
  if ((type_a+type_b) == 10) { calculate_plus(a,b,output,last); return POSITIVE; }
  else { calculate_plus(a,b,output,last); return NEGATIVE; }
 }
 return POSITIVE; // return positive if the answer is 0 situation(a=b) like (111-111)=0
}
void main(void)
{
 char a[MAX_LEN]="";
 char b[MAX_LEN]="";
 char output[MAX_LEN]="";  // clearing out garbages
 // opening files...
 ifstream input_file(IN_FILE); //open file to read
 ofstream output_file(OUT_FILE); //open file to write
 if(input_file.fail()) //input file check
  cerr << "Error opening "<<IN_FILE<<endl;
 else if(output_file.fail()) //output file check
  cerr << "Error opening "<<OUT_FILE<<endl;
 else
 {
  while (! input_file.eof()) //loop starts to get lines, stops end of the file.
  {
   strcpy(output,""); // just in case if the line have odd number
   //read file by line
   input_file.getline(a, sizeof(a)); //get a line, when repeats get the next odd line
   input_file.getline(b, sizeof(b)); //get a next line, when repeats get the next even line
   if (strcmp(a,"EOF")==0 || strcmp(b,"EOF")==0) break; // break out loop when meets "EOF" string, no matter if there's more to read.
    // so, really doesn't matter either line number is on even, or odd.
 
   //calculation
   //remove the sign
   int is_a_neg=signcheck_rmv(a);
   int is_b_neg=signcheck_rmv(b);
   switch(calculate(a, b, output, is_a_neg, is_b_neg)) // check out whether output positive calculation or negative.
   {
   case NEGATIVE:
    reform(output,strlen(output)+1);
    output[0]='-';
   case POSITIVE:
    break;
   }
   //cout<<"a: "<<a<<endl<<"b: "<<b<<endl<<"o: "<<output<<endl;  // just for testing purpose.
   output_file<<output<<endl; // write a line to output file.
  }//end of eof checking loop
 }//end of input file error checking
 // closing files...
 input_file.close(); 
 output_file.close();
} //end of main(void)*/
'geek_stuff > today' 카테고리의 다른 글
| 1kko.com 블로그의 변천사 (0) | 2006.05.21 | 
|---|---|
| 자료구조 과제 #2 (0) | 2006.05.10 | 
| 심심해서 서버 하나를 뚫어봤다. (0) | 2006.05.08 | 
| Apple.com이 윈도우즈를 지원한다?! (2) | 2006.04.06 | 
| 숫자 generator 프로그램 (0) | 2006.03.27 |