#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
。
答案 0 :(得分:1)
您正在使确认程序的第一个参数为全数字的逻辑变得复杂。您确实有三个任务:
EXIT_FAILURE
(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 char
或EOF
的值,因此将其强制转换为{{ 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;
}