// w3.cpp : 定义控制台应用程序的入口点。
//

#include <stdio.h>
#include <string.h>
#include <stdlib.h>
#include <malloc.h>

#define max 256
int count=0;
/*
* 加1后进位操作 
* 用字符串模拟数字的进位操作
*/
void add_one(int *array, int array_len, int radio, int *flow)
{
        int i;
        for ( i=array_len-1; i>=0; i-- )
        {
                array[i] += 1;
                //没有进位就退出
                if (array[i] < radio) return; else array[i] = 0;                        
        }
        // 最高位溢出 - 标志进位操作已经结束
        (*flow) = 1;
}

/*
* 获取全排列 
*/
int get_pailie(char *set, int set_len, int sub_len, char *out,char** ccout, int out_len)
{
        int  end_flag = 0;
        int *array    = NULL;
        int  i = 0;
        if ( NULL==set || NULL==out || out_len<sub_len ) return -1;
        if ( (array=(int *)malloc(sub_len * sizeof(int))) == NULL ) return -2;
        // 初始化整数集合为0
        for( i=0; i<sub_len; i++ )  array[i] = 0;
        while( 1 != end_flag )
        {
                for(i=0; i<sub_len; i++)out[i] = set[array[i]];// 输出结果的每一位与它对应的数的每一位相同
                strcpy(ccout[count],out);
				count++;
				// 下标+1
                add_one(array, sub_len, set_len, &end_flag);
        }
        free(array);
        return 0;
}

void fconv(FILE* pfs,FILE* pfd,int gap,int subcount[],char* substr[],int* subcc)
{
	char  buffer[200000+1]={'\0'};  
	char  buf2[5]={'\0'};  
	fseek (pfs , 0 , SEEK_END);  
	long lSize = ftell (pfs);    //获取原始文件长度
	rewind (pfs);
	int i=0;
	long  result = fread (buffer,1,lSize,pfs);  //一次读入全部文件至字符数组
	for(i=0;i<max;i++) subcount[i]=0;  //初始化(存放每个字符串模出现的数量)的数组
	int j=0;
	while(buffer[j]!='\0')
    {
         strncpy(buf2,&buffer[j],4);  //每次copy 4个字符
         for(i=0;i<max;i++)
         {
	         if(strcmp(buf2,substr[i])==0)  //与已生成模进行比对
             {
                 subcount[i]++;
                 (*subcc)++;  //统计总模的数量
              }
         }
         j+=gap;  //自增步长(楼主所说的间隔)
    }
	////////////////////////////////////////////////
	char buf3[256]={'\0'};
	sprintf(buf3,"共有%d个子模体被扫描到.\n",*subcc);
	fwrite(buf3,sizeof(char),strlen(buf3),pfd);
	for(i=0;i<max;i++)
    {
        if(subcount[i]>0)
        {
			memset(buf3,'\0',256);
			sprintf(buf3,"%s--->出现了%d次\n",substr[i],subcount[i]);  //格式化字符串
			fwrite(buf3,sizeof(char),strlen(buf3),pfd);   //写目标文件
        }
    }
   
}

int main()
{
	char *set="ACGT";
	char  out[5] = {0};
	int   set_len = 4;
	int   sub_len = 4;
	char* ccout[max];
	for(int k=0;k<max;k++) ccout[k]=(char*)malloc(sizeof(char)*5);
	get_pailie(set, set_len, sub_len, out,ccout, sub_len);
	///////上述7行代码完成4模的填充 即4*4*4*4=256个模  这是一组全排列含自身重复的代码序列
	int subcount[max];
    char buffer[3]={'\0'};
    int gap=5;
    int subcc=0;
	FILE* pfile = fopen ("d:\\123.txt", "rb" );    //打开原始文件   即存放原始模的
	FILE* pfile2 = fopen ("d:\\12300.txt", "w+" );  //打开目标文件  即存放某个模出现N次
    fconv(pfile,pfile2,gap,subcount,ccout,&subcc);
	//以下释放指针及代码结束
   	for(int k=0;k<max;k++) free(ccout[k]);
	fclose(pfile);
	fclose(pfile2);
    return 0;
}