从十六进制字符串形成字符串

问题描述

我试图通过读取文件内容创建文件的哈希值,然后使用 SHA1 对其进行哈希处理,之后我尝试使用此哈希值创建一个文件名,但问题只有哈希值的前两个字符字符串被占用。 哈希函数

void hash(const std::string& content,std::string& retValue,bool isFile)
{
    SHA_CTX ctx;
    SHA1_Init(&ctx);
    SHA1_Update(&ctx,content.c_str(),content.size());
    if (isFile) {
        FILE* f = fopen(content.c_str(),"r");
        assert(f != NULL);
        char buffer[1024]={0};
        while(fgets(buffer,1024,f))
            SHA1_Update(&ctx,buffer,strlen(buffer));
        fclose(f);
    }

    unsigned char hash[SHA_DIGEST_LENGTH] = {0};
    SHA1_Final(hash,&ctx);
    retValue.resize(60);
    int cnt = 0;
    for(int i=0;i<SHA_DIGEST_LENGTH;i++){
        char ch[3] = {0};
        sprintf(ch,"%02x",hash[i]);
        retValue[cnt++] = ch[0];
        retValue[cnt++] = ch[1];
        retValue[cnt++] = ch[2];
    }
    std::cout<<retValue<<std::endl;
}

当我在控制台中打印哈希值时,我得到一个有效的 val,例如 51d946cde43e90ec03493f88914ca948b5215916,但在这种情况下它只包含前两个字符 '51',我切换到 gdb 来查看字符串,gdb 显示我以一种奇怪的方式将字符串 51\000d9\000\064\066\000cd\000e4\000\063e\000\071\060\000ec\000\060\063\000\064\071\000\063f\000\070\070\000\071\061\000\064c\000a9\000\064\070\000b5\000\062\06 1\000\065\071\000\061\066。我正在使用 std::ofstream 保存文件。我看过上一个答案,说这是 gdb 中的一个错误,所以它会像这样打印,但在这里我可以看到创建的文件不是只有第一个哈希字符。 为什么会这样?
谢谢。
- - - - - - - - - - - - - - - - - - - - - - - -编辑 - -------------------------------------------------- --------------------- 从 dvix评论来看,它得到了解决,我用 ch[2] 复制了 '\0',所以基本上我只需要从每个十六进制字符 ch[0] 和 ch[1] 复制前两个字符,然后放置null 在字符串的最后。 所以for循环里面的代码应该是这样的

for(int i=0;i<SHA_DIGEST_LENGTH;i++){
        char ch[3] = {0};
        sprintf(ch,hash[i]);
        retValue[cnt++] = ch[0];
        retValue[cnt++] = ch[1];
    }
    retValue[cnt] = '\0';

解决方法

这是一个稍微短一点的版本,它做同样的事情:

for(int i=0;i<SHA_DIGEST_LENGTH;i++){
        sprintf(retValue + cnt,"%02x",hash[i]);
        cnt += 2;
    }