练习6来自C Kochan的第11章编程,找到位模式

时间:2017-01-08 18:33:12

标签: c bitwise-operators bits

希望对按位运算符有所帮助。练习内容如下:

  

编写一个名为bitpat_search()的函数,该函数查找unsigned int内指定的位模式的出现。该函数应该有三个参数,应该这样调用:

   bitpat_search (source, pattern, n)
     

该函数从最左边的位开始搜索整数" source",以查看" pattern"的最右边n位。发生在"来源"。如果找到模式,则让函数返回模式开始的位数,其中最左边的位为数字0.如果找不到模式,则使函数返回-1。所以,例如,电话

   index = bitpat_search (0xe1f4, 0x5, 3);
     

导致bit_pat(search()函数搜索数字0xe1f4(= 1110 0001 1111 0100二进制)以查找三位模式0x5(= 101二进制)的出现。函数返回11表示模式为发现在"来源"从第11位开始。

     

确保该函数不对int的大小做出假设。

我在解决这个问题上遇到了一些问题:

1-这些数字对我来说实际上没什么意义......我在每次尝试后尝试了各种printf()函数,看起来像0x5数字被读为100二进制,这将是四个。如果我尝试其他数字,他们只是相当随机,但往往作为000,所以....不是很有帮助。我算错了吗?右移是否会以某种方式改变它?

2 - 它返回了错误的位置(19而不是11),但是当我把这些数字搞砸为上面的q1时,它并没有真正发挥作用,是吗? ?

对不起,如果这对你所有可爱的人都很明显,我就能看到它。 (我只是试着从书中学到btw,它不是学校的家庭作业)。

由于

#include <stdio.h>

int int_size(unsigned int num);
int bit_test(unsigned int word, int position, int size);
int bitpat_search(unsigned int source, unsigned int pattern, int n);

int main(void)
{
    int index;

    index  = bitpat_search(0xe1f4, 0x5, 3);

    printf(" Pattern found in position %i\n", index);
    return 0;
}

int bitpat_search(unsigned int source, unsigned int pattern, int n)
{
    int i, j, tempSource, tempPat, count;

    int size = int_size(~0);

    for (i = 0; i < size;)
    {
        count = 0;
        for (j = 0; j < n; j++)
        {
            tempSource = bit_test(source, i, size);
            tempPat = bit_test(pattern, j, size);

            i++;
            count++;

            if (tempSource != tempPat)
            break;
        }
        if (count == n)
            return i - n;
    }
    return 0;

}

int bit_test(unsigned int word, int position, int size)
{
    if( (word >> (size - position)) & 0x1) // shift bits in word 31 minus n     spaces right, and AND word with hexadecimal 1
        return 1; // if above is true (1 & 1) return 1
    else
        return 0;

}

int int_size(unsigned int num)
{
    int size = 0;

    while (num)
    {
        size++;
        num >>= 1;
    }

    return size;
}

3 个答案:

答案 0 :(得分:0)

for (i = 0; i < size;)
{
    count = 0;
    for (j = 0; j < n; j++)
    {
        tempSource = bit_test(source, i, size);
        tempPat = bit_test(pattern, j, size);

在这里,您要检查源中位置i处的位与模式中位置j处的位。它必须在源中为i+j,否则您将源模式中的模式与一位进行比较,而不是将模式与 number 位进行比较。由于模式101包含1和0,所以你永远找不到任何东西。

附注:您可以用int_size替换sizeof(int)*8功能。这假设是8位字节,但自80年代初以来,这种假设不适用的计算机尚未成功,因此这应该是一个相当安全的假设。

答案 1 :(得分:0)

  

1-数字对我来说实际上没有多大意义......我在每次尝试后都尝试过各种printf()函数,看起来像0x5数字被读为100二进制,这将是四强。如果我尝试其他数字,他们只是相当随机,但往往作为000,所以....不是很有帮助。我算错了吗?

我无法评论您未提供的代码,但当然,十六进制0x5是二进制101。我倾向于认为在您的测试中,您打印的值与您认为打印的值不同,或者您打印它们的机制存在缺陷。

  

右移是否会以某种方式改变它?

Shift操作符保持其操作数不变。当然,如果符合移位操作的右手操作数不为零,则结果与左手操作数不同。如果左侧操作数是从变量中提取的,那么您可能会想到之后会覆盖该变量的值。

  

2 - 它返回错误的位置(19而不是11),但是当我把数字搞砸为上面的q1时,它确实不会起作用,是吗?

我不认为你的主要问题是“弄乱数字”。您的实施存在问题。考虑代码中的密钥循环嵌套:

for (i = 0; i < size;)
{
    count = 0;
    for (j = 0; j < n; j++)
    {
        tempSource = bit_test(source, i, size);
        tempPat = bit_test(pattern, j, size);

        i++;
        count++;

注意在内循环的每次迭代中递增外循环的控制变量。因此,您只对源字符串中的每个n th 起始索引测试模式。也就是说,您测试非重叠的源位集。你应该从每个可能的起始位置开始测试整个模式。

另请注意,由于该位置与源字符串结尾之间的位数少于n-bit,因此您可以测试n模式无法启动的起始位置。在这种情况下,您将最终通过对移位运算符使用无效的右侧操作数来调用未定义的行为。

答案 2 :(得分:0)

在提出的算法中,除了@WouterVerhelst发现的问题外,还存在导致错误结果的其他问题。

问题1 - 在函数bit_test()中,测试位不是预期的位。

  

要从最左侧测试一下,请将(size - position)替换为   (size - (position + 1))

int bit_test(unsigned int word, int position, int size)
{
    if( (word >> (size - (position + 1))) & 0x1) // 
        return 1; // if above is true (1 & 1) return 1
    else
        return 0;
}

第2期 - 要以source的相同大小进行测试,pattern应与左侧对齐。

  

bitpat_search()之前,for-loop之前,左移(size-n)   位。

int size = int_size(source);

pattern = pattern << (size-n);

问题3 - 要将正确的countn进行比较,应在{{1}之前完成与break;的比较}}

count++

第4期 - 返回的索引结果为 if (tempSource != tempPat) break; count++; 而不是i(与问题5相关联)。

i - n

第5期 - 正如@WouterVerhelst建议的那样,应该为每个位进行if (count == n) return (i); // instead of (i - n); source之间的比较。

pattern

第6期 - “未找到模式”的结果为-1。

for (i = 0; i < size;i++) // each bit ==> i++
{
    count = 0;
    for (j = 0; j < n; j++)
    {
        tempSource = bit_test(source, i+j, size);
        tempPat = bit_test(pattern, j, size);
        // not here i++;

        if (tempSource != tempPat)
            break;

        count++;
    }
    if (count == n)
        return (i);
}