CS50凯撒程序正在运行,但check50表示不起作用 [英] CS50 Caesar program is working but check50 says it isn't

查看:62
本文介绍了CS50凯撒程序正在运行,但check50表示不起作用的处理方法,对大家解决问题具有一定的参考价值,需要的朋友们下面随着小编来一起学习吧!

问题描述

我创建了这个程序,但是在CS50上出现错误,表明我没有正确执行任何操作.

要求如下:

在名为caesar的目录中的名为caesar.c的文件中实现程序.

您的程序必须接受单个命令行参数,即非负整数.为了讨论起见,我们称其为k.

如果执行的程序没有任何命令行参数或带有多个命令行参数,则您的程序应打印您选择的错误消息(带有printf),并从main返回值1(这通常会表示错误).

如果命令行参数的任何字符都不是十进制数字,则程序应打印消息用法:./caesar键,并从main返回值1.

不要假设k小于或等于26.您的程序应该对小于2 ^ 31-26的k的所有非负整数值起作用.换句话说,您不必担心如果用户为k选择的值太大或几乎太大而无法容纳int,则您的程序最终会中断.(请注意,一个int可能会溢出.)但是,即使k大于26,程序输入中的字母字符也应保留在程序输出中的字母字符.例如,如果k为27,

根据 http,即使[在ASCII中,A距A的位置仍为27位,但A不应成为[://www.asciichart.com/[asciichart.com] ;只要您从Z绕到A,A就应该变成B,因为B距A的位置为27个位置.

您的程序必须输出纯文本:(不带换行符),然后提示用户输入纯文本字符串(使用get_string).

您的程序必须输出密文:(不带换行符),后跟明文的相应密文,明文中的每个字母字符都旋转"了k个位置;非字母字符应原样输出.

您的程序必须保留大小写:大写字母尽管可以旋转,但必须保持大写字母;小写字母虽然可以旋转,但必须保持小写字母.

输出密文后,应打印换行符.然后,您的程序应通过从main返回0退出.

我的代码:

  #include< cs50.h>#include< stdio.h>#include< stdlib.h>#include< string.h>#include< ctype.h>int main(int argc,字符串argv []){//检查是否输入了k如果(argc!= 2){printf(用法:./caesar键\ n");返回1;}//值k是./caesar之后的数字int k = atoi(argv [1])%26;int x = 0;int s = strlen(argv [1]);//检查k是否为正整数如果(k <0){printf(用法:.caesar键\ n");返回1;}别的{//检查参数对于(int i = 0; i< s; i ++){如果(isalpha(argv [1] [i])){继续;}否则if(isalnum(argv [1] [i])){x ++;}别的{继续;}}如果(x!= s){printf(用法:./caesar键\ n");}否则(x == s){//获取纯文本字符串plain_text = get_string("plaintext:");printf("ciphertext:");for(int y = 0; y< = strlen(plain_text); y ++){//更改字母如果(isalpha(plain_text [y])){字符p = plain_text [y];int cipher_int = p + k;如果(isupper(p)){while(cipher_int> = 90){cipher_int-= 26;}char cipher_text = cipher_int;printf(%c",cipher_text);}如果(islower(p)){while(cipher_int> = 122){cipher_int-= 26;}char cipher_text = cipher_int;printf(%c",cipher_text);}}别的{printf(%c",plain_text [y]);}}printf("\ n");}}返回0;} 

解决方案

您的数字检查非常麻烦,并且如果参数不正确,也不会导致程序按要求返回 1 .

这是一个更简单的测试:

 //检查参数for(int i = 0; i< s; i ++){如果(!isdigit((unsigned char)argv [1] [i])){printf(用法:./caesar键\ n");返回1;}} 

还请注意,当索引==字符串的长度时,应停止编码循环.因此运算符应为< .

另一个问题是使用 isalpha()< ctype.h> 中具有 char 值的类似函数.这些函数未定义为负值( EOF 除外).某些平台默认将 char 定义为带符号,如果用户键入非ASCII文本,则使 isalpha(plaintext [y])具有未定义的行为.为避免此问题,将参数强制转换为(unsigned char).

此外,您不应使用硬编码的ASCII值(例如 90 122 ),而应使用字符常量(例如'a'"z" ,以提高可读性.这样做会使编码循环中的另一个错误更加明显: while(cipher_int> = 90)应该是 if(cipher_int>'A')while(cipher_int> = 122)应该是 if(cipher_int>'z').

这是修改后的版本:

  #include< cs50.h>#include< stdio.h>#include< stdlib.h>#include< ctype.h>int main(int argc,字符串argv []){//检查单个命令行参数如果(argc!= 2){printf(用法:./caesar键\ n");返回1;}char * arg = argv [1];如果(* arg =='\ 0'){printf("caesar:键不能为空字符串\ n");返回1;}//检查参数是否为非负数for(size_t i = 0; arg [i]; i ++){如果(!isdigit((unsigned char)arg [i])){printf(用法:./caesar键\ n");返回1;}}//值k是./caesar之后的班次号int k = atoi(argv [1])%26;//获得纯文本字符串plain_text = get_string("plaintext:");printf("ciphertext:");for(size_t i = 0; plain_text [i]!='\ 0'; i ++){无符号字符c = plain_text [i];//更改字母如果(islower(c)){putchar('a'+((c-'a')+ k)%26);} 别的如果(isupper(c)){putchar('A'+((c-'A')+ k)%26);} 别的 {putchar(c);}}printf("\ n");返回0;} 

I created this program but I'm getting errors on CS50 showing that I didn't do any of it correctly.

The requirements are as follows:

Implement your program in a file called caesar.c in a directory called caesar.

Your program must accept a single command-line argument, a non-negative integer. Let’s call it k for the sake of discussion.

If your program is executed without any command-line arguments or with more than one command-line argument, your program should print an error message of your choice (with printf) and return from main a value of 1 (which tends to signify an error) immediately.

If any of the characters of the command-line argument is not a decimal digit, your program should print the message Usage: ./caesar key and return from main a value of 1.

Do not assume that k will be less than or equal to 26. Your program should work for all non-negative integral values of k less than 2^31 - 26. In other words, you don’t need to worry if your program eventually breaks if the user chooses a value for k that’s too big or almost too big to fit in an int. (Recall that an int can overflow.) But, even if k is greater than 26, alphabetical characters in your program’s input should remain alphabetical characters in your program’s output. For instance, if k is 27,

A should not become [ even though [ is 27 positions away from A in ASCII, per http://www.asciichart.com/[asciichart.com]; A should become B, since B is 27 positions away from A, provided you wrap around from Z to A.

Your program must output plaintext: (without a newline) and then prompt the user for a string of plaintext (using get_string).

Your program must output ciphertext: (without a newline) followed by the plaintext’s corresponding ciphertext, with each alphabetical character in the plaintext "rotated" by k positions; non-alphabetical characters should be outputted unchanged.

Your program must preserve case: capitalized letters, though rotated, must remain capitalized letters; lowercase letters, though rotated, must remain lowercase letters.

After outputting ciphertext, you should print a newline. Your program should then exit by returning 0 from main.

My code:

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

int main(int argc, string argv[])
{
    //check if k inputed
    if (argc != 2)
    {
        printf("Usage: ./caesar key\n");
        return 1;
    }
    //value k is the number after ./caesar
    int k = atoi(argv[1]) % 26;
    int x = 0;
    int s = strlen(argv[1]);
    //check if k is a positive integer
    if (k < 0)
    {
        printf("Usage: .caesar key\n");
        return 1;
    }
    else
    {
        //check for arguments
        for (int i = 0; i < s; i++)
        {
            if (isalpha (argv[1][i]))
            {
                continue;
            }
            else if (isalnum (argv[1][i]))
            {
                x++;
            }
            else
            {
                continue;
            }
        }
        if (x != s)
        {
            printf("Usage: ./caesar key\n");
        }
        else if (x == s)
        {
            //get plaintext
            string plain_text = get_string("plaintext: ");
            printf("ciphertext: ");
            for (int y = 0; y <= strlen(plain_text); y++)
            {
                //change letters
                if (isalpha(plain_text[y]))
                {
                    char p = plain_text[y];
                    int cipher_int = p + k;
                    if (isupper(p))
                    {
                        while(cipher_int >= 90)
                        {
                            cipher_int -= 26;
                        }
                            char cipher_text = cipher_int;
                            printf("%c", cipher_text);
                    }
                    if (islower(p))
                    {
                        while(cipher_int >= 122)
                        {
                            cipher_int -= 26;
                        }
                            char cipher_text = cipher_int;
                            printf("%c", cipher_text);
                    }
                }
                else
                {
                    printf("%c", plain_text[y]);
                }
            }
            printf("\n");
        }
    }
    return 0;
}

解决方案

Your check for digits is very cumbersome and does not cause the program to return 1 as required if the argument is incorrect.

Here is a simpler test:

        //check for arguments
        for (int i = 0; i < s; i++) {
            if (!isdigit((unsigned char)argv[1][i])) {
                printf("Usage: ./caesar key\n");
                return 1;
            }
        }

Also note that you should stop the encoding loop when the index == the length of the string. therefore the operator should be <.

Another problem is the use of isalpha() and similar functions from <ctype.h> with char values. These functions are undefined for negative values (except EOF). Some platforms define char as signed by default, making isalpha(plaintext[y]) have undefined behavior if the user typed non ASCII text. Cast the argument as (unsigned char) to avoid this problem.

Furthermore, you should not use hardcoded ASCII values such as 90 and 122, use character constants such as 'a' and 'z' for better readability. Doing so would make another error in your encoding loop more obvious: while(cipher_int >= 90) should be if (cipher_int > 'A') and while(cipher_int >= 122) should be if(cipher_int > 'z').

Here is a modified version:

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

int main(int argc, string argv[])
{
    // check for a single command line argument
    if (argc != 2) {
        printf("Usage: ./caesar key\n");
        return 1;
    }
    char *arg = argv[1];
    if (*arg == '\0') {
        printf("caesar: key cannot be an empty string\n");
        return 1;
    }
    // check that the argument is a non negative number
    for (size_t i = 0; arg[i]; i++) {
        if (!isdigit((unsigned char)arg[i])) {
            printf("Usage: ./caesar key\n");
            return 1;
        }
    }
    // value k is the shift number after ./caesar
    int k = atoi(argv[1]) % 26;

    // get plaintext
    string plain_text = get_string("plaintext: ");
    printf("ciphertext: ");
    for (size_t i = 0; plain_text[i] != '\0'; i++) {
        unsigned char c = plain_text[i];
        // change letters
        if (islower(c)) {
            putchar('a' + ((c - 'a') + k) % 26);
        } else
        if (isupper(c)) {
            putchar('A' + ((c - 'A') + k) % 26);
        } else {
            putchar(c);
        }
    }
    printf("\n");
    return 0;
}

这篇关于CS50凯撒程序正在运行,但check50表示不起作用的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持IT屋!

查看全文
登录 关闭
扫码关注1秒登录
发送“验证码”获取 | 15天全站免登陆