“snprintf”: 找不到标识符

本文介绍了snprintf函数的使用方法及注意事项。snprintf函数类似于printf,用于格式化字符串并写入到指定大小的缓冲区中。文章说明了snprintf并非C/C++标准函数,在不同编译器中有不同的实现方式,如GCC中为snprintf,而在Visual Studio中为_snprintf。文中还给出了跨编译器兼容性的解决方案。

摘要生成于 C知道 ,由 DeepSeek-R1 满血版支持, 前往体验 >

snprintf()函数的格式跟printf差不多一样,是在c里面用的函数,包含在 #include <stdio.h>头文件中。

snprintf()函数并不是标准c/c++中规定的函数,所以在许多编译器中,厂商提供了其相应的实现的版本。在gcc中,该函数名称就snprintf(),而在VS中称为_snprintf。 所以在需要使用snprintf()时改成_snprintf就可以了,或则在预编译处加入:

#if _MSC_VER
#define snprintf _snprintf
#endif
#define _CRT_SECURE_NO_WARNINGS #define OPENSSL_API_COMPAT 10100 #include <stdio.h> #include <stdlib.h> #include <string.h> #include <openssl/evp.h> #include <ctype.h> #include <conio.h> // 用于getch()函数 enum { ALG_MD5, ALG_SHA256 }; // 修改函数返回类型和错误处理 int calc_hash(const char* filename, int alg, unsigned char* digest, const char** error_msg) { FILE* file = fopen(filename, "rb"); if (!file) { *error_msg = "打开文件失败"; return 0; } EVP_MD_CTX* ctx = EVP_MD_CTX_new(); if (!ctx) { fclose(file); *error_msg = "创建哈希上下文失败"; return 0; } const EVP_MD* md = (alg == ALG_MD5) ? EVP_md5() : EVP_sha256(); if (!EVP_DigestInit_ex(ctx, md, NULL)) { fclose(file); EVP_MD_CTX_free(ctx); *error_msg = "初始化哈希算法失败"; return 0; } unsigned char buffer[8192]; size_t bytes; while ((bytes = fread(buffer, 1, sizeof(buffer), file)) > 0) { if (!EVP_DigestUpdate(ctx, buffer, bytes)) { fclose(file); EVP_MD_CTX_free(ctx); *error_msg = "更新哈希失败"; return 0; } } unsigned int digest_len; if (!EVP_DigestFinal_ex(ctx, digest, &digest_len)) { fclose(file); EVP_MD_CTX_free(ctx); *error_msg = "获取最终哈希失败"; return 0; } fclose(file); EVP_MD_CTX_free(ctx); return 1; } char* to_hex(const unsigned char* hash, int len) { char* hex = (char*)malloc((len * 2) + 1); if (!hex) return NULL; for (int i = 0; i < len; i++) { snprintf(hex + (i * 2), 3, "%02x", hash[i]); } hex[len * 2] = '\0'; return hex; } int compare_hash(const char* hash1, const char* hash2) { if (!hash1 || !hash2) return 0; if (strlen(hash1) != strlen(hash2)) return 0; for (int i = 0; hash1[i] && hash2[i]; i++) { if (tolower((unsigned char)hash1[i]) != tolower((unsigned char)hash2[i])) return 0; } return 1; } // 修复:添加函数原型 int show_menu(const char* current_file, int current_alg); char* select_file(); // 修复:修改参数为 const char* int show_menu(const char* current_file, int current_alg) { system("cls"); // 清屏 (Windows) // system("clear"); // 如果是Linux/macOS使用这个 printf("\n ===============================\n"); printf(" 文件哈希校验工具 - 命令行交互版\n"); printf(" ===============================\n\n"); printf(" 当前文件: %s\n", current_file ? current_file : "未选择"); printf(" 当前算法: %s\n\n", current_alg == ALG_MD5 ? "MD5" : "SHA-256"); printf(" 请选择操作:\n"); printf(" 1. 选择文件\n"); printf(" 2. 切换算法 (当前: %s)\n", current_alg == ALG_MD5 ? "MD5" : "SHA-256"); printf(" 3. 计算哈希值\n"); printf(" 4. 验证文件完整性\n"); printf(" 5. 退出程序\n\n"); printf(" 输入选项 (1-5): "); int choice; if (scanf("%d", &choice) != 1) { // 清除输入缓冲区 while (getchar() != '\n'); return -1; } getchar(); // 消耗换行符 return choice; } // 修复:避免使用 strdup char* select_file() { char filename[256]; printf("\n 请输入文件路径 (或按回车返回): "); if (fgets(filename, sizeof(filename), stdin) == NULL) { return NULL; } // 去除换行符 size_t len = strlen(filename); if (len > 0 && filename[len-1] == '\n') { filename[len-1] = '\0'; } // 如果用户没有输入内容,返回NULL if (strlen(filename) == 0) { return NULL; } // 检查文件是否存在 FILE* file = fopen(filename, "r"); if (!file) { printf("\n ! 文件不存在或无法访问!\n"); printf(" 按任意键继续..."); getchar(); return NULL; } fclose(file); // 避免使用 strdup char* result = (char*)malloc(strlen(filename) + 1); if (result) { strcpy(result, filename); } return result; } int main() { char* filename = NULL; int alg = ALG_SHA256; // 默认算法 int running = 1; while (running) { int choice = show_menu(filename, alg); switch (choice) { case 1: { // 选择文件 char* new_file = select_file(); if (new_file) { if (filename) free(filename); filename = new_file; } break; } case 2: { // 切换算法 printf("\n 当前算法: %s\n", alg == ALG_MD5 ? "MD5" : "SHA-256"); printf(" 请选择新算法:\n"); printf(" 1. MD5\n"); printf(" 2. SHA-256\n"); printf(" 输入选项 (1-2): "); int alg_choice; if (scanf("%d", &alg_choice) != 1) { // 清除输入缓冲区 while (getchar() != '\n'); printf("\n ! 输入无效!\n"); break; } getchar(); // 消耗换行符 if (alg_choice == 1) { alg = ALG_MD5; printf("\n 算法已切换为 MD5\n"); } else if (alg_choice == 2) { alg = ALG_SHA256; printf("\n 算法已切换为 SHA-256\n"); } else { printf("\n ! 无效的选项!\n"); } printf(" 按任意键继续..."); getchar(); break; } case 3: { // 计算哈希值 if (!filename) { printf("\n ! 请先选择文件!\n"); printf(" 按任意键继续..."); getchar(); break; } unsigned char digest[32]; const char* error_msg = NULL; if (calc_hash(filename, alg, digest, &error_msg)) { const int digest_len = (alg == ALG_MD5) ? 16 : 32; char* hash_hex = to_hex(digest, digest_len); if (hash_hex) { printf("\n ===== 计算结果 =====\n"); printf(" 文件: %s\n", filename); printf(" 算法: %s\n", alg == ALG_MD5 ? "MD5" : "SHA-256"); printf(" 哈希值: %s\n", hash_hex); printf(" ====================\n"); free(hash_hex); } else { printf("\n ! 内存分配失败!\n"); } } else { printf("\n ! 计算失败: %s\n", error_msg); } printf("\n 按任意键继续..."); getchar(); break; } case 4: { // 验证文件完整性 if (!filename) { printf("\n ! 请先选择文件!\n"); printf(" 按任意键继续..."); getchar(); break; } char compare_hash_str[128]; printf("\n 请输入要比较的哈希值: "); if (fgets(compare_hash_str, sizeof(compare_hash_str), stdin) == NULL) { printf("\n ! 输入读取失败!\n"); break; } // 去除换行符 size_t len = strlen(compare_hash_str); if (len > 0 && compare_hash_str[len-1] == '\n') { compare_hash_str[len-1] = '\0'; } if (strlen(compare_hash_str) > 0) { unsigned char digest[32]; const char* error_msg = NULL; if (calc_hash(filename, alg, digest, &error_msg)) { const int digest_len = (alg == ALG_MD5) ? 16 : 32; char* hash_hex = to_hex(digest, digest_len); if (hash_hex) { printf("\n ===== 验证结果 =====\n"); printf(" 文件: %s\n", filename); printf(" 算法: %s\n", alg == ALG_MD5 ? "MD5" : "SHA-256"); printf(" 计算哈希值: %s\n", hash_hex); printf(" 提供哈希值: %s\n", compare_hash_str); if (compare_hash(hash_hex, compare_hash_str)) { // 使用Windows API设置颜色 HANDLE hConsole = GetStdHandle(STD_OUTPUT_HANDLE); SetConsoleTextAttribute(hConsole, 10); // 绿色 printf(" 结果: 文件完整\n"); SetConsoleTextAttribute(hConsole, 7); // 恢复默认 } else { HANDLE hConsole = GetStdHandle(STD_OUTPUT_HANDLE); SetConsoleTextAttribute(hConsole, 12); // 红色 printf(" 结果: 文件已被修改!\n"); SetConsoleTextAttribute(hConsole, 7); // 恢复默认 } printf(" ====================\n"); free(hash_hex); } else { printf("\n ! 内存分配失败!\n"); } } else { printf("\n ! 计算失败: %s\n", error_msg); } } else { printf("\n ! 未输入哈希值!\n"); } printf("\n 按任意键继续..."); getchar(); break; } case 5: // 退出程序 running = 0; break; default: if (choice != -1) { printf("\n ! 无效的选项!\n"); } printf(" 按任意键继续..."); getchar(); break; } } if (filename) free(filename); printf("\n 感谢使用文件哈希校验工具!再见!\n"); return EXIT_SUCCESS; } "HANDLE”:未声明的标识符 语法错误: 缺少”."(在标识符”hConsole"的前面 "hConsole”:未声明的标识符 "STD OUTPUT HANDLE”: 未声明的标识符 "GetStdHandle": 不到标识符 "hConsole: 未声明的标识符 “SetConsoleTextAttribute": 不到标识符 "hConsole": 未声明的标识符 "SetConsoleTextAttribute"”: 不到标识符 "HANDLE”: 未声明的标识符 语法错误: 缺少”"(在标识符”hConsole”的前面 "hConsole”: 未声明的标识符 "STD OUTPUT HANDLE”: 未声明的标识符 "GetStdHandle": 不到标识符 "hConsole": 未声明的标识符 "SetConsoleTextAttribute":不到标识符 "hConsole": 未声明的标识符 "SetConsoleTextAttribute": 不到标识特 报错了
06-02
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值