了解CS50中的“ Pset 2:凯撒”代码

时间:2020-07-31 02:26:56

标签: c loops command-line-arguments cs50

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

int main(int argc, string argv[])
{
    if (argc == 2)
    {
        string cmd = argv[1];

        for (int i = 0, n = strlen(cmd); i<n ; i++)
        {
            if (isdigit(cmd[i]))
            {
                continue;
            }
            else
            {
                printf("Usage: %s key \n", argv[0]);
            }
        }
    }
    else
    {
        printf("Usage: %s key \n", argv[0]);
    }
}

我正在学习CS50课程,并且遇到了“ Pset2:凯撒”问题。我可以接受命令行参数,并检查它们是否为数字。

我面临的问题是,在检查了参数的有效性之后,我希望程序返回该值。我想检查给定的输入是否仅是数字。如果是这样,我希望程序使用该数字参数值来计算密码。问题是_我正在使用循环检查输入,并且我不得不使用continue;感到困惑,因为如果删除continue;,程序将无法完成验证密钥的任务。

示例:如果我将continue;替换为printf("True\n");,则在输入TrueTrue作为输入后,程序将打印20。将20x作为输入后,我得到TrueTrueUsage: ./Caesar key,而理想情况下,它仅应返回Usage: ./Caesar key

问题陈述链接:https://cs50.harvard.edu/x/2020/psets/2/caesar/

2 个答案:

答案 0 :(得分:1)

您正在使确认程序的第一个参数为全数字的逻辑变得复杂。您确实有三个任务:

  1. 验证是否至少给出了一个参数;
  2. 遍历参数以验证每个字符是否为数字;
  • 如果找到非数字,则输出错误,显示用法,返回EXIT_FAILURE1
  1. 有效参数-输出密钥。

虽然检查(argc == 2)以在命令行上仅要求一个参数是完全可以的,但至少考虑一下需要什么通常会有所帮助。那里您至少需要一个参数,因此对(argc < 2)的检查可确定缺少参数,但是如果您采用其他可选参数,则也不能阻止输入多个参数。例如:

    if (argc < 2 ) {    /* validate 1 argument given */
        fprintf (stderr, "error: insufficient input,\n"
                        "usage: %s key (all digits)\n", argv[0]);
        return 1;
    }

注意:,关于错误,不需要else语句。只需处理错误并退出即可。这样可以在其余代码中节省一定的缩进程度。)

要验证每个字符都是数字,只需循环遍历每个字符并使用isdigit()进行检查即可。您不需要strlen()。在C中,字符串以n终止字符'\0'(具有ASCII值0)终止。要遍历字符串,您需要做的是:

    string cmd = argv[1];           /* assing to cmd */
    
    for (int i = 0; cmd[i]; i++)    /* loop over each char in cmd */
        if (isdigit((unsigned char)cmd[i]) == 0) {  /* if non-digit, handle error */
            fprintf (stderr, "error: '%c' is non-digit.\n"
                            "usage: %s key (all digits)\n", cmd[i], argv[0]);
            return 1;
        }

注意,当达到需要退出的错误条件时,不需要else,只需处理错误并退出)

还要注意,传递给isdigit()宏(对于所有ctype.h宏)的值必须具有unsigned charEOF的值,因此将其强制转换为{{ 1}}是必需的。请参阅man 3 isalpha(了解unsigned char的值始终在char内,但要早点养成良好的习惯)

在确认所有字符都是数字后,剩下的就是输出密钥。总而言之,您将拥有:

unsigned char

使用/输出示例

没有参数:

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

int main (int argc, char **argv) {
    
    if (argc < 2 ) {    /* validate 1 argument given */
        fprintf (stderr, "error: insufficient input,\n"
                        "usage: %s key (all digits)\n", argv[0]);
        return 1;
    }
    
    string cmd = argv[1];           /* assing to cmd */
    
    for (int i = 0; cmd[i]; i++)    /* loop over each char in cmd */
        if (isdigit((unsigned char)cmd[i]) == 0) {  /* if non-digit, handle error */
            fprintf (stderr, "error: '%c' is non-digit.\n"
                            "usage: %s key (all digits)\n", cmd[i], argv[0]);
            return 1;
        }
    
    printf ("key: %s\n", cmd);      /* output good key */
}

无效的参数:

$./bin/pset2_ceaser
error: insufficient input,
usage: ./bin/pset2_ceaser key (all digits)

好的输入内容:

$ ./bin/pset2_ceaser 123foo
error: 'f' is non-digit.
usage: ./bin/pset2_ceaser key (all digits)

仔细研究一下,如果您还有其他问题,或者我以任何方式误读了您的问题,请告诉我。

答案 1 :(得分:0)

如果代码遇到的是不是数字的字符,则可以提早中断循环:

   if ( !isdigit( cmd[i] ) )
   {
       printf("Usage: %s key \n", argv[0]);
       break;
   }

还有函数strtol(),可将参数转换为整数。它将为您处理错误。

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

int main( int argc, char *argv[] )
{
    if (argc == 2)
    {
        char *error_at = NULL;

        long rotation = strtol( argv[1], &error_at, 10 );

        if ( rotation == 0 )
        { 
            if ( error_at != argv[1] )
                fprintf( stderr, "A rotation of zero is ineffective\n" );

            else if ( error_at == argv[1] )
                fprintf( stderr, "That's not a number!\n" );

            exit( 1 );
        }
        else
        {
            // Cypher is limited to A-Z
            rotation %= 26;

            printf( "DEBUG: rotation is %ld\n", rotation );
        }
    }
    else
    {
        printf ("Usage: %s key \n", argv[0]);
        exit( 1 );
    }

    return 0;
}