Passing by Reference fails [C Programming] - c

I'm trying to use the function targetSum to find out if there are two values in the array that match the target value entered by the user. It takes in the array, the target, the 2 indices, and the size of the array. When I try to output the result in the main function, the value of indices does not change (even though I'm passing as reference). Help appreciated! [code below]
int targetSum(int arr[], int size, int target, int index1, int index2)
{
int max, min, sum;
index1 = 0;
index2 = size - 1;
min = arr[index1];
max = arr[index2];
while (index1 != index2) {
sum = max + min;
if (sum == target) {
return 1;
}
else if (sum < target) {
index1++;
min = arr[index1];
}
else if (sum > target) {
index2--;
max = arr[index2];
}
}
return -1;
}
int index1, index2 = 0;
int target;
if(target == -999){ // the program exits if the user enters target as -999
printf("Good Bye");
break;
}
if (targetSum(toArr, size, target, &index1, &index2) == 1) {
printf("Output: Success! Elements at indices ");
printf("%d", index1);
printf(" and ");
printf("%d", index2);
printf(" add up to ");
printf("%d", target);
printf("\n");
}
else {
printf("Output: Target sum failed!\n");
}

What you're passing to the function doesn't match what it's expecting.
The last two parameters to targetSum are of type int but you're passing in values of type int *. Your compiler should have warned you about this.
Change the function parameters to pointers:
int targetSum(int arr[], int size, int target, int *index1, int *index2)
Then dereference them as necessary in the body of the function.

In function definition, add pointer operator (*) everywhere before variables index1 and index2

Related

Core dumped error while trying to store double values in an array

For some reason, when I enter more values than the size of the array, the program returns an array with a weird value, then sorts it, and then the program returns an error saying "core dumped". My function shouldn't be out of bounds...
` //Function to store values from command line into array
void store_array(int argc, char *argv[], double arr[], int max_size){
if (argc<2){
printf("If you wish to store values in the array, enter them after the program command!\n");
}
int i;
for (i = 1; i < argc && i <= max_size; i++) {
arr[i-1] = atof(argv[i]);
}
if (argc - 1 > max_size){
printf("Sorry, but this function can only store %d values. The rest of the values weren't used.", max_size);
}
}
// Function to sort the array
void sort_arrays(double array[], int array_size){
int step, i;
double tmp;
for (step = 0; step < array_size-1; step++){
for (i=0; i < array_size - step - 1; i++){
if (array[i] > array[i+1]){
tmp = array[i];
array[i] = array[i+1];
array[i+1] = tmp;
}
}
}
return;
}
// Function to print the array
void print_double_array(double a2[], int num_entries){
int i;
for (i = 0; i < num_entries; i++) {
printf("%.2f\n", a2[i]);
}
}`
I used an array with a max_size of 10, below you will find my function to store the values into an array, to print the array, and the one to sort it. Thank you for your help.
Potentially you might be passing incorrect array_size/num_entries value to sort_arrays() or print_double_array(), because you are not returning the number of items in array from store_array(). Probably you need to take min(argc-1, max_size) as an array size, but it's too easy to forget about it and pass argc-1.
I would change store_array() to return the actual array size to avoid such situations.

Can this recursive function be optimized?

Is there a way to optimize the first defined function in attached code?
I wonder if the exercise I've done can be optimized for readability and performance. The exercise was about determining if the array, which stores the integer values is incrementally well sorted (every digit is greater than the previous [i.e. 1,2,3,4,5]), just incrementally sorted (the numbers are generally incrementally sorted, but there can be few with the same values in a row [i.e. 1,3,3,5]), or not sorted at all incrementally [i.e. 4,2,1].
The exercise has to be done by using recursive approach in the most optimized way. Below is my solution proposition:
// find if the array is well sorted incrementally, sorted incrementally or not sorted at all
// the function should return 1 if array is well sorted or just sorted and return 0 otherwise
// the function should pass by refference 1 if the array is well sorted or 0 otherwise
// the result will be thus determined based on those two parameters in separate function
// recursive approach
#include <stdio.h>
#define SIZE1 5 // constants for ready arrays tests
#define SIZE2 4 // ...
#define SIZE3 3 // ...
int findIfArrayIsSorted(int array[], int size, int *precision);
void printResult(int result, int precision);
void specifyInputArraySize(int *size);
void inputArrayElements(int array[], int size);
void printArrayElements(int array[], int size);
int findIfArrayIsSorted(int array[], int size, int *precision)
{
if (size > 1)
{
if (array[size-1] < array[size-2])
{
*precision = 0;
return 0;
}
else if (array[size-1] == array[size-2])
{
*precision = 0;
return findIfArrayIsSorted(array, size - 1, precision);
}
else if (array[size-1] > array[size-2])
return findIfArrayIsSorted(array, size - 1, precision);
}
return 1;
}
void printResult(int result, int precision)
{
if (result == 1 && precision == 1)
printf("This array is well sorted\n");
else if (result == 1 && precision == 0)
printf("This array is sorted\n");
else
printf("This array isn't sorted\n");
}
void specifyInputArraySize(int *size)
{
printf("Please enter the size: ");
scanf("%d", size);
}
void inputArrayElements(int array[], int size)
{
int i;
printf("Please input array elements (one by one):\n");
for (i = 0; i < size; i++)
scanf("%d", &array[i]);
}
void printArrayElements(int array[], int size)
{
int i;
printf("The elements stored in an array are:\n");
for (i = 0; i < size; i++)
printf("Element[%d] is %d\n", i, array[i]);
}
int main(void)
{
int result;
int precision;
// tests for ready arrays
int numArrayW[SIZE1] = {1, 2, 3, 4, 5};
int numArrayS[SIZE2] = {1, 3, 3, 5};
int numArrayU[SIZE3] = {4, 2, 1};
precision = 1; // default assumption
printArrayElements(numArrayW, SIZE1);
result = findIfArrayIsSorted(numArrayW, SIZE1, &precision);
printResult(result, precision);
precision = 1; // default assumption
printArrayElements(numArrayS, SIZE2);
result = findIfArrayIsSorted(numArrayS, SIZE2, &precision);
printResult(result, precision);
precision = 1; // default assumption
printArrayElements(numArrayU, SIZE3);
result = findIfArrayIsSorted(numArrayU, SIZE3, &precision);
printResult(result, precision);
// test for inputted array
int size;
precision = 1; // default assumption
specifyInputArraySize(&size);
int numInputtedArray[size];
inputArrayElements(numInputtedArray, size);
printArrayElements(numInputtedArray, size);
result = findIfArrayIsSorted(numInputtedArray, size, &precision);
printResult(result, precision);
return 0;
}
I would really appreciate if someone will find more optimized solution, thanks.
This variant optimizes for neither readability nor performance, but rather for usability and conformance, because it doesn't require the caller to preset the reference argument with the default assumption 1.
int findIfArrayIsSorted(int array[], int size, int *precision)
{
if (size <= 1) return *precision = 1;
if (array[size-1] < array[size-2]) return *precision = 0;
int sorted = findIfArrayIsSorted(array, size-1, precision);
*precision &= array[size-1] > array[size-2];
return sorted;
}

How to solve this error when trying to compute the twoSums coding question in C

Given an array of integers, return indices of the two numbers such that they add up to a specific target.
Given nums = [2, 7, 11, 15], target = 9,
Because nums[0] + nums[1] = 2 + 7 = 9,
return [0, 1].
#include<stdio.h>
int* twoSum(int* nums, int numsSize, int target);
int main(){
int*array;
int arraySize;
scanf("%d",&arraySize);
for (int i=0;i<arraySize;i++){
scanf("%d",&array[i]);
}
int target;
scanf("%d",&target);
int* positions=twoSum(array, arraySize, target);
printf("The positions are: %p",positions);
return 0;
}
int* twoSum(int* nums, int numsSize, int target){
int *returnSize = NULL;
for(int i=0,sum=0;i<numsSize;i++){
for(int j=0;j<numsSize;j++){
sum =sum+nums[i]+nums[j];
if(sum==target){
returnSize[0]=nums[i];
returnSize[1]=nums[j];
}
else
returnSize[0]= -1;
returnSize[1]= -1;
}
}
return returnSize;
}
The error I am getting makes reference to a line that is empty in my code. Please help
there are mistakes in this code.First you should allocate memory for int*array; after taking int arraySize; as input , you can do it like this
array = malloc(sizeof(int) * arraySize);
then here %p is not appropriate , instead use %d. Take look here for more information about %p %p format specifier and also since you want to print 2 positions you need to call two arguments in printf like this printf("The positions are: %d %d", positions[0], positions[1]);
In your twoSum function , you need to allocate memory for int* returnSize ; like this returnSize = malloc(sizeof(int) * 2);
and here you are not returning positions of found elements , you are returning elements themselfs.
if(sum==target){
returnSize[0]=nums[i];
returnSize[1]=nums[j];
}
also you need to add return in this if-statement other wise , you will traverse array completely and returnSize elements will become -1 again(unless answer is too last element of array)
so this if should be like this:
if (sum == target) {
returnSize[0] = i;//num[i] is not position. it is element of array
returnSize[1] = j;//num[j] is not position .it is element of array
return returnSize;//otherwise it will traverse array compeltely and they -1 again
}
also only if you code one line for if,else,while,for,... (conditional statements) ,you can avoid using braces ,otherwise only one line of your code will executed ,if that condition become true ,so you have to add a block for this else:
else
{
returnSize[0] = -1;
returnSize[1] = -1;
}//coding more than one line so your else should be in a block
and also here sum=sum+num[i]+num[j]; is wrong you should change this to sum=num[i]+num[j]; because you only want to check sum of two current number ,or better way don't use sum at all only check equality of target with num[i]+num[j]
here is complete code:
int* twoSum(int* nums, int numsSize, int target);
int main() {
int* array;
int arraySize;
scanf("%d", &arraySize);
array = malloc(sizeof(int) * arraySize);//allocate memory for array
for (int i = 0; i < arraySize; i++) {
scanf("%d", &array[i]);
}
int target;
scanf("%d", &target);
int* positions = twoSum(array, arraySize, target);
printf("The positions are: %d %d", positions[0], positions[1]);//%p is for not for content of array
return 0;
}
int* twoSum(int* nums, int numsSize, int target) {
int* returnSize ;
returnSize = malloc(sizeof(int) * 2);
for (int i = 0; i < numsSize; i++) {
for (int j = 0; j < numsSize; j++) {
if (nums[i] + nums[j] == target) {
returnSize[0] = i;//num[i] is not position. it is element of array
returnSize[1] = j;//num[j] is not position .it is element of array
return returnSize;//otherwise it will traverse array compeltely and they -1 again
}
else
{
returnSize[0] = -1;
returnSize[1] = -1;
}//coding more than one line so your else should be in a block
}
}
return returnSize;
}
There is some mistakes in your code:
memory allocation
You declare pointers on int to store data to process and result, but you do not allocate memory: malloc is for Memory ALLOCation:
array = malloc(sizeof *array * arraySize);
and
int *returnSize = malloc(sizeof *returnSize * 2);
Sum calculation logic
sum value
In twoSum function, the sum variable is getting bigger and bigger: sum =sum+nums[i]+nums[j];
Instead, a simple if (target == nums[i] + nums[j]) will perform the test you wanted.
sum test
In your code, each time sum is not equal to target, you reset returnSize[0] to -1
You do not have to have an else clause: you can initialize the returnSize before the for loop.
missing {...}
Look at your first code: for any value of sum and target, returnSize[1] is set to -1 because you've forgotten to put accolades after the else (but, as written before, you do not even need an else)
gcc can warn you about such issue (-Wmisleading-indentation, or better -Wall)
for(int j=0;j<numsSize;j++){
sum =sum+nums[i]+nums[j];
if(sum==target){
returnSize[0]=nums[i];
returnSize[1]=nums[j];
}
else
returnSize[0]= -1;
returnSize[1]= -1;
}
Considering this, you can write a code that do what you wanted.
Be careful, you should test the scanf and malloc return values too...
#include <stdio.h>
#include <stdlib.h>
int *twoSum(int *nums, int numsSize, int target);
int main()
{
int *array;
int arraySize;
// TODO: test that scanf returned 1
scanf("%d", &arraySize);
// TODO: test that arraysize is at least 2
/* allocate array to store the numbers*/
array = malloc(sizeof *array * arraySize);
for (int i = 0; i < arraySize; i++) {
// TODO: test that scanf returned 1
scanf("%d", &array[i]);
}
int target;
// TODO: test that scanf returned 1
scanf("%d", &target);
int *positions = twoSum(array, arraySize, target);
printf("The positions are: %d(%d) %d(%d)\n", positions[0], array[positions[0]], positions[1], array[positions[1]]);
/* memory has been allocated? free it */
free(positions)
free(array)
return 0;
}
int *twoSum(int *nums, int numsSize, int target)
{
int *returnSize = malloc(sizeof *returnSize * 2);
returnSize[0] = returnSize[1] = -1;
for (int i = 0; i < numsSize; i++) {
for (int j = 0; j < numsSize; j++) {
if (target ==nums[i] + nums[j] ) {
returnSize[0] = i;
returnSize[1] = j;
return returnSize;
}
}
}
return returnSize;
}
Here your code:
#include <stdio.h>
#include <stdlib.h>
#include <stdbool.h>
int* twoSum(int* nums, int numsSize, int target);
void print_pos(int * arr, int i) {
printf("test %d\n", i);
if (arr != NULL) {
printf("position 1 = %d, position 2 = %d\n", arr[0], arr[1]);
} else
printf("Not found\n");
}
int main(){
int array[5] = {5, 6, 2 ,1 ,3} ;
int target1 = 11, target2 = 9, target3 = 15;
int * positions1=twoSum(array, 5, target1);
int * positions2=twoSum(array, 5, target2);
int * positions3=twoSum(array, 5, target3);
print_pos(positions1, 1);
print_pos(positions2, 2);
print_pos(positions3, 3);
return 0;
}
int* twoSum(int* nums, int numsSize, int target){
int *return_arr = malloc(sizeof(int) * 2);
bool found = false;
for(int i=0;i<numsSize;i++){
for(int j=0;j<numsSize;j++){
if((nums[i]+nums[j])==target){
return_arr[0]= i;
return_arr[1]= j;
found = true;
}
}
}
if (found)
return return_arr;
else {
free(return_arr);
return NULL;
}
}

value searching in an ascending arrays in two different ways

I am doing a project for my C class. We are going to find the value in an ascending array with 10 distinctive numbers, then search the value users wanna and return the index of the searching number. The first method is called Linear Search which compare each element in the array to the value user wanted. The second method is called Binary, which you take the middle index compare with the searching value. If List[middle] = target element then return the variable middle which is the index of the element. In the case that target element is greater than List[Middle], then continue the process on the right half of the array. If it is lesser, then continue the same process on the left half of the array. The process of halving is done only until the ‘Left’ index variable is less than or equal to the ‘Right’ index variable. In case the target element is not found , -1 is returned.
#include<stdio.h>
int main()
{
int array[10];
int i = 0,value;
printf("Please enter 10 distinctive postive numbers with ascending order.");
for(i;i<10;i++)
{
scanf("%d",&array[i]);
}
printf("What value are you seaching for?");
scanf("%d",value);
printf("searchLinear(value,*array[10],10)");
return 0;
}
int searchLinear(int s,int *list[10],int n){
list[n];
int i = 0;
for(i;i<n;i++)
{
if(s == *list[i])
return *list[i];
}
if(i = n)
return -1;
}
int searchBinary(int s, int *list[10],int n) {
list[n];
int i,left,right,middle;
left = 0;
right = n-1;
for(i = 0;i<n/2;i++)
{
middle = (left + right)/2;
if(*list[middle] > s)
right = middle;
else if(*list[middle] < s)
left = middle;
else if(*list[middle] = s)
return *list[middle];
if(left == right)
return -1;
}
}
This is my code, looks like it runs into an infinite loop. How can I fix it?
The corrected code is
#include<stdio.h>
int searchLinear(int s,int list[],int n);
int searchBinary(int s, int list[],int n); //you need to give forward declaration of funcs
int main()
{
int array[10];
int i = 0,value;
printf("Please enter 10 distinctive postive numbers with ascending order.");
for(i;i<10;i++)
{
scanf("%d",&array[i]);
}
printf("What value are you seaching for?");
scanf("%d",&value); //you missed & here
printf("%d",searchBinary(value,array,10));
return 0;
}
int searchLinear(int s,int list[],int n){ // you can use this format of arguments
//list[n]; //what did you wanted to do with this line
int i = 0;
for(i;i<n;i++)
{
if(s == list[i])
return i; //return index not value
}
if(i = n)
return -1;
}
int searchBinary(int s, int list[],int n){
//list[n];
int i,left,right,middle;
left = 0;
right = n-1;
for(i = 0;i<n/2;i++)
{
middle = (left + right)/2;
if(left > right) //you have to check left>right, instead of left==right
return -1;
if(list[middle] > s)
right = middle-1;
else if(list[middle] < s)
left = middle+1;
else if(list[middle] == s) //== is used for comparision
return middle;
}
}
Observe the corrections in comments

C - Custom qsort not working

I am trying to make a qsort type of function that has the same paramenters. I also wrote 3 functions to compare int, float and characters. For some reason it does not work in any case.
I don't know whether this is a problem regarded my qsortx function or not, but I checked it several times and it should work perfectly fine. I am not sure what the problem is, or what I am doing wrong. I am currently learning the function pointers and I might not have got everything right related to it. Thanks in advance.
#include <stdio.h>
#include <stdlib.h>
#include <string.h>
void qsortx(void*, int, int, int (*)(const void*, const void*));
int intcmp();
int floatcmp();
int charcmp();
int main()
{
int i,n;
char items[]={'c', 'a', 'b'};
n = 3;
for (i=0;i<n;++i) {
printf("%c ", items[i]);
}
printf("\n");
qsortx(items, n, sizeof(char), charcmp);
for (i=0;i<n;++i) {
printf("%c ", items[i]);
}
printf("\n");
return 0;
}
void qsortx (void *tp, int length, int pace, int(*fp)(const void* a, const void* b)) {
int switched,i,j;
void *p;
p=(void*)malloc(pace);
switched = 1;
while (1) {
if (switched == 0) {
return;
}
switched = 0;
for (i=0; i<length-1;++i) {
for (j=0;j<length-1;++j) {
printf("%c %c", tp+i, tp+j);
if (fp(tp+i, tp+j) > 0) {
memcpy(p, tp+i, pace);
memcpy(tp+i, tp+j, pace);
memcpy(tp+j, p, pace);
switched++;
}
}
}
}
}
int intcmp(const void* a, const void* b) {
return *(int*)a - *(int*)b;
}
int floatcmp(const void* a, const void* b) {
return *(float*)a - *(float*)b;
}
int charcmp(const void* a, const void* b) {
return *(char*)a - *(char*)b;
}
You have multiple problems related to pointer arithmetic and element sizes. You also have a logic error in your sort (which I guess you know is a unidirectional shaker sort). Here's a version of the qsortx() function that fixes these deficiencies:
void qsortx (void *tp, int length, int pace, int(*fp)(const void* a, const void* b)) {
if (length > 1) {
char *bound = ((char *) tp) + (length * pace);
char *p = malloc(pace);
char *item1p;
for (item1p = tp; item1p < (bound - pace); item1p += pace) {
char *item2p;
for (item2p = item1p + pace; item2p < bound; item2p += pace) {
if (fp(item1p, item2p) > 0) {
memcpy(p, item1p, pace);
memcpy(item1p, item2p, pace);
memcpy(item2p, p, pace);
}
}
}
free(p);
}
}
Note that:
All pointer arithmetic is performed on values of type char *.
The element size (pace) must be taken into account as you step through the input array, else you just scramble your data.
The innermost loop should start at the element after the one being considered in the next-outer loop.
switched = 1 is a better choice than switched ++ because it cannot overflow, and all you care about is zero vs. non-zero. (Update: but switched is no longer relevant.)
(Update) It is incorrect to exit early in the event that a pass through the item1p loop results in zero swaps. Just because one element is already in its correct place does not mean that all the subsequent elements are also in their correct places. I updated my code above to remove that behavior.
(Update) As chux observed, the temporary space reserved for swapping elements was not freed. I added an appropriate free(p).
(Update) I also made sorting conditional on the array length being greater than 1, which avoids undefined behavior associated with bound - pace in the event that the length is zero.
here is the pseudo code and implementation of the quicksort (qsort) algorithm, with some accessory code, as defined in the http://www.codingbot.net/2013/01/quick-sort-algorithm-and-c-code.html web page:
Note that this algorithm is slightly different from qsort()
in that there is a different parameter list and certain other details.
However, the basic algorithm is the same.
function quicksort('array')
if length('array') ≤ 1
return 'array' // an array of zero or one elements is already sorted
select and remove a pivot value 'pivot' from 'array'
create empty lists 'less' and 'greater'
for each 'x' in 'array'
if 'x' ≤ 'pivot'
then append 'x' to 'less'
else
append 'x' to 'greater'
endif
end for
return concatenate(quicksort('less'), 'pivot', quicksort('greater') );
notice that qsort is a partition sort, using recursion.
#include<stdio.h>
#include<conio.h>
void quick_sort(int arr[20],int,int);
int main()
{
int arr[20],n,i;
clrscr();
printf("Enter the number of elements in the Array: ");
if( 1 != scanf(" %d",&n) )
{
perror( "scanf for count of elements" );
exit(1);
}
printf("\nEnter %d elements:\n\n",n);
for(i=0 ; i<n ; i++)
{
printf(" Array[%d] = ",i);
if( 1 != scanf(" %d",&arr[i]) )
{
perror( "scanf for element values" );
exit(2);
}
}
quick_sort(arr,0,n-1);
printf("\nThe Sorted Array is:\n\n");
for(i=0 ; i<n ; i++)
{
printf(" %4d",arr[i]);
}
getch();
}
void quick_sort(int arr[20],int low,int high)
{
int pivot; // used in partitioning the array
int j; // loop index
int temp; // for swapping
int i; // loop index
if(low<high)
{
pivot = low;
i = low;
j = high;
while(i<j)
{
// find next item not in proper sequence
while((arr[i] <= arr[pivot]) && (i<high))
{
i++;
}
// find next item not in proper sequence
while(arr[j] > arr[pivot])
{
j--;
}
// following is where a callback function would be invoked
if(i<j)
{
temp=arr[i];
arr[i]=arr[j];
arr[j]=temp;
}
}
temp=arr[pivot];
arr[pivot] = arr[j];
arr[j]=temp;
// following is where recursion is used to perform sort on sub partitions
quick_sort(arr,low,j-1);
quick_sort(arr,j+1,high);
}
}
this is a much better algorithm for your purposes.
however, it only handles integers, so you would need to
add the comparison function as a 4th parameter to quicksort()
and modify the code to use your comparison function
#include <stdio.h>
#include <stdlib.h>
void swap(int *x,int *y);
int choose_pivot(int i,int j );
void quicksort(int list[],int m,int n);
void display(int list[],const int n);
int main()
{
const int SIZE = 10;
int list[SIZE];
int i = 0;
/* generates random numbers and fill the list */
for(i = 0; i < SIZE; i++ )
{
list[i] = rand();
}
printf("The list before sorting is:\n");
display(list,SIZE);
/* sort the list using quicksort algorithm */
quicksort(list,0,SIZE-1);
printf("The list after sorting:\n");
display(list,SIZE);
}
void swap(int *x,int *y)
{
// for integer swaps, 3 exclusive OR operations would be much faster
// and not require a temp variable
int temp;
temp = *x;
*x = *y;
*y = temp;
}
int choose_pivot(int i,int j )
{
return((i+j) /2);
}
void quicksort(int list[],int m,int n)
{
int key,i,j,k;
if( m < n)
{
k = choose_pivot(m,n);
swap(&list[m],&list[k]);
key = list[m];
i = m+1;
j = n;
while(i <= j)
{
while((i <= n) && (list[i] <= key))
{
i++;
}
while((j >= m) && (list[j] > key))
{
j--;
}
if( i < j)
{
swap(&list[i],&list[j]);
}
}
/* swap two elements */
swap(&list[m],&list[j]);
/* recursively sort the lesser list */
quicksort(list,m,j-1);
quicksort(list,j+1,n);
}
}
void display(int list[],const int n)
{
int i;
for(i=0; i<n; i++)
{
printf("%d\t",list[i]);
}
}

Resources