我的任务是编写一个名为bitpatSearch()
的函数,该函数在unsigned int
内查找指定的位模式。该函数应该有3个参数:bitpatSearch(source, pattern, n)
。它应该在整数source
中搜索n
最右边的pattern
位,并输出模式开始的位数(对于32位整数,假设为0到31位排序)如果没有匹配,则匹配并-1
。
虽然练习建议从最左边的位进行搜索,但我的代码会从最右边的位置进行搜索,因为我认为它会更容易(因为我可以使用1
进行AND值。)但是,有些东西是错误的,并且我怀疑return
语句背后的算法可能是一个问题,但无法弄明白。
程序似乎总是让位置错误,但总是正确地告诉我是否匹配。
#include <stdio.h>
int bitpatSearch(unsigned int source, unsigned int pattern, int n){
unsigned int count, x, sourceCopy;
for(count = 0; count <= 32; ++count){ //loop for all possible shifts for a 32 bit integer
x = 0;
sourceCopy = source >> count;
while(((sourceCopy & 1) == (pattern & 1)) && (x != n)){
sourceCopy >>= 1;
pattern >>= 1;
++x;
}
if(x == n) //then there is a match
return 32 - (count + n); // I think the problem is here, with basic arithmetic
}
return -1;
}
答案 0 :(得分:2)
在内部while循环中,通过在匹配位时将其移位来部分销毁pattern
。因此,如果您获得部分匹配,则pattern
将不再为后续搜索保留正确的值。代码出错的一个例子是bitpatSearch(0xf0f, 0xff, 8)
。您的代码在第12位找到匹配项,但在任何地方都没有匹配项。
我会写这样的代码:
#include <limits.h>
#define INT_BITS (CHAR_BIT * sizeof(unsigned))
int bitpatSearch(unsigned int source, unsigned int pattern, int n){
if (n == 0) return 0;
if (n > INT_BITS) return -1;
if (n == INT_BITS) return source == pattern ? 0 : -1;
pattern &= (1u << n) - 1;
for (int i = 0; i <= INT_BITS - n; i++) {
if (((source >> i) & ((1u << n) - 1)) == pattern) {
return i;
}
}
return -1;
}
与您的代码不同,它会尝试在pattern
中一次性匹配source
处的给定移位值的int
的整体,并且是可移植的,因为它不会假设if (n == INT_BITS) return source == pattern ? 0 : -1;
是一个特定的大小。
代码努力避免未定义的行为;特别是避免按INT_BITS或更多移位。例如,在构造掩码(1u << n) - 1
时,必须使用案例#include <stdio.h>
int main(int argc, char **argv) {
struct {
unsigned source, pattern;
int n;
int want;
} test_cases[] = {
{ 0x0000000fu, 0xf, 4, 0 },
{ 0x0000000fu, 0xf, 2, 0 },
{ 0xf0000000u, 0xf, 4, 28 },
{ 0xf0000000u, 0xf, 2, 28 },
{ 0x01000000u, 0x1, 4, 24 },
{ 0x80000000u, 0x1, 1, 31 },
{ 1u << (INT_BITS - 1), 0x1, 2, -1 },
{ 0xffffffffu, 0x6, 3, -1 },
{ 0x777u, 0x77, 12, 4 },
{ 0x1234abcdu, 0x1234abcdu, 32, 0 },
{ 0x1234abcdu, 0x1234abcdu, 33, -1 },
{ 0x1234abcdu, 0x42u, 0, 0 },
{ 0xf0f, 0xff, 8, -1},
};
int failed = 0;
for (int i = 0; i < sizeof(test_cases) / sizeof(test_cases[0]); i++) {
unsigned source = test_cases[i].source;
unsigned pattern = test_cases[i].pattern;
int n = test_cases[i].n;
int want = test_cases[i].want;
int got = bitpatSearch(source, pattern, n);
if (got != want) {
printf("bitpatSearch(0x%x, 0x%x, %d) = %d, want %d\n", source, pattern, n, got, want);
failed = 1;
}
}
return failed ? 1 : 0;
}
来避免非法移位。
这是代码的一些简单的单元测试。一些测试用例假设是32位int,因为我太懒了,不能使它们可移植。
{{1}}
答案 1 :(得分:2)
您需要创建pattern
的副本,因为每次进入while循环时,您都会更改pattern
的值。因此,下次进入while循环时,您将与错误的模式进行比较。
#include <stdio.h>
int bitpatSearch(unsigned int source, unsigned int pattern, int n){
unsigned int count, x, sourceCopy,patternCopy;
for(count = 0; count <= 32; ++count){ //loop for all possible shifts for a 32 bit integer
x = 0;
sourceCopy = source >> count;
patternCopy=pattern;
while(((sourceCopy & 1) == (patternCopy & 1)) && (x < n)){
sourceCopy >>= 1;
patternCopy >>= 1;
++x;
}
if(x == n) //then there is a match
return 32 - (count + n); // I think the problem is here, with basic arithmetic
}
return -1;
}
int main()
{
printf("%d",bitpatSearch(243,9,4));
return 0;
}
答案 2 :(得分:1)
您不能将32位unsigned int
移位32,它未定义。将循环更改为在32之前停止:
for (count = 0; count < 32; ++count)
或者更好,让它循环超过系统类型的大小,可能与32不同:
#include <limits.h>
...
for (count = 0; count < sizeof(source) * CHAR_BIT; ++count)
关于你的算法,如果你应该从最重要的位搜索,那就去做吧!否则,如果模式出现多次,您可能找不到预期的位置。
请注意,在没有编号系统的精确定义的情况下谈论位数是非常困惑的:最左边(最重要)位或最右边(最不重要)位是位0
吗?在C中,通常对从最低有效位到最高有效位的位进行编号,因为这与移位运算符一致(位n
具有值1U << n
),但有些人习惯于编号从左到右的位,完全相反的惯例。
答案 3 :(得分:1)
请注意,位编号通常是从右到左,最右边的位是位0。
您的代码非常复杂。嵌套循环不是必需的。这是一个简单的解决方案(模式搜索从右到左):
(编辑:代码现在包括Paul Hankin和underscore_d建议的改进。)
#include <stdio.h>
#include <limits.h>
#define NO_MATCH -1
#define ARGUMENT_ERROR -2
#define DEBUG
int bitpatSearch(unsigned int source, unsigned int pattern, unsigned int n) {
unsigned int mask;
unsigned int tmp;
int i;
/********************************************************************
* Three trivial cases:
*
* (a) If n = 0, then every pattern is a match; so return 0
* (match at position 0).
* (b) If n = CHAR_BIT * sizeof(source), then there is a match at
* position 0 if source equals pattern and no match otherwise.
* (c) If n > CHAR_BIT * sizeof(source), it makes no sence to test
* for matching patterns, because we don't know the
* n - CHAR_BIT * sizeof(source) most significant bits.
*******************************************************************/
if (n == 0)
{
return 0;
}
if (n == CHAR_BIT * sizeof(source)) {
if (source == pattern) {
return 0;
}
return NO_MATCH;
}
if (n > CHAR_BIT * sizeof(source)) {
return ARGUMENT_ERROR;
}
mask = ~((~0u) << n);
pattern &= mask;
#ifdef DEBUG
printf("mask = 0x%08x\n", mask);
printf("pattern = 0x%08x\n", pattern);
#endif
for (i = 0; i <= CHAR_BIT * sizeof(source) - n; i++) {
tmp = (source >> i) & mask;
#ifdef DEBUG
printf("tmp = 0x%08x at position %2i:\n", tmp, i);
#endif
if (tmp == pattern) {
#ifdef DEBUG
printf("Match at position %2i!\n", i);
#endif
return i;
}
}
return NO_MATCH;
}
int main() {
int result;
/*
dec 243 = bin 11110011
dec 9 = bin 1001
^ match at position 1
*/
result = bitpatSearch(243, 9, 4);
printf("Result = %i\n", result);
return 0;
}