#include<stdio.h>
#include<ctype.h>
#include<conio.h>
#include<stdlib.h>
#include<alloc.h>

char* zpliku(char*,unsigned long int*);
char* odwroc(char*,unsigned long int);
char* mnozenie(unsigned long int,unsigned long int,unsigned long int*,char*,char*,char*);
int dopliku(char*,unsigned long int,char* );

int main(int argc,char *argv[])
{
   char *liczba1,*liczba2,*wynik;//wskazniki na poszczegolne tablice
   unsigned long int rozm1,rozm2,rozmwyn,i; //rozmiary poszczegolnych tablic
   clrscr();
   printf("\n\n===============================================\n");
   printf("\n PROGRAM MNOZACY LICZBY W SYSTEMIE SIODEMKOWYM\n");
   printf("\n===============================================\n\n\n\n");
   if((liczba1=zpliku("C:\\plik1.txt",&rozm1))==NULL) return(EXIT_FAILURE);//wczytanie z pliku pierwszej liczby, jesli sie nie uda wyjscie z programu
   if((liczba2=zpliku("C:\\plik2.txt",&rozm2))==NULL) return(EXIT_FAILURE);//wczytanie z pliku drugiej liczby, jesli sie nie uda wyjscie z programu
   if((wynik=mnozenie(rozm1,rozm2,&rozmwyn,liczba1,liczba2,wynik))==NULL) return(EXIT_FAILURE);//mnozenie liczb
   wynik=odwroc(wynik,rozmwyn);//odwrocenie elementow w tablicy, ostatni zamieniany jest z pierwszym itd.
   if(!dopliku(wynik,rozmwyn,"C:\\wynik.txt")) //zapis wyniku do pliku
      printf("\nWynik mnozenia znajduje sie w pliku c:\\wynik.txt");
   if(liczba1) free(liczba1);//zwolnienie pamieci tablicy przechowujacej pierwsza liczbe
   if(liczba2) free(liczba2);//zwolnienie pamieci tablicy przechowujacej druga liczbe
   if(wynik) free(wynik);//zwolnienie pamieci tablicy przechowujacej wynik
   getch();//zatrzymanie ekranu
   return(0);
}

char* zpliku(char *nazwa,unsigned long int *i)//wczytywanie liczb z pliku do tablicy
{
  unsigned long int max=0;
  FILE *fp;
  int c;
  char *tab; //wskaznik na tablice
  *i=0;//licznik wczytanych znakow
  tab=(char*)malloc(50*sizeof(char));//alokacja pamieci dla tablicy, poczatkowo pamiec jest przydzielona na 50 znakow
  if(!tab)
  {
     printf("\nBˆ¥d alokacji pami©ci.");
     return(NULL);   //jesli alokacja sie nie powiedzie wyjscie z funkcji
  }
  if((fp=fopen(nazwa,"r"))==NULL)//otwarcie pliku do odczytu
    {
       printf("\nBˆ¥d otwarcia pliku %s.",nazwa);
       return(NULL); //jesli sie nie udalo wyjscie z funkcji
    }
  else
  {
     while((c=fgetc(fp))!=EOF)  //pobranie znaku z pliku
     {
	if(!isdigit(c)||(c-'0')>6) //kontrola poprawnosci formatu
	{
	   free(tab);
	   printf("\nLiczba zapisana w pliku %s nie jest liczb¥ si¢demkow¥. ",nazwa);
	   return(NULL);
	}
	if(*i==max)
	{
	   tab=(char*)realloc(tab,(*i+50)*sizeof(char));//jesli wczytano juz 50 znakow jest alokowana pamiec na kolejne 50 znakow
	   if(!tab)
	   {
	     printf("\nBˆ¥d alokacji pami©ci.");
	     return(NULL);
	   }
	   max+=50;
	}
	tab[*i]=c-'0';(*i)++;//zapis liczby odpowiadajacej danemu znakowi do tablicy
     }
     tab=(char*)realloc(tab,(*i)*sizeof(char));//koncowa realokacja pamieci, w tym momencie znany jest juz rozmiar tablicy
     fclose(fp);//zamknieci pliku
  }
  tab=odwroc(tab,*i);//odwrocenie kolejnosci liczb w tablicy
		    //przy wykonywaniu mnozenia korzystniej jest jesli
		    //pierwszy element tablicy jest najmniej znaczaca cyfra liczby
  return(tab);//funkcja zwraca wskaznik do tablicy
}

char* odwroc(char *tab,unsigned long int max)//odwrocenie kolejnosci liczb w tablicy
{
  char *pom=tab; //wskaznik na poczatek tablicy
  char *kon=&tab[max-1],c; //wskaznik na koniec tablicy
  while(pom<kon) //dopuki wskazniki sie nie mina
  {
    c=*pom;        //zamiana elementow
    *pom=*kon;
    *kon=c;
    ++pom;--kon;
  }
    return(tab);
}

char* mnozenie(unsigned long int lA,unsigned long int lB,unsigned long int *lW,char *A,char *B,char *W)
{
  char *buf,przenies,nadmiar,temp;
  unsigned long int i,j,k,m;

  (*lW)=lA+lB+1;//maksymalny rozmiar wyniku=rozmiar 1 liczby +rozmiar 2 liczby + 1
  W=(char*)calloc((*lW),sizeof(char));//alokacja pamieci na wynik
  if(!W)
  {
     printf("\nBˆ¥d alokacji pami©ci.");
     return(NULL); //jesli alokacja sie nie powiodla wyjscie z funkcji
  }
  buf=(char*)calloc((lA+1),sizeof(char));//alokacja pamieci na bufor wykorzystywany podczas mnozenia
  if(!buf)
  {
     printf("\nBˆ¥d alokacji pami©ci.");
     return(NULL); //jesli alokacja sie nie powiodla wyjscie z funkcji
  }

  //mnozenie
  k=0;//przesuniecie bufora wzgledem wyniku
  for(i=0;i<lB;i++)//dopuki i mniejsze niz rozmiar drugiej liczby
    {
      for(j=0;j<(lA+1);j++) buf[j]=0;  //wyzerowanie bufora
      przenies=0;//poczotkowo przeniesienie rowne zero
      for(j=0;j<lA;j++)//dopuki j mniejsze od rozmiaru bufora
      {
	 if(B[i]==0) break;//jesli cyfra drugiej liczby jest rowna zero to nie mnoz tylko ja przeskocz
	 buf[j]=(A[j]*B[i]+przenies)%7;//zapisywane na aktualnej pozycji w buforze
	 przenies=(A[j]*B[i]+przenies)/7;//przeniesienie do nastepnej pozycji
      }
	buf[j]=przenies;//dopisz przeniesienie koncowe

	//sumowanie bufora z wynikiem
	nadmiar=0;//przeniesienie do nastepnej pozycji
	for(m=0+k;m<(*lW);m++) //dopuki m mniejsze od rozmiaru wyniku
	   {
	      if((m-k)<(lA+1))   //jesli istnieje pozycja m w buforze to dodaj
	      {
		temp=W[m];
		W[m]=(W[m]+buf[m-k]+nadmiar)%7;
		nadmiar=(temp+buf[m-k]+nadmiar)/7;
	      }
	      else  //jesli m wieksze niz rozmiar bufora to przepisz dalsza czesc wyniku
	      {
		W[m]=(W[m]+nadmiar)%7;
		nadmiar=(W[m]+nadmiar)/7;
	      }
	   }

	k++;// zwiekszenie przesuniecia
    }
    if(buf) free(buf);//zwolnienie pamieci bufora
    return(W);//funkcja zwraca wskaznik do tablicy zawierajacej wynik
}

int dopliku(char *tab,unsigned long int n,char *nazwa)//zapis do pliku
{
   unsigned long int i;
   FILE *fp;
   char c;
   if((fp=fopen(nazwa,"wb"))==NULL) //otwarcie pliku do zapisu
   {
     printf("\nBlad otwarcia pliku %s",nazwa);
     return(1); //jesli wystapil blad wyjscie z funkcji
   }
   for(i=0;i<n;i++)
    {
       switch(tab[i])   //zamiana liczby na odpowiedni znak
       {
	 case 0: c='0';break;
	 case 1: c='1';break;
	 case 2: c='2';break;
	 case 3: c='3';break;
	 case 4: c='4';break;
	 case 5: c='5';break;
	 case 6: c='6';break;
       }
       putc(c,fp);//zapis znaku do pliku

    }
   return(0);

}