You need to enable JavaScript to run this app.
优惠活动
大模型
产品
解决方案
定价
更多

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);

    }
}

错误分析

  1. 文件读取逻辑错误:原代码用fscanf("%s", cipherText)只能读取第一行的H,X,无法逐行读取所有字符映射对,也无法解析逗号分隔的原字符和替换字符。
  2. 映射表构建错误:原代码假设替换字符按a-z顺序存储,但cipher.txt只存储了部分字符的映射,且原字符是大写,直接按索引取会导致错误。
  3. 输入缓冲区残留问题:scanf("%c", &choice)会留下换行符,导致后续scanf("%s", string)可能读取空内容。
  4. 解密逻辑错误:解密时需要反向查找替换字符对应的原字符,原代码直接复用加密逻辑,完全错误。
  5. 未检查文件打开状态:如果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

相关产品推荐
方舟 Agent Plan

超全模态模型 × Harness 升级,最新支持 Deepseek-V4.1-Flash、GLM-5.3 系列、Doubao-Seedream-5.0-pro、Kimi-K3 (部分), 限时 9.9 元起

最近更新时间:2026.08.01 03:31:37