如何删除结构中的值?
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
拆分为容器的 capacity
和 size
.
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
增加对象的大小,只需要修改容器即可。
我正在尝试从我的代码的结构中删除一个“用户”。
例如,这是我的结构:
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
拆分为容器的 capacity
和 size
.
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
增加对象的大小,只需要修改容器即可。