#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 条评论

  • @ 2025-3-23 10:13:11

    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, ""); // 支持多字节字符
    
    

    有概率导致无法使用

    • @ 2025-3-23 10:13:02

      V2.1.1更新内容

      1. 多线程
      2. 全局UTF-8
      • 1