【问题标题】:CS50x Caesar - Segmentation fault when inserting isalpha(argv[1])CS50x Caesar - 插入 isalpha(argv[1]) 时出现分段错误
【发布时间】:2020-12-08 11:49:06
【问题描述】:

对于 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;
}

非常感谢您的帮助。

【问题讨论】:

  • 欢迎来到 SO。您应该在编译器中启用警告。然后阅读它们并处理它们!如果您不理解它们,请阅读 isalpha 期望的参数。提示:它不期望获得指向字符串的指针。
  • 不相关:不要使用幻数。如果你的意思是'a',写'a',而不是97
  • argv[1] 是一个 字符串,但 isalpha 需要一个字符。您在问argv[1] 的内存地址是否为 alpha。那是未定义的行为。

标签: c segmentation-fault cs50 caesar-cipher


【解决方案1】:

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
//...

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

您可以使用strtol 来获得更强大的替代方案。

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


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

【讨论】:

  • 非常感谢您的帮助。我意识到数据类型的问题。现在程序如愿运行。
猜你喜欢
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 2014-03-28
  • 1970-01-01
  • 2020-11-26
  • 2020-12-12
  • 2021-12-17
相关资源
最近更新 更多