my first question here was quite messy, so I really hope this one is better..
What I am trying to do is to delete a "user" from the struct on my code.
For example, this is the struct I have:
struct clients{
char name[30];
int year;
float ammount;
};
And this is the two outputs I have:
Name: Victor Birth Year: 1998 Ammount: 1000.00
Name: John Birth Year: 1996 Ammount: 1500.00
What I want to do is to delete John and all his information from my struct.
I am trying to learn dynamic memmory allocation, so I used this command:
clt = (struct clients*) malloc(n * sizeof(struct clients));
In my case I wish to write a command on case 3 that delete john from the struct, but I really can't figure out how to do that, I guess maybe using realloc? But I didn't even get close to write something it would work.
Here is my entire code so far:
#include <stdio.h>
#include <stdlib.h>
#include <string.h>
struct clients{
char name[30];
int year;
float ammount;
};
int main(){
struct clients *clt;
int option, n, d=0;
char name[30];
printf("Welcome, Choose an option to begin:");
do
{
printf("\n1 - Create a new list;\n");
printf("2 - Find a person in the list;\n");
printf("3 - Delete a person from the list.\n");
printf("4 - End the program.\n");
scanf("%d", &option);
switch (option)
{
case 1:
printf("\nType how many clients you want to register:");
scanf("%d", &n);
// allocating memory for n numbers of struct person
clt = (struct clients*) malloc(n * sizeof(struct clients));
for (int i=0; i < n; i )
{
printf("Type the name and the birth year:");
// To access members of 1st struct person,
scanf("%s %d", (clt i)->name, &(clt i)->year);
printf("\nType the ammount:");
scanf("%f", &(clt i)->ammount);
}
break;
case 2:
printf("Type the name you want to find:");
scanf("%s", name);
for(int i = 0; i < n; i ){
if (strcmp(&clt[i].name, name)==0)
{
printf("\nThats the name:");
printf("\nName: %s\n", (clt i)->name);
printf("Birth Year: %d\n", (clt i)->year);
printf("Ammount: %.2f\n", (clt i)->ammount);
d ;
}
}
if(d == 0)
printf("This name doesn't exist\n");
break;
case 3:
break;
case 4:
break;
}
} while (option != 4);
return 0;
}
CodePudding user response:
You need to discard the element from its location in the list by moving the contents in the remainder of the list up , and overwriting the target element.
for(int i = 0; i < n; i ) {
if (strcmp(&clt[i].name, name)==0)
{
printf("\nThats the name:");
printf("\nName: %s\n", (clt i)->name);
printf("Birth Year: %d\n", (clt i)->year);
printf("Ammount: %.2f\n", (clt i)->ammount);
d ; // This seems to be your sentinel value?
}
if ( 1 == d && i 1 != n ) // if the sentinel is set, but we're not off the end of the list yet
{
memcpy(clt i, clt i 1, sizeof( struct clients ));
}
}
n--; // reduce the list length
You could do this in one memcpy
call if you prefer.
if ( 1 == d && i != n-1 ) // if the sentinel is set, but we're not off the end of the list yet
{
memcpy(clt i, clt i 1, (n-i-1) * sizeof( struct clients ));
break; // break for i
}
CodePudding user response:
You are describing almost a dynamic array such as C 's std::vector
. It is static, but it could be a dynamic array without that much extra work. You could create a container, and split n
into the container's capacity
and size
.
struct clients_array {
size_t size, capacity;
struct clients *data;
};
Instead of having multiple pointers, one could create a struct clients_array
for each list. Sample code to deal with the struct clients_array
.
#include <inttypes.h>
#include <assert.h>
#include <errno.h>
/** `a` constructor with `n` spots. Returns true or false depending on whether
it could be constructed. */
static int clients_array_reserve(struct clients_array *const a,
const size_t n) {
assert(a && n);
if(n > SIZE_MAX / sizeof *a->data) return errno = ERANGE, 0;
if(!(a->data = malloc(sizeof *a->data * n))) return 0;
a->capacity = n;
a->size = 0;
return 1;
}
/** `a` destructor; call this when `a` has been successfully constructed. */
static void clients_array_(struct clients_array *const a)
{ if(a) { free(a->data); a->data = 0; a->capacity = a->size = 0; } }
/** Extract a new uninitialized entry out of constructed `a`. Returns null if
there is no more space. */
static struct clients *clients_array_new(struct clients_array *const a) {
assert(a);
return a->capacity > a->size ? a->data a->size : 0;
}
/** Remove index `rm` from `a`. */
static void clients_array_delete(struct clients_array *const a,
const size_t rm) {
assert(a && rm < a->size);
memmove(a->data rm, a->data rm 1,
sizeof *a->data * (a->size - rm - 1));
a->size--;
}
Then one can have different, independent arrays at once. If you want to update the code, say to allow realloc
to increase the size of the object, you only need to modify the container.