C语言写入十六进制字符串到文件出现乱码问题排查
问题
我希望创建一个每行包含一个新字符串密钥的文本文件program.txt,但运行以下C语言代码后,生成的文件出现乱码。请问代码哪里出错了?
原代码
#include <stdio.h> #include <stdlib.h> #include <time.h> #include <unistd.h> #include <fcntl.h> #include <string.h> #define KEYSIZE 16 int main(){ FILE *fptr; fptr = fopen("program.txt", "w"); if (fptr == NULL) { printf("Error!"); exit(1); } int num_keys = 1524006529 - 1523999329; const char *keys[num_keys]; int idx = 0; int j; for (j = 1523999329; j<= 1524006529; j++){ int i; char key[KEYSIZE]; srand (j); for (i = 0; i< KEYSIZE; i++){ key[i] = rand()%256; printf("%.2x", (unsigned char)key[i]); fprintf(fptr, "%.2x", (unsigned char)key[i]); } fprintf(fptr, "%s", " "); printf(" "); keys[idx] = key; idx ++; } fclose(fptr); return 0; }
生成的乱码内容
h?G??+? Mp???+?? a?G????#*Jb`e0?H?????G?????? S6&}?Μ??G??OFf??|???s8f?G????ɼ???5q??(???K?G?? ??J????9?+???G?????cZ?n0?Jr?G?????#O9]??????jH??G???krT?̇)?A ?g?v?G??????h^(?^? û/?G???^vB?~W?39???G??\????"?iJ_????G??p??>??????I???U?G????????:??o?RV???G??/?C?^?????|?۬?G??q@0.L$+??Nv?????G????u? L?Ϩ????dv?G??[??C「<?i???G??UyM??Ƭ/??CxXUě?G?????φ :W&?G????=J???o???I??G???G%DA+"?~5?Z¡?G??øL#??O=e?b?u.O?G????*jjɥ+T?)?օ?G??2w }a,ȃ??tC?s?G??J"/c??Mn???f?y??G????p?Ay?c????~"<??G?????Ӆ?=%??@???G??o?\??<w???4WϚBE?G??}oh??(??#HK???&?G????Vfz ???e?s?G??/?Ye??iV?؛?,-te?G??I?Ҁx??5?B!b?4?G??6Z??9?P?GcB?}???Y?~|"??dd??G??????=?ms? ??G?????^??[H??\:???G??2(J??A??????G???????o#?i?/???G??P?5?5?5X??
错误分析及修正
1. 换行符写入错误(直接导致乱码)
原代码中fprintf(fptr, "%s", " ");和printf(" ");的写法完全错误。C语言里字符串常量不能直接换行,这种写法会被编译器解析为无效字符串,实际写入文件的不是换行符\n,而是乱码字符。
修正方式:将换行写法改为标准的"\n":
fprintf(fptr, "\n"); printf("\n");
2. 局部变量指针悬空(严重未定义行为)
keys[idx] = key;把循环内的局部数组key的地址存入keys数组,但key是栈上的局部变量,每次循环结束后内存会被释放,keys里的指针都会变成无效的悬空指针,后续使用会触发未定义行为(虽不直接导致乱码,但必须修复)。
修正方式:若要保存密钥,需为每个密钥动态分配内存并复制内容:
// 先动态分配存储指针的数组 char** keys = malloc(num_keys * sizeof(char*)); // 循环内复制key内容 keys[idx] = malloc(KEYSIZE); memcpy(keys[idx], key, KEYSIZE); // 程序结束前释放内存 for(int i=0; i<num_keys; i++) free(keys[i]); free(keys);
3. 字符类型符号问题
char key[KEYSIZE];中的char在多数系统是有符号类型(范围-128127),但`rand()%256`生成0255的数值,超过127的数值会被当作负数存储,后续操作可能出问题。
修正方式:改用unsigned char定义key:
unsigned char key[KEYSIZE];
修正后的完整代码
#include <stdio.h> #include <stdlib.h> #include <time.h> #include <unistd.h> #include <fcntl.h> #include <string.h> #define KEYSIZE 16 int main(){ FILE *fptr; fptr = fopen("program.txt", "w"); if (fptr == NULL) { printf("Error!"); exit(1); } int num_keys = 1524006529 - 1523999329; // 动态分配存储密钥指针的数组(不需要保存密钥可删除此行) char** keys = malloc(num_keys * sizeof(char*)); int idx = 0; int j; for (j = 1523999329; j<= 1524006529; j++){ int i; unsigned char key[KEYSIZE]; srand(j); for (i = 0; i< KEYSIZE; i++){ key[i] = rand()%256; printf("%.2x", key[i]); fprintf(fptr, "%.2x", key[i]); } // 写入正确的换行符 fprintf(fptr, "\n"); printf("\n"); // 复制密钥到动态内存(不需要保存密钥可删除下面两行) keys[idx] = malloc(KEYSIZE); memcpy(keys[idx], key, KEYSIZE); idx ++; } fclose(fptr); // 释放动态分配的内存(不需要保存密钥可删除下面三行) for(int i=0; i<num_keys; i++){ free(keys[i]); } free(keys); return 0; }
内容的提问来源于stack exchange,提问作者James
相关产品推荐
相关产品推荐

