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

C语言ROT13加解密项目求助:字符串读取与字符转换问题

C语言ROT13加解密项目问题解决

一、解决fgets读取后输出乱码的问题

你的代码出现乱码有两个核心原因:

  1. scanf("%i", &menu)读取数字后,输入缓冲区里的换行符\n会被后续的fgets直接读取,导致text一开始就拿到空行。
  2. 循环遍历用了sizeof(text),会把数组中未初始化的随机内存内容也输出,这就是乱码的来源。

修复方法:

  • 在scanf后清理输入缓冲区的残留换行符;
  • 循环只遍历到字符串结束符'\0',而非整个数组长度。

二、实现ROT13加解密(无需大量if/switch)

ROT13的核心规则是字母循环移动13位,非字母字符保持不变。使用**查找表(LUT)**是最高效且简洁的实现方式:

  • 创建一个256字节的数组rot13_lut,覆盖所有ASCII字符;
  • 对小写字母:a-m映射到n-z,n-z映射到a-m;
  • 对大写字母:A-M映射到N-Z,N-Z映射到A-M;
  • 其他字符直接映射自身。

修改后的完整代码

#include <stdio.h>
#include <string.h>

// 预定义ROT13查找表
char rot13_lut[256];

// 初始化查找表
void init_rot13_lut() {
    for (int i = 0; i < 256; i++) {
        if (i >= 'a' && i <= 'm') {
            rot13_lut[i] = i + 13;
        } else if (i >= 'n' && i <= 'z') {
            rot13_lut[i] = i - 13;
        } else if (i >= 'A' && i <= 'M') {
            rot13_lut[i] = i + 13;
        } else if (i >= 'N' && i <= 'Z') {
            rot13_lut[i] = i - 13;
        } else {
            rot13_lut[i] = i; // 非字母字符保持不变
        }
    }
}

void Encrypt() {
    char text[50];
    printf("Insert the desired text (Maximum of 50 characters): \n");
    // 读取前先确保缓冲区干净,处理残留换行
    int c;
    while ((c = getchar()) != '\n' && c != EOF);
    
    fgets(text, sizeof(text), stdin);
    // 去掉fgets读取的换行符(如果存在)
    text[strcspn(text, "\n")] = '\0';
    
    printf("Original text: %s\n", text);
    printf("Encrypted text: ");
    for (int i = 0; text[i] != '\0'; i++) {
        printf("%c", rot13_lut[(unsigned char)text[i]]);
    }
    printf("\n");
}

void Decrypt() {
    // ROT13加密解密是同一个操作,直接复用逻辑即可
    char text[50];
    printf("Insert the text to decrypt (Maximum of 50 characters): \n");
    int c;
    while ((c = getchar()) != '\n' && c != EOF);
    
    fgets(text, sizeof(text), stdin);
    text[strcspn(text, "\n")] = '\0';
    
    printf("Encrypted text: %s\n", text);
    printf("Decrypted text: ");
    for (int i = 0; text[i] != '\0'; i++) {
        printf("%c", rot13_lut[(unsigned char)text[i]]);
    }
    printf("\n");
}

int main() {
    int menu = 0; // 初始化menu变量,避免未定义行为
    init_rot13_lut(); // 初始化查找表
    
    while (menu == 0) {
        printf("Choose one of the following options: \n");
        printf("[1] Encrypt\n");
        printf("[2] Decrypt\n");

        scanf("%i", &menu);

        if (menu == 1) {
            Encrypt();
            menu = 0; // 执行完后重置菜单,回到循环
        }
        if (menu == 2) {
            Decrypt();
            menu = 0;
        }
        if (menu != 1 && menu != 2) {
            printf("Invalid option, please try again.\n");
            menu = 0;
            // 清理无效输入后的缓冲区
            int c;
            while ((c = getchar()) != '\n' && c != EOF);
        }
    }
    return 0;
}

关键改动说明

  1. 初始化menu变量:原代码中menu未初始化就进入循环,属于未定义行为,必须初始化为0;
  2. 输入缓冲区清理:每次scanf后用循环读掉残留的换行符,避免fgets读取空内容;
  3. 字符串截断:用strcspn去掉fgets读取的换行符,避免输出多余空行;
  4. ROT13查找表:一次初始化后可重复使用,加解密逻辑完全一致(因为13*2=26,刚好是字母表长度);
  5. 循环终止条件:遍历到'\0'为止,只输出有效字符串内容。

内容的提问来源于stack exchange,提问作者white as void

相关产品推荐
方舟 Agent Plan

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

最近更新时间:2026.06.23 04:41:12