c语言中的凯撒分割错误

Caesar segmentation fault in c language

我正在做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;
}

根据C标准(5.1.2.2.1程序启动)

2 If they are declared, the parameters to the main function shall obey the following constraints:

— The value of argc shall be nonnegative.

— argv[argc] shall be a null pointer....

所以当你运行程序喜欢

./caesar

如果不指定命令行参数,则 argc 等于 1 并且 argv[argc]argv[1] 等于 NULL.

您的程序从调用函数 key 开始,该函数又立即为等于 NULL 的指针 v[1] 调用标准 C 函数 strlen

int key (int c, string v[])
{
    int m = strlen (v[1]);
    //...

此调用调用未定义的行为,导致您编写时出现分段错误。

在调用函数key之前你应该首先检查argc是否等于2,或者在函数内部这个if语句

if (c != 2)
{
    printf ("Usage: ./caesar key\n");
    return 1;
}

应该放在处理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;
    }
}

是多余的。您可以立即调用函数 strtol 并检查其执行是否成功..