How do i decrease the size of array? - c

#include<stdio.h>
#include<conio.h>
#include<stdlib.h>
void main()
{
int i=0,pos;
int *ptr;
clrscr();
ptr=(int *)malloc(10*sizeof(int));
printf("Enter 10 Elements:\n");
while(i<10)
{
scanf("%d",&ptr[i]);
i++;
}
printf("Current Array:\n");
for(i=0;i<10;i++)
{
printf("%d\t",ptr[i]);
}
printf("Enter the position to be deleted:");
scanf("%d",&pos);
for(i=pos;i<10;i++)
{
ptr[pos-1]=ptr[pos];
pos++;
}
for(i=0;i<10;i++)
{
printf("%d\t",ptr[i]);
}
getch();
}
Array i enter : 1 2 3 4 5 6 7 8 9 0
Suppose 4th position has been deleted
Array after deletion: 1 2 3 5 6 7 8 9 0 0
How can i make the program to print only 9 integers but without decresing the times the loop run.
i.e. without using
for(i=0;i<9;i++)

C doesn't allow you to do that. So, alternative is to dynamically allocate an array, put what you want in it, then when you get the size you want, transfer that data to a newly allocated array of the appropriate size and delete the old one.

Use a variable to keep track of how many elements of the array are being used.
When you start:
unsigned num_elements = 10;
int *ptr = malloc(num_elements * sizeof(int));
When you delete, do the following as well:
--num_elements;
When you print:
for (unsigned i=0; i<num_elements; ++i) {
...
}
Since you print the array in multiple places in the code, it would be nice to create a small function to do it.
void print_array(int *a, unsigned size) {
if (size == 0) {
printf("[empty]\n");
return;
}
printf("%d", a[0]);
for (unsigned i=1; i<size; ++i) {
printf("\t%d", a[i]);
}
printf("\n");
}
print_array(ptr, num_elements);

Your questions refers to 2 issues here:
Deleting an element of an dynamically allocated array
Printing values of an dynamically allocated array without adjusting for loop parameters
1)
for(i=pos;i<10;i++)
{
ptr[pos-1]=ptr[pos];
pos++;
}
Does not decrease the array at all - you just overwrite the particalur position with another element but you still have memory allocated for 10 int
One way to reach that would be using realloc after you moved the values by to the left beginning at the target element:
for (i = pos; i < array_size - 1; i++)
{
ptr[i] = ptr[i+1];
}
ptr = realloc(ptr, --array_size)
To 2)
Simple answer: This wont be possible. When you decrease the size of your array and dont adjust the loop's paramter you will access memory which doesnt belong to the array anymore.
Of course you dont want to adjust every for-loop by hand but you can simplify life if you always remember the array's size, preferably in immediate reference to it within a struct:
typedef struct
{
size_t size;
int *array;
} my_array_t;
If you ensure that size is properly adjusted everytime you allocate the array's memory (functions are your friend), you can always print the values with:
my_array_t a;
a.size = 10;
a.array = malloc(a.size * sizeof(int));
for (i=0; i < a.size; i++)
// ...

Related

Unexpected output of a growing dynamic array

I am attempting to create a dynamic array that will grow in size if needed, as I don't know how large the array will actually be. My code seems to work until the 8th element of the array where I start to see very large incorrect values that I did not enter. Not sure why this is happening.
#include <stdio.h>
#include <stdlib.h>
int main (int argc, char** argv)
{
int val;
int userInput;
int* arr;
int size = 1;
int arrIndex = 0;
arr = (int*) malloc(sizeof(int) * size);
/* prompt the user for input */
printf ("Enter in a list of numbers to be stored in a dynamic array.\n");
printf ("End the list with the terminal value of -999\n");
/* loop until the user enters -999 */
scanf ("%d", &val);
while (val != -999)
{
if (arrIndex >= size)
{
size++;
}
arr[arrIndex] = val;
arrIndex++;
/* get next value */
scanf("%d", &val);
}
int j = 0;
for(j = 0; j < size ; j++)
{
printf("%d \t", arr[j]);
}
}
The size of the array remains 1 and doesn't increase while incrementing size variable.
Your code worked until 8th element because adjacent memory after the array upto 7th element must be free.
In C array index out of bound is not checked and it is programmers responibility.
if you want to increase or decrease size of array you can use realloc inside while loop:
arr=(int*)realloc(arr,sizeof(int)*size);
Also Correct this if condition in your code initially arrayindex is 0 and size is 1 which results in false.
if (arrIndex >= size)
{
size++;
}

I'm trying to merge two sorted (int)arrays using pointers and for some reason it stores the addresses

void interclas(int *ptr,int *vec, int *c, int n) {
int i,j,tmp;
tmp=0;
for (i=0;i++;i<n)
for (j=0;i++;j<n)
{
if (vec[j]<=ptr[i])
c[tmp]=vec[j];
else
c[tmp]=ptr[i];
tmp++;
}
}
int main() {
int i,n;
int *ptr,*vec,*c;
printf("Nr. of elements of initial arrays : 5 \n");
n=5;
vec=(int*)malloc( n * sizeof(int));
ptr=(int*)malloc( n * sizeof(int));
c=(int*)malloc( 2 * n * sizeof(int));
for (i=0;i<n;i++) {
scanf("%d",&ptr[i]);
}
for (i=0;i<n;i++) {
scanf("%d",&vec[i]);
}
printf("\n");
printf("Initial arrays are : ");
for (i=0;i<n;i++) {
printf("%d ",ptr[i]);
}
printf("\n");
for (i=0;i<n;i++) {
printf("%d ",vec[i]);
}
interclas(ptr,vec,&c,n);
printf("Merged array is : ");
for (i=0;i<10;i++) {
printf("%d ",c[i]);
}
return 0;
}
So I'm trying to merge two sorted arrays into one new one using pointers with the function 'interclas'. I tried using the same method to sort an array with a pointer in a function and it worked just fine. Now as you can see, it stores the adress of the variable rather than the variable itself.
If I run this, it stores the adresses of the arrays. How can I fix this? (I'm still new to pointers)
In your method's body, change:
for (i=0;i++;i<n)
for (j=0;i++;j<n)
to this:
for (i=0; i<n; i++)
for (j=0; j<n; j++)
and then change the call to your method, from this:
interclas(ptr, vec, &c, n);
to this:
interclas(ptr, vec, c, n);
since the prototype expects a pointer to an int, for the third parameter.
The logic of your method is also flawed, try to put some printfs (e.g. printf("here i = %d, j = %d, ptr[i] = %d, vec[j] = %d, tmp = %d\n", i, j, ptr[i], vec[j], tmp);) to see what values your variables have at its iteration - you only get the first two elements of the first array to be merged!
If you think about it, what you'd like to do is to go through the first element of array ptr and vec, and store the minimum of this two. If now that min was of array ptr, you'd like the next element of ptr to be taken into account, otherwise the next element of vec.
Take a pencil and a paper and sketch that algorithm - you'll see that it goes out nicely, but some leftover elements might be left behind, and not get inserted in the output array.
Driven from that observation, after traversing both the arrays and comparing elements, we will loop over the first array, if needed, to collect elements that were not visited. Similarly for the second array.
Coding that thought gives something like this:
void interclas(int *ptr,int *vec, int *c, int n) {
int i = 0, j = 0, tmp = 0;
// Traverse both arrays simultaneously,
// and choose the min of the two current elements.
// Increase the counter of the array who had
// the min current element.
// Increase the counter for the output array in
// any case.
while(i < n && j < n)
{
if(ptr[i] < vec[j])
{
c[tmp++] = ptr[i++];
}
else
{
c[tmp++] = vec[j++];
}
}
// Store remaining elements of first array
while (i < n)
c[tmp++] = ptr[i++];
// Store remaining elements of second array
while (j < n)
c[tmp++] = vec[j++];
}
Not the source of your problem, but Do I cast the result of malloc? No.

How to compare if an array is the same in reverse in C?

C language
I want to compare an array with it's reversed form and check to see if it's the same.
For example, arr1 = 5 5 8 8 5 5
Reversed arr1 = 5 5 8 8 5 5
Then output would be: Array is the same in reverse.
For some reason when I try to compare my two arrays, it ALWAYS says it is the same even if it is not.
For example : 7 8 9 is entered. The reverse is 9 8 7, which is not the same as what was entered. However, my code says it is.
How can I fix my comparison so that the results are accurate? Please advise, thank you!
I tried using goto to display results. This is my code (function):
void function(int *arr)
{
int j, c, temp, size;
size = sizeof(arr);
int old[size];
int new[size];
/*Prints original array from user input*/
printf("Input Array: ");
for(j=0; j<size; j++)
{
printf("%d ", arr[j]);
old[j] = arr[j];
}
printf("\n");
/* Reversing the array */
c = j - 1;
j = 0;
while (j < c)
{
temp = arr[j];
arr[j] = arr[c];
arr[c] = temp;
j++;
c--;
}
/* Print Reversed Array */
int i;
for(i=0; i<size; i++)
{
printf("%d ", arr[i]);
/*saved to new for possible comparison*/
new[i] = arr[i];
}
printf("\n");
/* Compare original array with reversed array */
if(temp = arr[j])
{
goto same;
} else {
goto notsame;
}
same:
printf("Array is the same in reverse\n");
return 0;
notsame:
printf("Array is not the same in reverse\n");
return 0;
}
You can't get the size of the array with sizeof. You should print out size and see what that value is giving you, it won't be the size of the array.
The reason you are always getting the "same" is that you aren't actually comparing values. You are assigning arr[j] to temp. if(temp = arr[j]) should be if(temp == arr[j]). I think you will find that it won't go to same anymore.
An easier way to solve this problem would be:
void checkReverse(int* arr, int arrSize)
{
// Loop through the array until you have hit the middle
for (int i = 0; i < (arrSize - i); i++)
{
// Check the element to the element in the same place counting from the back
if (arr[i] != arr[arrSize - i - 1])
{
// If we find any that don't match, we know it's not the same and can return
printf("Array is NOT the same in reverse.\n");
return;
}
}
// If we made it this far, they are the same
printf("Array is the same in reverse.\n");
return;
}
You need to modify your code with the following two points:
In your code, size means the number of elements in the array correct? so to calculate it correctly replace
size = sizeof(arr)/sizeof(int);
sizeof gives you the memory size occupied by the array, so for the array of three integers, it gives 3*int size. To count the elements of an array you need to use sizeof(array) and divide it with the size of the data type.
You need to traverse in the loop and compare each element of the original array and reversed array to confirm is it the same not.
So you need to replace your comparison logic with :
/* Compare original array with reversed array */
for(i=0;i < size;i++)
{
if(new[i] != old[i]){
printf("Array is not the same in reverse\n");
return;
}
}
printf("Array is the same in reverse\n");
return;
If you want to use recursion to solve this problem.
#include <stdio.h>
int compare(int *arr, int p, int q)
{
/* base case, if we are at or pass the middle point */
if (p >= q)
return 1;
if (arr[p] != arr[q]) {
return 0;
} else {
return compare(arr, p + 1, q - 1);
}
}
int main(int argc, char *argv[])
{
int arr1[] = {5, 5, 8, 8, 5, 5};
size_t array_size = sizeof(arr1) / sizeof(int);
int first = 0;
int last = array_size - 1;
if (compare(arr1, first, last)) {
printf("Array is same in reverse\n");
} else {
printf("Array is not same in reverse\n");
}
return 0;
}
Best solution to this question during an interview IMO: Use a stack:
step 1)
racecar -> push into stack -> STACK
step 2)
STACK-> pop from stack -> racecar
The input and output strings are the same, therefore the word is a palindrome.
As opposed to:
step 1) something -> push into stack -> STACK
step 2) STACK-> pop from stack -> gnihtemos
The input and output strings are NOT the same, therefore the word is NOT a palindrome.

saving data from an array in C

I should mention that I am in my 1st 2 weeks of an intro to programming class before people get too crazy with answers.
Using this array as an example,
int scores[30] = {90,85,100,50,50,85,60,70,55,55,80,95,70,60,95,
80,100,75,70,95,90,90,70,95,50,65,85,95,100,65}
I am trying to parse through it to create 2 new parallel arrays to use later. The idea is to make one array that holds the "scores" and one that holds the "occurrences" of each score. I end up compiling with no errors however during run time it crashes.
void frequency(int scores[], int max){
int i, x=0, temp=0, count=0, sum=0, mode=0;
int score[sum]; //unknown length of array, sum gets added after the while loop
int freq[sum];
printf("score\tfrequency\n");
printf("-----\t---------\n");
fprintf(fp, "score\tfrequency\n");
fprintf(fp, "-----\t---------\n");
for (i = 0; i < max; ++i){
while (scores[i]==scores[x]){
x++;
count++;
sum++;
temp = x-1;
if(scores[i] != scores[x]){
//printf(" %d\t %d\n",scores[i], count);
freq[i] = count;
score[i] = scores[i];
count=0;
i=temp;
x=temp+1;
sum++;
printf("%d\t%d", score[i], freq[i]);
fprintf(fp, "%d\t%d", score[i], freq[i]);
}
}
}
}
This part:
int i, x=0, temp=0, count=0, sum=0, mode=0;
int score[sum];
int freq[sum];
looks wrong.
You set sumto zero and then use it for the array dimension. Did you mean to do:
sum = max;
I end up compiling with no errors however during run time it crashes.
Reason:
The reason why your program crashes is because you have not allocated sufficient memory to the arrays that you use int the frequency() function
void frequency(int scores[], int max){
int i, x=0, temp=0, count=0, sum=0, mode=0;
int score[sum];
int freq[sum];
Solution:
So, is there a way to provide memory during run time according to requirements or change memory size of blocks during compile time?
Yes, that's the very reason why Dynamic memory allocation is used.... though you send a fixed array to the frequency() function in your code, the function I've provided works for any integer array you send..
Here I've provided code in which
one array stores all the unique scores
and other array stores number of occurrences of each score
I've done this using dynamic memory allocation.. I think it's easy to understand if you have basic understanding of dynamic memory allocation functions.. if you have any doubts, ask me through the comments :) and by the way I've assumed your main function to be :
int main()
{
int scores[30] = {90,85,100,50,50,85,60,70,55,55,80,95,70,60,95,
80,100,75,70,95,90,90,70,95,50,65,85,95,100,65};
frequency(scores,30);
return 0;
}
Code:
#include <stdio.h>
#include <stdlib.h>
void frequency(int scores[], int max);
int main()
{
int scores[30] = {90,85,100,50,50,85,60,70,55,55,80,95,70,60,95,
80,100,75,70,95,90,90,70,95,50,65,85,95,100,65};
frequency(scores,30);
return 0;
}
void frequency(int scores[], int max)
{
int i,j,count=0,flag=0,occur=0;
int *score=malloc(sizeof(int));
if(malloc==NULL)
{
printf("memory allocation failed");
exit(1);
//it's good to check if memory allocated was successful or not
//I've avoided it for further allocations,to decrease the size of post :)
}
int *freq=malloc(sizeof(int));
printf("score\tfrequency\n");
printf("-----\t---------\n");
//building array which has only scores
for(i=0;i<max;i++)
{
if(count==0) //first time
{
score=realloc(score,(count+1)*sizeof(int));
//increasing size of array by 1*sizeof(int)
score[count]=scores[i];
count++;
}//first one requires no checking whether it's repeated or not
else
{
flag=0; //resetting flag value
for(j=0;j<count;j++)
{
if(scores[i]==score[j])
{
flag=1; //
break;
}
}
if(flag==0) // if not repeated need to add new element
{
score=realloc(score,(count+1)*sizeof(int));
score[count]=scores[i];
count++;
}
}
}
//allocating memory for frequency array
freq=realloc(freq,count*sizeof(int));
//building array which has frequency of each score
for(i=0;i<count;i++)
{
occur=0;
for(j=0;j<max;j++)
{
if(score[i]==scores[j])
occur++;
}
freq[i]=occur;
}
for(i=0;i<count;i++) //printing output
printf("\n %d\t %d\n",score[i],freq[i]);
free(score); //freeing the blocks
free(freq);
}
My approach is quite simple to understand
first I create array score which creates extra memory whenever it encounters unique elements and stores in it
and then I check occurrences for each of the element of score array in the scores array and store them in freq array.
Output:
score frequency
----- ---------
90 3
85 3
100 3
50 3
60 2
70 4
55 2
80 2
95 5
75 1
65 2
I hope this is what you were trying to achieve :)

Array doesn't print in reverse in C using pointers

I am trying to make a program that takes 10 numbers as input and outputs them in reverse order using pointers in C.
#include<stdio.h>
#define N 10
int array[N]; //Global variable
int main(void) {
int j;
int i;
printf("Enter 10 numbers: ");
for (i=0;i<N;i++) {
scanf("%d",(array+(4*i))); //Works
}
for (j=N-1;j<0;j--) {
printf("%d",array[j]); //Doesn't print, using *(array+j*4) doesn't
//print also
}
printf("\n");
printf("%d\n",*(array)); //Works so scanf works
printf("%d\n",*(array+4)); //Works so scanf works
return 0;
}
I have tried a making a seperate function for the two for loops but still it doesn't work. I want to know WHY this for-loop doesn't print but the two printfs below it print.
EDIT:
My new code is
#include<stdio.h>
#define N 10
int array[N]; //Global variable
int main(void) {
int j;
int i;
printf("Enter 10 numbers: ");
for (i=0;i<N;i++) {
scanf("%d",(array+i)); //Works
}
for (j=N-1;j<0;j--) { //it is supposed to be j>=0 or j>0 WHY
printf("%d",array[j]); //Doesn't print, using *(array+j) doesn't
//print also
}
printf("\n");
printf("%d\n",*(array)); //Works so scanf works
printf("%d\n",*(array+1)); //Works so scanf works
return 0;
}
Thanks to all the posts, I have a better understanding of how indexing works in C now but the printf doesn't work still unless I change the for-loop conditions(see above). WHY doesn't it work with the initial conditions but with the latter conditions.
Whoa!
This:
scanf("%d",(array+(4*i))); //Works
is very wrong and is overwriting memory! Why are you multiplying the index? You don't need to do that, C can index by itself. It should just be:
scanf("%d", &array[i]);
You want the address of the i:th array member, so say that, don't beat around the bush with strange multiplications.
If you really want to be "using pointers", as mentioned in a comment, you can do so:
scanf("%d", array + i);
This works since array is a pointer to the first element of the array, and adding i to is a fully valid use of pointer arithmetic; C will compute the proper pointer, knowing the size of each int in the array.
Your array consists of 10 elements with type int (obviously). In expression array + i variable i is not an offset in bytes. It is an index of element. So when you read it like you do (scanf("%d",(array+(4*i)))) you basicly read array[0], array[4], array[8], array[12] (we're out of array bounds here already, it causes memory corruption and might cause crashes), etc. Elements array[1],[2],[3],[5], etc. are uninitialized. That's why your code doesn't work :)
UPDATE:
And #shilong-liu's note about array indices is important, too. I didn't notice it.
for (j=N-1;j<0;j--) {
printf("%d",array[j]); //Doesn't print, using *(array+j*4)
}
the for loop is not right. The correct one is that
for (j = N - 1; j > 0; j--)
I guess since the pointer used is of type int, you assume that you have to multiply i by 4 because depending on the compiler int is 4 bytes. I guess if you really care only about the output, then you could do it the way you did with reverse iteration.
What you have to do has been already mentioned by the others so I will give you my solution for actually swapping the pointers memory wise and you could choose from the given solutions:
#include<stdio.h>
#define N 10
int array[N]; //Global variable
int main(void) {
int j;
int i;
printf("Enter 10 numbers: ");
for (i=0; i<N; i++) {
scanf("%d", (array + i));
}
for (left = 0; left < N / 2; left++)
{
int right = N - left - 1;
int temporary = array[left];
array[left] = array[right];
array[right] = temporary;
}
for (i=0; i<N; i++) {
printf("%d", (array + i));
}
return 0;
}
I have been programming for algorithmic contests so you could trust me.

Resources