#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。
答案 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];
如果你没有类似于
的某些typedeftypedef 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环境中)