【发布时间】:2020-10-20 03:03:57
【问题描述】:
我正在做 CS50 的第二个作业凯撒。除了最后一条,我的大部分评论似乎都是正确的。我无法处理缺少argv[1] 的情况,这意味着如果我只输入./caesar,则会出现分段错误。为什么?
#include <stdio.h>
#include <string.h>
#include <cs50.h>
#include <stdlib.h>
#include <ctype.h>
#include <math.h>
bool check;
int key (int c, string v[]);
int main (int argc, string k[])
{
key (argc, k);
if ((check))
{
string p = get_string("plaintext: ");
int n = strlen (p);
char f[n];
printf ("ciphertext: ");
for (int i = 0; i < n; i++)
{
if (isalpha (p[i]))
{
if (p[i] >= 'A' && p[i] <= 'Z')
{
if ((p[i] + x) > 90)
{
f[i] = ((p[i] + x) % 91) + 65;
printf ("%c", f[i]);
}
else
{
f[i] = ((p[i] + x) % 91);
printf ("%c", f[i]);
}
}
else if (p[i] >= 'a' && p[i] <= 'z')
{
if ((p[i] + x) > 122)
{
f[i] = ((p[i] + x) % 123) + 97;
printf ("%c", f[i]);
}
else
{
f[i] = ((p[i] + x) % 123);
printf ("%c", f[i]);
}
}
}
else
{
printf ("%c", p[i]);
}
}
printf ("\n");
}
}
int key (int c, string v[])
{
int m = strlen (v[1]);
for (int i = 0; i <= m; i++)
{
if (v[1][0] == 0)
{
printf ("Usage: ./caesar key\n");
return 1;
}
else if (v[1][i] >= 32 && v[1][i] < 48)
{
printf ("Usage: ./caesar key\n");
return 1;
}
else if (v[1][i] >= 58 && v[1][i] <= 126)
{
printf ("Usage: ./caesar key\n");
return 1;
}
}
if (c != 2)
{
printf ("Usage: ./caesar key\n");
return 1;
}
else
{
int r = atoi (v[1]);
if (r < 1)
{
printf ("Usage: ./caesar key\n");
return 1;
}
else
{
check = true;
return r;
}
}
return 0;
}
【问题讨论】:
-
这是学习如何使用调试器的最佳时机。使用调试器,您可以在崩溃发生时捕捉崩溃,并能够在代码中找到它发生的位置。然后,您还可以检查所有相关变量的值。
-
char f[n];==>char f[n+1];经典不允许为字符串终止符留出空间。 -
@Mahmoud Ferig 你期待这个声明 int m = strlen (v[1]);当 v[1] 等于 NULL 时会产生?编写一个只包含一条语句的简单程序 strlen( NULL );看看结果。
-
你还需要学习一些其他的东西,首先你不应该真正使用magic numbers。另一个好消息是关于the standard character classification and manipulation functions。还要始终检查有效的参数计数器
argc在尝试访问特定参数之前,例如,如果没有为您的程序提供参数,那么k[1]将是NULL。事实上,k[argc]总是NULL(在 C 规范中定义)。 -
@WeatherVane,OP 没有使用
f[]作为字符串。不需要 +1 - 至少现在不需要。
标签: c command-line-arguments undefined-behavior cs50 argv