C语言 将 malloc 与 c 中的结构一起使用
声明:本页面是StackOverFlow热门问题的中英对照翻译,遵循CC BY-SA 4.0协议,如果您需要使用它,必须同样遵循CC BY-SA许可,注明原文地址和作者信息,同时你必须将它归于原作者(不是我):StackOverFlow
原文地址: http://stackoverflow.com/questions/13312996/
Warning: these are provided under cc-by-sa 4.0 license. You are free to use/share it, But you must attribute it to the original authors (not me):
StackOverFlow
Using malloc with structures in c
提问by Jcmoney1010
So I'm trying add malloc to a phonebook application that I created, but since I'm kind of new to C I'm not sure if what I'm doing is correct. I've run into a small problem, but I've read through the beginner book that I have, and it doesn't go though as much detail as I would like, I can't tell by searching Google if I'm just completely wrong in how I set up the malloc or if there is something else I missed.
所以我正在尝试将 malloc 添加到我创建的电话簿应用程序中,但由于我对 C 有点陌生,我不确定我所做的是否正确。我遇到了一个小问题,但我已经通读了我拥有的初学者书籍,但它并没有像我想要的那样详细,如果我只是,我无法通过搜索谷歌来判断我设置 malloc 的方式完全错误,或者我错过了其他东西。
Basically what I've got are 4 arrays in my structure, First_Name, Last_name,home,cell. Each one of these have 2 functions, a function that gets the info from the user and a function that prints and adds the user info to the phonebook. What I've got right now is a small snipit of the original code that only adds the first name to the phonebook(so it's not the entire code) and in each function that gets the user input, I want to add the malloc function. Right now I've only got the first name and the first malloc set up, but the issue I have is that when I go to check the phonebook to see if the name was entered successfully, the program quits. If I take out the malloc, it works successfully.
基本上我的结构中有 4 个数组,First_Name, Last_name, home, cell。每一个都有 2 个函数,一个是从用户那里获取信息的函数,一个是打印用户信息并将其添加到电话簿的函数。我现在得到的是原始代码的一小段代码,它只将名字添加到电话簿中(所以它不是整个代码),并且在获取用户输入的每个函数中,我想添加 malloc 函数。现在我只设置了名字和第一个 malloc,但我遇到的问题是,当我去检查电话簿以查看名称是否输入成功时,程序退出。如果我取出 malloc,它会成功运行。
#include <stdio.h>
#include <string.h>
#include <stdlib.h>
#include <conio.h>
#define BUFFER 50
//Structure for contacts
typedef struct friends_contact {
char *First_Name;
char *Last_Name;
char *home;
char *cell;
} fr;
void menu(fr * friends, int *counter, int user_entry, int i);
void setFirst(fr *, int *, int i);
char getFirst(fr *, int i);
void add_contact(fr * friends, int *counter, int i);
void print_contact(fr * friends, int *counter, int i);
int main()
{
int user_entry = 0;
fr *friends;
int counter = 0;
int i = 0;
menu(friends, &counter, user_entry, i);
getch();
return 0;
}
//Menu function
void menu(fr * friends, int *counter, int user_entry, int i)
{
do {
int result;
printf("\nPhone Book Application\n");
printf
("1) Add friend\n2) Delete friend\n3) Show a friend\n4)Showphonebook\n5)Exit\n");
scanf("%d", &user_entry);
if (user_entry == 1) {
add_contact(friends, counter, i);
}
if (user_entry == 2) {
}
if (user_entry == 3) {
}
if (user_entry == 4) {
print_contact(friends, counter, i);
}
} while (user_entry != 5);
}
void setFirst(fr * friends, int *counter, int i)
{
// THE MALLOC FUNCTION!
friends = (fr *) malloc(BUFFER * sizeof(fr));
printf("Enter a first name \n");
scanf("%s", friends[*counter].First_Name);
if (friends != NULL) {
free(friends);
}
}
char getFirst(fr * friends, int pos)
{
printf("%s ", friends[pos].First_Name);
return *friends[pos].First_Name;
}
void add_contact(fr * friends, int *counter, int i)
{
setFirst(friends, counter, i);
(*counter)++;
}
void print_contact(fr * friends, int *counter, int i)
{
for (i = 0; i < *counter; i++)
if (strlen(friends[i].First_Name)) {
getFirst(friends, i);
}
}
Looking to give a big green check mark to whoever can help me out here.
希望给可以在这里帮助我的人打上一个大的绿色复选标记。
回答by
You need to allocate memory both for the record as a whole and separately for each field. For example:
您需要为整个记录分配内存,也需要为每个字段分别分配内存。例如:
void string_realloc_and_copy (char **dest, const char *src)
{
size_t len = strlen (src);
*dest = realloc (*dest, len + 1);
memcpy (*dest, src, len + 1);
}
typedef struct
{
char *name;
char *title;
} record;
record * record_new ()
{
record *r = malloc (sizeof (record));
r->name = NULL;
r->title = NULL;
return r;
}
void record_free (record *r)
{
free (r->name);
free (r->title);
free (r);
}
void record_set_name (record *r, const char *name)
{
string_realloc_and_copy (&r->name, name);
}
void record_set_title (record *r, const char *title)
{
string_realloc_and_copy (&r->title, title);
}
Now to create a record and fill it with values read from the user:
现在创建一个记录并用从用户读取的值填充它:
record *r;
char buffer[100 + 1];
r = record_new ();
printf("Enter a first name \n");
if (scanf ("%100s", buffer) == 1) {
record_set_name (r, buffer);
}
...
回答by Mike
Got some problems here:
这里有一些问题:
void setFirst(fr*friends, int* counter, int i) {
// THE MALLOC FUNCTION!
friends=(fr*) malloc(BUFFER*sizeof(fr)); <-- This is not doing what you're thinking
sizeof(fr)is going to be the size required for 4 pointers to character. For example if you're on a 32-bit x86 platform it takes 4 bytes for a pointer to a char, thus:
sizeof(fr)将是 4 个指向字符的指针所需的大小。例如,如果您在 32 位 x86 平台上,则指向 a 的指针需要 4 个字节char,因此:
sizeof(fr) == 4 x 4 == 16 bytes
So now you're malloc'ing 16*BUFFER or 16x50 = 800 bytes. This allows you to have an array of 50 'fr' structures.
所以现在您正在分配 16*BUFFER 或 16x50 = 800 字节。这允许您拥有 50 个 'fr' 结构的数组。
fr * friend
|
+--------> FirstName*
| LastName*
| home*
| cell*
+----> FirstName*
| LastName*
| home*
| cell*
...
So you've got the memory for 50 structures, but the contents of those structures still don't have memory. You need to assign memory to each member of the structure (and don't forget to free all those as well), or you could make them static members with arrays instead of pointers.
所以你有 50 个结构的内存,但这些结构的内容仍然没有内存。您需要为结构的每个成员分配内存(并且不要忘记释放所有成员),或者您可以使用数组而不是指针使它们成为静态成员。
Second problem:
第二个问题:
if(friends != NULL) <-- if malloc was successful
{
free(friends); <-- release the memory
You just lost all your friends. :)
You do need to free the memory but at the end of the program or at the end of where you're using it. If you assign and then free right away, then the memory is gone and you can't access it anymore.
你刚刚失去了所有的朋友。:)
您确实需要释放内存,但是在程序结束时或在使用它的地方结束时。如果您立即分配然后释放,那么内存就消失了,您无法再访问它。
回答by jpm
There are several more things to consider here, but for a start consider the following.
这里还有几件事需要考虑,但首先请考虑以下内容。
In setFirst, you're freeing your friendsbuffer, in essence saying "I don't need this anymore." When you do this, that memory just goes away. If you're going to dynamically allocate structures for the caller, you either have to provide a separate deallocation function, or let your user know it's their responsibility to clean up that structure.
在setFirst,你是free荷兰国际集团的friends缓冲区,从本质上说:“我不需要这个了。” 当你这样做时,那个记忆就会消失。如果您要为调用者动态分配结构,您要么必须提供单独的释放函数,要么让您的用户知道清理该结构是他们的责任。
Also, you're only ever changing the local copy of the friends pointer. If you want to point the caller's pointer to a new buffer, you need to change the argument type to fr**.
此外,您只会更改朋友指针的本地副本。如果要将调用者的指针指向新缓冲区,则需要将参数类型更改为fr**。
回答by William Morris
Your structure contains just pointers, not allocated memory. You would be better defining it to hold arrays into which you write names etc:
您的结构仅包含指针,而不包含分配的内存。您最好将其定义为保存您写入名称等的数组:
typedef struct friends_contact{
char First_Name[20];
char Last_Name[20];
char home[20];
char cell[20];
} fr;
Here I have made each field 20 characters long, but you can change that to suit.
在这里,我将每个字段设置为 20 个字符长,但您可以更改它以适应。
Edit: yes of course you can use dynamic memory, but is it worth the bother? The advantage of dynamic strings is that they can be exactly the right size; you might save a few bytes and you guarantee being able to fit the names into the fields. But are there many names longer than 20 chars and would it matter to have to abbreviate a few? With malloc, there is a lot of fiddly allocation (each of which can fail) and freeing too, of course.
编辑:是的,您当然可以使用动态内存,但值得麻烦吗?动态字符串的优点是它们的大小可以完全正确;您可能会节省一些字节,并保证能够将名称放入字段中。但是是否有许多名称超过 20 个字符,是否需要缩写一些?使用 malloc,当然有很多繁琐的分配(每个都可能失败)和释放。
As a compromise one might make the phone numbers fixed size (they don't change) and the names dynamic; then allocate the names using strdup(which can also fail).
作为一种妥协,可以使电话号码固定大小(它们不会改变)和名称动态;然后使用strdup(也可能失败)分配名称。
typedef struct friends_contact{
char *First_Name;
char *Last_Name;
char home[12];
char cell[12];
} fr;

