I've written this small C function to remove integers from an array.
/* remove `count` integers from `arr`, starting at index `idx` */
void remove_int(int (*arr)[100], int idx, int count)
{
int i, j;
for (i = 0; i < count; i++)
for (j = idx; *arr[j]; j++)
*arr[j] = *arr[j+1];
}
Say I run it like this:
int arr[100] = {25, 4, 4, 1, 2, 1, 2};
remove_int(&arr, 7, 2);
I get a Segmentation Fault. Why?
EDIT Comment by BLUEPIXY solved it, answer by chqrlie explained it. Thanks guys!
Your code does not do what you think it does:
arr is defined as a pointer to an array of 100 int elements.
arr[j] does not point to the element at offset j, but rather to the jth array in the array pointed to by arr.
*arr[j] dereferences the integer at location arr[j][0], much beyond the end of the arr array from the calling function.
If you keep the same API, you should write the code this way:
/* remove `count` integers from `arr`, starting at index `idx` */
void remove_int(int (*arr)[100], int idx, int count) {
int i, j;
for (i = idx + count; i < 100 && (*arr)[i]; i++)
(*arr)[i - count] = (*arr)[i];
for (j = 0; j < count && i - count + j < 100; j++) {
(*arr)[i - count + j] = 0;
}
It is not idiomatic in C to handle pointers to arrays, it is more common to just pass arrays directly, and the called function receives a pointer to the first element of the array.
The function would then be called this way:
int arr[100] = {25, 4, 4, 1, 2, 1, 2};
remove_int(arr, 7, 2);
And the function would be written this way:
/* remove `count` integers from `arr`, starting at index `idx` */
void remove_int(int arr[100], int idx, int count) {
int i, j;
for (i = idx + count; i < 100 && arr[i]; i++)
arr[i - count] = arr[i];
for (j = 0; j < count && i - count + j < 100; j++) {
arr[i - count + j] = 0;
}
In this case, the [100] array size is ignored and the function behaves exactly the same as if it was defined as void remove_int(int *arr, int idx, int count)
Related
How to separate the even position number of an array from the odd position number in C.
Example
int arr[]= {2,3,4,5,6,7,8,9,1};
int odd[]= {2,4,6,8,1};
int even[] = {3,5,7,9};
Use % to get the remainder. If the remainder is nonzero, then the index is odd, otherwise even. But index starts from 0 and not 1, thus the first element's index is 0 and is even. if you want to sort according to that (seems to be you do), add 1 to index.
#include <stdio.h>
int main() {
int arr[] = {2, 3, 4, 5, 6, 7, 8, 9, 1}; // our array
const size_t max_size = sizeof(arr) / sizeof(arr[0]);
int odd[max_size];
size_t odd_cnt = 0;
int even[max_size];
size_t even_cnt = 0;
for (size_t i = 0; i != max_size; ++i) {
if ((i + 1) % 2) { // if (i + 1) % 2 is nonzero, i + 1 is odd
odd[odd_cnt++] = arr[i];
} else {
even[even_cnt++] = arr[i];
}
}
for (size_t i = 0; i != odd_cnt; ++i) {
printf("%d ", odd[i]);
}
printf("\n");
for (size_t i = 0; i != even_cnt; ++i) {
printf("%d ", even[i]);
}
printf("\n");
return 0;
}
I have learnt C language at school but I'm not good at it... And when I was trying to implement this algorithm using C language:
ReverseArray(int A[], int i, int j) {
Input: Array A, nonnegative integer indices i and j
Output: The reversal of the elements in A starting at index i and ending at j
if i < j then
swap A[i] and A[j]
ReverseArray(A, i+1, j-1)
}
I managed to code this:
int *reverseArray(int A[], int i, int j) {
int *R = NULL;
if(i < j) {
int temp = A[j];
A[j] = A[i];
A[i] = temp;
R = reverseArray(A, i+1, j-1);
return R;
} else {
return R;
}
}
But when I tried to print the original and reversed array in the main:
int main(void) {
int A[] = {1, 3, 5, 6, 8, 3, 4, 2};
int *r = reverseArray(A, 0, 7);
//This prints out the reversed array, when I intended to print the original
for (size_t i = 0; i < 8; i++) {
printf("%d ", A[i]);
}
printf("\n");
/* This was intended to print the reversed array but doesn't work
for (size_t i = 0; i < 8; i++) {
printf("%d ", r[i]);
}
*/
return 0;
}
Could anyone please explain why the commented out for loop doesn't work? And why the first for loop prints out the reversed array...
Is there any other way to get the result of reverseArray() without using *r?
I tried to malloc *r just in case that was the problem, but it still didn't work.
Thank you.
Just don't return anything. You make a reversion in place, so the resulting array is the same as the array to be reversed, and the caller knows it already.
You need to print the contents of A before you call reverseArray, not after. The reason is that you are reversing the bytes in place so the array A itself is changed by calling reverseArray.
A try from your code base and the problem description
If allowed to rewrite the Array in place, then it will work
#include<stdio.h>
void reverseArray(int A[], int i, int j) {
//int *R = NULL;
if(i < j) {
int temp = A[j];
A[j] = A[i];
A[i] = temp;
reverseArray(A, i+1, j-1);
}
}
int main(void) {
int A[] = {1, 3, 5, 6, 8, 3, 4, 2};
//This prints out original array
for (size_t i = 0; i < 8; i++) {
printf("%d ", A[i]);
}
printf("\n");
reverseArray(A, 0, 7);
// print the reversed array
for (size_t i = 0; i < 8; i++) {
printf("%d ", A[i]);
}
return 0;
}
It will Output:
1 3 5 6 8 3 4 2
2 4 3 8 6 5 3 1
R is always assigned to NULL, and A is not a pointer, then you are editing the real data of the array.
if you want to reverse and create a new array, you must do something like that :
int *reverseArray(int array[], int arraySize) {
int *reversedArray = malloc(sizeof(int) * arraySize);
for ( int i = 0 ; i < arraySize ; ++i ) {
reversedArray[i] = array[arraySize - i - 1];
}
return reversedArray;
}
You can also do it in recursive way :
int *reverseArray(int inputArray[], int arrayLength ) {
int *_reverseArray (int inputArray[], int arrayLength, int *outputArray, int actual) {
if (outputArray == NULL) {
outputArray = malloc(sizeof(int) * arrayLength);
}
if (actual < arrayLength) {
outputArray[actual] = inputArray[arrayLength - actual - 1];
return _reverseArray(inputArray, arrayLength, outputArray, ++actual);
}
return outputArray;
}
return _reverseArray(inputArray, arrayLength, NULL, 0);
}
If you want to edit the original array :
void reverseArray(int array[], int arraySize)
{
for ( int i = 0 ; i < arraySize / 2 ; ++i ) {
array[i] ^= array[arraySize - i - 1];
array[arraySize - i - 1] ^= array[i];
array[i] ^= array[arraySize - i - 1];
}
}
I was working on these problems that I found online and one of the asks to rotate a two-dimensional NxN array in-place. My code for it is the following:
#include <stdio.h>
void rotate(int n, int *s)
{
int nx, ny, tmp;
int i, j;
if(n < 1) return;
/* Compute upper small square as basis for trajectories */
if(n % 2 == 0) {
nx = ny = n/2;
}
else {
ny = (n-1)/2;
nx = ny+1;
}
/* Move elements along their trajectories */
for(i = 0; i < nx; i++) {
for(j = 0; j < ny; j++) {
tmp = *(s + n*j + n-1-i);
*(s + n*j + n-1-i) = *(s + n*(n-1-i) + n-1-j);
*(s + n*(n-1-i) + n-1-j) = *(s + n*(n-1-j) + i);
*(s + n*(n-1-j) + i) = *(s + n*i + j);
*(s + n*i + j) = tmp;
}
}
}
int main(void)
{
int test[4][4] = {
{ 1, 2, 3, 4 },
{ 5, 6, 7, 8 },
{ 9, 10, 11, 12},
{ 13, 14, 15, 16}};
int n = 4;
int i, j;
for(i = 0; i < n; i++) {
for(j = 0; j < n; j++) {
printf("%d ", test[i][j]);
}
printf("\n");
}
printf("\nRotating matrix in place...\n\n");
rotate(n, test);
for(i = 0; i < n; i++) {
for(j = 0; j < n; j++) {
printf("%d ", test[i][j]);
}
printf("\n");
}
return 0;
}
I know that the compiler will complain when I pass the two-dimensional array to rotate() in the main() function, because of the double pointer conversion from arrays to pointers. My issues are the following:
What is the correct way to declare the type of the rotate() function.
How can I do it in a way that I can use the s[i][j] notation within the function rotate() without having to resort to pointer arithmetic? I realize that the type must be able to somehow dynamically take into account the value of n, so is it possible?
I know I could circumvent the ugly notation by defining a pair of inline getter and setter functions, but that would require typing too much.
Pass additional parameters along with the pointer to an array:
void Func( size_t y , size_t x , int(*a)[x] ) {...
This is identical to
void Func( size_t y , size_t x , int a[][x] ) {...
or
void Func( size_t y , size_t x , int a[y][x] ) {...
Apart from the outermost one, all dimensions must be provided for a. In this case y is optional. But you still need it to determine the outer size of the array in the function.
The notation is then identical as with the array:
a[y-1][x-1] = 1234 ;
I've looked around online for an non-recursive k-combinations algorithm, but have had trouble understanding all of the reindexing involved; The code I've found online is not commented well, or crashes.
For example, if I have the collection, {'a', 'b', 'c', 'd', 'e'} and I want to find a 3 combinations; ie,
abc
abd
abe
acd
ace
ade
bcd
bce
bde
cde
How can I implement an algorithm to do this? When I write down the general procedure, this it is clear. That is; I increment the last element in a pointer until it points to 'e', increment the second to last element and set the last element to the second to last element + 1, then increment the last element again until it reaches 'e' again, and so on and so forth, as illustrated by how I printed the combinations. I looked at Algorithm to return all combinations of k elements from n for inspiration, but my code only prints 'abc'. Here is a copy of it:
#include <stdio.h>
#include <stdlib.h>
static void
comb(char *buf, int n, int m)
{
// Initialize a pointer representing the combinations
char *ptr = malloc(sizeof(char) * m);
int i, j, k;
for (i = 0; i < m; i++) ptr[i] = buf[i];
while (1) {
printf("%s\n", ptr);
j = m - 1;
i = 1;
// flag used to denote that the end substring is at it's max and
// the j-th indice must be incremented and all indices above it must
// be reset.
int iter_down = 0;
while((j >= 0) && !iter_down) {
//
if (ptr[j] < (n - i) ) {
iter_down = 1;
ptr[j]++;
for (k = j + 1; k < m; k++) {
ptr[k] = ptr[j] + (k - j);
}
}
else {
j--;
i++;
}
}
if (!iter_down) break;
}
}
int
main(void)
{
char *buf = "abcde";
comb(buf, 5, 3);
return 1;
}
The very big problem with your code is mixing up indices and values. You have an array of chars, but then you try to increment the chars as if they were indices into the buffer. What you really need is an array of indices. The array of chars can be discarded, since the indices provide all you need, or you can keep the array of chars separately.
I found a psuedocode description here, http://www4.uwsp.edu/math/nwodarz/Math209Files/209-0809F-L10-Section06_03-AlgorithmsForGeneratingPermutationsAndCombinations-Notes.pdf
and implemented it in C by
#include <stdlib.h>
#include <stdio.h>
// Prints an array of integers
static void
print_comb(int *val, int len) {
int i;
for (i = 0; i < len; i++) {
printf("%d ", val[i]);
}
printf("\n");
}
// Calculates n choose k
static int
choose(int n, int k)
{
double i, l = 1.0;
double val = 1.0;
for (i = 1.0; i <= k; i++) {
l = ((double)n + 1 - i) / i;
val *= l;
}
return (int) val;
}
static void
comb(int n, int r)
{
int i, j, m, max_val;
int s[r];
// Initialize combinations
for (i = 0; i < r; i++) {
s[i] = i;
}
print_comb(s, r);
// Iterate over the remaining space
for (i = 1; i < choose(n, r); i++) {
// use for indexing the rightmost element which is not at maximum value
m = r - 1;
// use as the maximum value at an index, specified by m
max_val = n - 1; // use for
while(s[m] == max_val) {
m--;
max_val--;
}
// increment the index which is not at it's maximum value
s[m]++;
// iterate over the elements after m increasing their value recursively
// ie if the m-th element is incremented, all elements afterwards are
// incremented by one plus it's offset from m
// For example, this is responsible for switching 0 3 4 to 1 2 3 in
// comb(5, 3) since 3 and 4 in the first combination are at their maximum
// value
for (j = m; j < r - 1; j++) {
s[j + 1] = s[j] + 1;
}
print_comb(s, r);
}
}
int
main(void)
{
comb(5, 3);
return 1;
}
I've written the function which bubble-sorts some given array, and stops execution when the array is already sorted.
int sort(int *arr, int size) {
int i, j, temp, st = 1, count = 0;
for(i = 0; (i < size - 1) && (st == 1); i++)
{
st = 0;
for(j = 0; j < size - 1; j++)
{
if(arr[j] < arr[j + 1])
{
temp = arr[j];
arr[j] = arr[j + 1];
arr[j + 1] = temp;
st = 1;
}
count++;
}
}
return count;
}
As you can see, the loop should be broken when the array is sorted before size^2 move.
However, something is wrong, and the count variable is always size * size, no matter what array I pass, even {1, 2, 3, 4, 5} gives the same results.
What is wrong?
With the condition
if(arr[j] < arr[j + 1])
you are sorting the array in descending order. So if you pass it [5, 4, 3, 2, 1], you'll get a value of less than size*size.
Note that each iteration of the outer loop moves one element to its final place at the end of the array, so you can cut down the inner loop to run only
for(j = 0; j < size - 1 - i; j++)
If we run
#include <stdio.h>
int sort(int *arr, int size) {
int i, j, temp, st = 1, count = 0;
for(i = 0; (i < size - 1) && (st == 1); i++)
{
st = 0;
for(j = 0; j < size - 1; j++)
{
if(arr[j] < arr[j + 1])
{
temp = arr[j];
arr[j] = arr[j + 1];
arr[j + 1] = temp;
st = 1;
}
count++;
}
}
return count;
}
int main(void) {
#ifdef ASCENDING
int ar[] = { 1, 2, 3, 4, 5 };
#else
int ar[] = { 5, 4, 3, 2, 1 };
#endif
int i, ct = sort(ar, sizeof ar / sizeof ar[0]);
printf("%d\n",ct);
for(i = 0; i < (int)(sizeof ar / sizeof ar[0]); ++i) {
printf("%d ", ar[i]);
}
printf("\n");
return 0;
}
compiled without ASCENDING defined, the output is
4
5 4 3 2 1
thus the outer loop breaks after the first iteration because the array is already sorted as desired. When compiled with -DASCENDING, the array is originally in ascending order and needs the complete cycle to become sorted, i.e. the output is
16
5 4 3 2 1
(with the count being reduced to 10 if the inner loop runs only for j < size - 1 - i).