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

为何加密第二个单词后代码插入3个空格?附代码求排查

问题分析与修复方案

嘿,我帮你定位到问题根源了——你的代码里嵌套循环的逻辑完全违背了Vigenère密码的设计思路,这直接导致了空格重复输出、加密偏移混乱的问题。咱们一步步拆解问题,再给出修复方案:

你的代码核心问题

  • 双重循环导致非字母字符重复输出:你用外层循环遍历明文,内层循环遍历密钥。这意味着每个非字母字符(比如空格)会被输出密钥长度次——比如你的密钥是abcde(长度5),空格就会被打印5次,这就是你看到多个空格的原因。
  • 明文索引被随意修改:在内层循环里你手动执行k++,这会让外层的for循环索引彻底混乱,导致明文被跳着处理,加密结果完全错误。
  • 密钥循环逻辑搞反:Vigenère密码需要循环用密钥的每个字母对应明文的每个字母(非字母不消耗密钥位),但你的代码是把整个密钥套用到每个明文字符上,完全搞反了对应关系。

修复后的完整代码

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

int main(int argc, string argv[]) {
    // 先校验命令行参数合法性
    if (argc != 2) {
        printf("You didn't submit a valid encryption key.\n");
        printf("Please check your input and re-run the program.\n");
        printf("We require a keyword (letters only) as encryption key.\n");
        return 1;
    }

    string keyword = argv[1];
    // 额外检查密钥是否全为字母(Vigenère密码的密钥应为纯字母)
    for (int i = 0; i < strlen(keyword); i++) {
        if (!isalpha(keyword[i])) {
            printf("Keyword must contain only letters!\n");
            return 1;
        }
    }

    string plain = get_string("plaintext: ");
    printf("ciphertext: ");

    int key_len = strlen(keyword);
    int key_idx = 0; // 跟踪当前使用的密钥位置

    for (int k = 0; k < strlen(plain); k++) {
        char c = plain[k];
        if (isalpha(c)) {
            // 计算密钥偏移:统一转小写后得到0-25的偏移值
            int shift = tolower(keyword[key_idx]) - 'a';
            key_idx = (key_idx + 1) % key_len; // 密钥索引循环复用

            if (isupper(c)) {
                printf("%c", ((c - 'A' + shift) % 26) + 'A');
            } else {
                printf("%c", ((c - 'a' + shift) % 26) + 'a');
            }
        } else {
            // 非字母直接输出,不消耗密钥位
            printf("%c", c);
        }
    }
    printf("\n"); // 最后加换行,输出更规范
    return 0;
}

修复细节说明

  1. 移除错误的嵌套循环:改用单个循环遍历明文,用key_idx变量跟踪当前使用的密钥位置,逻辑更清晰。
  2. 正确实现密钥循环:只有处理明文的字母字符时,才移动key_idx,通过(key_idx + 1) % key_len实现密钥的循环复用,完全符合你预期的偏移逻辑。
  3. 修正参数与合法性检查:
    • 把main函数的参数修正为标准的string argv[](你原来的argv[1]写法不标准)。
    • 增加了密钥纯字母的检查(Vigenère密码的密钥应为字母,而非整数,你原来的提示文本也有误,已修正)。
  4. 优化代码可读性:用'A'和'a'代替硬编码的ASCII值65、97,去掉了冗余的do-while循环(参数检查不需要循环,不符合直接退出即可)。

现在测试你给出的例子:

  • 明文:Meet me at the Park
  • 密钥:abcde
    每个字母会对应正确的偏移量,空格只会输出一次,完全符合你预期的逻辑。

内容的提问来源于stack exchange,提问作者jstrnbrg

相关产品推荐
方舟 Agent Plan

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

最近更新时间:2026.05.15 08:09:34