我在 CS50 中进行加密练习,我被卡住了 有这样的部分:“添加到 caesar.c 的 main 下面,一个名为 only_digits 的函数,它接受一个字符串作为参数,如果该字符串仅包含数字(0 到 9),则返回 true,否则返回 false。确保将函数的原型也添加到 main 之上”。
这是我的代码:
#include <cs50.h>
#include <stdio.h>
#include <ctype.h>
#include <string.h>
bool only_digits(string s);
int main(int argc, string argv[])
{
// Make sure program was run with just one command-line argument
argc = only_digits(argv[1]);
if(argc != 2)
{
printf("Usage: ./caesar key\n");
return 1;
}
return 0;
}
// make sure that the character in argv[1] is a digit
bool only_digits(string s)
{
// int n = strlen(s);
for (int i = 0, n = strlen(s); i < n; i++)
{
if(isdigit(s[i]))
{
return 0;
}
}
printf("Usage: ./caesar key\n");
return 1;
}
我决定创建一个 for 循环,在其中我可以检查字符是否是数字,但我只需要检查第二个字符,而不是“凯撒”,因此,我认为我的代码失败并带有“用法” : ./凯撒钥匙 ”一直,如果我只写“./caesar” - 它会出现“分段错误(核心转储)”。显然我的代码有缺陷,但我找不到解决方案。
让我们注意一些错误/误用。
您可以这样做,但我不鼓励您这样做..将
argc
放在一边。我的意思是,不要将其重复用于其他用途。相反,创建一个专用变量..
在处理输入参数之前始终检查它们的有效性。在您的情况下,当用户没有输入时,您仍然检查号码。这会使您访问无效的内存区域并可能触发分段错误。
在您提供的示例代码中,
only_digits
返回0
或1
。因此,检查 if(argc != 2)
总是令人满意的。
你的函数
only_digits
应该返回一个布尔值=>要么true
(或1
)或false
(或0
)。按照惯例,在你的学习过程中,我建议你坚持true
和false
。
你的函数
only_digits
有一个否定的逻辑。如果只有非数字,则返回 true。
生成的代码如下所示:
#include <stdio.h>
#include <ctype.h>
#include <string.h>
bool only_digits(string s);
int main(int argc, string argv[])
{
/* Make sure there are enough arguments passed to your program. */
if (argc < 2) {
goto usage;
}
// Make sure program was run with just one command-line argument
bool isvalid = only_digits(argv[1]);
if(isvalid == 0) {
goto usage;
}
// everything is good.
return 0;
usage:
printf("Usage: ./caesar key\n");
return 1;
}
// make sure that the character in argv[1] is a digit
bool only_digits(string s)
{
for (int i = 0; i < strlen(s); i++) {
/* Here, we want to break the loop upon the first non-digit
* character. Thus the negation `!` */
if(!isdigit(s[i])) {
return false;
}
}
return true;
}
OP 代码试图做太多事情,并且顺序混乱。例如,函数
only_digits()
的任务是测试字符串是否仅由 ASCII 数字组成,而不报告如何执行程序。
下面使用较少的代码。检查传递参数的字符(如果有)。如果有一个参数,并且有 1+ 个字符要检查,并且检查到字符串末尾,则返回值是
true
表示一切正常。
#include <cs50.h>
#include <stdio.h>
#include <ctype.h>
#include <string.h>
bool only_digits(string s);
int main(int argc, string argv[])
{
if( only_digits( argv[1] ) == 0 )
{
printf("Usage: ./caesar key\n");
return 1;
}
/* more code here */
return 0;
}
bool only_digits(string s)
{
int i = 0;
while( s && isdigit( s[i] ) )
i++; // loop until end of string (if there is one)
return s && i && s[i] == '\0';
}
人们想要编写简洁的代码,不给错误留下隐藏的空间。
这会“消耗”一些额外的(极其便宜的)机器周期。谁在乎?
编辑
一个鲜为人知的事实是,C 保证 argv[] 的“后最终”值为 NULL。 (即:“a.out foobar”将 argv[0] 设置为指向“a.out”,将 argv[1] 设置为指向“foobar”,并将 argv[2] 设置为 NULL。人们可以将此信息用于自己的优势。