EDIT: Originally I had transcribed i++ not i--
The code now is as it was, and the code in the code block compiles and works.
Why, if unsigned int i; is used instead of int i; in the code snippet below, does using the function result in a segfault?
void insertion_sort_int_array(int * const Ints, unsigned int const len) {
unsigned int pos;
int key;
int i;
for (pos = 1; pos < len; ++pos) {
key = Ints[pos];
for (i = (pos - 1); (i >= 0) && Ints[i] > key; i--) {
Ints[i + 1] = Ints[i];
}
Ints[i + 1] = key;
}
}
THe posted code will fail in either case (possibly with a segfault, possibly only corrupting memory).
The inner loop starts at pos-1 and scans upwards in memory until some random condition is met - it does not check if it has passed the end of the array, so will run merrily on until it crashes or the end condition happens to be met by the (undefined) contents of the memory it is corrupting.
You probably meant to scan downwards in memory (using i-- in the loop), in which case it would fail because the loop will reach 0. Subtracting 1 from 0 gives you a very large positive number in an unsigned, so the loop will never end (i>=0 is always true) and it will access some memory somewhere in the region of Pluto.
insertionSort(array A)
begin
for x := 1 to length[A]-1 do
begin
value := A[x];
i := x - 1;
while i >= 0 and A[i] > value do
begin
A[i + 1] := A[i];
i := i - 1;
end;
A[i + 1] := value;
end;
end;
The only difference between the standard insertion sort algorithm and your code is that you're incrementing i instead of decrementing. That's your problem. I bet that in the code you're actually compiling and running, you have i-- instead of i++ in the inner loop. That's why the unsigned i makes a difference - it cannot be negative, so the inner loop will never end. Did you copy the code wrong when you posted?
EDIT:
Well, now that you changed the posted code, it all makes sense, right? An unsigned i will simply underflow to INT_MAX when you decrement it past 0, which will cause you to access memory outside of the array bounds.
What keeps i+1 within the bounds of your array 'ints'? It looks like badly formed data in your array will cause you to index into areas of memory which you shouldn't be in.
Why, if unsigned int i; is used
instead of int i; in the code snippet
below, does using the function result
in a segfault?
Because for unsigned int i, i >= 0 is always true, so your for loop is unlikely to terminate when you want.
You should always be extremely careful when looping backwards (from high to low) if your counter is unsigned.
i will [wraparound] causing access beyond the array limits.
Importing limits and comparing to UINT_MAX instead of the previous (i >= 0) fixes the issue:
#include <limits.h>
void insertion_sort_int_array(int * const Integers, unsigned int const N)
{
unsigned int o;
int target;
unsigned int i;
for (o = 1; o < N; o++) {
target = Integers[o];
for (i = (o - 1); (i != UINT_MAX) && (Ints[i] > target); i--) {
Integers[i + 1] = Integers[i];
}
Integers[i + 1] = key;
}
}
Related
I have a function named num_to_binary, which is used to convert a decimal number stored in the form of array. The prototype for this function num_to_binary is as below:
void num_to_binary(int *number_b, int size_of_number);
Here:
number_b is pointer to array which stores my number. For example, if I would like to convert the number 12345 to binary, then I will be storing 12345 in number_b as follows:
number_b[0] = 1
number_b[1] = 2
number_b[2] = 3
number_b[3] = 4
number_b[4] = 5
Also, size_of_number is the number of digits in the number (or it is the number of elements in the array number_b). So for the number 12345, size_of_number has the value 5.
Below is the full declaration of the function num_to_binary:
void num_to_binary(int *number_b, int size_of_number)
{
int *tmp_pointer = malloc(1 * sizeof(int));
int curr_size = 1;
int i = 0;
while(!is_zero(number_b,size_of_number))
{
if(i != 0)
{
curr_size += 1;
tmp_pointer = realloc(tmp_pointer, curr_size * sizeof(int));
}
if(number_b[size_of_number - 1] % 2 == 1)
{
tmp_pointer[i] = 1;
divide_by_2(number_b,size_of_number);
i = i + 1;
}
else
{
tmp_pointer[i] = 0;
divide_by_2(number_b,size_of_number);
i = i + 1;
}
}
int *fin_ans;
fin_ans = malloc(curr_size * sizeof(int));
for(int j = 0 ; j < curr_size; j++)
{
fin_ans[curr_size-1-j] = tmp_pointer[j];
}
}
In the above function:
tmp_pointer: It is initially allocated some memory using malloc(), and is used to store the reverse of the binary representation of the number stored in number_b
curr_size: It stores the current size of tmp_pointer. It is initially set to 1.
i: It is used to keep track of the while loop. It is also used to reallocation purpose, which I have explained a bit later.
is_zero(number_b, size_of_number): It is a function, which returns 1 if the number stored in number_b is 0, else it returns 1.
divide_by_2(number_b, size_of_number): It divides the number stored in number_b by 2. It does NOT change the size of the array number_b.
fin_ans: It is an integer pointer. Since the binary representation stored in the array tmp_pointer will be the reverse of the actual binary representation of the number, so fin_ans will store the correct binary representation of number by reversing the content of tmp_pointer.
Below is the how this function works :
First of all, tmp_pointer is allocated a memory equal to the
size of 1 int. So, now tmp_pointer can store an integer.
We now go into the while loop. The loop will terminate only
when the number stored in number_b equals 0.
Now, we check if i is equal to 0 or not. If it is not equal to
zero, then this means than the loops has been run atleast once, and
in order to store the next binary digit, we resize the memory
allocated to tmp_pointer so that it can store the next bit.
If the last digit of the number is odd, then that implies that the
corresponding binary digit will be 1, else it will be 0. The
if and else condition do this task. They also increment
i each time one of them is executed, and also divide the number by 2.
Now, we are out of the loop. It's time to reverse the binary number
stored in tmp_pointer to get the final answer.
For this, we create a new pointer called fin_ans, and allocate
it the memory which will be used for storing the correct binary
representation of the number.
The last for loop is used to reverse the binary representation
and store the correct binary representation in fin_ans.
The problem:
The code runs for small numbers such as 123, but for large numbers such as 1234567891, it gives a segmentation fault error. This can be checked by trying to print the digits stored in fin_ans.
I tried using GDB Debugger, and got to know that the reason for Segmentation Fault lies in the while loop. I am sure that the functions divide_by_2 and is_zero are not the reason for Segmentation Fault, since I have tested them thoroughly.
I also used DrMemory, which indicated that I am trying to access (read or write) a memory location which has not been allocated. Unfortunately, I am not able to figure out where the error lies.
I suspect realloc() to be the cause of Segmentation Fault, but I am not sure.
Apologies for such a long question, however, I would highly appreciate any help provided to me for this code.
Thanks in advance for helping me out !
There are multiple problems in the code:
you do not check for memory allocation failure
you forget to free tmp_pointer before leaving the function.
you allocate a new array fin_ans to reserve the array tmp_pointer and perform the reverse operation but you do not return this array to the caller, nor do you have a way to return its size. You should change the prototype to return this information.
if the number of zero, the converted number should probably have 1 digit initialized as 0, but you use malloc which does not initialize the array it allocates so tmp_pointer[0] is uninitialized.
you did not provide the code for is_zero() nor divide_by_two(). It is possible that bugs in these functions cause the segmentation fault, especially if the loop does not reach zero and memory is eventually exhausted during this infinite loop.
Here is a modified version:
int *num_to_binary(int *number_b, int size_of_number, int *binary_size) {
int i, j, curr_size;
int *p, *newp;
curr_size = 1;
p = malloc(1 * sizeof(int));
if (p == NULL)
return NULL;
p[0] = 0;
for (i = 0; !is_zero(number_b, size_of_number); i++) {
if (i != 0) {
curr_size += 1;
newp = realloc(p, curr_size * sizeof(int));
if (newp == NULL) {
free(p);
return NULL;
}
p = newp;
}
p[i] = number_b[size_of_number - 1] % 2;
divide_by_2(number_b, size_of_number);
}
for (i = 0, j = curr_size; i < j; i++)
int digit = p[--j];
p[j] = p[i];
p[i] = digit;
}
*binary_size = curr_size;
return p;
}
There is no need for multiple memory reallocations. Result memory buffer size could be easily evaluated as binary logarithm of the decimal input value. Calculation of the number binary representation could also be simplified:
//Transform binary array to actual number
int arr2int(int* pIntArray, unsigned int nSizeIn) {
if (!pIntArray || !nSizeIn)
return 0;
int nResult = 0;
for (unsigned int i = 0; i < nSizeIn; ++i)
nResult += pIntArray[i] * (int)pow(10, nSizeIn - i - 1);
return nResult;
}
int* int2bin(int* pIntArray, unsigned int nSizeIn, unsigned int* nSizeOut){
//0) Converting int array to the actual value
int nVal = arr2int(pIntArray, nSizeIn);
//1)Evaluating size of result array and allocating memory
if(!nVal)
*nSizeOut = 1;
else
*nSizeOut = (int)floor(log2(nVal)) + 1;
//2)Allocate and init memory
int* pResult = malloc(*nSizeOut);
memset(pResult, 0, *nSizeOut * sizeof(int));
//3) Evaluate binary representation
for (unsigned int i = 0; i < *nSizeOut; ++i){
int nBinDigit = (int)pow(2, i);
if (nBinDigit == (nVal & nBinDigit))
pResult[*nSizeOut - i - 1] = 1;
}
return pResult;
}
Testing:
#include <stdio.h>
#include <math.h>
#include <stdlib.h>
#include <string.h>
#define _DC 9
int main()
{
int test[_DC];
for (int i = 0; i < _DC; ++i)
test[i] = i;
unsigned int nRes = 0;
int* pRes = int2bin(test, _DC, &nRes);
for (unsigned int i = 0; i < nRes; ++i)
printf("%d", pRes[i]);
free(pRes);
return 0;
}
EDIT:
I forgot to mention that I do not want to allocate another temporarily array.
I am trying to solve a problem in C, which is:
Suppose you were given an array a and it's size N. You know that all of the elements in the array are between 0 to n-1. The function is supposed to return 0 if there is a missing number in the range (0 to n-1). Otherwise, it returns 1. As you can understand, duplicates are possible. The thing is that its supposed to run on O(n) runtime.
I think I managed to do it but i'm not sure. From looking at older posts here, it seems almost impossible and the algorithm seems much more complicated then the algorithm I have. Therefore, something feels wrong to me.
I could not find an input that returns the wrong output yet thou.
In any case, I'd appreciate your feedback- or if you can think of an input that this might not work for. Here's the code:
int missingVal(int* a, int size)
{
int i, zero = 0;
for (i = 0; i < size; i++)
//We multiply the element of corresponding index by -1
a[abs(a[i])] *= -1;
for (i = 0; i < size; i++)
{
//If the element inside the corresponding index is positive it means it never got multiplied by -1
//hence doesn't exist in the array
if (a[i] > 0)
return 0;
//to handle the cases for zeros, we will count them
if (a[i] == 0)
zero++;
}
if (zero != 1)
return 0;
return 1;
}
Just copy the values to another array placing each value in its ordinal position. Then walk the copy to see if anything is missing.
your program works and it is in O(N), but it is quite complicated and worst it modify the initial array
can be just that :
int check(int* a, int size)
{
int * b = calloc(size, sizeof(int));
int i;
for (i = 0; i != size; ++i) {
b[a[i]] = 1;
}
for (i = 0; i != size; ++i) {
if (b[i] == 0) {
free(b);
return 0;
}
}
free(b);
return 1;
}
This problem is the same as finding out if your array has duplicates. Here's why
All the numbers in the array are between 0 and n-1
The array has a size of n
If there's a missing number in that range, that can only mean that another number took its place. Which means that the array must have a duplicate number
An algorithm in O(n) time & O(1) space
Iterate through your array
If the sign of the current number is positive, then make it negative
If you found a negative this means that you have a duplicate. Since all items are originally greater (or equal) than 0
Implementation
int missingVal(int arr[], int size)
{
// Increment all the numbers to avoid an array with only 0s
for (int i = 0; i < size; i++) arr[i]++;
for (int i = 0; i < size; i++)
{
if (arr[abs(arr[i])] >= 0)
arr[abs(arr[i])] = -arr[abs(arr[i])];
else
return 0;
}
return 1;
}
Edit
As Bruno mentioned if we have an array with all zeros, we could have run into a problem. This is why I included in this edit an incrementation of all the numbers.
While this add another "pass" into the algorithm, the solution is still in O(n) time & O(1) space
Edit #2
Another great suggestion from Bruno which optimizes this, is to look if there's more than one zero instead of incrementing the array.
If there's 2 or more, we can directly return 0 since we have found a duplicate (and by the same token that not all the numbers in the range are in the array)
To overcome the requirement that excludes any extra memory consumption, the posted algorithm changes the values inside the array by simply negating their value, but that would leave index 0 unchanged.
I propose a different mapping: from [0, size) to (-1 - size, -1], so that e.g. {0, 1, 2, 3, 4, ...} becomes {-1, -2, -3, -4, -5, ...}. Note that, for a two's complement representation of integers, INT_MIN = -INT_MAX - 1.
// The following assumes that every value inside the array is in [0, size-1)
int missingVal(int* a, int size) // OT: I find the name misleading
{
int i = 0;
for (; i < size; i++)
{
int *pos = a[i] < 0
? a + (-a[i] - 1) // A value can already have been changed...
: a + a[i];
if ( *pos < 0 ) // but if the pointed one is negative, there's a duplicate
break;
*pos = -1 - *pos;
}
return i == size; // Returns 1 if there are no duplicates
}
If needed, the original values could be restored, before returning, with a simple loop
if ( i != size ) {
for (int j = 0; j < size; ++j) {
if ( a[j] < 0 )
a[j] = -a[j] - 1;
}
} else { // I already know that ALL the values are changed
for (int j = 0; j < size; ++j)
a[j] = -a[j] - 1;
}
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);
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 .
so my requirements are
REQUIRES: n >= 1. Elements a[0] ... a[n-1] exist.
PROMISES
The return value is 1 if n == 1.
If n > 1, the return value is 1 if a[0] ... a[n-1] form
an arithmetic sequence.
PROMISES
Otherwise, the return value is 0.
my function so far is
int is_arith_seq(const int *a, int n)
{
assert(n >= 1);
if (n == 1)
return 1;
int i;
int initaldif = a[1]-a[0];
int currentdif,result;
for (i=0;i<n;i++)
{
currentdif = a[i+1]-a[i];
if(initaldif!=currentdif)
return 0;
}
return 1;
}
My code does not work,as I am completely stuck now, what can I do to correct it.
If array has n elements your for loop will cause a segmentation fault. It goes all the way to n-1 but you are accessing a[i+1]. a[n] is out of bounds. Modify like this :
for (i = 0; i < n - 1; i++)
{
currentdif = a[i+1]-a[i];
if (initaldif != currentdif)
return 0;
}
Problem is here
currentdif = a[i+1]-a[i];
What do you think will happen to this code during n-1 th iteration?
i = n-1 + 1 = n
Therefore the function either returns 1 if n=1 or returns 0 due to the error!
Off-by-one errors are one of the most common programming mistakes. A good way to quickly track many of these down is to look at the very first and last iterations of your loops.
Your intent is that your loop computes the differences
a[1]-a[0] a[2]-a[1] ... a[n-1]-a[n-2]
The first iteration has i=0 and computes a[1]-a[0], and the last iteration has i=n-1 and computes a[n]-a[n-1]. Whoops, that's wrong! Need to adjust the loop.
Your arithmetic sequence test should set the initialdif as you have done, but then predict what the next element is throughout the sequence. If any term fails, the string of numbers is not an arithmetic sequence:
int initaldif = a[1]-a[0];
for (i = 2; i < n; i++)
if (a[i] != a[i-1] + initaldif)
return 0;
return 1;