- 数学
SC校验码开源
- 2025-3-15 20:46:03 @
#include <iostream>
#include <vector>
#include <bitset>
#include <string>
#include <functional>
#include <conio.h>
#include <thread>
#include <mutex>
#include <atomic>
#include <clocale> // 用于支持多字节字符
#include <windows.h>
#define LOG cout << "更新日志:\n"<< "V2.1.1:\n"<< "1. 修复了多字节字符处理时的一个潜在问题\n"<< "2. 优化了多线程处理的性能\n"<< "3. 优化了代码结构\n"<< "4. 优化了用户交互\n"<< "5. 优化了输出格式\n"<< "6. 优化了代码可靠性\n"<< "7. 优化了代码可用性\n"<< "8. 优化了代码稳定性\n"<< "9. 优化了代码安全性\n"<< "10. 优化了代码性能\n";
using namespace std;
vector<int> prime; // 使用动态数组
mutex mtx; // 用于保护共享资源的互斥锁
void SieveOfEratosthenes(int n) {
vector<bool> isPrime(n + 1, true);
for (int p = 2; p <= n; ++p) {
if (isPrime[p]) {
prime.push_back(p);
for (long long i = p * (long long)p; i <= n; i += p)
isPrime[i] = false;
}
}
}
unsigned long long fastPow(unsigned long long base, unsigned long long exp, unsigned long long mod) {
unsigned long long result = 1;
base = base % mod;
while (exp > 0) {
if (exp & 1)
result = (result * base) % mod;
exp >>= 1;
base = (base * base) % mod;
}
return result;
}
unsigned long long generateSalt(const string& s) {
hash<string> hasher;
return hasher(s); // 使用字符串的哈希值作为盐值
}
unsigned long long hashWithSalt(unsigned long long value, unsigned long long salt, int iterations, unsigned long long mod) {
for (int i = 0; i < iterations; ++i) {
value = (value ^ salt) % mod; // 简单地将盐值与原值进行异或操作,并取模以防溢出
salt = (salt * 31 + i) % mod; // 更新盐值,模拟变化过程
}
return value;
}
// 全局变量,用于多线程共享
atomic<size_t> globalIndex{0}; // 当前处理的字符索引
unsigned long long globalCnt1 = 0, globalCnt2 = 0; // 全局的 cnt1 和 cnt2
unsigned long long mod = 1e9 + 7; // 防止溢出的模数
// 每个线程处理字符串的一部分
void processChunk(const string& s) {
while (true) {
size_t i = globalIndex.fetch_add(1); // 原子地获取当前字符索引
if (i >= s.size()) break; // 如果超出字符串范围,退出循环
// 处理多字节字符
unsigned char val = static_cast<unsigned char>(s[i]);
int charWidth = 1; // 默认字符宽度为 1 字节
if ((val & 0x80) != 0) { // 判断是否为多字节字符
if ((val & 0xE0) == 0xC0) charWidth = 2; // 2 字节字符
else if ((val & 0xF0) == 0xE0) charWidth = 3; // 3 字节字符
else if ((val & 0xF8) == 0xF0) charWidth = 4; // 4 字节字符
}
// 计算字符的值(将多字节字符视为一个整体)
unsigned long long charValue = 0;
for (int k = 0; k < charWidth; ++k) {
if (i + k >= s.size()) break; // 防止越界
charValue = (charValue << 8) | static_cast<unsigned char>(s[i + k]);
}
// 更新 cnt1 和 cnt2
unsigned long long localCnt1 = fastPow(charValue, prime[i % prime.size()], mod);
unsigned long long localCnt2 = charValue % mod;
// 使用互斥锁保护共享变量
lock_guard<mutex> lock(mtx);
globalCnt1 = (globalCnt1 + localCnt1) % mod;
globalCnt2 = (globalCnt2 + localCnt2) % mod;
// 跳过已处理的多字节字符
if (charWidth > 1) {
globalIndex.fetch_add(charWidth - 1);
}
}
}
int main() {
SetConsoleOutputCP(65001); // 设置控制台输出编码为 UTF-8
SetConsoleCP(65001); // 设置控制台输入编码为 UTF-8
setlocale(LC_ALL, ""); // 支持多字节字符
SieveOfEratosthenes(10000); // 获取素数
string s;
cout << "请输入字符串(输入空字符串将自动退出,输入~将提供更新日志):";
while (getline(cin, s) && !s.empty()) {
if (s == "~") {
cout << "按下Y以确认...\n";
char ch = _getch();
if (ch == 'Y' || ch == 'y') {
LOG
}
}
globalCnt1 = 0, globalCnt2 = 0; // 重置全局变量
globalIndex = 0; // 重置字符索引
// 设置线程数(根据硬件并发性调整)
unsigned int numThreads = thread::hardware_concurrency();
if (numThreads == 0) numThreads = 4; // 默认使用4个线程
vector<thread> threads;
// 创建线程并分配任务
for (size_t i = 0; i < numThreads; ++i) {
threads.emplace_back(processChunk, ref(s));
}
// 等待所有线程完成
for (auto& t : threads) {
t.join();
}
unsigned long long total = (globalCnt1 + globalCnt2) % mod;
unsigned long long salt = generateSalt(s); // 根据输入字符串生成盐值
total = hashWithSalt(total, salt, 10, mod); // 使用盐值和多次哈希增强安全性
cout << "校验码:\n16进制:0x" << hex << total << "\n"
<< "10进制:" << dec << total << "\n"
<< "2进制:" << bitset<64>(total) << endl;
cout << "按回车键继续... ";
cin.get(); // 等待用户按键输入
//cin.ignore(numeric_limits<streamsize>::max(), '\n'); // 清理输入缓冲区
cout << "\n请输入下一个字符串(输入空字符串将自动退出):";
}
return 0;
}
请确保你的电脑包含所需要的标准库
版权所有 2025 TengYve.Inc
Copyright 2025 TengYve.Inc
2 条评论
-
方均宸 LV 10 @ 2025-3-21 10:02:06已修改
V2.1.1更新内容
- 多线程
- 全局UTF-8
-
2025-3-15 20:46:50@
V2.1更新内容
1.支持UTF-8
2.加入盐值与Hash
#include <iostream> #include <vector> #include <bitset> #include <string> #include <functional> // For std::hash using namespace std; vector<int> prime; // 使用动态数组 void SieveOfEratosthenes(int n) { vector<bool> isPrime(n + 1, true); for (int p = 2; p <= n; ++p) { if (isPrime[p]) { prime.push_back(p); for (long long i = p * (long long)p; i <= n; i += p) isPrime[i] = false; } } } unsigned long long fastPow(unsigned long long base, unsigned long long exp, unsigned long long mod) { unsigned long long result = 1; base = base % mod; while (exp > 0) { if (exp & 1) result = (result * base) % mod; exp >>= 1; base = (base * base) % mod; } return result; } // 根据输入字符串生成一个固定的"盐值" unsigned long long generateSalt(const string& s) { hash<string> hasher; return hasher(s); // 使用字符串的哈希值作为盐值 } unsigned long long hashWithSalt(unsigned long long value, unsigned long long salt, int iterations, unsigned long long mod) { for (int i = 0; i < iterations; ++i) { value = (value ^ salt) % mod; // 简单地将盐值与原值进行异或操作,并取模以防溢出 salt = (salt * 31 + i) % mod; // 更新盐值,模拟变化过程 } return value; } int main() { SieveOfEratosthenes(10000); // 获取素数 string s; cout << "请输入字符串(输入空字符串将自动退出):"; while (getline(cin, s) && !s.empty()) { unsigned long long cnt1 = 0, cnt2 = 0, j = 0; const unsigned long long mod = 1e9 + 7; // 防止溢出的模数 for (size_t i = 0; i < s.size(); ++i) { unsigned char val = static_cast<unsigned char>(s[i]); // 对于每个字符,无论是ASCII还是多字节字符,都直接使用其数值 cnt1 = (cnt1 + fastPow(val, prime[j % prime.size()], mod)) % mod; cnt2 = (cnt2 + val) % mod; if (i != 0 && s[i] != s[i - 1]) { ++j; } } unsigned long long total = (cnt1 + cnt2) % mod; unsigned long long salt = generateSalt(s); // 根据输入字符串生成盐值 total = hashWithSalt(total, salt, 10, mod); // 使用盐值和多次哈希增强安全性 cout << "校验码:\n16进制:0x" << hex << total << "\n" << "10进制:" << dec << total << "\n" << "2进制:" << bitset<64>(total) << endl; cout << "按2次回车键继续... "; cin.get(); // 等待用户按键输入 cin.ignore(numeric_limits<streamsize>::max(), '\n'); // 清理输入缓冲区 cout << "\n请输入下一个字符串(输入空字符串将自动退出):"; } return 0; }
若想要全局UTF-8并且V2.1.1无法运行,请加上:
SetConsoleOutputCP(65001); // 设置控制台输出编码为 UTF-8 SetConsoleCP(65001); // 设置控制台输入编码为 UTF-8 setlocale(LC_ALL, ""); // 支持多字节字符
有概率导致无法使用
- 1