C+中的简单散列方法+; 我尝试在C++中实现一个简单的哈希方法,它采用最大长度为1024的字符数组,并将其转换成最大长度为256的数组。我得到了不正确的值,我不知道为什么
测试输入:这是一个测试 测试输出:fWhis▒~▒▒▒▒t 预期输出:这是一个测试 我用java编写了相同的方法,效果很好C+中的简单散列方法+; 我尝试在C++中实现一个简单的哈希方法,它采用最大长度为1024的字符数组,并将其转换成最大长度为256的数组。我得到了不正确的值,我不知道为什么,c++,arrays,C++,Arrays,测试输入:这是一个测试 测试输出:fWhis▒~▒▒▒▒t 预期输出:这是一个测试 我用java编写了相同的方法,效果很好 void hash(char* message, char* output) { //Hash int i = 0; while (i < strlen(message)-1){ output[i % N] += message[i++]; } output[N-1] = '\0'; } 我认为在初始化输出数
void hash(char* message, char* output)
{
//Hash
int i = 0;
while (i < strlen(message)-1){
output[i % N] += message[i++];
}
output[N-1] = '\0';
}
我认为在初始化输出数组时,输出数组中有垃圾值,所以我尝试创建一个助手方法clear()来初始化输出数组中的每个值,但这又给了我奇怪的值。总结了注释中提到的内容
- 在修改变量时在同一语句中访问变量
两次是未定义的行为i
- 未初始化的缓冲区不是零初始化的。从中读取(也隐式地通过
)是未定义的行为+=
- 在循环的每次迭代中调用strlen是浪费的
- 输出缓冲区的NUL终止可疑。由于在一起添加字符不能保证提供任何可打印字符,因此NUL终止可能不是一个好主意
- 由于加法产生的值可能大于
所能容纳的值,因此应使用char
,因为有符号溢出是未定义的行为,无符号char
可能是char
或有符号的
无符号的
已经从缓冲区大小中减去了终止NUL字节的空间,因此可以将实际数组大小传递给它fgets
是一个幻数,它应该是N
的输入参数hash
#include <stddef.h>
#include <stdio.h>
#include <string.h>
void
hash(const char * message, unsigned char *const output, const size_t n)
{
size_t i = 0;
memset(output, 0, n);
while (*message != '\0')
output[i++ % n] += *message++;
}
int
main()
{
char message[1024];
unsigned char output[256];
printf("Please enter the message: ");
fgets(message, sizeof(message), stdin);
hash(message, output, sizeof(output));
fwrite(output, sizeof(output), 1, stdout);
fputc('\n', stdout);
}
#包括
#包括
#包括
无效的
散列(常量字符*消息,无符号字符*常量输出,常量大小\u t n)
{
尺寸i=0;
memset(输出,0,n);
而(*消息!='\0')
输出[i++%n]+=*消息++;
}
int
main()
{
字符消息[1024];
无符号字符输出[256];
printf(“请输入消息:”);
fgets(消息、sizeof(消息)、stdin);
散列(消息、输出、sizeof(输出));
fwrite(输出,sizeof(输出),1,标准输出);
fputc('\n',stdout);
}
您的代码有很多问题:
-
这是C++编写的C。从长远来看,你将更好地学习使用<代码>字符串< /> > 。
- 我们应该想象什么是
。我想是256。如果您提供小的、完整的、可运行的代码,您将从中获得更好的帮助N
- 您应该将输出的长度作为参数传递,而不是采用全局定义。这样函数就独立了,这是一种最佳实践
条件在每次迭代中调用while
的运行时间为O(strlen()<对于长度为
的字符串,code>strlen()n
)。您已将本应为O(n
)的循环转换为O(n
^2)n
- 在这里使用
,而
使用不是最佳做法。对
- 您从未初始化数组
输出
李>
- 您正在用
字符计算结果,然后用零覆盖N
th。缓冲区N
的长度必须为输出
+1,以便在N
输出字符后有空间写入终止的空字符N
是索引数组的错误方法。您应该真正使用int
size\u t
- 在调用代码中,您忘记了为空终止允许额外的字符。您的代码最多只能读取1023个字符,而不是1024个字符。散列也一样
- 您正在用
void hash(char* message, char* hash_buf, size_t hash_buf_size)
{
// Zero the output buffer, including the terminal null character.
memset(hash_buf, '\0', hash_buf_size);
size_t len = strlen(message);
for (size_t i = 0; i < len; i++)
hash_buf[i % (hash_buf_size - 1)] += message[i];
}
是否希望输出与输入相同?在本测试用例中,应该是因为消息不超过256个字符。基本上我想要的是,如果第一个字符是a,第256个字符是b,那么新的第一个字符将是b。换言之,每256个字符它就开始写入自身。当
输出中的数据量小于N
(我假设N
为256?)时,您不能正确地以null结尾。同样,此行输出[i%N]+=消息[i++]代码>显示未定义的行为。在单独的行上递增i
。缓冲区也未初始化为零,这是未定义行为的另一个来源。请不要在循环条件下重复调用strlen
。事实上,你根本不需要它。谢谢大家!在下一行增加i,初始化数组时为零,解决了这些问题。我还删除了对strlen的调用。“在修改变量时在同一语句中访问变量I两次是未定义的行为。”据我所知,在C++17中,情况已不再如此。执行顺序现在已经明确。
void hash(char* message, char* hash_buf, size_t hash_buf_size)
{
// Zero the output buffer, including the terminal null character.
memset(hash_buf, '\0', hash_buf_size);
size_t len = strlen(message);
for (size_t i = 0; i < len; i++)
hash_buf[i % (hash_buf_size - 1)] += message[i];
}
char message[1025], hash[257];
fgets(message, sizeof message, stdin);
hash(message, hash, sizeof hash);