c 中的分段错误,第 2 周凯撒,cs50x 哈佛课程

Segmentation Error in c, week 2 caesar, cs50x harvard course

所以我在哈佛 cs50 在线课程(2021x 版)的第 2 周。我们应该编写一个程序来加密文本,将每个字母的 ASCII 代码移动一定数量,由用户通过命令行决定。 Here is the full problem. 我快完成了,但是当我尝试 运行 程序时,(它编译得很好),它告诉我有一个 分段错误 .我真的不明白这个问题。我读过这个问题与访问无法访问的特定内存部分有关?我该如何解决这个问题?先感谢您! 这是我的代码..

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

int main(int argc, string argv[])
{
    int k, i;
    if (argc == 2 && isdigit(argv[1]) && argv[1] > 0)
    {
        k = (int) argv[1];
        string plaintext = get_string("plaintext: ");
        printf("cyphertext: ");
        for (i = 0; i < strlen(plaintext); i++)
        {
            if (islower(plaintext[i]) || isupper(plaintext[i]))
            {
                printf("%c", (((plaintext[i] + k) - 97) % 26) + 97);
                return 0;
            }
            
        }
    }
    else
    {
        printf("Usage: ./caesar key");
        return 1;
    }
}

您应该分别检查下位字符和上位字符。 如果角色是低级角色,那你是对的。你应该减去 97.But 如果字符是大写字符你应该减去 65。否则你在模式操作之前得到一个否定的结果,这会导致分段错误。

if(isupper(plainText[i])){
                
                cipherText[i] = (((plainText[i] - 65 + key) % 26) + 65);
                
            } else {
if(islower(plainText[i])){
                
                cipherText[i] = (((plainText[i] - 97 + key) % 26) + 97);
                    
                }
            }

I'm on week 2 of the harvard cs50 online course

听到这个消息我很难过。你的大部分问题都源于糟糕的 CS-50 class,它欺骗你相信 C 不知何故有一个预制的糖衣字符串 class。它没有,它只有以空终止结尾的原始字符数组,因此大多数字符串操作都是手动的。

其他问题来自编译器向您指出错误时没有听取。这里有一些:

  • isdigit(argv[1]) 没有意义。一个好的编译器会告诉你很多,例如 clang:

    warning: cast to smaller integer type 'int' from 'string' (aka 'char *')

    您将指针与字符串进行比较,而 isdigit 需要单个字符。为了使用 isdigit,您必须为字符串的每个字符循环调用它。

  • argv[1] > 0 没有意义,因为它将指针与 0 进行比较。

    error: ordered comparison between pointer and zero

  • k = (int) argv[1];也说不通

    warning: cast to smaller integer type 'int' from 'string' (aka 'char *')

    要将字符串转换为整数,必须使用 strtol 函数,例如 k = strtol(argv[1], NULL, 10)。它带有您可能也想使用的各种错误处理。

    而且因为 k 包含废话 - 实际上它包含一个转换为整数的内存地址,所以 plaintext[i] + k 也变成废话。

  • if (islower(plaintext[i]) || isupper(plaintext[i])) 没有意义,它说“如果一个字符是小写还是大写”。那么,它可能是?相反,您可能打算使用 touppertolower 进行大写或小写的所有计算,而不管用户键入什么。