#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-21 10:02:06

    V2.1.1更新内容

    1. 多线程
    2. 全局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