我有点拘泥于CS50加密练习的一部分,在这个练习中,我们必须用C语言实现一个使用凯撒密码加密消息的程序。
具体地说,这部分:;修改caesar.c,使您的程序不打印出提供的命令行参数,而是检查以确保该命令行参数的每个字符都是十进制数字(即0、1、2等(,如果其中任何字符不是,则在打印消息Usage:后终止/凯撒钥匙">
我的代码如下:
#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 keyn");
return 1;
}
else
{
printf("successn");
}
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("successn");
return 0;
}
else
{
printf("Usage: ./caesar keyn");
return 1;
}
}
}
正如您所看到的,第一部分是有效的(检查一个命令行参数(,但当我输入一个十进制数字字符串作为该参数时,如123c或1c23,它仍然会打印成功。
显然,这是因为循环检查字符串中的第一个字符是否是数字,如果是,则立即打印成功。因此,我想在代码中找到一种简单的方法来检查参数的每个字符是否为数字,然后只打印success或Usage:/凯撒钥匙。
感谢您的帮助,如果需要更多问题集的背景信息,请告诉我。
进行
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("successn"); return 0; } else { printf("Usage: ./caesar keyn"); 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 keyn");
return 1;
}
}
printf("successn");
return 0;
但是一个空参数被认为是可以接受的,很可能你也想得到这个数字,所以你可以使用strtol
或scanf
来得到这个数字并检查你有一个数字,而不是像你那样循环,所以例如:
#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 keyn", *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 keyn", argv[1]);
return 1;
}
printf("valid key %dn", 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], "%d %c", &key, &c) != 1) || (key < 0))
[编辑备注]
对于第一部分,即使我运行if(!isdigit((unsigned char(argv[1][I](,代码仍然无法正常工作。F.e.如果我运行F.e../caesar 12p仍然打印成功(和以前一样的问题(。
这意味着你没有得到我的所有代码,如果我把我的第一个提议放在一个完整的程序中,你可能会继续使用你的if
和两个分支:
#include <stdio.h>
#include <ctype.h>
int main(int argc, char ** argv)
{
//checks if the user provides exactly one command-line argument
if (argc != 2)
{
printf("Usage: %s keyn", *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 keyn");
return 1;
}
}
printf("successn");
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 $