removing duplicated names for array in c - arrays

this is what i have to make: c. It should be possible to remove an animal with a specified name. If more animals with the same name exist, it should remove all the animal with the same name.
this is my code:
void deleteAnimalByName(char *animalName, int *nrOfAnimals, ANIMAL *animalArray)
{
for(int i = 0; i < *nrOfAnimals; i ++)
{
if(strcmp((animalArray + i)->Name, animalName) == 0)
{
for(int j = i; j < *nrOfAnimals - 1; j++)
{
animalArray[j] = animalArray[j + 1];
}
(*nrOfAnimals)--;
}
}
}
the outcome after tyring to delete the animals with the same name:
Animals in shelter: 1
Name: ted
Species: Parrot
Age: 1
only one gets deleted, the other one stays. what could cause this?

For starters the function should be declared at least like
size_t deleteAnimalByName( ANIMAL *animalArray, size_t nrOfAnimals, const char *animalName );
And the function can be defined like
size_t deleteAnimalByName( ANIMAL *animalArray, size_t nrOfAnimals, const char *animalName )
{
size_t n = 0;
for ( size_t i = 0; i < nrOfAnimals; i++ )
{
if ( strcmp( animalArray[i].Name, animalName ) != 0 )
{
if ( n != i ) animalArray[n] = animalArray[i];
++n;
}
}
return n;
}
As for your approach then it at least is inefficient because you move all elements of the array one position left after finding an element that need to be deleted.
Here is a demonstrative program
#include <stdio.h>
#include <string.h>
typedef struct ANIMAL
{
char *Name;
} ANIMAL;
size_t deleteAnimalByName( ANIMAL *animalArray, size_t nrOfAnimals, const char *animalName )
{
size_t n = 0;
for ( size_t i = 0; i < nrOfAnimals; i++ )
{
if ( strcmp( animalArray[i].Name, animalName ) != 0 )
{
if ( n != i ) animalArray[n] = animalArray[i];
++n;
}
}
return n;
}
int main(void)
{
ANIMAL animalArray[] =
{
{ "hare" }, { "hare" }, { "fox" }, { "hare" }
};
size_t nrOfAnimals = sizeof( animalArray ) / sizeof( *animalArray );
nrOfAnimals = deleteAnimalByName( animalArray, nrOfAnimals, "hare" );
for ( size_t i = 0; i < nrOfAnimals; i++ )
{
printf( "%s ", animalArray[i].Name );
}
putchar( '\n' );
return 0;
}
The program output is
fox

Related

Common elements within 2 arrays

I'm trying to write a function that copies all of the values in source1 which are also found in source2 into a destination and then returns the number of elements copied into the destination.
int common_elements(int length, int source1[length], int source2[length], int destination[length])
{
int counter = 0;
int i = 0;
while (i < length) {
int j = 0;
while (j < length) {
if ( source1[i] == source2[j]) {
destination[counter] = source1[i];
counter++;
}
j++;
}
i++;
}
return counter;
}
The problem is e.g. given (common_elements(5, {1,2,3,4,5}, {1,2,3,2,1}, [])), the correct input should be
1,2,3
return value: 3
However, the program is accounting for the duplicates and produces :
1,1,2,2,3
return value: 5
which is incorrect.
How can I remedy this?
In this while loop
int j = 0;
while (j < length) {
if ( source1[i] == source2[j]) {
destination[counter] = source1[i];
counter++;
}
j++;
}
you are counting all elements in the array source2 that are equal to the element source1[i].
I can suggest the following solution provided that the source arrays may not be changed within the function.
#include <stdio.h>
size_t common_elements( int destination[],
const int source1[],
const int source2[],
size_t n )
{
size_t counter = 0;
for ( size_t i = 0; i < n; i++ )
{
size_t number = 1;
for ( size_t j = 0; j < i; j++ )
{
if ( source1[i] == source1[j] ) ++number;
}
for ( size_t j = 0; number && j < n; j++ )
{
if ( source1[i] == source2[j] ) --number;
}
if ( number == 0 ) destination[counter++] = source1[i];
}
return counter;
}
int main(void)
{
enum { N = 5 };
int source1[N] = { 1, 2, 3, 4, 5 };
int source2[N] = { 1, 2, 3, 2, 1 };
int destination[N];
size_t n = common_elements( destination, source1, source2, N );
for ( size_t i = 0; i < n; i++ )
{
printf( "%d ", destination[i] );
}
putchar( '\n' );
return 0;
}
The program output is
1 2 3

All max elements and their postition of array

So, for example, I have array: [1, 4, 9, 3, 9]
I need to find all max elements [9, 9] and their index [2, 4]
How can I do this? In C language
int i, pom, max;
max=*gradovi;
for(i=0;i<n;i++) {
if(*(gradovi+i)>max) {
max=*(gradovi+i);
pom=i;
}
if(*(gradovi+i)==max) {
pom=i;
}
}
return pom;
I need postions of all max elemenents, but this print just last
In any case you need a container that will store the indices of the elements with the maximum value.
You can allocate memory dynamically for such a container.
Here is a demonstrative program.
#include <stdio.h>
#include <stdlib.h>
size_t max_elements( const int a[], size_t n, size_t **result )
{
*result = NULL;
size_t count = 0;
if ( n != 0 )
{
size_t max_i = 0;
count = 1;
for ( size_t i = 1; i < n; i++ )
{
if ( a[max_i] < a[i] )
{
max_i = i;
count = 1;
}
else if ( !( a[i] < a[max_i] ) )
{
++count;
}
}
*result = malloc( count * sizeof( size_t ) );
if ( *result != NULL )
{
for ( size_t i = max_i, j = 0; i < n && j < count; i++ )
{
if ( !( a[i] < a[max_i ] ) ) ( *result )[j++] = i;
}
}
}
return count;
}
int main(void)
{
int a[] = { 1, 4, 9, 3, 9 };
const size_t N = sizeof( a ) / sizeof( *a );
size_t *result = NULL;
size_t count = max_elements( a, N, &result );
for ( size_t i = 0; i < count; i++ )
{
printf( "%zu: %d, ", result[i], a[result[i]] );
}
putchar( '\n' );
free( result );
return 0;
}
Its output is
2: 9, 4: 9,
If the returned value from the function is not equal to 0 but the pointer result was set to NULL then it means that there was a memory allocation error. You can check such a situation.
I'm stupid, it's simple solution:
void maks(int *gradovi, int n){
int i, pom, max;
max=*gradovi;
for(i=1;i<n;i++){
if(*(gradovi+i)>max){
max=*(gradovi+i);
}
if(*(gradovi+i)==max){
pom=i;
printf("Najvise zarazenih je u gradu sa indeksom: %d\n", pom);
}
}
}

Sort an array of structs by different members

I need to sort an array of structs each having members with different data types using qsort.
typedef struct {
char* name;
int age;
float wage;
} employee;
The question is, do I have to write 3 different comparator functions for each of them or is there a nice way to implement 1 function?
In any case you need to write a separate function for each data member by which the array will be sorted because within the function you need to compare values of concrete data members.
However you can write a general function that will supply the required comparison function for a call of qsort.
Here is a demonstrative program.
#include <stdio.h>
#include <string.h>
#include <stdlib.h>
typedef struct {
char* name;
int age;
float wage;
} employee;
int cmp_by_name( const void *a, const void *b )
{
const employee *first = a;
const employee *second = b;
return strcmp( first->name, second->name );
}
int cmp_by_age( const void *a, const void *b )
{
const employee *first = a;
const employee *second = b;
return ( second->age < first->age ) - ( first->age < second->age );
}
int cmp_by_wage( const void *a, const void *b )
{
const employee *first = a;
const employee *second = b;
return ( second->wage < first->wage ) - ( first->wage < second->wage );
}
enum SortBy { ByName, ByAge, ByWage };
int ( *select( enum SortBy sort_by ) )( const void *, const void * )
{
int ( *cmp[] )( const void *, const void * ) =
{
cmp_by_name, cmp_by_age, cmp_by_wage
};
switch ( sort_by )
{
default:
case ByName:
return cmp[ByName];
case ByAge:
return cmp[ByAge];
case ByWage:
return cmp[ByWage];
}
}
int main(void)
{
enum { N = 3 };
employee e[N] =
{
{ "Tom", 18, 3500.0f },
{ "Bob", 26, 4500.0f },
{ "Jim", 28, 4000.0f }
};
for ( size_t i = 0; i < N; i++ )
{
printf( "%s, %d, %f\n", e[i].name, e[i].age, e[i].wage );
}
putchar( '\n' );
qsort( e, N, sizeof( employee ), select( ByName ) );
for ( size_t i = 0; i < N; i++ )
{
printf( "%s, %d, %f\n", e[i].name, e[i].age, e[i].wage );
}
putchar( '\n' );
qsort( e, N, sizeof( employee ), select( ByAge ) );
for ( size_t i = 0; i < N; i++ )
{
printf( "%s, %d, %f\n", e[i].name, e[i].age, e[i].wage );
}
putchar( '\n' );
qsort( e, N, sizeof( employee ), select( ByWage ) );
for ( size_t i = 0; i < N; i++ )
{
printf( "%s, %d, %f\n", e[i].name, e[i].age, e[i].wage );
}
putchar( '\n' );
return 0;
}
The program output is
Tom, 18, 3500.000000
Bob, 26, 4500.000000
Jim, 28, 4000.000000
Bob, 26, 4500.000000
Jim, 28, 4000.000000
Tom, 18, 3500.000000
Tom, 18, 3500.000000
Bob, 26, 4500.000000
Jim, 28, 4000.000000
Tom, 18, 3500.000000
Jim, 28, 4000.000000
Bob, 26, 4500.000000
This function should accomplish what you seek:
int compare_employees(const void * e1, const void * e2) {
const employee * emp1 = (employee*)e1;
const employee * emp2 = (employee*)e2;
int ret1 = strcmp(emp1->name, emp2->name);
if (ret1 == 0) {
if (emp1->age == emp2->age) {
float ret2 = emp1->wage - emp2->wage;
if (ret2 == 0)
return 0;
else if (ret2 > 0)
return 1;
else
return -1;
} else {
return emp1->age - emp2->age;
}
} else {
return ret1;
}
}
It first takes alphabetical order into account, then age, and finally wage.
Of course, I assumed you wanted to sort the elements in ascending order. If you want to sort them in descending order, all you'd have to do is flip the values for each comparison:
float ret2 = emp2->wage - emp1->wage; to sort employees by wage in descending order, for example.
Moreover, if you want a different priority for your sorting function (i.e. wage is more decisive than the names' alphabetical order, but the latter is still more decisive than age), arrange them differently within the if statements:
if (ret1 == 0) {
int ret2 = strcmp(emp1->name, emp2->name);
if (ret2 == 0)
return emp1->age - emp2->age;
else
return ret2;
} else if (ret1 > 0) {
return 1;
} else {
return -1;
}
A comparison function appropriate for sorting objects of type employee will receive arguments that point to employee objects. That each object has members of several types affects how you would implement such a function, but that does not in itself present any reason why you would need more than one function.
int compare_employees(const void *e1, const void *e2) {
const employee *employee1 = e1;
const employee *employee2 = e2;
// ... code to compare *employee1 with *employee2 ...
}
However, each comparison function defines a particular way of sorting the objects. If you want to provide for sorting on different criteria then you need a different comparison function for each method of ordering. This has nothing in particular to do with whether the members all have the same data type.

Creating 2 (or 3?) dimensional array of string in C

I want to create an array of string like:
{{"zero","zero"},
{"zero","one"},
{"one","zero"},
{"one","one"}}
If I am not wrong I need 3D array. How can I create it with using dynamic memory allocation and how to return it from function? I mean how is my function should be (char ***getString etc...) and in my main function, how can I use it? Is char ***string = getstring(); work?
I didn't get I have to use 3d array yet, I tried it with 2 mallocs.
I create string of array in function like
char** editKeys = malloc(128 * sizeof(char*));
for (int i = 0; i < 128; i++ )
{
editKeys[i] = (char*) calloc(2, sizeof(char));
}
and it works in function. After that I calledmy function from main like
char **editFile=getEditFile();
printf("%s",editFile[0][0]);
at this point I failed and now I can't be sure is it 2d or 3d and my brain is failed me too. Can't think how can I turned it in 3d array.
If your compiler supports variable length arrays then you can allocate the array the following way
#include <stdio.h>
#include <stdlib.h>
#include <string.h>
void f( size_t n1, size_t n2, size_t n3, char s[n1][n2][n3] )
{
for ( size_t i = 0; i < n1; i++ )
{
if ( i < n1 / 2 )
{
strcpy( s[i][0], "zero" );
}
else
{
strcpy( s[i][0], "one" );
}
if ( i % 2 == 0 )
{
strcpy( s[i][1], "zero" );
}
else
{
strcpy( s[i][1], "one" );
}
}
}
int main(void)
{
enum { N1 = 4, N2 = 2, N3 = 5 };
char ( *p )[N2][N3] = malloc( sizeof( char[N1][N2][N3] ) );
f( N1, N2, N3, p );
for ( size_t i = 0; i < N1; i++ )
{
printf( "\"%s\" \"%s\"\n", p[i][0], p[i][1] );
}
free( p );
return 0;
}
The program output is
"zero" "zero"
"zero" "one"
"one" "zero"
"one" "one"
Or you can indeed allocate an array of arrays of arrays.
For example
#include <stdio.h>
#include <stdlib.h>
#include <string.h>
void f( char ***s, size_t n1, size_t n2, size_t n3 )
{
for ( size_t i = 0; i < n1; i++ )
{
if ( i < n1 / 2 )
{
strcpy( s[i][0], "zero" );
}
else
{
strcpy( s[i][0], "one" );
}
if ( i % 2 == 0 )
{
strcpy( s[i][1], "zero" );
}
else
{
strcpy( s[i][1], "one" );
}
}
}
int main(void)
{
enum { N1 = 4, N2 = 2, N3 = 5 };
char ***p = malloc( N1 * sizeof( char ** ) );
for ( size_t i = 0; i < N1; i++ )
{
p[i] = malloc( N2 * sizeof( char * ) );
for ( size_t j = 0; j < N2; j++ )
{
p[i][j] = malloc( N3 );
}
}
f( p, N1, N2, N3 );
for ( size_t i = 0; i < N1; i++ )
{
printf( "\"%s\" \"%s\"\n", p[i][0], p[i][1] );
}
for ( size_t i = 0; i < N1; i++ )
{
for ( size_t j = 0; j < N2; j++ )
{
free( p[i][j] );
}
free( p[i] );
}
free( p );
return 0;
}
Atain the program output is
"zero" "zero"
"zero" "one"
"one" "zero"
"one" "one"
There is also a third approach where the number of pointers can be less than in the last case. All you need is to allocate a one dimensional array of pointers to first elements of two dimensional arrays.
#include <stdio.h>
#include <stdlib.h>
#include <string.h>
enum { N1 = 4, N2 = 2, N3 = 5 };
void f( char ( **s )[N3], size_t n1 )
{
for ( size_t i = 0; i < n1; i++ )
{
if ( i < n1 / 2 )
{
strcpy( s[i][0], "zero" );
}
else
{
strcpy( s[i][0], "one" );
}
if ( i % 2 == 0 )
{
strcpy( s[i][1], "zero" );
}
else
{
strcpy( s[i][1], "one" );
}
}
}
int main(void)
{
char ( **p )[N3] = malloc( N1 * sizeof( char ( * )[N3] ) );
for ( size_t i = 0; i < N1; i++ )
{
p[i] = malloc( N2 * sizeof( char[N3] ) );
}
f( p, N1 );
for ( size_t i = 0; i < N1; i++ )
{
printf( "\"%s\" \"%s\"\n", p[i][0], p[i][1] );
}
for ( size_t i = 0; i < N1; i++ )
{
free( p[i] );
}
free( p );
return 0;
}
And at last (I hope) there is a forth approach to declare at first an array of pointers to arrays.
#include <stdio.h>
#include <stdlib.h>
#include <string.h>
enum { N1 = 4, N2 = 2, N3 = 5 };
void f( char * ( *s )[N2], size_t n1, size_t n3 )
{
for ( size_t i = 0; i < n1; i++ )
{
if ( i < n1 / 2 )
{
strcpy( s[i][0], "zero" );
}
else
{
strcpy( s[i][0], "one" );
}
if ( i % 2 == 0 )
{
strcpy( s[i][1], "zero" );
}
else
{
strcpy( s[i][1], "one" );
}
}
}
int main(void)
{
char * ( *p )[N2] = malloc( N1 * sizeof( char * [N2] ) );
for ( size_t i = 0; i < N1; i++ )
{
for ( size_t j = 0; j < N2; j++ )
{
p[i][j] = malloc( N3 * sizeof( char ) );
}
}
f( p, N1, N3 );
for ( size_t i = 0; i < N1; i++ )
{
printf( "\"%s\" \"%s\"\n", p[i][0], p[i][1] );
}
for ( size_t i = 0; i < N1; i++ )
{
for ( size_t j = 0; j < N2; j++ ) free( p[i][j] );
}
free( p );
return 0;
}
If the compiler indeed supports variable length array then the first approach is the best.
Note: In the approaches sometimes some parameter as for example n2 is not used because I knwo that it is equal to 2. But in general it should be specified.

2d / multidimensional array char

Here is my code
#include <stdio.h>
#include <string.h>
#include <stdlib.h>
int main ()
{
int i,k;
char a[4][2] = { {'*','*'}, {'*','*'}, {'*','*'}, {'*','*'}};
/* output each array element's value */
for ( i = 0; i < 4; i++ ) {
for ( k = 0; k < 2; k++ ) {
printf("%c ", a[i][k] );
}
printf("\n");
}
return 0;
}
I would like to know how to replace a character from a 2d array with another character with user input? for example if the user wants to replace the asterisk at [0][0] with an F the output would look like this:
F *
* *
* *
* *
`
I would really appreciate it because I can't seem to find any example of this anywhere. Thanks
int main ()
{
int i,k,row,column;
char a[4][2] = { {'*','*'}, {'*','*'}, {'*','*'}, {'*','*'}},rc;
// before replace
printf("Before Replace :\n");
for ( i = 0; i < 4; i++ ) {
for ( k = 0; k < 2; k++ ) {
printf("%c ", a[i][k] );
}
printf("\n");
}
printf("Enter a Character you want to Replace : ");
scanf("%c",&rc);
printf("Enter row and column Index: ");
scanf("%d%d",&row,&column);
for ( i = 0; i < 4; i++ ) {
for ( k = 0; k < 2; k++ ) {
if(i==row && k==column){
a[i][k]=rc;
}
}
}
printf("\nAfter replace :\n");
for ( i = 0; i < 4; i++ ) {
for ( k = 0; k < 2; k++ ) {
printf("%c ", a[i][k] );
}
printf("\n");
}
return 0;
}

Resources