好的伙计们,这是我在这里发表的第一篇文章。我的compsci类中的最新作业让我们编写了几个函数来编码和解码基于简单偏移的字符串。到目前为止,在我的加密函数中,我试图将字符串中的大写字母转换为ASCII等价物(一个int),添加偏移量(并调整ASCII值是否超过'Z'),将该int转换回char(新加密的char)并将其放入一个新的字符串中。我在这里编译得很好,但是当我运行它并输入简单的大写字符串时,它会产生一个Segmentation Fault(核心转储)错误。我在哪里错了? (注意:有一些注释掉的位来自于尝试解决在main中产生一些奇怪错误的情况)
#include <stdio.h>
#include <string.h>
#include <ctype.h>
//#include <stdlib.h>
char *encrypt(char *str, int offset){
int counter;
char medianstr[strlen(str)];
char *returnstr;// = malloc(sizeof(char) * strlen(str));
for(counter = 0; counter < strlen(str); counter++){
if(isalpha(str[counter]) && isupper(str[counter])){//If the character at current index is an alpha and uppercase
int charASCII = (int)str[counter];//Get ASCII value of character
int newASCII;
if(charASCII+offset <= 90 ){//If the offset won't put it outside of the uppercase range
newASCII = charASCII + offset;//Just add the offset for the new value
medianstr[counter] = (char)newASCII;
}else{
newASCII = 64 + ((charASCII + offset) - 90);//If the offset will put it outside the uppercase range, add the remaining starting at 64(right before A)
medianstr[counter] = (char)newASCII;
}
}
}
strcpy(returnstr, medianstr);
return returnstr;
}
/*
char *decrypt(char *str, int offset){
}
*/
int main(){
char *inputstr;
printf("Please enter the string to be encrypted:");
scanf("%s", inputstr);
char *encryptedstr;
encryptedstr = encrypt(inputstr, 5);
printf("%s", encryptedstr);
//free(encryptedstr);
return 0;
}
答案 0 :(得分:2)
你使用了一堆指针,但从不为它们分配任何内存。这将导致段故障。
实际上奇怪的是,你似乎知道你需要这样做,因为你已经有了代码,但是你评论了它:
char *returnstr;// = malloc(sizeof(char) * strlen(str));
当您使用指针时,您需要将其“指向”已分配的内存,它可以指向您通过malloc()
请求的动态内存或静态内存(例如您声明的数组);当你完成动态记忆时,你需要free()
它,但你似乎知道这一点,因为你注释了一个免费的电话。
只需malloc()
到inputstr
,只有returnstr
一个就足以让它发挥作用。
答案 1 :(得分:1)
不再继续使用scanf()。
scanf()发生分段错误,因为它试图写入* inputstr(inputtr指向的位置块);此时没有分配。 要调用scanf(),您需要输入一个指针,指针指向的内存地址首先被分配。
当然,要修复您想要的分段错误,请将内存分配给char * inputstr。
动态分配128字节的内存(即指针指向堆):
char *inputstr = (char *) malloc(128);
或静态分配128字节的内存(即指针指向堆栈):
char inputstr[128];
答案 2 :(得分:1)
encrypt()
函数中有很多复杂性并非真正必要。注意,在循环的每次迭代中计算字符串的长度通常是昂贵的过程。我在评论中指出:
90和64有什么关系?为什么不使用'A'和'Z'?你已经注释掉了returntr的内存分配,所以你要通过一个未初始化的指针进行复制然后返回它?不是快乐的秘诀!
其他答案也(准确地)指出你没有在main()
初始化你的指针,所以你没有机会在encrypt()
转储核心,因为你已经在main()
中转储核心。
#include <ctype.h>
#include <stdlib.h>
#include <string.h>
char *encrypt(char *str, int offset)
{
int len = strlen(str) + 1;
char *returnstr = malloc(len);
if (returnstr == 0)
return 0;
for (int i = 0; i < len; i++)
{
char c = str[i];
if (isupper((unsigned char)c))
{
c += offset;
if (c > 'Z')
c = 'A' + (c - 'Z') - 1;
}
returnstr[i] = c;
}
return returnstr;
}
长变量名称并不总是有用;他们使代码更难阅读。请注意,isupper()
为真的任何字符也都满足isalpha()
。 isupper()
参数的强制转换可防止char
类型签名时出现问题,并且您有无符号字符值在0x80..0xFF范围内的数据(设置了高位)。使用强制转换,代码将正常工作;没有,你可能会遇到麻烦。