2

我正在尝试将数字乘以它们的索引以创建哈希,但这似乎没有给出正确的输出。谁能告诉我这里有什么问题?

int main(){
    int i, hash=0, input;
    char temp[30];

    cin>>input;

    itoa (input, temp, 10);

    for(i=0; i<(sizeof(temp)/sizeof(*temp)); i++){
        hash+=((temp[i])*i);
    }

    cout<<hash;

    return 0;
}
4

3 回答 3

1

是的,您正在对 temp[30] 的所有 30 个字节进行哈希处理,而不是仅对您从标准输入读取的整数的 ascii 表示进行哈希处理。

我认为这更接近你想要的:

#include <iostream>
using namespace std;

int main() {
    int hash = 0;

    // Read input from stdin
    std::string input;
    std::cin >> input;

    // Make sure it contains only numbers
    if (input.find_first_not_of("0123456789") != std::string::npos) {
        std::cout << "Input doesn't contain only digits" << std::endl;
        return 1;
    }

    for (int i = 0; i < input.size(); i++) {
        hash += (input[i] - '0') * i;
    }

    std::cout << hash << std::endl;
    return 0;
}
于 2013-10-01T01:09:06.487 回答
1

这是因为itoa()返回一个 C 字符串。

每个 C-String 都是一个缓冲区(就像temp[30]),但不是每个缓冲区都是一个 C-String。

C-String 必须包含来自有效事物列表的字符(字母数字 + 一些符号 + 等),并且必须以“字符串终止符”(字符'\0')结尾

你的temp变量没有初始化(我们可以说它是作为一个通用缓冲区诞生的,而不是一个字符串),所以在itoa()你将你的“数字”转换为字符串之后(你的缓冲区刚刚变成了一个 C 字符串),但是在字符串之后terminator ( '\0') 你将有任何垃圾,一旦你没有初始化它!

您的缓冲区将是这样的:

temp[30] = { '1', '2', '3', '\0', ?, ?, ?, ..., ? }

? _ 可以是任何东西...

因为您循环遍历整个缓冲区 temp[30],所以您将一直在做不同的事情。

  • 解决方案 1:初始化 char temp[30] = { 0 } (有点愚蠢,但有效)
  • 解决方案 2:循环到 C-String 的“长度” temp,而不是整个缓冲区(这个更有意义!)

这个:

size_t length( strlen( temp ) );

for ( size_t i( 0 ); i < length; i++ )
{
    hash += (int)i * temp[ i ];
}
于 2013-10-01T01:11:01.423 回答
0

该 temp[] 缓冲区没有完全被 itoa() 填充,因此如果您将 i=0 循环到 (sizeof temp)-1,您将散列垃圾。尝试:

for (size_t i=0, n=strlen(temp); i<n; ++i)
{
    hash += (int)i*temp[i];
}

您需要<cstring>包含来定义 strlen()。

再想一想,no-<cstring>方法可能更好:

for (int i=0; temp[i] != 0; ++i)
{ 
    hash += i*temp[i]; 
}

这也消除了 (int) 演员表。

于 2013-10-01T01:10:06.430 回答