Recursive function for sum - c

I have this recursive function, and I try to pass the result in 's' variable.
However if I use *s=*s+v[i]; the function works.
But if I try to call sum(v,i+2,s+v[i],n); It doesn't work anymore.
Can someone tell me what is wrong?
Here is the code:
void sum(int v[], int i, int *s, int n)
{
if (i < n)
{
if (v[i] < 0)
{
//*s = *s + v[i];
//sum(v, i + 2, s, n);
sum(v, i + 2, s + v[i], n);
}
else
sum(v, i + 2, s, n);
}
}
int main()
{
int n = 7;
int v[] = { -5,-8,4,4,3,9,-5 };
int i = 0;
int s = 0;
sum(v, i, &s, n);
printf("SUM IS: %d", s);
return 0;
}

There is a major difference between to 2 ways.
The correct one:
*s = *s +v[i]; // increases the int object pointed to by s
sum(v, i + 2, s, n); // still pass the same pointer to sum
The wrong one:
sum(v, i+2, s+v[i], n);
Here, the pointer is increased instead of the pointed object. It is equivalent to:
s = s +v[i]; // s is not dereferenced here!
sum(v, i + 2, s, n); // pass an incorrect pointer to sum

Looks like you have multiple problems that need correction.
First of all, the inner if is not needed. It is unclear what you wanted to do with this. Handling negative numbers separately? If so, it is not needed since the + operator can also handle addition of negative numbers.
Secondly, the s + v[i] adds the value in your array to the pointer to sum, which is not what you want. You need to use the * operator to dereference s here so that the number is added to the sum that the pointer points to. Your own commented-out code does this correctly.
Thirdly, using sum(v, i + 2, s, n); skips alternate elements so to sum the whole array properly, you need to use i + 1 instead of i + 2.
The following code fixes these issues.
void sum(int v[], int i, int *s, int n)
{
if (i < n)
{
*s += v[i];
sum(v, i + 1, s, n);
}
}
int main()
{
int n = 7;
int v[] = { -5,-8,4,4,3,9,-5 };
int i = 0;
int s = 0;
sum(v, i, &s, n);
printf("SUM IS: %d", s);
return 0;
}

Related

Swapping sections of an array

I was asked to make a function that swaps two sections in array.
Something like this,
array[] = {1 , 2, 5, 7, 8, a , b, c}
| |
sections: First Second
The signature is void reverse_reg(int *arr, int s, int k, int j) where arr is the array, s is the first index of the first section, k is the last index of the first section and j denotes the end of the second section, the start is k ( since indexing in C start from 0 )
So far I have something something like this,
void reverse_reg(int *arr, int s, int k, int j)
{
for (int i = s; i < j; i++)
{
if (i > k / 2) /* swap the rest */
{
swap(&arr[i], &arr[j - i + 1]); /* this is wrong */
}
else
{
swap(&arr[i], &arr[k + i + 1]);
}
}
}
I have tested the else block and so far it swaps successfully the second section, producing,
result:
a b c 7 8 1 2 5
Though, I haven't been able to find a way to swap the second part, since the if block, produces something completely wrong (and it makes sense), which makes me think that the initial logic is wrong. Any hints?
If it helps, the way I call the function is, reverse_reg(arr, 0, 4, 8);
The resulting array should be:
result:
a b c 1 2 5 7 8
As pointed out by #EugeneSh., a simple way is to reverse each section and then reverse the whole array. It could be as simple as:
void swap(int* i, int* j) {
int k = *i;
*i = *j;
*j = k;
}
void reverse(int arr[], int len) {
for (int i = 0; i < len / 2; i++) {
swap(arr + i, arr + len - i - 1);
}
}
void reverse_reg(int* arr, int s, int k, int j) {
// you use last index of initial section while I need index of second one
++k;
reverse(arr + s, k - s);
reverse(arr + k, j - k);
reverse(arr + s, j - s);
}
"12578abc"
"abc12578"
Assuming array is declared as unsigned char array[8];, this can be a rotate operation on 64-bit integer. Using a rotate function, we can shift "abc" to the left, and "12578" to the right, then combine their result:
uint64_t rot_left_64(uint64_t num, int n)
{
return (num << n) | (num >> (64 - n));
}
uint64_t num = 0x01020507080a0b0c;
num = rot_left_64(num , 8 * 5);
printf("%016llX\n", n); //output 0x0A0B0C0102050708

C: Determine whether a pointer exists inside an array and print the following items

I need to write a function which gets an array, it's size and a pointer, I need to check if the pointer exists in the array and if so, print all the elements after it and i'm not allowed to create local variables or use [].
This is what i did to find whether the pointer exists or not.
void printAfterX(int* arr, int n, int* x)
{
if (x < (arr + n) && x >= arr)
{
}
}
Thank you.
I'll give you two hints:
(1) Function parameters are l-values.
(2) Eventually recursion.
You should try both, even if recusion is an overkill here.
since the pointer exists
for(x; x < (arr + n); x++){
printf("%i\n", *x);
}
should do the job
You can use the operator + for this situation who works exactly like [] on pointers at this situation.
At Pseudo it's look like that:
void printAfterX(int* arr, int n, int* x)
{
if arr < x < arr+n{
print array(x)
}
}
Assuming your main data type is int, and that you want to match the content pointed by the pointer (not the pointer itself), here's a working solution:
#include <stdio.h>
void printAfterX(int*, int, int*);
int main() {
int array[] = {0, 1, 2, 3, 4, 5, 6, 7, 8, 9};
int sizeOfArray = 10;
int *pointerX = &array[4];
printAfterX(array, sizeOfArray, pointerX);
return 0;
}
void printAfterX(int* arr, int n, int* x) {
// Iterates over given array
for (int i = 0; i < n; i++) {
// If contents match
if(*(arr + i) == *x) {
for(int j = i + 1; j < n; j++) {
// Print all elements after found element
// (not-inclusive, i.e. j = i + 1)
printf("%d ", *(arr + j));
}
break; // break outer loop, because job's done
}
}
printf("\n"); // Line feed at end of iteration
}
This should also work:
bool SearchForPointer(int* arr, int n, int* x)
{
if( 0 == n)
return false;
if( arr == x)
{
while( --n)
{
arr++;
::printf( "Pointer: 0x%08X; Value: %d;\r\n", (intptr_t)(arr), *(arr));
}
return true;
}
return SearchForPointer( ++arr, --n, x);
}
int main()
{
int arr[] = {1, 2, 3, 4, 5};
int* p = arr+2;
::printf( "Searching for: p = 0x%08X; value: %d\r\n", (intptr_t)p, *p);
SearchForPointer( arr, 5, p);
return 0;
}

Using macro to get the array length inside the struct [duplicate]

This question already has answers here:
How do I determine the size of my array in C?
(24 answers)
Closed 7 years ago.
I have some C code to practice the quick sort. I want to use macro the get the length of the array. The macro works fine in the main() function. But when I use the macro inside the sort function, it does not return the length of array.
Please see the comments inside the code I left.
Also, I want to use struct to create the member function pointer called "sort" and "quick_sort". Any people who are good at c programming gives me some advise if there are some points that I can improve, not matter the syntax, the code format. I feel kind of weird about the sort and quick_sort functions format inside the struct. My purpose is use Array struct to call the functions.
#include <stdio.h>
#include <stdlib.h>
#include <string.h>
#define NELEMS(a) (sizeof(a) / sizeof(a[0]))
typedef struct _Array Array;
struct _Array
{
void (*sort)(int* arr);
void (*quick_sort)(int* arr, int l, int r);
};
void sort(int* arr);
void sort(int* arr)
{
// Issues here.
// The len is 2 not 5.
// the macro returns the sizeof arr here is 8, not 20.
int len = NELEMS(arr);
if(len == 0){
return;
}
void quick_sort(int* arr, int l, int r);
quick_sort(arr, 0, len-1);
}
void quick_sort(int* arr, int l, int r)
{
int j;
if(l < r)
{
j = partition(arr, l, r);
quick_sort(arr, l, j - 1);
quick_sort(arr, j+1, r);
}
}
int partition( int* a, int l, int r) {
int pivot, i, j, t;
pivot = a[l];
i = l; j = r+1;
while( 1)
{
do ++i; while( a[i] <= pivot && i <= r );
do --j; while( a[j] > pivot );
if( i >= j ) break;
t = a[i]; a[i] = a[j]; a[j] = t;
}
t = a[l]; a[l] = a[j]; a[j] = t;
return j;
}
void print_array(int* array, int len){
int i;
for(i = 0; i < len; i++)
printf("%d, \n", array[i]);
}
int main(int argc, char const *argv[])
{
int nums[5] = {5, 1, 3, 2, 4};
// len is 20 / 4 = 5. It works fine.
int len = NELEMS(nums);
Array *array = malloc(sizeof(Array));
array->sort = sort;
array->quick_sort = quick_sort;
sort(nums);
print_array(nums, NELEMS(nums));
return 0;
}
The macro works in main because nums is an array, sizeof(nums) gets the size of the array.
However, when it's passed as function argument, it's automatically converted to a pointer. In sort(), sizeof(nums) only gets the size of the pointer.
You could fix it by passing the size of the array explicitly.

Function Parameter Changes in C

i've tried searching for the answer/ looking at the C library for pointers, but wasn't sure on the right solution. My question concerns changing the parameters of a function. I've been reading on pointers/functions, and from my understanding, if a function takes in (int x1), then when the function is done with x1, x1 outside the function remains untouched. However, if you pass in a int *x1, then it is changed.
I've been experimenting with it, and i've tried using this with a sort method...
void sorting(int *arr, int size) {
int *i, *j, temp;
int *len = arr + size - 1;
for(i = arr; i < len; i++) {
for(j = i + 1; j <= len; j++) {
if(*j < *i) {
temp = *i;
*i = *j;
*j = temp;
}
}
}
int k;
for(k = 0; k < size; k++) {
printf("k: %d, arr[k]: %d \n", k, *(arr + k));
}
}
What this would print is a fully sorted list. However, in my main function, if I called this...
int main() {
int temp[5] = {0, 2, 1, 3, 1};
int *p = &temp[5];
sorting(pa, 5);
print the values of pa...
}
Then the list remains unsorted if printing out the values of pa.
If this question has already been solved, could someone please link the question, and i'll delete the post.
You're accessing the array out of bounds here:
int *p = &temp[5];
The valid indices are [0, 5). Presumably you want a pointer to the first element:
int *p = &temp[0];
But note that you can pass an array to a function that expects a pointer. In this case the array decays to a pointer to the first element:
sorting(temp, 5);

C Allocating array of 500 and more longs

So.. I have something like this. It is supposed to create arrays with 10, 20, 50 100 .. up to 5000 random numbers that then sorts with Insertion Sort and prints out how many comparisions and swaps were done .. However, I am getting a runtime exception when I reach 200 numbers large array .. "Access violation writing location 0x00B60000." .. Sometimes I don't even reach 200 and stop right after 10 numbers. I have literally no idea.
long *arrayIn;
int *swap_count = (int*)malloc(sizeof(int)), *compare_count = (int*)malloc(sizeof(int));
compare_count = 0;
swap_count = 0;
int i, j;
for (j = 10; j <= 1000; j*=10) {
for (i = 1; i <= 5; i++){
if (i == 1 || i == 2 || i == 5) {
int n = i * j;
arrayIn = malloc(sizeof(long)*n);
fill_array(&arrayIn, n);
InsertionSort(&arrayIn, n, &swap_count, &compare_count);
print_array(&arrayIn, n, &swap_count, &compare_count);
compare_count = 0;
swap_count = 0;
free(arrayIn);
}
}
}
EDIT: ok with this free(arrayIn); I get this " Stack cookie instrumentation code detected a stack-based buffer overrun." and I get nowhere. However without it it's "just" "Access violation writing location 0x00780000." but i get up to 200numbers eventually
void fill_array(int *arr, int n) {
int i;
for (i = 0; i < n; i++) {
arr[i] = (RAND_MAX + 1)*rand() + rand();
}
}
void InsertionSort(int *arr, int n, int *swap_count, int *compare_count) {
int i, j, t;
for (j = 0; j < n; j++) {
(*compare_count)++;
t = arr[j];
i = j - 1;
*swap_count = *swap_count + 2;
while (i >= 0 && arr[i]>t) { //tady chybí compare_count inkrementace
*compare_count = *compare_count + 2;
arr[i + 1] = arr[i];
(*swap_count)++;
i--;
(*swap_count)++;
}
arr[i + 1] = t;
(*swap_count)++;
}
}
I am sure your compiler told you what was wrong.
You are passing a long** to a function that expects a int* at the line
fill_array(&arrayIn, n);
function prototype is
void fill_array(int *arr, int n)
Same problem with the other function. From there, anything can happen.
Always, ALWAYS heed the warnings your compiler gives you.
MAJOR EDIT
First - yes, the name of an array is already a pointer.
Second - declare a function prototype at the start of your code; then the compiler will throw you helpful messages which will help you catch these
Third - if you want to pass the address of a simple variable to a function, there is no need for a malloc; just use the address of the variable.
Fourth - the rand() function returns an integer between 0 and RAND_MAX. The code
a[i] = (RAND_MAX + 1) * rand() + rand();
is a roundabout way of getting
a[i] = rand();
since (RAND_MAX + 1) will overflow and give you zero... If you actually wanted to be able to get a "really big" random number, you would have to do the following:
1) make sure a is a long * (with the correct prototypes etc)
2) convert the numbers before adding / multiplying:
a[i] = (RAND_MAX + 1L) * rand() + rand();
might do it - or maybe you need to do some more casting to (long); I can never remember my order of precedence so I usually would do
a[i] = ((long)(RAND_MAX) + 1L) * (long)rand() + (long)rand();
to be 100% sure.
Putting these and other lessons together, here is an edited version of your code that compiles and runs (I did have to "invent" a print_array) - I have written comments where the code needed changing to work. The last point above (making long random numbers) was not taken into account in this code yet.
#include <stdio.h>
#include <stdlib.h>
// include prototypes - it helps the compiler flag errors:
void fill_array(int *arr, int n);
void InsertionSort(int *arr, int n, int *swap_count, int *compare_count);
void print_array(int *arr, int n, int *swap_count, int *compare_count);
int main(void) {
// change data type to match function
int *arrayIn;
// instead of mallocing, use a fixed location:
int swap_count, compare_count;
// often a good idea to give your pointers a _p name:
int *swap_count_p = &swap_count;
int *compare_count_p = &compare_count;
// the pointer must not be set to zero: it's the CONTENTs that you set to zero
*compare_count_p = 0;
*swap_count_p = 0;
int i, j;
for (j = 10; j <= 1000; j*=10) {
for (i = 1; i <= 5; i++){
if (i == 1 || i == 2 || i == 5) {
int n = i * j;
arrayIn = malloc(sizeof(long)*n);
fill_array(arrayIn, n);
InsertionSort(arrayIn, n, swap_count_p, compare_count_p);
print_array(arrayIn, n, swap_count_p, compare_count_p);
swap_count = 0;
compare_count = 0;
free(arrayIn);
}
}
}
return 0;
}
void fill_array(int *arr, int n) {
int i;
for (i = 0; i < n; i++) {
// arr[i] = (RAND_MAX + 1)*rand() + rand(); // causes integer overflow
arr[i] = rand();
}
}
void InsertionSort(int *arr, int n, int *swap_count, int *compare_count) {
int i, j, t;
for (j = 0; j < n; j++) {
(*compare_count)++;
t = arr[j];
i = j - 1;
*swap_count = *swap_count + 2;
while (i >= 0 && arr[i]>t) { //tady chybí compare_count inkrementace
*compare_count = *compare_count + 2;
arr[i + 1] = arr[i];
(*swap_count)++;
i--;
(*swap_count)++;
}
arr[i + 1] = t;
(*swap_count)++;
}
}
void print_array(int *a, int n, int* sw, int *cc) {
int ii;
for(ii = 0; ii < n; ii++) {
if(ii%20 == 0) printf("\n");
printf("%d ", a[ii]);
}
printf("\n\nThis took %d swaps and %d comparisons\n\n", *sw, *cc);
}
You are assigning the literal value 0 to some pointers. You are also mixing "pointers" with "address-of-pointers"; &swap_count gives the address of the pointer, not the address of its value.
First off, no need to malloc here:
int *swap_count = (int*)malloc(sizeof(int)) ..
Just make an integer:
int swap_coint;
Then you don't need to do
swap_coint = 0;
to this pointer (which causes your errors). Doing so on a regular int variable is, of course, just fine.
(With the above fixed, &swap_count ought to work, so don't change that as well.)
As I told in the comments, you are passing the addresses of pointers, which point to an actual value.
With the ampersand prefix (&) you are passing the address of something.
You only use this when you pass a primitive type.
E.g. filling the array by passing an int. But you are passing pointers, so no need to use ampersand.
What's actually happening is that you are looking in the address space of the pointer, not the actual value the pointer points to in the end. This causes various memory conflicts.
Remove all & where you are inputting pointers these lines:
fill_array(&arrayIn, n);
InsertionSort(&arrayIn, n, &swap_count, &compare_count);
print_array(&arrayIn, n, &swap_count, &compare_count);
So it becomes:
fill_array(arrayIn, n);
InsertionSort(arrayIn, n, swap_count, compare_count);
print_array(arrayIn, n, swap_count, compare_count);
I also note that you alloc memory for primitive types, which could be done way simpler:
int compare_count = 0;
int swap_count = 0;
But if you choose to use the last block of code, DO use &swap_count and &compare_count since you are passing primitive types, not pointers!

Resources