C语言实现Base64算法

清华大佬耗费三个月吐血整理的几百G的资源,免费分享!....>>>

/*
Base64是一种基于64个可打印字符来表示二进制数据的表示方法。三个字节有24个比特,对应于4个Base64单元,即3个字节需要用4个可打印字符来表示。
当最后剩余一个八位字节(一个byte)时,最后一个6位的base64字节块有四位是0值,最后附加上两个等号;
如果最后剩余两个八位字节(2个byte)时,最后一个6位的base字节块有两位是0值,最后附加一个等号。
*/
#include <stdio.h>
#include "string.h"  
#include "stdlib.h"
   
const char base[] = "ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789+/=";
static char find_pos(char ch);
char *base64_encode(const char* data, int data_len,int *len);
char *base64_decode(const char* data, int data_len,int *len);  
   
/**
 *找到ch在base中的位置
 */
static char find_pos(char ch)   
{  
    //the last position (the only) in base[]
    char *ptr = (char*)strrchr(base, ch); 
    return (ptr - base);  
}   
   
/**
 *BASE64编码
 */
char *base64_encode(const char* data, int data_len,int *len)  
{     
    int prepare = 0;  
    int ret_len;  
    *len=0;
    int temp = 0;  
    char *ret = NULL;  
    char *f = NULL;  
    int tmp = 0;  
    char changed[4];  
    int i = 0;  
    ret_len = data_len / 3;  
    temp = data_len % 3;  
    if (temp > 0)  
    {  
        ret_len += 1;  
    }  
    //最后一位以''结束 
    ret_len = ret_len*4 + 1;  
    ret = (char *)malloc(ret_len);  
          
    if ( ret == NULL)  
    {  
        printf("No enough memory.n");  
        exit(0);  
    }  
    memset(ret, 0, ret_len);  
    f = ret;
    //tmp记录data中移动位置  
    while (tmp < data_len)  
    {  
        temp = 0;  
        prepare = 0;  
        memset(changed, 0, 4);  
        while (temp < 3)  
        {     
            if (tmp >= data_len)  
            {  
                break;  
            } 
            //将data前8*3位移入prepare的低24位 
            prepare = ((prepare << 8) | (data[tmp] & 0xFF));  
            tmp++;  
            temp++;  
        }  
        //将有效数据移到以prepare的第24位起始位置
        prepare = (prepare<<((3-temp)*8));  
           
        for (i = 0; i < 4 ;i++ )  
        {  
            //最后一位或两位
            if (temp < i)  
            {  
                changed[i] = 0x40;  
            }  
            else
            {  
                //24位数据
                changed[i] = (prepare>>((3-i)*6)) & 0x3F;  
            }  
            *f = base[changed[i]];  
      
            f++;
            (*len)++; 
        }  
    }  
    *f = '';  
          
    return ret;  
          
}
   
/**
 *BASE64解码
 */
char *base64_decode(const char *data, int data_len,int *len)  
{  
    int ret_len = (data_len / 4) * 3+1;  
    int equal_count = 0;  
    char *ret = NULL;  
    char *f = NULL;  
    *len=0;
    int tmp = 0;  
    int temp = 0;  
    char need[3];  
    int prepare = 0;  
    int i = 0;  
    if (*(data + data_len - 1) == '=')  
    {  
        equal_count += 1;  
    }  
    if (*(data + data_len - 2) == '=')  
    {  
        equal_count += 1;  
    }  
       
    ret = (char *)malloc(ret_len);  
    if (ret == NULL)  
    {  
        printf("No enough memory.n");  
        exit(0);  
    }  
    memset(ret, 0, ret_len);  
    f = ret;  
    while (tmp < (data_len - equal_count))  
    {  
        temp = 0;  
        prepare = 0;  
        memset(need, 0, 4);  
        while (temp < 4)  
        {  
            if (tmp >= (data_len - equal_count))  
            {  
                break;  
            }  
            prepare = (prepare << 6) | (find_pos(data[tmp]));  
            temp++;  
            tmp++;  
        }  
        prepare = prepare << ((4-temp) * 6);  
        for (i=0; i<3 ;i++ )  
        {  
            if (i == temp)  
            {  
                break;  
            }  
            *f = (char)((prepare>>((2-i)*8)) & 0xFF);  
            f++;
            (*len)++;  
        }  
    }
    *f = '';
    if(data[data_len-1]=='=')
    {
        (*len)--;
    }
    /*
    while(*(--f)=='')
    {
      (*len)--;
         
    }
    */
    return ret;  
}
int main(){
    char *former = "hello";
    int len1,len2;
    printf("%sn",former);
    char *after = base64_encode(former, 5,&len1);
    printf("%d %sn",len1,after);
    former = base64_decode(after, len1,&len2);
    printf("%d %sn",len2,former);
}