请考虑以下代码:
char CeaserCrypt(char str[256],int key)
{
char encrypted[256],encryptedChar;
int currentAsci;
encrypted[0] = '\0';
for(int i = 0; i < strlen(str); i++)
{
currentAsci = (int)str[i];
encryptedChar = (char)(currentAsci+key);
encrypted[i] = encryptedChar;
}
return encrypted;
}
Visual Studio 2010出错,因为该函数返回一个数组。我该怎么办?
我的朋友告诉我将签名更改为void CeaserCrypt(char str[256], char encrypted[256], int key)
。但我不认为这是正确的。如何摆脱编译错误?
答案 0 :(得分:7)
返回类型应为char *
,但这只会增加另一个问题。
encrypted
在CeaserCrypt
的堆栈上被“分配”,并且在函数返回时可能无效。由于encrypted
与输入的长度相同,请执行:
int len = strlen(str);
char *encrypted = (char *) malloc(len+1);
encrypted[len] = '\0';
for (int i = 0; i < len; i++) {
// ...
}
不要忘记稍后释放缓冲区(使用free()
)。
编辑: @Yosy:不要觉得有必要复制/粘贴。将其用作指针以改善编码习惯。另外,为了满足批评者:使用上面的示例将已分配的指针传递给加密例程。
答案 1 :(得分:6)
它希望您返回char *而不是char。无论如何,您不应该返回引用或指向您在堆栈上创建的内容的指针。在堆栈上分配的东西有a lifetime that corresponds with their scope。范围结束后,允许那些堆栈变量消失。
返回std::vector而不是数组。
std::vector<char> CeaserCrypt(char str[256],int key)
{
std::vector<char> encrypted(256);
char encryptedChar;
int currentAsci;
encrypted[0] = '\0';
for(int i = 0; i < strlen(str); ++i)
{
currentAsci = (int)str[i];
encryptedChar = (char)(currentAsci+key);
encrypted[i] = encryptedChar;
}
return encrypted;
}
虽然存在另一个微妙的问题:你正在将一个整数转换为字符值。 int的最大大小远大于char,因此您的强制转换可能会截断该值。
答案 2 :(得分:3)
由于您使用的是C ++,因此您只需使用std::string
即可。但除此之外,你朋友建议的可能是最好的。
答案 3 :(得分:3)
这里有一些问题。首先:
char CeaserCrypt(char str[256],int key)
正如其他人所指出的,您的退货类型不正确。您不能在单个字符中返回整个数组。你可以返回char*
,但这会返回一个指向数组的指针,该数组将在堆栈上本地分配,因此一旦删除堆栈帧(基本上是在函数之后)就无效了。在英语中,您将访问该内存地址,但谁知道将会有什么...
正如你的朋友建议的那样,更好的签名是:
void CeaserCrypt(char* encrypted, const char str*, const size_t length ,int key)
我添加了一些内容 - size_t
长度,因此您可以处理任何长度的字符串。这样,可以根据需要定义str的大小。只需确保char* encrypted
的大小相同。
然后你可以这样做:
for(int i = 0; i < length; i++)
{
// ...
为此,调用者需要分配具有相同长度的适当大小的缓冲区,其长度必须在length参数中传入。查找malloc以获取C.如果使用C ++,请使用std::string
。
答案 4 :(得分:2)
如果需要C兼容性,请加密字符串函数参数。 如果没有,请使用C ++ std :: string而不是C样式字符串。
并且在您的代码中,加密字符串不以'\ 0'
结尾答案 5 :(得分:1)
原始代码的问题在于,您试图从一个原型返回char*
的函数返回一个char
指针(本地数组已经衰减)。函数不能在C中返回数组,也不能在C ++中返回。
您的朋友可能建议您以这样的方式更改功能,即调用者负责分配所需的缓冲区。
请注意,以下原型完全相等。您不能将数组作为参数传递给普通函数。
int func(char array[256]);
int func(char* array);
OTOH,你应该(如果可以的话)决定你使用的语言。更好的原版(用C ++编写)。
std::vector<unsigned char> CeaserCrypt(const std::string& str, const int key)
{
std::vector<unsigned char> encrypted(str.begin(), str.end());
for (std::vector<unsigned char>::iterator iter = vec.begin();
iter != vec.end(); ++iter) {
*iter += key;
}
return vec;
}
请注意溢出有符号整数会导致未定义的行为。
答案 6 :(得分:0)
VS2010正在“大喊大叫”,因为您正在尝试返回在堆栈上分配的值,并且在函数调用返回后不再有效。
您有两种选择:1)在函数内的堆上分配内存,或者2)使用调用者提供给您的内存。 2号是你朋友的建议,也是一种很好的做事方式。
对于1,您需要调用malloc()
或new
,具体取决于您使用的是C还是C ++。在C中,我有以下内容:
char* encrypted = malloc(256 * sizeof(char));
对于C ++,如果您不想使用字符串,请尝试
char* encrypted = new char[256];
编辑: facepalm 对C噪音感到抱歉,我应该更仔细地看一下这个问题,并意识到你正在使用C ++。
答案 7 :(得分:0)
您可以在适当的位置执行Caesar密码,无需将数组传入和传出。
char * CeaserCrypt(char str[256], int key)
{
for(unsigned i = 0; i < strlen(str); i++)
{
str[i] += key;
}
return str;
}
作为进一步的简化,请跳过返回值。
void CeaserCrypt(char str[256], int key)
{
for(unsigned i = 0; i < strlen(str); i++)
{
str[i] += key;
}
}
答案 8 :(得分:-1)
你返回的不是char,而是char数组。尝试将返回类型更改为char *(char *和char数组表面上与编译器相同)
char* CeaserCrypt(char str[256],int key)
编辑:如其他帖子所述,加密数组在函数调用后可能无效。你总是可以为加密做一个新的[]声明,记得以后删除[]。