如何检查以确保命令行参数的每个字符都是十进制数字即0、1、2等

问题描述

在CS50加密练习中,我有些困惑,我们必须实现一个程序,该程序使用Caesar的密码以C语言对消息进行加密。

特别是这一部分:“修改caesar.c,以使您的程序而不是打印出提供的命令行参数,而是检查以确保该命令行参数的每个字符均为十进制数字(即0、1 ,2等),如果没有,则在打印消息用法:./ caesar键后终止。”

我的代码如下:

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

int main (int argc,string argv[])
{
    //checks if the user provides exactly one command-line argument
    if (argc != 2)
    {
        printf("Usage: ./caesar key\n");
        return 1;
    }
    else
    {
        printf("success\n");
    }


    for (int i = 0,n = strlen(argv[1]); i < n; i++)
    {
        // check if any of the characters of the command-line argument is not a decimal digit
        
        if (isdigit(argv[1][i]))
        {
            printf("success\n");
            return 0;
        }
        else
        {       
            printf("Usage: ./caesar key\n");
            return 1;
        }
    }
}

您可以看到第一部分有效(检查一个命令行参数),但是当我输入一个十进制数字字符串作为该参数时,例如123c或1c23,它仍然会打印成功。

显然是因为循环检查字符串中的第一个字符是否为数字,如果是,则立即打印成功。因此,我想在代码中找到一种简单的方法来检查参数的每个字符是否为数字,然后才打印成功或用法:./ caesar键。

感谢您的帮助,如果需要更多有关问题集的背景信息,请告诉我。

解决方法

for (int i = 0,n = strlen(argv[1]); i < n; i++)
{
   // check if any of the characters of the command-line argument is not a decimal digit
   
   if (isdigit(argv[1][i]))
   {
       printf("success\n");
       return 0;
   }
   else
   {       
       printf("Usage: ./caesar key\n");
       return 1;
   }
}

您只考虑argv[1]的第一个字符,因为您在if的两个分支中都返回了

你可以做

for (int i = 0; argv[1][i]; i++)
{
    // check if any of the characters of the command-line argument is not a decimal digit
    
    if (!isdigit((unsigned char) argv[1][i]))
    {
        printf("Usage: ./caesar key\n");
        return 1;
    }
}

printf("success\n");
return 0;

但是一个空参数被认为是可以接受的,并且您很可能还希望获取数字,因此您可以使用strtolscanf来获取数字并检查您,而不是像那样循环播放有一个数字,例如:

#include <stdio.h>

int main(int argc,char ** argv)
{
  //checks if the user provides exactly one command-line argument
  if (argc != 2)
  {
    printf("Usage: %s key\n",*argv);
    return 1;
  }
  
  int key;
  char c;
  
  // check argv[1] is only a number
  if (sscanf(argv[1],"%d %c",&key,&c) != 1)
  {
    printf("'%s' is not a valid key\n",argv[1]);
    return 1;
  }
  
  printf("valid key %d\n",key);
  
  return 0;
}

编译和执行:

pi@raspberrypi:/tmp $ gcc -Wall c.c
pi@raspberrypi:/tmp $ ./a.out
Usage: ./a.out key
pi@raspberrypi:/tmp $ ./a.out aze
'aze' is not a valid key
pi@raspberrypi:/tmp $ ./a.out 1a
'1a' is not a valid key
pi@raspberrypi:/tmp $ ./a.out a1
'a1' is not a valid key
pi@raspberrypi:/tmp $ ./a.out 1
valid key 1
pi@raspberrypi:/tmp $ ./a.out 123
valid key 123
pi@raspberrypi:/tmp $ ./a.out "123 "
valid key 123
pi@raspberrypi:/tmp $ ./a.out "123 a"
'123 a' is not a valid key
pi@raspberrypi:/tmp $ ./a.out " 123 "
valid key 123
pi@raspberrypi:/tmp $ ./a.out " "
' ' is not a valid key
pi@raspberrypi:/tmp $ ./a.out ""
'' is not a valid key
pi@raspberrypi:/tmp $ 

如您所见,空格是可以容忍的,这是很平常的阅读数字

当然,如果您不想使用负数

if ((sscanf(argv[1],&c) != 1) || (key < 0))

[编辑您的评论]

对于第一部分,即使当我运行if(!isdigit((unsigned char)argv [1] [i]))时,代码仍无法正常工作。 F.e.如果我跑./caesar 12p仍然可以成功打印(与以前相同的问题)。

这意味着您没有获得我的所有代码,并且如果我将第一个建议放在完整的程序中,则可能继续在两个分支中拥有if

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

int main(int argc,*argv);
    return 1;
  }

  for (int i = 0; argv[1][i]; i++)
  {
    // check if any of the characters of the command-line argument is not a decimal digit
    
    if (!isdigit((unsigned char) argv[1][i]))
    {
      printf("Usage: ./caesar key\n");
      return 1;
    }
  }
  
  printf("success\n");
  return 0;
}

编译和执行:

pi@raspberrypi:/tmp $ gcc -Wall c.c
pi@raspberrypi:/tmp $ ./a.out 12p
Usage: ./caesar key
pi@raspberrypi:/tmp $ ./a.out 12
success
pi@raspberrypi:/tmp $