One array copying data to 2 other arrays using C pointers - c

I am new to Programming and to Stack overflow, so forgive me if I make any mistakes. I have this program where one array of ints is split into two other arrays depending on if they are larger or smaller than a user inputted int. Right now all the smaller and larger arrays do is copy the first integer regardless of the number put in. Any suggestions/critiques?
/*
This program will separate an input array into two arrays. One array will be filled by
elements greater than a specified number and the other array will be filled by elements
less than the specified number.
*/
#include <stdio.h>
void separate(int *a, int n, int value, int *larger, int *size, int *smaller);
int main()
{
//Find size of array
int length;
int *length_pointer = &length;
printf("Enter the length of the array: ");
scanf("%d", length_pointer);
//Enter array elements
int array[length], *p;
printf("Enter %d numbers: ", length);
for(p = array; p < array + length; p++)
scanf("%d", p);
//Find separating value
int value;
printf("Enter the number to split the array: ");
scanf("%d", &value);
//Declare arrays and call function
int n = 0, larger[length], smaller[length];
separate(array, n, value, larger, length_pointer, smaller);
//Display the arrays
printf("%d\n", *smaller);
printf("%d", *larger);
return 0;
}
/*************************************************************************************
separate finds numbers larger than value in array a and stores them in array larger.
Numbers smaller than or equal to value will be stored in the smaller array.
size points to a variable in which the function will store the number of larger
numbers in the array.
*************************************************************************************/
void separate(int *a, int n, int value, int *larger, int *size, int *smaller)
{
// Delete later *smaller = *larger = *a;
for(a = &n; a < n + size; a++)
if(a[n] > value)
{
larger = &a[n];
}
else if(a[n] <= value)
smaller = &a[n];
return;
}

I modified a bit your code to reach your goal. In order to get array size from user input under C99, you need to dynamically assign it e.g. by calloc(elements_number, element_size_in_bytes) when your program runs. Don't forget to free assigned memory to avoid memory leaks. Like below:
int* array = calloc(user_input, sizeof(int));
...
//some code
...
free(array);
Your separate function looks a bit complex. This part is wrong:
for(a = &n; a < n + size; a++)
What you are doing here is making a point to integer n. a does not point anymore to a source array. So making a call like a[n] when a is &n is like (&n)[n]. n is not changing value also, because you increment pointer to n, not the value it points to.
Next if you want to display array elements do it by using loop, like I did below.
I could not find the purpose of n parameter in your separate function. I used it as amount of real elements in larger array, so I don't have to print all elements.
I hope this answer meats your expectations.
#include <stdio.h>
#include <stdlib.h>
void separate(int *a, int *larger_count, int value, int *larger, int size, int *smaller);
int main()
{
//Find size of array
int length;
int *length_pointer = &length;
printf("Enter the length of the array: ");
scanf("%d", length_pointer);
//Enter array elements
int*array = calloc(*length_pointer, sizeof(int));
int*p;
printf("Enter %d numbers: ", length);
for(p = array; p < array + length; p++)
scanf("%d", p);
//Find separating value
int value;
printf("Enter the number to split the array: ");
scanf("%d", &value);
//Declare arrays and call function
int *larger = calloc(*length_pointer, sizeof(int));
int *smaller = calloc(*length_pointer, sizeof(int));
int larger_count = 0;
separate(array, &larger_count, value, larger, length, smaller);
for (int i = 0 ; i < larger_count ; ++i)
{
printf("%d ", larger[i]);
}
printf("\n");
for (int i = 0 ; i < length - larger_count; ++i)
{
printf("%d ", smaller[i]);
}
printf("\n");
free(array);
free(larger);
free(smaller);
return 0;
}
/*************************************************************************************
separate finds numbers larger than value in array a and stores them in array larger.
Numbers smaller than or equal to value will be stored in the smaller array.
size points to a variable in which the function will store the number of larger
numbers in the array.
*************************************************************************************/
void separate(int *a, int *larger_count, int value, int *larger, int size, int *smaller)
{
for(int x = 0, y = 0, z = 0; x < size; x++)
{
if (a[x] > value)
{
larger[y] = a[x];
y++;
*larger_count = y;
} else
{
smaller[z] = a[x];
z++;
}
}
}

Related

Accessing array pointer in separate function

Say I have an array of n characters.
I want to pass the amount, and a pointer to the array to a function, to check for the biggest value in the array. However, I'm unsure how to access the values from the pointer.
#include <stdio.h>
int max(int *numbers, int size) {
int temp = size;
for (int i=0;i<temp;i++) {
/*How do i access the array values?*/
}
return 0;
}
int main(void) {
int amount;
int Array[amount];
int *ptr;
printf("Enter size of array:");
scanf("%d",&amount);
ptr = &Array[amount];
for(int i=0;i<amount;i++) {
scanf("%d",&Array[i]);
}
printf("Number 2 in array: %d",Array[1]);
printf("\n calling function \n");
max(ptr,amount);
return 0;
}
Two problems -- you don't set amount before using it to create Array so you get an undefined-size array, and Array[amount] is past the end of the array. What you want is something more like:
int amount;
int *ptr;
printf("Enter size of array:");
scanf("%d",&amount);
int Array[amount];
ptr = Array;
and having ptr as a separate variable is not terribly useful -- you can just call max(Array, amount)

summing numbers using pointer arithmetic

I was given an assignment to write a code which takes in numbers as input from the user and provides the sum of it, specifically by the use of pointer arithmetic i.e. no array subscripting a[i] is allowed.
Below is the code that I wrote, which got compiled and even ran. But almost always it gives the sum of the input numbers as 0. I tried to fix it, but to no avail. Thus, I am asking for help, any help is greatly appreciated.
#include<stdio.h>
#define N 5
int sum_array( const int *p, int n)
{
int sum, a[N];
sum = 0;
for(p=&a[0]; p<&a[N]; p++)
sum += *p;
return sum;
}
int main()
{
int a[N], *i,x;
printf("Enter %d Numbers: ", N);
for(i=a; i<a+N; i++)
scanf("%d", i);
// all the input values get scanned as i or the array a
x= sum_array(i,N);
printf("the sum is %d\n", x);
return 0;
}
Beware, you are declaring array int a[N] in both main and sum_array. They are in different scopes, so they are different arrays (and the one from sum_array is never initialized so reading it invokes Undefined Behaviour).
The correct way is to pass the array along with its used length:
Here is a fixed version:
#include<stdio.h>
#define N 5
int sum_array( const int *a, int n) // a points to a array of at least n elements
{
int sum = 0; // initialize at definition time
for(const int *p=a; p<&a[n]; p++) // have the pointer p take all values from a
sum += *p;
return sum;
}
int main()
{
int a[N], *i,x;
printf("Enter %d Numbers: ", N);
for(i=a; i<a+N; i++)
scanf("%d", i);
// all the input values get scanned as i or the array a
x= sum_array(a,N); // pass the array address, not a pointer past last element
printf("the sum is %d\n", x);
return 0;
}
Finally it is mainly a matter of taste, but I was too often burnt for trying to add an instruction in a for loop without braces, so I strongly recommend using always braces for loops:
for(i=a; i<a+N; i++) {
scanf("%d", i);
}
int sum_array( const int *p, int n)
{
int sum = 0, i = 0;
for(i = 0; i < n ; i++)
sum += *(p+i);
return sum;
}
int main(void)
{
int a[N], i = 0, x = 0;
printf("Enter %d Numbers: ", N);
for(i=0; i<N; i++)
scanf("%d", a+i);
// all the input values get scanned as i or the array a
x= sum_array(a,N);
printf("the sum is %d\n", x);
return 0;
}
In x= sum_array(i,N); i is the iterator of your loop so after the loop has finished it points to the first position after the array.
You should pass the original array instead x= sum_array(a,N);
In the sum function you just throw away the passed pointer and replace it with your local a[].
int sum_array( const int *p, int n)
{
int sum = 0;
int *end = &p[n]; // first element after the array.
for(; p<end; p++) // just use p because you don't need the reference to the start of the array
{
sum += *p;
}
return sum;
}
but as you said that array notation is not allowed you can change it as follows
#include "stdio.h"
#define N 5
int sum_array( const int *p, int n)
{
int sum = 0;
const int *end = p+n; // first element after the array.
for(; p<end; p++)
{
sum += *p;
}
return sum;
}
int main()
{
int *a, *i, x;
a = malloc(N * sizeof(*a));
if (a == NULL)
exit(-1);
printf("Enter %d Numbers: ", N);
for(i=a; i<a+N; i++)
{
scanf("%d", i);
}
// all the input values get scanned as i or the array a
x= sum_array(a,N); // pass the array address, not a pointer past last element
printf("the sum is %d\n", x);
return 0;
}
in general, when programming, the code should be kept as simple as possible while still being complete.
The program criteria shows no need to keep a number after it is applied to the sum of the numbers, So in the proposed code, the input number is only kept long enough to be applied to the sum, then it is discarded.
The following proposed code:
cleanly compiles
performs the desired functionality
is kept very simple
properly checks for; and handles any errors
And now the proposed code:
#include <stdio.h> // scanf(), printf(), fprintf(), stderr
#include <stdlib.h> // exit(), EXIT_FAILURE
#define N 5
int main( void )
{
int num = 0;
int sum = 0;
printf("Enter %d Numbers: ", N);
for(size_t i=0; i<N; i++)
{
if( scanf("%d", &num) != 1 )
{
fprintf( stderr, "failed to read number\n" );
exit( EXIT_FAILURE );
}
// implied else, scanf successful
sum += num;
}
printf( "the sum is %d\n", sum );
return 0;
}

Sum of numbers using 2 functions

Just learning C and I'm trying to understand how I get the sum of numbers using 2 functions but the results is incorrect.
I'm trying to ask the user for 10 numbers which are stored in an array in function main. The sum is then calculated in a separate function and then displayed in main.
Here is my original code without multiple functions that works:
int main()
{
int n[10];
int index;
int sum_n = 0;
int largest_n;
int smallest_n;
int *p;
p = &n[10];
int a;
printf("Enter 10 Integers\n");
for (index = 0; index < 10; index ++){
scanf("%d", &n[index] );
sum_n += n[index];
}
printf("The Sum of numbers is %d\n", sum_n);
}
Here is me trying to convert it to functions but the sum isn't working out:
int calculations (int);
int main()
{
int n[10];
int index;
int largest_n;
int smallest_n;
int *p;
p = &n[10];
int a;
printf("Enter 10 Integers\n");
for (index = 0; index < 10; index ++){
scanf("%d", &n[index] );
}
if (n[index] = 10){
//sum_n += n[index];
printf("The Sum of numbers is %d\n",calculations(n[index]));
}
&
int calculations (int num){
int sum_n = 0;
sum_n += num;
return sum_n;
}
When I run the second program using functions for numbers 1 to 10 I'm getting:
I'm either doing something blatantly wrong or not understanding what I'm doing at all.
every time you call a function the variables declared within a function are reset.
in case you want a variable that won't be reset every time you call a function you can simply make it static.
moreover you are passing and argument n[10] but your array stores number from n[0] to n[9] . And if you want sum of all ten numbers then you have to call calculation function for every number or you could just pass whole array. here is modified code.
#include<stdio.h>
int calculations (int);
int main()
{
int n[10];
int index;
int largest_n;
int smallest_n;
int *p;
p = &n[10];
int a;
int ans=0;
printf("Enter 10 Integers\n");
for (index = 0; index < 10; index ++){
scanf("%d",&n[index]);
ans = calculations(n[index]);
}
printf("The Sum of numbers is %d\n",ans);
}
int calculations (int num){
static int sum_n;
sum_n += num;
return sum_n;
}
First you don't need array for sum in this code, Second always remember to check what returned by scanf.The code is very simple.
first part with main
int main()
{
int n;
int sum=0;
printf("Enter 10 Integers\n");
for (int index = 0; index < 10; index ++){
if(scanf("%d", &n))
sum+=n;
}
printf("The Sum of numbers is %d\n",sum);//calculations(n));
}
Second using function calculation
int sum=0;
void calculation(int num){
sum+= num;
}
int main()
{
int n;
printf("Enter 10 Integers\n");
for (int index = 0; index < 10; index ++){
if(scanf("%d", &n))
calculation(n);
}
printf("The Sum of numbers is %d\n",sum);//calculations(n));
}
Your function calculations() simply returns its parameter (0 + num is simply num).
The statement
int sum_n = 0;
in it resets sum_n to 0 every time of calling it.
Move this statement out of it - directly into main() function (and before calling calculations()).
Corrections mentioned in comments below.
int calculations (int *num){ //Should be a pointer or array eg. int num[] as you want to pass an array to this function
int sum_n = 0;
int i;
//Create loop here to iterate over array and sum elements
for(i=0; i<sizeof(num)/sizeof(int); i++)
sum_n+=num[i];
return sum_n;
}
And
if (n[index] = 10){ //This is logically incorrect. This should be if(index==10).
// n[index]=10 will assign 10 to a[10] and if will still pass as if(10) is true but make a note of it. Don't use assignment operator inside if, you need comparison operator `==`
printf("The Sum of numbers is %d\n",calculations(n[index])); //You should call calculations like this -> calculations(n). You should pass whole array not just an element.
}

thread 1: EXC_BAD_ACCESS(code = 1, address = 0x7fff00000001)

I'm trying to pass an array to a function that sums up all the elements in the array, but I get a bad access error at the line sum+=a[i]; how can i fix this? Here is the code:
#import <Foundation/Foundation.h>
int sum(int*, int);
int main() {
#autoreleasepool {
int size = 0;
int a[size];
int x;
NSLog(#"Enter a size for the array ");
scanf("%i", &size);
NSLog(#"Enter %i numbers to populate the array ", size);
for (int i = 0; i < size; i++) {
scanf("%i", &a[i]);
}
x = sum(a, size);
NSLog(#"The sum of the array is %i ", x);
}
return 0;
}
int sum(int *a, int n) {
int sum = 0;
for (int i = 0; i < n; i++) {
sum += a[i];
}
return sum;
}
It is because your array is 0 in size. Writing / Reading from a[i] may / may not crash as it's behavior is undefined.
Instead of
int size = 0;
int a[size];
int x;
NSLog(#"Enter a size for the array ");
scanf("%i", &size);
you should do this instead:
int size = 0;
int *a;
int x;
NSLog(#"Enter a size for the array ");
scanf("%i", &size);
a = malloc(sizeof(int) * size);
By dynamically allocate the array a, your program should no longer crash.
And after we use malloc, we have to free it when we don't need it anymore. Put this before return 0;
free(a);
Hope this helps.
You've defined an array of size 0. Since an array is a block of memory, and in this case a block of "no" memory, you cannot store anything into it.
You can use malloc/free as indicated in #Owen's answer. C99 also added the ability to declare arrays on the stack (so-called VLA, Variable Length Arrays). This saves you using malloc/free but leaves you at risk of using up all your stack space. For values which you know for a fact will be constrained, a VLA might make sense:
int size;
NSLog(#"Enter a size for the array ");
scanf("%i", &size);
int arr[size];
....
Note that in C89/C90/ANSI you would not be able to do that, since the size of an array must be a compile-time constant.

Optimizing a 'sorting code' in C

I am working on a code I want to optimize. The code is all about sorting a double array by ascending order of its second .
The first input is an integer N, and the second is a 2D array of size N*2 (call it c), then we sort the array by ascending order of c[.][1], and when there are equal elements, say if c[i][1]==c[j][1], for two integers i and j, we sort those elements by ascending of the elements of the first columns, so c[i][1] is below c[j][1] if c[i][1]<c[j][1]. Let's take an example :
input
3
2 3
1 3
4 2
output
4 2
1 3
2 3
The fact is that the code needs to run in less than 0.5s and mine is really too slow. Here it is
#include <stdio.h>
#include <stdlib.h>
//determining the index of the max elments in an array
int max(int i, int N, int **c)
{
int j=0;
int M=0;
for(j=0;j<i;j++)
{if(c[j][1]>c[M][1]){M=j;}else{}}
return M;
}
int main ()
{
//integers used for the loops
int i;
int j;
//the size of the 2D array is N*2
int N;
scanf("%d",&N);
int **c;
int mx;
int maxi;
//this array is the output, thath is the 2D array sorted
int e[N][2];
//2D array we want to sort
c = malloc(N*sizeof(int*));
for (i=0;i<N;i++)
{
c[i] = malloc(2*sizeof(int));
for (j=0;j<2;j++)
{
scanf("%d",&c[i][j]);
}
}
//at the first step, we have initialized the value of the max
maxi=max(N,N,c);
for(i=0;i<N;i++)
{
//we sort the c[.][1], and we take the max (called 'mx') of the array. At each step of the loop, we throw away the max from the array c[.][1] (we mean the max found at the precedent step of the loop)
mx=max(N-i,N,c);
//Here, we look at the multiple occurence of the max, if there are, we sort the c[.][0] for which c[.][1]=c[mx][1] by ascending order
if(maxi==mx){int k;
for(k=0;k <N;k++){if(c[k][1]==c[mx][1]){if(c[k][0]>c[mx][0]){mx=k;}}else{}}
}else{}
//we keep the value of the max in order to verify that the same value of the max has another occurence in following steps
maxi=mx;
//e is the double array for the output
e[i][0]=c[mx][0];
e[i][1]=c[mx][1];
int j;
//here we throw away the max from the array
for(j=mx;j< N-i-1;j++){c[j][1]=c[j+1][1];c[j][0]=c[j+1][0];}
}
for(i=0;i<N;i++)
{printf("%d %d",e[N-1-i][0],e[N-1-i][1]);
printf("\n");}
}
Could anyone help ?
Your code has way too high computational complexity. Also, int e[N][2] only works under GCC extension since N is a variable determined at run time instead of compile time.
An easy (in terms of coding) way to improve it is utilizing qsort() in C standard library.
struct IntPair
{
int n[2];
};
int compareIntPair(const void* lhs, const void* rhs)
{
const struct IntPair *l = (const struct IntPair*)lhs;
const struct IntPair *r = (const struct IntPair*)rhs;
if(l->n[1] < r->n[1])
return -1;
if(l->n[1] > r->n[1])
return 1;
if(l->n[0] < r->n[0])
return -1;
if(l->n[0] > r->n[0])
return 1;
return 0;
}
int main(void)
{
//integers used for the loops
int i;
//the size of the 2D array is N*2
int N;
struct IntPair* c;
scanf("%d",&N);
c = (struct IntPair*)calloc(N, sizeof(struct IntPair));
for(i = 0; i < N; ++i)
{
scanf("%d%d", &c[i].n[0], &c[i].n[1]);
}
qsort(c, N, sizeof(struct IntPair), compareIntPair);
for(i = 0; i < N; ++i)
printf("%d %d\n", c[i].n[0], c[i].n[1]);
free(c);
return 0;
}
Edit: to answer the question in comment "could each element of the N-dynamic allocation points to 1D array of size 2?"
int compareElem(const void* lhs, const void* rhs)
{
const int *l = *(const int**)lhs;
const int *r = *(const int**)rhs;
if(l[1] < r[1])
return -1;
if(l[1] > r[1])
return 1;
if(l[0] < r[0])
return -1;
if(l[0] > r[0])
return 1;
return 0;
}
int main(void)
{
//integers used for the loops
int i;
//the size of the 2D array is N*2
int N;
int ** c;
scanf("%d",&N);
c = (int**)calloc(N, sizeof(int*));
for(i = 0; i < N; ++i)
{
c[i] = (int*)calloc(2, sizeof(int));
scanf("%d%d", &c[i][0], &c[i][1]);
}
qsort(c, N, sizeof(int*), compareElem);
for(i = 0; i < N; ++i)
{
printf("%d %d\n", c[i][0], c[i][1]);
free(c[i]);
}
free(c);
return 0;
}

Resources