如何删除结构中的值?

How to delete a value in a struct?

我正在尝试从我的代码的结构中删除一个“用户”。

例如,这是我的结构:

struct clients {
   char name[30];
   int year;
   float amount;
};

这是我的两个输出:

Name: Victor
Birth Year: 1998
Amount: 1000.00
Name: John
Birth Year: 1996
Amount: 1500.00

我想做的是从我的结构中删除 John 和他的所有信息。

我正在尝试学习动态内存分配,所以我使用了这个命令:

clt = (struct clients*) malloc(n * sizeof(struct clients));

在我的例子中,我希望在案例 3 上编写一个命令,从结构中删除 john,但我真的不知道该怎么做,我想也许可以使用 realloc?但我什至没有接近写一些有用的东西。

到目前为止,这是我的全部代码:

#include <stdio.h>
#include <stdlib.h>
#include <string.h>

struct clients {
    char name[30];
    int year;
    float amount;
};

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 amount:");
                    scanf("%f", &(clt + i)->amount);
                }

                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("Amount: %.2f\n", (clt + i)->amount);
                        d++;
                    }
                }

                if (d == 0)
                    printf("This name doesn't exist\n");
    
                break;
            case 3:
                break;
            case 4:
                break;
        }
    } while (option != 4);

    return 0;
}

您需要通过向上移动列表其余部分的内容并覆盖目标元素,从列表中的位置丢弃该元素。

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("Amount: %.2f\n", (clt+i)->amount);
        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

如果您愿意,您可以在一个 memmove 电话中完成此操作。正如@Neil 在评论中所说,memmove 可以容忍重叠的源和目标。

if ( 1 == d && i != n-1 ) // if the sentinel is set, but we're not off the end of the list yet
{
    memmove(clt+i, clt+i+1, (n-i-1) * sizeof( struct clients )); 
    break; // break for i
}

您描述的几乎是 dynamic array,例如 C++ 的 std::vector。它是静态的,但它可以是一个动态数组而无需那么多额外的工作。您可以创建一个容器,并将 n 拆分为容器的 capacitysize.

struct clients_array {
    size_t size, capacity;
    struct clients *data;
};

可以为每个列表创建一个 struct clients_array,而不是拥有多个指针。处理 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--;
}

然后一个人可以同时拥有不同的、独立的数组。如果要更新代码,说允许realloc增加对象的大小,只需要修改容器即可。