I want to make a function that removes elements from an array.
I attempted making the function myself, however, not fully successful:
void remove_element(int* array, int number, int array_length)
{
int i, j;
for (i = 0; i < array_length; i++){
if (array[i] == number) {
for (j = i; j < array_length; j++)
array[j] = array[j+1];
array_length--;
}
}
}
first thing I noticed is after function is called in main, array_lenght is not changed, therefore length of an array remains the same after removing element(s).
So the first question is how to change length of an array inside the void function?
Second thing which doesn't work properly is if in an array are two or more same numbers next to each other, for example if array contains 1,1,3,4,5,6 and user wants to remove 1 function will remove only one element.
Example of my output (wrong):
1,1,3,4,5,6 after fucntion 1,3,4,5,6
Thanks
In the current signature you cannot modify the array, as returning the new array you also need to return the new length.
There are many ways to do it, here is a way with a single loop:
void
remove_element(int* array, int number, int *array_length)
{
int i, j;
for (i = 0, j=0; i < *array_length; i++) {
if (array[i] != number)
array[j++] = array[i];
}
*array_length = j;
}
Doing so, this will mutate both the initial array and the variable keeping its length in the caller and you must pass the value of array_length by reference, somthing like
int* some_array, some_array_length, n;
remove_element(some_array, n, &some_array_length)
Other method would be to return the new length and mutate the array or allocate a new array in the heap and return both the allocated array and the new length.
The other answers to your question aside, if you're likely to do more than one removal on average (or more than one per call ever, actually), it's better not to shift all the subsequent values again and again. Try this:
void remove_element(int *array, int number, int *array_length) {
for(int iRead = 0, iWrite = 0; iRead < *array_length; iRead++) {
if(array[iRead] == number)
continue; /* skip without increasing iWrite */
if(iWrite < iRead) /* it works without this line, too, what's better depends */
array[iWrite] = array[iRead];
iWrite++;
}
*array_length = iWrite;
}
How this works, e.g., with array = {1,1,2,2,3} and number = 2:
1 1 2 2 3
^ iRead
^ iWrite
(increases both, writes nothing)
1 1 2 2 3
^ iRead
^ iWrite
(increases both, writes nothing)
1 1 2 2 3
^ iRead
^ iWrite
(continue happens: increases only iRead)
1 1 2 2 3
^ iRead
^ iWrite
(continue happens: increases only iRead)
1 1 2 2 3
^ iRead
^ iWrite
(writes 3 to iWrite, increases both)
1 1 3 2 3
^ iRead = 5
^ iWrite = 3
(iRead is no longer < *array_length, loop stops, 3 == iWrite is the new length)
Based now on your Comments, I'll do it like this:
#include <stdio.h>
void remove_element(int number, int *arr, size_t *size);
int main(void){
int arr[] = {1,1,3,4,5,6};
long unsigned int arrSize;
int number = 1;
arrSize = sizeof arr / sizeof arr[0];
printf("Before:\n");
for ( size_t i = 0 ; i < arrSize ; i++ ){
printf("%d ", arr[i]);
}
printf("\nAfter:\n");
remove_element( number, arr, &arrSize );
for ( size_t j = 0 ; j < arrSize ; j++ ){
printf("%d ", arr[j]);
}
printf("\n");
}
void remove_element(int number, int *arr, size_t *size){
int arrTemp[*size];
long unsigned int j = 0,c;
for ( size_t i = 0 ; i < *size ; i++ ){
if ( arr[i] == number ){
continue;
}else{
arrTemp[j] = arr[i];
j++;
}
}
for ( size_t k = 0 ; k < j ; k++ ){
arr[k] = arrTemp[k];
}
c = j;
while ( *size > c ){
arr[c] = 0;
c++;
}
*size = j;
}
Output:
Before:
1 1 3 4 5 6
After:
3 4 5 6
By the way in your Question you said:
Examples of output:
1,1,3,4,5,6 after fucntion 1,3,4,5,6
And in your Comment you said:
It doesn't matter how many same numbers there are, in that case above if user wants to remove 1, all 1 's should be removed.
Please make up your mind.
Because array_length is not passed as pointer you're having copy of it on stack, so after you're getting outside of this function you're still having old value. You could use here memmove or memcpy instead of iteration over whole array after you find the same number. The reason why you didn't delete the next 1 in your array is, because when you're on i = 0 -> array[0] == 1, but when you move all of the numbers back then you move second 1 to array[0], without checking it afterwards because after you finished iteration you just increment i, without checking if what you moved to current value of array[i] is the same as previous one.
void remove_element(int *array, int number, int *array_length){
int sameValues = 0;
for(int i = 0; i < *array_length; i++){
while(array[i] == number){
*array_length--;
sameValues++;
}
if(sameValues > 0){
if(i < *array_length){
memmove(&array[i], &array[i + sameValues], (*array_length - i) * sizeof(int));
}
sameValues = 0;
}
}
}
To make it even more dynamic you could use realloc (and actually resize the space occupied by your array after you remove members, but then either you need to return new pointer or you need to point to pointer on your stack from where you call the function:
void remove_element(int **array, int number, int *array_length){
int sameValues = 0;
for(int i = 0; i < *array_length; i++){
while((*array)[i] == number){
*array_length--;
sameValues++;
}
if(sameValues > 0){
if(i < *array_length){
memmove(&(*array)[i], &(*array)[i + sameValues], (*array_length - i) * sizeof(int));
}
realloc(*array, *array_length);
sameValues = 0;
}
}
}
P.S. To use memmove you need to include string.h
When you declare an array the compiler will affect an amount of memory, and with array structure you can't change it. There is 2 solutions, change your array length but you still could access to the last "box" or redefine an array with the size wanted.
1st case :
void remove_element(int* array, int number, int * array_length){
int i = 0,j = 0;
while( i < *(array_length)-1){
if(array[i] == number && !find){
i++; //we step over
find = 1; //we find 1 element stop remove
}
array[j] = array[i];
i++;
j++;
}
*(array_length)--;
}
The int * array_length is a pointer to the memory, so your changes are keep when you go back in main. In your example, before remove_element array_length is equal to 6, and after it's 5. But you still could do array[5] (6th element cause notation 0 to 5 in c).
2nd case
int * remove_element(int * array, int number, int * array_length){
int * new_array = malloc((array_length -1) * sizeof(int)); // len - 1 cause we want to delet only 1 element
int i = 0;
int j = i;
int find = 0;
while( i < *(array_length)-1){
if(array[i] == number && !find){
i++; //we step over
find = 1; //we find 1 element stop remove
}
new_array[j] = array[i];
i++;
j++;
}
if (array[array_length] != number && !find){ //if we didn't find att all the element return array
return array;
} else {
*(array_length)--;
return new_array;
}
}
Here you have to return the new_array because int array[6] in your main is a constant : you can't change it with array = new_array.
Edit : yes of course when you don't need anymore your array you have to free it with free(array) (or it's automatically done at the end of the processus, but it's not proper code)
There is also a shorter method with addtion of pointers but it seems quite too complicated with your c lvl :)
Related
I had to make a program that have an array of numbers, and then I need to make a function that get the arr[0] and the length of the array, and then it will print all the numbers without the duplicate ones.
I made this program and it worked good but I feel like I used too much variables for this program. (I started to learned in the last few weeks so its not looks very good)
#include <stdio.h>
#define N 10
void print_set(int *arr, int n) {
int i = 1;
int duplicate_num, check_num, count;
printf(" %d", *arr); //printing the first number (arr[0]).
//starting to check the other number. if they new I'll print them. (start from arr[1]).
arr++;
while (i < n) {
if (*arr != duplicate_num) {
printf(" %d", *arr);
check_num = *arr;
// becouse I found new number, I change it no be equal to the first duplicate_num. (if there are more like him, I change them too).
while (i < n) {
if (*arr == check_num) {
*arr = duplicate_num;
}
arr++;
i++;
count++;
}
i = i - count;
arr = arr - count;
count = 0;
}
arr++;
i++;
}
}
int main() {
int arr[N] = {4, 6, 9, 8, 6, 9, 6, 1, 6, 6};
print_set(&arr[0], N);
return 0;
}
output for this program: 4 6 9 8 1
I'll be happy to see good method to make this program less messy.
For starters the function has undefined behavior. The user can pass 0 as the second argument. It means that the array is empty and has no elements. In this case the expression *arr is undefined.
The second problem is using the uninitialized variable duplicate_num in this if statement
if (*arr != duplicate_num) {
and the uninitialized variable count
count++;
Another problem is that the function changes the array
if (*arr == check_num) {
*arr = duplicate_num;
}
If you need only to output unique values in an array then the source array shall not be changed.
The function can be defined for example the following way
void print_set( const int *a, size_t n )
{
for ( size_t i = 0; i < n; i++ )
{
size_t j = 0;
while ( j != i && a[i] != a[j] ) ++j;
if ( j == i ) printf( "%d ", a[i] );
}
putchar( '\n' );
}
Hello I am trying to print something like this with 2d array.
Note that when user enters the same number, character should be printed above existing char.
EXPECTED RESULTS:
Input 1: 3 //user1 inputs 3
****
****
**x*
Input 2: 1 //user2 inputs 1
****
****
y*x*
Input 3: 1 //user1 inputs 1
****
x***
y*x*
current results:
enter first: 3
3***
***
**x
enter second: 1
1******
******
xx****
enter first: 2
2*********
*********
***xxx***
But keeping printed values on its previous places.
The problem is that they don't get printed in right order. And also it seems that I haven't done the best job with 2d array which is dynamically allocated.
Here is something what I've tried:
#include <stdio.h>
#include <stdlib.h>
int num(int term)
{
int number1;
int number2;
if(term==1)
{
scanf("%d", &number1);
return number1;
}
if (term==2)
{
scanf("%d", &number2);
return number2;
}
return 0;
}
void function(int a, int b, int result[], int size)
{
int i = 0;
int j = 0;
int desired_num = 0;
int count = 0;
int *arr[a];
for (i = 0; i < a; i++)
arr[i] = (int *)malloc(a * sizeof(int));
for (i = 0; i < a; i++)
for (j = 0; j < b; j++)
arr[i][j] = ++count;
for (i = 0; i < a; i++)
{
for (j = 0; j < b; j++)
{
for (int counter = 0; counter < size; counter++)
{
if (arr[i][j] == arr[a - 1][result[counter] - 1])
{
arr[i][j] = desired_num;
}
if (arr[i][j] == desired_num)
{
printf("%s", "x");
}
else
{
printf("*");
}
}
}
printf("\n");
}
}
int main()
{
int counter = 1;
int i = 0;
int given_number;
int array[20];
for (;;)
{
if (counter % 2 != 0)
{
printf("enter first: ");
given_number = num(1);
printf("%d", given_number);
}
else
{
printf("enter second: ");
given_number = num(2);
printf("%d", given_number);
}
array[i] = given_number;
function(3, 3, array, counter);
counter++;
}
return 0;
}
array[i] = given_number;
i is never changed from the value of 0. You are only ever overwriting the first element of array each iteration. The other 19 elements remain in an indeterminate state.
counter and array are passed to function, as size and result respectively:
This means as size is incremented, it is used as a bounds for accessing elements of result; elements that contain indeterminate values.
for (int counter = 0; counter < size; counter++)
{
if (arr[i][j] == arr[a - 1][result[counter] - 1])
This will surely lead to Undefined Behaviour as those indeterminate values are used to index arr, effectively accessing random memory offsets. This fact alone makes it hard to reason about the output you are seeing, as really anything is valid.
While perfectly valid, the variable-length array of dynamic allocations is a somewhat perplexing choice, especially considering you fail to free the memory allocated by malloc when you are done with it.
int *arr[a];
for (i = 0; i < a; i++)
arr[i] = (int *)malloc(a * sizeof(int));
int arr[a][b]; would work, given a and b are not stack-crushingly large values (or non-positive). You are, or would be, bounded by the size of array in main anyway.
The triply nested loop is confused at best. There is only logic for printing the x and * characters, so you obviously will never see a y.
For each element of arr, you iterate through each element of result. If the current element of arr equals the value of the column selected by the current value of result ([result[counter] - 1]) in the last row (arr[a - 1]) you print x, otherwise *.
Again UB from utilizing indeterminate values of result, but you can see you are printing a * b * size characters, plus newlines, each iteration.
This is severely flawed.
Some other things of note:
The two branches of the if .. else statement in the num function do the exact same thing, just with different identifiers.
The two branches of the if .. else statement in main are identical, other than the first printf in each, and the integer value passed to num, which have the same effect.
This means the only thing that needs to branch is the printf argument.
A generic function for getting an integer would work fine
int get_num(void)
{
int n;
if (1 != scanf("%d", &n)) {
fprintf(stderr, "Could not read input.\n");
exit(EXIT_FAILURE);
}
return n;
}
for use inside main
if (counter % 2 == 0)
printf("enter first: ");
else
printf("enter second: ");
given_number = get_num();
A small issue: printf("%d", given_number); is muddling the output slightly.
There is no reason to repeatedly generate the array. Initialize an array in main to serve as the state of the program. Over time, fill it with the users' selections, and simply print the array each iteration.
Make sure to always check the return value of scanf is the expected number of conversions, and ensure the integers provided by the users will not access invalid memory.
Here is a cursory example.
#include <stdio.h>
#include <stdlib.h>
#include <string.h>
#define EMPTY '*'
#define PLAYER_ONE 'X'
#define PLAYER_TWO 'O'
int get_num(void)
{
int n;
if (1 != scanf("%d", &n)) {
fprintf(stderr, "Could not read input.\n");
exit(EXIT_FAILURE);
}
return n;
}
int main(void)
{
const size_t rows = 6;
const size_t cols = 7;
char board[rows][cols + 1];
memset(board, EMPTY, sizeof board);
/* our rows are now strings */
for (size_t i = 0; i < rows; i++) {
board[i][cols] = '\0';
puts(board[i]);
}
unsigned char turn = 1;
while (1) {
printf("Player %s, Enter column #(1-%zu): ",
turn & 1 ? "One" : "Two", rows);
int input = get_num();
if (1 > input || input > cols) {
printf("Invalid column [%d]. Try again...\n", input);
continue;
}
size_t sel = input - 1;
if (board[0][sel] != EMPTY) {
printf("Column [%d] is full! Try again...\n", input);
continue;
}
size_t n = rows;
while (n--) {
if (board[n][sel] == EMPTY) {
board[n][sel] = turn & 1 ? PLAYER_ONE : PLAYER_TWO;
break;
}
}
for (size_t i = 0; i < rows; i++)
puts(board[i]);
turn ^= 1
}
}
Hi I wrote this sorting algorithm and I'm not sure why I'm getting the following error: "member reference base type 'int' is not a structure or union"
void sort(float avg_dist, cg[]){
int i,j,t;
for(i=1; i<=cg[i]-1; i++)
for(j=1; j<=cg[i]-i; j++)
if(cg[j-1].avg_dist >= cg[j].avg_dist){
t = cg[j-1];
cg[j-1] = cg[j];
cg[j] = t;
}
}
cg is an int array.
You can't access a "member" of an int, as in
cg[j-1].avg_dist
I'm not sure what you're trying to do. Maybe multiply ?
cg[j-1] * avg_dist
It's not the problem, but you're (perhaps intentionally) omitting the type specifier in your function
void sort(float avg_dist, cg[]){
C is defaulting to an int array type, which of course, renders cg[j].avg_dist syntactically invalid. (In reality you probably want to multiply by avg_dist, use * rather than the member selection operator .).
This should give you a clear Idea:
#include <stdio.h>
void sortArray(int *array, int length){
int i,j, k, temp;
for (i = 0 ; i < length-1; i++){
for (k = 0 ; k < length-i-1; k++){
if (array[k] > array[k+1]){
temp = array[k];
array[k] = array[k+1];
array[k+1] = temp;
}
}
}
printf("The result:\n");
for ( j = 0 ; j < length ; j++ ){
printf("%d ", array[j]);
}
}
int main(void){
int array[] = {1,4,2,-1,2,3,4,1,3,-1};
int length = sizeof array / sizeof array[0];
sortArray(array, length);
printf("\n");
return 0;
}
Output:
The result:
-1 -1 1 1 2 2 3 3 4 4
I have to write a function that will return true if every integer in the array is unique (different). So, I've tried correcting my for loops/my if statement and I've tried running the tests that I wrote. But, the test for a string with an integer appearing more than once still fails. I've reviewed my code but I still can't find the problem.
#include "in.h"
int in(int input[], int size)
{
for (int i = 0; i < size - 1; i++)
{
for (int j = i + 1; j < size; j++)
{
if (input[i] == input[j])
{
return 0;
}
}
}
return 1;
}
Here are my test cases:
#include "in.h"
#include "checkit.h"
void in_tests(void)
{
int input[3] = {2, 4, 5};
int answer;
answer = in(input, 3);
checkit_int(answer, 1);
int input1[4] = {1, 3, 4, 1};
int answer1;
answer1 = in(input1, 4);
checkit_int(answer, 0);
}
int main()
{
in_tests();
return 0;
}
without sort, an O(n2):
j begins with i+1.
int IsDiff(int array[], int count)
{
int i,j;
for (i=0; i<count; i++)
{
for (j=i+1;j<count;j++)
{
if (array[i] == array[j])
return 0;
}
}
return 1;
}
If space is not an issue, then we can have a O(n) solution using a hashtable. Start storing each element of the array in a hashtable. While inserting elements, make a check to see if it already present in the hashtable ( which takes O(1) time.) If the element is already present, then return false immediately, else iterate until the end of array and return true.
actually, thats not why your function doesn't work. the main reason is because currently you are checking if any pair DONT match, which would be great if you wanted to see if all the elements matched, but you want to do the opposite, so you want to check the opposite, if any pair DOES match. so first change your if to be
if(input[i] == input[j]) return false;
if one pair is equal then you know that your test has already failed so there is no need to check the remaining pairs, just return false there and then.
the only other thing to do is to sort out your loops so that you only iterate over each pair once and don't compare a value against it's self. to do that change the for loops to be:
for(int i =0; i<size-1; i++)
for(int j=i+1; j<size; j++)
then if you make it to the end of the function, it means no pair as matched, so just return true;
O(n^2) as well.. but I added this function that makes the code more understandable...
int unique(int input[], int value,int size){
int times=0;
for (int i = 0; i < size; i++)
{
if(input[i]==value){
times++;
if(times==2)
return 0;
}
}
return 1;
}
int in(int input[], int size)
{
int x, answer;
for (int i = 0; i < size; i++)
{
if(!unique(input,input[i],size))
return 0;
}
return 1;
}
You are very close, try this:
#include "in.h"
int in(int input[], int size)
{
int answer = 1;
for (int i = 0; i < size-1; i++)
{
for (int j = i+1; j < size; j++) //check everything above your current
//value because you have already checked
//below it.
{
if (input[i] == input[j])
{
answer = 0; //If any are not unique you
break; //should exit immediately to save time
}
}
if (answer == 0)
break
}
return answer;
}
Thinking about the problem
let's say you have an array like this: int array[] = { 3, 1, 4, 8, 2, 6, 7, 7, 9, 6 };
if you start with the first element you need to compare to the rest of the elements in the set ; so 3 needs to be compared to 1, 4, 3... etc.
if 3 is unique you need to now go to 1 and look at the remaining elements, but next time around you don't need to worry about the 3 ; so your value under consideration (let's call that V) needs to be each of, array[0] to array[N-1] where N is the size of array (in our case 10);
But if we imagine ourselves in the middle of the array, we'll notice that we have already compared previous elements to the current element when the previous element was the value under consideration. So we can ignore any elements "behind" us; which means comparison has to start the each time with the INDEX of current value under consideration (let's call that k) and compare it to values starting with the NEXT index and going to the end of the array ; so pseudo-code for our array of 10 it would look like this:
int is_a_set(int array[])
{
for ( k = 0; k < 10-1 ; k++ ) { /* value under consideration */
v = array[k];
for ( m = k+1 ; m < 10; m++ ) { /* compared to the remaining array starting
* starting from the next element */
if ( v == array[m] ) { /* we found a value that matches, no need to
* to continue going, we can return from this function
*/
return true;
}
}
}
return false;
}
now you can use something like:
if ( is_a_set(my_array) ) {
}
You should be able to use this to figure the rest of your code out :-)
NOTE: a collection with unique elements is called a set so I named the function is_a_set
HINTS: convert size of the array (10) into a parameter or a variable of some sort
Here's my attempt at it (very simple and inefficient though):
#include <stdio.h>
int uniq_int(int arr [], int size)
{
int i, j;
for (i = 0; i < size; i++)
for (j = i + 1; j < size; j++)
if (arr[i] == arr[j])
return 0;
return 1;
}
int main()
{
int arr [] = {1, 2, 4, 3, 5};
(uniq_int(arr, 5)) ? printf("Unique!\n") : printf("Not...\n");
/* the above can be written more traditionally like this:
if (uniq_int(arr, 5) != 0)
{
printf("Unique!\n");
}
else
{
printf("Not...\n");
}
*/
return 0;
}
This will compare every member of the array against the rest, starting from the first
and comparing it against the next one and so on until the end of the inner loop.
Then we start the outer loop again but this time we compare the second element of the array against the ones after it.
As soon as a match is found the function will return and there won't be a need to compare the other elements. Otherwise the outer loop will go on until the last element and once that's reached it will exit and return 1, meaning every member is unique.
It has a complexity of O(n^2) as the set is processed twice for each member in the worst case.
This question already has answers here:
Algorithm: efficient way to remove duplicate integers from an array
(34 answers)
Closed 8 years ago.
I want small clarification in array concept in C.
I have array:
int a[11]={1,2,3,4,5,11,11,11,11,16,16};
I want result like this:
{1,2,3,4,5,11,16}
Means I want remove duplicates.
How is it possible?
You can't readily resize arrays in C - at least, not arrays as you've declared that one. Clearly, if the data is in sorted order, it is straight-forward to copy the data to the front of the allocated array and treat it as if it was of the correct smaller size (and it is a linear O(n) algorithm). If the data is not sorted, it gets messier; the trivial algorithm is quadratic, so maybe a sort (O(N lg N)) followed by the linear algorithm is best for that.
You can use dynamically allocated memory to manage arrays. That may be beyond where you've reached in your studies, though.
#include <assert.h>
#include <stdio.h>
#include <stdlib.h>
static int intcmp(const void *pa, const void *pb)
{
int a = *(int *)pa;
int b = *(int *)pb;
if (a > b)
return +1;
else if (a < b)
return -1;
else
return 0;
}
static int compact(int *array, int size)
{
int i;
int last = 0;
assert(size >= 0);
if (size <= 0)
return size;
for (i = 1; i < size; i++)
{
if (array[i] != array[last])
array[++last] = array[i];
}
return(last + 1);
}
static void print(int *array, int size, const char *tag, const char *name)
{
int i;
printf("%s\n", tag);
for (i = 0; i < size; i++)
printf("%s[%d] = %d\n", name, i, array[i]);
}
int main(void)
{
int a[11] = {1,2,3,4,5,11,11,11,11,16,16};
int a_size = sizeof(a) / sizeof(a[0]);
print(a, a_size, "Before", "a");
a_size = compact(a, a_size);
print(a, a_size, "After", "a");
int b[11] = {11,1,11,3,16,2,5,11,4,11,16};
int b_size = sizeof(b) / sizeof(b[0]);
print(b, b_size, "Before", "b");
qsort(b, b_size, sizeof(b[0]), intcmp);
print(b, b_size, "Sorted", "b");
b_size = compact(b, b_size);
print(b, b_size, "After", "b");
return 0;
}
#define arraysize(x) (sizeof(x) / sizeof(x[0])) // put this before main
int main() {
bool duplicate = false;
int a[11] = {1,2,3,4,5,11,11,11,11,16,16}; // doesnt have to be sorted
int b[11];
int index = 0;
for(int i = 0; i < arraysize(a); i++) { // looping through the main array
for(int j = 0; j < index; j++) { // looping through the target array where we know we have data. if we haven't found anything yet, this wont loop
if(a[i] == b[j]) { // if the target array contains the object, no need to continue further.
duplicate = true;
break; // break from this loop
}
}
if(!duplicate) { // if our value wasn't found in 'b' we will add this non-dublicate at index
b[index] = a[i];
index++;
}
duplicate = false; // restart
}
// optional
int c[index]; // index will be the number of objects we have in b
for(int k = 0; k < index; k++) {
c[k] = b[k];
}
}
If you really have to you can create a new array where that is the correct size and copy this into it.
As you can see, C is a very basic (but powerful) language and if you can, use a vector to but your objects in instead (c++'s std::vector perhaps) which can easily increase with your needs.
But as long as you only use small numbers of integers you shouldn't loose to much. If you have big numbers of data, you can always allocate the array on the heap with "malloc()" and pick a smaller size (maybe half the size of the original source array) that you then can increase (using realloc()) as you add more objects to it. There is some downsides reallocating the memory all the time as well but it is a decision you have to make - fast but allocation more data then you need? or slower and having the exact number of elements you need allocated (which you really cant control since malloc() might allocate more data then you need in some cases).
//gcc -Wall q2.cc -o q2 && q2
//Write a program to remove duplicates from a sorted array.
/*
The basic idea of our algorithm is to compare 2 adjacent values and determine if they
are the same. If they are not the same and we weren't already looking previusly at adjacent pairs
that were the same, then we output the value at the current index. The algorithm does everything
in-place and doesn't allocate any new memory. It outputs the unique values into the input array.
*/
#include <stdio.h>
#include <assert.h>
int remove_dups(int *arr, int n)
{
int idx = 0, odx = -1;
bool dup = false;
while (idx < n)
{
if (arr[idx] != arr[idx+1])
{
if (dup)
dup = false;
else
{
arr[++odx] = arr[idx];
}
} else
dup = true;
idx++;
}
return (odx == -1) ? -1 : ++odx;
}
int main(int argc, char *argv[])
{
int a[] = {31,44,44,67,67,99,99,100,101};
int k = remove_dups(a,9);
assert(k == 3);
for (int i = 0;i<k;i++)
printf("%d ",a[i]);
printf("\n\n");
int b[] = {-5,-3,-2,-2,-2,-2,1,3,5,5,18,18};
k = remove_dups(b,12);
assert(k == 4);
for (int i = 0;i<k;i++)
printf("%d ",b[i]);
printf("\n\n");
int c[] = {1,2,3,4,5,6,7,8,9};
k = remove_dups(c,9);
assert(k == 9);
for (int i = 0;i<k;i++)
printf("%d ",c[i]);
return 0;
}
you should create a new array and you should check the array if contains the element you want to insert before insert new element to it.
The question is not clear. Though, if you are trying to remove duplicates, you can use nested 'for' loops and remove all those values which occur more than once.
C does not have a built in data type that supports what you want -- you would need to create your own.
int a[11]={1,2,3,4,5,11,11,11,11,16,16};
As this array is sorted array, you can achieve very easily by following code.
int LengthofArray = 11;
//First elemnt can not be a duplicate so exclude the same and start from i = 1 than 0.
for(int i = 1; i < LengthofArray; i++);
{
if(a[i] == a[i-1])
RemoveArrayElementatIndex(i);
}
//function is used to remove the elements in the same as index passed to remove.
RemoveArrayElementatIndex(int i)
{
int k = 0;
if(i <=0)
return;
k = i;
int j =1; // variable is used to next item(offset) in the array from k.
//Move the next items to the array
//if its last item then the length of the array is updated directly, eg. incase i = 10.
while((k+j) < LengthofArray)
{
if(a[k] == a[k+j])
{
//increment only j , as another duplicate in this array
j = j +1 ;
}
else
{
a[k] = a[k+j];
//increment only k , as offset remains same
k = k + 1;
}
}
//set the new length of the array .
LengthofArray = k;
}
You could utilise qsort from stdlib.h to ensure your array is sorted into ascending order to remove the need for a nested loop.
Note that qsort requires a pointer to a function (int_cmp in this instance), i've included it below.
This function, int_array_unique returns the duplicate free array 'in-place' i.e. it overwrites the original and returns the length of the duplicate free array via the pn pointer
/**
* Return unique version of int array (duplicates removed)
*/
int int_array_unique(int *array, size_t *pn)
{
size_t n = *pn;
/* return err code 1 if a zero length array is passed in */
if (n == 0) return 1;
int i;
/* count the no. of unique array values */
int c=0;
/* sort input array so any duplicate values will be positioned next to each
* other */
qsort(array, n, sizeof(int), int_cmp);
/* size of the unique array is unknown at this point, but the output array
* can be no larger than the input array. Note, the correct length of the
* data is returned via pn */
int *tmp_array = calloc(n, sizeof(int));
tmp_array[c] = array[0];
c++;
for (i=1; i<n; i++) {
/* true if consecutive values are not equal */
if ( array[i] != array[i-1]) {
tmp_array[c] = array[i];
c++;
}
}
memmove(array, tmp_array, n*sizeof(int));
free(tmp_array);
/* set return parameter to length of data (e.g. no. of valid integers not
* actual allocated array length) of the uniqe array */
*pn = c;
return 0;
}
/* qsort int comparison function */
int int_cmp(const void *a, const void *b)
{
const int *ia = (const int *)a; // casting pointer types
const int *ib = (const int *)b;
/* integer comparison: returns negative if b > a
and positive if a > b */
return *ia - *ib;
}
Store the array element with small condition into new array
**just run once 100% will work
!)store the first value into array
II)store the another element check with before stored value..
III)if it exists leave the element--and check next one and store
here the below code run this u will understand better
int main()
{
int a[10],b[10],i,n,j=0,pos=0;
printf("\n enter a n value ");
scanf("%d",&n);
printf("\n enter a array value");
for(i=0;i<n;i++)
{
scanf("%d",&a[i]);//gets the arry value
}
for(i=0;i<n;i++)
{
if(check(a[i],pos,b)==0)//checks array each value its exits or not
{
b[j]=a[i];
j++;
pos++;//count the size of new storing element
}
}
printf("\n after updating array");
for(j=0;j<pos;j++)
{
printf("\n %d",b[j]);
} return 0;
}
int check(int x,int pos,int b[])
{ int m=0,i;
for(i=0;i<pos;i++)//checking the already only stored element
{
if(b[i]==x)
{
m++; //already exists increment the m value
}
}
return m;
}