为什么我的程序显然没有读取所有输入数字,如何检测不是数字的输入?

时间:2012-03-15 16:58:18

标签: c hashtable

对于作业,我必须编写一个程序来处理哈希表。我已经做到了,它似乎工作得很好,只是如果我在特定点输入一个变量,它就不会产生预期的输出,如果我改变它,它就会起作用(让我相信它与它有关)读取数字的顺序。)

它读取与用户在开头输入的数量一样多的数字,然后将它们哈希并将它们添加到哈希表中。然后它计算出该数字的出现次数,如果它大于用户输入的阈值(比如用户输入4作为阈值,并且有5次出现333),它将打印出该数字。

在我的程序中,它应该打印333输出,至于我的计数,它出现8次,我将阈值设置为4.但它没有。如果我改变输出,使它出现在输入的前半部分,它就可以工作。这让我觉得它只是读取数组中LEN / 2之前的数字(LEN是我们设置为宏的值)。

以下是代码:

#include <stdio.h>

#define LEN 31

int main(int argc, char *argv[]) {
    int keys[LEN];
    int values[LEN];
    int numAmount, threshold, i, j, num, index, counter, count, n, advance = 1;

    // Set all indices of the arrays keys and values to 0
    for (i = 0; i < LEN; i++) {
        keys[i] = 0;
        values[i] = 0;
    }

    scanf("%d %d", &numAmount, &threshold);
    if (numAmount <= 0 || threshold <= 0) {
        printf("\nLength of array and/or threshold is not a positive integer.");
        advance = 0;
    }

    // Main loop for adding numbers to the hash table
    for (i = 0; i < numAmount && advance == 1; i++) {
        counter = 0;
        for (j = 0; j < LEN; j++) {
            if (keys[j] != 0) {
                counter++;
            }
        }
        if (counter > LEN / 2) { // Load factor is greater than 1/2
            printf("Load factor causes program to exit.");
            break;
        }

        scanf("%d", &num);

        // Illegal character detection
//      if (!num > 0) {
//          printf("Illegal character entry. Must be an integer from 0-9.");
//          break;
//      }

        index = num % LEN;

        if (keys[index] == 0) { // empty
            keys[index] = num;
            values[index] = 1;
        }
        else if (keys[index] == num) {
            values[index]++;
        }
        else if (keys[index] != 0 && keys[index] != num) { // Collision
            count = 0, n = 1;

            while (keys[index] != 0 || keys[index] != num) { // Collision solver
                if (count > LEN) {
                    break;
                }
                index = (index + n) % LEN;
                n++;
                count++;
            }
        }
    }

    // Only prints the results out if program went through with creating the hash table
    if (advance == 1) {
        for (i = 0; i < LEN; i++) {
            if (values[i] >= threshold) {
                printf("%d ", keys[i]);
                values[i] = 0;
            }
        }
    }
    printf("\n");
}

如果我将其复制并粘贴为输入:

40 4
105 50 3 55 100
532 550 100 55 100
550 55 100 240 42
100 99 105 333 120
333 333 100 315 333
120 333 240 550 333
302 100 333 240 333
42 55 42 55 3

它返回100 55,它只是所需输出的2/3;它错过了333。

但是如果我把333放在输入的开头附近,例如:

40 4
105 333 3 55 100
53 550 100 55 100
550 55 100 240 42
100 99 105 333 120
333 333 100 315 333
120 333 240 550 50
302 100 333 240 333
42 55 42 55 3

按预期工作,并输出100 333 55

我已经仔细考虑了一段时间的代码了,我似乎无法弄清楚为什么这个数字的位置对程序正常运行至关重要。

另外,快速的次要问题,我们被要求做的事情之一是确保没有非法字符输入,基本上任何非数字。我怎么检测到这个?我知道我可以使用if语句(我在上面的代码中有一个注释掉的结构),但我不确定if语句应该是什么条件。我知道Regex,但是 C 的Regex让我非常困惑。

1 个答案:

答案 0 :(得分:3)

我发现您的代码存在一些问题。没有特别的顺序:

  • 在碰撞求解器循环之后,你永远不会对indexnum做任何事情,所以碰撞的值就会被丢弃。

  • keys[index] != 0 || keys[index] != num期间使用碰撞求解器循环将导致它拒绝任何已经与num对应的索引,因为这样的索引在keys中已经具有非零值;将||更改为&&

  • 执行index = (index + n) % LEN会导致index继续累积偏移量(至少LEN = 31)会导致某些索引被多次检查而其他索引不会被检查检查完毕。请改为index = (index + 1) % LEN并完全取消n

至于检测无效输入,只需测试scanf是否返回0(表示输入的下一部分未能与"%d"匹配)。