所以...过去有人告诉我我的问题不好...我相信主要是因为我没有足够好地隔离出有问题的代码。在这篇文章中,我会尽我所能提出一个尖锐、简洁、切题的问题。我当然愿意接受有关如何更好地提出我的问题的建议。 谢谢。
我正在用 C 语言开发一个小项目,该项目将用作我已经开发了一段时间的大型错误程序的原型(prototype)。我试图先在一个较小的程序中计算出细节。我有两个结构:
struct list
{
char ownerName[20];
int ownerAge;
char sex;
}owner;
和
struct list2
{
char petName[20];
char owner[20];
char animal[4];
char breed[50];
char color[20];
}pets;
该程序应该从用户输入中获取 ownerName,并将其与 pets 结构中的“.owner”进行比较。然后应该将 ownerName 和 petName 元素复制到一个数组中,并且主人和他/她的宠物的名字将被打印在一个列表中。虽然我知道我不需要所有者结构来完成此操作,但我正在使用它来为我正在编写的其他程序建模。
我在用
if (strcmp(pets[i].owner, name) == 0)
比较结构元素,似乎把这部分放下了。
变量 j 计算满足此条件的记录数,变量 l = j + 1。我使用以下方式调用数组:
char *petsList[l];
数组的大小由 l (j + 1) 决定,因为我需要 j 个元素用于 petNames + 1 个元素用于所有者名称。
我还通过以下方式创建了一个指向 petsList 数组的指针:
char *(*ptr)[l] = &petsList
所有者名称通过以下命令添加到数组中:
(*ptr)[0] = (char *)malloc(sizeof(name));
strcpy ( (*ptr)[0], name);
使用 for 循环将 petNames 添加到数组 petsList 中。我已经初始化 i = 1 以防止 petsList[0] 被覆盖,并尝试通过以下循环将 petNames 写入数组:
i = 1;
for (k=0; k < PETS; k++)
{
if (strcmp(pets[k].owner, name) == 0)
{
(*ptr)[i] = (char *)malloc(sizeof(pets[k].petName));
if (!*(ptr)[i])
{
puts("\nMemory Allocation Error");
exit (1);
}
strcpy( (*ptr)[i], pets[k].petName);
i++;
}
}
假设对于给定的名称输入,我得到了三只匹配的宠物。循环前两次迭代很好,但是在循环的第三次迭代中,出现内存分配错误。这始终发生在循环的最后一次迭代中。例如,如果我有 2 只宠物与 ownerName 相关联,则该列表将在第一次迭代中正常运行,但在第二次迭代中失败;如果我有 4 只宠物与 ownerName 相关联,循环将在前 3 次运行良好,但在第四次失败,因此看起来循环的最后一次迭代始终失败。我曾多次尝试更改代码,但现在对如何推进该程序感到茫然。任何帮助是极大的赞赏。
谢谢。
最佳答案
不要转换 malloc 返回值。
因为我无法真正用一个最小的例子来检查。
char *(*ptr)[l] = &petsList
为什么要做这么复杂的结构?我什至不确定它应该完成什么。你想让第一个索引和下一个索引中的所有宠物都包含主人吗?这可以通过 petslist
最后你真正需要什么样的结构?
是不是像:
数组:
0 = owner
1 = pet 1
2 = pet 2
或者类似的东西
0,0 = owner 1,0 = owner 2 etc.
0,1 = pet 1 1,1 = pet 3
0,2 = pet 2 1,2 = pet 4
好的,这是您想要执行的工作示例。您可以轻松地扩展它来进行第二次数据排列。如果您有任何问题,请随时提问
#include <stdio.h>
#include <stdlib.h>
#include <string.h>
#define PETAMOUNT 40
struct list2
{
char petName[20];
char owner[20];
char animal[4];
char breed[50];
char color[20];
};
int main() {
struct list2 *pets; // list of all pets
char name[128]; // contain name of the owner, get from stdin
unsigned int i; // i and j are both counter variable
unsigned int j;
fgets(name, 128, stdin); // get string from stdin
name[strlen(name) - 1] = '\0'; // remove newline
pets = malloc(PETAMOUNT * sizeof(struct list2)); // allocate memory for the list of all pets
if (pets == NULL) {
printf("malloc err\n");
exit(1);
}
for (i = 0; i < PETAMOUNT; i++) { // initialize some pets and some owners
strcpy(pets[i].petName, "petname ");
strcpy(pets[i].owner, "owner ");
pets[i].petName[7] = i + '0'; // there are PETAMOUNT of petnames. petname0, petname1 etc
pets[i].owner[5] = (i / 4) + '0'; // there are PETAMOUNT / 4 owners. owner0 has petname0 to petname3, owner1 has petname4 to 7 etc
}
char ***petslist; // a list of list of strings or 3d char array
petslist = malloc(sizeof(char **)); // allocate pointer to contain a double array
petslist[0] = malloc(sizeof(char *)); // allocate a pointer to contain the name of the owner
if (petslist[0] == NULL) {
printf("malloc err\n");
exit(1);
}
petslist[0][0] = malloc(strlen(name) + 1); // allocate memory to contain the owner
if (petslist[0][0] == NULL) {
printf("malloc err\n");
exit(1);
}
strcpy(petslist[0][0], name); // copy owner into the first index
for (i = 0, j = 1; i < PETAMOUNT; i++) { // go through all pets
if (strcmp(pets[i].owner, name) == 0) { // if the owner of the current pet is the same as the inputted owner
petslist[0] = realloc(petslist[0], (j + 1) * sizeof(char *)); // allocate pointer for the next pet
petslist[0][j] = malloc(strlen(pets[i].petName) + 1); // allocate memory to contain the chars of the pet
if (petslist[0][j] == NULL) {
printf("malloc err\n");
exit(1);
}
strcpy(petslist[0][j], pets[i].petName); // copy the petname into the array
j++;
}
}
puts("petslist:"); // print it all out
for (i = 0; i < j; i++) {
printf("|%s|\n", petslist[0][i]);
}
exit(0);
}
目前我总是写到 [0][0] 但如果你重新分配你可以在那之后腾出空间
关于c - 最后一次循环迭代的内存分配失败,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/27045764/