-3
#include <stdio.h>
#include <cs50.h> //stdlib.h is included in cs50.h so I don't need it
#include <string.h>
#include <ctype.h>
#include <math.h>

int main(int argc, string argv[]) // command line input
{
    if(argc != 2) // check if there is only one input
    {
        printf("error\n");
        return 1;
    }

    int commandlength = strlen(argv[1]); // find string length of command string

    string key[commandlength + 1]; // taking the key from the input and putting it in something that will take less typing later

    for(int i = 0; i < commandlength; i++) // check if every char in the string is a letter
    {
        if(isalpha(argv[1][i]))
            continue;

        else
        {
            printf("error\n");
            return 1;
        }
    }

    strcpy(key[commandlength], argv[1]); // copy key from command line into a string called key
    string input = GetString();
    int inputlength = strlen(input); // length of string typed in when prompted
    int k = 0; // this will be used to iterate the key separately from i, since the key only iterates when applied to an alpha

    for(int i = 0; i < inputlength; i++)
    {
        if(ispunct(input[i]))
            printf("%c", input[i]);

        if(isspace(input[i]))
            printf("%c", input[i]);

        if(isupper(input[i]))
        {
            printf("%c", (input[i] + atoi(key[k]) % commandlength - 65) % 26 + 65);
            k++;
        }

        if(islower(input[i]))
        {
            printf("%c", (input[i] + atoi(key[k]) % commandlength - 97) % 26 + 97);
            k++;
        }        
    }

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

在阅读之前,请记住我是一名学生。获得详细的解释比简单的一行代码说“你去我修好了”要有益得多。我将在我的提交中链接这篇文章,我们确实对学术诚信以及什么是复制与帮助有非常严格的规定,如果能牢记这一点,我将不胜感激。

该项目的目的是创建一个 vigenere 密码。以下是我的老师提供的指示:

你本周的最后一个挑战是在 vigenere.c 中编写一个使用 Vigenère 密码加密消息的程序。该程序必须接受一个命令行参数:关键字 k,完全由字母字符组成。如果您的程序在没有任何命令行参数、多个命令行参数或一个包含任何非字母字符的命令行参数的情况下执行,您的程序应该立即报错并退出,main 返回 1(因此表示我们自己的测试可以检测到的错误)。否则,您的程序必须继续提示用户输入明文字符串 p,然后它必须根据 Vigenère 的密码用 k 对其进行加密,最终打印结果并退出,main 返回 0。

对于 k 中的字符,您必须将 A 和 a 视为 0,将 B 和 b 视为 1,...,并将 Z 和 z 视为 25。此外,您的程序必须仅将 Vigenère 密码应用于 p 中的字符,如果该字符是一封信。所有其他字符(数字、符号、空格、标点符号等)必须原样输出。此外,如果您的代码即将将 k 的第 j 个字符应用于 p 的第 i 个字符,但后者被证明是非字母字符,则您必须等待将 k 的第 j 个字符应用于 p 中的下一个字母字符; 你还不能前进到 k 中的下一个字符。最后,您的程序必须保留 p 中每个字母的大小写。

我很确定我达到了迭代代码的要求,确保密钥循环是否比被加密的短语短,并确保我没有将密钥应用于非字母字符。但是,在提示输入要加密的字符串之前,我得到了一个分段默认值,所以我很确定问题出在代码的上半部分。我已经查看了很多代码,但我仍然无法弄清楚为什么它会一直出现段错误。

4

4 回答 4

1

更改此声明

strcpy(key[commandlength], argv[1]); 

strcpy( key, argv[1] ); 

key[commandlength] 是一个 char 类型的对象,如果你使用这个无效的构造,它的值被用作字符串的地址

strcpy(key[commandlength], argv[1]); 

continue此外,在循环中使用也不是一个好主意。代替

for(int i = 0; i < commandlength; i++) // check if every char in the string is a letter
{
    if(isalpha(argv[1][i]))
        continue;

    else
    {
        printf("error\n");
        return 1;
    }
}

我会简单地写

for(int i = 0; i < commandlength; i++) // check if every char in the string is a letter
{
    if( !isalpha(argv[1][i] ) )
    {
        printf("error\n");
        return 1;
    }
}

正如 BLUEPIXY所说,而不是

string key[commandlength + 1]; 

会有

char key[commandlength + 1]; 

前提是您没有类似的 typedef

typedef char string;

但是,如果您确实有这样的 typedef,那么下面的语句

string input = GetString();

将无效,因为您正在尝试调用函数 strlen 进行输入:

int inputlength = strlen(input); 

并且不要在代码中使用幻数,例如在此语句中

printf("%c", (input[i] + atoi(key[k]) % commandlength - 65) % 26 + 65);

我想65是'A'。因此,最好使用明确的字符文字“A”而不是 65。

于 2014-09-26T10:10:14.680 回答
1

我不确定该string类型应该是什么(根据main(int argc string argv[])它看起来像char*. 如果是这样,那么您将获得一个带有该行的 char 指针数组 string key[commandlength + 1];

随着线strcpy(key[commandlength], argv[1]);

您将字符串 from 复制argv[i]到您创建的数组中的最后一个指针。但是由于这个指针(还)没有分配任何内存。此外,它具有随机内容并指向随机存储位置。因此你得到了段错误。

可能您想要的是一个指针,它具有字符串作为关联stringlength的内存。argv[1]

于 2014-09-26T10:23:29.050 回答
0

用户 johanneshau 给出的答案有些正确。要添加到他/她的答案中,您应该声明一个变量键,如下所示

string key;

代替

string key[commandlength + 1];

然后你应该为上面的指针变量分配内存,因为 string 是 char * 的 typedef,因此在分配一些内存之前它不能存储任何字符串。

key = (string)malloc(sizeof(char) * (commandlength + 1));

上面的行将分配内存来保存输入字符串。

然后您应该使用以下代码将输入字符串复制到其中

strcpy(key,argv[1]);

所以现在你已经将实际的字符串复制到了 key 变量中。

在从函数(语义编程)返回之前,您应该使用 free 函数释放内存,因为我们使用堆上的 malloc 函数动态分配了它。

free(key);
于 2014-09-26T10:43:32.517 回答
0

if you have not idea, then compile your source with following: "gcc -Wall -g source.c" ; run your program, after program crashes, run "dgb ./prog core"

into the gdb type "bt" and you will see the number of string where seg fault comes

if core dump cannot create in working directory, run following: "ulimit -c unlimited" (in bash environment)

于 2014-09-26T13:56:28.973 回答