Exercise 6 from Chapter 11 Programming in C Kochan, finding bit patterns - c

hoping for some help with bitwise operators. The exercise reads as following:
Write a function called bitpat_search() that looks for the occurence of a specified pattern of bits inside an unsigned int. The function should take three arguments, and should be called as such:
bitpat_search (source, pattern, n)
The function searches for the integer "source", starting at the leftmost bit, to see if the rightmost n bits of "pattern" occur in "source". If the pattern is found, have the function return the number of the bit at which the pattern begins, where the leftmost bit is number 0. If the pattern is not found, then have the function return -1. So, for example, the call
index = bitpat_search (0xe1f4, 0x5, 3);
causes the bit_pat(search() function to search the number 0xe1f4 (= 1110 0001 1111 0100 binary) for the occurence of the three-bit pattern 0x5 (= 101 binary). The function returns 11 to indicate that the pattern was found in the "source" beginning with bit number 11.
Make certain that the function makes no assumptions about the size of an int.
I've got a few problems getting this working:
1- The numbers don't actually make much sense to me... I've tried all kinds of printf() functions after each itiration, and it looks like the 0x5 number gets read as 100 binary, which would be four. If I try other numbers they just come fairly random, but often as 000, so.... not very helpful. Am I counting them wrong? Does the right shift change it somehow?
2 - it's returning the wrong position (19 rather than 11), but while I'm messing up the numbers as my q1 above, it's not really going to work, is it?
Sorry if this is obvious to all you lovely people, I just can see it. (I'm just trying to learn from the book btw, it's not homework from school).
Thanks
#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;
}

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);
Here, you're checking a bit at position i in the source against a bit at position j in the pattern. That needs to be i+j in the source, otherwise you compare a pattern against one bit, rather than a pattern against a number of bits, in the source. Since the pattern 101 contains ones and a zero, you'll never find anything.
Side note: you can replace the int_size function by sizeof(int)*8. That assumes 8-bit bytes, but computers for which that assumption does not hold haven't been made since the early eighties, so that should be a fairly safe assumption.

1- The numbers don't actually make much sense to me... I've tried all kinds of printf() functions after each itiration, and it looks like the 0x5 number gets read as 100 binary, which would be four. If I try other numbers they just come fairly random, but often as 000, so.... not very helpful. Am I counting them wrong?
I can't comment on code you've not presented, but of course hex 0x5 is binary 101. I'm inclined to suppose that in your tests you printed different values than you thought you were printing, or that your mechanism for printing them was flawed.
Does the right shift change it somehow?
Shift operators leave their operands unchanged. Of course, if the right-hand operand of a conforming shift operation is non-zero then the result differs from the left-hand operand. If the left-hand operand is drawn from a variable, then you might conceivably overwrite that variable's value afterward.
2 - it's returning the wrong position (19 rather than 11), but while I'm messing up the numbers as my q1 above, it's not really going to work, is it?
I don't think your main problem is "messing up the numbers". Your implementation is problematic. Consider the key loop nest in your code:
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++;
Observe that you increment the outer loop's control variable on each iteration of the inner loop. As a result, you test the pattern only against every nth starting index in the source string. That is, you test non-overlapping sets of the source bits. You should instead test the whole pattern starting at every possible starting position.
Note also that you test starting positions where an n-bit pattern cannot possibly start, on account of there being fewer than n bits between that position and the end of the source string. In this case you will end up invoking undefined behavior by using an invalid right-hand operand to a shift operator.

In the proposed algorithm, except the revealed issue by #WouterVerhelst, it exists other issues causing a wrong result.
Issue 1 - In the function bit_test(), the tested-bit is not the expected one.
To test a bit from the leftmost side, replace (size - position) by
(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;
}
Issue 2 - To be tested as the same size of source, the pattern shall be aligned to left.
In the bitpat_search(), before for-loop, shift-left of (size-n)
bits.
int size = int_size(source);
pattern = pattern << (size-n);
Issue 3 - To have the correct count to be compared with n, the comparison of bits with the break; should be done before count++.
if (tempSource != tempPat)
break;
count++;
Issue 4 - The index result returned would be i instead of i - n (linked with Issue 5).
if (count == n)
return (i); // instead of (i - n);
Issue 5 - As #WouterVerhelst suggests, the comparison between source and pattern should be done for each bit.
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);
}
Issue 6 - And the result in case of 'pattern not found' is -1.
return (-1); // Instead of (0);

Related

Decimal to binary - For loop prints the binary in reverse mode

Background on what the code is supposed to do, vs what I am achieving.
So the dec2bin function is supposed to get the values/numbers decimal from the array dec_nums[]={0, 1, 77, 159, 65530, 987654321};
the function is supposed to convert the value to binary numbers and print it out.
the conversion is done correctly however, it prints the binary backward.
Can someone help me on figuring out what the problem is, or if there is another way to achieve the correct results?
int main() {
int dec_nums[] = {0, 1, 77, 159, 65530, 987654321};
int i;
printf("=== dec2bin ===\n");
for (i = 0; i < sizeof(dec_nums) / sizeof(int); i++)
dec2bin(dec_nums[i]);
return 0;
}
void dec2bin(int num) {
int saveNum = num;
if (saveNum == 0) {
printf("\nBinary Number of %d", saveNum);
printf(" = 0");
} else {
int number;
int i;
printf("\nBinary Number of %i", saveNum);
printf(" = ");
for (i = 0; num > 0; i++) {
number = num % 2;
num = num / 2;
printf("%i", number);
}
printf("\n");
}
}
For bit fiddling unsigned types are preferrable, you avoid any kinds of problems with undefined behaviour due to under-/overflow.
Apart from, you can operate on bit masks:
for(unsigned mask = 1u << sizeof(mask) * CHAR_BIT - 1; mask; mask >>= 1)
{
unsigned bit = (value & mask) != 0;
// print it
}
CHAR_BIT is the value of bits within a char and comes from header limits.h, typically (but not necessarily) it is 8, with typically four bytes for ints you initialise the mask to 1 << 31 and further on shift it downwards until it reaches 1 << 0, i. e. 1, which is the last value yet considered. Yet another shift moves the single bit set out of the mask, so you get 0 and the loop aborts.
Above code will print leading zeros, you might prepend another loop that simply shifts down until the first 1-bit is met if you want to skip them.
This variant starts at most significant bit; by % 2 you always get the least significant bit instead – which is why you got the inverse order.
Side note: Getting length of an array is better done as sizeof(array)/sizeof(*array) – this avoids errors if you need to change the underlying type of the array...
A simple solution would be to write to bits into a char array, starting from the end of the array, the same way that we would do by hand.
Your dec2bin function would become (only minimal changes, with comments for added or changed lines):
void dec2bin(int num)
{
// declare a char array of size number_of_bits_in_an_int + 1 for the terminating null
char bin[sizeof(int) * CHAR_BIT + 1];
char* ix = bin + sizeof(bin) - 1; // make ix point to the last char
*ix-- = '\0'; // and write the terminating null
int saveNum = num;
if (saveNum == 0)
{
printf("\nBinary Number of %d", saveNum);
printf(" = 0");
}
else
{
int number;
int i;
printf("\nBinary Number of %i", saveNum);
printf(" = ");
for (i = 0; num > 0; i++)
{
number = num % 2;
num = num / 2;
*ix-- = '0' + number; // just write the bit representatin
}
printf("%s\n", ix+1); //print the binary representation
}
}
That is enough to get the expected result.

Decimal to binary using c language

I am very new to Coding. Here is a program that I wrote to convert decimal to binary
but there is one problem I am getting the result but it's in reverse
Example: Binary of 122 is 1111010 and I'm getting output 0101111.
Can anyone please tell me is it possible to reverse the output in my code?
Or what changes can I make in the following to get the correct output?
#include<stdio.h>
int main()
{
int n, q, r;
printf("Enter the decimal Number : ");
scanf("%d", &n);
int num=n;
while(n!=0)
{
r=n%2;
q=n/2;
printf("%d", r);
n=q;
}
return 0;
}
Seems like you are new to coding. It doesn't matter here is the problem.
Converting decimal to binary is like this,
eg:
division by 2
quotient
reminder
bit
10/2
5
0
0
5/2
2
1
1
2/2
1
0
2
1/2
0
1
3
=(1010)
So the output should have digits from bottom to top of the reminder column. Your output is printed from top to bottom.
See the code below where you need an array in order to store reminders and print the array in reverse order so you get the output you need
#include<stdio.h>
#include<stdlib.h>
int main(void){
int a[10],n,i;
printf("Enter the decimal Number : ");
scanf("%d",&n);
for(i=0;n>0;i++)
{
a[i]=n%2;
n=n/2;
}
printf("\nBinary of Given Number is=");
for(i=i-1;i>=0;i--)
{
printf("%d",a[i]);
}
return 0;
}
void display(unsigned n)
{
if(n == 0) return;
display(n /2);
printf("%d", n % 2);
}
and example usage:
https://godbolt.org/z/ahGPc74nf
As a homework: how to correctly handle 0?
Or not recursive version. This one can print or not leading zeroes:
void display(unsigned n, int printzeroes)
{
unsigned mask = 1 << (CHAR_BIT * sizeof(mask) - 1);
int print = printzeroes;
while(mask)
{
if(n & mask)
{
print = 1;
}
if(print) printf("%d", !!(n & mask));
mask >>= 1;
}
}
And usage: https://godbolt.org/z/7Eq71TMWb
First of all, please note that all numbers in a C program are to be regarded as binary. It's a common misconception among beginners that different number formats somehow co-exist in the executable program. But everything there is raw binary.
Sure the programmer may write numbers in different formats 7, 07 or 0x7 in the source code, but they get translated to binary by the compiler. Therefore, converting between binary and "x" doesn't make sense, because everything is already binary. You may however, convert from binary to a decimal string or similar, for the purpose of displaying a number to the user etc.
With that misconception out of the way - yes, you can create a binary string with the method you picked, dividing by ten and checking the remainder. The problem with that approach is that you'll get the most significant digit first. This is why you get the number backwards. So in order to do that, you'd have to store down the string in a character array first, before displaying it.
A more convenient way would be to use the "bitwise" operators like & and shift to mask out bit by bit in the data. Basically this:
if(n & (1u << bit)) // 1u to avoid shifting signed type
printf("1");
else
printf("0");
Where bit is the bit position 7,6,5... down to 0. If we prefer an up-counting loop instead, we can tweak the code into:
for(size_t i=0; i<8; i++)
{
size_t mask = 1u << 8-i-1;
...
}
And finally we can make the output a bit more compact, which is just a stylistic concern:
for(size_t i=0; i<8; i++)
{
size_t mask = 1u << 8-i-1;
printf("%c", n & mask ? '1' : '0');
}
If you aren't dead certain about C operator precedence, then use parenthesis, which is perfectly fine too:
for(size_t i=0; i<8; i++)
{
size_t mask = 1u << (8-i-1);
printf("%c", (n & mask) ? '1' : '0');
}
Here's the homework demanded by 0___________:
void printbin(int n)
{
static int depth;
if (n) ++depth, printbin(n / 2), --depth;
else if (depth) return; // print leading 0 only for n = 0
printf("%d", n % 2);
}
A leading 0 is not printed unless on the topmost recursion level.
You could maybe create an array of size 32 and keep adding the digits to the array. Or create a int variable and add the digits to the variable.
int result = 0;
while(n!=0)
{
r=n%2;
n=n/2;
result = result*10+r;
}

Subtracting arbitrary large integers in C

Question:
I want to know the difference of number n and a, both stored in char
arrays in ALI structures. Basically, what I'm doing is initialising
two integers (temp_n and temp_a) with the current digits of n and a,
subtracting them and placing the result in a new ALI instance named
k. If the j-th digits of a is greater than the i-th digit of n, then
I add 10 to the digit if n, finish the subtraction, and in the next
turn, I increase temp_a by one. The value of number a certainly falls
between 1 and n - 1 (that's given). If a is shorter than n, as soon
as I reach the last digits of a, I put the remaining digits of n to
the result array k. And I do this all backwards, so the initialising
value of i would be the size of n -1.
Example:
I store a number in a structure like this:
typedef struct Arbitrary_Large_Integer
{
char digits[];
} ALI;
Requirements:
I know that it could be easier to use char arrays instead of a
structure with a single member which barely makes sense, but I'm
forced to put structures in my code this time (that's a requirement
for my assignment).
Code:
ALI *subtraction(ALI n, ALI a, int nLength, int aLength)
{
ALI *result;
result = (ALI*)malloc(nLength * sizeof(ALI));
if (result == NULL)
printf("ERROR");
int temp_n, temp_a, difference;
int i = nLength - 1; //iterator for number 'n'
int j = aLength - 1; //iterator for number 'a'
int k = 0; //iterator for number 'k', n - a = k
bool carry = false; //to decide whether a carry is needed or not the turn
for (i; i >= 0; i--)
{
//subtracting 48 from n.digits[i], so temp_n gets the actual number
//and not its ASCII code when the value is passed
temp_n = n.digits[i] - ASCIICONVERT;
temp_a = a.digits[j] - ASCIICONVERT;
//Performing subtraction the same way as it's used on paper
if (carry) //if there is carry, a needs to be increased by one
{
temp_a++;
carry = false;
}
if (temp_n >= temp_a)
{
difference = temp_n - temp_a;
}
//I wrote else if instead of else so I can clearly see the condition
else if (temp_a > temp_n)
{
temp_n += 10;
difference = temp_n - temp_a;
carry = true;
}
//placing the difference in array k, but first converting it back to ASCII
result->digits[k] = difference + ASCIICONVERT;
k++;
//n is certainly longer than a, so after every subtraction is performed on a's digits,
//I place the remaining digits of n in k
if (j == 0)
{
for (int l = i - 1; l >= 0; l--)
{
result->digits[k] = n.digits[l];
k++;
}
//don't forget to close the array
result->digits[k] = '\0';
break;
}
j--;
}
//reverse the result array
_strrev(result->digits);
return result;
}
Output/Error:
Output results
It seems like when the array is passed to the function, its value
changes for some reason. I can't figure out what's wrong with it.
Problems:
Non-standard C
The typedef is not a valid standard C structure. The Flexible Array Member(FAM) .digits must be accompanied by at least one more prior named member in addition to the flexible array member. Recommend to put .nLength as the first member.
// Not standard
typedef struct Arbitrary_Large_Integer {
char digits[];
} ALI;
malloc(0)??
Since code is using a non-standard C, watch out that nLength * sizeof(ALI) may be the same as nLength * 0.
No room for the null character
Code is attempting to use .digits as a string with _strrev(), themallloc() is too small by 1, at least.
Other problems may exist
A Minimal, Complete, and Verifiable example is useful for additional fixes/solutions

Binary search accessing out of range index

This is the code:
char binarySearch(unsigned int target, int* primes, unsigned int size){
int* ptrToArray = primes;
unsigned int first = 0;
unsigned int last = size;
while (first <= last){
unsigned int middle = first + (last - first) / 2;
printf("first: %d, last: %d, middle: %d\n", first, last , middle);
if (ptrToArray[middle] == target){
return 1;
}
if (ptrToArray[middle] < target){
first = middle + 1;
}else{
last = middle - 1;
}
}
return 0;
}
This is the output:
I've been staring at that peace of code for more than one should and still can't figure out where is the flaw.
If middle is 0, as near the end of your debug output, the statement
last = middle - 1
causes an integer overflow; the conditions have to be reworked a bit.
You may get an out of bound when you are looking for an element not in the array, and is bigger than the array, due to allowing keep iteration when last and first equal each other in while (first <= last)
Think of what happens when you send an empty array: size == 0:
first = 0, last = 0, and thus: (first <= last) == true.
Then, middle = 0 + (0 - 0)/2 = 0, and next you access ptrToArray[0], which is out of bound.
The problem is that you define your index variables (first, last, middle) as unsigned int while in your logic, last can in fact become negative. However, in that case, since they're defined as unsigned and because of the way 2's complement representation of negative numbers works, the condition in your while loop is still true.
Take a look at the following example code for illustration:
#include <stdio.h>
int main() {
/* defining the variables as unsigned */
unsigned int first_u = 0;
unsigned int last_u = -1;
if (first_u <= last_u)
printf("less than\n");
else
printf("greater or equal\n");
/* defining the variables as signed */
int first_s = 0;
int last_s = -1;
if (first_s <= last_s)
printf("less than\n");
else
printf("greater or equal\n");
return 0;
}
Other than that, you should use either < in your while-condition or define the initial value of last as size-1. Otherwise, if you're searching for an element that is greater than the last element in your array, you will run out of bounds.
Firstly the negative value of middle is due to overflow (unsigned int).
Also I think you should have : unsigned int last = size-1 because if first becomes equal to last=size the you will use ptrToArray[middle] and middle=size so it will be out of array bounds. This will solve also the case of size =0 mentioned above .
Finally to make your code more easy to read you could write :
middle =(first+last)/2 which is the middle of [first,last] space, and equals to first+(last-first)/2 .

grey codes using 2d arrays (C)

My assignment is to print out grey codes using recursion. A user puts in a bit value between 0-8, therefore the maximum amount of strings you can have is 256 (2^8).
I've got the base case done but i don't know what I would do for the else portion.
My code so far:
#include <stdio.h>
#include <math.h>
#include <stdlib.h>
void gcodes (int n) {
char bits[256][8];
int i, j;
int x = pow (2, n);
if (n == 1) {
bits[0][0] = '0';
bits[1][0] = '1';
} else {
gcodes (n-1);
}
for (i=0; i<x; i++) {
for (j=0; j<n; j++) {
printf("%c", reverse[i][j]);
}
printf("\n");
}
}
int main(int argc, char *argv[]) {
if (argc != 2) {
printf("Invalid number of arguments\n");
return 0;
}
int n;
n = atoi (argv[1]);
if (n > 8 || n <= 0) {
printf("Invalid integer\n");
return 0;
}
gcodes (n);
}
a gray code can have only one bit change from one number to the next consecutive number. and over the whole sequence, there are no repeated values.
Given that criteria, there are several possible gray code implementations.
There are several deadend sequences where the values start off ok, then fail,
Calculating a gray code via code will take lots of experimentation.
In reality it is much easier to simply find a valid gray code sequence from the net, and paste that into any program that needs a gray code sequence.
Most often, a input is a gray coded wheel that is read to determine if the wheel moved rather than something generated in code.
however, if I were implementing a gray code generator, I would expect it to perform exclusive-or between the last generated value and the proposed new/next value and if that is valid (only one bit changed) I would search through the existing table of values to assure it is not a duplicate.
this SO question suggests a possible algorithm:
Non-recursive Grey code algorithm understanding
and the answer is repeated below:
The answer to all four your questions is that this algorithm does not start with lower values of n. All strings it generates have the same length, and the i-th (for i = 1, ..., 2n-1) string is generated from the (i-1)-th one.
Here is the first few steps for n = 4:
Start with G0 = 0000
To generate G1, flip 0-th bit in G0, as 0 is the position of the least significant 1 in the binary representation of 1 = 0001b. G1 = 0001.
To generate G2, flip 1-st bit in G1, as 1 is the position of the least significant 1 in the binary representation of 2 = 0010b. G2 = 0011.
To generate G3, flip 0-th bit in G2, as 0 is the position of the least significant 1 in the binary representation of 3 = 0011b. G3 = 0010.
To generate G4, flip 2-nd bit in G3, as 2 is the position of the least significant 1 in the binary representation of 4 = 0100b. G4 = 0110.
To generate G5, flip 0-th bit in G4, as 0 is the position of the least significant 1 in the binary representation of 5 = 0101b. G5 = 0111.
Since you define
char bits[256][8];
with automatic storage duration inside the function gcodes(), the array's lifetime ends when returning from the function, so you lose the results of the recursive calls. Thus, at least define it
static char bits[256][8];
or globally if you want to keep the resulting bits for use outside of gcodes().
Since in the standard Gray code the least significant bit (bit 0) follows the repetitive pattern of 0110, it is convenient to set the complete pattern in the base case even if it is not needed for n = 1.
For the ith code's bit j where j > 0, its value can be taken from bit j-1 of code i/2.
This leads to the completed function:
void gcodes(int n)
{
static char bits[256][8];
int i, j, x = pow(2, n);
if (n == 1)
{
bits[0][0] = '0';
bits[1][0] = '1';
bits[2][0] = '1';
bits[3][0] = '0';
}
else
{
gcodes(n-1);
// generate bit j (from n-1 down to 1) for codes up to x-1
for (i=0, j=n; --j; i=x/2)
for (; i<x; i++)
bits[i][j] = bits[i/2][j-1];
// replicate bit 0 for codes up to x-1
for (; i<x; i++)
bits[i][0] = bits[i%4][0];
}
for (i=0; i<x; i++, printf("\n"))
for (j=n; j--; )
printf("%c", bits[i][j]);
}

Resources