I'm trying to write a program that dynamically allocates memory for an array, which the user then fills with integer values and the program sorts said integer values. However, it seems that my array isn't working as intended. I have managed to get the program working with a static array, but the dynamic allocation is causing me a lot of problems with incorrect values and whatnot. Here's what I have so far for the dynamically allocated version (if it would help you guys, I can also provide the version that uses a static array):
#include <stdio.h>
#include "genlib.h"
#include "simpio.h"
void sortArray (int *numbers, int i2);
int indexMax (int *numbers, int low, int high);
void swap (int *num1, int *num2);
int getArray (int *numbers);
void displayArray (int *numbers, int i2);
main()
{
int *numbers, i2;
i2=getArray(numbers);
sortArray(numbers, i2);
displayArray (numbers, i2);
}
int getArray (int *numbers)
{
int i, i2;
printf("Please enter the amount of elements you wish to sort: ");
i2=GetInteger();
numbers=(int *)malloc(i2*sizeof(int));
for(i=0;i<i2;i++, numbers++)
{
printf("Enter next integer: ");
*numbers=GetInteger();
printf("\n");
}
return(i2);
}
void displayArray (int *numbers, int i2)
{
int i;
printf ("\nThe sorted list is: \n\n");
for (i=0;i<i2;i++, numbers++)printf ("%d\n", *numbers);
}
void sortArray (int *numbers, int i2)
{
int i, minInd;
for(i=0;i<i2;i++)
{
minInd=indexMax(numbers, i, i2-1);
swap(&numbers[i], &numbers[minInd]);
}
}
int indexMax (int *numbers, int low, int high)
{
int i, maxInd;
maxInd=high;
for (i=high;i>=low;i--)
{
if(*(numbers+i)>*(numbers+maxInd)) maxInd=i;
}
return (maxInd);
}
void swap (int *num1, int *num2)
{
int temp;
temp=*num1;
*num1=*num2;
*num2=temp;
}
Here is a working solution:
#include <stdio.h>
#include <stdlib.h>
void sortArray (int *numbers, int i2);
int indexMax (int *numbers, int low, int high);
void swap (int *num1, int *num2);
int getArray (int **numbers);
void displayArray (int *numbers, int i2);
main()
{
int *numbers, i2;
i2=getArray(&numbers);
sortArray(numbers, i2);
displayArray (numbers, i2);
}
int getArray (int **numbers)
{
int i, i2;
printf("Please enter the amount of elements you wish to sort: ");
scanf("%d", &i2);
(*numbers) = malloc(i2 * sizeof(int));
int *temp = *numbers;
for(i = 0; i < i2; i++)
{
printf("Enter next integer: ");
scanf("%d", &temp[i]);
printf("\n");
}
return(i2);
}
void displayArray (int *numbers, int i2)
{
int i;
printf ("\nThe sorted list is: \n\n");
for (i=0;i<i2;i++, numbers++)printf ("%d\n", *numbers);
}
void sortArray (int *numbers, int i2)
{
int i, minInd;
for(i=0;i<i2;i++)
{
minInd=indexMax(numbers, i, i2-1);
swap(&numbers[i], &numbers[minInd]);
}
}
int indexMax (int *numbers, int low, int high)
{
int i, maxInd;
maxInd=high;
for (i=high;i>=low;i--)
{
if(*(numbers+i)>*(numbers+maxInd)) maxInd=i;
}
return (maxInd);
}
void swap (int *num1, int *num2)
{
int temp;
temp=*num1;
*num1=*num2;
*num2=temp;
}
The thing is in your main when you are declaring int *numbers , numbers pointer is pointing to some junk memory location as local variables can have any garbage value, so while you are passing this numbers pointer to getArray() function you are passing its value, Suppose numbers is pointing to some random value = 1234 and suppose address of numbers is = 9999. Now when you call getArray(numbers) you tell taht whatever is there in numbers pass it to getArray's numbers variable that we are letting is 1234.
Then when you allocate memory to numbers that is local variable of getArray() function not main's and it might have address suppose = 0x8888. Then malloc allocates some address space as specified and stores the start address of that allocated address space(suppose i.e. = 0x7777) into location 0x8888 not 0x9999 which is the adress of main's numbers variable.
Thus when the getArray function ends and next time you call sortArray you pass it value present in numbers variable of main which is still junk 1234. and the actual value you should be passing is present at address 0x8888.
Try this:
int main(void)
{
int *numbers, i2;
i2 = getArray(&numbers);
sortArray(numbers, i2);
displayArray (numbers, i2);
return 0;
}
int getArray (int **numbers)
{
int i, i2;
printf("Please enter the amount of elements you wish to sort: ");
i2 = GetInteger();
*numbers = malloc(i2 * sizeof int);
etc...
You simply need one more level of indirection to make int getArray(int**) return a pointer to an allocated array.
As an aside, you can use the C library function qsort() to do the sorting work for you. Here is an example:
int main(void)
{
int a[]={4,7,9,1,34,90,66,12};
qsort(a, sizeof(a)/sizeof(a[0]), sizeof(int), compare);
return 0;
}
int compare(const void *a, const void *b){
const int *x = a, *y = b;
if(*x > *y)
return 1;
else
return(*x < *y) ? -1: 0;
}
Works just as well with dynamically allocated int arrays, or char arrays
Related
I've got a homework to create 2 functions add which adds element to dynamic array (what i've done) and remove which removes indicated element from that array. I have a problem with that 2nd function. I have no clue how to code it.
PS. I can't use memmove().
#include <stdlib.h>
#include <stdio.h>
void print_array(int *tab, int n);
void add(int x, int y, int *tab, int idx);
void remove_element(int *tab, int idx, int array_length);
int main() {
int *tab = malloc(24*sizeof(*tab));
int idx = 0;
tab[idx++] = 44;
tab[idx++] = 82;
tab[idx++] = 57;
tab[idx++] = 77;
printf("Before insert\n");
print_array(tab, idx);
idx++;
add(7, 0, tab, idx);
printf("After insert\n");
print_array(tab, idx);
free(tab);
idx--;
printf("After delete\n");
remove_element(tab, 3, idx);
print_array(tab, idx);
free(tab);
return(0);
}
void print_array(int *tab, int n) {
int i;
for (i = 0; i < n; i++) {
printf("t[%d] = %d\n", i, tab[i]);
}
}
void add(int x, int y, int *tab, int idx) {
int i;
for (i = idx; i > y; i--) {
tab[i] = tab[i-1];
}
tab[y] = x;
}
void remove_element(int *tab, int idx, int array_length) {
void *tmp = realloc(tab, (array_length - 1) * sizeof(int) );
array_length = array_length - 1;
tab = tmp;
}
About your array you can keep information about its size (eg iSize) and the number of elements in use (eg iUse). iUse<=isize, of course.
When you need to add an element but the array is too small (iUse==iSize), you increase its size, add the element and increment iUse.
When you remove an element, you just decrement iUse and, if you can't use memmov, make a loop to move al higher elements down.
What my program does is it finds 2 numbers of an array that are closest to the average, one is bigger, one is smaller. It works fine, however I need to change for example **array+a to *array[a].
However, when I load the program, it crashes after I input the numbers. If I try to print *array[0], *array[1], etc. it works fine. When I try to print or just do something with *array[a], *array[b], it crashes. Thank you for your help.
#include <stdio.h>
#include <stdlib.h>
int input (int *t, int *array[]);
void calculation (int *array[], int *t, int *x, int *y);
void output (int *x, int *y);
int main()
{
int *array, t, x, y;
input (&t, &array);
calculation (&array, &t, &x, &y);
output (&x, &y);
return 0;
}
int input (int *t, int *array[])
{ int n, *ptr;
printf ("How big is the array?");
scanf ("%d", &n);
ptr = (int*) malloc(n * sizeof(int));
int k;
printf ("Enter the numbers:");
for (k=0; k<n; k++)
{ scanf ("%d", ptr + k);
}
*t=n;
*array=ptr;
return 0;
}
void calculation (int *array[], int *t, int *x, int *y)
{ float sum=0, avg;
int min, max;
int more, less;
int a, b, c;
for (a=0; a<(*t); a++)
{sum=sum+ **array + a;
}
avg=sum/(*t);
min= *array[0];
max= *array[0];
for (b=0; b<(*t); b++)
{ if (max < (**array + b)) max=(**array + b);
if (min > (**array + b)) min=(**array + b);
}
more=max;
less=min;
for (c=0; c<(*t); c++)
{ if (((**array + c) < avg) && ((**array + c) > less)) less=(**array + c);
if (((**array + c) > avg) && ((**array + c) < more)) more=(**array + c);
}
*x=less;
*y=more;
}
void output (int *x, int *y)
{ printf("Number that is less than the average:%d\n", *x);
printf("Number that is more than the average:%d\n", *y);
}
It would be better to rethink your function prototypes a bit. It makes sense to pass a pointer to array to the input() function since you are allocating memory for it, and you want to be able to access it when you return. But you don't need to pass in the pointer to int t; instead, just return the value of n, and assign it to t in main.
There is no reason to pass a pointer to array to the function calculation(), since you are not changing the array allocation. You can also pass in the value of t from main(), since you only use this value in calculation(), but do not change it.
Similarly, the output() function only needs copies of x and y, since it does not change them.
The rule of thumb here is that you pass a pointer to a value into a function when you want to modify the value inside the function and have access to the modified value in the calling function. But you can also return a value instead of using a pointer to it.
These changes do not alter the functionality of your code, but they substantially improve its readability. You even get a sense of what is being modified in each function just by looking at the function prototypes. Well, the changes do alter the functionality in that your original **array + a was incorrect, and needed to be either *(*array + a) or (*array)[a]. But sorting that problem out should help you to appreciate the virtue of the simpler function prototypes. Here is the modified code:
#include <stdio.h>
#include <stdlib.h>
int input(int *array[]);
void calculation(int array[], int t, int *x, int *y);
void output(int x, int y);
int main(void)
{
int *array, t, x, y;
t = input(&array);
calculation(array, t, &x, &y);
output(x, y);
return 0;
}
int input(int *array[])
{ int n, *ptr;
printf("How big is the array?");
scanf("%d", &n);
ptr = (int*) malloc(n * sizeof(int));
int k;
printf("Enter the numbers:");
for (k=0; k<n; k++)
{ scanf("%d", ptr + k);
}
*array=ptr;
return n;
}
void calculation(int array[], int t, int *x, int *y)
{ float sum=0, avg;
int min, max;
int more, less;
int a, b, c;
for (a=0; a<t; a++)
{sum=sum+ array[a];
}
avg=sum/t;
min= array[0];
max= array[0];
for (b=0; b<t; b++)
{ if (max < array[b]) max=array[b];
if (min > array[b]) min=array[b];
}
more=max;
less=min;
for (c=0; c<t; c++)
{ if ((array[c] < avg) && (array[c] > less)) less=array[c];
if ((array[c] > avg) && (array[c] < more)) more=array[c];
}
*x=less;
*y=more;
}
void output(int x, int y)
{ printf("Number that is less than the average:%d\n", x);
printf("Number that is more than the average:%d\n", y);
}
Just like BLUEPIXY and Some programmer dude said, it's supposed to be (*array)[a]
I don't have idea where is the problem but the latest pointer(vector) have some troubles.
First value it's ok (V[0]+T[0]) , S[1] it's always 0 and third value it's random.
#include <stdio.h>
#include <stdlib.h>
int citire_vector(int n, int *V);
void afisare_vector(int n, int *V);
int produs_scalar(int n, int *V, int *T);
int suma_vectori(int n, int *V, int *T);
int main(void)
{
int n, *X, *Y, ps, *S;
printf("n = ");
scanf("%d",&n);
X = (int*) malloc(n*sizeof(int));
Y = (int*) malloc(n*sizeof(int));
citire_vector(n,X);
citire_vector(n,Y);
afisare_vector(n,X);
afisare_vector(n,Y);
ps = produs_scalar(n,X,Y);
printf("Produsul scalar = %d\n",ps);
S = (int*) malloc(n*sizeof(int));
*S= suma_vectori(n,X,Y);
afisare_vector(n,S);
}
int citire_vector(int n, int *V)
{
int i;
for(i=0;i<n;i++)
scanf("%d",V+i);
return *V;
}
void afisare_vector(int n, int *V)
{
int i;
printf("Valorile vectorului sunt:\n");
for(i=0;i<n;i++)
printf("%d ",*(V+i));
printf("\n");
}
int produs_scalar(int n, int *V, int *T)
{
int i, ps = 0;
for(i = 0;i<n;i++)
ps += (*(V+i))*(*(T+i));
return ps;
}
int suma_vectori(int n, int *V, int *T)
{
int i, *U;
for(i=0;i<n;i++)
{
*(U+i )= *(V+i);
}
return *U;
}
Your suma_vectori and its usage are incorrect.
Pointer U inside suma_vectori is uninitialized, causing undefined behavior on assignment
Assignment *S= suma_vectori(n,X,Y) has no effect beyond the initial element of S
To fix this problem, change suma_vectori to return int*, move malloc of the result inside the function, remove malloc for S, and assign S the result of the suma_vectori call:
int *suma_vectori(int n, int *V, int *T); // forward declaration
int *suma_vectori(int n, int *V, int *T) { // Implementation
int *U = malloc(n*sizeof(int)); // do not cast malloc
for(int i=0;i<n;i++) {
U[i] = V[i] + T[i];
}
return U;
}
// call
S= suma_vectori(n,X,Y);
// Don't forget to free malloc-ed memory
free(X);
free(Y);
free(S);
You have to allocate memory to U in suma_vectori function
as it is picking garbage value
I'm trying to print array of pointer using pointer instead of array but I got this error Segmentation fault at runtime:
enter number of element:5
array[0]=1
array[1]=2
array[2]=3
array[3]=4
array[4]=5
Segmentation fault
This is the code:
#include <stdio.h>
#include <stdlib.h>
int *array;
int n;
void input(int *array,int n);
void display(int *array,int n);
int sum(int *array,int n);
int main (void) {
int result;
printf("enter number of element:");scanf("%d",&n);
input(array,n);
display(array,n);
result=sum(array,n);
printf("sum of array=%d",result);
return 0;
}
void input(int *array,int n){
int j;
array=(int *)malloc(n*sizeof(int));
for(j=0;j<n;j++){
printf("array[%d]=",j);scanf("%d",array+j);
}
}
void display(int *array,int n){
int j;
for(j=0;j<n;j++)
printf("%d\t",*(array+j));
printf("\n");
}
int sum(int *array,int n){
int sum=0,j;
for(j=0;j<n;j++)
sum+=*array+j;
return sum;
}
How can I fixed this code? please somebody explain me what's wrong with that code.
Variable array is a local variable in function input.
As such, it is pointless to set it with array = ..., because this assignment takes effect only inside the function. You should typically pass its address (&array) to any function that needs to change it.
In your specific example, you also have a global variable array, so a quick solution to your problem would be to simply call function input without passing variable array as an argument:
void input(int n)
{
...
array = (int*)malloc(n*sizeof(int));
...
}
int main()
{
...
input(n);
...
}
Note that this is a "dirty" workaround, and you should typically strive to avoid the use of global variables.
To add the clean version to barak's answer:
int input(int ** array, const size_t n)
{
int result = 0;
assert(NULL != array);
(*array) = malloc(n * sizeof(**array));
if (NULL == (*array))
{
result = -1;
}
else
{
size_t j;
for(j = 0; j < n; ++j)
{
printf("array[%zu]=", j);
scanf("%d", (*array) + j); /* still missing error checking here . */
}
}
return result;
}
And call it like this:
if (-1 == input(&array, n))
{
perror("input() failed");
exit(EXIT_FAILURE);
}
Try this input():
void input(int **array,int n){
int j;
*array=(int *)malloc(n*sizeof(int));
for(j=0;j<n;j++){
printf("array[%d]=",j);scanf("%d",*array+j);
}
}
Because C use pass-by-value, if you want to change the value of a variable in a function, you need to pass the address of that variable as the argument to that function.
In this case, you want to change the value of array in input() and the type of array is int *, therefore the prototype of input() should be something like void input (int **array, ...).
this should do..make sure you understand what the others have said..
#include <stdio.h>
#include <stdlib.h>
int *array;
int n;
void input(int **array,int n);
void display(int **array,int n);
int sum(int **array,int n);
int main (void) {
int result;
printf("enter number of element:");scanf("%d",&n);
input(&array,n);
display(&array,n);
result = sum(&array,n);
printf("sum of array= %d",result);
return 0;
}
void input(int **array,int n){
int j;
*array= malloc(n*sizeof(int));
for(j=0;j<n;j++){
printf("array[%d]=",j);
scanf("%d",(*array)+j);
}
}
void display(int **array,int n){
int j;
for(j=0;j<n;j++){
printf("%d\t",*((*array)+j)); // you can use array notation aswell
//array[0][j] will work
}
printf("\n");
}
int sum(int **array,int n){
int sum=0,j;
for(j=0;j<n;j++){
sum += *((*array)+j);
}
return sum;
}
What does *array + j do? Does it evaluate *array and add j to it? Or does it add j to array and then dereference it? Would you be willing to bet $100 on it if I told you you are wrong?
Make your life and the life of anybody reading your code easier by using parentheses, or even better, write array [j].
This is one of the programs, where a set of numbers are sorted into ascending order, by finding the largest number in the range between the left point and the end of the array, then moving that element into its correct index position by switching the elements. My problem is that it is not in ascending order, as the numbers in between don't get ordered, and I'm wondering how to fit that in the program.
Here is my code at the moment:
#include <stdio.h> /* Library inclusions */
#include "genlib.h"
#include "simpio.h"
#define size 7 /* Constants */
void sortArray (int numbers[]); /* prototypes */
int indexMax (int numbers[], int low, int high);
void swap (int numbers[], int loc, int loc1);
void getArray (int numbers[]);
void displayArray (int numbers[]);
main()
{
int numbers[size];
getArray(numbers);
sortArray(numbers );
displayArray (numbers);
getchar();
}
void getArray (int numbers[]) /*Function getArray*/
{
int i;
for (i=0; i<size; i++)
{
printf ("Enter an integer? ");
numbers[i]=GetInteger();
}
}
void displayArray (int numbers[]) /*Function displayArray*/
{
int i;
printf ("\n The sorted list is: \n");
for (i=0; i< size; i++)
{
printf ("%d\t", numbers[i]);
}
}
void sortArray (int numbers[]) /*Function sortArray*/
{
int i , maxInd;
for (i=0; i<size;i++)
{
maxInd = indexMax (numbers, i, size-1);
swap (numbers, size-1, maxInd);
}
}
int indexMax (int numbers[], int low, int high) /*Function indexMax*/
{
int i, maxInd;
maxInd=high;
for (i=low;i<=high;i++)
{
if (numbers[i]>numbers[maxInd])
{
maxInd =i;
}
}
return (maxInd);
}
void swap (int numbers[], int loc, int loc1) /*Function swap*/
{
int temp;
temp=numbers[loc];
numbers[loc]=numbers[loc1];
numbers[loc1]=temp;
}
Thank you very much. :)
You SortArray function logic is wrong. You are finding maxindex from i to last index and replacing it with last index and then increment i. In first iteration the largest number reaches end thereafter in subsequent iterations, the last index only will be selected as maxindex and no change in array will be there.
Instead you always need to iterate from first index and upto one index less than previous last index.
void sortArray (int numbers[]) /*Function sortArray*/
{
int i , maxInd;
for (i=size-1; i>=0;i--)
{
maxInd = indexMax (numbers, 0, i);
swap (numbers, i, maxInd);
}
}
In indexMax function change greater than (>) to less than (>).
There may be something wrong in the function sortArray()
void sortArray (int numbers[])
{
int i
int maxInd;
for (i=0; i<size;i++)
{
maxInd = indexMax (numbers, i, size-i-1);
swap (numbers, size-1-i, maxInd);
}
}
I make a small change, and it worked!!