Binary search accessing out of range index - c

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 .

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.

checking if a array has numbers in it from 0 to length -1 in C

I have got an assignment and i'll be glad if you can help me with one question
in this assignment, i have a question that goes like this:
write a function that receives an array and it's length.
the purpose of the function is to check if the array has all numbers from 0 to length-1, if it does the function will return 1 or 0 otherwise.The function can go through the array only one.
you cant sort the array or use a counting array in the function
i wrote the function that calculate the sum and the product of the array's values and indexes
int All_Num_Check(int *arr, int n)
{
int i, index_sum = 0, arr_sum = 0, index_multi = 1, arr_multi = 1;
for (i = 0; i < n; i++)
{
if (i != 0)
index_multi *= i;
if (arr[i] != 0)
arr_multi *= arr[i];
index_sum += i;
arr_sum += arr[i];
}
if ((index_sum == arr_sum) && (index_multi == arr_multi))
return 1;
return 0;
}
i.e: length = 5, arr={0,3,4,2,1} - that's a proper array
length = 5 , arr={0,3,3,4,2} - that's not proper array
unfortunately, this function doesnt work properly in all different cases of number variations.
i.e: length = 5 , {1,2,2,2,3}
thank you your help.
Checking the sum and product is not enough, as your counter-example demonstrates.
A simple solution would be to just sort the array and then check that at every position i, a[i] == i.
Edit: The original question was edited such that sorting is also prohibited. Assuming all the numbers are positive, the following solution "marks" numbers in the required range by negating the corresponding index.
If any array cell already contains a marked number, it means we have a duplicate.
int All_Num_Check(int *arr, int n) {
int i, j;
for (i = 0; i < n; i++) {
j = abs(arr[i]);
if ((j >= n) || (arr[j] < 0)) return 0;
arr[j] = -arr[j];
}
return 1;
}
I thought for a while, and then i realized that it is a highly contrained problem.
Things that are not allowed:
Use of counting array.
Use of sorting.
Use of more than one pass to the original array.
Hence, i came up with this approach of using XOR operation to determine the results.
a ^ a = 0
a^b^c = a^c^b.
Try this:
int main(int argc, char const *argv[])
{
int arr[5], i, n , temp = 0;
for(i=0;i<n; i++){
if( i == 0){
temp = arr[i]^i;
}
else{
temp = temp^(i^arr[i]);
}
}
if(temp == 0){
return 1;
}
else{
return 0;
}
}
To satisfy the condition mentioned in the problem, every number has to occour excatly once.
Now, as the number lies in the range [0,.. n-1], the looping variable will also have the same possible range.
Variable temp , is originally set to 0.
Now, if all the numbers appear in this way, then each number will appear excatly twice.
And XORing the same number twice results in 0.
So, if in the end, when the whole array is traversed and a zero is obtained, this means that the array contains all the numbers excatly once.
Otherwise, multiple copies of a number is present, hence, this won't evaluate to 0.

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

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

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);

Comparison Between two array with C

i am working on a school problem. I am supposed to compare two arrays and find the number of mismatches and perfect matches. Example : I have Array[4]={8,4,8,8} and ArrayB[4]={4,8,8,4}. It should print out 1 perfect match and 3 mismatches. My code is like this : . The perfect match works but mismatch does not. Please help: Mis_match means it has the SAME value but at different position in array. Perfect match means it has the SAME value and the same position in both arrays.
int m,n,j;
int perfect = 0;
int mis_match=0;
for (m=0;m<4;m++)
{
if(A[m]=B[m])
perfect++;
A[m]==B[m]=-1;
else
for (n=0;n<4;n++)
{
for (j=0;j<4;j++)
{
if(A[n]== B[j])
mis_match++;
break;
}
}
printf("we have %d perfect matches, %d mismatches", perfect,mis_match);
return 0;
You seem to have a few mistakes here. First:
int perfect, mis_match; // need to be intialized.
So you have to set them to 0.
int perfect = 0;
int mis_match = 0;
You also have to note that: if(A[m]=B[m]) (In your first loop) should be if(A[m]==B[m]) (You got comparison operator wrong).
In the second mismatch set, if the array size is the same, then you can simply just do array length - matches = mismatches Since if it's not a match, it's a mismatch.
Code:
int a[4] = {8,4,8,8};
int b[4] = {4,8,8,4};
int mc = 0;
for(int i=0; i < 4; ++i)
if (a[i] == b[i])
++mc;
printf("we have %d perfect matches, %d mismatches", mc, 4 - mc);
Whatever I understand you need not to use any nested loops it increases the time complexity. I think it simply.
Here is the code--
int main(){
int A[4] = {8,4,8,8};
int B[4] = {4,8,8,4};
int perfect = 0;
int mis_match = 0;
for ( int i = 0; i < 4; i++ ){
if( A[i] == B[i] )
perfect++;
else
mis_match++;
}
printf("we have %d perfect matches, %d mismatches", perfect,mis_match);
First of all, you need to initialize the variable mis_match to 0. You do not even need this variable actually. You just check each element of the first array with each element of the second array and increment perfect if they match. Then calculate the difference between the size of the array and perfect. That is the number of mismatches.
Your modified code should look like this
int perfect=0,m=4;
int A[4]={8,4,8,8},B[4]={4,8,8,4};
for(i=0;i<m;i++)
{
if(A[i]==B[i])
perfect++;
}
printf("We have %d perfect matches and %d mismatches",perfect,m-perfect);
You have used if(A[m]=B[m]), which is wrong. This statement will assign the value ofB[m] in A[m] instead of checking whether they are equal. You need to use the == operator to check their equality.

Resources