我不知道为什么我收到分段错误错误

时间:2014-09-26 10:05:48

标签: c segmentation-fault cs50 vigenere

#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,完全由字母字符组成。如果你的程序没有任何命令行参数,有多个命令行参数,或者包含任何非字母字符的命令行参数,你的程序应该抱怨并立即退出,主要返回1(从而表示我们自己的测试可以检测到的错误)。否则,你的程序必须继续向用户提示一串明文p,然后必须根据Vigenère的密码加密k,最后打印结果并退出,主要返回0。

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

中每个字母的大小写

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

4 个答案:

答案 0 :(得分: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岁是&#39; A&#39;。因此,最好明确使用字符文字&#39; A&#39;而不是65。

答案 1 :(得分:1)

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

使用第strcpy(key[commandlength], argv[1]);

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

你想要的是一个指针,它将stringlength字符串argv[1]作为内存关联。

答案 2 :(得分:0)

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

string key;

而不是

string key[commandlength + 1];

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

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

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

然后你应该使用以下代码

将输入字符串复制到其中
strcpy(key,argv[1]);

所以现在你将实际的字符串复制到关键变量中。

在从函数(语义程序)返回之前,你应该使用自由函数释放内存,因为我们已经使用堆上的malloc函数动态分配它。

free(key);

答案 3 :(得分:0)

如果您不知道,请使用以下代码编译您的源代码:“gcc -Wall -g source.c”;在程序崩溃后运行程序,运行“dgb ./prog core”

进入gdb类型“bt”,你会看到seg fault出现的字符串数

如果核心转储无法在工作目录中创建,请运行以下命令:“ulimit -c unlimited”(在bash环境中)