Creating a new array without duplicate integers from an array in C - c

I was asked to create a new array without duplicate integars from an array.
I think I made a mistake in my code but can't notice anything wrong.
The output for "1, 2, 1, 2, 1, 4" is "1, 2, 2, 4".
It's supposed to be "1, 2, 4"
Would like to learn about my mistake.
// Exercise 2 -
void Ex2() {
int i, counter = 1, size = -1;
int* array = input_dynamic_array(&size);
int* newArr = (int*)malloc((size)* sizeof(int));
newArr[0] = array[0];
assert(array);
for (i = 1; i < size; i++) {
if (!find_num_in_newArr(newArr, size, array[i])) {
newArr[counter++] = array[i];
}
}
newArr = (int*)realloc(newArr, (counter)*sizeof(int));
printArray(newArr, counter);
free(array);
free(newArr);
}
bool find_num_in_newArr(int *newArr, int size, int num) {
int i;
for (i = 0; i < size; i++) {
if (newArr[i] == num) {
return true;
}
return false;
}
}
int* input_dynamic_array(int *size)
{
int *array;
int ii;
printf("Enter array size: ");
scanf("%d", size);
array = (int*)malloc((*size) * sizeof(int));
assert(array);
printf("Enter %d integer numbers: ", *size);
for (ii = 0; ii < *size; ii++)
scanf("%d", array + ii);
return array;
}

I see a problem here:
for (i = 0; i < size-1; i++)
{
if (newArr[i] == num)
{
return true;
}
return false;
}
This will never have another iteration. It will either return true or false from the first iteration. Thats not what you are planning for when you used a loop.
Based on your design, you might want to move return false; outside the loop.
Another advise, Don't cast the return value of malloc, its pointless.
Also,
int* newArr = (int*)malloc((size)* sizeof(int));
This needs to be followed by a check. You need to check if malloc returned NULL. If yes, then memory is not allocated and anything with modification based on newArr would be horrible.
A relative cleaner way of doing it will include using a function that looks like below:
int RemoveDuplicates(int* Arr, int length)
{
int i = 0, j = 0;
int LengthChanged = 0;
for (i = 1; i < length; i++)
{
for(j = 0; j < LengthChanged ; j++)
{
if(Arr[i] == Arr[j])
break;
}
// Copy as is if there is not duplicate element in the array
if (j == LengthChanged )
Arr[LengthChanged++] = Arr[i];
}
return LengthChanged;
}

There are 2 problems in your code:
find_num_in_newArr exits the loop with a return false; at the first iteration. move the return statement outside the loop body.
Ex2 check the whole array for duplicates instead of just the portion already copied: find_num_in_newArr(newArr, size, array[i]) should be find_num_in_newArr(newArr, i, array[i]). As posted, this code has undefined behavior.
Here is a corrected version with a few extra assertions:
// Exercise 2 -
bool find_num_in_newArr(const int *newArr, int size, int num) {
int i;
for (i = 0; i < size; i++) {
if (newArr[i] == num) {
return true;
}
}
return false;
}
int *input_dynamic_array(int *size) {
int *array;
int ii;
printf("Enter array size: ");
assert(scanf("%d", size) == 1);
assert(*size > 0);
array = (int*)malloc((*size) * sizeof(int));
assert(array != NULL);
printf("Enter %d integer numbers: ", *size);
for (ii = 0; ii < *size; ii++) {
assert(scanf("%d", array + ii) == 1);
}
return array;
}
void Ex2(void) {
int i, counter, size;
int *array = input_dynamic_array(&size);
int *newArr = (int*)malloc(size * sizeof(int));
assert(newArr != NULL);
newArr[0] = array[0];
counter = 1;
for (i = 1; i < size; i++) {
if (!find_num_in_newArr(newArr, i, array[i])) {
newArr[counter++] = array[i];
}
}
newArr = (int*)realloc(newArr, counter * sizeof(int));
assert(newArr != NULL);
printArray(newArr, counter);
free(array);
free(newArr);
}

You over complicate it a bit.
Use the correct types for the indexes (size_t)
int CheckValue(int *arr, int value, size_t size)
{
while (size--)
{
if (arr[size - 1] == value) return -1;
}
return 0;
}
int main()
{
int arr[] = {1,4,5,8,3,2,1,-1,9,-1,-1,6,8,1,5,4,2,3};
int newarr[sizeof(arr) / sizeof(arr[0])];
size_t size = 0;
for (size_t index = 0; index < sizeof(arr) / sizeof(arr[0]); index++)
{
if (!CheckValue(newarr, arr[index], size))
{
newarr[size++] = arr[index];
}
}
return 0;
}

Related

Deleting occurrences of an element in an array in C

This C code is for deleting all occurrences of an integer in an array. However, when I executed it, there is a problem with displaying the final array, the code doesn't display the rest of the array once it finds the first occurrence.
unsigned int T[10], n, i, j, exist, integerDeleteOccurences;
printf("Array length : ");
scanf("%u", &n);
for(i=0; i<n; i++)
{
printf("T[%u] : ", i);
scanf("%u", &T[i]);
}
for(i=0; i<n; i++)
{
printf("%u | ", T[i]);
}
printf("The number you want to delete its occurences : ");
scanf("%u", &integerDeleteOccurences);
exist = 0;
for (i=0; i<n; i++)
{
if (T[i] == integerDeleteOccurences)
{
j = i;
for (j=i; j<n-1; j++);
{
T[j] = T[j+1];
}
exist = 1;
i--;
n--;
}
}
if (exist == 1)
{
for (i=0; i<n; i++)
{
printf("%u | ", T[i]);
}
}
else if (exist == 0)
{
printf("This number doesn't exist in the array ! \n");
}
It is far to complicated.
size_t removeFromArray(int *arr, size_t size, int val)
{
int *tail = arr;
size_t newSize = size;
if(arr)
{
while(size--)
{
if(*tail == val) { tail++; newSize--;}
else
*arr++ = *tail++;
}
}
return newSize;
}
When working with statically allocated arrays (i.e. you know the maximum possible size), you should handle them by keeping track of their current size.
Here's a function that delete all occurrencies of an element, given an array and its size, and returns the number of deletions:
int deleteAllOccurrencies(int* arr, int size, int el)
{
int occurrencies = 0;
for (int i = 0; i < size; i++)
{
if (arr[i] == el)
{
occurrencies++;
// shift following elements
for (int j = i; j < size; j++)
{
arr[j] = arr[j + 1];
}
}
}
return occurrencies;
}
Edit with alternative solution (suggested by chqrlie)
The above function loops through an array of integers and for each occurrency found, removes the element from the array and shifts the following values by one position. However, that is not much efficient, since the time complexity of that approach is O(n²).
A better solution would be to loop through the array by using two indexes:
i, which is used to check each value in the starting array, and is increased at the end of each loop;
j, which is used to update only the array elements that are different from the one want to delete, and is increased only when that value is different.
This way we are able to get a much more efficient check, reaching a time complexity of O(n):
int deleteAllOccurrencies(int* arr, int size, int el)
{
int occurrencies = 0;
for (int i = 0, j = 0; i < size; i++)
{
if (arr[i] == el)
{
occurrencies++;
}
else
{
arr[j++] = arr[i];
}
}
return occurrencies;
}
Example Usage
#include <stdio.h>
#define MAX_SIZE 10
int deleteAllOccurrencies(int* arr, int size, int el);
void printArray(int* arr, int size);
int main(int argc, char** argv)
{
int array[MAX_SIZE] = { 1, 2, 3, 4, 2, 6, 7, 8, 2, 10 };
int size = MAX_SIZE, res;
printf("Array: ");
printArray(array, size);
res = deleteAllOccurrencies(array, size, 2);
size = MAX_SIZE - res;
printf("\nResult: %d occurrencies found!\n", res);
printf("Resulting array: ");
printArray(array, size);
return 0;
}
int deleteAllOccurrencies(int* arr, int size, int el)
{
int occurrencies = 0;
for (int i = 0, j = 0; i < size; i++)
{
if (arr[i] == el)
{
occurrencies++;
}
else
{
arr[j++] = arr[i];
}
}
return occurrencies;
}
void printArray(int* arr, int size)
{
printf("[ ");
for (int i = 0; i < size; i++)
{
printf("%d", arr[i]);
if (i < size - 1)
printf(", ");
}
printf("]\n");
}

I want to show elements of a matrix that appear only once

I got this but it I can't seem to make it work, tried everything I could think of.
#include <stdio.h>
#include <stdlib.h>
void alocare_vector(int *v, int nr, int elem)
{
int *v1;
if ((v1 = realloc(v, nr * sizeof(int))) == NULL)
{
printf("Memorie insuficienta");
free(v);
exit(EXIT_FAILURE);
}
v = v1;
v[nr - 1] = elem;
}
int main()
{
int a[100][100];
int n, *v = NULL, i, j, k, l, ok = 0, nr = 0;
printf("Number de elements n:");
scanf("%d", &n);
for (i = 0; i < n; i++)
for (j = 0; j < n; j++)
scanf("%d", &a[i][j]);
for (k = 0; k < n; k++)
{
for (l = 0; l < n; l++)
{
for (i = 0; i < n; i++)
for (j = 0; j < n; j++)
if (a[k][l] == a[i][j] && (k != i && l != j))
ok = 1;
if (ok == 0)
{
nr++;
alocare_vector(v, nr, a[k][l]);
}
ok = 0;
}
}
if (nr > 0)
{
printf("Elements:");
for (i = 0; i < nr; i++)
{
printf("%d ", v[i]);
}
}
free(v);
}
Basically, I need to create a matrix, ans print the elements that appear only once using an array with dynamic memory allocation.
one simple fix is to declare the "int * v" as a global variable and modify the function as alocare_vector(int nr, int elem)
now using a hash table you can store the numbers in the array, below is the your implementation just a bit modified.
#include <stdio.h>
#include <stdlib.h>
int hash[1000]={0};
int * v=NULL;
void alocare_vector(int nr, int elem)
{
int *v1;
if ((v1 = (int*)realloc(v, nr * sizeof(int))) == NULL)
{
printf("Memorie insuficienta");
free(v);
exit(EXIT_FAILURE);
}
v = v1;
v[nr - 1] = elem;
}
int main()
{
int a[100][100];
int n, i, j, nr = 0;
printf("Number de elements n:");
scanf("%d", &n);
for (i = 0; i < n; i++)
{
for (j = 0; j < n; j++)
{
scanf("%d", &a[i][j]);
++hash[a[i][j]];
}
}
for (i = 0; i < n; i++)
{
for (j = 0; j < n; j++)
{
if(hash[a[i][j]]==1)
{
nr++;
alocare_vector(nr, a[i][j]);
}
}
}
if (nr > 0)
{
printf("Elements:");
for (i = 0; i < nr; i++)
{
printf("%d ", v[i]);
}
}
free(v);
}
When calling a your funtion you pass a copy of the pointer. Therfore any modifications to this local copy of the pointer will not affect the copy in main. Therfore you need a refrence or pointer to the pointer in main.
void alocare_vector(int **v, int nr, int elem)
{
...
*v = v1;
}
Here you have brut force example how to generate array of distinct elements of the 2D array:
typedef struct
{
size_t length;
int data[];
}data_t;
data_t *add_element(data_t *arr, int element)
{
size_t newsize = arr ? arr -> length : 0;
arr = realloc(arr, newsize * sizeof(arr -> data[0]) + sizeof(*arr));
if(arr)
{
arr -> length = newsize;
arr -> data[newsize - 1] = element;
}
return arr;
}
int isPresent(size_t rows, size_t cols, size_t vrow, size_t vcol, int (*array)[cols])
{
int val = array[vrow][vcol];
for(size_t row = 0; row < rows; row++)
for(size_t col = 0; col < cols; col++)
{
if(vcol == col && vrow == row) continue;
if(array[row][col] == val)
{
return 1;
}
}
return 0;
}
data_t *distinctElements(size_t rows, size_t cols, int (*array)[cols])
{
data_t *dist = NULL;
for(size_t row = 0; row < rows; row++)
{
for(size_t col = 0; col < cols; col++)
{
if(!isPresent(rows, cols, row, col, array))
{
data_t *tmp = add_element(dist, array[row][col]);
if(tmp) dist = tmp;
else { /* error handling */}
}
}
}
return dist;
}

Function returns incorrect value inside for loop (but correct value outside)

I'm trying to write a basic selection-sort program in C. From debugging, I can see that under the first for loop (// Swap the values), selection(nums, size, i).index returns the same value as i. However, if I call the selection function with the exact same code outside of the for loop, it will correctly return the index (of the number in the array with the smallest value and to the right of the given index).
How can I make selection return the correct value inside the for loop?
#include <stdio.h>
typedef struct {
int value;
int index;
} sorted;
sorted selection(int integers[], int size, int idx);
int main(void) {
int nums[] = {7, 2, 3, 0, 1, 4, 6, 5};
int size = sizeof(nums)/sizeof(int);
int temp;
// Swap the values
for (int i = 0; i < size; i++) {
temp = nums[i];
nums[i] = selection(nums, size, i).value;
nums[selection(nums, size, i).index] = temp;
}
// Print the array
printf("[");
for (int j = 0; j < size; j++) {
if (!(j == size - 1)) {
printf("%i ", nums[j]);
}
else {
printf("%i", nums[j]);
}
}
printf("]\n");
}
sorted selection(int arr[], int size, int start) {
sorted smallest;
for (int i = start; i < size; i++) {
// If first element
if (i == start) {
smallest.value = arr[i];
smallest.index = i;
}
// If smaller
else if (arr[i] < smallest.value) {
smallest.value = arr[i];
smallest.index = i;
}
}
return smallest;
}
The reason why your version is failing is that you are calling selection a second time after starting to modify the array, when the index just needed to be retained after the first call.
The use of sorted and selection are, as #WhozCraig pointed out, completely unnecessary. You are also passing sorted by value which is not the convention in C.
I've renamed the function to indicate its purpose. This could be simplified to take only the elements right of the current index, but that would require some additional adjustments when handling the return value, so its a trade off.
#include <stdio.h>
int indexOfSmallest(int integers[], int size, int idx);
int main(void) {
int nums[] = {7, 2, 3, 0, 1, 4, 6, 5};
int size = sizeof(nums)/sizeof(int);
int temp;
// Swap the values
for (int i = 0; i < size; i++) {
temp = nums[i];
int smallest = indexOfSmallest(nums, size, i);
nums[i] = nums[smallest];
nums[smallest] = temp;
}
// Print the array
printf("[");
for (int j = 0; j < size; j++) {
if (!(j == size - 1)) {
printf("%i ", nums[j]);
}
else {
printf("%i", nums[j]);
}
}
printf("]\n");
}
int indexOfSmallest(int arr[], int size, int start) {
int smallest = start;
for (int i = start; i < size; i++) {
if (arr[i] < arr[smallest]) {
smallest = i;
}
}
return smallest;
}
You need change loop "// Swap the values"
// Swap the values
for (int i = 0; i < size; i++)
{
sorted select = selection(nums, size, i);
temp = nums[i];
nums[i] = select.value;
nums[select.index] = temp;
}

C - Create dynamic matrix with values

i try to create dynamic matrix and enter values with scanf.
Its work only for 1 row, when i increase the error begins.
Can not make progress from the first line and thus can not get values.
int main()
{
int **matrix1;
BuildMatrix(&matrix1, 3, 3);
}
void BuildMatrix(int*** matrix, int row, int column)
{
int i, j, flag = 1, num;
*matrix = (int**)malloc(row * sizeof(int*));
if (*matrix == NULL)
{
printf("Not enough memory!\n");
}
else
{
for (i = 0; i < row && flag; i++)
{
*matrix[i] = (int* )malloc(column * sizeof(int));
if (*matrix[i] == NULL)
{
printf("Not enough memory!\n");
for (j = 0; j < i; j++)
{
free(*matrix[j]);
flag = 0;
}
free(*matrix);
}
}
if (flag)
{
for (i = 0; i < row; i++)
{
for (j = 0; j < column; j++)
{
scanf("%d", &*matrix[i][j]);
}
}
}
}
}
Due to operator precedence, the expression *matrix[i] is equal to *(matrix[i]). That is, it dereferences matrix[i] and not matrix.
You need to use (*matrix)[i] instead.

free() crashes the code

#include <stdio.h>
#include <stdlib.h>
void printingArr(int** arr, int rows);
void sortingEachOneOfThem(int** pArr, int rows);
void sortingTheWholeArray(int** pArr, int rows);
void bubbleSort(int* arr);
void freeArray(int **a, int m);
int main(void)
{
int** pArr = 0;
int numOfRows = 0;
int sizes = 0;
printf("Enter number of rows: ");
scanf("%d", &numOfRows);
pArr = (int**) malloc(sizeof(int*) * numOfRows);
if (pArr == NULL)
{
printf("Unsuccessful malloc!\n");
return 1;
}
for (int i = 0; i < numOfRows; i++)
{
printf("Enter array length for row %d: ",i);
scanf("%d", &sizes);
pArr[i] = (int*) malloc(sizeof(int) * sizes + 1);
if (pArr[i] == NULL)
{
printf("Unsuccessful malloc!\n");
return 1;
}
pArr[i][0] = sizes;
for (int k = 1; k < sizes + 1; k++)
{
printf("Enter value for array: ");
scanf("%d", &pArr[i][k]);
}
}
printingArr(pArr, numOfRows);
sortingEachOneOfThem(pArr, numOfRows);
printingArr(pArr, numOfRows);
sortingTheWholeArray(pArr, numOfRows);
printingArr(pArr, numOfRows);
for (int i = 0; i < numOfRows; i++)
{
if (pArr[i] != NULL)
{
free(*(pArr + i));
}
}
//free(pArr);
system("pause");
return 0;
}
/*
this amazing, wonderfull piece of program prints the array given
input: int** arr, int rows
output: none
*/
void printingArr(int** arr, int rows)
{
int i = 0;
int k = 0;
for (i = 0; i < rows; i++)
{
for (k = 0; k <= arr[i][0]; k++)
{
printf("%d ", arr[i][k]);
}
printf("\n");
}
printf("\n");
}
/*
This beautiful function sorts the whole array, but its length of rows like a pyramid
input: int** arr, int rows
output: none
*/
void sortingTheWholeArray(int** pArr, int rows)
{
int* temp = 0;
int i = 0, k = 0;
for (i = 0; i < rows - 1; i++)
{
for (k = 0; k < rows - 1; k++)
{
if (pArr[k][0] > pArr[k + 1][0])
{
temp = pArr[k];
pArr[k] = pArr[k + 1];
pArr[k + 1] = temp;
}
}
}
}
/*
This little small function sorts every row of the array of arrays given to it
input: int** arr, int rows
output: none
*/
void sortingEachOneOfThem(int** pArr, int rows)
{
int i = 0;
for (i = 0; i < rows; i++)
{
bubbleSort(pArr[i]);
}
}
/*
This little piece of a code is a bubble sort, sorts the array given to it :)
input: int* arr, int rows
output: none
*/
void bubbleSort(int* arr)
{
int i = 1, k = 0;
for (i = 1; i < arr[0] - 1; i++)
{
for (k = 1; k <= arr[0] - i; k++)
{
if (arr[k] > arr[k + 1])
{
arr[k] += arr[k + 1];
arr[k + 1] = arr[k] - arr[k + 1];
arr[k] -= arr[k + 1];
}
}
}
}
the free at the end crashes my code, showing this error:
https://i.stack.imgur.com/nqxBG.png
the same usage of the function free() on another code worked good, but not here. I have tried running through it in step by step mode, it crashes at the first free. Dr. memory shows this: https://i.stack.imgur.com/rSZJr.png
another link: https:// i.stack. imgur.com/ZX2Ne.png (paste it without the spaces in the middle, Can't post more than 2 links)
what can I do?
This:
pArr[i] = (int*) malloc(sizeof(int) * sizes + 1);
under-allocates. Adding a single byte to the size of an array of int makes little sense. You probably meant:
pArr[i] = malloc((sizes + 1) * sizeof *pArri[i]);
Don't cast the return value of malloc(), and use sizeof on the left-hand side.

Resources