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

CS50 Caesar程序处理非数字密钥超时问题修复求助

修复Caesar密码程序的非数字密钥超时问题

我是CS50新手,正在完成Caesar密码作业。当前程序测试反馈如下:

  • ✅ caesar.c exists.
  • ✅ caesar.c compiles.
  • ✅ encrypts "a" as "b" using 1 as key
  • ✅ encrypts "barfoo" as "yxocll" using 23 as key
  • ✅ encrypts "BARFOO" as "EDUIRR" using 3 as key
  • ✅ encrypts "BaRFoo" as "FeVJss" using 4 as key
  • ✅ encrypts "barfoo" as "onesbb" using 65 as key
  • ✅ encrypts "world, say hello!" as "iadxp, emk tqxxa!" using 12 as key
  • ✅ handles lack of argv[1]
  • ❌ handles non-numeric key(timed out while waiting for program to exit)
  • ✅ handles too many arguments

仅「处理非数字密钥」测试失败,提示等待程序退出时超时。我的代码如下:

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

int main(int argc, string argv[])
{
    if (argc != 2)
    {
        printf("Usage: ./ceasar key\n");
        return 1;
    }

    if (atoi(argv[1]) == 0)
    {
        printf("Usage: ./ceasar key\n");
        return 1;
    }

    int k = atoi(argv[1]);
    k = k % 26;
    string plaintext = get_string("plaintext:  ");
    string ciphertext = plaintext;
    int n = strlen(plaintext);

    for (int i = 0; i < n; i++)
    {
        if ('a' <= plaintext[i] && plaintext[i] <= 'z')
        {
            if ((plaintext[i] + k) > 'z')
            {
                ciphertext[i] = ((plaintext[i] + k) - 26);
            }
            else
            {
                ciphertext[i] = (plaintext[i] + k);
            }
        }
        else if ('A' <= plaintext[i] && plaintext[i] <= 'Z')
        {
            if ((plaintext[i] + k) > 'Z')
            {
                ciphertext[i] = ((plaintext[i] + k) - 26);
            }
            else
            {
                ciphertext[i] = (plaintext[i] + k);
            }
        }
    }
    printf("ciphertext: %s\n", ciphertext);
    return 0;
}

问题根源

超时的核心原因是密钥合法性判断逻辑错误:

  • 用atoi(argv[1]) == 0判断非数字密钥不可靠:
    1. 合法密钥"0"会被错误判定为非法,直接退出;
    2. 输入混合数字与非数字的字符串(比如"12a")时,atoi会返回前半部分有效数字,程序不会触发错误提示,反而继续执行到get_string等待用户输入明文,导致测试用例超时。

正确的做法是遍历密钥的每个字符,确保所有字符都是数字,而非依赖atoi的返回值。

修复后的代码

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

int main(int argc, string argv[])
{
    if (argc != 2)
    {
        printf("Usage: ./ceasar key\n");
        return 1;
    }

    // 遍历密钥字符,检查是否全为数字
    for (int i = 0; argv[1][i] != '\0'; i++)
    {
        if (!isdigit(argv[1][i]))
        {
            printf("Usage: ./ceasar key\n");
            return 1;
        }
    }

    int k = atoi(argv[1]);
    k = k % 26;
    // 处理负密钥,转换为等效正偏移
    if (k < 0)
    {
        k += 26;
    }
    
    string plaintext = get_string("plaintext:  ");
    string ciphertext = plaintext;
    int n = strlen(plaintext);

    for (int i = 0; i < n; i++)
    {
        if ('a' <= plaintext[i] && plaintext[i] <= 'z')
        {
            ciphertext[i] = (plaintext[i] - 'a' + k) % 26 + 'a';
        }
        else if ('A' <= plaintext[i] && plaintext[i] <= 'Z')
        {
            ciphertext[i] = (plaintext[i] - 'A' + k) % 26 + 'A';
        }
        // 非字母字符保持不变,无需额外处理
    }
    printf("ciphertext: %s\n", ciphertext);
    return 0;
}

额外优化说明

  • 替换了原有的字母偏移边界判断,用(字符 - 基准字母 + 偏移) %26 + 基准字母的方式,逻辑更简洁且避免边界错误;
  • 增加了负密钥处理,确保输入负数时也能得到正确的加密结果;
  • 移除冗余的分支判断,代码可读性更强。

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

相关产品推荐
方舟 Agent Plan

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

最近更新时间:2026.07.01 22:50:37