CS50x凯撒-插入isalpha(argv [1])时出现分段错误

时间:2020-08-19 08:35:35

标签: c segmentation-fault cs50 caesar-cipher

对于CS50x问题Caesar,我创建了一个程序,该程序使用Caesar的密码对消息进行加密。

为此,程序必须认识到命令行参数只是一个数字。因此,没有两个或多个数字,没有零以下的数字,也没有文本。

但是,一旦我添加了检查内容是否为|| isalpha(argv[1])的文本,该程序便无法正常工作。

当我尝试运行程序时,终端打印以下内容:

Segmentation fault

谁能告诉我代码是什么问题

#include <cs50.h>
#include <stdio.h>
#include <stdlib.h>
#include <ctype.h>
#include <string.h>

int main(int argc, string argv[])
{
    int kkey = 0;

    // Check if correct command-line arguments
    if (argc != 2 || atoi(argv[1]) < 0 || isalpha(argv[1])) //segfault here
    {
        printf("./caesar key\n");
        return 1;
    }
    else
    {
        kkey = atoi(argv[1]);
    }

    // Ask for Plaintext to encrypt
    string plaintext = get_string("plaintext: ");

    for (int i = 0, n = strlen(plaintext); i < n; i++)
    {
        if (isalpha(plaintext[i]) && islower(plaintext[i]))
        {
            plaintext[i] = (plaintext[i] - 'a' + kkey) % 26 + 97;
        }
        else if (isalpha(plaintext[i]) && isupper(plaintext[i]))
        {
            plaintext[i] = (plaintext[i] - 'A' + kkey) % 26 + 65;
        }

        printf("%c", plaintext[i]);
    }

    printf("\n");
    return 0;
}

非常感谢您的帮助。

1 个答案:

答案 0 :(得分:0)

As said by @Gerhardh,不能将字符串用作isalpha的参数,需要循环检查字符串的每个字符。

在任何不是最佳方法的情况下,使用否定的isdigit都是更好的选择,因为它会考虑所有其他非数字字符。

//...
// Check if correct command-line arguments
if (argc != 2 || atoi(argv[1]) < 0) 
{
    printf("./caesar key\n");
    return 1;
}

for(size_t i = 0; i < strlen(argv[1]); i++){
    if(!isdigit(argv[1][i])){ //if one of the characters is not a digit 0-9
        puts("./caesar key\n");
        return 1;
    }
}

kkey = atoi(argv[1]); //no else needed
//...

请注意,如果转换后的值无法用atoi表示,int将调用未定义的行为。

您可以使用strtol作为更可靠的选择。

该链接用于Linux手册页,我觉得很好,但这是跨平台的。


再次使用as stated by @Gerhardh,使用字符代码可能会适得其反,在这种情况下,您使用的是ASCII编码,但是还有其他情况,这会使代码的可移植性降低,请改用字符26 + 'a'和{ {1}}。