给@蕾米莉亞_斯卡雷特的代码演示
给@蕾米莉亞_斯卡雷特的代码演示
对于av号转bv号/bv号转av号 c语言一文中的代码
如何用30行代码实现几乎相同的功能

#include<stdio.h>
#include<stdlib.h>
int to_a[256],to_b[256],check_res,order[]= {9,8,1,6,2,4,0,7,3,5},data[]={13,12,46,31,43,18,40,28,5,54,20,15,8,39,57,45,36,38,51,42,49,52,53,7,4,9,50,10,44,34,6,25,1,26,29,56,3,24,0,47,27,22,41,16,11,37,2,35,21,17,33,30,48,23,55,32,14,19};
char input[13],cset[] ={"123456789ABCDEFGHJKLMNPQRSTUVWXYZabcdefghijkmnopqrstuvwxyz"};
int is_digit(char *s) {
for(char* ss=s; *ss; ss++)if('0'>*ss||*ss>'9')return 0;
return 1;
}//判断是不是纯数字(av号)
unsigned long long B_to_A(char* s) {
unsigned long long sum = 0;
for(int i=9; i>=0; i--)sum*=58,sum+=to_a[s[order[i]]];//order控制顺序
return (sum-100618342136696320)^0xa93b324;//这个异或等价于那十几行零一串的代码
}//转化为av号的等价代码
char* A_to_B(char* s) {
unsigned long long av = (strtoull(s,NULL,10)^0xa93b324)+100618342136696320;
for(int i=0; i<10; i++)s[order[i]]=to_b[av%58],av/=58;//直接和上面反过来
return s;
}//转化为Bv号的等价代码
int main() {
for(int i=0; i<58; i++) {
to_a[cset[i]] = data[i];
to_b[data[i]] = cset[i];//直接用数组索引建立双射
}
printf("请输入av/bv号:");
gets(input);//这里有一点不同的是,要求格式必须正确,然后去掉前两个字母
if(!is_digit(input+2))printf("您输入的bv号所对应的av号是:av%llu",B_to_A(input+2));
else printf("您输入的av号所对应的bv号是:BV%s",A_to_B(input+2));
}

这里提出几个思想,一是用数组保存加密的结果,建立映射,用索引直接访问,避免使用函数遍历(其实这样也更快了),然后个数位转换和顺序可以通过简单逻辑和循环实现。对于无符号长整形可以直接使用位运算(异或运算)以避免转化成二进制。
如果加入安全输入,即判断输入的格式是否合法,代码会变成60行(其实基本功能也就十多行,大部分还是输入和判断)。

#include<stdio.h>
#include<stdlib.h>
#include<string.h>
#include<ctype.h>
const int len = 58;
int to_a[256],to_b[256],check_res,order[]= {9,8,1,6,2,4,0,7,3,5},
data[]= {13,12,46,31,43,18,40,28,5,54,20,15,8,39,57,45,36,38,51,42,49,52,53,7,4,9,50,10,44,34,6,25,1,26,29,56,3,24,0,47,27,22,41,16,11,37,2,35,21,17,33,30,48,23,55,32,14,19};
char input[13],cset[] = {"123456789ABCDEFGHJKLMNPQRSTUVWXYZabcdefghijkmnopqrstuvwxyz"};
int is_digit(char *s) {
for(char* ss=s; *ss; ss++)if(!isdigit(*ss))return 0;
return 1;
}
int is_Bv(char *s) {
for(char* ss=s; *ss; ss++)if(!to_a[*ss])return 0;return 1;
}
int checkavOrBv(char* s) {
if(!*s)return -1;
char hat[13];
strncpy(hat,s,2);
strupr(hat);
if(!strcmp(hat,"av")) {
strcpy(s,s+2);
return is_digit(s)?1:-1;
} else if(!strcmp(hat,"BV")) {
strcpy(s,s+2);
return is_Bv(s)?0:-1;
} else return is_digit(s)?1:is_Bv(s)?0:-1;
}
unsigned long long B_to_A(char* s) {
unsigned long long sum = 0;
for(int i=9; i>=0; i--)sum*=len,sum+=to_a[s[order[i]]];
return (sum-100618342136696320)^0xa93b324;
}
char* A_to_B(char* s) {
unsigned long long av = (strtoull(s,NULL,10)^0xa93b324)+100618342136696320;
printf("%llu",strtoull(s,NULL,10));
for(int i=0; i<10; i++)s[order[i]]=to_b[av%len],av/=len;s[10]=0;
return s;
}
int main() {
for(int i=0; i<len; i++) {
to_a[cset[i]] = data[i];
to_b[data[i]] = cset[i];
}
printf("请输入av/bv号:");
while(true) {
gets(input);
if((check_res=checkavOrBv(input))==-1) {
printf("你输入的格式不正确,请重新输入:");
continue;
} else if(check_res==0)printf("您输入的bv号所对应的av号是:av%llu",B_to_A(input));
else printf("您输入的av号所对应的bv号是:BV%s",A_to_B(input));
break;
}
}

在av号超过0xFFFFFFF(十六进制)后两者结果会不一样,是正常现象,现在的av号也不会超过这个值。至于为什么不一样,可以自己思考一下。