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

CS50 Caesar程序问题:大写字母加密后出现不可见字符

CS50 Caesar项目:大写字母加密后出现不可见字符导致Check50失败

我为CS50的Caesar项目写了代码,本地自测符合需求,但用Check50检测时,所有包含大写字母的测试用例全失败。检测显示大写字母间有额外不可见字符,本地运行没这问题。

Check50报错:

:( encrypts "BARFOO" as "EDUIRR" using 3 as key
    expected "ciphertext: ED...", not "ciphertext: E\..."
:( encrypts "BaRFoo" as "FeVJss" using 4 as key
    expected "ciphertext: Fe...", not "ciphertext: F\..."

我的代码:

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

bool only_digits(string s);
char rotate(int, int);

int main(int argc, string argv[])
{
    // 确保密钥输入正确
    if (argc != 2)
    {
        printf("Usage: ./caesar key\n");
        return 1;
    }
    else
    {
        int cont = only_digits(argv[1]);
        if (cont != 1)
        {
            return 1;
        }
        else
        {
            // 将密钥从字符串转为整数
            int key = atoi(argv[1]);
            string plain = get_string("plain text: \n");
            // 使用密钥旋转字母
            printf("ciphertext: ");
            for (int i = 0, len = strlen(plain); i < len; i++)
            {
                rotate(plain[i], key);
            }
            printf("\n");
        }
    }
}

// 使用密钥旋转字母
char rotate(int p, int i)
{
    // 处理大写字母
    if (isupper(p))
    {
        p = p - 65;
        char c = (p + i) % 26;
        c += 65;
        printf("%c", c);
    }
    // 处理小写字母
    if (islower(p))
    {
        p = p - 97;
        char c = (p + i) % 26;
        c += 97;
        printf("%c", c);
    }
    // 非字母字符保持不变
    else
    {
        printf("%c", p);
    }
    return 0;
}

// 确保输入的密钥仅包含数字
bool only_digits(string s)
{
    for (int i = 0, len = strlen(s); i < len; i++)
    {
        if (!isdigit(s[i]))
        {
            printf("Usage: ./caesar key\n");
            return 0;
        }
    }
    return 1;
}

问题分析

问题出在rotate函数的逻辑上:

  1. 分支结构错误:第二个if(islower(p))是独立判断,不是else if,导致else分支只和第二个if绑定。当处理大写字母时,第一个if执行完后,第二个if不成立,会直接进入else分支重复打印内容。
  2. 修改了原变量值:在处理大写字母时,你修改了p的值(p = p - 65),导致后续判断islower(p)时,p已经变成0-25的数字,必然不满足小写条件,进而执行else分支打印这个数字对应的不可见ASCII字符(比如ASCII 1是控制字符),这就是Check50检测到的额外不可见字符。

修复代码

把第二个if改成else if,并且使用临时变量保存计算值,不修改原p:

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

bool only_digits(string s);
char rotate(int, int);

int main(int argc, string argv[])
{
    if (argc != 2)
    {
        printf("Usage: ./caesar key\n");
        return 1;
    }
    if (!only_digits(argv[1]))
    {
        return 1;
    }
    
    int key = atoi(argv[1]);
    string plain = get_string("plain text: ");
    printf("ciphertext: ");
    
    for (int i = 0, len = strlen(plain); i < len; i++)
    {
        rotate(plain[i], key);
    }
    printf("\n");
    return 0;
}

char rotate(int p, int key)
{
    if (isupper(p))
    {
        // 用临时变量计算,不修改原p
        int temp = p - 'A';
        char c = (temp + key) % 26 + 'A';
        printf("%c", c);
    }
    else if (islower(p))
    {
        int temp = p - 'a';
        char c = (temp + key) % 26 + 'a';
        printf("%c", c);
    }
    else
    {
        printf("%c", p);
    }
    return 0;
}

bool only_digits(string s)
{
    for (int i = 0, len = strlen(s); i < len; i++)
    {
        if (!isdigit(s[i]))
        {
            printf("Usage: ./caesar key\n");
            return false;
        }
    }
    return true;
}

另外,代码里多余的大括号也可以去掉,让结构更清晰。修复后,大写字母只会被处理一次,不会再输出额外的不可见字符,Check50就能通过测试了。

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

相关产品推荐
方舟 Agent Plan

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

最近更新时间:2026.08.13 14:40:28