当了数据结构的助教,还要修改作业。在学生们的作业本上留下了对错号。但是没有写其他的东西。为了防止有学生来冒充我的笔迹来自行打对错号,然后声称没有给分这种现象的发生。我花了一个小时做了一个数字签名。因为我的笔迹很烂,很容易模仿。
代码如下:基本原理使用的Hash散列。所以不知道签名数据的人,绝对可能从自己作业的签名中获取签名数据,自然也不可能去冒充一个签名。
我使用的mysql的散列函数
#include
"
stdafx.h
"
#include < iostream >
#include < string >
using namespace std;
int iHTLen;
// mySql hash
unsigned int Hash ( const char * keys, const int len)
... {
const char * key = keys;
// Hash function for character keys
int length = len;
int nr=1, nr2=4;
while (length--)
...{
nr^= (((nr & 63)+nr2)*(*key++))+ (nr << 8);
nr2+=3;
}
return((unsigned int) nr) % iHTLen;
}
// just Test the consequence are correct or not
bool TestHashValue( const unsigned int hashValue[], int len)
... {
for(int i = 0; i < len; i++)
...{
for(int j = i+1; j < len; j++)
...{
if(hashValue[i] == hashValue[j])
...{
return false;
}
}
}
return true;
}
// guarantee the input values are not the same
bool TestPreValue( const string students[], int len)
... {
for(int i = 0; i < len; i++)
...{
for(int j = i+1; j < len; j++)
...{
if(students[i] == students[j])
...{
return false;
}
}
}
return true;
}
unsigned int Hash( string studentName, string date, string signer)
... {
int len = studentName.length()+date.length()+signer.length();
char * sign = new char[len];
memset(sign,0,len);
strcpy(sign,studentName.c_str());
strcat(sign,date.c_str());
strcat(sign,signer.c_str());
return Hash(sign,len);
}
int _tmain( int argc, _TCHAR * argv[])
... {
int num = 0;
cin >> num;
string* students = new string[num];
string signName;
string date;
for(int i = 0; i < num; i++)
...{
cin >> students[i];
}
cin >> date;
cin >> signName;
cin >> iHTLen;
bool isGoon = TestPreValue(students,num);
if(!isGoon)
...{
cout << "students' names are the same? "<<endl;
exit(2);
}
unsigned int* signNum = new unsigned int[num];
for(int i = 0; i < num; i++)
...{
signNum[i] = Hash(students[i],signName,date);
}
bool isSuccess = TestHashValue(signNum,num);
if(!isSuccess)
...{
cout << "please change the last value and run again!"<<endl;
exit(2);
}
for(int i = 0; i < num; i++)
...{
cout << students[i]<<" "<<signNum[i]<<endl;
}
return 0;
}
#include < iostream >
#include < string >
using namespace std;
int iHTLen;
// mySql hash
unsigned int Hash ( const char * keys, const int len)
... {
const char * key = keys;
// Hash function for character keys
int length = len;
int nr=1, nr2=4;
while (length--)
...{
nr^= (((nr & 63)+nr2)*(*key++))+ (nr << 8);
nr2+=3;
}
return((unsigned int) nr) % iHTLen;
}
// just Test the consequence are correct or not
bool TestHashValue( const unsigned int hashValue[], int len)
... {
for(int i = 0; i < len; i++)
...{
for(int j = i+1; j < len; j++)
...{
if(hashValue[i] == hashValue[j])
...{
return false;
}
}
}
return true;
}
// guarantee the input values are not the same
bool TestPreValue( const string students[], int len)
... {
for(int i = 0; i < len; i++)
...{
for(int j = i+1; j < len; j++)
...{
if(students[i] == students[j])
...{
return false;
}
}
}
return true;
}
unsigned int Hash( string studentName, string date, string signer)
... {
int len = studentName.length()+date.length()+signer.length();
char * sign = new char[len];
memset(sign,0,len);
strcpy(sign,studentName.c_str());
strcat(sign,date.c_str());
strcat(sign,signer.c_str());
return Hash(sign,len);
}
int _tmain( int argc, _TCHAR * argv[])
... {
int num = 0;
cin >> num;
string* students = new string[num];
string signName;
string date;
for(int i = 0; i < num; i++)
...{
cin >> students[i];
}
cin >> date;
cin >> signName;
cin >> iHTLen;
bool isGoon = TestPreValue(students,num);
if(!isGoon)
...{
cout << "students' names are the same? "<<endl;
exit(2);
}
unsigned int* signNum = new unsigned int[num];
for(int i = 0; i < num; i++)
...{
signNum[i] = Hash(students[i],signName,date);
}
bool isSuccess = TestHashValue(signNum,num);
if(!isSuccess)
...{
cout << "please change the last value and run again!"<<endl;
exit(2);
}
for(int i = 0; i < num; i++)
...{
cout << students[i]<<" "<<signNum[i]<<endl;
}
return 0;
}
幸好没有重名的学生。(*^__^*) 嘻嘻……
以上的代码使用VS2005的编译器。不过数据不方便透露,所以大家看懂代码可以自己输入自己的签名数据。大家不必在意Hash函数是如何去写的。因为我也不清楚为什么这样写。
以后改作业可以省心了。