給@蕾米莉亞_斯卡雷特的代碼演示
給@蕾米莉亞_斯卡雷特的代碼演示
對(duì)于av號(hào)轉(zhuǎn)bv號(hào)/bv號(hào)轉(zhuǎn)av號(hào) c語(yǔ)言一文中的代碼
如何用30行代碼實(shí)現(xiàn)幾乎相同的功能

#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;
}//判斷是不是純數(shù)字(av號(hào))?
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;//這個(gè)異或等價(jià)于那十幾行零一串的代碼?
}//轉(zhuǎn)化為av號(hào)的等價(jià)代碼
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;//直接和上面反過(guò)來(lái)?
return s;
}//轉(zhuǎn)化為Bv號(hào)的等價(jià)代碼?
int main() {
for(int i=0; i<58; i++) {
to_a[cset[i]] = data[i];
to_b[data[i]] = cset[i];//直接用數(shù)組索引建立雙射?
}
printf("請(qǐng)輸入av/bv號(hào):");
gets(input);//這里有一點(diǎn)不同的是,要求格式必須正確,然后去掉前兩個(gè)字母?
if(!is_digit(input+2))printf("您輸入的bv號(hào)所對(duì)應(yīng)的av號(hào)是:av%llu",B_to_A(input+2));
else printf("您輸入的av號(hào)所對(duì)應(yīng)的bv號(hào)是:BV%s",A_to_B(input+2));
}

????????這里提出幾個(gè)思想,一是用數(shù)組保存加密的結(jié)果,建立映射,用索引直接訪問(wèn),避免使用函數(shù)遍歷(其實(shí)這樣也更快了),然后個(gè)數(shù)位轉(zhuǎn)換和順序可以通過(guò)簡(jiǎn)單邏輯和循環(huán)實(shí)現(xiàn)。對(duì)于無(wú)符號(hào)長(zhǎng)整形可以直接使用位運(yùn)算(異或運(yùn)算)以避免轉(zhuǎn)化成二進(jìn)制。
????????如果加入安全輸入,即判斷輸入的格式是否合法,代碼會(huì)變成60行(其實(shí)基本功能也就十多行,大部分還是輸入和判斷)。

#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("請(qǐng)輸入av/bv號(hào):");
while(true) {
gets(input);
if((check_res=checkavOrBv(input))==-1) {
printf("你輸入的格式不正確,請(qǐng)重新輸入:");
continue;
} else if(check_res==0)printf("您輸入的bv號(hào)所對(duì)應(yīng)的av號(hào)是:av%llu",B_to_A(input));
else printf("您輸入的av號(hào)所對(duì)應(yīng)的bv號(hào)是:BV%s",A_to_B(input));
break;
}
}

在av號(hào)超過(guò)0xFFFFFFF(十六進(jìn)制)后兩者結(jié)果會(huì)不一樣,是正?,F(xiàn)象,現(xiàn)在的av號(hào)也不會(huì)超過(guò)這個(gè)值。至于為什么不一樣,可以自己思考一下。