C语言替换密码程序无法读取cipher.txt实现字符替换求助
替换密码程序问题解决
问题说明
我正在为作业编写替换密码程序,需使用cipher.txt文件进行字符替换。当前编写的C语言代码如下,cipher.txt文件采用每行「原字符,替换字符」的格式(例如H,X、E,P等),我尝试用该文件实现字符串(如hello)的加解密,但无法让程序正确读取文件并完成字符替换,希望获得解决方法。
cipher.txt文件内容:
H,X
E,P
L,R
O,Q
原代码:
#include<stdio.h> int main() { //ask the user what they want to encrypt or decrypt a string printf("Do you want to encrypt or decrypt a string? (e/d): "); char choice; scanf("%c", &choice); //if the user wants to encrypt, then use cipher.txt to encrypt the string if (choice == 'e') { //ask the user for the string they want to encrypt printf("Enter the string you want to encrypt: "); char string[100]; scanf("%s", string); //open cipher.txt FILE* cipher; cipher = fopen("cipher.txt", "r"); //read the cipher.txt file char cipherText[26]; fscanf(cipher, "%s", cipherText); //close cipher.txt fclose(cipher); //encrypt the string int i; for (i = 0; i < 100; i++) { if (string[i] == '\0') { break; } else if (string[i] >= 'a' && string[i] <= 'z') { string[i] = cipherText[string[i] - 'a']; } else if (string[i] >= 'A' && string[i] <= 'Z') { string[i] = cipherText[string[i] - 'A'] - 32; } } //print the encrypted string printf("The encrypted string is: %s: ", string); } //if the user chooses decryption, then decrypt the string else if (choice == 'd') { //ask the user for the string they want to decrypt printf("Enter the string you want to decrypt: "); char string[100]; scanf("%s", string); //open cipher.txt FILE* cipher; cipher = fopen("cipher.txt", "r"); //read the cipher.txt file char cipherText[26]; fscanf(cipher, "%s", cipherText); //close cipher.txt fclose(cipher); //decrypt the string int i; for (i = 0; i < 100; i++) { if (string[i] == '\0') { break; } else if (string[i] >= 'a' && string[i] <= 'z') { string[i] = cipherText[string[i] - 'a']; } else if (string[i] >= 'A' && string[i] <= 'Z') { string[i] = cipherText[string[i] - 'A'] - 32; } } //print the decrypted string printf("The decrypted string is: %s", string); } }
错误分析
- 文件读取逻辑错误:原代码用
fscanf("%s", cipherText)只能读取第一行的H,X,无法逐行读取所有字符映射对,也无法解析逗号分隔的原字符和替换字符。 - 映射表构建错误:原代码假设替换字符按a-z顺序存储,但
cipher.txt只存储了部分字符的映射,且原字符是大写,直接按索引取会导致错误。 - 输入缓冲区残留问题:
scanf("%c", &choice)会留下换行符,导致后续scanf("%s", string)可能读取空内容。 - 解密逻辑错误:解密时需要反向查找替换字符对应的原字符,原代码直接复用加密逻辑,完全错误。
- 未检查文件打开状态:如果
cipher.txt不存在或无法打开,程序会直接崩溃。
修正后的代码
#include<stdio.h> #include<string.h> #include<ctype.h> // 初始化映射表,默认字符不变 void init_maps(char encrypt_map[], char decrypt_map[]) { int i; for (i = 0; i < 256; i++) { encrypt_map[i] = i; decrypt_map[i] = i; } } int main() { printf("Do you want to encrypt or decrypt a string? (e/d): "); char choice; // 处理输入缓冲区的换行符 scanf("%c", &choice); getchar(); // 吃掉回车 // 初始化加密和解密映射表 char encrypt_map[256], decrypt_map[256]; init_maps(encrypt_map, decrypt_map); // 打开并读取cipher.txt FILE* cipher = fopen("cipher.txt", "r"); if (!cipher) { printf("Failed to open cipher.txt!\n"); return 1; } char orig, replace; // 逐行读取原字符和替换字符,忽略逗号和换行 while (fscanf(cipher, "%c,%c\n", &orig, &replace) == 2) { // 处理大写字符的映射 encrypt_map[(unsigned char)orig] = replace; decrypt_map[(unsigned char)replace] = orig; // 同时处理小写字符的映射 encrypt_map[(unsigned char)tolower(orig)] = tolower(replace); decrypt_map[(unsigned char)tolower(replace)] = tolower(orig); } fclose(cipher); char string[100]; if (choice == 'e') { printf("Enter the string you want to encrypt: "); fgets(string, sizeof(string), stdin); // 去掉fgets读取的换行符 string[strcspn(string, "\n")] = '\0'; // 加密字符串 for (int i = 0; string[i] != '\0'; i++) { string[i] = encrypt_map[(unsigned char)string[i]]; } printf("The encrypted string is: %s\n", string); } else if (choice == 'd') { printf("Enter the string you want to decrypt: "); fgets(string, sizeof(string), stdin); string[strcspn(string, "\n")] = '\0'; // 解密字符串 for (int i = 0; string[i] != '\0'; i++) { string[i] = decrypt_map[(unsigned char)string[i]]; } printf("The decrypted string is: %s\n", string); } else { printf("Invalid choice!\n"); } return 0; }
关键改进点
- 使用256长度的数组作为映射表,覆盖所有ASCII字符,默认字符保持不变(未在cipher.txt中定义的字符不替换)。
- 逐行解析
cipher.txt中的原字符,替换字符对,同时处理大小写字符的映射。 - 用
fgets读取输入字符串,避免空格截断问题,同时处理输入缓冲区的换行符。 - 增加文件打开失败的错误处理,避免程序崩溃。
- 加密和解密分别使用独立的映射表,逻辑清晰正确。
内容的提问来源于stack exchange,提问作者dillon524
相关产品推荐
相关产品推荐

