【问题标题】:Check50 "not a valid ASCII Ouput" on pset2 caesar在 pset2 caesar 上检查 50“不是有效的 ASCII 输出”
【发布时间】:2022-08-18 16:30:44
【问题描述】:

我在 cs50 上完成了凯撒任务,并在我的终端上对其进行了测试,它运行良好,但在 check50 上一直未能通过一些测试。

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

int getkey(string k);
string cipher(string s, int key);
int key;
int p;
int q;

int main(int argc, string argv[])
{
    // Allow 2 command line inputs
    if (argc == 2)
    {
        // Assign a local string to allow char scan
        string s = argv[1];

        // Check if all inputs are numbers
        for (int i = 0; s[i] != 0; i++)
        {
            if (s[i] < 48 || s[i] > 57)
            {
                printf(\"Usage: ./caesar key\\n\");
                return 1;
            }
        }
        // Get key from string
        int cipherkey = getkey(s);

        // Get user text
        string text = get_string(\"plaintext: \");

        // Calculate ciphertext and print
        string ciphertext = cipher(text, cipherkey);
        printf(\"ciphertext: %s\\n\", ciphertext);
    }
    else
    {
        printf(\"Usage: ./caesar key\\n\");
        return 1;
    }
}

// Change string to int. Turns out theres already a function for this called atoi()
int getkey(string k)
{
    key = 0;
    for(int i = 0, conv = 0, n = strlen(k); k[i] != 0; i++, n--)
    {
        // Calcute the placevalue
        p = pow(10, n-1);
        conv = k[i] - 48; // Convert to int
        key = key + (conv * p); // Sum up
    }
    return key % 26;
}

// Cipher text
string cipher (string s, int key)
{
    for(int i = 0; s[i] != 0; i++)
    {
       if(islower(s[i]))
       {
           s[i] = s[i] + key;
           while(s[i] > 122)
           {
               s[i] = (s[i] - 123) + 97;
           }
       }
       else if(isupper(s[i]))
       {
           s[i] = s[i] + key;
           while(s[i] > 90)
           {
               s[i] = (s[i] - 91) + 65;
           }
       }
    }
    return s;
}

带有错误信息

:) caesar.c compiles.
:) encrypts \"a\" as \"b\" using 1 as key
:( encrypts \"barfoo\" as \"yxocll\" using 23 as key
    output not valid ASCII text
:) 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
    output not valid ASCII text
:) handles lack of argv[1]
:) handles non-numeric key
:) handles too many arguments

我在不知道“atoi”函数的情况下编写了代码,所以我实现了一个名为 getkey() 的函数来返回密钥。当我正常返回密钥时,它失败了。

:( encrypts \"barfoo\" as \"onesbb\" using 65 as key
Output not a valid ASCII text

直到我返回 key % 26;

尽管该程序在我的终端上运行良好,但我不知道为什么 check50 不起作用。请帮忙。

更新代码:

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

string cipher(string s, int key);

int main(int argc, string argv[])
{
    // Allow 2 command line inputs
    if (argc == 2)
    {
        // Assign a local string to allow char scan
        string s = argv[1];

        // Check if all inputs are numbers
        for (int i = 0; s[i] != 0; i++)
        {
            if (s[i] < 48 || s[i] > 57)
            {
                printf(\"Usage: ./caesar key\\n\");
                return 1;
            }
        }
        // Get key from string
        int cipherkey = atoi(s);

        // Get user text
        string text = get_string(\"plaintext: \");

        // Calculate ciphertext and print
        string ciphertext = cipher(text, cipherkey);
        printf(\"ciphertext: %s\\n\", ciphertext);
    }
    else
    {
        printf(\"Usage: ./caesar key\\n\");
        return 1;
    }
}

// Cipher text
string cipher (string s, int key)
{
    for(int i = 0; s[i] != 0; i++)
    {
        if(islower(s[i]))
        {
            s[i] = (int) s[i] + key;
            while(s[i] > \'z\')
            {
                s[i] = (s[i] - 123) + 97;
            }
        }
        else if(isupper(s[i]))
        {
            s[i] = (int) s[i] + key;
            while(s[i] > \'Z\')
            {
                s[i] = (s[i] - 91) + 65;
            }
        }
    }
    return s;
}
  • k[i] - 48你永远不应该使用这样的“幻数”。如果您指的是字符 \'0\',则应使用 \'0\' 而不是某个数字。
  • 如果您已经知道您的 getkey 实现会导致问题,您可以删除所有其他代码并将此函数与您的测试用例一起发布。
  • 如果getkey 函数旨在将字符串转换为数字,则添加%26 没有任何意义。这似乎是您的加密机制的一些限制。然后在加密期间或解析该字符串后处理它。但是不要用这种不相关的功能污染该功能
  • 除了指出string 隐藏了您正在处理signed chars 的事实之外,没有时间研究您的密码函数...当您向(特别是)小写有符号字符添加值时,结果可能是负数数字...-127 to +128 8 位签名...也许将char 复制到int 以便有足够的位保持正数并允许&gt; 按您的意愿工作...
  • @Gerhardh 我已经摆脱了 getkey 函数并使用了 atoi(),我将一些幻数(如 90 和 122)更改为 \'z\' 和 \'Z\' 但它仍然返回错误消息

标签: c cs50


【解决方案1】:

我重写了函数,试图避免进行更正和改进。现在,副本实际上是不必要的,但我希望它可以帮助您了解“有符号(8 位)字符”不够“宽”,无法用于导致溢出的计算......

请阅读以下内容并尝试跟随。

string cipher( string s, int key ) {
    for( int i = 0; s[i] != '\0'; i++ ) {
        if( !isalpha( s[i] ) )
            continue;

        int copy = (int)s[i]; // unnecessary casting, but...

        // transform ASCII value into 0-25 range
        if( islower( s[i] ) )
            copy = copy - 'a';
        else // must be uppercase
            copy = copy - 'A';

        copy = (copy + key) % 26;

        // transform enciphered MODULO back into ASCII char
        if( islower( s[i] ) )
            copy = copy + 'a';
        else // must be uppercase
            copy = copy + 'A';

        s[i] = copy;
    }

    return s;
}

【讨论】:

    猜你喜欢
    • 2022-07-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 2020-11-26
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 2013-08-05
    相关资源
    最近更新 更多